@sma1lboy/kobe 0.7.22 → 0.7.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +291 -48
- package/dist/web-ui/assets/AppShell-C0hhV6qB.js +16 -0
- package/dist/web-ui/assets/AppShell-NZ5KYJKh.css +1 -0
- package/dist/web-ui/assets/{routes-BY2-JOW5.js → ChatTerminal-j3zmSA6m.js} +3 -3
- package/dist/web-ui/assets/ChatTerminal-kHJ-D0s7.css +1 -0
- package/dist/web-ui/assets/index-BPEy1cTR.css +2 -0
- package/dist/web-ui/assets/index-CMnpXQhx.js +10 -0
- package/dist/web-ui/assets/jsx-runtime-bzQ4Vb5N.js +1 -0
- package/dist/web-ui/assets/overview-Gj7Z3GGU.js +1 -0
- package/dist/web-ui/assets/routes-BQZWyGJi.js +1 -0
- package/dist/web-ui/assets/task._taskId-CF3ph7W5.js +1 -0
- package/dist/web-ui/assets/triage-DT7sWoTl.js +1 -0
- package/dist/web-ui/index.html +3 -2
- package/dist/web-ui/pty-scrollback.mjs +51 -0
- package/dist/web-ui/pty-server.mjs +16 -3
- package/package.json +1 -1
- package/dist/web-ui/assets/index-B_AO4Tl6.js +0 -10
- package/dist/web-ui/assets/index-ClDlEZ7A.css +0 -2
- package/dist/web-ui/assets/routes-O3B6rKf2.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,a)=>(a=n==null?{}:e(i(n)),s(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),l=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function D(e,t){return E(e.type,t,e.props)}function O(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function k(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var A=/\/+/g;function j(e,t){return typeof e==`object`&&e&&e.key!=null?k(``+e.key):t.toString(36)}function M(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function N(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,N(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+j(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(A,`$&/`)+`/`),N(o,r,i,``,function(e){return e})):o!=null&&(O(o)&&(o=D(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(A,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u<e.length;u++)a=e[u],s=l+j(a,u),c+=N(a,r,i,s,o);else if(u=m(e),typeof u==`function`)for(e=u.call(e),u=0;!(a=e.next()).done;)a=a.value,s=l+j(a,u++),c+=N(a,r,i,s,o);else if(s===`object`){if(typeof e.then==`function`)return N(M(e),r,i,a,o);throw r=String(e),Error(`Objects are not valid as a React child (found: `+(r===`[object Object]`?`object with keys {`+Object.keys(e).join(`, `)+`}`:r)+`). If you meant to render a collection of children, use an array instead.`)}return c}function P(e,t,n){if(e==null)return e;var r=[],i=0;return N(e,r,``,``,function(e){return t.call(n,e,i++)}),r}function F(e){if(e._status===-1){var t=e._result;t=t(),t.then(function(t){(e._status===0||e._status===-1)&&(e._status=1,e._result=t)},function(t){(e._status===0||e._status===-1)&&(e._status=2,e._result=t)}),e._status===-1&&(e._status=0,e._result=t)}if(e._status===1)return e._result.default;throw e._result}var I=typeof reportError==`function`?reportError:function(e){if(typeof window==`object`&&typeof window.ErrorEvent==`function`){var t=new window.ErrorEvent(`error`,{bubbles:!0,cancelable:!0,message:typeof e==`object`&&e&&typeof e.message==`string`?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if(typeof process==`object`&&typeof process.emit==`function`){process.emit(`uncaughtException`,e);return}console.error(e)},L={map:P,forEach:function(e,t,n){P(e,function(){t.apply(this,arguments)},n)},count:function(e){var t=0;return P(e,function(){t++}),t},toArray:function(e){return P(e,function(e){return e})||[]},only:function(e){if(!O(e))throw Error(`React.Children.only expected to receive a single React element child.`);return e}};e.Activity=f,e.Children=L,e.Component=v,e.Fragment=r,e.Profiler=a,e.PureComponent=b,e.StrictMode=i,e.Suspense=l,e.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=w,e.__COMPILER_RUNTIME={__proto__:null,c:function(e){return w.H.useMemoCache(e)}},e.cache=function(e){return function(){return e.apply(null,arguments)}},e.cacheSignal=function(){return null},e.cloneElement=function(e,t,n){if(e==null)throw Error(`The argument must be a React element, but you passed `+e+`.`);var r=g({},e.props),i=e.key;if(t!=null)for(a in t.key!==void 0&&(i=``+t.key),t)!T.call(t,a)||a===`key`||a===`__self`||a===`__source`||a===`ref`&&t.ref===void 0||(r[a]=t[a]);var a=arguments.length-2;if(a===1)r.children=n;else if(1<a){for(var o=Array(a),s=0;s<a;s++)o[s]=arguments[s+2];r.children=o}return E(e.type,i,r)},e.createContext=function(e){return e={$$typeof:s,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null},e.Provider=e,e.Consumer={$$typeof:o,_context:e},e},e.createElement=function(e,t,n){var r,i={},a=null;if(t!=null)for(r in t.key!==void 0&&(a=``+t.key),t)T.call(t,r)&&r!==`key`&&r!==`__self`&&r!==`__source`&&(i[r]=t[r]);var o=arguments.length-2;if(o===1)i.children=n;else if(1<o){for(var s=Array(o),c=0;c<o;c++)s[c]=arguments[c+2];i.children=s}if(e&&e.defaultProps)for(r in o=e.defaultProps,o)i[r]===void 0&&(i[r]=o[r]);return E(e,a,i)},e.createRef=function(){return{current:null}},e.forwardRef=function(e){return{$$typeof:c,render:e}},e.isValidElement=O,e.lazy=function(e){return{$$typeof:d,_payload:{_status:-1,_result:e},_init:F}},e.memo=function(e,t){return{$$typeof:u,type:e,compare:t===void 0?null:t}},e.startTransition=function(e){var t=w.T,n={};w.T=n;try{var r=e(),i=w.S;i!==null&&i(n,r),typeof r==`object`&&r&&typeof r.then==`function`&&r.then(C,I)}catch(e){I(e)}finally{t!==null&&n.types!==null&&(t.types=n.types),w.T=t}},e.unstable_useCacheRefresh=function(){return w.H.useCacheRefresh()},e.use=function(e){return w.H.use(e)},e.useActionState=function(e,t,n){return w.H.useActionState(e,t,n)},e.useCallback=function(e,t){return w.H.useCallback(e,t)},e.useContext=function(e){return w.H.useContext(e)},e.useDebugValue=function(){},e.useDeferredValue=function(e,t){return w.H.useDeferredValue(e,t)},e.useEffect=function(e,t){return w.H.useEffect(e,t)},e.useEffectEvent=function(e){return w.H.useEffectEvent(e)},e.useId=function(){return w.H.useId()},e.useImperativeHandle=function(e,t,n){return w.H.useImperativeHandle(e,t,n)},e.useInsertionEffect=function(e,t){return w.H.useInsertionEffect(e,t)},e.useLayoutEffect=function(e,t){return w.H.useLayoutEffect(e,t)},e.useMemo=function(e,t){return w.H.useMemo(e,t)},e.useOptimistic=function(e,t){return w.H.useOptimistic(e,t)},e.useReducer=function(e,t,n){return w.H.useReducer(e,t,n)},e.useRef=function(e){return w.H.useRef(e)},e.useState=function(e){return w.H.useState(e)},e.useSyncExternalStore=function(e,t,n){return w.H.useSyncExternalStore(e,t,n)},e.useTransition=function(){return w.H.useTransition()},e.version=`19.2.7`})),u=o(((e,t)=>{t.exports=l()})),d=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),f=o(((e,t)=>{t.exports=d()}));export{c as i,u as n,o as r,f as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{i as e,n as t,t as n}from"./jsx-runtime-bzQ4Vb5N.js";import{r}from"./index-CMnpXQhx.js";import{D as i,F as a,I as o,P as s,a as c,c as l,f as u,n as d,p as f,r as p,s as m}from"./triage-DT7sWoTl.js";var h=o(`arrow-left`,[[`path`,{d:`m12 19-7-7 7-7`,key:`1l729n`}],[`path`,{d:`M19 12H5`,key:`x3x0zl`}]]),g=e(t(),1),_=n(),v=[{key:`attention`,title:`Needs you`,hint:`waiting on input, rate-limited, or errored`,accent:`text-kobe-blue`},{key:`working`,title:`Working`,hint:`engine is running right now`,accent:`text-kobe-orange`},{key:`changes`,title:`Uncommitted changes`,hint:`idle with a dirty worktree`,accent:`text-kobe-green`},{key:`quiet`,title:`Quiet`,hint:`idle, clean`,accent:`text-subtle`}];function y({entry:e,onOpen:t}){let{task:n,engine:r,changes:i}=e,a=f(r?.state);return(0,_.jsxs)(`button`,{type:`button`,onClick:t,className:`flex w-full flex-col gap-1.5 border border-line bg-surface p-3 text-left transition-colors hover:border-primary hover:bg-inset`,children:[(0,_.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,_.jsx)(`span`,{className:`h-1.5 w-1.5 shrink-0 rounded-full ${u(r?.state)}`}),(0,_.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[13px] text-fg`,children:n.title||n.branch||n.id}),i&&(i.added>0||i.deleted>0)&&(0,_.jsxs)(`span`,{className:`shrink-0 font-mono text-[10px]`,children:[(0,_.jsxs)(`span`,{className:`text-kobe-green`,children:[`+`,i.added]}),` `,(0,_.jsxs)(`span`,{className:`text-kobe-red`,children:[`−`,i.deleted]})]})]}),(0,_.jsxs)(`div`,{className:`flex items-center gap-2 text-[11px] text-subtle`,children:[(0,_.jsx)(`span`,{className:`min-w-0 truncate font-mono`,children:n.branch||n.repo}),(0,_.jsxs)(`span`,{className:`ml-auto flex shrink-0 items-center gap-2`,children:[a&&(0,_.jsx)(`span`,{className:`text-muted`,children:a}),(0,_.jsx)(`span`,{children:p(n.updatedAt||n.createdAt)})]})]})]})}function b(){let{tasks:e,engineStates:t,worktreeChanges:n,hydrated:o}=l(),u=r(),[f,p]=(0,g.useState)(``),b=(0,g.useRef)(null);(0,g.useEffect)(()=>{let e=e=>{if(e.metaKey||e.ctrlKey||e.altKey)return;let t=e.target,n=!!t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.tagName===`SELECT`||t.isContentEditable);e.key===`/`&&!n?(e.preventDefault(),b.current?.focus()):e.key===`Escape`&&t===b.current&&f&&(e.preventDefault(),p(``))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[f]);let x=(0,g.useMemo)(()=>e.filter(e=>!e.archived&&e.kind!==`main`).map(e=>{let r=t[e.id],i=n[e.worktreePath];return{task:e,engine:r,changes:i,bucket:d(r,i)}}),[e,t,n]),S=(0,g.useMemo)(()=>x.filter(e=>c(e.task,f)),[x,f]),C=(0,g.useMemo)(()=>{let e={attention:[],working:[],changes:[],quiet:[]};for(let t of S)e[t.bucket].push(t);return e},[S]),w=e=>{i(e),m(`task.setActive`,{taskId:e}).catch(()=>{}),u({to:`/task/$taskId`,params:{taskId:e}})},T={attention:C.attention.length,working:C.working.length,changes:C.changes.length};return(0,_.jsxs)(`div`,{className:`flex h-screen flex-col overflow-hidden bg-bg text-fg`,children:[(0,_.jsxs)(`header`,{className:`flex h-10 shrink-0 items-center gap-3 border-b border-line bg-surface px-3`,children:[(0,_.jsxs)(`button`,{type:`button`,onClick:()=>u({to:`/`}),className:`flex items-center gap-1.5 text-muted transition-colors hover:text-fg`,title:`Back to workspace`,children:[(0,_.jsx)(h,{size:15,strokeWidth:1.8}),(0,_.jsx)(`span`,{className:`text-[12px]`,children:`Workspace`})]}),(0,_.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-fg`,children:`Overview`}),(0,_.jsxs)(`label`,{className:`flex h-7 items-center gap-1.5 border border-line bg-bg px-2 text-muted focus-within:border-line-active`,children:[(0,_.jsx)(a,{size:13,strokeWidth:1.8,className:`shrink-0 text-subtle`}),(0,_.jsx)(`input`,{ref:b,value:f,onChange:e=>p(e.target.value),placeholder:`Filter tasks ( / )`,className:`w-44 bg-transparent text-[12px] text-fg placeholder:text-subtle focus:outline-none`}),f&&(0,_.jsx)(`button`,{type:`button`,onClick:()=>p(``),className:`shrink-0 text-subtle hover:text-fg`,"aria-label":`clear filter`,title:`Clear filter`,children:(0,_.jsx)(s,{size:13,strokeWidth:2})})]}),(0,_.jsxs)(`div`,{className:`ml-auto flex items-center gap-3 font-mono text-[11px]`,children:[(0,_.jsxs)(`span`,{className:`text-kobe-blue`,children:[T.attention,` need input`]}),(0,_.jsxs)(`span`,{className:`text-kobe-orange`,children:[T.working,` running`]}),(0,_.jsxs)(`span`,{className:`text-kobe-green`,children:[T.changes,` dirty`]})]})]}),(0,_.jsx)(`div`,{className:`min-h-0 flex-1 overflow-auto p-4`,children:o?x.length===0?(0,_.jsx)(`p`,{className:`text-[12px] text-subtle`,children:`No worktree tasks yet. Create one from the workspace.`}):S.length===0?(0,_.jsxs)(`p`,{className:`text-[12px] text-subtle`,children:[`No tasks match “`,f.trim(),`”.`]}):(0,_.jsx)(`div`,{className:`grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4`,children:v.map(({key:e,title:t,hint:n,accent:r})=>{let i=C[e];return(0,_.jsxs)(`section`,{className:`flex min-w-0 flex-col`,children:[(0,_.jsxs)(`div`,{className:`mb-2 flex items-baseline gap-2`,children:[(0,_.jsx)(`h2`,{className:`text-[11px] font-bold uppercase tracking-[0.12em] ${r}`,children:t}),(0,_.jsx)(`span`,{className:`font-mono text-[10px] text-subtle`,children:i.length})]}),(0,_.jsx)(`p`,{className:`mb-2 text-[10px] leading-relaxed text-subtle`,children:n}),(0,_.jsx)(`div`,{className:`flex flex-col gap-2`,children:i.length===0?(0,_.jsx)(`div`,{className:`border border-dashed border-line-subtle p-3 text-center text-[11px] text-subtle`,children:`none`}):i.map(e=>(0,_.jsx)(y,{entry:e,onOpen:()=>w(e.task.id)},e.task.id))})]},e)})}):(0,_.jsx)(`p`,{className:`text-[12px] text-subtle`,children:`Loading…`})})]})}var x=b;export{x as component};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./AppShell-C0hhV6qB.js";var t=e;export{t as component};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{i as e,n as t,t as n}from"./jsx-runtime-bzQ4Vb5N.js";import{t as r}from"./index-CMnpXQhx.js";import{D as i,j as a,s as o}from"./triage-DT7sWoTl.js";import{t as s}from"./AppShell-C0hhV6qB.js";var c=e(t()),l=n();function u(){let{taskId:e}=r.useParams(),{selectedTaskId:t}=a();return(0,c.useEffect)(()=>{!e||e===t||(i(e),o(`task.setActive`,{taskId:e}).catch(()=>{}))},[e,t]),(0,l.jsx)(s,{})}export{u as component};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{i as e,n as t}from"./jsx-runtime-bzQ4Vb5N.js";var n=e(t()),r=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase(),i=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,n)=>n?n.toUpperCase():t.toLowerCase()),a=e=>{let t=i(e);return t.charAt(0).toUpperCase()+t.slice(1)},o=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),s=e=>{for(let t in e)if(t.startsWith(`aria-`)||t===`role`||t===`title`)return!0},c={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:2,strokeLinecap:`round`,strokeLinejoin:`round`},l=(0,n.forwardRef)(({color:e=`currentColor`,size:t=24,strokeWidth:r=2,absoluteStrokeWidth:i,className:a=``,children:l,iconNode:u,...d},f)=>(0,n.createElement)(`svg`,{ref:f,...c,width:t,height:t,stroke:e,strokeWidth:i?Number(r)*24/Number(t):r,className:o(`lucide`,a),...!l&&!s(d)&&{"aria-hidden":`true`},...d},[...u.map(([e,t])=>(0,n.createElement)(e,t)),...Array.isArray(l)?l:[l]])),u=(e,t)=>{let i=(0,n.forwardRef)(({className:i,...s},c)=>(0,n.createElement)(l,{ref:c,iconNode:t,className:o(`lucide-${r(a(e))}`,`lucide-${e}`,i),...s}));return i.displayName=a(e),i},d=u(`search`,[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]),f=u(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]);function ee(){let e=location.protocol===`https:`?`wss`:`ws`,t=location.hostname||`localhost`,n=Number.parseInt(location.port||`5173`,10);return`${e}://${t}:${Number.isFinite(n)?n+2:5175}`}function te(){let e=location.protocol===`https:`?`https`:`http`,t=location.hostname||`localhost`,n=Number.parseInt(location.port||`5173`,10);return`${e}://${t}:${Number.isFinite(n)?n+2:5175}`}function ne(e,t,n,r,i){let a=new URLSearchParams({tab:e,taskId:t,mode:n,cols:String(r),rows:String(i)});return`${ee()}/pty?${a.toString()}`}async function p(e){try{await fetch(`${te()}/pty/close`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({tab:e})})}catch{}}var m=`kobe-web.tabs`,h={selectedTaskId:null,tabsByTask:{},activeByTask:{},splitByTask:{}};function g(){return{id:S(),kind:`empty`,title:`New tab`}}function _(e,t){let n=e.tabsByTask[t]??[],r=e.activeByTask[t],i=e.splitByTask[t],a=e;if(i&&(!n.some(e=>e.id===i)||i===r)){let{[t]:n,...r}=e.splitByTask;a={...e,splitByTask:r}}if(n.length>0)return r&&n.some(e=>e.id===r)?a:{...a,activeByTask:{...e.activeByTask,[t]:n[0].id}};let o=g();return{...a,tabsByTask:{...e.tabsByTask,[t]:[o]},activeByTask:{...e.activeByTask,[t]:o.id}}}function re(e){let t=e,n=typeof e?.kind==`string`?e.kind:void 0;if(n===`notes`)return g();let r=n===`chat`?`vendor`:n??`vendor`;return{...t,kind:r}}function ie(){try{let e=localStorage.getItem(m);if(e){let t=JSON.parse(e),n=Object.fromEntries(Object.entries(t.tabsByTask??{}).map(([e,t])=>[e,t.map(re)])),r={selectedTaskId:t.selectedTaskId??null,tabsByTask:n,activeByTask:t.activeByTask??{},splitByTask:t.splitByTask??{}};return r.selectedTaskId?_(r,r.selectedTaskId):r}}catch{}return h}var v=typeof localStorage>`u`?h:ie(),y=new Set;function b(e){v=e;try{localStorage.setItem(m,JSON.stringify(v))}catch{}for(let e of y)e()}var x=0;function S(){try{return crypto.randomUUID()}catch{return x+=1,`tab-${Date.now().toString(36)}-${x}`}}function ae(e){b(_({...v,selectedTaskId:e},e))}var C=new Map;function oe(e,t){C.set(e,t)}function se(e){let t=C.get(e);return t===void 0?null:(C.delete(e),t)}function ce(){for(let e of Object.values(v.tabsByTask))for(let t of e)(t.kind===`vendor`||t.kind===`terminal`)&&p(t.id);b({...h})}function le(e){let t=Object.keys(v.tabsByTask).filter(t=>!e.has(t)),n=v.selectedTaskId!==null&&!e.has(v.selectedTaskId);if(t.length===0&&!n)return;for(let e of t)for(let t of v.tabsByTask[e]??[])(t.kind===`vendor`||t.kind===`terminal`)&&p(t.id);let r={...v.tabsByTask},i={...v.activeByTask},a={...v.splitByTask};for(let e of t)delete r[e],delete i[e],delete a[e];b({selectedTaskId:n?null:v.selectedTaskId,tabsByTask:r,activeByTask:i,splitByTask:a})}function ue(){b({...v,selectedTaskId:null})}function de(e){let t=v.tabsByTask[e]??[],n=S(),r={id:n,kind:`vendor`,title:`Vendor ${t.filter(e=>e.kind===`vendor`).length+1}`};return b({...v,tabsByTask:{...v.tabsByTask,[e]:[...t,r]},activeByTask:{...v.activeByTask,[e]:n},splitByTask:v.splitByTask}),n}function fe(e){let t=v.tabsByTask[e]??[],n=g();return b({...v,tabsByTask:{...v.tabsByTask,[e]:[...t,n]},activeByTask:{...v.activeByTask,[e]:n.id},splitByTask:v.splitByTask}),n.id}function pe(e,t,n){let r=v.tabsByTask[e]??[],i=r.map(e=>e.id===t?n===`vendor`?{id:t,kind:n,title:`Vendor ${r.filter(e=>e.kind===`vendor`).length+1}`}:n===`transcript`?{id:t,kind:n,title:`Chat`}:{id:t,kind:n,title:`Terminal ${r.filter(e=>e.kind===`terminal`).length+1}`}:e);b({...v,tabsByTask:{...v.tabsByTask,[e]:i},activeByTask:{...v.activeByTask,[e]:t},splitByTask:v.splitByTask})}function me(e,t){let n=v.tabsByTask[e]??[],r=n.find(e=>e.kind===`file`&&e.path===t);if(r)return w(e,r.id),r.id;let i=S(),a={id:i,kind:`file`,title:t.split(`/`).at(-1)??t,path:t};return b({...v,tabsByTask:{...v.tabsByTask,[e]:[...n,a]},activeByTask:{...v.activeByTask,[e]:i},splitByTask:v.splitByTask}),i}function he(e,t){let n=v.tabsByTask[e]??[],r=n.findIndex(e=>e.id===t),i=n.filter(e=>e.id!==t);i.length===0&&(i=[g()]);let a=v.activeByTask[e]===t,o={...v.activeByTask},s={...v.splitByTask};if(a){let t=Math.max(0,Math.min(r,i.length-1));o[e]=i[t].id}(s[e]===t||s[e]===o[e])&&delete s[e],b({...v,tabsByTask:{...v.tabsByTask,[e]:i},activeByTask:o,splitByTask:s})}function w(e,t){let n={...v.splitByTask},r={...v.activeByTask},i=r[e];n[e]===t&&i&&i!==t?n[e]=i:n[e]===t&&delete n[e],r[e]=t,b({...v,activeByTask:r,splitByTask:n})}function ge(e,t){let n=v.tabsByTask[e]??[];if(!n.some(e=>e.id===t))return;let r=v.activeByTask[e],i={...v.activeByTask};if(r===t){let r=n.find(e=>e.id!==t);if(!r)return;i[e]=r.id}b({...v,activeByTask:i,splitByTask:{...v.splitByTask,[e]:t}})}function _e(e){let{[e]:t,...n}=v.splitByTask;b({...v,splitByTask:n})}function ve(){return(0,n.useSyncExternalStore)(e=>(y.add(e),()=>y.delete(e)),()=>v,()=>v)}var T=`claude`,E=`kobe-web.theme`,D=null,O=null,k=be(),A=null,ye=!1,j=new Set;function be(){try{return localStorage.getItem(E)}catch{return null}}function M(){for(let e of j)e()}function xe(e,t,n=T){return e??t??n}function N(){return xe(k,A)}function P(){ye||typeof window>`u`||(ye=!0,fetch(`/api/themes`).then(async e=>{if(!e.ok)return;let t=await e.json();t.themes&&(D=t.themes,F(),M())}).catch(()=>{}))}function F(){if(P(),!D)return;let e=N();if(O===e)return;let t=D[e]??D[T];if(!t)return;O=e;let n=document.documentElement;for(let[e,r]of Object.entries(t))n.style.setProperty(`--color-${e}`,r);M()}function I(e){A=e,F()}function Se(e){k=e;try{localStorage.setItem(E,e)}catch{}F(),M()}function Ce(){k=null;try{localStorage.removeItem(E)}catch{}O=null,F(),M()}function we(){return{names:D?Object.keys(D):[],palettes:D??{},active:N(),overridden:k!==null}}var L=we();function R(){let e=we();return(e.active!==L.active||e.overridden!==L.overridden||e.names.length!==L.names.length)&&(L=e),L}function Te(){return P(),(0,n.useSyncExternalStore)(e=>(j.add(e),()=>j.delete(e)),R,R)}F();function Ee(){return D?D[N()]??null:null}function De(){let e=Ee();return e?{background:e.bg,foreground:e.fg,cursor:e.primary,cursorAccent:e.bg,selectionBackground:e.menu,black:e.bg,red:e[`kobe-red`],green:e[`kobe-green`],yellow:e[`kobe-yellow`],blue:e[`kobe-blue`],magenta:e[`kobe-violet`],cyan:e[`primary-hover`],white:e.muted,brightBlack:e.subtle,brightRed:e[`kobe-red`],brightGreen:e[`kobe-green`],brightYellow:e[`kobe-yellow`],brightBlue:e[`kobe-blue`],brightMagenta:e[`kobe-violet`],brightCyan:e[`primary-hover`],brightWhite:e.fg}:null}function Oe(e){switch(e){case`running`:return`bg-kobe-orange`;case`waiting_permission`:return`bg-kobe-blue`;case`rate_limited`:return`bg-kobe-yellow`;case`error`:return`bg-kobe-red`;case`idle`:return`bg-kobe-green/60`;default:return`bg-subtle`}}function ke(e){switch(e){case`running`:return`running`;case`waiting_permission`:return`needs input`;case`rate_limited`:return`rate limited`;case`error`:return`error`;case`idle`:return`idle`;default:return``}}var z=`kobe-web.notify`,B=null,V=Ae(),H=new Set;function Ae(){try{return localStorage.getItem(z)===`1`}catch{return!1}}function je(){for(let e of H)e()}function U(e){return e===`waiting_permission`||e===`error`}function Me(e){return!e.enabled||e.permission!==`granted`||!e.hidden?!1:!U(e.prev)&&U(e.next)}function Ne(e){B=e}function W(){return typeof Notification>`u`?`denied`:Notification.permission}function G(){return{supported:typeof Notification<`u`,permission:W(),enabled:V&&W()===`granted`}}var K=G();function q(){let e=G();return(e.supported!==K.supported||e.permission!==K.permission||e.enabled!==K.enabled)&&(K=e),K}async function Pe(e){if(e&&typeof Notification<`u`&&Notification.permission==="default")try{await Notification.requestPermission()}catch{}V=e;try{localStorage.setItem(z,e?`1`:`0`)}catch{}je()}function Fe(){return(0,n.useSyncExternalStore)(e=>(H.add(e),()=>H.delete(e)),q,q)}function Ie(e,t,n,r){let i=typeof document>`u`||document.visibilityState!==`visible`;if(!Me({prev:n,next:r,enabled:V,permission:W(),hidden:i}))return;let a=r===`error`?`errored`:`needs your input`;try{let n=new Notification(`kobe: ${t}`,{body:`Task ${a}.`,tag:`kobe-task-${e}`});n.onclick=()=>{window.focus(),B?.(e),n.close()}}catch{}}var J={tasks:[],activeTaskId:null,engineStates:{},update:null,jobs:{},worktreeChanges:{},uiPrefs:null,hydrated:!1,daemonConnected:!1,streamConnected:!1},Y=new Set;function X(e){J={...J,...e};for(let e of Y)e()}function Z(e,t){let n=Object.entries(e).filter(([e])=>t.has(e));return n.length===Object.keys(e).length?e:Object.fromEntries(n)}function Le(e,t){return!e&&t===`idle`}function Re(e,t){if(t.phase===`running`)return{...e,[t.taskId]:t};let{[t.taskId]:n,...r}=e;return r}function ze(e){let t=new Set(e.map(e=>e.id));X({tasks:e,engineStates:Z(J.engineStates,t),jobs:Z(J.jobs,t)}),le(t)}function Be(e){switch(e.channel){case`task.snapshot`:ze(e.payload.tasks);break;case`active-task`:X({activeTaskId:e.payload.taskId});break;case`engine-state`:{let t=J.engineStates[e.payload.taskId]?.state,n=J.tasks.find(t=>t.id===e.payload.taskId);if(Le(n,e.payload.state))break;Ie(e.payload.taskId,n?.title||n?.branch||e.payload.taskId,t,e.payload.state),X({engineStates:{...J.engineStates,[e.payload.taskId]:e.payload}});break}case`update`:X({update:e.payload.info});break;case`task.jobs`:X({jobs:Re(J.jobs,e.payload)});break;case`worktree.changes`:X({worktreeChanges:e.payload.changes});break;case`ui-prefs`:X({uiPrefs:e.payload}),I(e.payload.theme);break}}var Q=null;function Ve(){Q||(Q=new EventSource(`/events`),Q.addEventListener(`open`,()=>X({streamConnected:!0})),Q.addEventListener(`snapshot`,e=>{let t=JSON.parse(e.data);X({tasks:t.tasks,activeTaskId:t.activeTaskId,engineStates:t.engineStates,update:t.update,jobs:t.jobs??{},worktreeChanges:t.worktreeChanges??{},uiPrefs:t.uiPrefs??null,hydrated:!0,daemonConnected:t.connected,streamConnected:!0}),t.uiPrefs&&I(t.uiPrefs.theme),t.connected&&le(new Set(t.tasks.map(e=>e.id)))}),Q.addEventListener(`channel`,e=>{Be(JSON.parse(e.data)),J.daemonConnected||X({daemonConnected:!0})}),Q.addEventListener(`error`,()=>X({streamConnected:!1})))}function He(e){return Ve(),Y.add(e),()=>{Y.delete(e)}}function Ue(){return J}function We(){return(0,n.useSyncExternalStore)(He,Ue,Ue)}async function Ge(e,t){let n=await fetch(`/api/rpc`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({name:e,payload:t})}),r=await n.json();if(!n.ok||r.error)throw Error(r.error??`rpc ${e} failed (${n.status})`);return r.result}function Ke(e){let t=Date.parse(e.updatedAt||e.createdAt);return Number.isFinite(t)?t:0}function $(e,t){let n=Ke(t)-Ke(e);return n===0?t.id.localeCompare(e.id):n}function qe(e,t){let n=e.filter(e=>e.kind===`main`),r=e.filter(e=>e.kind!==`main`&&e.pinned),i=e.filter(e=>e.kind!==`main`&&!e.pinned);return t===`recent`&&(n.sort($),r.sort($),i.sort($)),[...n,...r,...i]}function Je(e,t){return t?[e.title,e.branch,e.repo,e.worktreePath,e.vendor,e.status].filter(Boolean).join(` `).toLowerCase().includes(t.toLowerCase()):!0}function Ye(e,t=Date.now()){if(!e)return``;let n=Math.max(0,Math.round((t-e)/1e3));if(n<60)return`just now`;let r=Math.round(n/60);if(r<60)return`${r}m ago`;let i=Math.round(r/60);return i<24?`${i}h ago`:`${Math.round(i/24)}d ago`}function Xe(e,t=Date.now()){let n=Date.parse(e);if(!Number.isFinite(n))return``;let r=Math.max(0,Math.round((t-n)/1e3));if(r<45)return`now`;let i=Math.round(r/60);if(i<60)return`${i}m`;let a=Math.round(i/60);if(a<24)return`${a}h`;let o=Math.round(a/24);if(o<7)return`${o}d`;let s=Math.round(o/7);if(s<5)return`${s}w`;let c=Math.round(o/30);return c<12?`${c}mo`:`${Math.round(o/365)}y`}function Ze(e,t){let n=e?.state;return n===`waiting_permission`||n===`error`||n===`rate_limited`?`attention`:n===`running`?`working`:t&&(t.added>0||t.deleted>0)?`changes`:`quiet`}function Qe(e,t,n){return n===`all`||Ze(e,t)===n}export{ge as A,pe as C,ae as D,ce as E,d as F,u as I,p as M,ne as N,w as O,f as P,he as S,me as T,De as _,Je as a,ue as b,We as c,Fe as d,Oe as f,Te as g,Se as h,Ye as i,ve as j,oe as k,Pe as l,Ce as m,Ze as n,qe as o,ke as p,Xe as r,Ge as s,Qe as t,Ne as u,fe as v,se as w,_e as x,de as y};
|
package/dist/web-ui/index.html
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>kobe-web</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-CMnpXQhx.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-bzQ4Vb5N.js">
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BPEy1cTR.css">
|
|
10
11
|
</head>
|
|
11
12
|
<body>
|
|
12
13
|
<div id="app"></div>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded scrollback ring for the PTY server.
|
|
3
|
+
*
|
|
4
|
+
* The web terminal replays recent output on every (re)attach, so each PTY keeps
|
|
5
|
+
* a cap of recent bytes. The naive shape — `buffer = (buffer + data).slice(-CAP)`
|
|
6
|
+
* on every chunk — re-flattens the whole ~256KB buffer per chunk once full, so a
|
|
7
|
+
* burst of N small chunks costs O(N·CAP) (quadratic) on the same thread that
|
|
8
|
+
* relays bytes to the browser.
|
|
9
|
+
*
|
|
10
|
+
* This ring keeps the chunks as-is and a running length total: `push` is
|
|
11
|
+
* O(chunk) (append + shift whole chunks off the head until back under the cap),
|
|
12
|
+
* and the string is materialized only on `replay` — once per attach, O(cap).
|
|
13
|
+
*
|
|
14
|
+
* "Length" is measured in JS string length (UTF-16 code units), matching the
|
|
15
|
+
* prior `.slice(-CAP)` semantics: the cap is an approximate recent-output
|
|
16
|
+
* window, not an exact byte count.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {number} cap Max retained length (string code units).
|
|
21
|
+
* @returns {{ push: (data: string) => void, replay: () => string, length: () => number, chunkCount: () => number }}
|
|
22
|
+
*/
|
|
23
|
+
export function createScrollback(cap) {
|
|
24
|
+
/** @type {string[]} */
|
|
25
|
+
let chunks = []
|
|
26
|
+
let total = 0
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
push(data) {
|
|
30
|
+
if (!data) return
|
|
31
|
+
chunks.push(data)
|
|
32
|
+
total += data.length
|
|
33
|
+
// Drop whole chunks off the head while over cap, but always keep the
|
|
34
|
+
// most recent chunk so a single oversized chunk still replays.
|
|
35
|
+
while (total > cap && chunks.length > 1) {
|
|
36
|
+
const dropped = chunks.shift()
|
|
37
|
+
total -= dropped.length
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
replay() {
|
|
41
|
+
if (chunks.length === 0) return ""
|
|
42
|
+
return chunks.length === 1 ? chunks[0] : chunks.join("")
|
|
43
|
+
},
|
|
44
|
+
length() {
|
|
45
|
+
return total
|
|
46
|
+
},
|
|
47
|
+
chunkCount() {
|
|
48
|
+
return chunks.length
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -123,7 +123,17 @@ const server = createServer((req, res) => {
|
|
|
123
123
|
res.end()
|
|
124
124
|
})
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
// A PTY WS is arbitrary command exec in the worktree, so reject cross-origin
|
|
127
|
+
// upgrades: a browser sends an Origin header, and only localhost pages may
|
|
128
|
+
// attach (defends a malicious local page / DNS-rebinding even on the loopback
|
|
129
|
+
// bind). Non-browser clients (no Origin) are allowed — there's no browser to
|
|
130
|
+
// forge their request.
|
|
131
|
+
const LOCAL_ORIGIN = /^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/
|
|
132
|
+
const wss = new WebSocketServer({
|
|
133
|
+
server,
|
|
134
|
+
path: "/pty",
|
|
135
|
+
verifyClient: ({ origin }) => !origin || LOCAL_ORIGIN.test(origin),
|
|
136
|
+
})
|
|
127
137
|
|
|
128
138
|
wss.on("connection", (ws, req) => {
|
|
129
139
|
const url = new URL(req.url ?? "/", "http://localhost")
|
|
@@ -181,8 +191,11 @@ wss.on("connection", (ws, req) => {
|
|
|
181
191
|
})()
|
|
182
192
|
})
|
|
183
193
|
|
|
184
|
-
|
|
185
|
-
|
|
194
|
+
// Bind loopback by default — a PTY is an arbitrary shell/engine in the
|
|
195
|
+
// worktree, so it must never listen on all interfaces. KOBE_WEB_HOST overrides.
|
|
196
|
+
const HOST = process.env.KOBE_WEB_HOST?.trim() || "127.0.0.1"
|
|
197
|
+
server.listen(PORT, HOST, () => {
|
|
198
|
+
process.stdout.write(`kobe pty-server listening on ${HOST}:${PORT} (bridge :${BRIDGE_PORT})\n`)
|
|
186
199
|
})
|
|
187
200
|
|
|
188
201
|
const shutdown = () => {
|
package/package.json
CHANGED