Plugin (Go server + React webapp): - Custom post type 'custom_livestatus' with terminal-style rendering - WebSocket broadcasts for real-time updates (no PUT, no '(edited)') - KV store for session persistence across reconnects - Shared secret auth for daemon-to-plugin communication - Auto-scroll terminal with user scroll override - Collapsible sub-agent sections - Theme-compatible CSS (light/dark) Daemon integration: - PluginClient for structured data push to plugin - Auto-detection: GET /health on startup + periodic re-check - Graceful fallback: if plugin unavailable, uses REST API (PUT) - Per-session mode tracking: sessions created via plugin stay on plugin - Mid-session fallback: if plugin update fails, auto-switch to REST Plugin deployed and active on Mattermost v11.4.0.
1 line
13 KiB
JavaScript
1 line
13 KiB
JavaScript
!function(e,n){if("object"==typeof exports&&"object"==typeof module)module.exports=n(require("React"));else if("function"==typeof define&&define.amd)define(["React"],n);else{var t="object"==typeof exports?n(require("React")):n(e.React);for(var s in t)("object"==typeof exports?exports:e)[s]=t[s]}}(self,e=>(()=>{"use strict";var n={999(e,n,t){t.d(n,{A:()=>l});var s=t(601),a=t.n(s),r=t(314),o=t.n(r)()(a());o.push([e.id,"/* OpenClaw Live Status — Post Type Styles */\n\n.ls-post {\n border-radius: 4px;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n margin: 4px 0;\n}\n\n/* Header */\n.ls-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--center-channel-bg, #fff);\n border-bottom: 1px solid var(--center-channel-color-08, rgba(0, 0, 0, 0.08));\n}\n\n.ls-agent-badge {\n font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;\n font-size: 12px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n background: var(--button-bg, #166de0);\n color: var(--button-color, #fff);\n}\n\n.ls-child-badge {\n font-size: 11px;\n background: var(--center-channel-color-24, rgba(0, 0, 0, 0.24));\n}\n\n.ls-status-badge {\n font-size: 11px;\n font-weight: 600;\n padding: 2px 6px;\n border-radius: 3px;\n text-transform: uppercase;\n}\n\n.ls-status-active .ls-status-badge {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.ls-status-done .ls-status-badge {\n background: #e3f2fd;\n color: #1565c0;\n}\n\n.ls-status-error .ls-status-badge {\n background: #fbe9e7;\n color: #c62828;\n}\n\n.ls-status-interrupted .ls-status-badge {\n background: #fff3e0;\n color: #e65100;\n}\n\n.ls-elapsed {\n font-size: 12px;\n color: var(--center-channel-color-56, rgba(0, 0, 0, 0.56));\n margin-left: auto;\n font-family: 'SFMono-Regular', Consolas, monospace;\n}\n\n/* Live dot — pulsing green indicator */\n.ls-live-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #4caf50;\n animation: ls-pulse 1.5s ease-in-out infinite;\n}\n\n@keyframes ls-pulse {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.5;\n transform: scale(0.8);\n }\n}\n\n/* Terminal view */\n.ls-terminal {\n max-height: 400px;\n overflow-y: auto;\n padding: 8px 12px;\n background: var(--center-channel-color-04, rgba(0, 0, 0, 0.04));\n font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;\n font-size: 12px;\n line-height: 1.6;\n}\n\n/* Status lines */\n.ls-status-line {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.ls-tool-call {\n color: var(--center-channel-color, #3d3c40);\n}\n\n.ls-tool-name {\n color: var(--link-color, #2389d7);\n font-weight: 600;\n}\n\n.ls-tool-args {\n color: var(--center-channel-color-72, rgba(0, 0, 0, 0.72));\n}\n\n.ls-marker-ok {\n color: #4caf50;\n font-weight: 600;\n}\n\n.ls-marker-err {\n color: #f44336;\n font-weight: 600;\n}\n\n.ls-thinking {\n color: var(--center-channel-color-48, rgba(0, 0, 0, 0.48));\n}\n\n.ls-thinking-prefix {\n color: var(--center-channel-color-24, rgba(0, 0, 0, 0.24));\n}\n\n/* Children (sub-agents) */\n.ls-children {\n border-top: 1px solid var(--center-channel-color-08, rgba(0, 0, 0, 0.08));\n padding: 4px 0;\n}\n\n.ls-child {\n margin: 0 12px;\n border-left: 2px solid var(--center-channel-color-16, rgba(0, 0, 0, 0.16));\n padding-left: 8px;\n}\n\n.ls-child-header {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 0;\n font-size: 12px;\n}\n\n.ls-expand-icon {\n font-size: 10px;\n color: var(--center-channel-color-48, rgba(0, 0, 0, 0.48));\n width: 12px;\n}\n\n/* Footer */\n.ls-footer {\n padding: 4px 12px 8px;\n font-size: 11px;\n color: var(--center-channel-color-48, rgba(0, 0, 0, 0.48));\n font-family: 'SFMono-Regular', Consolas, monospace;\n}\n\n/* Loading state */\n.ls-loading {\n padding: 12px;\n color: var(--center-channel-color-48, rgba(0, 0, 0, 0.48));\n font-style: italic;\n}\n\n/* Scrollbar styling */\n.ls-terminal::-webkit-scrollbar {\n width: 6px;\n}\n\n.ls-terminal::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.ls-terminal::-webkit-scrollbar-thumb {\n background: var(--center-channel-color-16, rgba(0, 0, 0, 0.16));\n border-radius: 3px;\n}\n\n.ls-terminal::-webkit-scrollbar-thumb:hover {\n background: var(--center-channel-color-32, rgba(0, 0, 0, 0.32));\n}\n",""]);const l=o},314(e){e.exports=function(e){var n=[];return n.toString=function(){return this.map(function(n){var t="",s=void 0!==n[5];return n[4]&&(t+="@supports (".concat(n[4],") {")),n[2]&&(t+="@media ".concat(n[2]," {")),s&&(t+="@layer".concat(n[5].length>0?" ".concat(n[5]):""," {")),t+=e(n),s&&(t+="}"),n[2]&&(t+="}"),n[4]&&(t+="}"),t}).join("")},n.i=function(e,t,s,a,r){"string"==typeof e&&(e=[[null,e,void 0]]);var o={};if(s)for(var l=0;l<this.length;l++){var i=this[l][0];null!=i&&(o[i]=!0)}for(var c=0;c<e.length;c++){var d=[].concat(e[c]);s&&o[d[0]]||(void 0!==r&&(void 0===d[5]||(d[1]="@layer".concat(d[5].length>0?" ".concat(d[5]):""," {").concat(d[1],"}")),d[5]=r),t&&(d[2]?(d[1]="@media ".concat(d[2]," {").concat(d[1],"}"),d[2]=t):d[2]=t),a&&(d[4]?(d[1]="@supports (".concat(d[4],") {").concat(d[1],"}"),d[4]=a):d[4]="".concat(a)),n.push(d))}},n}},601(e){e.exports=function(e){return e[1]}},72(e){var n=[];function t(e){for(var t=-1,s=0;s<n.length;s++)if(n[s].identifier===e){t=s;break}return t}function s(e,s){for(var r={},o=[],l=0;l<e.length;l++){var i=e[l],c=s.base?i[0]+s.base:i[0],d=r[c]||0,u="".concat(c," ").concat(d);r[c]=d+1;var p=t(u),m={css:i[1],media:i[2],sourceMap:i[3],supports:i[4],layer:i[5]};if(-1!==p)n[p].references++,n[p].updater(m);else{var f=a(m,s);s.byIndex=l,n.splice(l,0,{identifier:u,updater:f,references:1})}o.push(u)}return o}function a(e,n){var t=n.domAPI(n);return t.update(e),function(n){if(n){if(n.css===e.css&&n.media===e.media&&n.sourceMap===e.sourceMap&&n.supports===e.supports&&n.layer===e.layer)return;t.update(e=n)}else t.remove()}}e.exports=function(e,a){var r=s(e=e||[],a=a||{});return function(e){e=e||[];for(var o=0;o<r.length;o++){var l=t(r[o]);n[l].references--}for(var i=s(e,a),c=0;c<r.length;c++){var d=t(r[c]);0===n[d].references&&(n[d].updater(),n.splice(d,1))}r=i}}},659(e){var n={};e.exports=function(e,t){var s=function(e){if(void 0===n[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(e){t=null}n[e]=t}return n[e]}(e);if(!s)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");s.appendChild(t)}},540(e){e.exports=function(e){var n=document.createElement("style");return e.setAttributes(n,e.attributes),e.insert(n,e.options),n}},56(e,n,t){e.exports=function(e){var n=t.nc;n&&e.setAttribute("nonce",n)}},825(e){e.exports=function(e){if("undefined"==typeof document)return{update:function(){},remove:function(){}};var n=e.insertStyleElement(e);return{update:function(t){!function(e,n,t){var s="";t.supports&&(s+="@supports (".concat(t.supports,") {")),t.media&&(s+="@media ".concat(t.media," {"));var a=void 0!==t.layer;a&&(s+="@layer".concat(t.layer.length>0?" ".concat(t.layer):""," {")),s+=t.css,a&&(s+="}"),t.media&&(s+="}"),t.supports&&(s+="}");var r=t.sourceMap;r&&"undefined"!=typeof btoa&&(s+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(r))))," */")),n.styleTagTransform(s,e,n.options)}(n,e,t)},remove:function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)}}}},113(e){e.exports=function(e,n){if(n.styleSheet)n.styleSheet.cssText=e;else{for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(document.createTextNode(e))}}},883(n){n.exports=e}},t={};function s(e){var a=t[e];if(void 0!==a)return a.exports;var r=t[e]={id:e,exports:{}};return n[e](r,r.exports,s),r.exports}s.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return s.d(n,{a:n}),n},s.d=(e,n)=>{for(var t in n)s.o(n,t)&&!s.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},s.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),s.nc=void 0;var a=s(883),r=s.n(a);const o=({line:e})=>{const n=e.match(/^(\S+?): (.+?)( \[OK\]| \[ERR\])?$/);if(n){const e=n[1],t=n[2],s=(n[3]||"").trim();return r().createElement("div",{className:"ls-status-line ls-tool-call"},r().createElement("span",{className:"ls-tool-name"},e,":"),r().createElement("span",{className:"ls-tool-args"}," ",t),s&&r().createElement("span",{className:"[OK]"===s?"ls-marker-ok":"ls-marker-err"}," ",s))}return r().createElement("div",{className:"ls-status-line ls-thinking"},r().createElement("span",{className:"ls-thinking-prefix"},"│"," "),r().createElement("span",{className:"ls-thinking-text"},e))},l=({lines:e,maxLines:n=30})=>{const t=(0,a.useRef)(null),[s,l]=(0,a.useState)(!1),i=(0,a.useRef)(null);(0,a.useEffect)(()=>{!s&&i.current&&i.current.scrollIntoView({behavior:"smooth"})},[e.length,s]);const c=e.slice(-n);return r().createElement("div",{className:"ls-terminal",ref:t,onScroll:()=>{if(!t.current)return;const{scrollTop:e,scrollHeight:n,clientHeight:s}=t.current;l(!(n-e-s<20))}},c.map((e,n)=>r().createElement(o,{key:n,line:e})),r().createElement("div",{ref:i}))};function i(e){e<0&&(e=0);const n=Math.floor(e/1e3),t=Math.floor(n/60),s=Math.floor(t/60);return s>0?`${s}h${t%60}m`:t>0?`${t}m${n%60}s`:`${n}s`}"undefined"!=typeof window&&(window.__livestatus_updates=window.__livestatus_updates||{},window.__livestatus_listeners=window.__livestatus_listeners||{});const c=({child:e})=>{const[n,t]=(0,a.useState)(!1);return r().createElement("div",{className:"ls-child"},r().createElement("div",{className:"ls-child-header",onClick:()=>t(!n),style:{cursor:"pointer"}},r().createElement("span",{className:"ls-expand-icon"},n?"▼":"▶"),r().createElement("span",{className:"ls-agent-badge ls-child-badge"},e.agent_id),r().createElement("span",{className:`ls-status-badge ls-status-${e.status}`},e.status.toUpperCase()),r().createElement("span",{className:"ls-elapsed"},i(e.elapsed_ms))),n&&r().createElement(l,{lines:e.lines,maxLines:15}))},d=({post:e,theme:n})=>{const[t,s]=(0,a.useState)(0),o={session_key:e.props.session_key||"",post_id:e.id,agent_id:e.props.agent_id||"unknown",status:e.props.status||"active",lines:e.props.final_lines||[],elapsed_ms:e.props.elapsed_ms||0,token_count:e.props.token_count||0,children:[],start_time_ms:e.props.start_time_ms||0},d=function(e,n){const[t,s]=(0,a.useState)(window.__livestatus_updates[e]||n);return(0,a.useEffect)(()=>{window.__livestatus_listeners[e]||(window.__livestatus_listeners[e]=[]);const n=e=>s(e);return window.__livestatus_listeners[e].push(n),window.__livestatus_updates[e]&&s(window.__livestatus_updates[e]),()=>{const t=window.__livestatus_listeners[e];if(t){const e=t.indexOf(n);e>=0&&t.splice(e,1)}}},[e]),t}(e.id,o),u="active"===(null==d?void 0:d.status);if((0,a.useEffect)(()=>{if(!u||!(null==d?void 0:d.start_time_ms))return;const e=setInterval(()=>{s(Date.now()-d.start_time_ms)},1e3);return()=>clearInterval(e)},[u,null==d?void 0:d.start_time_ms]),!d)return r().createElement("div",{className:"ls-post ls-loading"},"Loading status...");const p=u&&d.start_time_ms?i(t||Date.now()-d.start_time_ms):i(d.elapsed_ms),m=`ls-status-${d.status}`;return r().createElement("div",{className:`ls-post ${m}`},r().createElement("div",{className:"ls-header"},r().createElement("span",{className:"ls-agent-badge"},d.agent_id),u&&r().createElement("span",{className:"ls-live-dot"}),r().createElement("span",{className:`ls-status-badge ${m}`},d.status.toUpperCase()),r().createElement("span",{className:"ls-elapsed"},p)),r().createElement(l,{lines:d.lines,maxLines:30}),d.children&&d.children.length>0&&r().createElement("div",{className:"ls-children"},d.children.map((e,n)=>r().createElement(c,{key:e.session_key||n,child:e}))),!u&&d.token_count>0&&r().createElement("div",{className:"ls-footer"},(f=d.token_count)>=1e6?`${(f/1e6).toFixed(1)}M`:f>=1e3?`${(f/1e3).toFixed(1)}k`:String(f)," tokens"));var f};var u=s(72),p=s.n(u),m=s(825),f=s.n(m),v=s(659),g=s.n(v),h=s(56),_=s.n(h),b=s(540),x=s.n(b),w=s(113),y=s.n(w),k=s(999),E={};E.styleTagTransform=y(),E.setAttributes=_(),E.insert=g().bind(null,"head"),E.domAPI=f(),E.insertStyleElement=x(),p()(k.A,E),k.A&&k.A.locals&&k.A.locals;const N="com.openclaw.livestatus",S=`custom_${N}_update`;return"undefined"!=typeof window&&(window.__livestatus_updates=window.__livestatus_updates||{},window.__livestatus_listeners=window.__livestatus_listeners||{}),window.registerPlugin(N,new class{constructor(){this.postTypeComponentId=null}initialize(e,n){this.postTypeComponentId=e.registerPostTypeComponent("custom_livestatus",d),e.registerWebSocketEventHandler(S,e=>{const n=e.data;if(!n||!n.post_id)return;const t={session_key:n.session_key,post_id:n.post_id,agent_id:n.agent_id,status:n.status,lines:n.lines||[],elapsed_ms:n.elapsed_ms||0,token_count:n.token_count||0,children:n.children||[],start_time_ms:n.start_time_ms||0};window.__livestatus_updates[n.post_id]=t;const s=window.__livestatus_listeners[n.post_id];s&&s.forEach(e=>e(t))})}uninitialize(){}}),{}})()); |