@karmaniverous/jeeves-server 3.4.2 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/.tsbuildinfo +1 -1
  2. package/CHANGELOG.md +38 -1
  3. package/README.md +18 -17
  4. package/client/package.json +19 -19
  5. package/client/src/components/SearchModal.tsx +11 -1
  6. package/client/src/components/layout/Header.tsx +3 -3
  7. package/client/src/lib/api.ts +10 -5
  8. package/dist/client/assets/CodeEditor-Brh86AGF.js +1 -0
  9. package/dist/client/assets/CodeViewer-Cegj3cEn.js +1 -0
  10. package/dist/client/assets/dist-2YqVIvgv.js +2 -0
  11. package/dist/client/assets/dist-5vamY028.js +1 -0
  12. package/dist/client/assets/dist-6_auAGci.js +1 -0
  13. package/dist/client/assets/dist-B0kq1DQG.js +1 -0
  14. package/dist/client/assets/dist-B2SZD_eN.js +1 -0
  15. package/dist/client/assets/dist-B2t4dYA2.js +1 -0
  16. package/dist/client/assets/dist-B5gFYAn7.js +1 -0
  17. package/dist/client/assets/dist-BPy6CnYN.js +1 -0
  18. package/dist/client/assets/dist-CL6VCrQn.js +9 -0
  19. package/dist/client/assets/dist-CWsHar9N.js +1 -0
  20. package/dist/client/assets/dist-CnFc5Ssx.js +1 -0
  21. package/dist/client/assets/dist-DSgLBuTS.js +1 -0
  22. package/dist/client/assets/dist-DUcac0X_.js +7 -0
  23. package/dist/client/assets/dist-DcTcc-BG.js +6 -0
  24. package/dist/client/assets/dist-DvfTyWk_.js +1 -0
  25. package/dist/client/assets/dist-Dz1Ulpqa.js +1 -0
  26. package/dist/client/assets/dist-Kr-mUYW1.js +5 -0
  27. package/dist/client/assets/dist-OX4k3MMG.js +2 -0
  28. package/dist/client/assets/dist-qiU0qoeK.js +1 -0
  29. package/dist/client/assets/dist-ui4J6fvl.js +23 -0
  30. package/dist/client/assets/index-Dk_myGs4.css +2 -0
  31. package/dist/client/assets/index-DrBXupPz.js +62 -0
  32. package/dist/client/assets/theme-CPpIxvB0.js +2 -0
  33. package/dist/client/index.html +3 -2
  34. package/dist/src/cli/commands/config.test.js +5 -40
  35. package/dist/src/cli/index.js +9 -15
  36. package/dist/src/cli/start-server.js +16 -0
  37. package/dist/src/config/index.js +48 -37
  38. package/dist/src/config/loadConfig.test.js +27 -25
  39. package/dist/src/config/migration.js +60 -0
  40. package/dist/src/config/schema.js +4 -3
  41. package/dist/src/descriptor.js +46 -0
  42. package/dist/src/routes/api/diagramExport.js +101 -0
  43. package/dist/src/routes/api/diagramExport.test.js +134 -0
  44. package/dist/src/routes/api/events.js +13 -0
  45. package/dist/src/routes/api/export.js +6 -82
  46. package/dist/src/routes/api/index.js +4 -0
  47. package/dist/src/routes/api/search.js +9 -50
  48. package/dist/src/routes/api/sharing.js +40 -23
  49. package/dist/src/routes/api/sharing.test.js +52 -0
  50. package/dist/src/routes/auth.js +1 -1
  51. package/dist/src/routes/config.js +8 -2
  52. package/dist/src/routes/keys.js +4 -4
  53. package/dist/src/routes/path/index.js +1 -1
  54. package/dist/src/routes/status.js +15 -16
  55. package/dist/src/routes/status.test.js +13 -8
  56. package/dist/src/server.js +21 -16
  57. package/dist/src/services/markdown.js +2 -1
  58. package/dist/src/services/markdown.test.js +22 -0
  59. package/dist/src/util/packageVersion.js +7 -16
  60. package/dist/src/util/packageVersion.test.js +7 -0
  61. package/guides/api-integration.md +4 -0
  62. package/guides/deployment.md +11 -10
  63. package/guides/event-gateway.md +4 -0
  64. package/guides/exports.md +4 -0
  65. package/guides/index.md +1 -1
  66. package/guides/setup.md +17 -16
  67. package/guides/sharing.md +4 -0
  68. package/package.json +3 -3
  69. package/scripts/download-plantuml.js +0 -1
  70. package/src/cli/commands/config.test.ts +5 -45
  71. package/src/cli/index.ts +9 -16
  72. package/src/cli/start-server.ts +21 -0
  73. package/src/config/index.ts +56 -43
  74. package/src/config/loadConfig.test.ts +27 -29
  75. package/src/config/migration.ts +76 -0
  76. package/src/config/schema.ts +5 -4
  77. package/src/descriptor.ts +55 -0
  78. package/src/routes/api/diagramExport.test.ts +200 -0
  79. package/src/routes/api/diagramExport.ts +170 -0
  80. package/src/routes/api/events.ts +22 -0
  81. package/src/routes/api/export.ts +6 -131
  82. package/src/routes/api/index.ts +4 -0
  83. package/src/routes/api/search.ts +9 -63
  84. package/src/routes/api/sharing.test.ts +66 -0
  85. package/src/routes/api/sharing.ts +47 -23
  86. package/src/routes/auth.ts +1 -1
  87. package/src/routes/config.ts +15 -2
  88. package/src/routes/keys.ts +4 -4
  89. package/src/routes/path/index.ts +1 -1
  90. package/src/routes/status.test.ts +14 -8
  91. package/src/routes/status.ts +56 -62
  92. package/src/server.ts +29 -17
  93. package/src/services/markdown.test.ts +26 -0
  94. package/src/services/markdown.ts +2 -1
  95. package/src/util/packageVersion.test.ts +9 -0
  96. package/src/util/packageVersion.ts +11 -18
  97. package/src/util/platform.ts +1 -1
  98. package/dist/client/assets/CodeEditor-DQZZL5Rq.js +0 -1
  99. package/dist/client/assets/CodeViewer-ofJVD1Vn.js +0 -1
  100. package/dist/client/assets/index--MBieNJA.js +0 -1
  101. package/dist/client/assets/index-BENeXQI_.js +0 -1
  102. package/dist/client/assets/index-BbBpoOxz.js +0 -1
  103. package/dist/client/assets/index-BdV9g5AM.js +0 -6
  104. package/dist/client/assets/index-BjAilRri.js +0 -2
  105. package/dist/client/assets/index-BqbhWo2I.js +0 -3
  106. package/dist/client/assets/index-CVbycZ0H.js +0 -1
  107. package/dist/client/assets/index-Cs5oz2oJ.js +0 -5
  108. package/dist/client/assets/index-D-RC7ZS6.css +0 -1
  109. package/dist/client/assets/index-D8KZVveX.js +0 -1
  110. package/dist/client/assets/index-DC4HMHxY.js +0 -13
  111. package/dist/client/assets/index-DcY2RXqX.js +0 -1
  112. package/dist/client/assets/index-Duy-tZYV.js +0 -1
  113. package/dist/client/assets/index-Dw7rDFmE.js +0 -7
  114. package/dist/client/assets/index-FlCUvrjv.js +0 -2
  115. package/dist/client/assets/index-K6OVmfhg.js +0 -1
  116. package/dist/client/assets/index-MLwyFRN0.js +0 -1
  117. package/dist/client/assets/index-OpqBpSjn.js +0 -1
  118. package/dist/client/assets/index-SsHei0HE.js +0 -1
  119. package/dist/client/assets/index-jSGuHSeS.js +0 -62
  120. package/dist/client/assets/index-uQa2yckk.js +0 -1
  121. package/dist/client/assets/index-udkXoIER.js +0 -1
  122. package/dist/src/cli/commands/config.js +0 -105
  123. package/dist/src/cli/commands/service.js +0 -93
  124. package/dist/src/cli/commands/start.js +0 -24
  125. package/src/cli/commands/config.ts +0 -117
  126. package/src/cli/commands/service.ts +0 -129
  127. package/src/cli/commands/start.ts +0 -27
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/dist-2YqVIvgv.js","assets/dist-B2t4dYA2.js","assets/dist-5vamY028.js","assets/dist-Kr-mUYW1.js","assets/dist-DUcac0X_.js","assets/dist-BPy6CnYN.js","assets/dist-ui4J6fvl.js","assets/dist-qiU0qoeK.js","assets/dist-DSgLBuTS.js","assets/dist-B2SZD_eN.js","assets/dist-B5gFYAn7.js","assets/dist-DcTcc-BG.js","assets/dist-CL6VCrQn.js","assets/dist-DvfTyWk_.js","assets/dist-Dz1Ulpqa.js","assets/dist-B0kq1DQG.js","assets/dist-CnFc5Ssx.js","assets/dist-CWsHar9N.js","assets/dist-OX4k3MMG.js","assets/dist-6_auAGci.js"])))=>i.map(i=>d[i]);
2
+ 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),t.exports),s=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},c=(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},l=(n,r,a)=>(a=n==null?{}:e(i(n)),c(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),u=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.4`})),d=o(((e,t)=>{t.exports=u()})),f=`modulepreload`,p=function(e){return`/app/`+e},m={},h=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=p(t,n),t in m)return;m[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:f,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},g=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})),_=o(((e,t)=>{t.exports=g()}));async function v(){let[{EditorView:e,basicSetup:t},{EditorState:n},{keymap:r},{oneDark:i}]=await Promise.all([h(()=>import(`./dist-2YqVIvgv.js`),__vite__mapDeps([0,1,2,3,4])),h(()=>import(`./dist-Kr-mUYW1.js`).then(e=>e.x),[]),h(()=>import(`./dist-DUcac0X_.js`).then(e=>e.c),__vite__mapDeps([4,3])),h(()=>import(`./dist-BPy6CnYN.js`),__vite__mapDeps([5,2,3,4]))]);return{EditorView:e,EditorState:n,basicSetup:t,keymap:r,oneDark:i}}async function y(e){switch(e.toLowerCase()){case`js`:case`jsx`:case`mjs`:case`cjs`:return(await h(async()=>{let{javascript:e}=await import(`./dist-ui4J6fvl.js`).then(e=>e.t);return{javascript:e}},__vite__mapDeps([6,1,2,3,4,7]))).javascript({jsx:e.includes(`x`)});case`ts`:case`tsx`:case`mts`:case`cts`:return(await h(async()=>{let{javascript:e}=await import(`./dist-ui4J6fvl.js`).then(e=>e.t);return{javascript:e}},__vite__mapDeps([6,1,2,3,4,7]))).javascript({jsx:e.includes(`x`),typescript:!0});case`html`:case`htm`:return(await h(async()=>{let{html:e}=await import(`./dist-DSgLBuTS.js`);return{html:e}},__vite__mapDeps([8,9,2,3,4,7,6,1]))).html();case`css`:case`scss`:return(await h(async()=>{let{css:e}=await import(`./dist-B2SZD_eN.js`).then(e=>e.r);return{css:e}},__vite__mapDeps([9,2,3,4,7]))).css();case`json`:case`jsonl`:return(await h(async()=>{let{json:e}=await import(`./dist-B5gFYAn7.js`);return{json:e}},__vite__mapDeps([10,2,3,4,7]))).json();case`md`:case`mdx`:case`markdown`:return(await h(async()=>{let{markdown:e}=await import(`./dist-DcTcc-BG.js`);return{markdown:e}},__vite__mapDeps([11,1,2,3,4,8,9,7,6]))).markdown();case`py`:case`pyw`:return(await h(async()=>{let{python:e}=await import(`./dist-CL6VCrQn.js`);return{python:e}},__vite__mapDeps([12,1,2,3,4,7]))).python();case`xml`:case`svg`:case`xsl`:case`xhtml`:return(await h(async()=>{let{xml:e}=await import(`./dist-DvfTyWk_.js`);return{xml:e}},__vite__mapDeps([13,2,3,4,7]))).xml();case`yaml`:case`yml`:return(await h(async()=>{let{yaml:e}=await import(`./dist-Dz1Ulpqa.js`);return{yaml:e}},__vite__mapDeps([14,2,3,4,7]))).yaml();case`c`:case`h`:case`cpp`:case`hpp`:case`cc`:case`cxx`:return(await h(async()=>{let{cpp:e}=await import(`./dist-B0kq1DQG.js`);return{cpp:e}},__vite__mapDeps([15,2,3,4,7]))).cpp();case`java`:return(await h(async()=>{let{java:e}=await import(`./dist-CnFc5Ssx.js`);return{java:e}},__vite__mapDeps([16,2,3,4,7]))).java();case`rs`:return(await h(async()=>{let{rust:e}=await import(`./dist-CWsHar9N.js`);return{rust:e}},__vite__mapDeps([17,2,3,4,7]))).rust();case`sql`:return(await h(async()=>{let{sql:e}=await import(`./dist-OX4k3MMG.js`);return{sql:e}},__vite__mapDeps([18,1,2,3,4,7]))).sql();case`php`:return(await h(async()=>{let{php:e}=await import(`./dist-6_auAGci.js`);return{php:e}},__vite__mapDeps([19,8,9,2,3,4,7,6,1]))).php();default:return null}}var b=l(d(),1);function x(e){e===`dark`?document.documentElement.classList.add(`dark`):document.documentElement.classList.remove(`dark`)}function S(){let[e,t]=(0,b.useState)(()=>{let e=localStorage.getItem(`jeeves-theme`)===`dark`?`dark`:`light`;return x(e),e});return(0,b.useEffect)(()=>{x(e)},[e]),[e,(0,b.useCallback)(()=>{t(e=>{let t=e===`dark`?`light`:`dark`;return localStorage.setItem(`jeeves-theme`,t),t})},[])]}export{h as a,s as c,_ as i,l,y as n,d as o,v as r,o as s,S as t};
@@ -6,8 +6,9 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <meta name="robots" content="noindex, nofollow" />
8
8
  <title>Jeeves Server</title>
9
- <script type="module" crossorigin src="/app/assets/index-jSGuHSeS.js"></script>
10
- <link rel="stylesheet" crossorigin href="/app/assets/index-D-RC7ZS6.css">
9
+ <script type="module" crossorigin src="/app/assets/index-DrBXupPz.js"></script>
10
+ <link rel="modulepreload" crossorigin href="/app/assets/theme-CPpIxvB0.js">
11
+ <link rel="stylesheet" crossorigin href="/app/assets/index-Dk_myGs4.css">
11
12
  </head>
12
13
  <body>
13
14
  <div id="root"></div>
@@ -17,7 +17,10 @@ const VALID_CONFIG = {
17
17
  events: {},
18
18
  };
19
19
  function writeConfig(dir, config) {
20
- const filePath = path.join(dir, 'jeeves-server.config.json');
20
+ // Write to the new convention path: {dir}/jeeves-server/config.json
21
+ const configDir = path.join(dir, 'jeeves-server');
22
+ fs.mkdirSync(configDir, { recursive: true });
23
+ const filePath = path.join(configDir, 'config.json');
21
24
  fs.writeFileSync(filePath, JSON.stringify(config));
22
25
  return filePath;
23
26
  }
@@ -32,13 +35,10 @@ describe('jeeves-server config validate', () => {
32
35
  afterEach(() => {
33
36
  fs.rmSync(tmpDir, { recursive: true, force: true });
34
37
  });
35
- it('validates a valid config and prints summary', async () => {
38
+ it('validates a valid config and prints success', async () => {
36
39
  const configPath = writeConfig(tmpDir, VALID_CONFIG);
37
40
  const { stdout } = await runCli(['config', 'validate', '-c', configPath]);
38
41
  expect(stdout).toContain('Configuration valid');
39
- expect(stdout).toContain('Port: 8765');
40
- expect(stdout).toContain('Auth modes: keys');
41
- expect(stdout).toContain('Keys: 2');
42
42
  });
43
43
  it('exits with error for invalid config', async () => {
44
44
  const configPath = writeConfig(tmpDir, { port: 1234 });
@@ -47,38 +47,3 @@ describe('jeeves-server config validate', () => {
47
47
  });
48
48
  });
49
49
  });
50
- describe('jeeves-server config show', () => {
51
- let tmpDir;
52
- beforeEach(() => {
53
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jeeves-cli-'));
54
- });
55
- afterEach(() => {
56
- fs.rmSync(tmpDir, { recursive: true, force: true });
57
- });
58
- it('shows resolved config with key and insider details', async () => {
59
- const configPath = writeConfig(tmpDir, {
60
- ...VALID_CONFIG,
61
- insiders: { 'test@example.com': {} },
62
- watcherUrl: 'http://localhost:3458',
63
- });
64
- const { stdout } = await runCli(['config', 'show', '-c', configPath]);
65
- expect(stdout).toContain('Config file:');
66
- expect(stdout).toContain('port: 8765');
67
- expect(stdout).toContain('modes: keys');
68
- expect(stdout).toContain('primary:');
69
- expect(stdout).toContain('unscoped');
70
- expect(stdout).toContain('test@example.com');
71
- expect(stdout).toContain('watcherUrl: http://localhost:3458');
72
- });
73
- it('shows scoped keys correctly', async () => {
74
- const configPath = writeConfig(tmpDir, {
75
- ...VALID_CONFIG,
76
- keys: {
77
- ...VALID_CONFIG.keys,
78
- scoped: { key: 'c'.repeat(64), scopes: ['/docs'] },
79
- },
80
- });
81
- const { stdout } = await runCli(['config', 'show', '-c', configPath]);
82
- expect(stdout).toContain('scoped (allow: 1, deny: 0)');
83
- });
84
- });
@@ -1,20 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @packageDocumentation
4
- *
5
3
  * jeeves-server CLI entrypoint.
6
- * Commands: start, config validate, config show, service install/uninstall.
4
+ *
5
+ * Uses `createServiceCli(descriptor)` from core for all standard commands.
6
+ * The `start` command uses `descriptor.startCommand` which points to
7
+ * `start-server.ts` for direct in-process server launch.
8
+ *
9
+ * @packageDocumentation
7
10
  */
8
- import { Command } from '@commander-js/extra-typings';
9
- import { packageVersion } from '../util/packageVersion.js';
10
- import { registerConfigCommand } from './commands/config.js';
11
- import { registerServiceCommand } from './commands/service.js';
12
- import { registerStartCommand } from './commands/start.js';
13
- const cli = new Command()
14
- .name('jeeves-server')
15
- .description('Self-hosted file browser, document server, and webhook gateway')
16
- .version(packageVersion);
17
- registerStartCommand(cli);
18
- registerConfigCommand(cli);
19
- registerServiceCommand(cli);
11
+ import { createServiceCli } from '@karmaniverous/jeeves';
12
+ import { serverDescriptor } from '../descriptor.js';
13
+ const cli = createServiceCli(serverDescriptor);
20
14
  cli.parse();
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Minimal server launcher for use by system service managers (NSSM, systemd, launchd).
4
+ *
5
+ * This is the entry point referenced by `descriptor.startCommand`. It initializes
6
+ * config from the `--config` CLI argument and starts the Fastify server directly,
7
+ * without going through the full Commander CLI.
8
+ *
9
+ * The CLI's `start` command uses this same logic in-process.
10
+ */
11
+ import { initConfig } from '../config/index.js';
12
+ const configIndex = process.argv.indexOf('--config');
13
+ const configPath = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
14
+ initConfig(configPath);
15
+ // Dynamic import to ensure config is initialized before server modules load
16
+ await import('../server.js');
@@ -2,60 +2,71 @@
2
2
  * @packageDocumentation
3
3
  *
4
4
  * Config loading and singleton management.
5
- * Loads config via cosmiconfig, validates with Zod, applies env var substitution,
5
+ * Loads config from a JSON file, validates with Zod, applies env var substitution,
6
6
  * resolves runtime types via resolve.ts, and exposes getConfig()/resetConfig().
7
7
  */
8
+ import fs from 'node:fs';
8
9
  import path from 'node:path';
9
10
  import { fileURLToPath } from 'node:url';
10
- import { cosmiconfig } from 'cosmiconfig';
11
+ import { migrateConfigPath } from './migration.js';
11
12
  import { buildRuntimeConfig } from './resolve.js';
12
13
  import { jeevesConfigSchema } from './schema.js';
13
14
  import { substituteEnvVars } from './substituteEnvVars.js';
14
15
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
16
  const rootDir = path.resolve(__dirname, '../../..');
16
- const MODULE_NAME = 'jeeves-server';
17
17
  /**
18
- * Load and validate jeeves-server configuration via cosmiconfig.
19
- *
20
- * Searches for `jeeves-server.config.{json,yaml,yml,js,ts,cjs,mjs}`
21
- * or `.jeeves-serverrc` in the package root and parent directories.
18
+ * Load and validate jeeves-server configuration from a JSON file.
22
19
  *
23
20
  * @param configPath - Optional explicit path to a config file.
24
21
  * @returns Resolved runtime configuration.
25
22
  */
26
- export async function loadConfig(configPath) {
27
- const explorer = cosmiconfig(MODULE_NAME, {
28
- searchPlaces: [
29
- 'package.json',
30
- `.${MODULE_NAME}rc`,
31
- `.${MODULE_NAME}rc.json`,
32
- `.${MODULE_NAME}rc.yaml`,
33
- `.${MODULE_NAME}rc.yml`,
34
- `${MODULE_NAME}.config.json`,
35
- `${MODULE_NAME}.config.yaml`,
36
- `${MODULE_NAME}.config.yml`,
37
- `${MODULE_NAME}.config.js`,
38
- `${MODULE_NAME}.config.ts`,
39
- `${MODULE_NAME}.config.mjs`,
40
- `${MODULE_NAME}.config.cjs`,
41
- ],
42
- });
43
- const result = configPath
44
- ? await explorer.load(configPath)
45
- : await explorer.search(rootDir);
46
- if (!result || result.isEmpty) {
47
- throw new Error(`No jeeves-server configuration found. Create a jeeves-server.config.json (or .yaml) file.\n` +
48
- `Searched from: ${rootDir}`);
23
+ export function loadConfig(configPath) {
24
+ const resolvedPath = configPath
25
+ ? migrateConfigPath(configPath)
26
+ : findDefaultConfig();
27
+ if (!fs.existsSync(resolvedPath)) {
28
+ throw new Error(`Configuration file not found: ${resolvedPath}\n` +
29
+ `Create a jeeves-server config.json file or pass --config <path>.`);
30
+ }
31
+ // Reject non-JSON config files
32
+ const ext = path.extname(resolvedPath).toLowerCase();
33
+ if (ext && ext !== '.json') {
34
+ throw new Error(`Unsupported config file format: ${ext}\n` +
35
+ `Only JSON configuration files are supported. ` +
36
+ `Please convert your config to JSON format.`);
37
+ }
38
+ const rawContent = fs.readFileSync(resolvedPath, 'utf8');
39
+ let rawConfig;
40
+ try {
41
+ rawConfig = JSON.parse(rawContent);
42
+ }
43
+ catch (err) {
44
+ throw new Error(`Failed to parse config file ${resolvedPath}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
49
45
  }
50
- const substituted = substituteEnvVars(result.config);
46
+ const substituted = substituteEnvVars(rawConfig);
51
47
  const parseResult = jeevesConfigSchema.safeParse(substituted);
52
48
  if (!parseResult.success) {
53
49
  const issues = parseResult.error.issues
54
50
  .map((i) => ` - ${i.path.join('.')}: ${i.message}`)
55
51
  .join('\n');
56
- throw new Error(`Invalid configuration in ${result.filepath}:\n${issues}`);
52
+ throw new Error(`Invalid configuration in ${resolvedPath}:\n${issues}`);
57
53
  }
58
- return buildRuntimeConfig(parseResult.data, rootDir, result.filepath);
54
+ return buildRuntimeConfig(parseResult.data, rootDir, resolvedPath);
55
+ }
56
+ /**
57
+ * Find the default config file in the package root directory.
58
+ */
59
+ function findDefaultConfig() {
60
+ // Try new convention first
61
+ const newPath = path.join(rootDir, 'jeeves-server', 'config.json');
62
+ if (fs.existsSync(newPath))
63
+ return newPath;
64
+ // Fall back to old convention
65
+ const oldPath = path.join(rootDir, 'jeeves-server.config.json');
66
+ if (fs.existsSync(oldPath))
67
+ return oldPath;
68
+ // Return new path for error message
69
+ return newPath;
59
70
  }
60
71
  let configInstance = null;
61
72
  let lastConfigPath;
@@ -79,17 +90,17 @@ export function getConfig() {
79
90
  * Initialize the config singleton. Must be called once at startup.
80
91
  * @param configPath - Optional explicit path to a config file.
81
92
  */
82
- export async function initConfig(configPath) {
93
+ export function initConfig(configPath) {
83
94
  lastConfigPath = configPath;
84
- configInstance = await loadConfig(configPath);
95
+ configInstance = loadConfig(configPath);
85
96
  return configInstance;
86
97
  }
87
98
  /**
88
99
  * Reload the config singleton from the last-used config path.
89
100
  * Call after mutating state that affects resolved config (e.g., key rotation).
90
101
  */
91
- export async function resetConfig() {
92
- configInstance = await loadConfig(lastConfigPath);
102
+ export function resetConfig() {
103
+ configInstance = loadConfig(lastConfigPath);
93
104
  }
94
105
  /**
95
106
  * Clear the config singleton (for testing only).
@@ -28,21 +28,23 @@ describe('loadConfig', () => {
28
28
  fs.rmSync(tmpDir, { recursive: true, force: true });
29
29
  clearConfig();
30
30
  });
31
- it('loads a valid JSON config file', async () => {
31
+ it('loads a valid JSON config file', () => {
32
32
  const configPath = writeConfig(tmpDir, VALID_CONFIG);
33
- const config = await loadConfig(configPath);
33
+ const config = loadConfig(configPath);
34
34
  expect(config.port).toBe(9999);
35
35
  expect(config.chromePath).toBe('/usr/bin/chromium');
36
- expect(config.configPath).toBe(configPath);
36
+ // Migration moves jeeves-server.config.json → jeeves-server/config.json
37
+ const expectedPath = path.join(tmpDir, 'jeeves-server', 'config.json');
38
+ expect(config.configPath).toBe(expectedPath);
37
39
  });
38
- it('throws on missing config', async () => {
39
- await expect(loadConfig(path.join(tmpDir, 'nonexistent.json'))).rejects.toThrow();
40
+ it('throws on missing config', () => {
41
+ expect(() => loadConfig(path.join(tmpDir, 'nonexistent.json'))).toThrow();
40
42
  });
41
- it('throws on invalid config (missing auth)', async () => {
43
+ it('throws on invalid config (missing auth)', () => {
42
44
  const configPath = writeConfig(tmpDir, { port: 1234 });
43
- await expect(loadConfig(configPath)).rejects.toThrow('Invalid configuration');
45
+ expect(() => loadConfig(configPath)).toThrow('Invalid configuration');
44
46
  });
45
- it('applies env var substitution', async () => {
47
+ it('applies env var substitution', () => {
46
48
  const original = process.env['TEST_CHROME_PATH'];
47
49
  process.env['TEST_CHROME_PATH'] = '/custom/chrome';
48
50
  try {
@@ -50,7 +52,7 @@ describe('loadConfig', () => {
50
52
  ...VALID_CONFIG,
51
53
  chromePath: '${TEST_CHROME_PATH}',
52
54
  });
53
- const config = await loadConfig(configPath);
55
+ const config = loadConfig(configPath);
54
56
  expect(config.chromePath).toBe('/custom/chrome');
55
57
  }
56
58
  finally {
@@ -60,14 +62,14 @@ describe('loadConfig', () => {
60
62
  process.env['TEST_CHROME_PATH'] = original;
61
63
  }
62
64
  });
63
- it('applies default port when omitted', async () => {
65
+ it('applies default port when omitted', () => {
64
66
  const noPort = { ...VALID_CONFIG };
65
67
  delete noPort.port;
66
68
  const configPath = writeConfig(tmpDir, noPort);
67
- const config = await loadConfig(configPath);
69
+ const config = loadConfig(configPath);
68
70
  expect(config.port).toBe(1934);
69
71
  });
70
- it('rejects _plugin key with scopes', async () => {
72
+ it('rejects _plugin key with scopes', () => {
71
73
  const configPath = writeConfig(tmpDir, {
72
74
  ...VALID_CONFIG,
73
75
  keys: {
@@ -75,9 +77,9 @@ describe('loadConfig', () => {
75
77
  _plugin: { key: 'c'.repeat(64), scopes: ['/restricted'] },
76
78
  },
77
79
  });
78
- await expect(loadConfig(configPath)).rejects.toThrow('_plugin key must not have scopes');
80
+ expect(() => loadConfig(configPath)).toThrow('_plugin key must not have scopes');
79
81
  });
80
- it('rejects _internal key with scopes', async () => {
82
+ it('rejects _internal key with scopes', () => {
81
83
  const configPath = writeConfig(tmpDir, {
82
84
  ...VALID_CONFIG,
83
85
  keys: {
@@ -85,9 +87,9 @@ describe('loadConfig', () => {
85
87
  _internal: { key: 'b'.repeat(64), scopes: ['/restricted'] },
86
88
  },
87
89
  });
88
- await expect(loadConfig(configPath)).rejects.toThrow('_internal key must not have scopes');
90
+ expect(() => loadConfig(configPath)).toThrow('_internal key must not have scopes');
89
91
  });
90
- it('accepts _plugin key without scopes', async () => {
92
+ it('accepts _plugin key without scopes', () => {
91
93
  const configPath = writeConfig(tmpDir, {
92
94
  ...VALID_CONFIG,
93
95
  keys: {
@@ -95,10 +97,10 @@ describe('loadConfig', () => {
95
97
  _plugin: 'c'.repeat(64),
96
98
  },
97
99
  });
98
- const config = await loadConfig(configPath);
100
+ const config = loadConfig(configPath);
99
101
  expect(config.resolvedKeys.find((k) => k.name === '_plugin')?.seed).toBe('c'.repeat(64));
100
102
  });
101
- it('rejects undefined named scope references', async () => {
103
+ it('rejects undefined named scope references', () => {
102
104
  const configPath = writeConfig(tmpDir, {
103
105
  ...VALID_CONFIG,
104
106
  scopes: { restricted: { allow: ['/**'], deny: ['/secret'] } },
@@ -107,16 +109,16 @@ describe('loadConfig', () => {
107
109
  'b@example.com': { scopes: 'missing' },
108
110
  },
109
111
  });
110
- await expect(loadConfig(configPath)).rejects.toThrow('Scope "missing" is not defined');
112
+ expect(() => loadConfig(configPath)).toThrow('Scope "missing" is not defined');
111
113
  });
112
- it('does not treat path globs as named scope references', async () => {
114
+ it('does not treat path globs as named scope references', () => {
113
115
  const configPath = writeConfig(tmpDir, {
114
116
  ...VALID_CONFIG,
115
117
  insiders: {
116
118
  'a@example.com': { scopes: ['/docs/**'] },
117
119
  },
118
120
  });
119
- const config = await loadConfig(configPath);
121
+ const config = loadConfig(configPath);
120
122
  expect(config.resolvedInsiders.find((i) => i.email === 'a@example.com')?.scopes).toEqual({
121
123
  allow: ['/docs/**'],
122
124
  deny: [],
@@ -138,15 +140,15 @@ describe('config singleton', () => {
138
140
  it('throws if getConfig called before initConfig', () => {
139
141
  expect(() => getConfig()).toThrow('Config not initialized');
140
142
  });
141
- it('initConfig populates getConfig', async () => {
143
+ it('initConfig populates getConfig', () => {
142
144
  const configPath = writeConfig(tmpDir, VALID_CONFIG);
143
- await initConfig(configPath);
145
+ initConfig(configPath);
144
146
  const config = getConfig();
145
147
  expect(config.port).toBe(9999);
146
148
  });
147
- it('clearConfig clears the singleton', async () => {
149
+ it('clearConfig clears the singleton', () => {
148
150
  const configPath = writeConfig(tmpDir, VALID_CONFIG);
149
- await initConfig(configPath);
151
+ initConfig(configPath);
150
152
  clearConfig();
151
153
  expect(() => getConfig()).toThrow('Config not initialized');
152
154
  });
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Config path migration — handles old → new config path convention.
3
+ *
4
+ * Old convention: `<configDir>/jeeves-server.config.json`
5
+ * New convention: `<configDir>/jeeves-server/config.json`
6
+ */
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+ const NON_JSON_EXTENSIONS = new Set([
10
+ '.ts',
11
+ '.yaml',
12
+ '.yml',
13
+ '.toml',
14
+ '.mjs',
15
+ '.cjs',
16
+ '.js',
17
+ ]);
18
+ /**
19
+ * Migrate config path from old convention to new convention if needed.
20
+ *
21
+ * If the passed path matches the old convention (jeeves-server.config.json)
22
+ * and the new path does not exist, migrates the file. If non-JSON config
23
+ * is found, rejects with a clear error.
24
+ *
25
+ * @param configPath - The config path passed via --config CLI flag.
26
+ * @returns The resolved config path (may be the new path after migration).
27
+ */
28
+ export function migrateConfigPath(configPath) {
29
+ const ext = path.extname(configPath).toLowerCase();
30
+ // Reject non-JSON config files
31
+ if (NON_JSON_EXTENSIONS.has(ext)) {
32
+ throw new Error(`Unsupported config file format: ${ext}\n` +
33
+ `Only JSON configuration files are supported. ` +
34
+ `Please convert your config to JSON format.`);
35
+ }
36
+ const basename = path.basename(configPath);
37
+ const configDir = path.dirname(configPath);
38
+ // Check if this matches the old convention
39
+ if (basename !== 'jeeves-server.config.json') {
40
+ return configPath;
41
+ }
42
+ const newDir = path.join(configDir, 'jeeves-server');
43
+ const newPath = path.join(newDir, 'config.json');
44
+ // If new path already exists, use it
45
+ if (fs.existsSync(newPath)) {
46
+ console.log(`[config-migration] Using new config path: ${newPath} ` +
47
+ `(old path ${configPath} is superseded)`);
48
+ return newPath;
49
+ }
50
+ // If old path exists, migrate it
51
+ if (fs.existsSync(configPath)) {
52
+ console.log(`[config-migration] Migrating config: ${configPath} → ${newPath}`);
53
+ fs.mkdirSync(newDir, { recursive: true });
54
+ fs.renameSync(configPath, newPath);
55
+ console.log(`[config-migration] Migration complete.`);
56
+ return newPath;
57
+ }
58
+ // Neither exists — return the passed path for downstream error handling
59
+ return configPath;
60
+ }
@@ -1,3 +1,4 @@
1
+ import { SERVER_PORT } from '@karmaniverous/jeeves';
1
2
  import { z } from 'zod';
2
3
  /** Supported authentication methods */
3
4
  export const authModeSchema = z.enum(['google', 'keys']);
@@ -88,7 +89,7 @@ function getScopeRefs(scopes) {
88
89
  /** Top-level Jeeves Server configuration */
89
90
  export const jeevesConfigSchema = z
90
91
  .object({
91
- port: z.number().int().positive().default(1934),
92
+ port: z.number().int().positive().default(SERVER_PORT),
92
93
  /**
93
94
  * Network interface to bind the server to.
94
95
  * Default: '0.0.0.0' (all interfaces — required for external access by insiders, share links, etc.)
@@ -115,7 +116,7 @@ export const jeevesConfigSchema = z
115
116
  roots: z.record(z.string(), z.string()).optional(),
116
117
  /**
117
118
  * URL of the jeeves-runner API for process dashboard proxy.
118
- * Default: 'http://127.0.0.1:3100'
119
+ * Default: 'http://127.0.0.1:1937'
119
120
  */
120
121
  runnerUrl: z.url().optional(),
121
122
  /** @deprecated Mermaid is now bundled. This field is ignored but kept for backward compatibility. */
@@ -142,7 +143,7 @@ export const jeevesConfigSchema = z
142
143
  diagramCachePath: z.string().optional(),
143
144
  /**
144
145
  * URL of the jeeves-watcher API for semantic search.
145
- * When set, the search UI appears in the header. Example: 'http://localhost:3458'
146
+ * When set, the search UI appears in the header. Example: 'http://127.0.0.1:1936'
146
147
  */
147
148
  watcherUrl: z.url().optional(),
148
149
  /**
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Server-side JeevesComponentDescriptor for the jeeves-server component.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { jeevesComponentDescriptorSchema, SERVER_PORT, } from '@karmaniverous/jeeves';
9
+ import { jeevesConfigSchema } from './config/schema.js';
10
+ import { packageVersion } from './util/packageVersion.js';
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ /** Absolute path to the start-server entry point (resolves correctly from any cwd). */
13
+ const startServerPath = path.resolve(__dirname, 'cli', 'start-server.js');
14
+ export const serverDescriptor = jeevesComponentDescriptorSchema.parse({
15
+ name: 'server',
16
+ version: packageVersion,
17
+ servicePackage: '@karmaniverous/jeeves-server',
18
+ pluginPackage: '@karmaniverous/jeeves-server-openclaw',
19
+ defaultPort: SERVER_PORT,
20
+ configSchema: jeevesConfigSchema,
21
+ configFileName: 'config.json',
22
+ initTemplate: () => ({
23
+ chromePath: 'CHANGE_ME_chromePath',
24
+ auth: {
25
+ modes: ['keys'],
26
+ sessionSecret: 'CHANGE_ME_sessionSecret',
27
+ },
28
+ keys: {
29
+ default: 'CHANGE_ME_defaultKey',
30
+ },
31
+ }),
32
+ onConfigApply: async () => {
33
+ const { resetConfig } = await import('./config/index.js');
34
+ resetConfig();
35
+ },
36
+ startCommand: (configPath) => [
37
+ 'node',
38
+ startServerPath,
39
+ '--config',
40
+ configPath,
41
+ ],
42
+ sectionId: 'Server',
43
+ refreshIntervalSeconds: 61,
44
+ generateToolsContent: () => '',
45
+ dependencies: { hard: [], soft: ['watcher', 'runner', 'meta'] },
46
+ });