cli-jaw 2.17.47 → 2.17.48

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.
Files changed (68) hide show
  1. package/dist/src/agent/claude-runtime-run.js +5 -3
  2. package/dist/src/agent/claude-runtime-run.js.map +1 -1
  3. package/dist/src/agent/lifecycle-handler.js +20 -13
  4. package/dist/src/agent/lifecycle-handler.js.map +1 -1
  5. package/dist/src/agent/runtime/acp/runtime-session.js +2 -2
  6. package/dist/src/agent/runtime/acp/runtime-session.js.map +1 -1
  7. package/dist/src/agent/runtime/claude-sdk-session.js +3 -2
  8. package/dist/src/agent/runtime/claude-sdk-session.js.map +1 -1
  9. package/dist/src/agent/runtime/events.js +4 -0
  10. package/dist/src/agent/runtime/events.js.map +1 -1
  11. package/dist/src/agent/runtime/projection.js +27 -12
  12. package/dist/src/agent/runtime/projection.js.map +1 -1
  13. package/dist/src/agent/spawn.js +16 -13
  14. package/dist/src/agent/spawn.js.map +1 -1
  15. package/dist/src/core/config.js +2 -0
  16. package/dist/src/core/config.js.map +1 -1
  17. package/dist/src/discord/bot.js +1 -2
  18. package/dist/src/discord/bot.js.map +1 -1
  19. package/dist/src/discord/forwarder.js +2 -1
  20. package/dist/src/discord/forwarder.js.map +1 -1
  21. package/dist/src/memory/heartbeat-destination.js +64 -0
  22. package/dist/src/memory/heartbeat-destination.js.map +1 -0
  23. package/dist/src/memory/heartbeat.js +30 -40
  24. package/dist/src/memory/heartbeat.js.map +1 -1
  25. package/dist/src/messaging/forwarder-origin.js +36 -0
  26. package/dist/src/messaging/forwarder-origin.js.map +1 -1
  27. package/dist/src/messaging/run-pin.js +58 -0
  28. package/dist/src/messaging/run-pin.js.map +1 -0
  29. package/dist/src/messaging/send.js +6 -3
  30. package/dist/src/messaging/send.js.map +1 -1
  31. package/dist/src/routes/chat-sessions.js +9 -4
  32. package/dist/src/routes/chat-sessions.js.map +1 -1
  33. package/dist/src/routes/heartbeat.js +18 -1
  34. package/dist/src/routes/heartbeat.js.map +1 -1
  35. package/dist/src/slack/bot.js +1 -2
  36. package/dist/src/slack/bot.js.map +1 -1
  37. package/dist/src/slack/forwarder.js +4 -1
  38. package/dist/src/slack/forwarder.js.map +1 -1
  39. package/dist/src/slack/progress-activity.js +10 -0
  40. package/dist/src/slack/progress-activity.js.map +1 -1
  41. package/dist/src/slack/progress-lifecycle.js +7 -0
  42. package/dist/src/slack/progress-lifecycle.js.map +1 -1
  43. package/dist/src/slack/progress.js +88 -5
  44. package/dist/src/slack/progress.js.map +1 -1
  45. package/dist/src/telegram/bot.js +1 -6
  46. package/dist/src/telegram/bot.js.map +1 -1
  47. package/dist/src/telegram/forwarder.js +7 -5
  48. package/dist/src/telegram/forwarder.js.map +1 -1
  49. package/dist/src/trace/activity-control.js +3 -2
  50. package/dist/src/trace/activity-control.js.map +1 -1
  51. package/dist/src/trace/activity-journal.js +3 -1
  52. package/dist/src/trace/activity-journal.js.map +1 -1
  53. package/package.json +1 -1
  54. package/public/dist/.vite/manifest.json +19 -19
  55. package/public/dist/assets/{ChannelEnablementControl-egwTtO9-.js → ChannelEnablementControl-8KNIMzHd.js} +4 -4
  56. package/public/dist/assets/{ChannelSetupEntry-CCrUYd2-.js → ChannelSetupEntry-xvHkWzg1.js} +1 -1
  57. package/public/dist/assets/{ChannelsDiscord-B6rJAsQG.js → ChannelsDiscord-BV1rTT6B.js} +1 -1
  58. package/public/dist/assets/{ChannelsSlack-CrSIw4Wd.js → ChannelsSlack-YfI_w4Tf.js} +1 -1
  59. package/public/dist/assets/{ChannelsTelegram-DPrdLEnT.js → ChannelsTelegram-C4WV655d.js} +1 -1
  60. package/public/dist/assets/{manager-CFwOAoe0.js → manager-KjU4gHRX.js} +1 -1
  61. package/public/dist/assets/{settings-qkC0NuQ7.js → settings-CjSj1Y5Q.js} +1 -1
  62. package/public/dist/assets/{settings-embedding-DspkJ6sr.js → settings-embedding-CuWqXH7z.js} +1 -1
  63. package/public/dist/manager/index.html +1 -1
  64. package/public/dist/settings/index.html +1 -1
  65. package/public/locales/en.json +1 -0
  66. package/public/locales/ja.json +1 -0
  67. package/public/locales/ko.json +1 -0
  68. package/public/locales/zh.json +1 -0
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./react-C_pPTFsM.js";import{t as n}from"./jsx-runtime-NZYk81nU.js";import{t as r}from"./settings-client-CmwRsVd1.js";import{i,n as a}from"./ChannelEnablementControl-egwTtO9-.js";var o=e(t(),1),s=n();function c({client:e,label:t,endpoint:n,method:i=`GET`,interpret:a,auto:c=!1}){let[d,f]=(0,o.useState)({kind:`idle`}),p=(0,o.useRef)(null),m=(0,o.useRef)(!0),h=(0,o.useCallback)(async()=>{p.current?.abort();let t=new AbortController;p.current=t,f({kind:`checking`});try{let r=i===`POST`?await e.post(n,{},{signal:t.signal}):await e.get(n,{signal:t.signal});if(!m.current||t.signal.aborted)return;f(a(r))}catch(e){if(!m.current||t.signal.aborted)return;if(e instanceof r&&e.status===404){f({kind:`unknown`,reason:`Probe endpoint not implemented on this instance.`});return}let n=e instanceof Error?e.message:String(e);f({kind:`error`,reason:n})}},[e,n,a,i]);return(0,o.useEffect)(()=>(m.current=!0,c&&h(),()=>{m.current=!1,p.current?.abort()}),[c,h]),(0,s.jsxs)(`div`,{className:`settings-health-badge`,role:`status`,"aria-live":`polite`,children:[(0,s.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:()=>void h(),disabled:d.kind===`checking`,children:d.kind===`checking`?`Checking…`:`Check ${t}`}),(0,s.jsx)(`span`,{className:`settings-health-pill is-${d.kind}`,children:l(d)}),u(d)?(0,s.jsx)(`span`,{className:`settings-health-detail`,children:u(d)}):null]})}function l(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 u(e){return e.kind===`ok`&&e.detail||e.kind===`degraded`?e.detail:e.kind===`unknown`||e.kind===`error`?e.reason:null}function d(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 f(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 p({channel:e,client:t,dirty:n,open:r,onOpenChange:c,onSaved:l}){let u=(0,o.useRef)(null),d=(0,o.useRef)(!1),f=`${e}.setup`,p=(0,o.useMemo)(()=>i(document.documentElement.lang),[]);(0,o.useEffect)(()=>(d.current=!0,()=>{d.current=!1,n.remove(f)}),[t,n,f]);let m=!r&&n.isDirty();return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(`button`,{ref:u,type:`button`,"data-onboard-channel":e,disabled:r||m,onClick:()=>{n.isDirty()||(n.set(f,{value:!0,original:!1,valid:!1}),c(!0))},children:p(`onboarding.open`)}),m&&(0,s.jsx)(`p`,{className:`settings-field-hint`,children:`Save or discard your changes before opening setup.`}),r&&(0,s.jsx)(a,{channel:e,client:t,t:p,initialDraft:{},returnFocus:u.current,onBeforeSave:()=>async()=>{d.current&&(await l(),d.current&&n.remove(f))},onClose:()=>{n.remove(f),c(!1)}},e)]})}export{d as i,c as n,f as r,p as t};
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./react-C_pPTFsM.js";import{t as n}from"./jsx-runtime-NZYk81nU.js";import{t as r}from"./settings-client-CmwRsVd1.js";import{i,n as a}from"./ChannelEnablementControl-8KNIMzHd.js";var o=e(t(),1),s=n();function c({client:e,label:t,endpoint:n,method:i=`GET`,interpret:a,auto:c=!1}){let[d,f]=(0,o.useState)({kind:`idle`}),p=(0,o.useRef)(null),m=(0,o.useRef)(!0),h=(0,o.useCallback)(async()=>{p.current?.abort();let t=new AbortController;p.current=t,f({kind:`checking`});try{let r=i===`POST`?await e.post(n,{},{signal:t.signal}):await e.get(n,{signal:t.signal});if(!m.current||t.signal.aborted)return;f(a(r))}catch(e){if(!m.current||t.signal.aborted)return;if(e instanceof r&&e.status===404){f({kind:`unknown`,reason:`Probe endpoint not implemented on this instance.`});return}let n=e instanceof Error?e.message:String(e);f({kind:`error`,reason:n})}},[e,n,a,i]);return(0,o.useEffect)(()=>(m.current=!0,c&&h(),()=>{m.current=!1,p.current?.abort()}),[c,h]),(0,s.jsxs)(`div`,{className:`settings-health-badge`,role:`status`,"aria-live":`polite`,children:[(0,s.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:()=>void h(),disabled:d.kind===`checking`,children:d.kind===`checking`?`Checking…`:`Check ${t}`}),(0,s.jsx)(`span`,{className:`settings-health-pill is-${d.kind}`,children:l(d)}),u(d)?(0,s.jsx)(`span`,{className:`settings-health-detail`,children:u(d)}):null]})}function l(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 u(e){return e.kind===`ok`&&e.detail||e.kind===`degraded`?e.detail:e.kind===`unknown`||e.kind===`error`?e.reason:null}function d(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 f(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 p({channel:e,client:t,dirty:n,open:r,onOpenChange:c,onSaved:l}){let u=(0,o.useRef)(null),d=(0,o.useRef)(!1),f=`${e}.setup`,p=(0,o.useMemo)(()=>i(document.documentElement.lang),[]);(0,o.useEffect)(()=>(d.current=!0,()=>{d.current=!1,n.remove(f)}),[t,n,f]);let m=!r&&n.isDirty();return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(`button`,{ref:u,type:`button`,"data-onboard-channel":e,disabled:r||m,onClick:()=>{n.isDirty()||(n.set(f,{value:!0,original:!1,valid:!1}),c(!0))},children:p(`onboarding.open`)}),m&&(0,s.jsx)(`p`,{className:`settings-field-hint`,children:`Save or discard your changes before opening setup.`}),r&&(0,s.jsx)(a,{channel:e,client:t,t:p,initialDraft:{},returnFocus:u.current,onBeforeSave:()=>async()=>{d.current&&(await l(),d.current&&n.remove(f))},onClose:()=>{n.remove(f),c(!1)}},e)]})}export{d as i,c as n,f as r,p as t};
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./react-C_pPTFsM.js";import{t as n}from"./jsx-runtime-NZYk81nU.js";import{a as r,i,n as a,r as o,t as s}from"./page-shell-BeGD0rRQ.js";import{a as c,n as l,o as u,s as d}from"./fields-mlGpofqQ.js";import{t as f}from"./path-utils-B6vBr0DD.js";import{n as p,r as m,t as h}from"./ChannelSetupEntry-CCrUYd2-.js";import{a as g,t as _}from"./ChannelEnablementControl-egwTtO9-.js";var v=e(t(),1),y=n(),b=[`messaging.enabledChannels`,`messaging.homeChannel`,`discord.enabled`,`discord.token`,`discord.guildId`,`discord.channelIds`,`discord.forwardAll`,`discord.allowBots`,`discord.mentionOnly`];function x(e){return e?/^\d{5,32}$/.test(e.trim()):!1}function S({port:e,client:t,dirty:n,registerSave:S}){let{state:w,refresh:T,setData:E}=r(t,`/api/settings`),[D,O]=(0,v.useState)(!1),[k,A]=(0,v.useState)([]),[j,M]=(0,v.useState)(`telegram`),[N,P]=(0,v.useState)(!1),[F,I]=(0,v.useState)(``),[L,R]=(0,v.useState)(``),[z,B]=(0,v.useState)([]),[V,H]=(0,v.useState)(!0),[U,W]=(0,v.useState)(!1),[G,K]=(0,v.useState)(!1);(0,v.useEffect)(()=>{if(w.kind!==`ready`)return;let e=w.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];A(t.filter(C)),M(C(e.homeChannel)?e.homeChannel:`telegram`);let n=w.data.discord||{};P(!!n.enabled),I(``),R(n.guildId??``),B(Array.isArray(n.channelIds)?[...n.channelIds]:[]),H(n.forwardAll!==!1),W(!!n.allowBots),K(!!n.mentionOnly)},[w]),(0,v.useEffect)(()=>()=>{for(let e of b)n.remove(e)},[n]);let q=(0,v.useCallback)((e,t)=>n.set(e,t),[n]),J=(0,v.useMemo)(()=>w.kind===`ready`&&w.data.discord||{},[w]),Y=(0,v.useCallback)(async()=>{if(D)throw Error(`Finish channel setup before saving settings.`);let e=n.saveBundle();if(Object.keys(e).length===0)return;let r=f(e),i=await t.put(`/api/settings`,r),a=i&&typeof i==`object`&&`data`in i?i.data:i;n.clear(),E(a);let o=a.messaging||{};A(Array.isArray(o.enabledChannels)?o.enabledChannels.filter(C):[]),M(C(o.homeChannel)?o.homeChannel:`telegram`);let s=a.discord||{};P(!!s.enabled),I(``),R(s.guildId??``),B(Array.isArray(s.channelIds)?[...s.channelIds]:[]),H(s.forwardAll!==!1),W(!!s.allowBots),K(!!s.mentionOnly),await T()},[t,n,T,E,D]);if((0,v.useEffect)(()=>{if(S)return S(Y),()=>S(null)},[S,Y]),w.kind===`loading`)return(0,y.jsx)(a,{});if(w.kind===`offline`)return(0,y.jsx)(o,{port:e});if(w.kind===`error`)return(0,y.jsx)(s,{message:w.message});let X=J.token?J.token.slice(-4):``,Z=J.token?`••••••••${X}`:`(empty)`,Q=L&&!x(L)?`Guild ID must be a numeric snowflake.`:null,$=z.filter(e=>!x(e)),ee=$.length>0?`Snowflake IDs only — invalid: ${$.join(`, `)}`:null;return(0,y.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),Y()},children:[(0,y.jsxs)(`fieldset`,{disabled:D,className:`settings-slack-fields`,children:[(0,y.jsxs)(i,{title:`Channels`,hint:`Choose which channels receive inbound chat. Outbound send can still work on any configured channel.`,children:[(0,y.jsx)(_,{pageChannel:`discord`,snapshot:w.kind===`ready`?w.data:{},enabledChannels:k,homeChannel:j,setEnabledChannels:A,setHomeChannel:M,dirty:n,idPrefix:`di-channel`}),(0,y.jsx)(g,{client:t,channel:`discord`})]}),(0,y.jsxs)(i,{title:`Discord`,hint:`Bot token, guild + channels, forwarding rules.`,children:[(0,y.jsx)(c,{id:`dc-enabled`,label:`Discord enabled`,value:N,onChange:e=>{P(e),q(`discord.enabled`,{value:e,original:!!J.enabled,valid:!0})}}),(0,y.jsx)(u,{id:`dc-token`,label:`Bot token`,value:F,placeholder:Z,onChange:e=>{if(I(e),e.length===0){n.remove(`discord.token`);return}q(`discord.token`,{value:e,original:J.token??``,valid:!0})}}),(0,y.jsx)(d,{id:`dc-guildId`,label:`Guild ID`,value:L,placeholder:`123456789012345678`,error:Q,onChange:e=>{R(e);let t=e.length===0||x(e);q(`discord.guildId`,{value:e,original:J.guildId??``,valid:t})}}),(0,y.jsx)(l,{id:`dc-channelIds`,label:`Channel IDs`,value:z,placeholder:`987654321098765432`,error:ee,onChange:e=>{B(e);let t=e.every(x);q(`discord.channelIds`,{value:e,original:J.channelIds??[],valid:t})}}),(0,y.jsx)(c,{id:`dc-forwardAll`,label:`Forward all`,value:V,onChange:e=>{H(e),q(`discord.forwardAll`,{value:e,original:J.forwardAll!==!1,valid:!0})}}),(0,y.jsx)(c,{id:`dc-allowBots`,label:`Allow other bots`,value:U,onChange:e=>{W(e),q(`discord.allowBots`,{value:e,original:!!J.allowBots,valid:!0})}}),(0,y.jsx)(c,{id:`dc-mentionOnly`,label:`Mention only`,value:G,onChange:e=>{K(e),q(`discord.mentionOnly`,{value:e,original:!!J.mentionOnly,valid:!0})}})]}),(0,y.jsx)(i,{title:`Health`,hint:`Probes /api/health for Discord readiness. Degraded mode means the bot is missing the MESSAGE_CONTENT intent (slash commands only).`,children:(0,y.jsx)(p,{client:t,label:`Discord`,endpoint:`/api/health`,method:`GET`,interpret:m})})]}),(0,y.jsx)(h,{channel:`discord`,client:t,dirty:n,open:D,onOpenChange:O,onSaved:async()=>E(await t.get(`/api/settings`))})]})}function C(e){return e===`telegram`||e===`discord`||e===`slack`}export{S as default,x as isValidSnowflake};
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./react-C_pPTFsM.js";import{t as n}from"./jsx-runtime-NZYk81nU.js";import{a as r,i,n as a,r as o,t as s}from"./page-shell-BeGD0rRQ.js";import{a as c,n as l,o as u,s as d}from"./fields-mlGpofqQ.js";import{t as f}from"./path-utils-B6vBr0DD.js";import{n as p,r as m,t as h}from"./ChannelSetupEntry-xvHkWzg1.js";import{a as g,t as _}from"./ChannelEnablementControl-8KNIMzHd.js";var v=e(t(),1),y=n(),b=[`messaging.enabledChannels`,`messaging.homeChannel`,`discord.enabled`,`discord.token`,`discord.guildId`,`discord.channelIds`,`discord.forwardAll`,`discord.allowBots`,`discord.mentionOnly`];function x(e){return e?/^\d{5,32}$/.test(e.trim()):!1}function S({port:e,client:t,dirty:n,registerSave:S}){let{state:w,refresh:T,setData:E}=r(t,`/api/settings`),[D,O]=(0,v.useState)(!1),[k,A]=(0,v.useState)([]),[j,M]=(0,v.useState)(`telegram`),[N,P]=(0,v.useState)(!1),[F,I]=(0,v.useState)(``),[L,R]=(0,v.useState)(``),[z,B]=(0,v.useState)([]),[V,H]=(0,v.useState)(!0),[U,W]=(0,v.useState)(!1),[G,K]=(0,v.useState)(!1);(0,v.useEffect)(()=>{if(w.kind!==`ready`)return;let e=w.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];A(t.filter(C)),M(C(e.homeChannel)?e.homeChannel:`telegram`);let n=w.data.discord||{};P(!!n.enabled),I(``),R(n.guildId??``),B(Array.isArray(n.channelIds)?[...n.channelIds]:[]),H(n.forwardAll!==!1),W(!!n.allowBots),K(!!n.mentionOnly)},[w]),(0,v.useEffect)(()=>()=>{for(let e of b)n.remove(e)},[n]);let q=(0,v.useCallback)((e,t)=>n.set(e,t),[n]),J=(0,v.useMemo)(()=>w.kind===`ready`&&w.data.discord||{},[w]),Y=(0,v.useCallback)(async()=>{if(D)throw Error(`Finish channel setup before saving settings.`);let e=n.saveBundle();if(Object.keys(e).length===0)return;let r=f(e),i=await t.put(`/api/settings`,r),a=i&&typeof i==`object`&&`data`in i?i.data:i;n.clear(),E(a);let o=a.messaging||{};A(Array.isArray(o.enabledChannels)?o.enabledChannels.filter(C):[]),M(C(o.homeChannel)?o.homeChannel:`telegram`);let s=a.discord||{};P(!!s.enabled),I(``),R(s.guildId??``),B(Array.isArray(s.channelIds)?[...s.channelIds]:[]),H(s.forwardAll!==!1),W(!!s.allowBots),K(!!s.mentionOnly),await T()},[t,n,T,E,D]);if((0,v.useEffect)(()=>{if(S)return S(Y),()=>S(null)},[S,Y]),w.kind===`loading`)return(0,y.jsx)(a,{});if(w.kind===`offline`)return(0,y.jsx)(o,{port:e});if(w.kind===`error`)return(0,y.jsx)(s,{message:w.message});let X=J.token?J.token.slice(-4):``,Z=J.token?`••••••••${X}`:`(empty)`,Q=L&&!x(L)?`Guild ID must be a numeric snowflake.`:null,$=z.filter(e=>!x(e)),ee=$.length>0?`Snowflake IDs only — invalid: ${$.join(`, `)}`:null;return(0,y.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),Y()},children:[(0,y.jsxs)(`fieldset`,{disabled:D,className:`settings-slack-fields`,children:[(0,y.jsxs)(i,{title:`Channels`,hint:`Choose which channels receive inbound chat. Outbound send can still work on any configured channel.`,children:[(0,y.jsx)(_,{pageChannel:`discord`,snapshot:w.kind===`ready`?w.data:{},enabledChannels:k,homeChannel:j,setEnabledChannels:A,setHomeChannel:M,dirty:n,idPrefix:`di-channel`}),(0,y.jsx)(g,{client:t,channel:`discord`})]}),(0,y.jsxs)(i,{title:`Discord`,hint:`Bot token, guild + channels, forwarding rules.`,children:[(0,y.jsx)(c,{id:`dc-enabled`,label:`Discord enabled`,value:N,onChange:e=>{P(e),q(`discord.enabled`,{value:e,original:!!J.enabled,valid:!0})}}),(0,y.jsx)(u,{id:`dc-token`,label:`Bot token`,value:F,placeholder:Z,onChange:e=>{if(I(e),e.length===0){n.remove(`discord.token`);return}q(`discord.token`,{value:e,original:J.token??``,valid:!0})}}),(0,y.jsx)(d,{id:`dc-guildId`,label:`Guild ID`,value:L,placeholder:`123456789012345678`,error:Q,onChange:e=>{R(e);let t=e.length===0||x(e);q(`discord.guildId`,{value:e,original:J.guildId??``,valid:t})}}),(0,y.jsx)(l,{id:`dc-channelIds`,label:`Channel IDs`,value:z,placeholder:`987654321098765432`,error:ee,onChange:e=>{B(e);let t=e.every(x);q(`discord.channelIds`,{value:e,original:J.channelIds??[],valid:t})}}),(0,y.jsx)(c,{id:`dc-forwardAll`,label:`Forward all`,value:V,onChange:e=>{H(e),q(`discord.forwardAll`,{value:e,original:J.forwardAll!==!1,valid:!0})}}),(0,y.jsx)(c,{id:`dc-allowBots`,label:`Allow other bots`,value:U,onChange:e=>{W(e),q(`discord.allowBots`,{value:e,original:!!J.allowBots,valid:!0})}}),(0,y.jsx)(c,{id:`dc-mentionOnly`,label:`Mention only`,value:G,onChange:e=>{K(e),q(`discord.mentionOnly`,{value:e,original:!!J.mentionOnly,valid:!0})}})]}),(0,y.jsx)(i,{title:`Health`,hint:`Probes /api/health for Discord readiness. Degraded mode means the bot is missing the MESSAGE_CONTENT intent (slash commands only).`,children:(0,y.jsx)(p,{client:t,label:`Discord`,endpoint:`/api/health`,method:`GET`,interpret:m})})]}),(0,y.jsx)(h,{channel:`discord`,client:t,dirty:n,open:D,onOpenChange:O,onSaved:async()=>E(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{t}from"./react-C_pPTFsM.js";import{t as n}from"./jsx-runtime-NZYk81nU.js";import{t as r}from"./settings-client-CmwRsVd1.js";import{a as i,i as a,n as o,r as s,t as c}from"./page-shell-BeGD0rRQ.js";import{a as l,n as ee,o as u,s as te}from"./fields-mlGpofqQ.js";import{t as ne}from"./path-utils-B6vBr0DD.js";import{a as re,i as ie,r as ae,t as oe}from"./ChannelEnablementControl-egwTtO9-.js";function se(e){return e.trim().length>0}function d(e){return e.trim().startsWith(`xoxb-`)}function f(e){return e.trim().startsWith(`xapp-`)}var p=e(t(),1),m=n(),h=[`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 g(e){return e?/^[CGD][A-Z0-9]{6,20}$/.test(e.trim().toUpperCase()):!1}var _=[`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`,`slack.channelIds`,`slack.attachPort`],v=`slack.setup`,ce=[`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`];function le(e){return e&&typeof e==`object`&&`data`in e?e.data:e}function ue(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 y({port:e,client:t,dirty:n,registerSave:y,manager:fe}){let b=(0,p.useMemo)(()=>ie(fe?.ui.locale??document.documentElement.lang),[fe?.ui.locale]),[pe,x]=(0,p.useState)(``),[S,me]=(0,p.useState)(!1),C=(0,p.useRef)(!1),w=(0,p.useRef)(0),he=(0,p.useRef)(null),[T,E]=(0,p.useState)(!1),[D,O]=(0,p.useState)(null),[ge,k]=(0,p.useState)(0),A=(0,p.useRef)(!1),j=(0,p.useRef)(!1),M=(0,p.useRef)({}),[_e,N]=(0,p.useState)(!1),[ve,P]=(0,p.useState)(!1);(0,p.useLayoutEffect)(()=>(j.current=!0,M.current={},()=>{j.current=!1,M.current={},++w.current}),[e,t]);let{state:F,refresh:I,setData:L}=i(t,`/api/settings`),[ye,R]=(0,p.useState)([]),[be,z]=(0,p.useState)(`telegram`),[xe,Se]=(0,p.useState)(!1),[B,V]=(0,p.useState)(``),[H,U]=(0,p.useState)(``),[Ce,we]=(0,p.useState)(``),[W,Te]=(0,p.useState)([]),[Ee,De]=(0,p.useState)(!0),[Oe,ke]=(0,p.useState)(!1),[Ae,je]=(0,p.useState)(!0),[Me,Ne]=(0,p.useState)(!0),[Pe,Fe]=(0,p.useState)(!1),G=(0,p.useCallback)(e=>{let t=Object.fromEntries([...n.pending].filter(([e])=>e.startsWith(`slack.`)&&e!==v).map(([e,t])=>[e,t.value])),r=ne(t).slack;e={...e,...r,ack:{...e.ack,...r?.ack}},x(e.attachPort??``),Se(!!e.enabled),V(String(n.pending.get(`slack.botToken`)?.value??``)),U(String(n.pending.get(`slack.appToken`)?.value??``)),we(e.teamId??``),Te(Array.isArray(e.channelIds)?[...e.channelIds]:[]),De(e.forwardAll!==!1),ke(!!e.allowBots),je(e.mentionOnly!==!1),Ne(e.replyInThread!==!1),Fe(!!e.ack?.enabled)},[n]);(0,p.useEffect)(()=>{if(F.kind!==`ready`)return;let e=F.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];R(t.filter(de)),z(de(e.homeChannel)?e.homeChannel:`telegram`),G(F.data.slack||{})},[F,G]),(0,p.useEffect)(()=>()=>{for(let e of h)n.remove(e)},[n]);let K=(0,p.useCallback)((e,t)=>n.set(e,t),[n]),q=(0,p.useMemo)(()=>F.kind===`ready`&&F.data.slack||{},[F]),J=F.kind===`ready`&&Array.isArray(F.data.slackEnvironmentVariables)?F.data.slackEnvironmentVariables:[],Y=J.length>0,X=(0,p.useRef)({environmentManaged:Y,environmentVariables:J,t:b});(0,p.useLayoutEffect)(()=>{X.current={environmentManaged:Y,environmentVariables:J,t:b}},[Y,J,b]);let Z=(0,p.useCallback)(async()=>{let e=X.current;if(A.current||C.current)throw Error(e.t(`settings.slack.resetFailed`));let r=n.saveBundle();if(Object.keys(r).length===0)return;if(e.environmentManaged&&_.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])=>h.includes(e)||e.startsWith(`messaging.`))),a=new Map([...n.pending].filter(([e])=>e in i)),o=M.current,s=ne(i),c=await t.put(`/api/settings`,s),l=c&&typeof c==`object`&&`data`in c?c.data:c;j.current&&o===M.current&&(Q(a),L(l),G(l.slack||{}),await I())},[t,n,I,L,G]);(0,p.useEffect)(()=>{if(y)return y(Z),()=>y(null)},[y,Z]);function Q(e){for(let[t,r]of e)n.pending.get(t)===r&&n.remove(t)}function Ie(){X.current.environmentManaged||A.current||C.current||(he.current=document.activeElement instanceof HTMLElement?document.activeElement:null,++w.current,C.current=!0,n.set(v,{value:!0,original:!1,valid:!1}),me(!0))}function Le(){++w.current,C.current=!1,me(!1),n.remove(v)}(0,p.useEffect)(()=>()=>{++w.current,C.current=!1,n.remove(v)},[n]);function Re(){let e=w.current,r=new Map([...n.pending].filter(([e])=>ce.includes(e)||e===v));return async()=>{if(!j.current||!C.current||e!==w.current)return;let n=le(await t.get(`/api/settings`));j.current&&C.current&&e===w.current&&(Q(r),L(n),k(e=>e+1))}}async function ze(){if(A.current)return;if(Y){O(b(`settings.slack.resetManagedByEnvironment`,{variables:J.join(`, `)}));return}if(!B.trim()&&!H.trim()&&!q.botToken&&!q.appToken){O(b(`settings.slack.resetEmpty`));return}if(!window.confirm(b(`settings.slack.resetConfirm`)))return;let e=new Map([...n.pending].filter(([e])=>_.includes(e))),i=M.current;A.current=!0,E(!0),O(null);let a=null;try{try{await t.post(`/api/settings/slack/reset`,{})}catch(e){if(e instanceof r&&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=le(await t.get(`/api/settings`));if(!j.current||i!==M.current)return;let s=a??o.slackEnvironmentVariables??[];if(s.length){for(let e of _)n.remove(e);L({...o,slackEnvironmentVariables:s}),O(b(`settings.slack.resetManagedByEnvironment`,{variables:s.join(`, `)}));return}if(!ue(o)){O(b(`settings.slack.resetFailed`));return}Q(e),V(``),U(``),N(!1),P(!1),L(o)}catch{j.current&&i===M.current&&O(b(`settings.slack.resetFailed`))}finally{A.current=!1,j.current&&i===M.current&&(E(!1),k(e=>e+1))}}if(F.kind===`loading`)return(0,m.jsx)(o,{});if(F.kind===`offline`)return(0,m.jsx)(s,{port:e});if(F.kind===`error`)return(0,m.jsx)(c,{message:F.message});let Be=e=>e?`••••••••${e.slice(-4)}`:`(empty)`,$=W.filter(e=>!g(e)),Ve=$.length>0?`Slack conversation IDs only (C…/G…/D…) — invalid: ${$.join(`, `)}`:null,He=_e&&B.trim()&&!d(B)?b(`settings.slack.guide.botTokenError`):null,Ue=ve&&H.trim()&&!f(H)?b(`settings.slack.guide.appTokenError`):null,We=!!q.enabled&&!!q.botToken&&!q.appToken,Ge=Y?`Connection settings are read-only because they are managed by environment variables: ${J.join(`, `)}.`:We?`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,m.jsxs)(`form`,{className:`settings-page-form`,onBlurCapture:e=>{let t=e.target.id;t===`sl-botToken`&&N(!0),t===`sl-appToken`&&P(!0)},onSubmit:e=>{e.preventDefault(),Z().catch(()=>O(b(`settings.slack.resetFailed`)))},children:[(0,m.jsxs)(`fieldset`,{disabled:T||S,className:`settings-slack-fields`,children:[(0,m.jsxs)(a,{title:`Channels`,hint:`Choose which channels receive inbound chat. Outbound send can still work on any configured channel.`,children:[(0,m.jsx)(oe,{pageChannel:`slack`,snapshot:F.kind===`ready`?F.data:{},enabledChannels:ye,homeChannel:be,setEnabledChannels:R,setHomeChannel:z,dirty:n,idPrefix:`sl-channel`}),(0,m.jsx)(re,{client:t,channel:`slack`},ge)]}),(0,m.jsxs)(a,{title:`Slack`,hint:Ge,children:[(0,m.jsx)(l,{id:`sl-enabled`,label:`Slack enabled`,value:xe,disabled:Y,onChange:e=>{Se(e),K(`slack.enabled`,{value:e,original:!!q.enabled,valid:!0}),e&&!Y&&!se(B||q.botToken||``)&&Ie()}}),(0,m.jsx)(u,{id:`sl-botToken`,label:`Bot token`,value:B,placeholder:Be(q.botToken),error:He,disabled:Y,onChange:e=>{if(V(e),e.trim().length===0){n.remove(`slack.botToken`);return}K(`slack.botToken`,{value:e.trim(),original:q.botToken??``,valid:d(e)})}}),(0,m.jsx)(u,{id:`sl-appToken`,label:`App-level token`,value:H,placeholder:Be(q.appToken),error:Ue,disabled:Y,onChange:e=>{if(U(e),e.trim().length===0){n.remove(`slack.appToken`);return}K(`slack.appToken`,{value:e.trim(),original:q.appToken??``,valid:f(e)})}}),(0,m.jsx)(te,{id:`sl-teamId`,label:`Team ID`,value:Ce,placeholder:`T01234567 (optional)`,disabled:Y,onChange:e=>{we(e),K(`slack.teamId`,{value:e,original:q.teamId??``,valid:!0})}}),(0,m.jsx)(ee,{id:`sl-channelIds`,label:`Channel IDs`,value:W,placeholder:`C01234567`,error:Ve,disabled:Y,onChange:e=>{Te(e),K(`slack.channelIds`,{value:e,original:q.channelIds??[],valid:e.every(g)})}}),(0,m.jsx)(te,{id:`sl-attachPort`,label:b(`settings.slack.attachPort`),value:pe,disabled:Y||T||S,onChange:e=>{x(e),K(`slack.attachPort`,{value:e.trim(),original:q.attachPort??``,valid:!0})}}),(0,m.jsx)(`button`,{type:`button`,disabled:Y||T||S,"data-onboard-channel":`slack`,onClick:Ie,children:b(`onboarding.open`)}),(0,m.jsx)(`button`,{type:`button`,disabled:Y||T||S,onClick:()=>void ze(),children:b(`settings.slack.resetConnection`)}),D&&(0,m.jsx)(`p`,{role:`alert`,children:D}),(0,m.jsx)(l,{id:`sl-mentionOnly`,label:`Mention only`,value:Ae,onChange:e=>{je(e),K(`slack.mentionOnly`,{value:e,original:q.mentionOnly!==!1,valid:!0})}}),(0,m.jsx)(l,{id:`sl-replyInThread`,label:`Reply in thread`,value:Me,onChange:e=>{Ne(e),K(`slack.replyInThread`,{value:e,original:q.replyInThread!==!1,valid:!0})}}),(0,m.jsx)(l,{id:`sl-forwardAll`,label:`Forward all`,value:Ee,onChange:e=>{De(e),K(`slack.forwardAll`,{value:e,original:q.forwardAll!==!1,valid:!0})}}),(0,m.jsx)(l,{id:`sl-allowBots`,label:`Allow bots`,value:Oe,onChange:e=>{ke(e),K(`slack.allowBots`,{value:e,original:!!q.allowBots,valid:!0})}}),(0,m.jsx)(l,{id:`sl-ackEnabled`,label:`Emoji reactions (👀 → ✅)`,value:Pe,onChange:e=>{Fe(e),K(`slack.ack.enabled`,{value:e,original:!!q.ack?.enabled,valid:!0})}})]})]}),S&&(0,m.jsx)(ae,{client:t,t:b,initialDraft:{botToken:B,appToken:H},returnFocus:he.current,onBeforeSave:Re,onClose:Le},e)]})}function de(e){return e===`telegram`||e===`discord`||e===`slack`}export{y as default,g as isValidSlackConversationId};
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./react-C_pPTFsM.js";import{t as n}from"./jsx-runtime-NZYk81nU.js";import{t as r}from"./settings-client-CmwRsVd1.js";import{a as i,i as a,n as o,r as s,t as c}from"./page-shell-BeGD0rRQ.js";import{a as l,n as ee,o as u,s as te}from"./fields-mlGpofqQ.js";import{t as ne}from"./path-utils-B6vBr0DD.js";import{a as re,i as ie,r as ae,t as oe}from"./ChannelEnablementControl-8KNIMzHd.js";function se(e){return e.trim().length>0}function d(e){return e.trim().startsWith(`xoxb-`)}function f(e){return e.trim().startsWith(`xapp-`)}var p=e(t(),1),m=n(),h=[`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 g(e){return e?/^[CGD][A-Z0-9]{6,20}$/.test(e.trim().toUpperCase()):!1}var _=[`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`,`slack.channelIds`,`slack.attachPort`],v=`slack.setup`,ce=[`slack.enabled`,`slack.botToken`,`slack.appToken`,`slack.teamId`];function le(e){return e&&typeof e==`object`&&`data`in e?e.data:e}function ue(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 y({port:e,client:t,dirty:n,registerSave:y,manager:fe}){let b=(0,p.useMemo)(()=>ie(fe?.ui.locale??document.documentElement.lang),[fe?.ui.locale]),[pe,x]=(0,p.useState)(``),[S,me]=(0,p.useState)(!1),C=(0,p.useRef)(!1),w=(0,p.useRef)(0),he=(0,p.useRef)(null),[T,E]=(0,p.useState)(!1),[D,O]=(0,p.useState)(null),[ge,k]=(0,p.useState)(0),A=(0,p.useRef)(!1),j=(0,p.useRef)(!1),M=(0,p.useRef)({}),[_e,N]=(0,p.useState)(!1),[ve,P]=(0,p.useState)(!1);(0,p.useLayoutEffect)(()=>(j.current=!0,M.current={},()=>{j.current=!1,M.current={},++w.current}),[e,t]);let{state:F,refresh:I,setData:L}=i(t,`/api/settings`),[ye,R]=(0,p.useState)([]),[be,z]=(0,p.useState)(`telegram`),[xe,Se]=(0,p.useState)(!1),[B,V]=(0,p.useState)(``),[H,U]=(0,p.useState)(``),[Ce,we]=(0,p.useState)(``),[W,Te]=(0,p.useState)([]),[Ee,De]=(0,p.useState)(!0),[Oe,ke]=(0,p.useState)(!1),[Ae,je]=(0,p.useState)(!0),[Me,Ne]=(0,p.useState)(!0),[Pe,Fe]=(0,p.useState)(!1),G=(0,p.useCallback)(e=>{let t=Object.fromEntries([...n.pending].filter(([e])=>e.startsWith(`slack.`)&&e!==v).map(([e,t])=>[e,t.value])),r=ne(t).slack;e={...e,...r,ack:{...e.ack,...r?.ack}},x(e.attachPort??``),Se(!!e.enabled),V(String(n.pending.get(`slack.botToken`)?.value??``)),U(String(n.pending.get(`slack.appToken`)?.value??``)),we(e.teamId??``),Te(Array.isArray(e.channelIds)?[...e.channelIds]:[]),De(e.forwardAll!==!1),ke(!!e.allowBots),je(e.mentionOnly!==!1),Ne(e.replyInThread!==!1),Fe(!!e.ack?.enabled)},[n]);(0,p.useEffect)(()=>{if(F.kind!==`ready`)return;let e=F.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];R(t.filter(de)),z(de(e.homeChannel)?e.homeChannel:`telegram`),G(F.data.slack||{})},[F,G]),(0,p.useEffect)(()=>()=>{for(let e of h)n.remove(e)},[n]);let K=(0,p.useCallback)((e,t)=>n.set(e,t),[n]),q=(0,p.useMemo)(()=>F.kind===`ready`&&F.data.slack||{},[F]),J=F.kind===`ready`&&Array.isArray(F.data.slackEnvironmentVariables)?F.data.slackEnvironmentVariables:[],Y=J.length>0,X=(0,p.useRef)({environmentManaged:Y,environmentVariables:J,t:b});(0,p.useLayoutEffect)(()=>{X.current={environmentManaged:Y,environmentVariables:J,t:b}},[Y,J,b]);let Z=(0,p.useCallback)(async()=>{let e=X.current;if(A.current||C.current)throw Error(e.t(`settings.slack.resetFailed`));let r=n.saveBundle();if(Object.keys(r).length===0)return;if(e.environmentManaged&&_.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])=>h.includes(e)||e.startsWith(`messaging.`))),a=new Map([...n.pending].filter(([e])=>e in i)),o=M.current,s=ne(i),c=await t.put(`/api/settings`,s),l=c&&typeof c==`object`&&`data`in c?c.data:c;j.current&&o===M.current&&(Q(a),L(l),G(l.slack||{}),await I())},[t,n,I,L,G]);(0,p.useEffect)(()=>{if(y)return y(Z),()=>y(null)},[y,Z]);function Q(e){for(let[t,r]of e)n.pending.get(t)===r&&n.remove(t)}function Ie(){X.current.environmentManaged||A.current||C.current||(he.current=document.activeElement instanceof HTMLElement?document.activeElement:null,++w.current,C.current=!0,n.set(v,{value:!0,original:!1,valid:!1}),me(!0))}function Le(){++w.current,C.current=!1,me(!1),n.remove(v)}(0,p.useEffect)(()=>()=>{++w.current,C.current=!1,n.remove(v)},[n]);function Re(){let e=w.current,r=new Map([...n.pending].filter(([e])=>ce.includes(e)||e===v));return async()=>{if(!j.current||!C.current||e!==w.current)return;let n=le(await t.get(`/api/settings`));j.current&&C.current&&e===w.current&&(Q(r),L(n),k(e=>e+1))}}async function ze(){if(A.current)return;if(Y){O(b(`settings.slack.resetManagedByEnvironment`,{variables:J.join(`, `)}));return}if(!B.trim()&&!H.trim()&&!q.botToken&&!q.appToken){O(b(`settings.slack.resetEmpty`));return}if(!window.confirm(b(`settings.slack.resetConfirm`)))return;let e=new Map([...n.pending].filter(([e])=>_.includes(e))),i=M.current;A.current=!0,E(!0),O(null);let a=null;try{try{await t.post(`/api/settings/slack/reset`,{})}catch(e){if(e instanceof r&&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=le(await t.get(`/api/settings`));if(!j.current||i!==M.current)return;let s=a??o.slackEnvironmentVariables??[];if(s.length){for(let e of _)n.remove(e);L({...o,slackEnvironmentVariables:s}),O(b(`settings.slack.resetManagedByEnvironment`,{variables:s.join(`, `)}));return}if(!ue(o)){O(b(`settings.slack.resetFailed`));return}Q(e),V(``),U(``),N(!1),P(!1),L(o)}catch{j.current&&i===M.current&&O(b(`settings.slack.resetFailed`))}finally{A.current=!1,j.current&&i===M.current&&(E(!1),k(e=>e+1))}}if(F.kind===`loading`)return(0,m.jsx)(o,{});if(F.kind===`offline`)return(0,m.jsx)(s,{port:e});if(F.kind===`error`)return(0,m.jsx)(c,{message:F.message});let Be=e=>e?`••••••••${e.slice(-4)}`:`(empty)`,$=W.filter(e=>!g(e)),Ve=$.length>0?`Slack conversation IDs only (C…/G…/D…) — invalid: ${$.join(`, `)}`:null,He=_e&&B.trim()&&!d(B)?b(`settings.slack.guide.botTokenError`):null,Ue=ve&&H.trim()&&!f(H)?b(`settings.slack.guide.appTokenError`):null,We=!!q.enabled&&!!q.botToken&&!q.appToken,Ge=Y?`Connection settings are read-only because they are managed by environment variables: ${J.join(`, `)}.`:We?`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,m.jsxs)(`form`,{className:`settings-page-form`,onBlurCapture:e=>{let t=e.target.id;t===`sl-botToken`&&N(!0),t===`sl-appToken`&&P(!0)},onSubmit:e=>{e.preventDefault(),Z().catch(()=>O(b(`settings.slack.resetFailed`)))},children:[(0,m.jsxs)(`fieldset`,{disabled:T||S,className:`settings-slack-fields`,children:[(0,m.jsxs)(a,{title:`Channels`,hint:`Choose which channels receive inbound chat. Outbound send can still work on any configured channel.`,children:[(0,m.jsx)(oe,{pageChannel:`slack`,snapshot:F.kind===`ready`?F.data:{},enabledChannels:ye,homeChannel:be,setEnabledChannels:R,setHomeChannel:z,dirty:n,idPrefix:`sl-channel`}),(0,m.jsx)(re,{client:t,channel:`slack`},ge)]}),(0,m.jsxs)(a,{title:`Slack`,hint:Ge,children:[(0,m.jsx)(l,{id:`sl-enabled`,label:`Slack enabled`,value:xe,disabled:Y,onChange:e=>{Se(e),K(`slack.enabled`,{value:e,original:!!q.enabled,valid:!0}),e&&!Y&&!se(B||q.botToken||``)&&Ie()}}),(0,m.jsx)(u,{id:`sl-botToken`,label:`Bot token`,value:B,placeholder:Be(q.botToken),error:He,disabled:Y,onChange:e=>{if(V(e),e.trim().length===0){n.remove(`slack.botToken`);return}K(`slack.botToken`,{value:e.trim(),original:q.botToken??``,valid:d(e)})}}),(0,m.jsx)(u,{id:`sl-appToken`,label:`App-level token`,value:H,placeholder:Be(q.appToken),error:Ue,disabled:Y,onChange:e=>{if(U(e),e.trim().length===0){n.remove(`slack.appToken`);return}K(`slack.appToken`,{value:e.trim(),original:q.appToken??``,valid:f(e)})}}),(0,m.jsx)(te,{id:`sl-teamId`,label:`Team ID`,value:Ce,placeholder:`T01234567 (optional)`,disabled:Y,onChange:e=>{we(e),K(`slack.teamId`,{value:e,original:q.teamId??``,valid:!0})}}),(0,m.jsx)(ee,{id:`sl-channelIds`,label:`Channel IDs`,value:W,placeholder:`C01234567`,error:Ve,disabled:Y,onChange:e=>{Te(e),K(`slack.channelIds`,{value:e,original:q.channelIds??[],valid:e.every(g)})}}),(0,m.jsx)(te,{id:`sl-attachPort`,label:b(`settings.slack.attachPort`),value:pe,disabled:Y||T||S,onChange:e=>{x(e),K(`slack.attachPort`,{value:e.trim(),original:q.attachPort??``,valid:!0})}}),(0,m.jsx)(`button`,{type:`button`,disabled:Y||T||S,"data-onboard-channel":`slack`,onClick:Ie,children:b(`onboarding.open`)}),(0,m.jsx)(`button`,{type:`button`,disabled:Y||T||S,onClick:()=>void ze(),children:b(`settings.slack.resetConnection`)}),D&&(0,m.jsx)(`p`,{role:`alert`,children:D}),(0,m.jsx)(l,{id:`sl-mentionOnly`,label:`Mention only`,value:Ae,onChange:e=>{je(e),K(`slack.mentionOnly`,{value:e,original:q.mentionOnly!==!1,valid:!0})}}),(0,m.jsx)(l,{id:`sl-replyInThread`,label:`Reply in thread`,value:Me,onChange:e=>{Ne(e),K(`slack.replyInThread`,{value:e,original:q.replyInThread!==!1,valid:!0})}}),(0,m.jsx)(l,{id:`sl-forwardAll`,label:`Forward all`,value:Ee,onChange:e=>{De(e),K(`slack.forwardAll`,{value:e,original:q.forwardAll!==!1,valid:!0})}}),(0,m.jsx)(l,{id:`sl-allowBots`,label:`Allow bots`,value:Oe,onChange:e=>{ke(e),K(`slack.allowBots`,{value:e,original:!!q.allowBots,valid:!0})}}),(0,m.jsx)(l,{id:`sl-ackEnabled`,label:`Emoji reactions (👀 → ✅)`,value:Pe,onChange:e=>{Fe(e),K(`slack.ack.enabled`,{value:e,original:!!q.ack?.enabled,valid:!0})}})]})]}),S&&(0,m.jsx)(ae,{client:t,t:b,initialDraft:{botToken:B,appToken:H},returnFocus:he.current,onBeforeSave:Re,onClose:Le},e)]})}function de(e){return e===`telegram`||e===`discord`||e===`slack`}export{y as default,g as isValidSlackConversationId};
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./react-C_pPTFsM.js";import{t as n}from"./jsx-runtime-NZYk81nU.js";import{a as r,i,n as a,r as o,t as s}from"./page-shell-BeGD0rRQ.js";import{a as c,n as l,o as u}from"./fields-mlGpofqQ.js";import{t as d}from"./path-utils-B6vBr0DD.js";import{i as f,n as p,t as m}from"./ChannelSetupEntry-CCrUYd2-.js";import{a as h,t as g}from"./ChannelEnablementControl-egwTtO9-.js";var _=e(t(),1),v=n(),y=[`messaging.enabledChannels`,`messaging.homeChannel`,`telegram.enabled`,`telegram.token`,`telegram.allowedChatIds`,`telegram.forwardAll`,`telegram.mentionOnly`];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}){let{state:E,refresh:D,setData:O}=r(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)(!0),[U,W]=(0,_.useState)(!0);(0,_.useEffect)(()=>{if(E.kind!==`ready`)return;let e=E.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];M(t.filter(T)),P(T(e.homeChannel)?e.homeChannel:`telegram`);let n=E.data.telegram||{};I(!!n.enabled),R(``),B(S(n.allowedChatIds)),H(n.forwardAll!==!1),W(n.mentionOnly!==!1)},[E]),(0,_.useEffect)(()=>()=>{for(let e of y)n.remove(e)},[n]);let G=(0,_.useCallback)((e,t)=>n.set(e,t),[n]),K=(0,_.useMemo)(()=>E.kind===`ready`&&E.data.telegram||{},[E]),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=d(e),i=await t.put(`/api/settings`,r),a=i&&typeof i==`object`&&`data`in i?i.data:i;n.clear(),O(a);let o=a.messaging||{};M(Array.isArray(o.enabledChannels)?o.enabledChannels.filter(T):[]),P(T(o.homeChannel)?o.homeChannel:`telegram`);let s=a.telegram||{};I(!!s.enabled),R(``),B(S(s.allowedChatIds)),H(s.forwardAll!==!1),W(s.mentionOnly!==!1),await D()},[t,n,D,O,k]);if((0,_.useEffect)(()=>{if(w)return w(q),()=>w(null)},[w,q]),E.kind===`loading`)return(0,v.jsx)(a,{});if(E.kind===`offline`)return(0,v.jsx)(o,{port:e});if(E.kind===`error`)return(0,v.jsx)(s,{message:E.message});let J=K.token?K.token.slice(-4):``,Y=K.token?`••••••••${J}`:`(empty)`,{invalid:X}=x(z),Z=X.length>0?`Numeric chat IDs only — invalid: ${X.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)(i,{title:`Channels`,hint:`Choose which channels receive inbound chat. Outbound send can still work on any configured channel.`,children:[(0,v.jsx)(g,{pageChannel:`telegram`,snapshot:E.kind===`ready`?E.data:{},enabledChannels:j,homeChannel:N,setEnabledChannels:M,setHomeChannel:P,dirty:n,idPrefix:`tg-channel`}),(0,v.jsx)(h,{client:t,channel:`telegram`})]}),(0,v.jsxs)(i,{title:`Telegram`,hint:`Bot token, allow-list, and forwarding rules.`,children:[(0,v.jsx)(c,{id:`tg-enabled`,label:`Telegram enabled`,value:F,onChange:e=>{I(e),G(`telegram.enabled`,{value:e,original:!!K.enabled,valid:!0})}}),(0,v.jsx)(u,{id:`tg-token`,label:`Bot token`,value:L,placeholder:Y,onChange:e=>{if(R(e),e.length===0){n.remove(`telegram.token`);return}G(`telegram.token`,{value:e,original:K.token??``,valid:!0})}}),(0,v.jsx)(l,{id:`tg-allowedChatIds`,label:`Allowed chat IDs`,value:z,placeholder:`123456789`,error:Z,onChange:e=>{B(e);let t=e.every(b);G(`telegram.allowedChatIds`,{value:C(e),original:K.allowedChatIds??[],valid:t})}}),(0,v.jsx)(c,{id:`tg-forwardAll`,label:`Forward all responses`,value:V,onChange:e=>{H(e),G(`telegram.forwardAll`,{value:e,original:K.forwardAll!==!1,valid:!0})}}),(0,v.jsx)(c,{id:`tg-mentionOnly`,label:`Mention only`,value:U,onChange:e=>{W(e),G(`telegram.mentionOnly`,{value:e,original:K.mentionOnly!==!1,valid:!0})}})]}),(0,v.jsx)(i,{title:`Health`,hint:`Probe the bot to confirm token + connectivity. 404 means the instance hasn't shipped the probe endpoint yet.`,children:(0,v.jsx)(p,{client:t,label:`Telegram`,endpoint:`/api/telegram/probe`,method:`POST`,interpret:f})})]}),(0,v.jsx)(m,{channel:`telegram`,client:t,dirty:n,open:k,onOpenChange:A,onSaved:async()=>O(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
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./react-C_pPTFsM.js";import{t as n}from"./jsx-runtime-NZYk81nU.js";import{a as r,i,n as a,r as o,t as s}from"./page-shell-BeGD0rRQ.js";import{a as c,n as l,o as u}from"./fields-mlGpofqQ.js";import{t as d}from"./path-utils-B6vBr0DD.js";import{i as f,n as p,t as m}from"./ChannelSetupEntry-xvHkWzg1.js";import{a as h,t as g}from"./ChannelEnablementControl-8KNIMzHd.js";var _=e(t(),1),v=n(),y=[`messaging.enabledChannels`,`messaging.homeChannel`,`telegram.enabled`,`telegram.token`,`telegram.allowedChatIds`,`telegram.forwardAll`,`telegram.mentionOnly`];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}){let{state:E,refresh:D,setData:O}=r(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)(!0),[U,W]=(0,_.useState)(!0);(0,_.useEffect)(()=>{if(E.kind!==`ready`)return;let e=E.data.messaging||{},t=Array.isArray(e.enabledChannels)?e.enabledChannels:[];M(t.filter(T)),P(T(e.homeChannel)?e.homeChannel:`telegram`);let n=E.data.telegram||{};I(!!n.enabled),R(``),B(S(n.allowedChatIds)),H(n.forwardAll!==!1),W(n.mentionOnly!==!1)},[E]),(0,_.useEffect)(()=>()=>{for(let e of y)n.remove(e)},[n]);let G=(0,_.useCallback)((e,t)=>n.set(e,t),[n]),K=(0,_.useMemo)(()=>E.kind===`ready`&&E.data.telegram||{},[E]),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=d(e),i=await t.put(`/api/settings`,r),a=i&&typeof i==`object`&&`data`in i?i.data:i;n.clear(),O(a);let o=a.messaging||{};M(Array.isArray(o.enabledChannels)?o.enabledChannels.filter(T):[]),P(T(o.homeChannel)?o.homeChannel:`telegram`);let s=a.telegram||{};I(!!s.enabled),R(``),B(S(s.allowedChatIds)),H(s.forwardAll!==!1),W(s.mentionOnly!==!1),await D()},[t,n,D,O,k]);if((0,_.useEffect)(()=>{if(w)return w(q),()=>w(null)},[w,q]),E.kind===`loading`)return(0,v.jsx)(a,{});if(E.kind===`offline`)return(0,v.jsx)(o,{port:e});if(E.kind===`error`)return(0,v.jsx)(s,{message:E.message});let J=K.token?K.token.slice(-4):``,Y=K.token?`••••••••${J}`:`(empty)`,{invalid:X}=x(z),Z=X.length>0?`Numeric chat IDs only — invalid: ${X.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)(i,{title:`Channels`,hint:`Choose which channels receive inbound chat. Outbound send can still work on any configured channel.`,children:[(0,v.jsx)(g,{pageChannel:`telegram`,snapshot:E.kind===`ready`?E.data:{},enabledChannels:j,homeChannel:N,setEnabledChannels:M,setHomeChannel:P,dirty:n,idPrefix:`tg-channel`}),(0,v.jsx)(h,{client:t,channel:`telegram`})]}),(0,v.jsxs)(i,{title:`Telegram`,hint:`Bot token, allow-list, and forwarding rules.`,children:[(0,v.jsx)(c,{id:`tg-enabled`,label:`Telegram enabled`,value:F,onChange:e=>{I(e),G(`telegram.enabled`,{value:e,original:!!K.enabled,valid:!0})}}),(0,v.jsx)(u,{id:`tg-token`,label:`Bot token`,value:L,placeholder:Y,onChange:e=>{if(R(e),e.length===0){n.remove(`telegram.token`);return}G(`telegram.token`,{value:e,original:K.token??``,valid:!0})}}),(0,v.jsx)(l,{id:`tg-allowedChatIds`,label:`Allowed chat IDs`,value:z,placeholder:`123456789`,error:Z,onChange:e=>{B(e);let t=e.every(b);G(`telegram.allowedChatIds`,{value:C(e),original:K.allowedChatIds??[],valid:t})}}),(0,v.jsx)(c,{id:`tg-forwardAll`,label:`Forward all responses`,value:V,onChange:e=>{H(e),G(`telegram.forwardAll`,{value:e,original:K.forwardAll!==!1,valid:!0})}}),(0,v.jsx)(c,{id:`tg-mentionOnly`,label:`Mention only`,value:U,onChange:e=>{W(e),G(`telegram.mentionOnly`,{value:e,original:K.mentionOnly!==!1,valid:!0})}})]}),(0,v.jsx)(i,{title:`Health`,hint:`Probe the bot to confirm token + connectivity. 404 means the instance hasn't shipped the probe endpoint yet.`,children:(0,v.jsx)(p,{client:t,label:`Telegram`,endpoint:`/api/telegram/probe`,method:`POST`,interpret:f})})]}),(0,v.jsx)(m,{channel:`telegram`,client:t,dirty:n,open:k,onOpenChange:A,onSaved:async()=>O(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};