cli-jaw 2.17.72 → 2.17.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/src/agent/aside-catalog.js +339 -0
- package/dist/src/agent/aside-catalog.js.map +1 -0
- package/dist/src/agent/aside-cli.js +208 -0
- package/dist/src/agent/aside-cli.js.map +1 -0
- package/dist/src/agent/aside-replay.js +120 -0
- package/dist/src/agent/aside-replay.js.map +1 -0
- package/dist/src/agent/aside-runtime.js +175 -0
- package/dist/src/agent/aside-runtime.js.map +1 -0
- package/dist/src/agent/lifecycle-handler.js +26 -18
- package/dist/src/agent/lifecycle-handler.js.map +1 -1
- package/dist/src/agent/memory-flush-controller.js +3 -0
- package/dist/src/agent/memory-flush-controller.js.map +1 -1
- package/dist/src/agent/prompt-context.js +2 -2
- package/dist/src/agent/prompt-context.js.map +1 -1
- package/dist/src/agent/session-persistence.js +2 -0
- package/dist/src/agent/session-persistence.js.map +1 -1
- package/dist/src/agent/spawn/backend-aside.js +314 -0
- package/dist/src/agent/spawn/backend-aside.js.map +1 -0
- package/dist/src/agent/spawn/resume.js +3 -0
- package/dist/src/agent/spawn/resume.js.map +1 -1
- package/dist/src/agent/spawn-env.js +5 -0
- package/dist/src/agent/spawn-env.js.map +1 -1
- package/dist/src/agent/spawn.js +60 -6
- package/dist/src/agent/spawn.js.map +1 -1
- package/dist/src/cli/cli-status-worker.js +2 -1
- package/dist/src/cli/cli-status-worker.js.map +1 -1
- package/dist/src/cli/employee-handler.js +2 -0
- package/dist/src/cli/employee-handler.js.map +1 -1
- package/dist/src/cli/handlers-completions.js +20 -8
- package/dist/src/cli/handlers-completions.js.map +1 -1
- package/dist/src/cli/handlers-runtime.js +2 -0
- package/dist/src/cli/handlers-runtime.js.map +1 -1
- package/dist/src/cli/readiness.js +7 -3
- package/dist/src/cli/readiness.js.map +1 -1
- package/dist/src/cli/registry-live.js +47 -0
- package/dist/src/cli/registry-live.js.map +1 -1
- package/dist/src/cli/registry.js +5 -0
- package/dist/src/cli/registry.js.map +1 -1
- package/dist/src/core/config.js +10 -3
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/employees.js +5 -3
- package/dist/src/core/employees.js.map +1 -1
- package/dist/src/core/settings-merge.js +35 -0
- package/dist/src/core/settings-merge.js.map +1 -1
- package/dist/src/core/settings-watch.js +10 -1
- package/dist/src/core/settings-watch.js.map +1 -1
- package/dist/src/orchestrator/gateway.js +2 -0
- package/dist/src/orchestrator/gateway.js.map +1 -1
- package/dist/src/routes/employees.js +8 -0
- package/dist/src/routes/employees.js.map +1 -1
- package/dist/src/routes/jaw-memory.js +4 -0
- package/dist/src/routes/jaw-memory.js.map +1 -1
- package/dist/src/routes/orchestrate.js +22 -3
- package/dist/src/routes/orchestrate.js.map +1 -1
- package/dist/src/routes/settings.js +23 -0
- package/dist/src/routes/settings.js.map +1 -1
- package/dist/src/shared/aside-contract.js +2 -0
- package/dist/src/shared/aside-contract.js.map +1 -0
- package/dist/src/types/cli-engine.js +1 -0
- package/dist/src/types/cli-engine.js.map +1 -1
- package/package.json +1 -1
- package/public/dist/.vite/manifest.json +186 -175
- package/public/dist/assets/{Activity-DPLlOJ46.js → Activity-DsBgOkCP.js} +1 -1
- package/public/dist/assets/{AdvancedExport-BgOgGvc5.js → AdvancedExport-COGQ7vbK.js} +1 -1
- package/public/dist/assets/Agent-6qGQN7lY.js +1 -0
- package/public/dist/assets/AsideSelectionFields-DvU5xWAP.js +1 -0
- package/public/dist/assets/{Browser-m6VynQXV.js → Browser-r09vOsR1.js} +1 -1
- package/public/dist/assets/ChannelEnablementControl-ooOkdd-Q.js +85 -0
- package/public/dist/assets/{ChannelSetupEntry-DHLoZEzJ.js → ChannelSetupEntry-B0b4TdhH.js} +1 -1
- package/public/dist/assets/{ChannelsDiscord-B-G8vsYy.js → ChannelsDiscord-9EMLt5b3.js} +1 -1
- package/public/dist/assets/{ChannelsSlack-oPuh922z.js → ChannelsSlack-B8ETzWFt.js} +1 -1
- package/public/dist/assets/{ChannelsTelegram-PmTv43KQ.js → ChannelsTelegram-CflLUsQw.js} +1 -1
- package/public/dist/assets/{DashboardMeta-BqEiJrvr.js → DashboardMeta-wjEuh9-E.js} +1 -1
- package/public/dist/assets/{Developer-CbySB7_Z.js → Developer-B3cDkldo.js} +1 -1
- package/public/dist/assets/{Display-DU4_76cS.js → Display-BXQxpv6-.js} +1 -1
- package/public/dist/assets/{Display-C0Zdamcb.js → Display-Cl4DD334.js} +1 -1
- package/public/dist/assets/{Embedding-CCFMOB_2.js → Embedding-D-T92-En.js} +1 -1
- package/public/dist/assets/{Employees-BanvF58d.js → Employees-Cf4IeF0N.js} +1 -1
- package/public/dist/assets/{Heartbeat-uyi_MpUd.js → Heartbeat-Bj8V_bUM.js} +1 -1
- package/public/dist/assets/{Mcp-rjPoL_Zo.js → Mcp-jAcut_fw.js} +1 -1
- package/public/dist/assets/Memory-BOXkBFKg.js +1 -0
- package/public/dist/assets/ModelProvider-DIDQ37z-.js +1 -0
- package/public/dist/assets/{Network-CuqFrOvR.js → Network-I5eOe2hf.js} +1 -1
- package/public/dist/assets/{Permissions-BltXiZnz.js → Permissions-B7PthH01.js} +1 -1
- package/public/dist/assets/{Permissions-DcCbFMIq.js → Permissions-BCYUfJg1.js} +1 -1
- package/public/dist/assets/Profile-CYPMVhQM.js +1 -0
- package/public/dist/assets/{Prompts-C9vY8ivQ.js → Prompts-BRAgZLNQ.js} +1 -1
- package/public/dist/assets/{SpeechKeys-BJ8V7U5E.js → SpeechKeys-UlXNSFoe.js} +1 -1
- package/public/dist/assets/{TelegramHub-DtyjLGFR.js → TelegramHub-BhUFhIcv.js} +1 -1
- package/public/dist/assets/agent-meta-v4jNRAbX.js +1 -0
- package/public/dist/assets/app-SVIyP1TT.js +59 -0
- package/public/dist/assets/bgtask-badge-HIrvpcr_.js +1 -0
- package/public/dist/assets/{bgtask-badge-oPvZyylH.js → bgtask-badge-tYRnplEV.js} +1 -1
- package/public/dist/assets/constants-_iw-lnKY.js +1 -0
- package/public/dist/assets/{employees-BchFBkDz.js → employees-DNTPcxtZ.js} +2 -2
- package/public/dist/assets/{error-normalize-clOi-AAA.js → error-normalize-jnjrKZDu.js} +1 -1
- package/public/dist/assets/{iframe-renderer-CcGzEi0v.js → iframe-renderer--lHbKTDh.js} +2 -2
- package/public/dist/assets/iframe-renderer-DigNC5FU.js +1 -0
- package/public/dist/assets/{manager-nquYZ7_x.js → manager-qGH-xUZ7.js} +1 -1
- package/public/dist/assets/{memory-DTpD4see.js → memory-BAdRkBdk.js} +1 -1
- package/public/dist/assets/memory-DA8x5314.js +1 -0
- package/public/dist/assets/message-history-CGOgZH4l.js +1 -0
- package/public/dist/assets/{message-history-DSvflaZ9.js → message-history-PAYeKmia.js} +1 -1
- package/public/dist/assets/page-shell-Cz2ylri8.js +1 -0
- package/public/dist/assets/{render-D8dVQ_bm.js → render-F6xF6w6c.js} +1 -1
- package/public/dist/assets/settings-DMbNzuTm.js +1 -0
- package/public/dist/assets/{settings-DMiQe469.js → settings-DZ2-ca8T.js} +1 -1
- package/public/dist/assets/{settings-Bp0sgQ2a.js → settings-W0WFhBf2.js} +1 -1
- package/public/dist/assets/settings-core-2vZXNf6n.js +2 -0
- package/public/dist/assets/settings-core-BofMyzL9.js +1 -0
- package/public/dist/assets/{settings-embedding-BRW0WZvh.js → settings-embedding-Bjwpe8xu.js} +2 -2
- package/public/dist/assets/{shared-D1begqvi.js → shared-CftvKNY9.js} +1 -1
- package/public/dist/assets/{sidebar-CrpBbYFg.js → sidebar-Clkqd78q.js} +3 -3
- package/public/dist/assets/{skills-Bx8U-gJa.js → skills-0aA-RuN9.js} +1 -1
- package/public/dist/assets/skills-SqmQXndw.js +1 -0
- package/public/dist/assets/{slash-commands-DkrGUOnC.js → slash-commands-4zHHXEeU.js} +1 -1
- package/public/dist/assets/slash-commands-D5LqONzL.js +1 -0
- package/public/dist/assets/{trace-drawer-Dbe5pTbf.js → trace-drawer-B4O0Tl1M.js} +1 -1
- package/public/dist/assets/{ui-rnVAM91F.js → ui-CVtGpivr.js} +1 -1
- package/public/dist/assets/ui-_cqgseFX.js +1 -0
- package/public/dist/index.html +1 -1
- package/public/dist/manager/index.html +1 -1
- package/public/dist/settings/index.html +1 -1
- package/public/js/constants.ts +5 -0
- package/public/js/features/employees.ts +3 -3
- package/public/js/features/heartbeat.ts +14 -1
- package/public/js/features/settings-core.ts +39 -13
- package/public/js/features/settings-types.ts +1 -1
- package/public/locales/en.json +2 -0
- package/public/locales/ja.json +2 -0
- package/public/locales/ko.json +2 -0
- package/public/locales/zh.json +2 -0
- package/public/manager/src/settings/SettingsShell.tsx +1 -1
- package/public/manager/src/settings/pages/Agent.tsx +137 -52
- package/public/manager/src/settings/pages/Heartbeat.tsx +6 -0
- package/public/manager/src/settings/pages/Memory.tsx +8 -6
- package/public/manager/src/settings/pages/ModelProvider.tsx +31 -6
- package/public/manager/src/settings/pages/Profile.tsx +2 -2
- package/public/manager/src/settings/pages/components/AsideSelectionFields.tsx +33 -0
- package/public/manager/src/settings/pages/components/AvatarCard.tsx +22 -34
- package/public/manager/src/settings/pages/components/PerCliRow.tsx +29 -1
- package/public/manager/src/settings/pages/components/agent/FlushAgentSection.tsx +7 -6
- package/public/manager/src/settings/pages/components/agent/RuntimeEmployeeRow.tsx +4 -4
- package/public/manager/src/settings/pages/components/agent/RuntimeHeader.tsx +5 -0
- package/public/manager/src/settings/pages/components/agent/agent-meta.ts +7 -0
- package/public/manager/src/settings/pages/components/agent/runtime-employees-helpers.ts +3 -2
- package/public/manager/src/settings/pages/components/aside-models.ts +104 -0
- package/public/manager/src/settings/settings-client.ts +3 -1
- package/public/manager/src/settings/types.ts +1 -0
- package/public/dist/assets/Agent-O_U8ny90.js +0 -1
- package/public/dist/assets/ChannelEnablementControl-BSuKQhTW.js +0 -85
- package/public/dist/assets/Memory-C9I33pIi.js +0 -1
- package/public/dist/assets/ModelProvider-fiUktMaO.js +0 -1
- package/public/dist/assets/Profile-DUL7-RE_.js +0 -1
- package/public/dist/assets/agent-meta-94LMwZZK.js +0 -1
- package/public/dist/assets/app-Iu76iEiU.js +0 -59
- package/public/dist/assets/bgtask-badge-DHo2mkMI.js +0 -1
- package/public/dist/assets/constants-DmZ9Rjym.js +0 -1
- package/public/dist/assets/iframe-renderer-DSLsfZq8.js +0 -1
- package/public/dist/assets/memory-BgUF3M9l.js +0 -1
- package/public/dist/assets/message-history-DkB768L3.js +0 -1
- package/public/dist/assets/page-shell-DfinU3mb.js +0 -1
- package/public/dist/assets/settings-DxjoyiIM.js +0 -1
- package/public/dist/assets/settings-core-CXWmPKUE.js +0 -1
- package/public/dist/assets/settings-core-D4zGy72z.js +0 -2
- package/public/dist/assets/skills-BY-hQnqM.js +0 -1
- package/public/dist/assets/slash-commands-C53T9J3g.js +0 -1
- package/public/dist/assets/ui-C0o427q6.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{d as r,l as i}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{d as r,l as i}from"./page-shell-Cz2ylri8.js";import{a,r as o}from"./ChannelEnablementControl-ooOkdd-Q.js";var s=e(t(),1),c=n();function l({client:e,label:t,endpoint:n,method:a=`GET`,interpret:o,auto:l=!1}){let[f,p]=(0,s.useState)({kind:`idle`}),m=(0,s.useRef)(null),h=(0,s.useRef)(!0),g=(0,s.useCallback)(async()=>{m.current?.abort();let t=new AbortController;m.current=t,p({kind:`checking`});try{let r=a===`POST`?await e.post(n,{},{signal:t.signal}):await e.get(n,{signal:t.signal});if(!h.current||t.signal.aborted)return;p(o(r))}catch(e){if(!h.current||t.signal.aborted)return;if(e instanceof r&&e.status===404){p({kind:`unknown`,reason:`Probe endpoint not implemented on this instance.`});return}let n=e instanceof Error?e.message:String(e);p({kind:`error`,reason:n})}},[e,n,o,a]);(0,s.useEffect)(()=>(h.current=!0,l&&g(),()=>{h.current=!1,m.current?.abort()}),[l,g]);let _=f.kind===`ok`?`ok`:f.kind===`degraded`?`warn`:f.kind===`error`?`error`:`neutral`;return(0,c.jsxs)(`div`,{className:`settings-health-badge settings-card-toolbar`,role:`status`,"aria-live":`polite`,children:[(0,c.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:()=>void g(),disabled:f.kind===`checking`,children:f.kind===`checking`?`Checking…`:`Check ${t}`}),(0,c.jsx)(i,{tone:_,children:u(f)}),d(f)?(0,c.jsx)(`span`,{className:`settings-health-detail settings-field-hint`,children:d(f)}):null]})}function u(e){switch(e.kind){case`idle`:return`Not checked`;case`checking`:return`Checking`;case`ok`:return`Healthy`;case`degraded`:return`Degraded`;case`unknown`:return`Unknown`;case`error`:return`Error`}}function d(e){return e.kind===`ok`&&e.detail||e.kind===`degraded`?e.detail:e.kind===`unknown`||e.kind===`error`?e.reason:null}function f(e){if(!e||typeof e!=`object`)return{kind:`unknown`,reason:`Empty probe response.`};let t=e;if(t.ok===!0){let e=typeof t.username==`string`?t.username:void 0;return e?{kind:`ok`,detail:`@${e}`}:{kind:`ok`}}return{kind:`error`,reason:typeof t.error==`string`?t.error:`Probe failed.`}}function p(e){if(!e||typeof e!=`object`)return{kind:`unknown`,reason:`Empty health response.`};let t=e,n=t.discord&&typeof t.discord==`object`?t.discord:null;return n?n.ready===!0&&n.degraded!==!0?{kind:`ok`}:n.degraded===!0?{kind:`degraded`,detail:typeof n.degradedReason==`string`?n.degradedReason:`MESSAGE_CONTENT intent missing — slash commands only.`}:n.ready===!1?{kind:`error`,reason:typeof n.error==`string`?n.error:`Bot not connected.`}:{kind:`unknown`,reason:`Discord status indeterminate.`}:{kind:`unknown`,reason:`No discord block in /api/health.`}}function m({channel:e,client:t,dirty:n,open:r,onOpenChange:i,onSaved:l,disabled:u=!1}){let d=(0,s.useRef)(null),f=(0,s.useRef)(!1),p=`${e}.setup`,m=(0,s.useMemo)(()=>a(document.documentElement.lang),[]);(0,s.useEffect)(()=>(f.current=!0,()=>{f.current=!1,n.remove(p)}),[t,n,p]);let h=!r&&n.isDirty();return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`button`,{ref:d,type:`button`,className:`settings-action`,"data-onboard-channel":e,disabled:u||r||h,onClick:()=>{u||n.isDirty()||(n.set(p,{value:!0,original:!1,valid:!1}),i(!0))},children:m(`onboarding.open`)}),h&&(0,c.jsx)(`span`,{className:`settings-field-hint`,children:`Save or discard your changes before opening setup.`}),r&&(0,c.jsx)(o,{channel:e,client:t,t:m,initialDraft:{},returnFocus:d.current,onBeforeSave:()=>async()=>{f.current&&(await l(),f.current&&n.remove(p))},onClose:()=>{n.remove(p),i(!1)}},e)]})}export{f as i,l as n,p as r,m as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{a as r,i,l as a,n as o,r as s,s as c,t as l,u}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{a as r,i,l as a,n as o,r as s,s as c,t as l,u}from"./page-shell-Cz2ylri8.js";import{a as d,n as ee,o as te,s as ne}from"./fields-CicOWY-X.js";import{t as re}from"./path-utils-B6vBr0DD.js";import{a as ie,n as f,t as p}from"./ChannelEnablementControl-ooOkdd-Q.js";import{n as m,r as h,t as g}from"./ChannelSetupEntry-B0b4TdhH.js";var _=e(t(),1),v=n(),y=[`messaging.enabledChannels`,`messaging.homeChannel`,`discord.enabled`,`discord.token`,`discord.guildId`,`discord.channelIds`,`discord.forwardAll`,`discord.allowBots`,`discord.mentionOnly`],b=[`discord.enabled`,`discord.token`,`discord.guildId`,`discord.channelIds`];function x(e){return e?/^\d{5,32}$/.test(e.trim()):!1}function S({port:e,client:t,dirty:n,registerSave:S,manager:w}){let T=(0,_.useMemo)(()=>ie(w?.ui.locale??document.documentElement.lang),[w?.ui.locale]),{state:E,refresh:D,setData:O}=u(t,`/api/settings`),[k,A]=(0,_.useState)(!1),[j,M]=(0,_.useState)([]),[N,P]=(0,_.useState)(`telegram`),[F,I]=(0,_.useState)(!1),[L,R]=(0,_.useState)(``),[z,B]=(0,_.useState)(``),[V,H]=(0,_.useState)([]),[U,W]=(0,_.useState)(!0),[ae,G]=(0,_.useState)(!1),[oe,K]=(0,_.useState)(!1);(0,_.useEffect)(()=>{if(E.kind!==`ready`)return;let e=E.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];M(t.filter(C)),P(C(e.homeChannel)?e.homeChannel:`telegram`);let n=E.data.discord||{};I(!!n.enabled),R(``),B(n.guildId??``),H(Array.isArray(n.channelIds)?[...n.channelIds]:[]),W(n.forwardAll!==!1),G(!!n.allowBots),K(!!n.mentionOnly)},[E]),(0,_.useEffect)(()=>()=>{for(let e of y)n.remove(e)},[n]);let q=(0,_.useCallback)((e,t)=>n.set(e,t),[n]),J=(0,_.useMemo)(()=>E.kind===`ready`&&E.data.discord||{},[E]),Y=E.kind===`ready`&&Array.isArray(E.data.discordEnvironmentVariables)?E.data.discordEnvironmentVariables:[],X=Y.length>0,Z=(0,_.useRef)({environmentManaged:X,environmentVariables:Y,t:T});(0,_.useLayoutEffect)(()=>{Z.current={environmentManaged:X,environmentVariables:Y,t:T}},[X,Y,T]);let Q=(0,_.useCallback)(async()=>{if(k)throw Error(`Finish channel setup before saving settings.`);let e=n.saveBundle();if(Object.keys(e).length===0)return;let r=Z.current;if(r.environmentManaged&&b.some(t=>t in e))throw Error(r.t(`settings.discord.managedByEnvironment`,{variables:r.environmentVariables.join(`, `)}));let i=re(e),a=await t.put(`/api/settings`,i),o=a&&typeof a==`object`&&`data`in a?a.data:a;n.clear(),O(o);let s=o.messaging||{};M(Array.isArray(s.enabledChannels)?s.enabledChannels.filter(C):[]),P(C(s.homeChannel)?s.homeChannel:`telegram`);let c=o.discord||{};I(!!c.enabled),R(``),B(c.guildId??``),H(Array.isArray(c.channelIds)?[...c.channelIds]:[]),W(c.forwardAll!==!1),G(!!c.allowBots),K(!!c.mentionOnly),await D()},[t,n,D,O,k]);if((0,_.useEffect)(()=>{if(S)return S(Q),()=>S(null)},[S,Q]),E.kind===`loading`)return(0,v.jsx)(o,{});if(E.kind===`offline`)return(0,v.jsx)(s,{port:e});if(E.kind===`error`)return(0,v.jsx)(l,{message:E.message});let se=J.token?J.token.slice(-4):``,ce=J.token?`••••••••${se}`:`(empty)`,le=z&&!x(z)?`Guild ID must be a numeric snowflake.`:null,$=V.filter(e=>!x(e)),ue=$.length>0?`Snowflake IDs only — invalid: ${$.join(`, `)}`:null;return(0,v.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),Q()},children:[(0,v.jsxs)(`fieldset`,{disabled:k,className:`settings-slack-fields`,children:[(0,v.jsxs)(c,{title:`Status`,hint:`Live transport state plus a readiness probe for this channel.`,children:[(0,v.jsx)(r,{items:[{label:`Discord`,value:F?(0,v.jsx)(a,{tone:`ok`,children:`Enabled`}):(0,v.jsx)(a,{tone:`neutral`,children:`Disabled`})},...X?[{label:`Managed by`,value:Y.join(`, `),mono:!0}]:[]]}),(0,v.jsx)(f,{client:t,channel:`discord`}),(0,v.jsx)(m,{client:t,label:`Discord`,endpoint:`/api/health`,method:`GET`,interpret:h})]}),(0,v.jsxs)(c,{title:`Credentials`,hint:X?T(`settings.discord.managedByEnvironment`,{variables:Y.join(`, `)}):`Bot token, guild, and channel IDs.`,children:[(0,v.jsx)(d,{id:`dc-enabled`,label:`Discord enabled`,value:F,disabled:X,onChange:e=>{I(e),q(`discord.enabled`,{value:e,original:!!J.enabled,valid:!0})}}),(0,v.jsx)(te,{id:`dc-token`,label:`Bot token`,value:L,placeholder:ce,disabled:X,onChange:e=>{if(R(e),e.length===0){n.remove(`discord.token`);return}q(`discord.token`,{value:e,original:J.token??``,valid:!0})}}),(0,v.jsx)(ne,{id:`dc-guildId`,label:`Guild ID`,value:z,placeholder:`123456789012345678`,error:le,disabled:X,onChange:e=>{B(e);let t=e.length===0||x(e);q(`discord.guildId`,{value:e,original:J.guildId??``,valid:t})}}),(0,v.jsx)(ee,{id:`dc-channelIds`,label:`Channel IDs`,value:V,placeholder:`987654321098765432`,error:ue,disabled:X,onChange:e=>{H(e);let t=e.every(x);q(`discord.channelIds`,{value:e,original:J.channelIds??[],valid:t})}})]}),(0,v.jsxs)(c,{title:`Routing`,hint:`Choose which channels receive inbound chat and how replies are delivered. Outbound send can still work on any configured channel.`,children:[(0,v.jsx)(p,{pageChannel:`discord`,snapshot:E.kind===`ready`?E.data:{},enabledChannels:j,homeChannel:N,setEnabledChannels:M,setHomeChannel:P,dirty:n,idPrefix:`di-channel`}),(0,v.jsx)(d,{id:`dc-forwardAll`,label:`Forward all`,value:U,onChange:e=>{W(e),q(`discord.forwardAll`,{value:e,original:J.forwardAll!==!1,valid:!0})}}),(0,v.jsx)(d,{id:`dc-allowBots`,label:`Allow other bots`,value:ae,onChange:e=>{G(e),q(`discord.allowBots`,{value:e,original:!!J.allowBots,valid:!0})}}),(0,v.jsx)(d,{id:`dc-mentionOnly`,label:`Mention only`,value:oe,onChange:e=>{K(e),q(`discord.mentionOnly`,{value:e,original:!!J.mentionOnly,valid:!0})}})]})]}),(0,v.jsx)(c,{title:`Actions`,hint:`Guided setup validates credentials with the issuer before saving.`,children:(0,v.jsx)(i,{children:(0,v.jsx)(g,{channel:`discord`,client:t,dirty:n,disabled:X,open:k,onOpenChange:A,onSaved:async()=>O(await t.get(`/api/settings`))})})})]})}function C(e){return e===`telegram`||e===`discord`||e===`slack`}export{S as default,x as isValidSnowflake};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{a as r,d as i,i as a,l as o,n as s,o as c,r as l,s as u,t as ee,u as te}from"./page-shell-DfinU3mb.js";import{a as d,n as ne,o as re,s as ie}from"./fields-CicOWY-X.js";import{t as ae}from"./path-utils-B6vBr0DD.js";import{a as oe,i as se,n as ce,t as le}from"./ChannelEnablementControl-BSuKQhTW.js";function ue(e){return e.trim().length>0}function f(e){return e.trim().startsWith(`xoxb-`)}function p(e){return e.trim().startsWith(`xapp-`)}var m=e(t(),1),h=n(),g=[`slack.attachPort`,`channel`,`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`,`slack.channelIds`,`slack.forwardAll`,`slack.allowBots`,`slack.mentionOnly`,`slack.replyInThread`,`slack.ack.enabled`];function _(e){return e?/^[CGD][A-Z0-9]{6,20}$/.test(e.trim().toUpperCase()):!1}var v=[`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`,`slack.channelIds`,`slack.attachPort`],y=`slack.setup`,de=[`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`];function fe(e){return e&&typeof e==`object`&&`data`in e?e.data:e}function pe(e){if(!e||typeof e!=`object`||!e.slack)return!1;let t=e.slack;return!t?.enabled&&!t?.botToken&&!t?.appToken&&!t?.teamId&&!t?.channelIds?.length&&!t?.attachPort}function b({port:e,client:t,dirty:n,registerSave:b,manager:he}){let x=(0,m.useMemo)(()=>oe(he?.ui.locale??document.documentElement.lang),[he?.ui.locale]),[ge,_e]=(0,m.useState)(``),[S,ve]=(0,m.useState)(!1),C=(0,m.useRef)(!1),w=(0,m.useRef)(0),T=(0,m.useRef)(null),[E,D]=(0,m.useState)(!1),[O,k]=(0,m.useState)(null),[ye,A]=(0,m.useState)(0),j=(0,m.useRef)(!1),M=(0,m.useRef)(!1),N=(0,m.useRef)({}),[be,P]=(0,m.useState)(!1),[xe,F]=(0,m.useState)(!1);(0,m.useLayoutEffect)(()=>(M.current=!0,N.current={},()=>{M.current=!1,N.current={},++w.current}),[e,t]);let{state:I,refresh:L,setData:R}=te(t,`/api/settings`),[Se,z]=(0,m.useState)([]),[Ce,we]=(0,m.useState)(`telegram`),[Te,Ee]=(0,m.useState)(!1),[B,V]=(0,m.useState)(``),[H,U]=(0,m.useState)(``),[De,Oe]=(0,m.useState)(``),[ke,Ae]=(0,m.useState)([]),[je,Me]=(0,m.useState)(!0),[Ne,Pe]=(0,m.useState)(!1),[Fe,Ie]=(0,m.useState)(!0),[Le,Re]=(0,m.useState)(!0),[ze,Be]=(0,m.useState)(!1),W=(0,m.useCallback)(e=>{let t=Object.fromEntries([...n.pending].filter(([e])=>e.startsWith(`slack.`)&&e!==y).map(([e,t])=>[e,t.value])),r=ae(t).slack;e={...e,...r,ack:{...e.ack,...r?.ack}},_e(e.attachPort??``),Ee(!!e.enabled),V(String(n.pending.get(`slack.botToken`)?.value??``)),U(String(n.pending.get(`slack.appToken`)?.value??``)),Oe(e.teamId??``),Ae(Array.isArray(e.channelIds)?[...e.channelIds]:[]),Me(e.forwardAll!==!1),Pe(!!e.allowBots),Ie(e.mentionOnly!==!1),Re(e.replyInThread!==!1),Be(!!e.ack?.enabled)},[n]);(0,m.useEffect)(()=>{if(I.kind!==`ready`)return;let e=I.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];z(t.filter(me)),we(me(e.homeChannel)?e.homeChannel:`telegram`),W(I.data.slack||{})},[I,W]),(0,m.useEffect)(()=>()=>{for(let e of g)n.remove(e)},[n]);let G=(0,m.useCallback)((e,t)=>n.set(e,t),[n]),K=(0,m.useMemo)(()=>I.kind===`ready`&&I.data.slack||{},[I]),q=I.kind===`ready`&&Array.isArray(I.data.slackEnvironmentVariables)?I.data.slackEnvironmentVariables:[],J=q.length>0,Y=(0,m.useRef)({environmentManaged:J,environmentVariables:q,t:x});(0,m.useLayoutEffect)(()=>{Y.current={environmentManaged:J,environmentVariables:q,t:x}},[J,q,x]);let X=(0,m.useCallback)(async()=>{let e=Y.current;if(j.current||C.current)throw Error(e.t(`settings.slack.resetFailed`));let r=n.saveBundle();if(Object.keys(r).length===0)return;if(e.environmentManaged&&v.some(e=>e in r))throw Error(e.t(`settings.slack.resetManagedByEnvironment`,{variables:e.environmentVariables.join(`, `)}));let i=Object.fromEntries(Object.entries(r).filter(([e])=>g.includes(e)||e.startsWith(`messaging.`))),a=new Map([...n.pending].filter(([e])=>e in i)),o=N.current,s=ae(i),c=await t.put(`/api/settings`,s),l=c&&typeof c==`object`&&`data`in c?c.data:c;M.current&&o===N.current&&(Z(a),R(l),W(l.slack||{}),await L())},[t,n,L,R,W]);(0,m.useEffect)(()=>{if(b)return b(X),()=>b(null)},[b,X]);function Z(e){for(let[t,r]of e)n.pending.get(t)===r&&n.remove(t)}function Ve(){Y.current.environmentManaged||j.current||C.current||(T.current=document.activeElement instanceof HTMLElement?document.activeElement:null,++w.current,C.current=!0,n.set(y,{value:!0,original:!1,valid:!1}),ve(!0))}function He(){++w.current,C.current=!1,ve(!1),n.remove(y)}(0,m.useEffect)(()=>()=>{++w.current,C.current=!1,n.remove(y)},[n]);function Ue(){let e=w.current,r=new Map([...n.pending].filter(([e])=>de.includes(e)||e===y));return async()=>{if(!M.current||!C.current||e!==w.current)return;let n=fe(await t.get(`/api/settings`));M.current&&C.current&&e===w.current&&(Z(r),R(n),A(e=>e+1))}}async function We(){if(j.current)return;if(J){k(x(`settings.slack.resetManagedByEnvironment`,{variables:q.join(`, `)}));return}if(!B.trim()&&!H.trim()&&!K.botToken&&!K.appToken){k(x(`settings.slack.resetEmpty`));return}if(!window.confirm(x(`settings.slack.resetConfirm`)))return;let e=new Map([...n.pending].filter(([e])=>v.includes(e))),r=N.current;j.current=!0,D(!0),k(null);let a=null;try{try{await t.post(`/api/settings/slack/reset`,{})}catch(e){if(e instanceof i&&e.status===409)try{let t=JSON.parse(e.detail);t.error===`slack_connection_managed_by_environment`&&(a=Array.isArray(t.environmentVariables)?t.environmentVariables.filter(e=>typeof e==`string`):[`SLACK_*`])}catch{}}let o=fe(await t.get(`/api/settings`));if(!M.current||r!==N.current)return;let s=a??o.slackEnvironmentVariables??[];if(s.length){for(let e of v)n.remove(e);R({...o,slackEnvironmentVariables:s}),k(x(`settings.slack.resetManagedByEnvironment`,{variables:s.join(`, `)}));return}if(!pe(o)){k(x(`settings.slack.resetFailed`));return}Z(e),V(``),U(``),P(!1),F(!1),R(o)}catch{M.current&&r===N.current&&k(x(`settings.slack.resetFailed`))}finally{j.current=!1,M.current&&r===N.current&&(D(!1),A(e=>e+1))}}if(I.kind===`loading`)return(0,h.jsx)(s,{});if(I.kind===`offline`)return(0,h.jsx)(l,{port:e});if(I.kind===`error`)return(0,h.jsx)(ee,{message:I.message});let Ge=e=>e?`••••••••${e.slice(-4)}`:`(empty)`,Q=ke.filter(e=>!_(e)),Ke=Q.length>0?`Slack conversation IDs only (C…/G…/D…) — invalid: ${Q.join(`, `)}`:null,qe=be&&B.trim()&&!f(B)?x(`settings.slack.guide.botTokenError`):null,Je=xe&&H.trim()&&!p(H)?x(`settings.slack.guide.appTokenError`):null,$=!!K.enabled&&!!K.botToken&&!K.appToken,Ye=J?`Connection settings are read-only because they are managed by environment variables: ${q.join(`, `)}.`:$?`Currently OUTBOUND-ONLY: the app-level token (xapp-) is missing, so no inbound Slack events can arrive.`:`Slack needs TWO tokens: a bot token (xoxb-) for the Web API and an app-level token (xapp-) for Socket Mode.`;return(0,h.jsxs)(`form`,{className:`settings-page-form`,onBlurCapture:e=>{let t=e.target.id;t===`sl-botToken`&&P(!0),t===`sl-appToken`&&F(!0)},onSubmit:e=>{e.preventDefault(),X().catch(()=>k(x(`settings.slack.resetFailed`)))},children:[(0,h.jsxs)(`fieldset`,{disabled:E||S,className:`settings-slack-fields`,children:[(0,h.jsxs)(u,{title:`Status`,hint:`Live transport state for this channel.`,children:[(0,h.jsx)(r,{items:[{label:`Slack`,value:Te?(0,h.jsx)(o,{tone:`ok`,children:`Enabled`}):(0,h.jsx)(o,{tone:`neutral`,children:`Disabled`})},...$?[{label:`Mode`,value:(0,h.jsx)(o,{tone:`warn`,children:`Outbound only`})}]:[],...J?[{label:`Managed by`,value:q.join(`, `),mono:!0}]:[]]}),(0,h.jsx)(ce,{client:t,channel:`slack`},ye)]}),(0,h.jsxs)(u,{title:`Credentials`,hint:Ye,children:[(0,h.jsx)(d,{id:`sl-enabled`,label:`Slack enabled`,value:Te,disabled:J,onChange:e=>{Ee(e),G(`slack.enabled`,{value:e,original:!!K.enabled,valid:!0}),e&&!J&&!ue(B||K.botToken||``)&&Ve()}}),(0,h.jsx)(re,{id:`sl-botToken`,label:`Bot token`,value:B,placeholder:Ge(K.botToken),error:qe,disabled:J,onChange:e=>{if(V(e),e.trim().length===0){n.remove(`slack.botToken`);return}G(`slack.botToken`,{value:e.trim(),original:K.botToken??``,valid:f(e)})}}),(0,h.jsx)(re,{id:`sl-appToken`,label:`App-level token`,value:H,placeholder:Ge(K.appToken),error:Je,disabled:J,onChange:e=>{if(U(e),e.trim().length===0){n.remove(`slack.appToken`);return}G(`slack.appToken`,{value:e.trim(),original:K.appToken??``,valid:p(e)})}}),(0,h.jsx)(ie,{id:`sl-teamId`,label:`Team ID`,value:De,placeholder:`T01234567 (optional)`,disabled:J,onChange:e=>{Oe(e),G(`slack.teamId`,{value:e,original:K.teamId??``,valid:!0})}}),(0,h.jsx)(ne,{id:`sl-channelIds`,label:`Channel IDs`,value:ke,placeholder:`C01234567`,error:Ke,disabled:J,onChange:e=>{Ae(e),G(`slack.channelIds`,{value:e,original:K.channelIds??[],valid:e.every(_)})}}),(0,h.jsx)(ie,{id:`sl-attachPort`,label:x(`settings.slack.attachPort`),value:ge,disabled:J||E||S,onChange:e=>{_e(e),G(`slack.attachPort`,{value:e.trim(),original:K.attachPort??``,valid:!0})}})]}),(0,h.jsxs)(u,{title:`Routing`,hint:`Choose which channels receive inbound chat and how replies are delivered. Outbound send can still work on any configured channel.`,children:[(0,h.jsx)(le,{pageChannel:`slack`,snapshot:I.kind===`ready`?I.data:{},enabledChannels:Se,homeChannel:Ce,setEnabledChannels:z,setHomeChannel:we,dirty:n,idPrefix:`sl-channel`}),(0,h.jsx)(d,{id:`sl-mentionOnly`,label:`Mention only`,value:Fe,onChange:e=>{Ie(e),G(`slack.mentionOnly`,{value:e,original:K.mentionOnly!==!1,valid:!0})}}),(0,h.jsx)(d,{id:`sl-replyInThread`,label:`Reply in thread`,value:Le,onChange:e=>{Re(e),G(`slack.replyInThread`,{value:e,original:K.replyInThread!==!1,valid:!0})}}),(0,h.jsx)(d,{id:`sl-forwardAll`,label:`Forward all`,value:je,onChange:e=>{Me(e),G(`slack.forwardAll`,{value:e,original:K.forwardAll!==!1,valid:!0})}}),(0,h.jsx)(d,{id:`sl-allowBots`,label:`Allow bots`,value:Ne,onChange:e=>{Pe(e),G(`slack.allowBots`,{value:e,original:!!K.allowBots,valid:!0})}}),(0,h.jsx)(d,{id:`sl-ackEnabled`,label:`Emoji reactions (👀 → ✅)`,value:ze,onChange:e=>{Be(e),G(`slack.ack.enabled`,{value:e,original:!!K.ack?.enabled,valid:!0})}})]})]}),(0,h.jsxs)(u,{title:`Actions`,hint:`Guided setup validates credentials with the issuer before saving.`,children:[(0,h.jsxs)(a,{children:[(0,h.jsx)(`button`,{type:`button`,className:`settings-action settings-action-danger`,disabled:J||E||S,onClick:()=>void We(),children:x(`settings.slack.resetConnection`)}),(0,h.jsx)(`button`,{type:`button`,className:`settings-action`,disabled:J||E||S,"data-onboard-channel":`slack`,onClick:Ve,children:x(`onboarding.open`)})]}),O&&(0,h.jsx)(c,{tone:`error`,role:`alert`,children:O})]}),S&&(0,h.jsx)(se,{client:t,t:x,initialDraft:{botToken:B,appToken:H},returnFocus:T.current,onBeforeSave:Ue,onClose:He},e)]})}function me(e){return e===`telegram`||e===`discord`||e===`slack`}export{b as default,_ as isValidSlackConversationId};
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{a as r,d as i,i as a,l as o,n as s,o as c,r as l,s as u,t as ee,u as te}from"./page-shell-Cz2ylri8.js";import{a as d,n as ne,o as re,s as ie}from"./fields-CicOWY-X.js";import{t as ae}from"./path-utils-B6vBr0DD.js";import{a as oe,i as se,n as ce,t as le}from"./ChannelEnablementControl-ooOkdd-Q.js";function ue(e){return e.trim().length>0}function f(e){return e.trim().startsWith(`xoxb-`)}function p(e){return e.trim().startsWith(`xapp-`)}var m=e(t(),1),h=n(),g=[`slack.attachPort`,`channel`,`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`,`slack.channelIds`,`slack.forwardAll`,`slack.allowBots`,`slack.mentionOnly`,`slack.replyInThread`,`slack.ack.enabled`];function _(e){return e?/^[CGD][A-Z0-9]{6,20}$/.test(e.trim().toUpperCase()):!1}var v=[`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`,`slack.channelIds`,`slack.attachPort`],y=`slack.setup`,de=[`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`];function fe(e){return e&&typeof e==`object`&&`data`in e?e.data:e}function pe(e){if(!e||typeof e!=`object`||!e.slack)return!1;let t=e.slack;return!t?.enabled&&!t?.botToken&&!t?.appToken&&!t?.teamId&&!t?.channelIds?.length&&!t?.attachPort}function b({port:e,client:t,dirty:n,registerSave:b,manager:he}){let x=(0,m.useMemo)(()=>oe(he?.ui.locale??document.documentElement.lang),[he?.ui.locale]),[ge,_e]=(0,m.useState)(``),[S,ve]=(0,m.useState)(!1),C=(0,m.useRef)(!1),w=(0,m.useRef)(0),T=(0,m.useRef)(null),[E,D]=(0,m.useState)(!1),[O,k]=(0,m.useState)(null),[ye,A]=(0,m.useState)(0),j=(0,m.useRef)(!1),M=(0,m.useRef)(!1),N=(0,m.useRef)({}),[be,P]=(0,m.useState)(!1),[xe,F]=(0,m.useState)(!1);(0,m.useLayoutEffect)(()=>(M.current=!0,N.current={},()=>{M.current=!1,N.current={},++w.current}),[e,t]);let{state:I,refresh:L,setData:R}=te(t,`/api/settings`),[Se,z]=(0,m.useState)([]),[Ce,we]=(0,m.useState)(`telegram`),[Te,Ee]=(0,m.useState)(!1),[B,V]=(0,m.useState)(``),[H,U]=(0,m.useState)(``),[De,Oe]=(0,m.useState)(``),[ke,Ae]=(0,m.useState)([]),[je,Me]=(0,m.useState)(!0),[Ne,Pe]=(0,m.useState)(!1),[Fe,Ie]=(0,m.useState)(!0),[Le,Re]=(0,m.useState)(!0),[ze,Be]=(0,m.useState)(!1),W=(0,m.useCallback)(e=>{let t=Object.fromEntries([...n.pending].filter(([e])=>e.startsWith(`slack.`)&&e!==y).map(([e,t])=>[e,t.value])),r=ae(t).slack;e={...e,...r,ack:{...e.ack,...r?.ack}},_e(e.attachPort??``),Ee(!!e.enabled),V(String(n.pending.get(`slack.botToken`)?.value??``)),U(String(n.pending.get(`slack.appToken`)?.value??``)),Oe(e.teamId??``),Ae(Array.isArray(e.channelIds)?[...e.channelIds]:[]),Me(e.forwardAll!==!1),Pe(!!e.allowBots),Ie(e.mentionOnly!==!1),Re(e.replyInThread!==!1),Be(!!e.ack?.enabled)},[n]);(0,m.useEffect)(()=>{if(I.kind!==`ready`)return;let e=I.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];z(t.filter(me)),we(me(e.homeChannel)?e.homeChannel:`telegram`),W(I.data.slack||{})},[I,W]),(0,m.useEffect)(()=>()=>{for(let e of g)n.remove(e)},[n]);let G=(0,m.useCallback)((e,t)=>n.set(e,t),[n]),K=(0,m.useMemo)(()=>I.kind===`ready`&&I.data.slack||{},[I]),q=I.kind===`ready`&&Array.isArray(I.data.slackEnvironmentVariables)?I.data.slackEnvironmentVariables:[],J=q.length>0,Y=(0,m.useRef)({environmentManaged:J,environmentVariables:q,t:x});(0,m.useLayoutEffect)(()=>{Y.current={environmentManaged:J,environmentVariables:q,t:x}},[J,q,x]);let X=(0,m.useCallback)(async()=>{let e=Y.current;if(j.current||C.current)throw Error(e.t(`settings.slack.resetFailed`));let r=n.saveBundle();if(Object.keys(r).length===0)return;if(e.environmentManaged&&v.some(e=>e in r))throw Error(e.t(`settings.slack.resetManagedByEnvironment`,{variables:e.environmentVariables.join(`, `)}));let i=Object.fromEntries(Object.entries(r).filter(([e])=>g.includes(e)||e.startsWith(`messaging.`))),a=new Map([...n.pending].filter(([e])=>e in i)),o=N.current,s=ae(i),c=await t.put(`/api/settings`,s),l=c&&typeof c==`object`&&`data`in c?c.data:c;M.current&&o===N.current&&(Z(a),R(l),W(l.slack||{}),await L())},[t,n,L,R,W]);(0,m.useEffect)(()=>{if(b)return b(X),()=>b(null)},[b,X]);function Z(e){for(let[t,r]of e)n.pending.get(t)===r&&n.remove(t)}function Ve(){Y.current.environmentManaged||j.current||C.current||(T.current=document.activeElement instanceof HTMLElement?document.activeElement:null,++w.current,C.current=!0,n.set(y,{value:!0,original:!1,valid:!1}),ve(!0))}function He(){++w.current,C.current=!1,ve(!1),n.remove(y)}(0,m.useEffect)(()=>()=>{++w.current,C.current=!1,n.remove(y)},[n]);function Ue(){let e=w.current,r=new Map([...n.pending].filter(([e])=>de.includes(e)||e===y));return async()=>{if(!M.current||!C.current||e!==w.current)return;let n=fe(await t.get(`/api/settings`));M.current&&C.current&&e===w.current&&(Z(r),R(n),A(e=>e+1))}}async function We(){if(j.current)return;if(J){k(x(`settings.slack.resetManagedByEnvironment`,{variables:q.join(`, `)}));return}if(!B.trim()&&!H.trim()&&!K.botToken&&!K.appToken){k(x(`settings.slack.resetEmpty`));return}if(!window.confirm(x(`settings.slack.resetConfirm`)))return;let e=new Map([...n.pending].filter(([e])=>v.includes(e))),r=N.current;j.current=!0,D(!0),k(null);let a=null;try{try{await t.post(`/api/settings/slack/reset`,{})}catch(e){if(e instanceof i&&e.status===409)try{let t=JSON.parse(e.detail);t.error===`slack_connection_managed_by_environment`&&(a=Array.isArray(t.environmentVariables)?t.environmentVariables.filter(e=>typeof e==`string`):[`SLACK_*`])}catch{}}let o=fe(await t.get(`/api/settings`));if(!M.current||r!==N.current)return;let s=a??o.slackEnvironmentVariables??[];if(s.length){for(let e of v)n.remove(e);R({...o,slackEnvironmentVariables:s}),k(x(`settings.slack.resetManagedByEnvironment`,{variables:s.join(`, `)}));return}if(!pe(o)){k(x(`settings.slack.resetFailed`));return}Z(e),V(``),U(``),P(!1),F(!1),R(o)}catch{M.current&&r===N.current&&k(x(`settings.slack.resetFailed`))}finally{j.current=!1,M.current&&r===N.current&&(D(!1),A(e=>e+1))}}if(I.kind===`loading`)return(0,h.jsx)(s,{});if(I.kind===`offline`)return(0,h.jsx)(l,{port:e});if(I.kind===`error`)return(0,h.jsx)(ee,{message:I.message});let Ge=e=>e?`••••••••${e.slice(-4)}`:`(empty)`,Q=ke.filter(e=>!_(e)),Ke=Q.length>0?`Slack conversation IDs only (C…/G…/D…) — invalid: ${Q.join(`, `)}`:null,qe=be&&B.trim()&&!f(B)?x(`settings.slack.guide.botTokenError`):null,Je=xe&&H.trim()&&!p(H)?x(`settings.slack.guide.appTokenError`):null,$=!!K.enabled&&!!K.botToken&&!K.appToken,Ye=J?`Connection settings are read-only because they are managed by environment variables: ${q.join(`, `)}.`:$?`Currently OUTBOUND-ONLY: the app-level token (xapp-) is missing, so no inbound Slack events can arrive.`:`Slack needs TWO tokens: a bot token (xoxb-) for the Web API and an app-level token (xapp-) for Socket Mode.`;return(0,h.jsxs)(`form`,{className:`settings-page-form`,onBlurCapture:e=>{let t=e.target.id;t===`sl-botToken`&&P(!0),t===`sl-appToken`&&F(!0)},onSubmit:e=>{e.preventDefault(),X().catch(()=>k(x(`settings.slack.resetFailed`)))},children:[(0,h.jsxs)(`fieldset`,{disabled:E||S,className:`settings-slack-fields`,children:[(0,h.jsxs)(u,{title:`Status`,hint:`Live transport state for this channel.`,children:[(0,h.jsx)(r,{items:[{label:`Slack`,value:Te?(0,h.jsx)(o,{tone:`ok`,children:`Enabled`}):(0,h.jsx)(o,{tone:`neutral`,children:`Disabled`})},...$?[{label:`Mode`,value:(0,h.jsx)(o,{tone:`warn`,children:`Outbound only`})}]:[],...J?[{label:`Managed by`,value:q.join(`, `),mono:!0}]:[]]}),(0,h.jsx)(ce,{client:t,channel:`slack`},ye)]}),(0,h.jsxs)(u,{title:`Credentials`,hint:Ye,children:[(0,h.jsx)(d,{id:`sl-enabled`,label:`Slack enabled`,value:Te,disabled:J,onChange:e=>{Ee(e),G(`slack.enabled`,{value:e,original:!!K.enabled,valid:!0}),e&&!J&&!ue(B||K.botToken||``)&&Ve()}}),(0,h.jsx)(re,{id:`sl-botToken`,label:`Bot token`,value:B,placeholder:Ge(K.botToken),error:qe,disabled:J,onChange:e=>{if(V(e),e.trim().length===0){n.remove(`slack.botToken`);return}G(`slack.botToken`,{value:e.trim(),original:K.botToken??``,valid:f(e)})}}),(0,h.jsx)(re,{id:`sl-appToken`,label:`App-level token`,value:H,placeholder:Ge(K.appToken),error:Je,disabled:J,onChange:e=>{if(U(e),e.trim().length===0){n.remove(`slack.appToken`);return}G(`slack.appToken`,{value:e.trim(),original:K.appToken??``,valid:p(e)})}}),(0,h.jsx)(ie,{id:`sl-teamId`,label:`Team ID`,value:De,placeholder:`T01234567 (optional)`,disabled:J,onChange:e=>{Oe(e),G(`slack.teamId`,{value:e,original:K.teamId??``,valid:!0})}}),(0,h.jsx)(ne,{id:`sl-channelIds`,label:`Channel IDs`,value:ke,placeholder:`C01234567`,error:Ke,disabled:J,onChange:e=>{Ae(e),G(`slack.channelIds`,{value:e,original:K.channelIds??[],valid:e.every(_)})}}),(0,h.jsx)(ie,{id:`sl-attachPort`,label:x(`settings.slack.attachPort`),value:ge,disabled:J||E||S,onChange:e=>{_e(e),G(`slack.attachPort`,{value:e.trim(),original:K.attachPort??``,valid:!0})}})]}),(0,h.jsxs)(u,{title:`Routing`,hint:`Choose which channels receive inbound chat and how replies are delivered. Outbound send can still work on any configured channel.`,children:[(0,h.jsx)(le,{pageChannel:`slack`,snapshot:I.kind===`ready`?I.data:{},enabledChannels:Se,homeChannel:Ce,setEnabledChannels:z,setHomeChannel:we,dirty:n,idPrefix:`sl-channel`}),(0,h.jsx)(d,{id:`sl-mentionOnly`,label:`Mention only`,value:Fe,onChange:e=>{Ie(e),G(`slack.mentionOnly`,{value:e,original:K.mentionOnly!==!1,valid:!0})}}),(0,h.jsx)(d,{id:`sl-replyInThread`,label:`Reply in thread`,value:Le,onChange:e=>{Re(e),G(`slack.replyInThread`,{value:e,original:K.replyInThread!==!1,valid:!0})}}),(0,h.jsx)(d,{id:`sl-forwardAll`,label:`Forward all`,value:je,onChange:e=>{Me(e),G(`slack.forwardAll`,{value:e,original:K.forwardAll!==!1,valid:!0})}}),(0,h.jsx)(d,{id:`sl-allowBots`,label:`Allow bots`,value:Ne,onChange:e=>{Pe(e),G(`slack.allowBots`,{value:e,original:!!K.allowBots,valid:!0})}}),(0,h.jsx)(d,{id:`sl-ackEnabled`,label:`Emoji reactions (👀 → ✅)`,value:ze,onChange:e=>{Be(e),G(`slack.ack.enabled`,{value:e,original:!!K.ack?.enabled,valid:!0})}})]})]}),(0,h.jsxs)(u,{title:`Actions`,hint:`Guided setup validates credentials with the issuer before saving.`,children:[(0,h.jsxs)(a,{children:[(0,h.jsx)(`button`,{type:`button`,className:`settings-action settings-action-danger`,disabled:J||E||S,onClick:()=>void We(),children:x(`settings.slack.resetConnection`)}),(0,h.jsx)(`button`,{type:`button`,className:`settings-action`,disabled:J||E||S,"data-onboard-channel":`slack`,onClick:Ve,children:x(`onboarding.open`)})]}),O&&(0,h.jsx)(c,{tone:`error`,role:`alert`,children:O})]}),S&&(0,h.jsx)(se,{client:t,t:x,initialDraft:{botToken:B,appToken:H},returnFocus:T.current,onBeforeSave:Ue,onClose:He},e)]})}function me(e){return e===`telegram`||e===`discord`||e===`slack`}export{b as default,_ as isValidSlackConversationId};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{a as r,i,l as a,n as o,r as s,s as c,t as l,u}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{a as r,i,l as a,n as o,r as s,s as c,t as l,u}from"./page-shell-Cz2ylri8.js";import{a as d,n as f,o as ee}from"./fields-CicOWY-X.js";import{t as p}from"./path-utils-B6vBr0DD.js";import{a as m,n as h,t as te}from"./ChannelEnablementControl-ooOkdd-Q.js";import{i as ne,n as re,t as ie}from"./ChannelSetupEntry-B0b4TdhH.js";var g=e(t(),1),_=n(),v=[`messaging.enabledChannels`,`messaging.homeChannel`,`telegram.enabled`,`telegram.token`,`telegram.allowedChatIds`,`telegram.forwardAll`,`telegram.mentionOnly`],y=[`telegram.enabled`,`telegram.token`,`telegram.allowedChatIds`];function b(e){return e?/^-?\d+$/.test(e.trim()):!1}function x(e){let t=[],n=[];for(let r of e)b(r)?t.push(r.trim()):n.push(r);return{valid:t,invalid:n}}function S(e){return e?e.filter(e=>Number.isFinite(e)).map(e=>String(e)):[]}function C(e){let t=[];for(let n of e){if(!b(n))continue;let e=Number(n);Number.isFinite(e)&&t.push(e)}return t}function w({port:e,client:t,dirty:n,registerSave:w,manager:E}){let D=(0,g.useMemo)(()=>m(E?.ui.locale??document.documentElement.lang),[E?.ui.locale]),{state:O,refresh:k,setData:A}=u(t,`/api/settings`),[j,M]=(0,g.useState)(!1),[N,P]=(0,g.useState)([]),[F,I]=(0,g.useState)(`telegram`),[L,R]=(0,g.useState)(!1),[z,B]=(0,g.useState)(``),[V,H]=(0,g.useState)([]),[U,W]=(0,g.useState)(!0),[G,K]=(0,g.useState)(!0);(0,g.useEffect)(()=>{if(O.kind!==`ready`)return;let e=O.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];P(t.filter(T)),I(T(e.homeChannel)?e.homeChannel:`telegram`);let n=O.data.telegram||{};R(!!n.enabled),B(``),H(S(n.allowedChatIds)),W(n.forwardAll!==!1),K(n.mentionOnly!==!1)},[O]),(0,g.useEffect)(()=>()=>{for(let e of v)n.remove(e)},[n]);let q=(0,g.useCallback)((e,t)=>n.set(e,t),[n]),J=(0,g.useMemo)(()=>O.kind===`ready`&&O.data.telegram||{},[O]),Y=O.kind===`ready`&&Array.isArray(O.data.telegramEnvironmentVariables)?O.data.telegramEnvironmentVariables:[],X=Y.length>0,Z=(0,g.useRef)({environmentManaged:X,environmentVariables:Y,t:D});(0,g.useLayoutEffect)(()=>{Z.current={environmentManaged:X,environmentVariables:Y,t:D}},[X,Y,D]);let Q=(0,g.useCallback)(async()=>{if(j)throw Error(`Finish channel setup before saving settings.`);let e=n.saveBundle();if(Object.keys(e).length===0)return;let r=Z.current;if(r.environmentManaged&&y.some(t=>t in e))throw Error(r.t(`settings.telegram.managedByEnvironment`,{variables:r.environmentVariables.join(`, `)}));let i=p(e),a=await t.put(`/api/settings`,i),o=a&&typeof a==`object`&&`data`in a?a.data:a;n.clear(),A(o);let s=o.messaging||{};P(Array.isArray(s.enabledChannels)?s.enabledChannels.filter(T):[]),I(T(s.homeChannel)?s.homeChannel:`telegram`);let c=o.telegram||{};R(!!c.enabled),B(``),H(S(c.allowedChatIds)),W(c.forwardAll!==!1),K(c.mentionOnly!==!1),await k()},[t,n,k,A,j]);if((0,g.useEffect)(()=>{if(w)return w(Q),()=>w(null)},[w,Q]),O.kind===`loading`)return(0,_.jsx)(o,{});if(O.kind===`offline`)return(0,_.jsx)(s,{port:e});if(O.kind===`error`)return(0,_.jsx)(l,{message:O.message});let ae=J.token?J.token.slice(-4):``,oe=J.token?`••••••••${ae}`:`(empty)`,{invalid:$}=x(V),se=$.length>0?`Numeric chat IDs only — invalid: ${$.join(`, `)}`:null;return(0,_.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),Q()},children:[(0,_.jsxs)(`fieldset`,{disabled:j,className:`settings-slack-fields`,children:[(0,_.jsxs)(c,{title:`Status`,hint:`Live transport state plus a token/connectivity probe for this channel.`,children:[(0,_.jsx)(r,{items:[{label:`Telegram`,value:L?(0,_.jsx)(a,{tone:`ok`,children:`Enabled`}):(0,_.jsx)(a,{tone:`neutral`,children:`Disabled`})},...X?[{label:`Managed by`,value:Y.join(`, `),mono:!0}]:[]]}),(0,_.jsx)(h,{client:t,channel:`telegram`}),(0,_.jsx)(re,{client:t,label:`Telegram`,endpoint:`/api/telegram/probe`,method:`POST`,interpret:ne})]}),(0,_.jsxs)(c,{title:`Credentials`,hint:X?D(`settings.telegram.managedByEnvironment`,{variables:Y.join(`, `)}):`Bot token and the allow-list for inbound chats.`,children:[(0,_.jsx)(d,{id:`tg-enabled`,label:`Telegram enabled`,value:L,disabled:X,onChange:e=>{R(e),q(`telegram.enabled`,{value:e,original:!!J.enabled,valid:!0})}}),(0,_.jsx)(ee,{id:`tg-token`,label:`Bot token`,value:z,placeholder:oe,disabled:X,onChange:e=>{if(B(e),e.length===0){n.remove(`telegram.token`);return}q(`telegram.token`,{value:e,original:J.token??``,valid:!0})}}),(0,_.jsx)(f,{id:`tg-allowedChatIds`,label:`Allowed chat IDs`,value:V,placeholder:`123456789`,error:se,disabled:X,onChange:e=>{H(e);let t=e.every(b);q(`telegram.allowedChatIds`,{value:C(e),original:J.allowedChatIds??[],valid:t})}})]}),(0,_.jsxs)(c,{title:`Routing`,hint:`Choose which channels receive inbound chat and how replies are delivered. Outbound send can still work on any configured channel.`,children:[(0,_.jsx)(te,{pageChannel:`telegram`,snapshot:O.kind===`ready`?O.data:{},enabledChannels:N,homeChannel:F,setEnabledChannels:P,setHomeChannel:I,dirty:n,idPrefix:`tg-channel`}),(0,_.jsx)(d,{id:`tg-forwardAll`,label:`Forward all responses`,value:U,onChange:e=>{W(e),q(`telegram.forwardAll`,{value:e,original:J.forwardAll!==!1,valid:!0})}}),(0,_.jsx)(d,{id:`tg-mentionOnly`,label:`Mention only`,value:G,onChange:e=>{K(e),q(`telegram.mentionOnly`,{value:e,original:J.mentionOnly!==!1,valid:!0})}})]})]}),(0,_.jsx)(c,{title:`Actions`,hint:`Guided setup validates credentials with the issuer before saving.`,children:(0,_.jsx)(i,{children:(0,_.jsx)(ie,{channel:`telegram`,client:t,dirty:n,disabled:X,open:j,onOpenChange:M,onSaved:async()=>A(await t.get(`/api/settings`))})})})]})}function T(e){return e===`telegram`||e===`discord`||e===`slack`}export{S as chatIdsToChips,C as chipsToChatIds,w as default,b as isValidChatId,x as partitionChatIds};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{n as r,s as i,t as a,u as o}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{n as r,s as i,t as a,u as o}from"./page-shell-Cz2ylri8.js";import{a as s,s as c}from"./fields-CicOWY-X.js";var l=e(t(),1),u=n();function d(){return{async get(e){let t=await fetch(e);if(!t.ok)throw Error(`GET ${e} → ${t.status}`);return await t.json()},async patch(e,t){let n=await fetch(e,{method:`PATCH`,headers:{"content-type":`application/json`},body:JSON.stringify(t)});if(!n.ok)throw Error(`PATCH ${e} → ${n.status}`);return await n.json()}}}var f=[`meta.label`,`meta.group`,`meta.favorite`,`meta.hidden`,`meta.notes`];function p(e,t){let n=e?.registry?.instances?.[String(t)];return{label:n?.label??null,favorite:n?.favorite===!0,group:n?.group??null,hidden:n?.hidden===!0,notes:n?.notes??null}}function m(e){return{label:e.label||``,group:e.group||``,favorite:e.favorite,hidden:e.hidden,notes:e.notes||``}}function h(){return(0,u.jsx)(`p`,{className:`settings-empty`,role:`status`,children:`Select an instance to edit its dashboard metadata.`})}function g(e){return e.port?(0,u.jsx)(_,{...e}):(0,u.jsx)(h,{})}function _({port:e,client:t,dirty:n,registerSave:h,managerClient:g}){let{state:_,refresh:v,setData:y}=o(t,`__dashboard_meta_unused__`,[e]),[b,x]=(0,l.useState)(null),[S,C]=(0,l.useState)(null),[w,T]=(0,l.useState)({label:``,group:``,favorite:!1,hidden:!1,notes:``}),E=g||d();(0,l.useEffect)(()=>{let t=!1;return C(null),E.get(`/api/dashboard/registry`).then(n=>{t||(x(n),T(m(p(n,e))))}).catch(e=>{t||C(e instanceof Error?e.message:String(e))}),()=>{t=!0}},[e]),(0,l.useEffect)(()=>()=>{for(let e of f)n.remove(e)},[n]);let D=p(b,e),O=(0,l.useCallback)((e,t)=>n.set(e,t),[n]),k=(0,l.useCallback)(async()=>{let t=w.label.trim()||null,r=w.group.trim()||null,i=w.notes.trim()||null,a={instances:{[String(e)]:{label:t,group:r,favorite:w.favorite,hidden:w.hidden,notes:i}}},o=await E.patch(`/api/dashboard/registry`,a);x(o),T(m(p(o,e)));for(let e of f)n.remove(e)},[w,E,n,e]);return(0,l.useEffect)(()=>{if(h)return h(k),()=>h(null)},[h,k]),S?(0,u.jsx)(a,{message:S}):b?(0,u.jsx)(`form`,{className:`settings-page-form settings-form`,onSubmit:e=>{e.preventDefault(),k()},children:(0,u.jsxs)(i,{title:`Dashboard meta`,hint:`Manager-side metadata for this instance. Stored in the dashboard registry.`,children:[(0,u.jsx)(c,{id:`dashmeta-label`,label:`Label`,value:w.label,placeholder:`(unset — falls back to home folder name)`,onChange:e=>{T({...w,label:e}),O(`meta.label`,{value:e,original:D.label||``,valid:!0})}}),(0,u.jsx)(c,{id:`dashmeta-group`,label:`Group`,value:w.group,placeholder:`e.g. work, personal`,onChange:e=>{T({...w,group:e}),O(`meta.group`,{value:e,original:D.group||``,valid:!0})}}),(0,u.jsx)(s,{id:`dashmeta-favorite`,label:`Pin favorite`,value:w.favorite,onChange:e=>{T({...w,favorite:e}),O(`meta.favorite`,{value:e,original:D.favorite,valid:!0})}}),(0,u.jsx)(s,{id:`dashmeta-hidden`,label:`Hide by default`,description:`Hide from the default instance list.`,value:w.hidden,onChange:e=>{T({...w,hidden:e}),O(`meta.hidden`,{value:e,original:D.hidden,valid:!0})}}),(0,u.jsxs)(`label`,{className:`settings-field`,htmlFor:`dashmeta-notes`,children:[(0,u.jsx)(`span`,{className:`settings-field-label`,children:`Notes`}),(0,u.jsx)(`textarea`,{id:`dashmeta-notes`,rows:4,value:w.notes,placeholder:`Free-form notes only the dashboard remembers.`,onChange:e=>{let t=e.target.value;T({...w,notes:t}),O(`meta.notes`,{value:t,original:D.notes||``,valid:!0})}})]})]})}):(0,u.jsx)(r,{label:`Loading dashboard registry…`})}var v={readInstance:p,toDraft:m,META_KEYS:f};export{v as __test__,g as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-CkEUZM6i.js";import{s as t}from"./shared-
|
|
1
|
+
import{t as e}from"./jsx-runtime-CkEUZM6i.js";import{s as t}from"./shared-CftvKNY9.js";var n=e(),r={ko:{title:`개발 도구`,description:`Diff 패널이 선택된 인스턴스의 repo root와 기본 비교 방식을 고르는 기준입니다.`,rootPolicy:[`Repo root 우선순위`,`Diff panel`,`선택된 인스턴스에서 어떤 경로를 먼저 git repo로 볼지 정합니다.`],diffMode:[`기본 diff 모드`,`Diff panel`,`처음 열 때 사용할 비교 범위입니다.`],baseRef:[`기본 base ref`,`Base ref 모드`,`origin/master, main, HEAD 같은 기준 ref입니다.`],untracked:[`Untracked 포함`,`Diff summary`,`아직 git에 추가되지 않은 파일도 목록에 표시합니다.`]},en:{title:`Developer tools`,description:`Defaults used by the Diff panel when it resolves a repo root from the selected instance.`,rootPolicy:[`Repo root priority`,`Diff panel`,`Choose which selected-instance path is tried first as a git repository.`],diffMode:[`Default diff mode`,`Diff panel`,`Comparison scope used when the panel opens.`],baseRef:[`Default base ref`,`Base ref mode`,`Reference used for base comparisons, such as origin/master, main, or HEAD.`],untracked:[`Include untracked`,`Diff summary`,`Show files that are not yet tracked by git.`]},zh:{title:`开发工具`,description:`Diff 面板从已选实例解析 repo root 与默认比较方式时使用的设置。`,rootPolicy:[`Repo root 优先级`,`Diff panel`,`决定优先把已选实例中的哪个路径当作 git repo。`],diffMode:[`默认 diff 模式`,`Diff panel`,`面板打开时使用的比较范围。`],baseRef:[`默认 base ref`,`Base ref 模式`,`例如 origin/master、main 或 HEAD。`],untracked:[`包含 untracked`,`Diff summary`,`显示尚未被 git 跟踪的文件。`]},ja:{title:`開発ツール`,description:`Diff パネルが選択中インスタンスから repo root と比較方式を決めるときの既定値です。`,rootPolicy:[`Repo root の優先順位`,`Diff panel`,`選択中インスタンスのどのパスを先に git repo として扱うかを決めます。`],diffMode:[`既定の diff モード`,`Diff panel`,`パネルを開いたときの比較範囲です。`],baseRef:[`既定の base ref`,`Base ref モード`,`origin/master、main、HEAD などの基準 ref です。`],untracked:[`Untracked を含める`,`Diff summary`,`git で未追跡のファイルも一覧に表示します。`]}},i=[{value:`project-first`,label:`Project dirs first`},{value:`working-dir-first`,label:`Working dir first`},{value:`manual`,label:`Pinned root first`}],a=[{value:`unstaged`,label:`Unstaged`},{value:`staged`,label:`Staged`},{value:`head`,label:`HEAD`},{value:`base`,label:`Base ref`}];function o(e,t,r){return(0,n.jsxs)(`div`,{className:`dashboard-settings-row`,children:[(0,n.jsxs)(`div`,{className:`dashboard-settings-row-main`,children:[(0,n.jsxs)(`label`,{className:`dashboard-settings-row-heading`,htmlFor:e,children:[(0,n.jsx)(`span`,{children:t[0]}),(0,n.jsx)(`span`,{className:`dashboard-settings-row-scope`,children:t[1]})]}),(0,n.jsx)(`p`,{className:`dashboard-settings-row-description`,children:t[2]})]}),(0,n.jsx)(`div`,{className:`dashboard-settings-row-control`,children:r})]})}function s(e){let t=r[e.locale]||r.ko;return(0,n.jsxs)(`section`,{className:`dashboard-settings-section`,children:[(0,n.jsxs)(`header`,{children:[(0,n.jsx)(`h3`,{children:t.title}),(0,n.jsx)(`p`,{children:t.description})]}),(0,n.jsxs)(`div`,{className:`dashboard-settings-field-list`,children:[o(`dashboard-diff-root-policy`,t.rootPolicy,(0,n.jsx)(`select`,{id:`dashboard-diff-root-policy`,className:`dashboard-settings-select`,value:e.ui.diffRootPolicy,onChange:t=>e.onUiPatch({diffRootPolicy:t.currentTarget.value}),children:i.map(e=>(0,n.jsx)(`option`,{value:e.value,children:e.label},e.value))})),o(`dashboard-diff-default-mode`,t.diffMode,(0,n.jsx)(`select`,{id:`dashboard-diff-default-mode`,className:`dashboard-settings-select`,value:e.ui.diffDefaultMode,onChange:t=>e.onUiPatch({diffDefaultMode:t.currentTarget.value}),children:a.map(e=>(0,n.jsx)(`option`,{value:e.value,children:e.label},e.value))})),o(`dashboard-diff-base-ref`,t.baseRef,(0,n.jsx)(`input`,{id:`dashboard-diff-base-ref`,className:`dashboard-settings-shortcut-input`,type:`text`,value:e.ui.diffBaseRef,onChange:t=>e.onUiPatch({diffBaseRef:t.currentTarget.value})})),o(`dashboard-diff-include-untracked`,t.untracked,(0,n.jsx)(`input`,{id:`dashboard-diff-include-untracked`,className:`dashboard-settings-toggle`,type:`checkbox`,checked:e.ui.diffIncludeUntracked,onChange:t=>e.onUiPatch({diffIncludeUntracked:t.currentTarget.checked})}))]})]})}function c({manager:e}){return e?(0,n.jsx)(s,{locale:t(e.ui.locale),ui:e.ui,onUiPatch:e.onUiPatch}):null}export{c as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-CkEUZM6i.js";import{i as t,n}from"./manager-shortcuts-Cqmr0mEq.js";import{s as r}from"./page-shell-
|
|
1
|
+
import{t as e}from"./jsx-runtime-CkEUZM6i.js";import{i as t,n}from"./manager-shortcuts-Cqmr0mEq.js";import{s as r}from"./page-shell-Cz2ylri8.js";import{a as i,c as a,i as o,n as s,r as c,s as l,t as u}from"./shared-CftvKNY9.js";var d=e();function f({manager:e}){if(!e)return null;let f=e,p=l(f.ui.locale),m=u[p];function h(e,t){f.onUiPatch({dashboardShortcutKeymap:{...f.ui.dashboardShortcutKeymap,[e]:t}})}return(0,d.jsxs)(r,{title:m.displayTitle,hint:m.displayDescription,children:[(0,d.jsx)(c,{id:`dashboard-show-activity-title`,label:m.fields.activity.label,scope:m.fields.activity.scope,value:f.ui.showLatestActivityTitles,description:m.fields.activity.description,onChange:e=>f.onUiPatch({showLatestActivityTitles:e})}),(0,d.jsx)(c,{id:`dashboard-show-label-editor`,label:m.fields.rename.label,scope:m.fields.rename.scope,value:f.ui.showInlineLabelEditor,description:m.fields.rename.description,onChange:e=>f.onUiPatch({showInlineLabelEditor:e})}),(0,d.jsx)(c,{id:`dashboard-show-runtime-line`,label:m.fields.runtime.label,scope:m.fields.runtime.scope,value:f.ui.showSidebarRuntimeLine,description:m.fields.runtime.description,onChange:e=>f.onUiPatch({showSidebarRuntimeLine:e})}),(0,d.jsx)(c,{id:`dashboard-show-row-actions`,label:m.fields.actions.label,scope:m.fields.actions.scope,value:f.ui.showSelectedRowActions,description:m.fields.actions.description,onChange:e=>f.onUiPatch({showSelectedRowActions:e})}),(0,d.jsx)(s,{id:`dashboard-locale`,label:m.fields.language.label,scope:m.fields.language.scope,value:p,options:i,description:m.fields.language.description,onChange:e=>f.onUiPatch({locale:e})}),(0,d.jsx)(c,{id:`dashboard-shortcuts-enabled`,label:m.fields.shortcuts.label,scope:m.fields.shortcuts.scope,value:f.ui.dashboardShortcutsEnabled,description:m.fields.shortcuts.description,onChange:e=>f.onUiPatch({dashboardShortcutsEnabled:e})}),n.map(e=>{let n=m.fields[a(e)];return(0,d.jsx)(o,{action:e,label:n.label,scope:n.scope,value:f.ui.dashboardShortcutKeymap[e],description:`${n.description} Current: ${t(f.ui.dashboardShortcutKeymap[e])}`,onChange:h},e)})]})}export{f as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{r as t,t as n}from"./presentation-DWHWElFr.js";import{n as r,t as i}from"./jsx-runtime-CkEUZM6i.js";import{n as a,o,r as s,s as c,t as l,u}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{r as t,t as n}from"./presentation-DWHWElFr.js";import{n as r,t as i}from"./jsx-runtime-CkEUZM6i.js";import{n as a,o,r as s,s as c,t as l,u}from"./page-shell-Cz2ylri8.js";import{t as d}from"./error-normalize-jnjrKZDu.js";import{i as f,r as p}from"./fields-CicOWY-X.js";import{t as m}from"./path-utils-B6vBr0DD.js";var h=e(r(),1),g=i(),_=[{value:`jaw-default`,label:`Jaw default`},{value:`jaw-dark`,label:`Jaw dark`},{value:`jaw-light`,label:`Jaw light`},{value:`jaw-contrast`,label:`High contrast`}],v=[{value:`default`,label:`default`},{value:`vim`,label:`vim`},{value:`emacs`,label:`emacs`}],y=[{value:`summary`,label:`summary`},{value:`unified`,label:`unified`},{value:`side-by-side`,label:`side-by-side`}],b=[`presentation.mode`,`tui.themeSeed`,`tui.keymapPreset`,`tui.pasteCollapseLines`,`tui.pasteCollapseChars`,`tui.diffStyle`];function x({port:e,client:r,dirty:i,registerSave:x}){let{state:S,refresh:C,setData:w}=u(r,`/api/settings`,[e]),[T,E]=(0,h.useState)({}),D=(0,h.useSyncExternalStore)(i.subscribe,()=>i.pending.get(`presentation.mode`)?.value,()=>void 0),O=n(D)?D:t(S.kind===`ready`?S.data:void 0),[k,A]=(0,h.useState)(null),[j,M]=(0,h.useState)(!1),N=(0,h.useRef)(null),P=(0,h.useRef)(null);(0,h.useLayoutEffect)(()=>(N.current={client:r,port:e},P.current=null,M(!1),()=>{N.current=null,P.current=null}),[r,e,i]),(0,h.useEffect)(()=>{S.kind===`ready`&&E({...S.data.tui||{}})},[S]),(0,h.useEffect)(()=>(E({}),A(null),()=>{for(let e of b)i.remove(e)}),[r,e,i]);let F=(0,h.useCallback)((e,t)=>i.set(e,t),[i]),I=(0,h.useCallback)(()=>{let t=N.current;if(!t||t.client!==r||t.port!==e)return Promise.resolve();if(P.current?.instance===t)return P.current.promise;A(null);let n=i.saveBundle();if(Object.keys(n).length===0)return Promise.resolve();let a=m(n),o=new Map([...i.pending].filter(([e])=>Object.hasOwn(n,e)));M(!0);let s={instance:t,promise:Promise.resolve()};return s.promise=Promise.resolve().then(async()=>{if(N.current!==t)return;let e=await r.put(`/api/settings`,a);if(N.current!==t)return;let n=e&&typeof e==`object`&&`data`in e?e.data:e;for(let[e,t]of o)i.pending.get(e)===t&&i.remove(e);E({...n.tui||{}}),w(n),await C()}).finally(()=>{P.current===s&&(P.current=null),N.current===t&&M(!1)}),P.current=s,s.promise},[r,e,i,C,w]);if((0,h.useEffect)(()=>{if(x)return x(I),()=>x(null)},[x,I]),S.kind===`loading`)return(0,g.jsx)(a,{});if(S.kind===`offline`)return(0,g.jsx)(s,{port:e});if(S.kind===`error`)return(0,g.jsx)(l,{message:S.message});let L=S.data.tui||{};return(0,g.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault();let t=N.current;I().catch(e=>{t&&N.current===t&&A(d(e))})},children:[(0,g.jsxs)(c,{title:`Conversation display`,hint:`Changes conversation display only. Runtime and permissions stay unchanged.`,children:[k?(0,g.jsx)(o,{tone:`error`,role:`alert`,children:k}):null,(0,g.jsx)(f,{disabled:j,id:`display-presentation-mode`,label:`Presentation`,value:O,options:[{value:`activity`,label:`Activity (default)`},{value:`legacy`,label:`Legacy transcript`}],onChange:e=>{P.current||(e===`activity`||e===`legacy`)&&F(`presentation.mode`,{value:e,original:t(S.data),valid:!0})}})]}),(0,g.jsxs)(c,{title:`Display`,hint:`TUI options applied to /i/${e}.`,children:[(0,g.jsx)(f,{disabled:j,id:`display-themeSeed`,label:`Theme seed`,value:T.themeSeed??L.themeSeed??`jaw-default`,options:_,onChange:e=>{P.current||(E({...T,themeSeed:e}),F(`tui.themeSeed`,{value:e,original:L.themeSeed??`jaw-default`,valid:!0}))}}),(0,g.jsx)(f,{disabled:j,id:`display-keymapPreset`,label:`Keymap preset`,value:T.keymapPreset??L.keymapPreset??`default`,options:v,onChange:e=>{P.current||(E({...T,keymapPreset:e}),F(`tui.keymapPreset`,{value:e,original:L.keymapPreset??`default`,valid:!0}))}}),(0,g.jsx)(p,{disabled:j,id:`display-pasteCollapseLines`,label:`Paste collapse — lines`,value:T.pasteCollapseLines??L.pasteCollapseLines??2,min:0,step:1,onChange:e=>{P.current||(E({...T,pasteCollapseLines:e}),F(`tui.pasteCollapseLines`,{value:e,original:L.pasteCollapseLines??2,valid:Number.isFinite(e)&&e>=0}))}}),(0,g.jsx)(p,{disabled:j,id:`display-pasteCollapseChars`,label:`Paste collapse — chars`,value:T.pasteCollapseChars??L.pasteCollapseChars??160,min:0,step:10,onChange:e=>{P.current||(E({...T,pasteCollapseChars:e}),F(`tui.pasteCollapseChars`,{value:e,original:L.pasteCollapseChars??160,valid:Number.isFinite(e)&&e>=0}))}}),(0,g.jsx)(f,{disabled:j,id:`display-diffStyle`,label:`Diff style`,value:T.diffStyle??L.diffStyle??`summary`,options:y,onChange:e=>{P.current||(E({...T,diffStyle:e}),F(`tui.diffStyle`,{value:e,original:L.diffStyle??`summary`,valid:!0}))}})]})]})}export{x as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{s as r,t as i}from"./shared-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{s as r,t as i}from"./shared-CftvKNY9.js";var a=e(t(),1),o=n(),s=`/api/dashboard/memory`,c=[`provider`,`apikey`,`test`,`indexing`,`active`],l={provider:`Provider`,apikey:`API Key`,test:`Test connection`,indexing:`Indexing`,active:`Active`},u=[{value:``,label:`(select)`},{value:`openai`,label:`OpenAI`},{value:`gemini`,label:`Gemini`},{value:`voyage`,label:`Voyage AI`},{value:`vertex`,label:`Vertex AI`},{value:`local`,label:`Local (Ollama)`}],d=[{value:`hybrid`,label:`Hybrid (FTS5 + Embedding)`},{value:`embedding`,label:`Embedding only`},{value:`fts5`,label:`FTS5 only (no vectors)`}],f={openai:{model:`text-embedding-3-small`,dimensions:1536},gemini:{model:`gemini-embedding-001`,dimensions:768},voyage:{model:`voyage-3-lite`,dimensions:512},vertex:{model:`text-embedding-005`,dimensions:768},local:{model:`nomic-embed-text`,dimensions:768}};async function p(e,t){let n=await fetch(`${s}${e}`,{credentials:`same-origin`,headers:{"Content-Type":`application/json`},...t});if(!n.ok)throw Error(`HTTP ${n.status}`);return n.json()}function m(e,t,n){return e?.provider?e.provider!==`local`&&!e.apiKey&&!e.apiKeyPresent?`apikey`:t?.state===`ACTIVE_HYBRID`||t?.state===`ACTIVE_EMBEDDING`?`active`:t?.state===`INDEXING`?`indexing`:n?!t?.active&&(t?.indexedChunks??0)<(t?.totalChunks??1)?`indexing`:`active`:`test`:`provider`}function h({current:e}){let t=c.indexOf(e);return(0,o.jsx)(`div`,{className:`embed-stepper`,role:`list`,children:c.map((e,n)=>{let r=n<t,i=n===t;return(0,o.jsxs)(`div`,{className:r?`embed-step is-done`:i?`embed-step is-active`:`embed-step`,role:`listitem`,"aria-current":i?`step`:void 0,children:[(0,o.jsx)(`span`,{className:`embed-step-badge`,children:r?`✓`:n+1}),(0,o.jsx)(`span`,{className:`embed-step-label`,children:l[e]})]},e)})})}function g(){let[e,t]=(0,a.useState)(null),[n,r]=(0,a.useState)(null),[i,c]=(0,a.useState)(null),[l,g]=(0,a.useState)(!0),[_,v]=(0,a.useState)(``),[y,b]=(0,a.useState)(``),[x,S]=(0,a.useState)(1536),[C,w]=(0,a.useState)(``),[T,E]=(0,a.useState)(`hybrid`),[D,O]=(0,a.useState)(``),[k,A]=(0,a.useState)(null),[j,M]=(0,a.useState)(``),[N,P]=(0,a.useState)(!1),[F,I]=(0,a.useState)(!1),[L,R]=(0,a.useState)({done:0,total:0}),[z,B]=(0,a.useState)(null),V=(0,a.useRef)(null),H=(0,a.useCallback)(async()=>{try{let[e,n,i]=await Promise.all([p(`/embed-config`),p(`/embed-state`),p(`/embed-estimate`)]);t(e.config),r(n.status);let{ok:a,...o}=i;c(o)}catch{B(`Failed to load embedding state`)}finally{g(!1)}},[]);(0,a.useEffect)(()=>{H()},[H]),(0,a.useEffect)(()=>{e&&(v(e.provider||``),b(e.model||f[e.provider||``]?.model||``),S(e.dimensions??f[e.provider||``]?.dimensions??1536),w(e.apiKey||``),E(e.searchMode||`hybrid`),O(e.baseUrl||``))},[e]);let U=m(e,n,k),W=(0,a.useCallback)(async e=>{P(!0),B(null);try{await p(`/embed-config`,{method:`POST`,body:JSON.stringify(e)}),await H()}catch(e){B(e instanceof Error?e.message:String(e))}finally{P(!1)}},[H]),G=(0,a.useCallback)(()=>{if(!_)return;A(null),M(``);let e={provider:_,model:y,dimensions:x,searchMode:T};D&&(e.baseUrl=D),W(e)},[_,y,x,T,D,W]),K=(0,a.useCallback)(()=>{W({apiKey:C})},[C,W]),q=(0,a.useCallback)(async()=>{A(null),M(`Testing...`),B(null);try{let e={provider:_,model:y,dimensions:x,test:!0};C.trim()&&(e.apiKey=C.trim());let t=await p(`/embed-config`,{method:`POST`,body:JSON.stringify(e)});t.testResult===`ok`?(A(!0),M(`Connection successful`)):(A(!1),M(t.testError||`Connection failed`))}catch(e){A(!1),M(e instanceof Error?e.message:String(e))}},[_,y,x,C]),J=(0,a.useCallback)(async()=>{I(!0),R({done:0,total:0}),B(null);let e=new AbortController;V.current=e;try{let t=await fetch(`${s}/reindex-stream`,{signal:e.signal,credentials:`same-origin`});if(!t.ok||!t.body)throw Error(`HTTP ${t.status}`);let n=t.body.getReader(),r=new TextDecoder,i=``;for(;;){let{done:e,value:t}=await n.read();if(e)break;i+=r.decode(t,{stream:!0});let a=i.split(`
|
|
2
2
|
`);i=a.pop()||``;for(let e of a)if(e.startsWith(`data: `))try{let t=JSON.parse(e.slice(6));if(t.complete){I(!1),await H();return}if(t.error){B(String(t.error)),I(!1);return}typeof t.done==`number`&&R({done:t.done,total:t.total||0})}catch{}}I(!1),await H()}catch(e){e.name!==`AbortError`&&B(e instanceof Error?e.message:String(e)),I(!1)}},[H]);if((0,a.useEffect)(()=>()=>V.current?.abort(),[]),l)return(0,o.jsx)(`p`,{className:`dashboard-settings-row-description`,children:`Loading...`});let Y=n?.state===`NEEDS_REINDEX`,X=n?.state===`ACTIVE_HYBRID`||n?.state===`ACTIVE_EMBEDDING`;return(0,o.jsxs)(`div`,{className:`dashboard-embed-section`,children:[(0,o.jsx)(h,{current:U}),(0,o.jsxs)(`fieldset`,{className:`dashboard-embed-fieldset`,children:[(0,o.jsx)(`legend`,{children:`Provider`}),(0,o.jsxs)(`div`,{className:`dashboard-embed-field`,children:[(0,o.jsx)(`label`,{htmlFor:`embed-provider`,children:`Provider`}),(0,o.jsx)(`select`,{id:`embed-provider`,value:_,onChange:e=>{let t=e.target.value;v(t),A(null);let n=f[t];n&&(b(n.model),S(n.dimensions))},children:u.map(e=>(0,o.jsx)(`option`,{value:e.value,children:e.label},e.value))})]}),(0,o.jsxs)(`div`,{className:`dashboard-embed-field`,children:[(0,o.jsx)(`label`,{htmlFor:`embed-search-mode`,children:`Search mode`}),(0,o.jsx)(`select`,{id:`embed-search-mode`,value:T,onChange:e=>E(e.target.value),children:d.map(e=>(0,o.jsx)(`option`,{value:e.value,children:e.label},e.value))})]}),(0,o.jsxs)(`div`,{className:`dashboard-embed-field`,children:[(0,o.jsx)(`label`,{htmlFor:`embed-model`,children:`Model`}),(0,o.jsx)(`input`,{id:`embed-model`,type:`text`,value:y,onChange:e=>b(e.target.value),placeholder:f[_]?.model||`model name`})]}),(0,o.jsxs)(`div`,{className:`dashboard-embed-field`,children:[(0,o.jsx)(`label`,{htmlFor:`embed-dimensions`,children:`Dimensions`}),(0,o.jsx)(`input`,{id:`embed-dimensions`,type:`number`,min:64,max:4096,value:x,onChange:e=>S(Number(e.target.value)||1536)})]}),(_===`local`||_===`vertex`)&&(0,o.jsxs)(`div`,{className:`dashboard-embed-field`,children:[(0,o.jsx)(`label`,{htmlFor:`embed-base-url`,children:_===`vertex`?`Project ID / Region`:`Base URL`}),(0,o.jsx)(`input`,{id:`embed-base-url`,type:`text`,value:D,onChange:e=>O(e.target.value),placeholder:_===`local`?`http://localhost:11434`:`project-id/us-central1`})]}),(0,o.jsx)(`button`,{type:`button`,className:`dashboard-embed-btn`,disabled:!_||N,onClick:G,children:N?`Saving...`:`Save provider`})]}),(0,o.jsxs)(`fieldset`,{className:`dashboard-embed-fieldset`,children:[(0,o.jsx)(`legend`,{children:`API Key`}),_===`local`?(0,o.jsx)(`p`,{className:`dashboard-settings-row-description`,children:`Local provider uses Ollama — no API key needed.`}):(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(`div`,{className:`dashboard-embed-field`,children:[(0,o.jsx)(`label`,{htmlFor:`embed-api-key`,children:`API Key`}),(0,o.jsx)(`input`,{id:`embed-api-key`,type:`password`,value:C,onChange:e=>w(e.target.value),placeholder:`sk-...`,disabled:!_})]}),(0,o.jsx)(`button`,{type:`button`,className:`dashboard-embed-btn`,disabled:!C||N,onClick:K,children:`Save key`})]})]}),(0,o.jsxs)(`fieldset`,{className:`dashboard-embed-fieldset`,children:[(0,o.jsx)(`legend`,{children:`Connection test`}),(0,o.jsx)(`button`,{type:`button`,className:`dashboard-embed-btn`,disabled:!_||!C&&!e?.apiKeyPresent&&_!==`local`,onClick:()=>void q(),children:`Test connection`}),j&&(0,o.jsxs)(`p`,{className:k?`dashboard-embed-ok`:`dashboard-embed-err`,role:`status`,children:[k?`✓ `:`✗ `,j]})]}),(0,o.jsxs)(`fieldset`,{className:`dashboard-embed-fieldset`,children:[(0,o.jsxs)(`legend`,{children:[`Indexing`,i&&(0,o.jsxs)(`small`,{children:[` — `,i.totalChunks,` chunks · ~`,i.batches,` batches · ~`,Math.ceil(i.estimatedSeconds),`s · $`,i.estimatedCost.toFixed(4)]})]}),F?(0,o.jsxs)(`div`,{className:`embed-progress`,children:[(0,o.jsx)(`div`,{className:`embed-progress-bar`,children:(0,o.jsx)(`div`,{className:`embed-progress-fill`,style:{width:L.total>0?`${Math.round(L.done/L.total*100)}%`:`0%`}})}),(0,o.jsxs)(`span`,{className:`dashboard-settings-row-description`,children:[L.done,`/`,L.total,` batches`]})]}):(0,o.jsx)(`button`,{type:`button`,className:`dashboard-embed-btn`,disabled:!k&&!X&&!Y,onClick:()=>void J(),children:Y?`Re-index (provider changed)`:X?`Re-index`:`Start indexing`})]}),(0,o.jsxs)(`fieldset`,{className:`dashboard-embed-fieldset`,children:[(0,o.jsx)(`legend`,{children:`Status`}),n?(0,o.jsxs)(`dl`,{className:`embed-status-grid`,children:[(0,o.jsx)(`dt`,{children:`State`}),(0,o.jsx)(`dd`,{children:(0,o.jsx)(`code`,{children:n.state})}),(0,o.jsx)(`dt`,{children:`Mode`}),(0,o.jsx)(`dd`,{children:n.mode}),(0,o.jsx)(`dt`,{children:`Provider`}),(0,o.jsxs)(`dd`,{children:[n.provider||`-`,` / `,n.model||`-`]}),(0,o.jsx)(`dt`,{children:`Indexed`}),(0,o.jsxs)(`dd`,{children:[n.indexedChunks,` chunks`]}),(0,o.jsx)(`dt`,{children:`DB size`}),(0,o.jsx)(`dd`,{children:n.dbSizeBytes>0?`${(n.dbSizeBytes/1024/1024).toFixed(1)} MB`:`-`}),(0,o.jsx)(`dt`,{children:`Last sync`}),(0,o.jsx)(`dd`,{children:n.lastSyncAt||`never`}),(0,o.jsx)(`dt`,{children:`Fallback`}),(0,o.jsx)(`dd`,{children:n.fallback?`Yes (${n.reason})`:`No`})]}):(0,o.jsx)(`p`,{className:`dashboard-settings-row-description`,children:`No state available`})]}),z&&(0,o.jsx)(`p`,{className:`dashboard-embed-err`,role:`alert`,children:z})]})}function _({manager:e}){if(!e)return null;let t=i[r(e.ui.locale)];return(0,o.jsxs)(`section`,{className:`dashboard-settings-section`,children:[(0,o.jsxs)(`header`,{children:[(0,o.jsx)(`h3`,{children:t.embeddingTitle}),(0,o.jsx)(`p`,{children:t.embeddingDescription})]}),(0,o.jsx)(g,{})]})}export{_ as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{o as r,s as i}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{o as r,s as i}from"./page-shell-Cz2ylri8.js";var a=e(t(),1),o=n(),s=[`employees`],c=[`claude`,`codex`,`codex-app`,`copilot`,`cursor`,`kiro-code`,`gemini`,`grok`,`opencode`],l=0;function u(){return l+=1,`emp_${Date.now().toString(36)}_${l}`}function d(){let e=globalThis.crypto;if(e&&typeof e.randomUUID==`function`)try{return e.randomUUID()}catch{}return u()}function f(e=d()){return{id:e,name:``,cli:`claude`,role:``,prompt:``,active:!0}}function p(e){if(!Array.isArray(e))return[];let t=[],n=0;for(let r of e){if(typeof r==`string`){n+=1,t.push({...f(`emp_legacy_${n}`),name:r});continue}if(!r||typeof r!=`object`)continue;let e=r,i=typeof e.name==`string`?e.name:``;if(!i&&!e.id)continue;n+=1;let a=typeof e.id==`string`&&e.id.trim()?e.id.trim():`emp_unknown_${n}`,o=typeof e.cli==`string`&&e.cli.trim()?e.cli.trim():`claude`,s=typeof e.role==`string`?e.role:``,c=typeof e.prompt==`string`?e.prompt:``,l=e.active!==!1;t.push({id:a,name:i,cli:o,role:s,prompt:c,active:l})}return t}function m(e){return e.name.trim()?e.cli.trim()?null:`CLI is required`:`Name is required`}function h(e){return e.some(e=>m(e)!==null)}function g(e){let t=new Map;for(let n of e){let e=n.name.trim().toLowerCase();e&&t.set(e,(t.get(e)??0)+1)}let n=new Set;for(let[e,r]of t)r>1&&n.add(e);return n}function _(e){return e.map(e=>{let t={id:e.id,name:e.name.trim(),cli:e.cli.trim()||`claude`,role:e.role.trim(),active:e.active};return e.prompt.trim()&&(t.prompt=e.prompt),t})}function v({registerSave:e}){return(0,a.useEffect)(()=>{if(e)return e(null),()=>e(null)},[e]),(0,o.jsx)(`form`,{className:`settings-page-form`,onSubmit:e=>e.preventDefault(),children:(0,o.jsx)(i,{title:`Employees`,hint:`Runtime employees are now managed from the Agent page.`,children:(0,o.jsx)(r,{children:`Open Runtime / Agent to edit dispatchable employees, static employee model overrides, and database-backed employees in one place.`})})})}export{c as DEFAULT_CLI_OPTIONS,s as EMPLOYEE_KEYS,v as default,g as duplicateNameSet,m as employeeRowError,h as employeesHaveErrors,f as makeDefaultEmployee,d as newEmployeeId,p as normalizeEmployees,_ as toPersistShape};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{r as t,t as n}from"./cli-engine-NdU0lzs_.js";import{n as r,t as i}from"./jsx-runtime-CkEUZM6i.js";import{i as a,l as o,n as s,o as c,r as l,s as u,t as d,u as f}from"./page-shell-DfinU3mb.js";import{a as p,i as m,s as h}from"./fields-CicOWY-X.js";import{a as g,d as _}from"./agent-meta-94LMwZZK.js";import{t as v}from"./path-utils-B6vBr0DD.js";var y=e(r(),1),b=i(),x=[{value:`every`,label:`every (interval)`},{value:`cron`,label:`cron expression`}];function S({job:e,index:t,bodyError:n,timeZoneError:r,onChange:i,onRemove:a}){let s=(0,y.useId)(),c=e.schedule.kind,l=e.schedule.timeZone??``,u=e.name||`Job ${t+1}`;return(0,b.jsxs)(`div`,{className:`settings-card-group`,role:`group`,"aria-label":`Heartbeat job ${t+1}${e.name?` (${e.name})`:``}`,children:[(0,b.jsxs)(`div`,{className:`settings-card-actions`,children:[(0,b.jsxs)(`div`,{className:`settings-card-actions-status`,children:[(0,b.jsx)(`strong`,{children:u}),` `,e.enabled?(0,b.jsx)(o,{tone:`ok`,children:`Enabled`}):(0,b.jsx)(o,{tone:`neutral`,children:`Disabled`}),` `,(0,b.jsx)(o,{tone:`neutral`,children:c===`every`?`interval`:`cron`})]}),(0,b.jsx)(`div`,{className:`settings-card-actions-buttons`,children:(0,b.jsx)(`button`,{type:`button`,className:`settings-action settings-action-danger`,onClick:a,"aria-label":`Remove heartbeat job ${u}`,children:`Remove job`})})]}),(0,b.jsx)(p,{id:`${s}-enabled`,label:`Enabled`,value:e.enabled,onChange:e=>i({enabled:e})}),(0,b.jsx)(h,{id:`${s}-name`,label:`Name`,value:e.name,placeholder:`Morning summary`,onChange:e=>i({name:e})}),(0,b.jsx)(m,{id:`${s}-kind`,label:`Schedule kind`,value:c,options:x,onChange:e=>{e===`every`&&c!==`every`?i({schedule:{kind:`every`,minutes:30,...l?{timeZone:l}:{}}}):e===`cron`&&c!==`cron`&&i({schedule:{kind:`cron`,cron:`0 9 * * *`,...l?{timeZone:l}:{}}})}}),c===`every`?(0,b.jsx)(h,{id:`${s}-minutes`,label:`Every (minutes)`,value:String(e.schedule.minutes??``),placeholder:`30`,error:n??null,onChange:e=>{let t=e.trim(),n=Number(t);i({schedule:{kind:`every`,minutes:Number.isFinite(n)?n:NaN,...l?{timeZone:l}:{}}})}}):(0,b.jsx)(h,{id:`${s}-cron`,label:`Cron expression`,value:e.schedule.cron??``,placeholder:`0 9 * * *`,error:n??null,onChange:e=>i({schedule:{kind:`cron`,cron:e,...l?{timeZone:l}:{}}})}),(0,b.jsx)(h,{id:`${s}-tz`,label:`Time zone (optional)`,value:l,placeholder:`Asia/Seoul`,error:r??null,onChange:t=>{let n=t.trim();i(c===`every`?{schedule:{kind:`every`,minutes:e.schedule.minutes,...n?{timeZone:n}:{}}}:{schedule:{kind:`cron`,cron:e.schedule.cron,...n?{timeZone:n}:{}}})}}),(0,b.jsxs)(`label`,{className:`settings-field settings-field-textarea`,htmlFor:`${s}-prompt`,children:[(0,b.jsx)(`span`,{className:`settings-field-label`,children:`Prompt`}),(0,b.jsx)(`textarea`,{id:`${s}-prompt`,rows:3,value:e.prompt,placeholder:`What should this heartbeat do?`,onChange:e=>i({prompt:e.target.value})})]})]})}var C=/^\d+[smh]$/,w=/^([01]\d|2[0-3]):[0-5]\d$/,T=[`claude`,`codex`,`codex-app`,`copilot`,`cursor`,`kiro-code`,`gemini`,`grok`,`opencode`],E=[`heartbeat.enabled`,`heartbeat.every`,`heartbeat.activeHours.start`,`heartbeat.activeHours.end`,`heartbeat.target`],D=[`heartbeat.jobs`,`heartbeat.md`];function O(e){return C.test(e.trim())}function k(e){return w.test(e.trim())}var A=0;function j(e=Date.now()){return{id:`hb_${e}_${A++}`,name:``,enabled:!0,schedule:{kind:`every`,minutes:30},prompt:``}}function M(e){return e.startsWith(`heartbeat.`)&&e!==`heartbeat.jobs`&&e!==`heartbeat.md`}function N(e,t){if(!e||typeof e!=`object`)return null;let n=e,r=typeof n.id==`string`&&n.id.trim()?n.id.trim():`hb_unknown_${t}`,i=typeof n.name==`string`?n.name:``,a=n.enabled!==!1,o=typeof n.prompt==`string`?n.prompt:``,s=n.schedule,c;if(s&&typeof s==`object`){let e=s;c=e.kind===`cron`&&typeof e.cron==`string`?{kind:`cron`,cron:e.cron,...typeof e.timeZone==`string`&&e.timeZone?{timeZone:e.timeZone}:{}}:{kind:`every`,minutes:typeof e.minutes==`number`?e.minutes:30,...typeof e.timeZone==`string`&&e.timeZone?{timeZone:e.timeZone}:{}}}else c={kind:`every`,minutes:30};return{id:r,name:i,enabled:a,schedule:c,prompt:o}}function P(e){if(!e||typeof e!=`object`)return[];let t=e.jobs;return Array.isArray(t)?t.map((e,t)=>N(e,t)).filter(e=>e!==null):[]}function F(e){if(e.kind===`every`){let t=e.minutes;return!Number.isFinite(t)||t<=0||!Number.isInteger(t)?`Minutes must be a positive integer`:null}let t=e.cron?.trim()??``;return t?t.split(/\s+/).length<5?`Cron must have at least 5 fields`:null:`Cron expression required`}function I(e){return e.some(e=>F(e.schedule)!==null)}function L({port:e,client:t,dirty:n,snapshot:r}){let[i,o]=(0,y.useState)([]),[s,u]=(0,y.useState)([]),[f,p]=(0,y.useState)(!1),[m,h]=(0,y.useState)(null);(0,y.useEffect)(()=>{if(r.kind!==`ready`)return;let e=P(r.data);o(e),u(e)},[r]),(0,y.useEffect)(()=>{n.set(`heartbeat.jobs`,{value:i,original:s,valid:!I(i)})},[i,s,n]),(0,y.useEffect)(()=>()=>{n.remove(`heartbeat.jobs`)},[n]);let g=(0,y.useCallback)(async()=>{if(I(i)){h(`Fix invalid schedules before saving.`);return}p(!0),h(null);try{let e=P(await t.put(`/api/heartbeat`,{jobs:i}));o(e),u(e),n.remove(`heartbeat.jobs`)}catch(e){h(e instanceof Error?e.message:String(e))}finally{p(!1)}},[t,n,i]);if(r.kind===`loading`)return(0,b.jsx)(c,{children:`Loading jobs…`});if(r.kind===`offline`)return(0,b.jsx)(l,{port:e});if(r.kind===`error`)return(0,b.jsx)(d,{message:r.message});let _=n.pending.has(`heartbeat.jobs`),v=I(i);function x(e,t){o(n=>n.map((n,r)=>r===e?{...n,...t}:n))}function C(){o(e=>[...e,j()])}function w(e){o(t=>t.filter((t,n)=>n!==e))}return(0,b.jsxs)(b.Fragment,{children:[i.length===0?(0,b.jsx)(c,{children:`No jobs configured. Add one below.`}):(0,b.jsx)(b.Fragment,{children:i.map((e,t)=>(0,b.jsx)(S,{job:e,index:t,bodyError:F(e.schedule),onChange:e=>x(t,e),onRemove:()=>w(t)},e.id))}),(0,b.jsxs)(a,{children:[(0,b.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:C,children:`+ Add job`}),(0,b.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,onClick:()=>void g(),disabled:f||!_||v,children:f?`Saving…`:`Apply jobs`})]}),m?(0,b.jsx)(c,{tone:`error`,role:`alert`,children:m}):null]})}function R({port:e,client:t,dirty:n,snapshot:r}){let[i,o]=(0,y.useState)(``),[s,u]=(0,y.useState)(``),[f,p]=(0,y.useState)(!1),[m,h]=(0,y.useState)(null);(0,y.useEffect)(()=>{if(r.kind!==`ready`)return;let e=r.data.content??``;o(e),u(e)},[r]),(0,y.useEffect)(()=>{n.set(`heartbeat.md`,{value:i,original:s,valid:!0})},[i,s,n]),(0,y.useEffect)(()=>()=>{n.remove(`heartbeat.md`)},[n]);let g=(0,y.useCallback)(async()=>{p(!0),h(null);try{await t.put(`/api/heartbeat-md`,{content:i}),u(i),n.remove(`heartbeat.md`)}catch(e){h(e instanceof Error?e.message:String(e))}finally{p(!1)}},[t,n,i]);if(r.kind===`loading`)return(0,b.jsx)(c,{children:`Loading template…`});if(r.kind===`offline`)return(0,b.jsx)(l,{port:e});if(r.kind===`error`)return(0,b.jsx)(d,{message:r.message});let _=n.pending.has(`heartbeat.md`);return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(`label`,{className:`settings-field settings-field-textarea`,htmlFor:`hb-md`,children:[(0,b.jsx)(`span`,{className:`settings-field-label`,children:`Template`}),(0,b.jsx)(`textarea`,{id:`hb-md`,rows:10,spellCheck:!1,value:i,onChange:e=>o(e.target.value),style:{fontFamily:`var(--font-mono, ui-monospace, monospace)`}})]}),(0,b.jsx)(a,{children:(0,b.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,onClick:()=>void g(),disabled:f||!_,children:f?`Saving…`:`Save template`})}),m?(0,b.jsx)(c,{tone:`error`,role:`alert`,children:m}):null]})}function z({port:e,client:r,dirty:i,registerSave:a}){let o=f(r,`/api/settings`),c=f(r,`/api/heartbeat`),x=f(r,`/api/heartbeat-md`),[S,C]=(0,y.useState)(!1),[w,D]=(0,y.useState)(`30m`),[A,j]=(0,y.useState)(`08:00`),[N,P]=(0,y.useState)(`22:00`),[F,I]=(0,y.useState)(`all`);(0,y.useEffect)(()=>{if(o.state.kind!==`ready`)return;let e=o.state.data.heartbeat||{};C(!!e.enabled),D(typeof e.every==`string`?e.every:`30m`),j(e.activeHours?.start??`08:00`),P(e.activeHours?.end??`22:00`),I(typeof e.target==`string`?e.target:`all`)},[o.state]),(0,y.useEffect)(()=>()=>{for(let e of E)i.remove(e)},[i]);let z=(0,y.useMemo)(()=>o.state.kind===`ready`&&o.state.data.heartbeat||{},[o.state]),B=(0,y.useCallback)((e,t)=>i.set(e,t),[i]),V=(0,y.useRef)(0),H=(0,y.useCallback)(async()=>{let e=i.saveBundle(),t={};for(let[n,r]of Object.entries(e))M(n)&&(t[n]=r);if(Object.keys(t).length===0)return;let n=++V.current,a=v(t),s=await r.put(`/api/settings`,a);if(n!==V.current)return;let c=s&&typeof s==`object`&&`data`in s?s.data:s;for(let e of E)i.remove(e);o.setData(c);let l=c.heartbeat||{};C(!!l.enabled),D(typeof l.every==`string`?l.every:`30m`),j(l.activeHours?.start??`08:00`),P(l.activeHours?.end??`22:00`),I(typeof l.target==`string`?l.target:`all`),await o.refresh()},[r,i,o]);if((0,y.useEffect)(()=>{if(a)return a(H),()=>a(null)},[a,H]),o.state.kind===`loading`)return(0,b.jsx)(s,{});if(o.state.kind===`offline`)return(0,b.jsx)(l,{port:e});if(o.state.kind===`error`)return(0,b.jsx)(d,{message:o.state.message});let U=O(w)?null:"Use the form `<n>s|m|h`, e.g. `30m`",W=k(A)?null:`Use HH:MM (24h)`,G=k(N)?null:`Use HH:MM (24h)`,K=o.state.data.perCli||{},q=_(Object.keys(K)),J=[{value:`all`,label:`all (broadcast)`},...(q.length>0?q:[...T]).map(e=>({value:e,label:g(e).label||e}))];return!n(F)&&!J.some(e=>e.value===F)&&J.push({value:F,label:`${g(F).label||F} (legacy)`}),(0,b.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),H()},children:[(0,b.jsxs)(u,{title:`Heartbeat`,hint:`Background prompts the agent runs on a schedule.`,children:[(0,b.jsx)(p,{id:`hb-enabled`,label:`Heartbeat enabled`,value:S,onChange:e=>{C(e),B(`heartbeat.enabled`,{value:e,original:!!z.enabled,valid:!0})}}),(0,b.jsx)(h,{id:`hb-every`,label:`Default interval`,value:w,placeholder:`30m`,error:U,onChange:e=>{D(e),B(`heartbeat.every`,{value:e,original:z.every??`30m`,valid:O(e)})}}),(0,b.jsx)(h,{id:`hb-start`,label:`Active hours start`,value:A,placeholder:`08:00`,error:W,onChange:e=>{j(e),B(`heartbeat.activeHours.start`,{value:e,original:z.activeHours?.start??`08:00`,valid:k(e)})}}),(0,b.jsx)(h,{id:`hb-end`,label:`Active hours end`,value:N,placeholder:`22:00`,error:G,onChange:e=>{P(e),B(`heartbeat.activeHours.end`,{value:e,original:z.activeHours?.end??`22:00`,valid:k(e)})}}),(0,b.jsx)(m,{id:`hb-target`,label:`Target`,value:F,missingValueLabel:n(F)?t(F):void 0,error:n(F)?`The saved target runtime is retired. Choose an available target.`:null,options:J,onChange:e=>{I(e),B(`heartbeat.target`,{value:e,original:z.target??`all`,valid:!0})}})]}),(0,b.jsx)(u,{title:`Jobs`,hint:`Each job replaces the entire heartbeat.json on save. Concurrent edits from multiple browsers will overwrite — last write wins.`,children:(0,b.jsx)(L,{port:e,client:r,dirty:i,snapshot:c.state})}),(0,b.jsx)(u,{title:`Default heartbeat prompt template`,hint:`Markdown shown to the agent when a heartbeat fires without a job-specific prompt.`,children:(0,b.jsx)(R,{port:e,client:r,dirty:i,snapshot:x.state})})]})}export{D as PAGE_LOCAL_KEYS,E as SECTION_A_KEYS,T as TARGET_FALLBACK,z as default,M as isHeartbeatSettingsKey,F as jobScheduleBodyError,I as jobsHaveErrors,j as makeDefaultJob,P as normalizeJobsResponse,k as validateHHMM,O as validateInterval};
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{r as t,t as n}from"./cli-engine-NdU0lzs_.js";import{n as r,t as i}from"./jsx-runtime-CkEUZM6i.js";import{i as a,l as o,n as s,o as c,r as l,s as u,t as d,u as f}from"./page-shell-Cz2ylri8.js";import{a as p,i as m,s as h}from"./fields-CicOWY-X.js";import{f as g,o as _}from"./agent-meta-v4jNRAbX.js";import{t as v}from"./path-utils-B6vBr0DD.js";var y=e(r(),1),b=i(),x=[{value:`every`,label:`every (interval)`},{value:`cron`,label:`cron expression`}];function S({job:e,index:t,bodyError:n,timeZoneError:r,onChange:i,onRemove:a}){let s=(0,y.useId)(),c=e.schedule.kind,l=e.schedule.timeZone??``,u=e.name||`Job ${t+1}`;return(0,b.jsxs)(`div`,{className:`settings-card-group`,role:`group`,"aria-label":`Heartbeat job ${t+1}${e.name?` (${e.name})`:``}`,children:[(0,b.jsxs)(`div`,{className:`settings-card-actions`,children:[(0,b.jsxs)(`div`,{className:`settings-card-actions-status`,children:[(0,b.jsx)(`strong`,{children:u}),` `,e.enabled?(0,b.jsx)(o,{tone:`ok`,children:`Enabled`}):(0,b.jsx)(o,{tone:`neutral`,children:`Disabled`}),` `,(0,b.jsx)(o,{tone:`neutral`,children:c===`every`?`interval`:`cron`})]}),(0,b.jsx)(`div`,{className:`settings-card-actions-buttons`,children:(0,b.jsx)(`button`,{type:`button`,className:`settings-action settings-action-danger`,onClick:a,"aria-label":`Remove heartbeat job ${u}`,children:`Remove job`})})]}),(0,b.jsx)(p,{id:`${s}-enabled`,label:`Enabled`,value:e.enabled,onChange:e=>i({enabled:e})}),(0,b.jsx)(h,{id:`${s}-name`,label:`Name`,value:e.name,placeholder:`Morning summary`,onChange:e=>i({name:e})}),(0,b.jsx)(m,{id:`${s}-kind`,label:`Schedule kind`,value:c,options:x,onChange:e=>{e===`every`&&c!==`every`?i({schedule:{kind:`every`,minutes:30,...l?{timeZone:l}:{}}}):e===`cron`&&c!==`cron`&&i({schedule:{kind:`cron`,cron:`0 9 * * *`,...l?{timeZone:l}:{}}})}}),c===`every`?(0,b.jsx)(h,{id:`${s}-minutes`,label:`Every (minutes)`,value:String(e.schedule.minutes??``),placeholder:`30`,error:n??null,onChange:e=>{let t=e.trim(),n=Number(t);i({schedule:{kind:`every`,minutes:Number.isFinite(n)?n:NaN,...l?{timeZone:l}:{}}})}}):(0,b.jsx)(h,{id:`${s}-cron`,label:`Cron expression`,value:e.schedule.cron??``,placeholder:`0 9 * * *`,error:n??null,onChange:e=>i({schedule:{kind:`cron`,cron:e,...l?{timeZone:l}:{}}})}),(0,b.jsx)(h,{id:`${s}-tz`,label:`Time zone (optional)`,value:l,placeholder:`Asia/Seoul`,error:r??null,onChange:t=>{let n=t.trim();i(c===`every`?{schedule:{kind:`every`,minutes:e.schedule.minutes,...n?{timeZone:n}:{}}}:{schedule:{kind:`cron`,cron:e.schedule.cron,...n?{timeZone:n}:{}}})}}),(0,b.jsxs)(`label`,{className:`settings-field settings-field-textarea`,htmlFor:`${s}-prompt`,children:[(0,b.jsx)(`span`,{className:`settings-field-label`,children:`Prompt`}),(0,b.jsx)(`textarea`,{id:`${s}-prompt`,rows:3,value:e.prompt,placeholder:`What should this heartbeat do?`,onChange:e=>i({prompt:e.target.value})})]})]})}var C=/^\d+[smh]$/,w=/^([01]\d|2[0-3]):[0-5]\d$/,T=[`claude`,`codex`,`codex-app`,`copilot`,`cursor`,`kiro-code`,`gemini`,`grok`,`opencode`],E=[`heartbeat.enabled`,`heartbeat.every`,`heartbeat.activeHours.start`,`heartbeat.activeHours.end`,`heartbeat.target`],D=[`heartbeat.jobs`,`heartbeat.md`];function O(e){return C.test(e.trim())}function k(e){return w.test(e.trim())}var A=0;function j(e=Date.now()){return{id:`hb_${e}_${A++}`,name:``,enabled:!0,schedule:{kind:`every`,minutes:30},prompt:``}}function M(e){return e.startsWith(`heartbeat.`)&&e!==`heartbeat.jobs`&&e!==`heartbeat.md`}function N(e,t){if(!e||typeof e!=`object`)return null;let n=e,r=typeof n.id==`string`&&n.id.trim()?n.id.trim():`hb_unknown_${t}`,i=typeof n.name==`string`?n.name:``,a=n.enabled!==!1,o=typeof n.prompt==`string`?n.prompt:``,s=n.schedule,c;if(s&&typeof s==`object`){let e=s;c=e.kind===`cron`&&typeof e.cron==`string`?{kind:`cron`,cron:e.cron,...typeof e.timeZone==`string`&&e.timeZone?{timeZone:e.timeZone}:{}}:{kind:`every`,minutes:typeof e.minutes==`number`?e.minutes:30,...typeof e.timeZone==`string`&&e.timeZone?{timeZone:e.timeZone}:{}}}else c={kind:`every`,minutes:30};return{id:r,name:i,enabled:a,schedule:c,prompt:o}}function P(e){if(!e||typeof e!=`object`)return[];let t=e.jobs;return Array.isArray(t)?t.map((e,t)=>N(e,t)).filter(e=>e!==null):[]}function F(e){if(e.kind===`every`){let t=e.minutes;return!Number.isFinite(t)||t<=0||!Number.isInteger(t)?`Minutes must be a positive integer`:null}let t=e.cron?.trim()??``;return t?t.split(/\s+/).length<5?`Cron must have at least 5 fields`:null:`Cron expression required`}function I(e){return e.some(e=>F(e.schedule)!==null)}function L({port:e,client:t,dirty:n,snapshot:r}){let[i,o]=(0,y.useState)([]),[s,u]=(0,y.useState)([]),[f,p]=(0,y.useState)(!1),[m,h]=(0,y.useState)(null);(0,y.useEffect)(()=>{if(r.kind!==`ready`)return;let e=P(r.data);o(e),u(e)},[r]),(0,y.useEffect)(()=>{n.set(`heartbeat.jobs`,{value:i,original:s,valid:!I(i)})},[i,s,n]),(0,y.useEffect)(()=>()=>{n.remove(`heartbeat.jobs`)},[n]);let g=(0,y.useCallback)(async()=>{if(I(i)){h(`Fix invalid schedules before saving.`);return}p(!0),h(null);try{let e=P(await t.put(`/api/heartbeat`,{jobs:i}));o(e),u(e),n.remove(`heartbeat.jobs`)}catch(e){h(e instanceof Error?e.message:String(e))}finally{p(!1)}},[t,n,i]);if(r.kind===`loading`)return(0,b.jsx)(c,{children:`Loading jobs…`});if(r.kind===`offline`)return(0,b.jsx)(l,{port:e});if(r.kind===`error`)return(0,b.jsx)(d,{message:r.message});let _=n.pending.has(`heartbeat.jobs`),v=I(i);function x(e,t){o(n=>n.map((n,r)=>r===e?{...n,...t}:n))}function C(){o(e=>[...e,j()])}function w(e){o(t=>t.filter((t,n)=>n!==e))}return(0,b.jsxs)(b.Fragment,{children:[i.length===0?(0,b.jsx)(c,{children:`No jobs configured. Add one below.`}):(0,b.jsx)(b.Fragment,{children:i.map((e,t)=>(0,b.jsx)(S,{job:e,index:t,bodyError:F(e.schedule),onChange:e=>x(t,e),onRemove:()=>w(t)},e.id))}),(0,b.jsxs)(a,{children:[(0,b.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:C,children:`+ Add job`}),(0,b.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,onClick:()=>void g(),disabled:f||!_||v,children:f?`Saving…`:`Apply jobs`})]}),m?(0,b.jsx)(c,{tone:`error`,role:`alert`,children:m}):null]})}function R({port:e,client:t,dirty:n,snapshot:r}){let[i,o]=(0,y.useState)(``),[s,u]=(0,y.useState)(``),[f,p]=(0,y.useState)(!1),[m,h]=(0,y.useState)(null);(0,y.useEffect)(()=>{if(r.kind!==`ready`)return;let e=r.data.content??``;o(e),u(e)},[r]),(0,y.useEffect)(()=>{n.set(`heartbeat.md`,{value:i,original:s,valid:!0})},[i,s,n]),(0,y.useEffect)(()=>()=>{n.remove(`heartbeat.md`)},[n]);let g=(0,y.useCallback)(async()=>{p(!0),h(null);try{await t.put(`/api/heartbeat-md`,{content:i}),u(i),n.remove(`heartbeat.md`)}catch(e){h(e instanceof Error?e.message:String(e))}finally{p(!1)}},[t,n,i]);if(r.kind===`loading`)return(0,b.jsx)(c,{children:`Loading template…`});if(r.kind===`offline`)return(0,b.jsx)(l,{port:e});if(r.kind===`error`)return(0,b.jsx)(d,{message:r.message});let _=n.pending.has(`heartbeat.md`);return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(`label`,{className:`settings-field settings-field-textarea`,htmlFor:`hb-md`,children:[(0,b.jsx)(`span`,{className:`settings-field-label`,children:`Template`}),(0,b.jsx)(`textarea`,{id:`hb-md`,rows:10,spellCheck:!1,value:i,onChange:e=>o(e.target.value),style:{fontFamily:`var(--font-mono, ui-monospace, monospace)`}})]}),(0,b.jsx)(a,{children:(0,b.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,onClick:()=>void g(),disabled:f||!_,children:f?`Saving…`:`Save template`})}),m?(0,b.jsx)(c,{tone:`error`,role:`alert`,children:m}):null]})}function z({port:e,client:r,dirty:i,registerSave:a}){let o=f(r,`/api/settings`),c=f(r,`/api/heartbeat`),x=f(r,`/api/heartbeat-md`),[S,C]=(0,y.useState)(!1),[w,D]=(0,y.useState)(`30m`),[A,j]=(0,y.useState)(`08:00`),[N,P]=(0,y.useState)(`22:00`),[F,I]=(0,y.useState)(`all`);(0,y.useEffect)(()=>{if(o.state.kind!==`ready`)return;let e=o.state.data.heartbeat||{};C(!!e.enabled),D(typeof e.every==`string`?e.every:`30m`),j(e.activeHours?.start??`08:00`),P(e.activeHours?.end??`22:00`),I(typeof e.target==`string`?e.target:`all`)},[o.state]),(0,y.useEffect)(()=>()=>{for(let e of E)i.remove(e)},[i]);let z=(0,y.useMemo)(()=>o.state.kind===`ready`&&o.state.data.heartbeat||{},[o.state]),B=(0,y.useCallback)((e,t)=>i.set(e,t),[i]),V=(0,y.useRef)(0),H=(0,y.useCallback)(async()=>{let e=i.saveBundle(),t={};for(let[n,r]of Object.entries(e))M(n)&&(t[n]=r);if(Object.keys(t).length===0)return;let n=++V.current,a=v(t),s=await r.put(`/api/settings`,a);if(n!==V.current)return;let c=s&&typeof s==`object`&&`data`in s?s.data:s;for(let e of E)i.remove(e);o.setData(c);let l=c.heartbeat||{};C(!!l.enabled),D(typeof l.every==`string`?l.every:`30m`),j(l.activeHours?.start??`08:00`),P(l.activeHours?.end??`22:00`),I(typeof l.target==`string`?l.target:`all`),await o.refresh()},[r,i,o]);if((0,y.useEffect)(()=>{if(a)return a(H),()=>a(null)},[a,H]),o.state.kind===`loading`)return(0,b.jsx)(s,{});if(o.state.kind===`offline`)return(0,b.jsx)(l,{port:e});if(o.state.kind===`error`)return(0,b.jsx)(d,{message:o.state.message});let U=O(w)?null:"Use the form `<n>s|m|h`, e.g. `30m`",W=k(A)?null:`Use HH:MM (24h)`,G=k(N)?null:`Use HH:MM (24h)`,K=o.state.data.perCli||{},q=g(Object.keys(K)),J=[{value:`all`,label:`all (broadcast)`},...(q.length>0?q:[...T]).map(e=>({value:e,label:_(e).label||e}))];return!n(F)&&!J.some(e=>e.value===F)&&J.push({value:F,label:`${_(F).label||F} (legacy)`}),(0,b.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),H()},children:[(0,b.jsxs)(u,{title:`Heartbeat`,hint:`Background prompts the agent runs on a schedule.`,children:[o.state.data.cli===`aside`?(0,b.jsx)(`div`,{className:`settings-inline-notice`,role:`status`,children:(0,b.jsx)(`p`,{children:`Scheduled heartbeat runs are unsupported with Aside as the main runtime and will be rejected. Choose another main runtime in Agent settings to use heartbeat.`})}):null,(0,b.jsx)(p,{id:`hb-enabled`,label:`Heartbeat enabled`,value:S,onChange:e=>{C(e),B(`heartbeat.enabled`,{value:e,original:!!z.enabled,valid:!0})}}),(0,b.jsx)(h,{id:`hb-every`,label:`Default interval`,value:w,placeholder:`30m`,error:U,onChange:e=>{D(e),B(`heartbeat.every`,{value:e,original:z.every??`30m`,valid:O(e)})}}),(0,b.jsx)(h,{id:`hb-start`,label:`Active hours start`,value:A,placeholder:`08:00`,error:W,onChange:e=>{j(e),B(`heartbeat.activeHours.start`,{value:e,original:z.activeHours?.start??`08:00`,valid:k(e)})}}),(0,b.jsx)(h,{id:`hb-end`,label:`Active hours end`,value:N,placeholder:`22:00`,error:G,onChange:e=>{P(e),B(`heartbeat.activeHours.end`,{value:e,original:z.activeHours?.end??`22:00`,valid:k(e)})}}),(0,b.jsx)(m,{id:`hb-target`,label:`Target`,value:F,missingValueLabel:n(F)?t(F):void 0,error:n(F)?`The saved target runtime is retired. Choose an available target.`:null,options:J,onChange:e=>{I(e),B(`heartbeat.target`,{value:e,original:z.target??`all`,valid:!0})}})]}),(0,b.jsx)(u,{title:`Jobs`,hint:`Each job replaces the entire heartbeat.json on save. Concurrent edits from multiple browsers will overwrite — last write wins.`,children:(0,b.jsx)(L,{port:e,client:r,dirty:i,snapshot:c.state})}),(0,b.jsx)(u,{title:`Default heartbeat prompt template`,hint:`Markdown shown to the agent when a heartbeat fires without a job-specific prompt.`,children:(0,b.jsx)(R,{port:e,client:r,dirty:i,snapshot:x.state})})]})}export{D as PAGE_LOCAL_KEYS,E as SECTION_A_KEYS,T as TARGET_FALLBACK,z as default,M as isHeartbeatSettingsKey,F as jobScheduleBodyError,I as jobsHaveErrors,j as makeDefaultJob,P as normalizeJobsResponse,k as validateHHMM,O as validateInterval};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{c as r,i,l as a,n as o,o as s,r as c,s as l,t as ee,u}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{c as r,i,l as a,n as o,o as s,r as c,s as l,t as ee,u}from"./page-shell-Cz2ylri8.js";import{t as d}from"./fields-CicOWY-X.js";var f=e(t(),1),p=/^[a-zA-Z0-9._-]+$/;function m(e){return typeof e!=`string`||e.length===0||e.length>64?!1:p.test(e)}function h(e){if(!e||typeof e!=`object`)return{servers:{}};let t=e,n=t.servers,r={};if(n&&typeof n==`object`&&!Array.isArray(n))for(let[e,t]of Object.entries(n))r[e]=g(t);return{...t,servers:r}}function g(e){if(!e||typeof e!=`object`)return{};let t=e,n=typeof t.command==`string`&&t.command?t.command:void 0,r=typeof t.url==`string`&&t.url?t.url:void 0,i=Array.isArray(t.args)?t.args.filter(e=>typeof e==`string`):void 0,a=t.env&&typeof t.env==`object`&&!Array.isArray(t.env)?Object.fromEntries(Object.entries(t.env).filter(e=>typeof e[1]==`string`)):void 0,o=t.headers&&typeof t.headers==`object`&&!Array.isArray(t.headers)?Object.fromEntries(Object.entries(t.headers).filter(e=>typeof e[1]==`string`)):void 0,s=typeof t.autostart==`boolean`?t.autostart:void 0,c={};n&&(c.command=n),r&&(c.url=r),i&&i.length>0&&(c.args=i),a&&Object.keys(a).length>0&&(c.env=a),o&&Object.keys(o).length>0&&(c.headers=o),s!==void 0&&(c.autostart=s);for(let[e,n]of Object.entries(t))[`command`,`url`,`args`,`env`,`headers`,`autostart`].includes(e)||(c[e]=n);return c}function _(e=`local`){return e===`remote`?{url:``}:{command:``}}function v(e){return!e||e.length===0?``:e.join(`
|
|
2
2
|
`)}function y(e){if(!e)return[];let t=e.split(/\r?\n|,/),n=[];for(let e of t){let t=e.trim();t.length>0&&n.push(t)}return n}var b=/^[A-Za-z_][A-Za-z0-9_]*$/;function x(e){let t={};if(!e)return t;for(let n of e.split(/\r?\n/)){let e=n.trim();if(e===``||e.startsWith(`#`))continue;let r=e.indexOf(`=`);if(r===-1)continue;let i=e.slice(0,r).trim(),a=e.slice(r+1);b.test(i)&&(t[i]=a)}return t}function S(e){return e?Object.entries(e).map(([e,t])=>`${e}=${t}`).join(`
|
|
3
3
|
`):``}function C(e,t){if(!m(e))return{kind:`invalid`,reason:`Server name must match [a-zA-Z0-9._-] (1–64 chars).`};let n=t.command&&t.command.trim()!==``,r=t.url&&String(t.url).trim()!==``;return!n&&!r?{kind:`invalid`,reason:`Command or URL is required.`}:{kind:`ok`}}function te(e){if(e.url)return`remote`;if(!e.command)return null;let t=e.command;return t===`npx`||t.endsWith(`/npx`)?`npx`:t===`uvx`||t===`uv`||t.endsWith(`/uvx`)?`uvx`:t===`docker`||t.endsWith(`/docker`)?`docker`:null}function ne(e){return Object.values(e).filter(e=>e.command?e.command===`npx`||e.command===`uv`||e.command===`uvx`:!1).length}function w(e){let t=new Set,n=new Set;for(let r of e){let e=r.toLowerCase();t.has(e)?n.add(e):t.add(e)}return n}function T(e){let t={};for(let[n,r]of Object.entries(e.servers)){let e={};r.command&&(e.command=r.command),r.url&&(e.url=r.url),r.args&&r.args.length>0&&(e.args=[...r.args]),r.env&&Object.keys(r.env).length>0&&(e.env={...r.env}),r.headers&&Object.keys(r.headers).length>0&&(e.headers={...r.headers}),r.autostart!==void 0&&(e.autostart=r.autostart);for(let[t,n]of Object.entries(r))[`command`,`url`,`args`,`env`,`headers`,`autostart`].includes(t)||(e[t]=n);t[n]=e}return{...e,servers:t}}function re(e){let t=1;for(;e.includes(`server-${t}`);)t+=1;return`server-${t}`}var E=n();function ie({name:e,server:t,onRename:n,onChange:r,onRemove:i,nameError:o}){let s=`mcp-${e||`unnamed`}`,c=v(t.args),l=S(t.env),ee=S(t.headers),u=te(t),d=u===`remote`;return(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`div`,{className:`settings-card-actions`,role:`group`,"aria-label":`MCP server ${e||`(unnamed)`}`,children:[(0,E.jsxs)(`div`,{className:`settings-card-actions-status`,children:[(0,E.jsx)(`strong`,{children:e||`(unnamed)`}),u?(0,E.jsx)(a,{tone:`neutral`,children:u}):null]}),(0,E.jsx)(`div`,{className:`settings-card-actions-buttons`,children:(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-danger`,onClick:i,"aria-label":`Remove ${e||`server`}`,children:`Remove`})})]}),(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${s}-name`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Server name`}),(0,E.jsx)(`input`,{id:`${s}-name`,type:`text`,value:e,spellCheck:!1,placeholder:`my-server`,"aria-invalid":!!o,onChange:e=>n(e.target.value)}),o?(0,E.jsx)(`span`,{className:`settings-field-error`,role:`alert`,children:o}):null]}),d?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${s}-url`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`URL`}),(0,E.jsx)(`input`,{id:`${s}-url`,type:`text`,value:t.url||``,placeholder:`https://mcp.example.com/sse`,spellCheck:!1,onChange:e=>r({...t,url:e.target.value})})]}),(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${s}-headers`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Headers (KEY=value per line)`}),(0,E.jsx)(`textarea`,{id:`${s}-headers`,value:ee,rows:3,spellCheck:!1,onChange:e=>r({...t,headers:x(e.target.value)})})]})]}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${s}-command`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Command`}),(0,E.jsx)(`input`,{id:`${s}-command`,type:`text`,value:t.command||``,placeholder:`npx`,spellCheck:!1,onChange:e=>r({...t,command:e.target.value})})]}),(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${s}-args`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Args (one per line, or comma-separated)`}),(0,E.jsx)(`textarea`,{id:`${s}-args`,value:c,rows:3,spellCheck:!1,onChange:e=>r({...t,args:y(e.target.value)})})]}),(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`${s}-env`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Env (KEY=value per line)`}),(0,E.jsx)(`textarea`,{id:`${s}-env`,value:l,rows:3,spellCheck:!1,onChange:e=>r({...t,env:x(e.target.value)})})]})]}),(0,E.jsxs)(`label`,{className:`settings-field settings-field-toggle`,htmlFor:`${s}-autostart`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Autostart`}),(0,E.jsx)(`input`,{id:`${s}-autostart`,type:`checkbox`,checked:!!t.autostart,onChange:e=>r({...t,autostart:e.target.checked})})]})]})}var D=`mcp.config`;function O({port:e,client:t,dirty:n,registerSave:p}){let{state:m,refresh:g,setData:v}=u(t,`/api/mcp`),[y,b]=(0,f.useState)({servers:{}}),[x,S]=(0,f.useState)([]),[O,oe]=(0,f.useState)(!1),[k,se]=(0,f.useState)(!0),[A,j]=(0,f.useState)({kind:`idle`}),M=(0,f.useRef)(0),[ce,le]=(0,f.useState)(!1),[N,P]=(0,f.useState)(`active`),[F,ue]=(0,f.useState)(`local`),[I,de]=(0,f.useState)(``),[L,fe]=(0,f.useState)(``),[R,pe]=(0,f.useState)(``),[z,B]=(0,f.useState)(``),[V,me]=(0,f.useState)(``),[H,he]=(0,f.useState)(``),[ge,U]=(0,f.useState)(null),[_e,W]=(0,f.useState)(!1),G=(0,f.useMemo)(()=>m.kind===`ready`?h(m.data):{servers:{}},[m]);(0,f.useEffect)(()=>{if(m.kind===`ready`){let e=h(m.data);b(e),S(Object.keys(e.servers))}},[m]),(0,f.useEffect)(()=>()=>{n.remove(D)},[n]);let K=(0,f.useMemo)(()=>Object.keys(y.servers),[y]),q=(0,f.useMemo)(()=>w(K),[K]),ve=(0,f.useMemo)(()=>K.map(e=>({name:e,result:C(e,y.servers[e]??_())})),[y,K]).some(e=>e.result.kind===`invalid`),J=q.size>0,ye=!ve&&!J&&k,be=(0,f.useMemo)(()=>ne(y.servers),[y]),Y=(0,f.useCallback)((e,t)=>{n.set(D,{value:T(e),original:T(G),valid:t})},[n,G]),X=(0,f.useCallback)((e,t)=>{b(e),t&&S(t);let n=t??Object.keys(e.servers),r=w(n),i=n.every(t=>C(t,e.servers[t]??_()).kind===`ok`);Y(e,i&&r.size===0&&k)},[k,Y]),xe=(0,f.useCallback)((e,t)=>{if(e===t)return;let n=x.map(n=>n===e?t:n),r={};for(let i of n)r[i]=i===t?y.servers[e]??_():y.servers[i]??_();X({...y,servers:r},n)},[y,x,X]),Se=(0,f.useCallback)((e,t)=>{X({...y,servers:{...y.servers,[e]:t}},x)},[y,x,X]),Ce=(0,f.useCallback)(e=>{let t={...y.servers};delete t[e];let n=x.filter(t=>t!==e);X({...y,servers:t},n)},[y,x,X]);(0,f.useCallback)(()=>{let e=re(x);X({...y,servers:{...y.servers,[e]:_()}},[...x,e])},[y,x,X]);let we=(0,f.useCallback)((e,t)=>{if(se(t),!t){Y(y,!1);return}if(e&&typeof e==`object`&&!Array.isArray(e)){let t=h(e);b(t),S(Object.keys(t.servers));let n=w(Object.keys(t.servers)),r=Object.entries(t.servers).every(([e,t])=>C(e,t).kind===`ok`);Y(t,r&&n.size===0)}},[y,Y]),Te=(0,f.useCallback)(async()=>{let e=n.saveBundle();if(!(D in e))return;let r=e[D],i=await t.put(`/api/mcp`,r);n.clear();let a=await t.get(`/api/mcp`).catch(()=>i),o=h(a);b(o),S(Object.keys(o.servers)),v(a),await g()},[t,n,g,v]);(0,f.useEffect)(()=>{if(p)return p(Te),()=>p(null)},[p,Te]);let Z=(0,f.useCallback)(async(e,r)=>{if(n.isDirty()&&typeof window<`u`&&!window.confirm(`You have unsaved MCP edits. ${e} will use the on-disk config, not your unsaved changes. Continue?`))return;let i=M.current+1;M.current=i,j({kind:`pending`,label:e});try{let n=await t.post(r,{});if(M.current!==i)return;j({kind:`success`,message:`${e} succeeded${n?.servers?`: ${JSON.stringify(n.servers)}`:``}`})}catch(e){if(M.current!==i)return;j({kind:`error`,message:e instanceof Error?e.message:String(e)})}},[t,n]),Q=(0,f.useCallback)(()=>{de(``),fe(``),pe(``),B(``),me(``),he(``),U(null),W(!1)},[]),Ee=(0,f.useCallback)(()=>{P(`active`),Q(),le(!0)},[Q]),$=(0,f.useCallback)(()=>{le(!1),Q()},[Q]),De=(0,f.useCallback)(async()=>{let e=I.trim()||re(Object.keys(G.servers)),r=F===`remote`?{url:V.trim(),...H.trim()?{headers:ae(H)}:{}}:{command:L.trim(),...R.trim()?{args:R.split(/\r?\n|,/).map(e=>e.trim()).filter(Boolean)}:{},...z.trim()?{env:ae(z)}:{}},i=C(e,r);if(i.kind===`invalid`){U(i.reason);return}if(G.servers[e]){U(`Server "${e}" already exists.`);return}W(!0),U(null);try{let i={...G,servers:{...G.servers,[e]:r}};await t.put(`/api/mcp`,T(i)),await t.post(`/api/mcp/sync`,{}),n.clear();let a=await t.get(`/api/mcp`).catch(()=>i),o=h(a);b(o),S(Object.keys(o.servers)),v(a),await g(),$()}catch(e){U(e instanceof Error?e.message:String(e)),W(!1)}},[I,F,V,H,L,R,z,G,t,n,g,v,$]),Oe=(0,f.useCallback)(async e=>{let r={...G.servers};delete r[e];let i={...G,servers:r};try{await t.put(`/api/mcp`,T(i)),await t.post(`/api/mcp/sync`,{}),n.clear();let e=await t.get(`/api/mcp`).catch(()=>i),r=h(e);b(r),S(Object.keys(r.servers)),v(e),await g()}catch(e){j({kind:`error`,message:e instanceof Error?e.message:String(e)})}},[G,t,n,g,v]);if(m.kind===`loading`)return(0,E.jsx)(o,{});if(m.kind===`offline`)return(0,E.jsx)(c,{port:e});if(m.kind===`error`)return(0,E.jsx)(ee,{message:m.message});let ke=Array.from(q).sort();return(0,E.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>e.preventDefault(),children:[(0,E.jsxs)(l,{title:`MCP servers`,hint:`Edit each server's command/args/env. Save writes back to mcp.json; Sync pushes the saved config to all CLIs.`,children:[x.length===0&&(0,E.jsxs)(s,{children:[`No servers configured. Add one or run `,(0,E.jsx)(`code`,{children:`Reset to defaults`}),`.`]}),x.map(e=>{let t=y.servers[e]??_(),n=e.toLowerCase(),r=q.has(n),i=C(e,t),a=r?`Duplicate server name (case-insensitive).`:i.kind===`invalid`?i.reason:null;return(0,E.jsx)(ie,{name:e,server:t,onRename:t=>xe(e,t),onChange:t=>Se(e,t),onRemove:()=>Ce(e),nameError:a},e)}),J&&(0,E.jsxs)(s,{tone:`error`,role:`alert`,children:[`Duplicate server name`,ke.length===1?``:`s`,`: `,ke.join(`, `),`. Saving is blocked until names are unique.`]}),ve&&!J&&(0,E.jsx)(s,{tone:`error`,role:`alert`,children:`Some servers have errors (missing command/URL or invalid name). Saving is blocked until they are fixed.`})]}),(0,E.jsxs)(l,{title:`Actions`,hint:`These act on the saved config. Save edits first if you want them included.`,children:[(0,E.jsxs)(i,{status:A.kind===`pending`?(0,E.jsxs)(`span`,{role:`status`,children:[A.label,`…`]}):A.kind===`success`?(0,E.jsx)(`span`,{role:`status`,children:A.message}):void 0,children:[(0,E.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:Ee,children:`+ Add, Set MCP`}),(0,E.jsx)(`button`,{type:`button`,className:`settings-action`,disabled:A.kind===`pending`,onClick:()=>void Z(`Sync to all CLIs`,`/api/mcp/sync`),children:`Sync to all CLIs`}),(0,E.jsxs)(`button`,{type:`button`,className:`settings-action`,disabled:A.kind===`pending`||be===0,onClick:()=>void Z(`Install bundle`,`/api/mcp/install`),children:[`Install bundle (`,be,`)`]}),(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-danger`,disabled:A.kind===`pending`,onClick:()=>{typeof window<`u`&&!window.confirm(`Reset MCP config to defaults? Your custom servers will be removed.`)||Z(`Reset to defaults`,`/api/mcp/reset`)},children:`Reset to defaults`})]}),A.kind===`error`&&(0,E.jsx)(s,{tone:`error`,role:`alert`,children:A.message})]}),(0,E.jsxs)(l,{title:`Advanced (raw JSON)`,hint:`Edit the entire config object. Useful for fields not surfaced in the structured editor.`,children:[(0,E.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:()=>oe(e=>!e),"aria-expanded":O,children:O?`Hide raw JSON`:`Show raw JSON`}),O&&(0,E.jsx)(d,{id:`mcp-raw`,label:`mcp.json`,value:T(y),rows:16,onChange:we}),!ye&&(0,E.jsx)(s,{children:`Save is disabled while validation errors are present.`})]}),ce&&(0,E.jsx)(`div`,{className:`settings-memory-modal settings-pi-modal`,role:`dialog`,"aria-modal":`true`,"aria-label":`MCP Server Management`,onClick:$,children:(0,E.jsxs)(`div`,{className:`settings-memory-modal-card`,onClick:e=>e.stopPropagation(),children:[(0,E.jsxs)(`header`,{className:`settings-memory-modal-header`,children:[(0,E.jsx)(`h3`,{children:`MCP servers`}),(0,E.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:$,children:`Close`})]}),(0,E.jsxs)(r,{children:[(0,E.jsx)(`button`,{type:`button`,"aria-pressed":N===`active`,className:`settings-action`,onClick:()=>P(`active`),children:`Active Servers`}),(0,E.jsx)(`button`,{type:`button`,"aria-pressed":N===`add`,className:`settings-action`,onClick:()=>{P(`add`),Q()},children:`Add New`})]}),N===`active`&&(0,E.jsxs)(E.Fragment,{children:[Object.keys(G.servers).length===0&&(0,E.jsx)(s,{children:`No active MCP servers.`}),Object.entries(G.servers).map(([e,t])=>{let n=te(t);return(0,E.jsx)(i,{status:(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`strong`,{children:e}),` `,(0,E.jsx)(`code`,{children:t.url||[t.command,...t.args||[]].filter(Boolean).join(` `)}),` `,n?(0,E.jsx)(a,{tone:`neutral`,children:n}):null]}),children:(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-danger`,onClick:()=>void Oe(e),children:`Remove`})},e)})]}),N===`add`&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(r,{children:[(0,E.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":F===`local`,className:`settings-action${F===`local`?` settings-action-save`:``}`,onClick:()=>ue(`local`),children:`Local`}),(0,E.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":F===`remote`,className:`settings-action${F===`remote`?` settings-action-save`:``}`,onClick:()=>ue(`remote`),children:`Remote`})]}),(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Name`}),(0,E.jsx)(`input`,{type:`text`,value:I,placeholder:`my-server`,spellCheck:!1,onChange:e=>de(e.target.value)})]}),F===`local`?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Command`}),(0,E.jsx)(`input`,{type:`text`,value:L,placeholder:`npx`,spellCheck:!1,onChange:e=>fe(e.target.value)})]}),(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Args (one per line)`}),(0,E.jsx)(`textarea`,{value:R,rows:3,spellCheck:!1,placeholder:`-y
|
|
4
4
|
@upstash/context7-mcp`,onChange:e=>pe(e.target.value)})]}),(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Env (KEY=value per line)`}),(0,E.jsx)(`textarea`,{value:z,rows:2,spellCheck:!1,onChange:e=>B(e.target.value)})]})]}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`URL`}),(0,E.jsx)(`input`,{type:`text`,value:V,placeholder:`https://mcp.example.com/sse`,spellCheck:!1,onChange:e=>me(e.target.value)})]}),(0,E.jsxs)(`label`,{className:`settings-field settings-field-text`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`Headers (KEY=value per line)`}),(0,E.jsx)(`textarea`,{value:H,rows:2,spellCheck:!1,onChange:e=>he(e.target.value)})]})]}),ge&&(0,E.jsx)(s,{tone:`error`,role:`alert`,children:ge}),(0,E.jsxs)(i,{children:[(0,E.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:$,children:`Cancel`}),(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,disabled:_e,onClick:()=>void De(),children:_e?`Adding…`:`Add & Sync`})]})]})]})})]})}function ae(e){let t={};for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith(`#`))continue;let r=e.indexOf(`=`);r!==-1&&(t[e.slice(0,r).trim()]=e.slice(r+1))}return t}export{O as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{r as t,t as n}from"./cli-engine-NdU0lzs_.js";import{n as r,t as i}from"./jsx-runtime-CkEUZM6i.js";import{i as a,l as o,n as s,o as c,r as l,s as u,t as d,u as f}from"./page-shell-Cz2ylri8.js";import{a as p,i as m,r as h}from"./fields-CicOWY-X.js";import{o as g,r as ee}from"./agent-meta-v4jNRAbX.js";import{t as _}from"./path-utils-B6vBr0DD.js";var v=e(r(),1),y=[`memory.enabled`,`memory.flushEvery`,`memory.cli`,`memory.retentionDays`,`memory.autoReflectAfterFlush`,`memory.flushLanguage`],b=[{value:`en`,label:`English (en)`},{value:`ko`,label:`한국어 (ko)`},{value:`ja`,label:`日本語 (ja)`},{value:`zh`,label:`中文 (zh)`}],x=50;function S(e){return y.includes(e)}function C(e){let t=w(e);if(!Array.isArray(t))return[];let n=[];for(let e of t){let t=T(e);t&&n.push(t)}return n}function w(e){if(!e||typeof e!=`object`)return e;let t=e;return Array.isArray(t)?t:`data`in t?t.data:e}function T(e){if(!e||typeof e!=`object`)return null;let t=e,n=typeof t.key==`string`?t.key:null;return n?{key:n,value:typeof t.value==`string`?t.value:``,source:typeof t.source==`string`?t.source:`manual`}:null}function E(e,t){return!Number.isFinite(e)||!Number.isInteger(e)||e<=0?`${t} must be a positive integer`:null}function D(e,t,n=50){let r=Math.max(0,Math.floor(t))*n,i=e.slice(r,r+n),a=Math.max(1,Math.ceil(e.length/n));return{slice:i,hasMore:r+n<e.length,pageCount:a}}function O(e,t=80){return e.length<=t?e:`${e.slice(0,t)}…`}var k=i();function te({row:e,onOpen:t}){return(0,k.jsxs)(`div`,{className:`settings-card-actions`,children:[(0,k.jsxs)(`div`,{className:`settings-card-actions-status`,children:[(0,k.jsx)(`strong`,{children:(0,k.jsx)(`code`,{children:e.key})}),` `,(0,k.jsx)(o,{tone:`neutral`,children:e.source}),` `,(0,k.jsxs)(`span`,{className:`settings-field-hint`,children:[e.value.length,` chars · `,O(e.value)]})]}),(0,k.jsx)(`div`,{className:`settings-card-actions-buttons`,children:(0,k.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:()=>t(e),"aria-label":`Open memory entry ${e.key}`,children:`Open`})})]})}var ne={busy:null,notice:null,error:null};function A({port:e,client:r,dirty:i,registerSave:o}){let x=f(r,`/api/settings`),w=f(r,`/api/memory`),[T,O]=(0,v.useState)(!0),[A,j]=(0,v.useState)(10),[M,N]=(0,v.useState)(``),[P,F]=(0,v.useState)(30),[I,L]=(0,v.useState)(!1),[re,R]=(0,v.useState)(`en`),[z,B]=(0,v.useState)(0),[V,H]=(0,v.useState)(null),[U,W]=(0,v.useState)(ne);(0,v.useEffect)(()=>{if(x.state.kind!==`ready`)return;let e=x.state.data.memory||{};O(e.enabled!==!1),j(typeof e.flushEvery==`number`?e.flushEvery:10),N(typeof e.cli==`string`?e.cli:``),F(typeof e.retentionDays==`number`?e.retentionDays:30),L(!!e.autoReflectAfterFlush),R(typeof e.flushLanguage==`string`&&e.flushLanguage?e.flushLanguage:`en`)},[x.state]),(0,v.useEffect)(()=>()=>{for(let e of y)i.remove(e)},[i]),(0,v.useEffect)(()=>{if(!V)return;let e=e=>{e.key===`Escape`&&H(null)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[V]);let G=(0,v.useCallback)((e,t)=>i.set(e,t),[i]),K=(0,v.useMemo)(()=>x.state.kind===`ready`&&x.state.data.memory||{},[x.state]),q=(0,v.useCallback)(async()=>{let e=i.saveBundle(),t={};for(let[n,r]of Object.entries(e))S(n)&&(t[n]=r);if(Object.keys(t).length===0)return;if(t[`memory.cli`]===`aside`||t[`memory.cli`]===``&&x.state.kind===`ready`&&x.state.data.cli===`aside`)throw Error(`Aside cannot run memory flush.`);let n=_(t),a=await r.put(`/api/settings`,n),o=a&&typeof a==`object`&&`data`in a?a.data:a;for(let e of y)i.remove(e);x.setData(o);let s=o.memory||{};O(s.enabled!==!1),j(typeof s.flushEvery==`number`?s.flushEvery:10),N(typeof s.cli==`string`?s.cli:``),F(typeof s.retentionDays==`number`?s.retentionDays:30),L(!!s.autoReflectAfterFlush),R(typeof s.flushLanguage==`string`&&s.flushLanguage?s.flushLanguage:`en`),await x.refresh()},[r,i,x]);(0,v.useEffect)(()=>{if(o)return o(q),()=>o(null)},[o,q]);let J=(0,v.useCallback)(async()=>{W({busy:`flush`,notice:null,error:null});try{await r.post(`/api/jaw-memory/flush`,{}),W({busy:null,notice:`Memory flush queued. Browse refreshes when it completes.`,error:null}),await w.refresh()}catch(e){W({busy:null,notice:null,error:e instanceof Error?e.message:String(e)})}},[r,w]),Y=(0,v.useCallback)(async()=>{W({busy:`reflect`,notice:null,error:null});try{await r.post(`/api/jaw-memory/reflect`,{}),W({busy:null,notice:`Reflect complete.`,error:null}),await w.refresh()}catch(e){W({busy:null,notice:null,error:e instanceof Error?e.message:String(e)})}},[r,w]),ie=(0,v.useCallback)(()=>{if(w.state.kind!==`ready`)return;let t=C(w.state.data),n=new Blob([JSON.stringify(t,null,2)],{type:`application/json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=`jaw-memory-${e}-${Date.now()}.json`,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r)},[w.state,e]);if(x.state.kind===`loading`)return(0,k.jsx)(s,{});if(x.state.kind===`offline`)return(0,k.jsx)(l,{port:e});if(x.state.kind===`error`)return(0,k.jsx)(d,{message:x.state.message});let ae=E(A,`Flush every`),oe=E(P,`Retention days`),se=x.state.data.perCli||{},ce=ee(Object.keys(se)),X=!M&&x.state.data.cli===`aside`,Z=[...x.state.data.cli===`aside`?[]:[{value:``,label:`(profile default)`}],...ce.map(e=>({value:e,label:g(e).label||e}))];M&&M!==`aside`&&!n(M)&&!Z.some(e=>e.value===M)&&Z.push({value:M,label:`${g(M).label||M} (legacy)`});let Q=w.state.kind===`ready`?C(w.state.data):[],{slice:le,hasMore:$,pageCount:ue}=D(Q,Math.min(z,Math.max(0,Math.ceil(Q.length/50)-1)));return(0,k.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),q()},children:[(0,k.jsxs)(u,{title:`Memory engine`,hint:`Background memory flush and reflection cadence.`,children:[(0,k.jsx)(p,{id:`memory-enabled`,label:`Memory enabled`,value:T,onChange:e=>{O(e),G(`memory.enabled`,{value:e,original:K.enabled!==!1,valid:!0})}}),(0,k.jsx)(h,{id:`memory-flush-every`,label:`Flush every (sessions)`,value:A,min:1,error:ae,onChange:e=>{j(e),G(`memory.flushEvery`,{value:e,original:typeof K.flushEvery==`number`?K.flushEvery:10,valid:E(e,`Flush every`)===null})}}),(0,k.jsx)(m,{id:`memory-cli`,label:`Flush CLI`,value:M,missingValueLabel:X?`(profile default unavailable)`:M===`aside`?`Aside (main-only)`:n(M)?t(M):void 0,error:X||M===`aside`?`Aside cannot run memory flush. Choose a separate runtime.`:n(M)?`The saved runtime is retired. Choose an available runtime.`:null,options:Z,onChange:e=>{N(e),G(`memory.cli`,{value:e,original:K.cli??``,valid:!0})}}),(0,k.jsx)(h,{id:`memory-retention`,label:`Retention days`,value:P,min:1,error:oe,onChange:e=>{F(e),G(`memory.retentionDays`,{value:e,original:typeof K.retentionDays==`number`?K.retentionDays:30,valid:E(e,`Retention days`)===null})}}),(0,k.jsx)(p,{id:`memory-auto-reflect`,label:`Auto-reflect after flush`,value:I,onChange:e=>{L(e),G(`memory.autoReflectAfterFlush`,{value:e,original:!!K.autoReflectAfterFlush,valid:!0})}}),(0,k.jsx)(m,{id:`memory-flush-language`,label:`Flush language`,value:re,options:[...b],onChange:e=>{R(e),G(`memory.flushLanguage`,{value:e,original:K.flushLanguage??`en`,valid:!0})}})]}),(0,k.jsx)(u,{title:`Stored entries`,hint:`Read-only browse of the key/value memory table (50/page).`,children:w.state.kind===`loading`?(0,k.jsx)(c,{children:`Loading entries…`}):w.state.kind===`offline`?(0,k.jsx)(l,{port:e}):w.state.kind===`error`?(0,k.jsx)(d,{message:w.state.message}):Q.length===0?(0,k.jsx)(c,{children:`No memory entries yet.`}):(0,k.jsxs)(k.Fragment,{children:[le.map(e=>(0,k.jsx)(te,{row:e,onOpen:H},e.key)),(0,k.jsxs)(a,{status:(0,k.jsxs)(`span`,{children:[`Page `,z+1,` / `,ue]}),children:[(0,k.jsx)(`button`,{type:`button`,className:`settings-action`,disabled:z===0,onClick:()=>B(e=>Math.max(0,e-1)),children:`Prev`}),(0,k.jsx)(`button`,{type:`button`,className:`settings-action`,disabled:!$,onClick:()=>B(e=>e+1),children:`Next`})]})]})}),(0,k.jsxs)(u,{title:`Actions`,hint:`Flush runs async — the browse list refreshes when it finishes.`,children:[(0,k.jsxs)(a,{status:U.notice?(0,k.jsx)(`span`,{role:`status`,children:U.notice}):void 0,children:[(0,k.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,disabled:U.busy!==null,onClick:()=>void J(),children:U.busy===`flush`?`Queuing…`:`Flush now`}),(0,k.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,disabled:U.busy!==null,onClick:()=>void Y(),children:U.busy===`reflect`?`Reflecting…`:`Reflect soul`}),(0,k.jsx)(`button`,{type:`button`,className:`settings-action`,disabled:w.state.kind!==`ready`,onClick:ie,children:`Export memory`})]}),U.error?(0,k.jsx)(c,{tone:`error`,role:`alert`,children:U.error}):null]}),V?(0,k.jsx)(`div`,{className:`settings-memory-modal settings-pi-modal`,role:`dialog`,"aria-modal":`true`,"aria-label":`Memory entry ${V.key}`,onClick:e=>{e.target===e.currentTarget&&H(null)},children:(0,k.jsxs)(`div`,{className:`settings-memory-modal-card`,children:[(0,k.jsxs)(`header`,{className:`settings-memory-modal-header`,children:[(0,k.jsx)(`h3`,{children:V.key}),(0,k.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:()=>H(null),"aria-label":`Close memory entry`,children:`Close`})]}),(0,k.jsx)(`pre`,{className:`settings-memory-modal-body`,children:V.value})]})}):null]})}export{b as FLUSH_LANGUAGE_OPTIONS,x as MEMORY_PAGE_SIZE,y as MEMORY_SECTION_A_KEYS,A as default,S as isMemorySettingsKey,C as normalizeMemoryRows,D as paginate,O as previewValue,E as validatePositiveInt};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{r as t,t as n}from"./cli-engine-NdU0lzs_.js";import{n as r,t as i}from"./jsx-runtime-CkEUZM6i.js";import{a,c as o,i as s,n as c,o as l,r as u,s as d,t as f,u as p}from"./page-shell-Cz2ylri8.js";import{t as m}from"./error-normalize-jnjrKZDu.js";import{a as h,i as g,n as _,s as v}from"./fields-CicOWY-X.js";import{i as y,n as b,r as x,t as S}from"./AsideSelectionFields-DvU5xWAP.js";import{a as C,f as w,i as T,o as E,s as D}from"./agent-meta-v4jNRAbX.js";import{t as O}from"./path-utils-B6vBr0DD.js";var k=e(r(),1),A=i(),j=[`basic`,`openai`,`anthropic`,`vertex`],M=`[hidden], [inert], [aria-disabled="true"], fieldset[disabled]`;function N(e){return Array.from(e.querySelectorAll(`button, input, select, textarea, a[href], [tabindex]`)).filter(e=>{if(e.tabIndex<0||e.matches(`:disabled`)||e.closest(M))return!1;for(let t=e;t;t=t.parentElement){let e=t.ownerDocument.defaultView?.getComputedStyle(t);if(e?.display===`none`||e?.visibility===`hidden`||e?.visibility===`collapse`)return!1}return!0})}function P(e){return e===`anthropic`?`https://api.anthropic.com/v1/messages`:e===`vertex`?`https://LOCATION-aiplatform.googleapis.com/v1`:`http://127.0.0.1:18645/v1`}function F({client:e,pi:t,provider:n,model:r,onClose:i,onRegistered:a}){let o=(0,k.useRef)(null),c=(0,k.useMemo)(()=>t?.profiles?.find(e=>e.id===n)||t?.profiles?.[0],[t,n]),[u,d]=(0,k.useState)(c?.mode||`basic`),[f,p]=(0,k.useState)(c?.id||n||`progrok`),[m,h]=(0,k.useState)(c?.endpoint||P(u)),[_,y]=(0,k.useState)(r||c?.model||`grok-composer-2.5-fast`),[b,x]=(0,k.useState)(``),[S,C]=(0,k.useState)(!1),[w,T]=(0,k.useState)(null);(0,k.useEffect)(()=>{let e=o.current;if(!e||e.closest(M))return;let t=e.ownerDocument.activeElement,n=N(e);return(n.find(e=>e.id===`pi-profile-id`)??n[0])?.focus(),()=>{t instanceof HTMLElement&&t.isConnected&&!t.matches(`:disabled`)&&!t.closest(M)&&t.focus({preventScroll:!0})}},[]),(0,k.useEffect)(()=>{h(e=>e||P(u))},[u]);let E=e=>{let t=o.current;if(!(!t||t.closest(M)||e.defaultPrevented)){if(e.key===`Escape`)e.preventDefault(),e.stopPropagation(),i();else if(e.key===`Tab`){let n=N(t),r=n[0],i=n.at(-1),a=t.ownerDocument.activeElement;(!r||!n.some(e=>e===a)||(e.shiftKey?a===r:a===i))&&(e.preventDefault(),(e.shiftKey?i??t:r??t).focus())}}},D=async()=>{let t=o.current,n=t?.querySelector(`.settings-action-save`);t&&n&&t.ownerDocument.activeElement===n&&!t.closest(M)&&N(t).find(e=>e!==n)?.focus(),C(!0),T(null);try{let t=(await e.post(`/api/pi/profiles/register`,{id:f,label:f,mode:u,endpoint:m,model:_,apiKey:b})).data;a({provider:f,model:_,models:t.models||[],pi:t.settings?.pi}),i()}catch(e){T(e instanceof Error?e.message:String(e))}finally{C(!1)}};return(0,A.jsx)(`div`,{className:`settings-memory-modal settings-pi-modal`,ref:o,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`pi-profile-title`,tabIndex:-1,onKeyDown:E,children:(0,A.jsxs)(`div`,{className:`settings-memory-modal-card`,children:[(0,A.jsxs)(`header`,{className:`settings-memory-modal-header`,children:[(0,A.jsx)(`h3`,{id:`pi-profile-title`,children:`Pi Settings`}),(0,A.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:i,children:`Close`})]}),(0,A.jsxs)(`div`,{className:`settings-section-body`,children:[(0,A.jsx)(g,{id:`pi-profile-mode`,label:`Mode`,value:u,options:j.map(e=>({value:e,label:e})),onChange:e=>d(e)}),(0,A.jsx)(v,{id:`pi-profile-id`,label:`Provider`,value:f,onChange:p,placeholder:`progrok`}),(0,A.jsx)(v,{id:`pi-profile-endpoint`,label:`Endpoint`,value:m,onChange:h,placeholder:P(u)}),(0,A.jsx)(v,{id:`pi-profile-model`,label:`Model`,value:_,onChange:y,placeholder:`grok-composer-2.5-fast`}),(0,A.jsx)(v,{id:`pi-profile-key`,label:`API Key`,value:b,onChange:x,placeholder:c?.apiKeySet?`set (${c.apiKeyLast4||`****`})`:`empty for local proxy`}),(0,A.jsx)(l,{children:`Default: grok-composer-2.5-fast. Bare grok-composer-2.5 currently has no verified team access.`}),w?(0,A.jsx)(l,{tone:`error`,role:`alert`,children:w}):null,(0,A.jsx)(s,{children:(0,A.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,disabled:S,onClick:()=>void D(),children:S?`Registering...`:`Register`})})]})]})})}function I(e,t,n=``){let r=new Set;n&&r.add(n);for(let n of e?.discoveredModels?.[t]||[])r.add(n);let i=e?.profiles?.find(e=>e.id===t);return i?.model&&r.add(i.model),[...r]}function L(e,t=``){let n=new Set;t&&n.add(t);for(let t of e?.profiles||[])n.add(t.id);return[...n]}function R(e){return e===`cursor`||e===`grok`||e===`claude`}function z(e){return e===`native`||e===`print`}var B=`unrecognized`,V=[{value:`native`,label:`Native session (opt-in)`},{value:`print`,label:`Print compatibility`}];function H({cli:e,original:t,dirty:n,disabled:r=!1,setEntry:i}){let a=R(e)?`perCli.${e}.transport`:null,o=(0,k.useSyncExternalStore)(n.subscribe,()=>a===null?void 0:n.pending.get(a)),s=(0,k.useRef)(r);(0,k.useLayoutEffect)(()=>(s.current=r,()=>{s.current=!0}),[r]);let c=t===void 0?`print`:t,l=o?o.value:c,u=z(l);return a===null?null:(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(g,{id:`percli-${e}-transport`,label:`Runtime transport`,value:u?l:B,options:u?V:[...V,{value:B,label:`Unrecognized transport`}],disabled:r,error:u?null:`Choose a supported runtime transport.`,onChange:e=>{!s.current&&z(e)&&i(a,{value:e,original:c,valid:!0})}}),u?null:(0,A.jsx)(`p`,{className:`settings-field-error`,role:`alert`,children:`Stored runtime transport is unrecognized.`}),(0,A.jsx)(`p`,{className:`settings-percli-note`,children:`Applies to the next run. Independent of Activity / Legacy presentation.`}),l===`native`?(0,A.jsx)(`p`,{className:`settings-percli-note`,children:e===`claude`?`Claude native supports Auto (YOLO) / Safe permissions.`:`Native requires Auto (YOLO) permissions; no native worker assignments.`}):null]})}function U(e,t,n=!0){return{value:e,original:t,valid:n}}function ee({cli:e,meta:t,original:n,value:r,setValue:i,setEntry:a,dirty:s,disabled:c=!1,client:l,aside:u,asideOverride:d,pi:f,setPi:p,onPiRegistered:m}){let _=`percli-${e}-models`,y=e===`pi`,[b,w]=(0,k.useState)(!1),E=(0,k.useRef)(c);if((0,k.useLayoutEffect)(()=>(E.current=c,()=>{E.current=!0}),[c]),e===`aside`&&u)return(0,A.jsxs)(`div`,{className:`settings-percli-row`,"data-cli":e,children:[(0,A.jsx)(o,{children:(0,A.jsx)(`strong`,{className:`settings-percli-title`,children:`Aside`})}),(0,A.jsx)(S,{id:`percli-aside`,account:r.account||``,host:r.host,model:r.model||``,effort:r.effort||``,inventory:u.inventory,disabled:c,refresh:u.refresh,onAccountChange:e=>{E.current||(i({...r,account:e,host:`local`}),a(`perCli.aside.account`,U(e,n.account||``,x(e))),a(`perCli.aside.host`,U(`local`,n.host||``)),a(`activeOverrides.aside.model`,U(``,d?.model||``)),a(`activeOverrides.aside.effort`,U(``,d?.effort||``)))},onModelChange:e=>{E.current||(i({...r,model:e}),a(`perCli.aside.model`,U(e,n.model||``)))},onEffortChange:e=>{E.current||(i({...r,effort:e}),a(`perCli.aside.effort`,U(e,n.effort||``)))}})]});let D=r.provider||t.defaultProvider||t.providers?.[0]||`claude`,O=y?I(f,D,r.model||``):[],j=!y&&(t.providers?.length??0)>0,M=y?O:j?t.modelsByProvider?.[D]??t.models:t.models,N=j?t.effortsByProvider?.[D]??t.efforts:void 0,P=C(t,r.model||``,N,j?D:void 0);return(0,A.jsxs)(`div`,{className:`settings-percli-row`,"data-cli":e,children:[(0,A.jsx)(o,{children:(0,A.jsx)(`strong`,{className:`settings-percli-title`,children:t.label})}),(0,A.jsxs)(`div`,{className:`settings-percli-grid${y?` settings-percli-grid--pi`:``}`,children:[y&&L(f,D).length?(0,A.jsx)(g,{id:`percli-${e}-provider`,label:`Provider`,disabled:c,value:D,options:L(f,D).map(e=>({value:e,label:e})),onChange:t=>{if(E.current)return;let o=I(f,t),s=o.includes(r.model||``)?r.model||``:o[0]||``;i({...r,provider:t,model:s}),a(`perCli.${e}.provider`,U(t,n.provider??`progrok`)),a(`perCli.${e}.model`,U(s,n.model??``))}}):j?(0,A.jsx)(g,{id:`percli-${e}-provider`,label:`Provider`,disabled:c,value:D,options:(t.providers??[]).map(e=>({value:e,label:e})),onChange:o=>{if(E.current)return;let s=t.modelsByProvider?.[o]??[],c=t.effortsByProvider?.[o]??[],l=s.includes(r.model||``)?r.model||``:s[0]||``,u=T(t,l,r.effort??``,c,o);i({...r,provider:o,model:l,effort:u}),a(`perCli.${e}.provider`,U(o,n.provider??t.defaultProvider??`claude`)),a(`perCli.${e}.model`,U(l,n.model??``)),a(`perCli.${e}.effort`,U(u,n.effort??``))}}):null,y&&M.length>0?(0,A.jsx)(g,{id:`percli-${e}-model`,label:`Model`,disabled:c,value:r.model??M[0]??``,options:M.map(e=>({value:e,label:e})),onChange:o=>{if(E.current)return;let s=T(t,o,r.effort??``,N,j?D:void 0);i({...r,model:o,effort:s}),a(`perCli.${e}.model`,U(o,n.model??``)),s!==(r.effort??``)&&a(`perCli.${e}.effort`,U(s,n.effort??``))}}):(0,A.jsx)(v,{id:`percli-${e}-model`,label:`Model`,disabled:c,value:r.model??``,onChange:t=>{E.current||(i({...r,model:t}),a(`perCli.${e}.model`,U(t,n.model??``)))},placeholder:M[0]??`model id`}),t.modelNote?(0,A.jsx)(`p`,{className:`settings-percli-note`,children:t.modelNote}):null,M.length>0?(0,A.jsx)(`datalist`,{id:_,children:M.map(e=>(0,A.jsx)(`option`,{value:e},e))}):null,P.length>0?(0,A.jsxs)(`div`,{className:`settings-percli-effort`,children:[(0,A.jsx)(g,{id:`percli-${e}-effort`,label:`Effort`,disabled:c,value:r.effort??``,options:[{value:``,label:`(default)`},...P.map(e=>({value:e,label:e}))],onChange:t=>{E.current||(i({...r,effort:t}),a(`perCli.${e}.effort`,U(t,n.effort??``)))}}),t.effortNote?(0,A.jsx)(`p`,{className:`settings-percli-note`,children:t.effortNote}):null]}):t.effortNote?(0,A.jsx)(`p`,{className:`settings-percli-note settings-percli-note--effort`,children:t.effortNote}):null,R(e)?(0,A.jsx)(H,{cli:e,original:n.transport,dirty:s,disabled:c,setEntry:a}):null,(0,A.jsx)(h,{id:`percli-${e}-fastmode`,label:`Fast mode`,disabled:c,value:!!r.fastMode,onChange:t=>{E.current||(i({...r,fastMode:t}),a(`perCli.${e}.fastMode`,U(t,!!n.fastMode)))}}),y&&l?(0,A.jsx)(`button`,{type:`button`,className:`settings-action settings-percli-settings`,disabled:c,onClick:()=>{E.current||w(!0)},children:`Settings`}):null]}),y&&l&&b?(0,A.jsx)(`div`,{inert:c,"aria-busy":c,children:(0,A.jsx)(F,{client:l,pi:f,provider:D,model:r.model||`grok-composer-2.5-fast`,onClose:()=>w(!1),onRegistered:t=>{if(m){m(t);return}if(E.current)return;let{provider:o,model:s,pi:c}=t;c&&p&&p(c),i({...r,provider:o,model:s}),a(`perCli.${e}.provider`,U(o,n.provider??`progrok`)),a(`perCli.${e}.model`,U(s,n.model??``))}})}):null]})}var W=e=>e===`fallbackOrder`||e.startsWith(`perCli.`)||e===`activeOverrides.aside.model`||e===`activeOverrides.aside.effort`;function te(e){let t=e&&typeof e==`object`&&`data`in e?e.data:e;if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Invalid settings response. Refresh before retrying.`);return t}function ne(e){return w(e).sort((e,t)=>e===`pi`?-1:+(t===`pi`))}function re(e){let t=new Set;for(let n of Object.keys(e.activeOverrides||{}))t.add(n);for(let n of Object.keys(e.perCli||{}))t.add(n);let n={};for(let e of t)n[e]={model:``,effort:``};return{activeOverrides:n}}function G({port:e,instanceUrl:r,client:i,dirty:o,registerSave:h}){let g=(0,k.useMemo)(()=>({client:i,port:e,instanceUrl:r,dirty:o}),[i,e,r,o]),v=(0,k.useRef)(null),x=(0,k.useRef)(null),S=(0,k.useRef)(0),C=(0,k.useMemo)(()=>({...i,get:async(e,t)=>({instance:g,value:await i.get(e,t)})}),[i,g]),{state:w,refresh:T,setData:j}=p(C,`/api/settings`,[e]),M=(0,k.useMemo)(()=>w.kind===`ready`?w.data.instance===g?{kind:`ready`,data:w.data.value}:{kind:`loading`}:w,[w,g]),N=(0,k.useCallback)(e=>j({instance:g,value:e}),[g,j]),[P,F]=(0,k.useState)({}),[I,L]=(0,k.useState)(void 0),[R,z]=(0,k.useState)([]),[B,V]=(0,k.useState)(!1),[H,U]=(0,k.useState)(null),[G,K]=(0,k.useState)(null),[q,J]=(0,k.useState)(!1),[ie,Y]=(0,k.useState)(null),X=P.aside,ae=y(i,r,e,X?.account||``,!!X),Z=X?X.host===`local`?b(ae.inventory,X.model||``,X.effort||``):`Aside requires the local host.`:null;(0,k.useEffect)(()=>{for(let[e,t]of o.pending)if(e.startsWith(`perCli.aside.`)||e.startsWith(`activeOverrides.aside.`)){let n=!Z;t.valid!==n&&o.set(e,{...t,valid:n})}},[Z,o]),(0,k.useLayoutEffect)(()=>(v.current=g,x.current=null,++S.current,J(!1),V(!1),K(null),U(null),Y(null),()=>{v.current=null,x.current=null,++S.current}),[g]);let Q=(0,k.useCallback)(()=>v.current===g&&!x.current,[g]),$=(0,k.useCallback)(async()=>{if(v.current!==g)return;let e=++S.current;try{let t=await i.get(`/api/cli-registry`);if(v.current!==g||e!==S.current)return;let n=t&&typeof t==`object`&&`data`in t?t.data:t;Y(D(n))}catch{v.current===g&&e===S.current&&Y(null)}},[i,g]);(0,k.useEffect)(()=>{$()},[$]),(0,k.useEffect)(()=>{if(M.kind!==`ready`)return;let e={...M.data.perCli||{}},t=Object.fromEntries(Object.entries(o.saveBundle()).filter(([e])=>W(e))),n=O(t).perCli;if(n&&typeof n==`object`&&!Array.isArray(n))for(let[t,r]of Object.entries(n))r&&typeof r==`object`&&!Array.isArray(r)&&(e[t]={...e[t],...r});F(e),L(M.data.pi),z([...M.data.fallbackOrder||[]])},[M,o]);let oe=(0,k.useCallback)(e=>{if(v.current!==g)return;let t=M.kind===`ready`?M.data.perCli?.pi:void 0;e.pi&&L(e.pi),F(t=>({...t,pi:{...t.pi,provider:e.provider,model:e.model}})),o.set(`perCli.pi.provider`,{value:e.provider,original:t?.provider??`progrok`,valid:!0}),o.set(`perCli.pi.model`,{value:e.model,original:t?.model??``,valid:!0})},[o,g,M]);(0,k.useEffect)(()=>()=>{for(let e of Array.from(o.pending.keys()))W(e)&&o.remove(e)},[o,g]);let se=(0,k.useCallback)((e,t)=>{Q()&&W(e)&&o.set(e,t)},[o,Q]),ce=(0,k.useCallback)(()=>{if(v.current!==g)return Promise.resolve();let e=x.current;if(e)return e.kind===`save`?e.promise:Promise.reject(Error(`Wait for the active override reset before saving.`));if([...o.pending.keys()].some(e=>e.startsWith(`perCli.aside.`)||e.startsWith(`activeOverrides.aside.`))&&Z)return Promise.reject(Error(Z));let t=Object.fromEntries(Object.entries(o.saveBundle()).filter(([e])=>W(e)));if(Object.keys(t).length===0)return Promise.resolve();if(Object.keys(t).some(e=>e.startsWith(`perCli.aside.`)||e.startsWith(`activeOverrides.aside.`))&&Z)return Promise.reject(Error(Z));if(t.fallbackOrder&&t.fallbackOrder.includes(`aside`))return Promise.reject(Error(`Aside cannot be used as a fallback.`));Object.hasOwn(t,`perCli.aside.account`)&&(t[`activeOverrides.aside.model`]=``,t[`activeOverrides.aside.effort`]=``);let n=O(t),r=new Map([...o.pending].filter(([e])=>Object.hasOwn(t,e)));J(!0),K(null);let a={instance:g,kind:`save`,promise:Promise.resolve()};return a.promise=Promise.resolve().then(async()=>{if(v.current!==g)return;let e=await i.put(`/api/settings`,n);if(v.current!==g)return;let t=te(e);for(let[e,t]of r)o.pending.get(e)===t&&o.remove(e);N(t),await T(),await $()}).catch(e=>{if(v.current===g)throw e}).finally(()=>{x.current===a&&(x.current=null),v.current===g&&J(!1)}),x.current=a,a.promise},[i,o,g,$,T,N,Z]);(0,k.useEffect)(()=>{if(h)return h(ce),()=>h(null)},[h,ce]);let le=(0,k.useCallback)(()=>{if(!Q()||M.kind!==`ready`||!window.confirm(`Reset all active overrides?`))return;V(!0),U(null);let e=re(M.data),t={instance:g,kind:`reset`,promise:Promise.resolve()};return t.promise=Promise.resolve().then(async()=>{if(v.current!==g)return;let t=await i.put(`/api/settings`,e);if(v.current!==g)return;let n=te(t);N(n),await T()}).catch(e=>{v.current===g&&U(m(e))}).finally(()=>{x.current===t&&(x.current=null),v.current===g&&V(!1)}),x.current=t,t.promise},[Q,i,g,T,N,M]);if(M.kind===`loading`)return(0,A.jsx)(c,{});if(M.kind===`offline`)return(0,A.jsx)(u,{port:e});if(M.kind===`error`)return(0,A.jsx)(f,{message:M.message});let ue=M.data,de=ue.perCli||{},fe=ne(Object.keys(de)),pe=ue.activeOverrides||{},me=Object.entries(pe);return(0,A.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),ce().catch(e=>{v.current===g&&K(m(e))})},children:[G?(0,A.jsx)(f,{message:G}):null,(0,A.jsx)(d,{title:`Model defaults`,hint:`Per-CLI model and runtime defaults. Runtime transport applies to the next run; display and permissions stay separate.`,children:fe.length===0?(0,A.jsx)(l,{children:`No CLIs registered for this instance.`}):fe.map(e=>(0,A.jsx)(ee,{cli:e,meta:E(e,ie),original:de[e]||{},value:P[e]||de[e]||{},dirty:o,disabled:q||B,setValue:t=>{Q()&&F({...P,[e]:t})},setEntry:se,client:i,aside:ae,asideOverride:pe[e]||{},pi:I,setPi:e=>{Q()&&L(e)},onPiRegistered:oe},e))}),(0,A.jsx)(d,{title:`Fallback order`,hint:`Order of CLIs used when the active CLI fails. Press Enter to add a chip; Backspace to remove the last.`,children:(0,A.jsx)(_,{id:`model-fallbackOrder`,label:`Fallback order`,error:(()=>{if(R.includes(`aside`))return`Aside is main-only. Remove it from the fallback order.`;let e=R.find(n);return e?`A saved ${t(e).replace(` (retired)`,``)} fallback is retired. Remove it before changing this order.`:null})(),disabled:q||B,value:R,onChange:e=>{Q()&&(z(e),se(`fallbackOrder`,{value:e,original:ue.fallbackOrder||[],valid:!e.includes(`aside`)&&!e.some(n)}))},placeholder:`cli name`})}),(0,A.jsxs)(d,{title:`Active overrides`,hint:`Per-session overrides applied on top of per-CLI defaults.`,children:[me.length===0?(0,A.jsx)(l,{children:`No active overrides.`}):(0,A.jsx)(a,{items:me.flatMap(([e,t])=>[{label:`${e} model`,value:t?.model||`—`,mono:!0},{label:`${e} effort`,value:t?.effort||`—`,mono:!0}])}),(0,A.jsx)(s,{status:H?(0,A.jsx)(`span`,{className:`settings-field-error`,role:`alert`,children:H}):null,children:(0,A.jsx)(`button`,{type:`button`,className:`settings-action settings-action-danger`,onClick:()=>void le(),disabled:q||B||me.length===0,children:B?`Resetting…`:`Reset overrides`})})]})]})}export{re as buildResetOverridesPatch,G as default,ne as orderModelCliKeys};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{n as r,o as i,r as a,s as o,t as s,u as c}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{n as r,o as i,r as a,s as o,t as s,u as c}from"./page-shell-Cz2ylri8.js";import{a as l,i as u,s as d}from"./fields-CicOWY-X.js";import{t as f}from"./InlineWarn-Cq4z28F3.js";import{t as p}from"./path-utils-B6vBr0DD.js";var m=e(t(),1),h=n(),g=[`off`,`http-only`,`full`];function _(e){return e===`off`||e===`http-only`||e===`full`}var v=[`network.bindHost`,`network.lanBypass`,`network.remoteAccess.mode`,`network.remoteAccess.trustProxies`,`network.remoteAccess.trustForwardedFor`,`network.remoteAccess.publicOriginHint`],y=[{value:`127.0.0.1`,label:`127.0.0.1 — loopback only (recommended)`},{value:`0.0.0.0`,label:`0.0.0.0 — all interfaces (LAN exposed)`}],b=[{value:`off`,label:`off — block remote requests`},{value:`http-only`,label:`http-only — read-only HTTP from remote`},{value:`full`,label:`full — HTTP + WebSocket from remote`}];function x(e){let t={};return e.bindHost!==void 0&&(t.bindHost=e.bindHost),e.lanBypass!==void 0&&(t.lanBypass=e.lanBypass),t.remoteAccess={...e.remoteAccess??{}},t}function S(e){let t=(e||``).trim();if(t===``)return{kind:`empty`};let n;try{n=new URL(t)}catch{return{kind:`invalid`,reason:`Must be an absolute URL (https://… or http://…).`}}return n.protocol!==`http:`&&n.protocol!==`https:`?{kind:`invalid`,reason:`Only http:// or https:// origins are accepted.`}:n.hostname?n.pathname&&n.pathname!==`/`?{kind:`invalid`,reason:`Origin must not include a path.`}:n.search||n.hash?{kind:`invalid`,reason:`Origin must not include query or hash.`}:{kind:`valid`,origin:n.origin}:{kind:`invalid`,reason:`Origin must include a host.`}}function C(e){let t=(e.locationHost||``).toLowerCase().split(`:`)[0]||``;return t===``||t===`localhost`||t===`127.0.0.1`||t===`::1`||e.currentMode===e.nextMode?!1:e.nextMode===`off`}function w({port:e,client:t,dirty:n,registerSave:g}){let{state:w,refresh:T,setData:E}=c(t,`/api/settings`),[D,O]=(0,m.useState)({});(0,m.useEffect)(()=>{if(w.kind===`ready`){let e=w.data.network??{};O(x(e))}},[w]),(0,m.useEffect)(()=>()=>{for(let e of v)n.remove(e)},[n]);let k=(0,m.useCallback)((e,t)=>n.set(e,t),[n]),A=(0,m.useMemo)(()=>w.kind===`ready`?w.data.network??{}:{},[w]),j=A.remoteAccess??{},M=D.remoteAccess??{},N=D.bindHost??A.bindHost??`127.0.0.1`,P=!!(D.lanBypass??A.lanBypass),F=_(M.mode)?M.mode:_(j.mode)?j.mode:`off`,I=F!==`off`,L=!!(M.trustProxies??j.trustProxies),R=!!(M.trustForwardedFor??j.trustForwardedFor),z=M.publicOriginHint??j.publicOriginHint??``,B=S(z),V=C({currentMode:_(j.mode)?j.mode:`off`,nextMode:F,locationHost:typeof window<`u`?window.location.host:``}),H=(0,m.useCallback)(async()=>{let e=n.saveBundle();if(Object.keys(e).length===0||V&&typeof window<`u`&&!window.confirm(`You are accessing this dashboard over a remote origin. Saving with remote access "off" will lock you out. Continue?`))return;let r=p(e),i=await t.put(`/api/settings`,r),a=i&&typeof i==`object`&&`data`in i?i.data:i;n.clear();let o=a.network??{};O(x(o)),E(a),await T()},[t,n,V,T,E]);if((0,m.useEffect)(()=>{if(g)return g(H),()=>g(null)},[g,H]),w.kind===`loading`)return(0,h.jsx)(r,{});if(w.kind===`offline`)return(0,h.jsx)(a,{port:e});if(w.kind===`error`)return(0,h.jsx)(s,{message:w.message});let U=(D.bindHost??A.bindHost)!==(A.bindHost??`127.0.0.1`);return(0,h.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),H()},children:[(0,h.jsxs)(o,{title:`Bind`,hint:`Listening interface for /i/${e}. Changes require an instance restart.`,children:[(0,h.jsx)(u,{id:`network-bindHost`,label:`Bind host`,value:N,options:y,onChange:e=>{O({...D,bindHost:e}),k(`network.bindHost`,{value:e,original:A.bindHost??`127.0.0.1`,valid:!0})}}),N===`0.0.0.0`&&(0,h.jsxs)(f,{children:[`Listening on `,(0,h.jsx)(`code`,{children:`0.0.0.0`}),` exposes this instance's API to anyone on your LAN. Pair with auth + firewall rules.`]}),U&&(0,h.jsx)(f,{tone:`info`,children:`Restart the instance for the new bind host to take effect.`}),(0,h.jsx)(l,{id:`network-lanBypass`,label:`LAN bypass`,description:`Skip auth checks for clients on the same LAN.`,value:P,onChange:e=>{O({...D,lanBypass:e}),k(`network.lanBypass`,{value:e,original:!!A.lanBypass,valid:!0})}}),P&&(0,h.jsx)(f,{children:`LAN bypass disables auth for any client on the same network. Only enable on a trusted network.`})]}),(0,h.jsxs)(o,{title:`Remote access`,hint:`Mode controls what reaches the API from outside the loopback interface.`,children:[(0,h.jsx)(u,{id:`network-remoteAccess-mode`,label:`Remote access mode`,value:F,options:b,onChange:e=>{_(e)&&(O({...D,remoteAccess:{...M,mode:e}}),k(`network.remoteAccess.mode`,{value:e,original:_(j.mode)?j.mode:`off`,valid:!0}))}}),(0,h.jsxs)(i,{children:[(0,h.jsx)(`strong`,{children:`off`}),` — only loopback can talk to the API.`,` `,(0,h.jsx)(`strong`,{children:`http-only`}),` — remote can issue HTTP requests but no WebSocket upgrades. `,(0,h.jsx)(`strong`,{children:`full`}),` — HTTP + WebSocket open to remote (use with auth).`]}),V&&(0,h.jsxs)(i,{tone:`error`,role:`alert`,children:[`Saving will close remote access while you're connected from`,(0,h.jsxs)(`code`,{children:[` `,typeof window<`u`?window.location.host:``,` `]}),`— you will be locked out. Reach the dashboard over loopback first.`]}),I&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(l,{id:`network-remoteAccess-trustProxies`,label:`Trust proxies`,description:`Honor proxy headers when computing the client origin.`,value:L,onChange:e=>{O({...D,remoteAccess:{...M,trustProxies:e}}),k(`network.remoteAccess.trustProxies`,{value:e,original:!!j.trustProxies,valid:!0})}}),(0,h.jsx)(l,{id:`network-remoteAccess-trustForwardedFor`,label:`Trust X-Forwarded-For`,description:`Use X-Forwarded-For for the client IP. Only enable behind a known proxy.`,value:R,onChange:e=>{O({...D,remoteAccess:{...M,trustForwardedFor:e}}),k(`network.remoteAccess.trustForwardedFor`,{value:e,original:!!j.trustForwardedFor,valid:!0})}}),R&&!L&&(0,h.jsx)(f,{children:`Trusting X-Forwarded-For without trusting the proxy chain lets any client spoof its IP. Enable "Trust proxies" too.`}),(0,h.jsx)(d,{id:`network-remoteAccess-publicOriginHint`,label:`Public origin hint`,value:z,placeholder:`https://your-tunnel-url`,error:B.kind===`invalid`?B.reason:null,onChange:e=>{O({...D,remoteAccess:{...M,publicOriginHint:e}});let t=S(e);k(`network.remoteAccess.publicOriginHint`,{value:t.kind===`valid`?t.origin:e,original:j.publicOriginHint??``,valid:t.kind!==`invalid`})}})]})]})]})}export{g as REMOTE_ACCESS_MODES,w as default,C as detectSelfLockoutRisk,_ as isRemoteAccessMode,S as parsePublicOriginHint};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{a as r,l as i,n as a,o,r as s,s as c,t as l,u}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{a as r,l as i,n as a,o,r as s,s as c,t as l,u}from"./page-shell-Cz2ylri8.js";import{i as d,n as f}from"./fields-CicOWY-X.js";import{t as p}from"./InlineWarn-Cq4z28F3.js";var m=e(t(),1),h=/^[a-zA-Z0-9._:*-]+$/;function g(e){return typeof e==`string`&&e.length>0&&e.length<=64&&h.test(e)}function _(e){if(typeof e!=`string`)return!1;let t=e.trim();return t.length===0||g(t)}function v(e){if(e===`auto`||e===`safe`)return!0;if(!Array.isArray(e))return!1;for(let t=0;t<e.length;t+=1)if(!_(e[t]))return!1;return!0}var y=n(),b=[`bash`,`read`,`write`,`edit`,`mcp.*`];function x(e){return e===`auto`?`Auto (YOLO)`:e===`safe`?`Safe`:e==null?`Not provided`:Array.isArray(e)&&v(e)?`Custom (${e.length} ${e.length===1?`entry`:`entries`})`:`Unrecognized`}function S(e){return e===`auto`}function C(e){return S(e)?{mode:`auto`}:e===`safe`?{mode:`safe`}:Array.isArray(e)?{mode:`custom`,tokens:e.filter(e=>typeof e==`string`).map(e=>e.trim()).filter(e=>e.length>0)}:{mode:`unknown`}}function w(e){return g(e)}function T(e){return v(e)?e===`auto`?`auto`:e===`safe`?`safe`:`custom`:`invalid`}function E(e){return Array.isArray(e)&&e.length>0?Array.from(new Set(e.filter(w))):[...b]}function D(e){return e.length!==0&&e.every(w)}function O(e){return e===`auto`?`warn`:e===`safe`?`ok`:Array.isArray(e)&&v(e)||e==null?`neutral`:`error`}var k=[{value:`auto`,label:`Auto (YOLO)`},{value:`safe`,label:`Safe`},{value:`custom`,label:`Custom — explicit allowlist below`}];function A({port:e,client:t,dirty:n,registerSave:h}){let{state:g,refresh:_,setData:v}=u(t,`/api/settings`),[b,S]=(0,m.useState)(`auto`),[A,j]=(0,m.useState)([]),M=(0,m.useMemo)(()=>g.kind===`ready`?C(g.data.permissions):null,[g]);(0,m.useEffect)(()=>{if(g.kind!==`ready`)return;let e=T(g.data.permissions),t=C(g.data.permissions);S(e),j(e===`custom`&&t.mode===`custom`?t.tokens:[])},[g]),(0,m.useEffect)(()=>()=>{n.remove(`permissions`)},[n]);let N=(0,m.useCallback)(e=>n.set(`permissions`,e),[n]),P=g.kind===`ready`?g.data.permissions:void 0,F=(0,m.useMemo)(()=>M?M.mode===`custom`?M.tokens:M.mode===`safe`?`safe`:M.mode===`unknown`?P:`auto`:`auto`,[M,P]),I=(0,m.useCallback)(e=>{if(e===`auto`){S(`auto`),j([]),N({value:`auto`,original:F,valid:!0});return}if(e===`safe`){S(`safe`),j([]),N({value:`safe`,original:F,valid:!0});return}if(e===`custom`){S(`custom`);let e=M&&M.mode===`custom`&&M.tokens.length>0?[...M.tokens]:E(null);j(e),N({value:e,original:F,valid:D(e)})}},[M,F,N]),L=(0,m.useCallback)(e=>{let t=e.map(e=>e.trim()).filter(e=>e.length>0);j(t),N({value:t,original:F,valid:D(t)})},[F,N]),R=(0,m.useCallback)(async()=>{let e=n.saveBundle();if(Object.keys(e).length===0)return;let r=await t.put(`/api/settings`,e),i=r&&typeof r==`object`&&`data`in r?r.data:r;n.clear();let a=T(i.permissions),o=C(i.permissions);S(a),j(a===`custom`&&o.mode===`custom`?o.tokens:[]),v(i),await _()},[t,n,_,v]);if((0,m.useEffect)(()=>{if(h)return h(R),()=>h(null)},[h,R]),g.kind===`loading`)return(0,y.jsx)(a,{});if(g.kind===`offline`)return(0,y.jsx)(s,{port:e});if(g.kind===`error`)return(0,y.jsx)(l,{message:g.message});let z=A.filter(e=>!w(e)),B=z.length>0,V=b===`custom`&&A.length===0,H=x(g.data.permissions),U=O(g.data.permissions);return(0,y.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>e.preventDefault(),children:[(0,y.jsxs)(c,{title:`Saved policy`,hint:`The permission policy currently saved on this instance.`,children:[(0,y.jsx)(r,{items:[{label:`Configured policy:`,value:(0,y.jsxs)(y.Fragment,{children:[` `,(0,y.jsx)(i,{tone:U,children:H})]}),className:`settings-readonly-line`}]}),M?.mode===`unknown`&&(0,y.jsx)(o,{children:`Unrecognized value: choose a policy below (or in Agent) to replace it.`})]}),(0,y.jsxs)(c,{title:`Change policy`,hint:`Selecting a value changes the draft. Save applies it. Auto (YOLO) requests automatic approval or permission bypass. Behavior varies by runtime.`,children:[(0,y.jsx)(d,{id:`permissions-mode`,label:`Change policy to`,value:b,options:k,onChange:I,missingValueLabel:b===`invalid`?`Unrecognized saved policy`:void 0}),b===`invalid`&&(0,y.jsx)(p,{role:`alert`,children:`The saved permissions value is not a recognized policy. Pick a policy above to replace it.`}),b===`custom`&&(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(f,{id:`permissions-allowlist`,label:`Allowlist`,value:A,onChange:L,placeholder:`bash, read, mcp.*`,error:B?`Invalid token${z.length===1?``:`s`}: ${z.join(`, `)}`:V?`Allowlist cannot be empty in Custom mode.`:null}),(0,y.jsxs)(o,{children:[`Each chip is a permission token. Examples: `,(0,y.jsx)(`code`,{children:`bash`}),`,`,(0,y.jsx)(`code`,{children:` read`}),`, `,(0,y.jsx)(`code`,{children:` write`}),`, `,(0,y.jsx)(`code`,{children:` mcp.*`}),`.`]}),V&&(0,y.jsx)(p,{role:`alert`,children:`An empty Custom allowlist cannot be saved. Add at least one token or switch back to Auto (YOLO).`})]})]})]})}export{S as a,E as c,w as i,x as n,C as o,D as r,T as s,A as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./Permissions-
|
|
1
|
+
import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./Permissions-B7PthH01.js";export{r as configuredPolicyLabel,s as default,a as isAllowlistValid,n as isPermissionToken,e as isPermissionsAuto,i as parsePermissionsValue,o as permissionsEditMode,t as seedAutoAllowlist};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{i as t}from"./icons-CVkqyECl.js";import{n,t as r}from"./jsx-runtime-CkEUZM6i.js";import{n as i,r as a,s as o,t as s,u as c}from"./page-shell-Cz2ylri8.js";import{a as l,i as u}from"./fields-CicOWY-X.js";import{t as d}from"./path-utils-B6vBr0DD.js";var f=e(n(),1),p=r(),m=`image/png,image/jpeg,image/webp,image/gif`;function h({kind:e,client:n}){let[r,i]=(0,f.useState)(null),[a,o]=(0,f.useState)(!1),[s,c]=(0,f.useState)(null),l=(0,f.useRef)(null);(0,f.useEffect)(()=>{let t=!1;return c(null),i(null),n.get(`/api/avatar`).then(n=>{if(t)return;let r=(`data`in n&&n.data?n.data:n)[e]||null;i(r)}).catch(e=>{t||c(e instanceof Error?e.message:String(e))}),()=>{t=!0}},[e,n]);let u=()=>l.current?.click(),d=async t=>{o(!0),c(null);try{let r=await t.arrayBuffer(),a=t.type||`application/octet-stream`,o=await n.post(`/api/avatar/${e}/upload`,void 0,{headers:{"content-type":a,"x-filename":encodeURIComponent(t.name)},body:r,signal:new AbortController().signal}),s=`data`in o&&o.data?o.data:o;i(s)}catch(e){c(e instanceof Error?e.message:String(e))}finally{o(!1),l.current&&(l.current.value=``)}},h=async()=>{o(!0),c(null);try{let t=await n.delete(`/api/avatar/${e}/image`),r=`data`in t&&t.data?t.data:t;i(r)}catch(e){c(e instanceof Error?e.message:String(e))}finally{o(!1)}},g=r&&r.kind===`image`?n.url(r.imageUrl):null,_=e===`agent`?`Agent avatar`:`User avatar`;return(0,p.jsxs)(`div`,{className:`settings-avatar-card`,children:[(0,p.jsx)(`div`,{className:`settings-avatar-preview`,"aria-label":`${_} preview`,children:g?(0,p.jsx)(`img`,{src:g,alt:`${_} current`}):e===`agent`?(0,p.jsx)(`img`,{className:`settings-avatar-mascot`,src:`/icons/mascot.png`,alt:``,"aria-hidden":`true`}):(0,p.jsx)(`span`,{className:`settings-avatar-placeholder`,"aria-hidden":`true`,dangerouslySetInnerHTML:{__html:t(`user`,28)}})}),(0,p.jsxs)(`div`,{className:`settings-avatar-controls`,children:[(0,p.jsx)(`span`,{className:`settings-field-label`,children:_}),(0,p.jsx)(`input`,{ref:l,type:`file`,accept:m,style:{display:`none`},onChange:e=>{let t=e.target.files?.[0];t&&d(t)}}),(0,p.jsxs)(`div`,{className:`settings-avatar-buttons`,children:[(0,p.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:u,disabled:a,children:a?`Working…`:`Upload image`}),g?(0,p.jsx)(`button`,{type:`button`,className:`settings-action settings-action-danger`,onClick:()=>void h(),disabled:a,children:`Clear`}):null]}),s?(0,p.jsx)(`p`,{className:`settings-field-error`,role:`alert`,children:s}):null]})]})}var g=[{value:`ko`,label:`한국어 (ko)`},{value:`en`,label:`English (en)`},{value:`ja`,label:`日本語 (ja)`},{value:`zh`,label:`中文 (zh)`}];function _({port:e,client:t,dirty:n,registerSave:r}){let{state:m,refresh:_,setData:v}=c(t,`/api/settings`),[y,b]=(0,f.useState)({});(0,f.useEffect)(()=>{m.kind===`ready`&&b(m.data)},[m]),(0,f.useEffect)(()=>()=>{for(let e of Array.from(n.pending.keys()))(e===`locale`||e===`showReasoning`)&&n.remove(e)},[n]);let x=(0,f.useCallback)((e,t)=>n.set(e,t),[n]),S=(0,f.useCallback)(async()=>{let e=n.saveBundle();if(Object.keys(e).length===0)return;let r=d(e),i=await t.put(`/api/settings`,r),a=i&&typeof i==`object`&&`data`in i?i.data:i;n.clear(),b(a),v(a),await _()},[t,n,_,v]);if((0,f.useEffect)(()=>{if(r)return r(S),()=>r(null)},[r,S]),m.kind===`loading`)return(0,p.jsx)(i,{});if(m.kind===`offline`)return(0,p.jsx)(a,{port:e});if(m.kind===`error`)return(0,p.jsx)(s,{message:m.message});let C=m.data;return(0,p.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),S()},children:[(0,p.jsxs)(o,{title:`Profile`,hint:`Identity and display preferences for this instance.`,children:[(0,p.jsx)(u,{id:`profile-locale`,label:`Locale`,value:y.locale??C.locale??`ko`,options:g,onChange:e=>{b({...y,locale:e}),x(`locale`,{value:e,original:C.locale??`ko`,valid:!0})}}),(0,p.jsx)(l,{id:`profile-showReasoning`,label:`Show reasoning traces`,value:!!(y.showReasoning??C.showReasoning),onChange:e=>{b({...y,showReasoning:e}),x(`showReasoning`,{value:e,original:!!C.showReasoning,valid:!0})}})]}),(0,p.jsxs)(o,{title:`Avatars`,hint:`Uploads write to the instance's home folder.`,children:[(0,p.jsx)(h,{kind:`agent`,client:t}),(0,p.jsx)(h,{kind:`user`,client:t})]})]})}export{_ as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{l as r,n as i,o as a,r as o,s,t as c,u as l}from"./page-shell-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-CkEUZM6i.js";import{l as r,n as i,o as a,r as o,s,t as c,u as l}from"./page-shell-Cz2ylri8.js";var u=e(t(),1),d=n(),f=`prompt.system`;function p(e){return`prompt.template.${e}`}function m(e){return!e||!Array.isArray(e.templates)?[]:e.templates.filter(e=>!!e&&typeof e.id==`string`&&typeof e.content==`string`)}function h(e){let t=m(e),n=e?.tree,r=[],i=new Set;if(Array.isArray(n)){for(let e of n)if(e&&Array.isArray(e.children))for(let n of e.children){if(i.has(n))continue;let a=t.find(e=>e.id===n);if(!a)continue;let o=e.emoji?`${e.emoji} ${e.label} · `:`${e.label} · `;r.push({value:a.id,label:`${o}${a.id}`}),i.add(n)}}for(let e of t)i.has(e.id)||(r.push({value:e.id,label:e.id}),i.add(e.id));return r}function g(e,t){return m(e).find(e=>e.id===t)??null}function _({port:e,client:t,dirty:n,registerSave:_}){let v=l(t,`/api/prompt`),y=l(t,`/api/prompt-templates`),[b,x]=(0,u.useState)(``),[S,C]=(0,u.useState)(null),[w,T]=(0,u.useState)(``),E=(0,u.useMemo)(()=>v.state.kind===`ready`?v.state.data?.content??``:``,[v.state]),D=(0,u.useMemo)(()=>y.state.kind===`ready`?y.state.data:null,[y.state]),O=(0,u.useMemo)(()=>h(D),[D]),k=(0,u.useRef)(new Set);(0,u.useEffect)(()=>{v.state.kind===`ready`&&x(v.state.data?.content??``)},[v.state]),(0,u.useEffect)(()=>{if(!D||S!==null)return;let e=m(D);if(e.length===0)return;let t=O[0]?.value??e[0].id;C(t);let n=g(D,t);T(n?.content??``)},[D,O,S]),(0,u.useEffect)(()=>()=>{n.remove(f);for(let e of k.current)n.remove(e)},[n]);let A=(0,u.useCallback)((e,t)=>{n.set(e,t),k.current.add(e)},[n]),j=(0,u.useCallback)(e=>{x(e),n.set(f,{value:e,original:E,valid:!0})},[n,E]),M=(0,u.useCallback)(e=>{if(!S)return;T(e);let t=g(D,S)?.content??``;A(p(S),{value:e,original:t,valid:!0})},[S,A,D]),N=(0,u.useCallback)(e=>{if(!S||e===S)return;let t=p(S);if(n.pending.get(t)&&typeof window<`u`&&!window.confirm(`You have unsaved edits to "${S}". Switching will keep them pending — Save will write all dirty templates.`))return;C(e);let r=p(e),i=n.pending.get(r),a=g(D,e)?.content??``;T(i&&typeof i.value==`string`?i.value:a)},[S,n,D]),P=(0,u.useCallback)(async()=>{let e=n.saveBundle(),r=[];f in e&&r.push(t.put(`/api/prompt`,{content:e[f]}));for(let[n,i]of Object.entries(e)){if(!n.startsWith(`prompt.template.`))continue;let e=n.slice(16);r.push(t.put(`/api/prompt-templates/${e}`,{content:i}))}if(r.length!==0){for(let e of r)await e;n.clear(),k.current.clear(),await Promise.all([v.refresh(),y.refresh()])}},[t,n,v,y]);if((0,u.useEffect)(()=>{if(_)return _(P),()=>_(null)},[_,P]),v.state.kind===`loading`||y.state.kind===`loading`)return(0,d.jsx)(i,{});if(v.state.kind===`offline`||y.state.kind===`offline`)return(0,d.jsx)(o,{port:e});if(v.state.kind===`error`)return(0,d.jsx)(c,{message:v.state.message});if(y.state.kind===`error`)return(0,d.jsx)(c,{message:y.state.message});let F=m(D),I=S?g(D,S)?.content??``:``,L=S!==null&&w!==I;return(0,d.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>e.preventDefault(),children:[(0,d.jsxs)(s,{title:`System prompt`,hint:`The agent's a2/system prompt. Saved to a2.md; regenerates the merged b prompt.`,children:[(0,d.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`prompt-system-body`,children:[(0,d.jsx)(`span`,{className:`settings-field-label`,children:`a2.md`}),(0,d.jsx)(`textarea`,{id:`prompt-system-body`,className:`settings-mono-input`,value:b,rows:14,spellCheck:!1,onChange:e=>j(e.target.value)})]}),b!==E&&(0,d.jsxs)(a,{children:[(0,d.jsx)(r,{tone:`warn`,children:`Unsaved`}),` `,`Pending edits to a2.md.`]})]}),(0,d.jsx)(s,{title:`Templates`,hint:`Edit individual prompt template bodies. Saving regenerates b automatically.`,children:F.length===0?(0,d.jsx)(a,{children:`No templates returned by /api/prompt-templates.`}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsxs)(`label`,{className:`settings-field settings-field-select`,htmlFor:`prompt-template-select`,children:[(0,d.jsx)(`span`,{className:`settings-field-label`,children:`Template`}),(0,d.jsx)(`select`,{id:`prompt-template-select`,value:S??``,onChange:e=>N(e.target.value),children:O.map(e=>(0,d.jsx)(`option`,{value:e.value,children:e.label},e.value))})]}),(0,d.jsxs)(`label`,{className:`settings-field settings-field-text`,htmlFor:`prompt-template-body`,children:[(0,d.jsx)(`span`,{className:`settings-field-label`,children:S?`${S}.md`:`Template body`}),(0,d.jsx)(`textarea`,{id:`prompt-template-body`,className:`settings-mono-input`,value:w,rows:16,spellCheck:!1,disabled:!S,onChange:e=>M(e.target.value)})]}),L&&(0,d.jsxs)(a,{children:[(0,d.jsx)(r,{tone:`warn`,children:`Unsaved`}),` `,`Pending edits to `,S,`.md.`]})]})})]})}export{h as buildTemplateOptions,_ as default,g as findTemplate,m as flattenTemplates,p as templateDirtyKey};
|