openclaw-manager 0.1.1

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 (49) hide show
  1. package/bin/openclaw-manager.js +198 -0
  2. package/dist/app.js +39 -0
  3. package/dist/controllers/auth.controller.js +19 -0
  4. package/dist/controllers/cli.controller.js +10 -0
  5. package/dist/controllers/discord.controller.js +21 -0
  6. package/dist/controllers/jobs.controller.js +138 -0
  7. package/dist/controllers/process.controller.js +26 -0
  8. package/dist/controllers/quickstart.controller.js +11 -0
  9. package/dist/controllers/status.controller.js +10 -0
  10. package/dist/deps.js +1 -0
  11. package/dist/dev.js +156 -0
  12. package/dist/index.js +37 -0
  13. package/dist/lib/auth.js +57 -0
  14. package/dist/lib/commands.js +123 -0
  15. package/dist/lib/config.js +48 -0
  16. package/dist/lib/constants.js +9 -0
  17. package/dist/lib/gateway.js +37 -0
  18. package/dist/lib/jobs.js +117 -0
  19. package/dist/lib/onboarding.js +96 -0
  20. package/dist/lib/runner.js +99 -0
  21. package/dist/lib/static.js +69 -0
  22. package/dist/lib/system.js +31 -0
  23. package/dist/lib/utils.js +31 -0
  24. package/dist/middlewares/auth.js +23 -0
  25. package/dist/routes/auth.js +5 -0
  26. package/dist/routes/cli.js +4 -0
  27. package/dist/routes/discord.js +5 -0
  28. package/dist/routes/health.js +9 -0
  29. package/dist/routes/index.js +18 -0
  30. package/dist/routes/jobs.js +11 -0
  31. package/dist/routes/processes.js +6 -0
  32. package/dist/routes/quickstart.js +4 -0
  33. package/dist/routes/status.js +4 -0
  34. package/dist/services/auth.service.js +24 -0
  35. package/dist/services/cli.service.js +21 -0
  36. package/dist/services/discord.service.js +38 -0
  37. package/dist/services/jobs.service.js +307 -0
  38. package/dist/services/process.service.js +9 -0
  39. package/dist/services/quickstart.service.js +124 -0
  40. package/dist/services/resource.service.js +46 -0
  41. package/dist/services/status.service.js +32 -0
  42. package/package.json +18 -0
  43. package/web-dist/assets/index-BabnD_ew.js +13 -0
  44. package/web-dist/assets/index-CBtcOjoT.css +1 -0
  45. package/web-dist/docker.sh +62 -0
  46. package/web-dist/index.html +13 -0
  47. package/web-dist/install.ps1 +110 -0
  48. package/web-dist/install.sh +261 -0
  49. package/web-dist/stop.sh +52 -0
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600&family=Space+Grotesk:wght@400;500;600;700&display=swap";*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.bottom-\[-10\%\]{bottom:-10%}.left-\[-20\%\]{left:-20%}.left-\[2\.25rem\]{left:2.25rem}.right-\[-10\%\]{right:-10%}.top-\[-10\%\]{top:-10%}.top-\[3\.5rem\]{top:3.5rem}.z-10{z-index:10}.mx-auto{margin-left:auto;margin-right:auto}.mb-10{margin-bottom:2.5rem}.mb-2{margin-bottom:.5rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.flex{display:flex}.inline-flex{display:inline-flex}.hidden{display:none}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-20{height:5rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-80{height:20rem}.h-9{height:2.25rem}.h-96{height:24rem}.h-px{height:1px}.max-h-40{max-height:10rem}.max-h-48{max-height:12rem}.min-h-screen{min-height:100vh}.w-0\.5{width:.125rem}.w-10{width:2.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-20{width:5rem}.w-3{width:.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-80{width:20rem}.w-96{width:24rem}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-lg{max-width:32rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded-2xl{border-radius:1rem}.rounded-3xl{border-radius:1.5rem}.rounded-full{border-radius:9999px}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-line{border-color:hsl(var(--line))}.border-line\/40{border-color:hsl(var(--line) / .4)}.border-line\/50{border-color:hsl(var(--line) / .5)}.border-line\/60{border-color:hsl(var(--line) / .6)}.border-line\/70{border-color:hsl(var(--line) / .7)}.border-line\/80{border-color:hsl(var(--line) / .8)}.border-success{border-color:hsl(var(--success))}.bg-accent{background-color:hsl(var(--accent))}.bg-accent-2\/20{background-color:hsl(var(--accent-2) / .2)}.bg-accent\/10{background-color:hsl(var(--accent) / .1)}.bg-accent\/15{background-color:hsl(var(--accent) / .15)}.bg-bg{background-color:hsl(var(--bg))}.bg-black\/80{background-color:#000c}.bg-danger{background-color:hsl(var(--danger))}.bg-danger\/15{background-color:hsl(var(--danger) / .15)}.bg-ink\/10{background-color:hsl(var(--ink) / .1)}.bg-ink\/5{background-color:hsl(var(--ink) / .05)}.bg-line\/20{background-color:hsl(var(--line) / .2)}.bg-line\/30{background-color:hsl(var(--line) / .3)}.bg-line\/50{background-color:hsl(var(--line) / .5)}.bg-line\/70{background-color:hsl(var(--line) / .7)}.bg-success{background-color:hsl(var(--success))}.bg-success\/10{background-color:hsl(var(--success) / .1)}.bg-success\/15{background-color:hsl(var(--success) / .15)}.bg-warning\/10{background-color:hsl(var(--warning) / .1)}.bg-warning\/15{background-color:hsl(var(--warning) / .15)}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/40{background-color:#fff6}.bg-white\/60{background-color:#fff9}.bg-white\/70{background-color:#ffffffb3}.bg-white\/80{background-color:#fffc}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-widest{letter-spacing:.1em}.text-accent{color:hsl(var(--accent))}.text-danger{color:hsl(var(--danger))}.text-emerald-200{--tw-text-opacity: 1;color:rgb(167 243 208 / var(--tw-text-opacity, 1))}.text-emerald-300{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity, 1))}.text-ink{color:hsl(var(--ink))}.text-muted{color:hsl(var(--muted))}.text-success{color:hsl(var(--success))}.text-warning{color:hsl(var(--warning))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.opacity-60{opacity:.6}.opacity-90{opacity:.9}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-accent\/30{--tw-shadow-color: hsl(var(--accent) / .3);--tw-shadow: var(--tw-shadow-colored)}.outline{outline-style:solid}.blur-\[140px\]{--tw-blur: blur(140px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-\[150px\]{--tw-blur: blur(150px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur{--tw-backdrop-blur: blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-xl{--tw-backdrop-blur: blur(24px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}@keyframes enter{0%{opacity:var(--tw-enter-opacity, 1);transform:translate3d(var(--tw-enter-translate-x, 0),var(--tw-enter-translate-y, 0),0) scale3d(var(--tw-enter-scale, 1),var(--tw-enter-scale, 1),var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity, 1);transform:translate3d(var(--tw-exit-translate-x, 0),var(--tw-exit-translate-y, 0),0) scale3d(var(--tw-exit-scale, 1),var(--tw-exit-scale, 1),var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))}}.duration-300{animation-duration:.3s}.running{animation-play-state:running}:root{--bg: 36 40% 96%;--surface: 0 0% 100%;--ink: 226 24% 16%;--muted: 217 12% 46%;--accent: 17 90% 55%;--accent-2: 197 80% 38%;--line: 222 14% 85%;--success: 148 48% 40%;--warning: 35 92% 55%;--danger: 0 80% 55%}*{box-sizing:border-box}body{margin:0;font-family:Instrument Sans,Helvetica Neue,sans-serif;color:hsl(var(--ink))}h1,h2,h3,h4,h5,h6{font-family:Space Grotesk,Helvetica Neue,sans-serif}.bg-hero-pattern{background-image:radial-gradient(circle at top,hsla(var(--accent) / .08),transparent 55%),radial-gradient(circle at 20% 20%,hsla(var(--accent-2) / .12),transparent 40%),linear-gradient(135deg,hsla(var(--accent) / .08),hsla(var(--accent-2) / .12))}@keyframes fade-up{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}.animate-fade-up{animation:fade-up .6s ease forwards}.shadow-soft{box-shadow:0 12px 40px -28px #0f172a73}@keyframes bounce-once{0%,to{transform:scale(1)}50%{transform:scale(1.15)}}.animate-bounce-once{animation:bounce-once .4s ease}@keyframes pulse-subtle{0%,to{opacity:1}50%{opacity:.6}}.animate-pulse-subtle{animation:pulse-subtle 2s ease-in-out infinite}.hover\:translate-y-\[-1px\]:hover{--tw-translate-y: -1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:bg-ink\/5:hover{background-color:hsl(var(--ink) / .05)}.hover\:bg-white:hover{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.hover\:text-accent:hover{color:hsl(var(--accent))}.hover\:underline:hover{text-decoration-line:underline}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-accent\/40:focus{--tw-ring-color: hsl(var(--accent) / .4)}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-accent:focus-visible{--tw-ring-color: hsl(var(--accent))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:640px){.sm\:inline{display:inline}}@media(min-width:768px){.md\:flex{display:flex}.md\:hidden{display:none}.md\:p-12{padding:3rem}}
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ NAME="${MANAGER_DOCKER_NAME:-moltbot-manager}"
5
+ PORT="${MANAGER_API_PORT:-17321}"
6
+ ADMIN_USER="${MANAGER_ADMIN_USER:-admin}"
7
+ ADMIN_PASS="${MANAGER_ADMIN_PASS:-pass}"
8
+ REPO_URL="${MANAGER_REPO_URL:-https://github.com/Peiiii/moltbot-manager.git}"
9
+ VOLUME="${MANAGER_CONFIG_VOLUME:-moltbot-manager-config}"
10
+ GATEWAY_TIMEOUT_MS="${MANAGER_GATEWAY_TIMEOUT_MS:-}"
11
+
12
+ EXTRA_ENV=()
13
+ if [[ -n "$GATEWAY_TIMEOUT_MS" ]]; then
14
+ EXTRA_ENV+=("-e" "MANAGER_GATEWAY_TIMEOUT_MS=$GATEWAY_TIMEOUT_MS")
15
+ fi
16
+
17
+ docker rm -f "$NAME" 2>/dev/null || true
18
+ docker volume create "$VOLUME" >/dev/null
19
+
20
+ docker run -d --name "$NAME" -p "${PORT}:${PORT}" \
21
+ -e MANAGER_ADMIN_USER="$ADMIN_USER" \
22
+ -e MANAGER_ADMIN_PASS="$ADMIN_PASS" \
23
+ -e MANAGER_API_HOST=0.0.0.0 \
24
+ -e MANAGER_API_PORT="$PORT" \
25
+ -e MANAGER_WEB_DIST=/opt/moltbot-manager/apps/web/dist \
26
+ -e MANAGER_CONFIG_PATH=/etc/clawdbot-manager/config.json \
27
+ "${EXTRA_ENV[@]}" \
28
+ -v "$VOLUME":/etc/clawdbot-manager \
29
+ node:22-bullseye bash -lc "set -euo pipefail; \
30
+ REPO_URL=\"$REPO_URL\"; \
31
+ apt-get update -y >/dev/null; \
32
+ apt-get install -y --no-install-recommends git curl ca-certificates >/dev/null; \
33
+ corepack enable; corepack prepare pnpm@10.23.0 --activate; \
34
+ git clone \"$REPO_URL\" /opt/moltbot-manager; \
35
+ cd /opt/moltbot-manager; \
36
+ CI=true pnpm install >/dev/null; pnpm build >/dev/null; \
37
+ node apps/api/scripts/create-admin.mjs --username \"\$MANAGER_ADMIN_USER\" --password \"\$MANAGER_ADMIN_PASS\" --config /etc/clawdbot-manager/config.json; \
38
+ exec node /opt/moltbot-manager/apps/api/dist/index.js"
39
+
40
+ if command -v curl >/dev/null 2>&1; then
41
+ for _ in {1..120}; do
42
+ if curl -fsS "http://127.0.0.1:${PORT}/health" >/dev/null 2>&1; then
43
+ break
44
+ fi
45
+ sleep 1
46
+ done
47
+ else
48
+ echo "[manager] curl not found; skip readiness check."
49
+ fi
50
+
51
+ PUBLIC_HOST="${MANAGER_PUBLIC_HOST:-}"
52
+ if [[ -z "$PUBLIC_HOST" ]] && command -v curl >/dev/null 2>&1; then
53
+ PUBLIC_HOST="$(curl -fsS https://api.ipify.org 2>/dev/null || true)"
54
+ fi
55
+
56
+ echo "[manager] Open (local): http://127.0.0.1:${PORT}"
57
+ if [[ -n "$PUBLIC_HOST" ]]; then
58
+ echo "[manager] Open (public): http://${PUBLIC_HOST}:${PORT}"
59
+ else
60
+ echo "[manager] Open (public): set MANAGER_PUBLIC_HOST to print public URL"
61
+ fi
62
+ echo "[manager] Login: ${ADMIN_USER} / ${ADMIN_PASS}"
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Clawdbot Manager</title>
7
+ <script type="module" crossorigin src="/assets/index-BabnD_ew.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-CBtcOjoT.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,110 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $defaultRepoUrl = "https://github.com/Peiiii/moltbot-manager.git"
4
+ $repoUrl = $env:MANAGER_REPO_URL
5
+ $apiPort = if ($env:MANAGER_API_PORT) { $env:MANAGER_API_PORT } else { "17321" }
6
+ $apiHost = if ($env:MANAGER_API_HOST) { $env:MANAGER_API_HOST } else { "0.0.0.0" }
7
+
8
+ if (-not $repoUrl) {
9
+ $repoUrl = $defaultRepoUrl
10
+ Write-Host "[manager] MANAGER_REPO_URL not set. Using default: $repoUrl"
11
+ }
12
+
13
+ function Require-Command {
14
+ param(
15
+ [Parameter(Mandatory = $true)][string]$Name,
16
+ [string]$Hint
17
+ )
18
+ if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
19
+ if ($Hint) { Write-Error $Hint } else { Write-Error "[manager] $Name is required." }
20
+ exit 1
21
+ }
22
+ }
23
+
24
+ Require-Command -Name "git"
25
+ Require-Command -Name "node" -Hint "[manager] Node.js is required."
26
+
27
+ if (-not (Get-Command "pnpm" -ErrorAction SilentlyContinue)) {
28
+ if (Get-Command "corepack" -ErrorAction SilentlyContinue) {
29
+ corepack enable | Out-Null
30
+ corepack prepare pnpm@10.23.0 --activate | Out-Null
31
+ } else {
32
+ Write-Error "[manager] pnpm is required. Install via: npm i -g pnpm"
33
+ exit 1
34
+ }
35
+ }
36
+
37
+ $installDir = if ($env:MANAGER_INSTALL_DIR) { $env:MANAGER_INSTALL_DIR } else { Join-Path $env:USERPROFILE "clawdbot-manager" }
38
+ $configDir = if ($env:MANAGER_CONFIG_DIR) { $env:MANAGER_CONFIG_DIR } else { Join-Path $env:USERPROFILE ".clawdbot-manager" }
39
+
40
+ if (Test-Path $installDir) {
41
+ if (-not (Test-Path (Join-Path $installDir ".git"))) {
42
+ Write-Error "[manager] Install dir exists and is not a git repo: $installDir. Please choose an empty directory or remove it, then retry."
43
+ exit 1
44
+ }
45
+ }
46
+
47
+ if (Test-Path (Join-Path $installDir ".git")) {
48
+ Write-Host "[manager] Updating $installDir"
49
+ git -C $installDir pull --rebase
50
+ } else {
51
+ Write-Host "[manager] Cloning to $installDir"
52
+ git clone $repoUrl $installDir
53
+ }
54
+
55
+ Set-Location $installDir
56
+
57
+ if (-not $env:MANAGER_ADMIN_USER) {
58
+ $env:MANAGER_ADMIN_USER = Read-Host "Admin username"
59
+ }
60
+
61
+ if (-not $env:MANAGER_ADMIN_PASS) {
62
+ $secure = Read-Host "Admin password" -AsSecureString
63
+ $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure)
64
+ try {
65
+ $env:MANAGER_ADMIN_PASS = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr)
66
+ } finally {
67
+ [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr)
68
+ }
69
+ }
70
+
71
+ pnpm install
72
+ pnpm build
73
+
74
+ New-Item -ItemType Directory -Force -Path $configDir | Out-Null
75
+
76
+ node apps/api/scripts/create-admin.mjs `
77
+ --username "$($env:MANAGER_ADMIN_USER)" `
78
+ --password "$($env:MANAGER_ADMIN_PASS)" `
79
+ --config (Join-Path $configDir "config.json")
80
+
81
+ $logPath = if ($env:MANAGER_LOG_PATH) { $env:MANAGER_LOG_PATH } else { Join-Path $env:TEMP "clawdbot-manager.log" }
82
+ $errorLogPath = if ($env:MANAGER_ERROR_LOG_PATH) { $env:MANAGER_ERROR_LOG_PATH } else { Join-Path $env:TEMP "clawdbot-manager.error.log" }
83
+ if ($errorLogPath -eq $logPath) {
84
+ $errorLogPath = "$logPath.err"
85
+ }
86
+ $webDist = Join-Path $installDir "apps/web/dist"
87
+ $configPath = Join-Path $configDir "config.json"
88
+ $pidPath = Join-Path $configDir "manager.pid"
89
+
90
+ $env:MANAGER_API_HOST = $apiHost
91
+ $env:MANAGER_API_PORT = $apiPort
92
+ $env:MANAGER_WEB_DIST = $webDist
93
+ $env:MANAGER_CONFIG_PATH = $configPath
94
+
95
+ $proc = Start-Process -FilePath "node" `
96
+ -ArgumentList "$installDir\\apps\\api\\dist\\index.js" `
97
+ -WorkingDirectory $installDir `
98
+ -WindowStyle Hidden `
99
+ -RedirectStandardOutput $logPath `
100
+ -RedirectStandardError $errorLogPath `
101
+ -PassThru
102
+
103
+ $proc.Id | Out-File -Encoding ascii $pidPath
104
+
105
+ Write-Host "[manager] Started in background (log: $logPath)."
106
+ Write-Host "[manager] Error log: $errorLogPath"
107
+ Write-Host "[manager] PID saved to $pidPath."
108
+ Write-Host "[manager] Open (local): http://localhost:$apiPort"
109
+ Write-Host "[manager] Open (local): http://127.0.0.1:$apiPort"
110
+ Write-Host "[manager] Open (LAN): http://<your-server-ip>:$apiPort"
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ DEFAULT_REPO_URL="https://github.com/Peiiii/moltbot-manager.git"
5
+ REPO_URL="${MANAGER_REPO_URL:-$DEFAULT_REPO_URL}"
6
+ MANAGER_API_PORT="${MANAGER_API_PORT:-17321}"
7
+ MANAGER_API_HOST="${MANAGER_API_HOST:-0.0.0.0}"
8
+
9
+ if [[ -z "${MANAGER_REPO_URL:-}" ]]; then
10
+ echo "[manager] MANAGER_REPO_URL not set. Using default: $REPO_URL"
11
+ fi
12
+
13
+ if ! command -v git >/dev/null 2>&1; then
14
+ echo "[manager] git is required."
15
+ exit 1
16
+ fi
17
+
18
+ prompt_confirm() {
19
+ local prompt="$1"
20
+ if command -v gum >/dev/null 2>&1; then
21
+ gum confirm "$prompt"
22
+ return $?
23
+ fi
24
+ if [[ -t 0 ]]; then
25
+ read -r -p "$prompt [y/N]: " reply
26
+ elif [[ -r /dev/tty && -w /dev/tty ]]; then
27
+ read -r -p "$prompt [y/N]: " reply < /dev/tty
28
+ else
29
+ return 1
30
+ fi
31
+ case "$reply" in
32
+ [yY]|[yY][eE][sS]) return 0 ;;
33
+ *) return 1 ;;
34
+ esac
35
+ }
36
+
37
+ run_as_root() {
38
+ if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then
39
+ "$@"
40
+ return $?
41
+ fi
42
+ if command -v sudo >/dev/null 2>&1; then
43
+ sudo -E "$@"
44
+ return $?
45
+ fi
46
+ echo "[manager] sudo is required to install Node.js."
47
+ return 1
48
+ }
49
+
50
+ get_node_major() {
51
+ local version
52
+ version="$(node -v 2>/dev/null || true)"
53
+ version="${version#v}"
54
+ echo "${version%%.*}"
55
+ }
56
+
57
+ install_node_with_nvm() {
58
+ if ! command -v curl >/dev/null 2>&1; then
59
+ echo "[manager] curl is required to install Node.js."
60
+ return 1
61
+ fi
62
+ echo "[manager] Installing Node.js via nvm..."
63
+ curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
64
+ export NVM_DIR="$HOME/.nvm"
65
+ # shellcheck disable=SC1090
66
+ . "$NVM_DIR/nvm.sh"
67
+ nvm install 22
68
+ nvm use 22
69
+ }
70
+
71
+ install_node() {
72
+ echo "[manager] Installing Node.js >= 22..."
73
+ if command -v apt-get >/dev/null 2>&1; then
74
+ if ! command -v curl >/dev/null 2>&1; then
75
+ run_as_root apt-get update -y
76
+ run_as_root apt-get install -y curl
77
+ fi
78
+ curl -fsSL https://deb.nodesource.com/setup_22.x | run_as_root bash -
79
+ run_as_root apt-get install -y nodejs
80
+ return 0
81
+ fi
82
+ if command -v dnf >/dev/null 2>&1; then
83
+ if ! command -v curl >/dev/null 2>&1; then
84
+ run_as_root dnf install -y curl
85
+ fi
86
+ curl -fsSL https://rpm.nodesource.com/setup_22.x | run_as_root bash -
87
+ run_as_root dnf install -y nodejs
88
+ return 0
89
+ fi
90
+ if command -v yum >/dev/null 2>&1; then
91
+ if ! command -v curl >/dev/null 2>&1; then
92
+ run_as_root yum install -y curl
93
+ fi
94
+ curl -fsSL https://rpm.nodesource.com/setup_22.x | run_as_root bash -
95
+ run_as_root yum install -y nodejs
96
+ return 0
97
+ fi
98
+ install_node_with_nvm
99
+ }
100
+
101
+ if ! command -v node >/dev/null 2>&1; then
102
+ echo "[manager] Node.js >= 22 is required."
103
+ if [[ "${MANAGER_AUTO_INSTALL_NODE:-}" == "1" ]]; then
104
+ install_node || exit 1
105
+ else
106
+ if prompt_confirm "Node.js not found. Install automatically?"; then
107
+ install_node || exit 1
108
+ else
109
+ exit 1
110
+ fi
111
+ fi
112
+ else
113
+ NODE_MAJOR="$(get_node_major)"
114
+ if [[ -z "$NODE_MAJOR" || "$NODE_MAJOR" -lt 22 ]]; then
115
+ echo "[manager] Node.js >= 22 is required (current: v${NODE_MAJOR})."
116
+ if [[ "${MANAGER_AUTO_INSTALL_NODE:-}" == "1" ]]; then
117
+ install_node || exit 1
118
+ else
119
+ if prompt_confirm "Node.js version is too low. Upgrade automatically?"; then
120
+ install_node || exit 1
121
+ else
122
+ exit 1
123
+ fi
124
+ fi
125
+ fi
126
+ fi
127
+
128
+ if ! command -v pnpm >/dev/null 2>&1; then
129
+ if command -v corepack >/dev/null 2>&1; then
130
+ corepack enable
131
+ corepack prepare pnpm@10.23.0 --activate
132
+ else
133
+ echo "[manager] pnpm is required (install via corepack)."
134
+ exit 1
135
+ fi
136
+ fi
137
+
138
+ if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then
139
+ INSTALL_DIR="${MANAGER_INSTALL_DIR:-/opt/clawdbot-manager}"
140
+ CONFIG_DIR="${MANAGER_CONFIG_DIR:-/etc/clawdbot-manager}"
141
+ else
142
+ INSTALL_DIR="${MANAGER_INSTALL_DIR:-$HOME/clawdbot-manager}"
143
+ CONFIG_DIR="${MANAGER_CONFIG_DIR:-$HOME/.clawdbot-manager}"
144
+ fi
145
+
146
+ if [[ -d "$INSTALL_DIR/.git" ]]; then
147
+ echo "[manager] Updating $INSTALL_DIR"
148
+ git -C "$INSTALL_DIR" pull --rebase
149
+ else
150
+ echo "[manager] Cloning to $INSTALL_DIR"
151
+ git clone "$REPO_URL" "$INSTALL_DIR"
152
+ fi
153
+
154
+ cd "$INSTALL_DIR"
155
+
156
+ prompt_env() {
157
+ local var_name="$1"
158
+ local prompt="$2"
159
+ local secret="${3:-0}"
160
+ local input=""
161
+
162
+ if [[ -n "${!var_name:-}" ]]; then
163
+ return 0
164
+ fi
165
+
166
+ if [[ -t 0 ]]; then
167
+ if [[ "$secret" == "1" ]]; then
168
+ read -r -s -p "$prompt" input
169
+ echo ""
170
+ else
171
+ read -r -p "$prompt" input
172
+ fi
173
+ elif [[ -r /dev/tty && -w /dev/tty ]]; then
174
+ if [[ "$secret" == "1" ]]; then
175
+ read -r -s -p "$prompt" input < /dev/tty
176
+ echo "" > /dev/tty
177
+ else
178
+ read -r -p "$prompt" input < /dev/tty
179
+ fi
180
+ else
181
+ echo "[manager] $var_name is required. Set env var or run in a TTY."
182
+ exit 1
183
+ fi
184
+
185
+ if [[ -z "$input" ]]; then
186
+ echo "[manager] $var_name is required."
187
+ exit 1
188
+ fi
189
+
190
+ printf -v "$var_name" "%s" "$input"
191
+ }
192
+
193
+ prompt_env "MANAGER_ADMIN_USER" "Admin username: " "0"
194
+ prompt_env "MANAGER_ADMIN_PASS" "Admin password: " "1"
195
+
196
+ pnpm install
197
+ pnpm build
198
+
199
+ node apps/api/scripts/create-admin.mjs \
200
+ --username "$MANAGER_ADMIN_USER" \
201
+ --password "$MANAGER_ADMIN_PASS" \
202
+ --config "$CONFIG_DIR/config.json"
203
+
204
+ if command -v systemctl >/dev/null 2>&1 && [[ "${EUID:-$(id -u)}" -eq 0 ]]; then
205
+ SERVICE_PATH="/etc/systemd/system/clawdbot-manager.service"
206
+ cat > "$SERVICE_PATH" <<SERVICE
207
+ [Unit]
208
+ Description=Clawdbot Manager API
209
+ After=network.target
210
+
211
+ [Service]
212
+ Type=simple
213
+ WorkingDirectory=$INSTALL_DIR
214
+ Environment=MANAGER_API_HOST=$MANAGER_API_HOST
215
+ Environment=MANAGER_API_PORT=$MANAGER_API_PORT
216
+ Environment=MANAGER_WEB_DIST=$INSTALL_DIR/apps/web/dist
217
+ Environment=MANAGER_CONFIG_PATH=$CONFIG_DIR/config.json
218
+ ExecStart=/usr/bin/env node $INSTALL_DIR/apps/api/dist/index.js
219
+ Restart=always
220
+ RestartSec=3
221
+
222
+ [Install]
223
+ WantedBy=multi-user.target
224
+ SERVICE
225
+
226
+ systemctl daemon-reload
227
+ systemctl enable --now clawdbot-manager
228
+ echo "[manager] Service started."
229
+ else
230
+ LOG_PATH="${MANAGER_LOG_PATH:-/tmp/clawdbot-manager.log}"
231
+ PID_FILE="$CONFIG_DIR/manager.pid"
232
+ nohup env \
233
+ MANAGER_API_HOST="$MANAGER_API_HOST" \
234
+ MANAGER_API_PORT="$MANAGER_API_PORT" \
235
+ MANAGER_WEB_DIST="$INSTALL_DIR/apps/web/dist" \
236
+ MANAGER_CONFIG_PATH="$CONFIG_DIR/config.json" \
237
+ node "$INSTALL_DIR/apps/api/dist/index.js" \
238
+ > "$LOG_PATH" 2>&1 &
239
+ echo $! > "$PID_FILE"
240
+ echo "[manager] Started in background (log: $LOG_PATH)."
241
+ echo "[manager] PID saved to $PID_FILE."
242
+ fi
243
+
244
+ HOST_IP=$(hostname -I 2>/dev/null | awk '{print $1}' || true)
245
+ if [[ -z "$HOST_IP" ]]; then
246
+ HOST_IP="<your-server-ip>"
247
+ fi
248
+
249
+ PUBLIC_HOST="${MANAGER_PUBLIC_HOST:-}"
250
+ if [[ -z "$PUBLIC_HOST" ]] && command -v curl >/dev/null 2>&1; then
251
+ PUBLIC_HOST="$(curl -fsS https://api.ipify.org 2>/dev/null || true)"
252
+ fi
253
+
254
+ echo "[manager] Open (local): http://localhost:$MANAGER_API_PORT"
255
+ echo "[manager] Open (local): http://127.0.0.1:$MANAGER_API_PORT"
256
+ echo "[manager] Open (LAN): http://$HOST_IP:$MANAGER_API_PORT"
257
+ if [[ -n "$PUBLIC_HOST" ]]; then
258
+ echo "[manager] Open (public): http://$PUBLIC_HOST:$MANAGER_API_PORT"
259
+ else
260
+ echo "[manager] Open (public): set MANAGER_PUBLIC_HOST to print public URL"
261
+ fi
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ MANAGER_API_PORT="${MANAGER_API_PORT:-17321}"
5
+
6
+ if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then
7
+ CONFIG_DIR="${MANAGER_CONFIG_DIR:-/etc/clawdbot-manager}"
8
+ INSTALL_DIR="${MANAGER_INSTALL_DIR:-/opt/clawdbot-manager}"
9
+ else
10
+ CONFIG_DIR="${MANAGER_CONFIG_DIR:-$HOME/.clawdbot-manager}"
11
+ INSTALL_DIR="${MANAGER_INSTALL_DIR:-$HOME/clawdbot-manager}"
12
+ fi
13
+
14
+ PID_FILE="$CONFIG_DIR/manager.pid"
15
+ SERVICE_NAME="clawdbot-manager"
16
+
17
+ if command -v systemctl >/dev/null 2>&1 && [[ -f "/etc/systemd/system/${SERVICE_NAME}.service" ]]; then
18
+ systemctl stop "$SERVICE_NAME"
19
+ echo "[manager] Service stopped."
20
+ exit 0
21
+ fi
22
+
23
+ if [[ -f "$PID_FILE" ]]; then
24
+ PID=$(cat "$PID_FILE" 2>/dev/null || true)
25
+ if [[ -n "$PID" ]] && kill -0 "$PID" 2>/dev/null; then
26
+ kill "$PID"
27
+ echo "[manager] Stopped PID $PID."
28
+ rm -f "$PID_FILE"
29
+ exit 0
30
+ fi
31
+ fi
32
+
33
+ if command -v pgrep >/dev/null 2>&1; then
34
+ MATCH="$INSTALL_DIR/apps/api/dist/index.js"
35
+ PIDS=$(pgrep -f "$MATCH" || true)
36
+ if [[ -n "$PIDS" ]]; then
37
+ echo "$PIDS" | xargs kill
38
+ echo "[manager] Stopped processes: $PIDS."
39
+ exit 0
40
+ fi
41
+ fi
42
+
43
+ if command -v lsof >/dev/null 2>&1; then
44
+ PIDS=$(lsof -nP -iTCP:"$MANAGER_API_PORT" -sTCP:LISTEN -t 2>/dev/null || true)
45
+ if [[ -n "$PIDS" ]]; then
46
+ echo "$PIDS" | xargs kill
47
+ echo "[manager] Stopped processes on port $MANAGER_API_PORT: $PIDS."
48
+ exit 0
49
+ fi
50
+ fi
51
+
52
+ echo "[manager] No running process found."