@michael-joseph-miller/ant-bot 0.1.0 → 0.1.2
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/CHANGELOG.md +42 -5
- package/README.md +69 -24
- package/dist/{browser-OHRD7YI3.js → browser-4ZHHBD6J.js} +132 -4
- package/dist/browser-4ZHHBD6J.js.map +7 -0
- package/dist/{bundled-46DUK5PG.js → bundled-26SJR7EB.js} +5 -5
- package/dist/{bundled-46DUK5PG.js.map → bundled-26SJR7EB.js.map} +1 -1
- package/dist/{chunk-DYIJTUMY.js → chunk-AON76FHD.js} +113 -83
- package/dist/chunk-AON76FHD.js.map +7 -0
- package/dist/{chunk-AHAON6J7.js → chunk-CNCHYZVD.js} +2 -2
- package/dist/{chunk-AHAON6J7.js.map → chunk-CNCHYZVD.js.map} +1 -1
- package/dist/{chunk-Z2YT2PZN.js → chunk-GYWJUW4E.js} +6 -6
- package/dist/{chunk-Z2YT2PZN.js.map → chunk-GYWJUW4E.js.map} +3 -3
- package/dist/{chunk-7BOHBPB2.js → chunk-JCZBDGBA.js} +3 -3
- package/dist/{chunk-7BOHBPB2.js.map → chunk-JCZBDGBA.js.map} +1 -1
- package/dist/{chunk-KSQOVWP5.js → chunk-MSSHR6SW.js} +6 -6
- package/dist/chunk-MSSHR6SW.js.map +7 -0
- package/dist/index.js +28 -28
- package/dist/index.js.map +2 -2
- package/dist/{install-IY2M3OUQ.js → install-KTEW2CW3.js} +3 -3
- package/dist/{plugin-POMHVGD4.js → plugin-WYUCG6F7.js} +2 -2
- package/dist/{plugin-POMHVGD4.js.map → plugin-WYUCG6F7.js.map} +1 -1
- package/dist/{scheduler-Q7OHNGP6.js → scheduler-VZVHQWGD.js} +3 -3
- package/dist/scheduler-VZVHQWGD.js.map +7 -0
- package/dist/server.js +58 -41
- package/dist/server.js.map +3 -3
- package/dist/{skills-66WRX64H.js → skills-JUHWFBD6.js} +2 -2
- package/dist/skills-spec.js +2 -2
- package/dist/skills-spec.js.map +1 -1
- package/dist/{tools-P5537ASX.js → tools-YNE7ZRPR.js} +2 -2
- package/dist/{tools-P5537ASX.js.map → tools-YNE7ZRPR.js.map} +1 -1
- package/package.json +1 -1
- package/skills/README.md +1 -1
- package/web/dist/assets/index-BBZbK10k.js +130 -0
- package/web/dist/assets/index-BKrFsCQD.css +2 -0
- package/web/dist/index.html +2 -2
- package/dist/browser-OHRD7YI3.js.map +0 -7
- package/dist/chunk-DYIJTUMY.js.map +0 -7
- package/dist/chunk-KSQOVWP5.js.map +0 -7
- package/dist/scheduler-Q7OHNGP6.js.map +0 -7
- package/web/dist/assets/index-BLQ8rPiN.js +0 -130
- package/web/dist/assets/index-IEIkG_jd.css +0 -2
- /package/dist/{install-IY2M3OUQ.js.map → install-KTEW2CW3.js.map} +0 -0
- /package/dist/{skills-66WRX64H.js.map → skills-JUHWFBD6.js.map} +0 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}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;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:0}.right-4{right:calc(var(--spacing) * 4)}.bottom-24{bottom:calc(var(--spacing) * 24)}.z-50{z-index:50}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:var(--spacing)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-12{height:calc(var(--spacing) * 12)}.h-40{height:calc(var(--spacing) * 40)}.h-dvh{height:100dvh}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-96{max-height:calc(var(--spacing) * 96)}.max-h-full{max-height:100%}.min-h-0{min-height:0}.min-h-\[38px\]{min-height:38px}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-3{width:calc(var(--spacing) * 3)}.w-12{width:calc(var(--spacing) * 12)}.w-20{width:calc(var(--spacing) * 20)}.w-32{width:calc(var(--spacing) * 32)}.w-40{width:calc(var(--spacing) * 40)}.w-48{width:calc(var(--spacing) * 48)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-80{width:calc(var(--spacing) * 80)}.w-96{width:calc(var(--spacing) * 96)}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.max-w-\[75\%\]{max-width:75%}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.rotate-0{rotate:0deg}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.cursor-crosshair{cursor:crosshair}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.grid-cols-\[160px_1fr\]{grid-template-columns:160px 1fr}.flex-col{flex-direction:column}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-\(--color-amber\)\/40{border-color:var(--color-amber)}@supports (color:color-mix(in lab, red, red)){.border-\(--color-amber\)\/40{border-color:color-mix(in oklab, var(--color-amber) 40%, transparent)}}.border-\(--color-amber\)\/50{border-color:var(--color-amber)}@supports (color:color-mix(in lab, red, red)){.border-\(--color-amber\)\/50{border-color:color-mix(in oklab, var(--color-amber) 50%, transparent)}}.border-\(--color-border\){border-color:var(--color-border)}.border-\(--color-red\),.border-\(--color-red\)\/40{border-color:var(--color-red)}@supports (color:color-mix(in lab, red, red)){.border-\(--color-red\)\/40{border-color:color-mix(in oklab, var(--color-red) 40%, transparent)}}.border-\(--color-red\)\/50{border-color:var(--color-red)}@supports (color:color-mix(in lab, red, red)){.border-\(--color-red\)\/50{border-color:color-mix(in oklab, var(--color-red) 50%, transparent)}}.border-l-\(--color-amber\){border-left-color:var(--color-amber)}.bg-\(--color-accent\),.bg-\(--color-accent\)\/15{background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.bg-\(--color-accent\)\/15{background-color:color-mix(in oklab, var(--color-accent) 15%, transparent)}}.bg-\(--color-accent\)\/25{background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.bg-\(--color-accent\)\/25{background-color:color-mix(in oklab, var(--color-accent) 25%, transparent)}}.bg-\(--color-amber\),.bg-\(--color-amber\)\/10{background-color:var(--color-amber)}@supports (color:color-mix(in lab, red, red)){.bg-\(--color-amber\)\/10{background-color:color-mix(in oklab, var(--color-amber) 10%, transparent)}}.bg-\(--color-amber\)\/15{background-color:var(--color-amber)}@supports (color:color-mix(in lab, red, red)){.bg-\(--color-amber\)\/15{background-color:color-mix(in oklab, var(--color-amber) 15%, transparent)}}.bg-\(--color-bg\){background-color:var(--color-bg)}.bg-\(--color-bg-elevated\){background-color:var(--color-bg-elevated)}.bg-\(--color-blue\),.bg-\(--color-blue\)\/15{background-color:var(--color-blue)}@supports (color:color-mix(in lab, red, red)){.bg-\(--color-blue\)\/15{background-color:color-mix(in oklab, var(--color-blue) 15%, transparent)}}.bg-\(--color-border\){background-color:var(--color-border)}.bg-\(--color-green\),.bg-\(--color-green\)\/15{background-color:var(--color-green)}@supports (color:color-mix(in lab, red, red)){.bg-\(--color-green\)\/15{background-color:color-mix(in oklab, var(--color-green) 15%, transparent)}}.bg-\(--color-red\),.bg-\(--color-red\)\/10{background-color:var(--color-red)}@supports (color:color-mix(in lab, red, red)){.bg-\(--color-red\)\/10{background-color:color-mix(in oklab, var(--color-red) 10%, transparent)}}.bg-\(--color-red\)\/15{background-color:var(--color-red)}@supports (color:color-mix(in lab, red, red)){.bg-\(--color-red\)\/15{background-color:color-mix(in oklab, var(--color-red) 15%, transparent)}}.bg-\(--color-text-faint\){background-color:var(--color-text-faint)}.bg-black\/20{background-color:#0003}@supports (color:color-mix(in lab, red, red)){.bg-black\/20{background-color:color-mix(in oklab, var(--color-black) 20%, transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\/50{background-color:color-mix(in oklab, var(--color-black) 50%, transparent)}}.bg-current{background-color:currentColor}.bg-transparent{background-color:#0000}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:var(--spacing)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-1{padding-top:var(--spacing)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-24{padding-top:calc(var(--spacing) * 24)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\(--color-accent\){color:var(--color-accent)}.text-\(--color-accent-fg\){color:var(--color-accent-fg)}.text-\(--color-amber\){color:var(--color-amber)}.text-\(--color-bg\){color:var(--color-bg)}.text-\(--color-blue\){color:var(--color-blue)}.text-\(--color-green\){color:var(--color-green)}.text-\(--color-red\){color:var(--color-red)}.text-\(--color-text\){color:var(--color-text)}.text-\(--color-text-faint\){color:var(--color-text-faint)}.text-\(--color-text-muted\){color:var(--color-text-muted)}.text-white{color:var(--color-white)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.opacity-60{opacity:.6}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline-2{outline-style:var(--tw-outline-style);outline-width:2px}.outline-\(--color-accent\){outline-color:var(--color-accent)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:bg-\(--color-bg-hover\):hover{background-color:var(--color-bg-hover)}.hover\:bg-\(--color-red\)\/10:hover{background-color:var(--color-red)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-\(--color-red\)\/10:hover{background-color:color-mix(in oklab, var(--color-red) 10%, transparent)}}.hover\:text-\(--color-red\):hover{color:var(--color-red)}.hover\:text-\(--color-text\):hover{color:var(--color-text)}.hover\:text-\(--color-text-muted\):hover{color:var(--color-text-muted)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}}.focus\:border-\(--color-accent\):focus{border-color:var(--color-accent)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}}:root{--color-bg:#0b0d10;--color-bg-elevated:#14171c;--color-bg-hover:#1b1f26;--color-border:#262b33;--color-text:#e6e9ef;--color-text-muted:#8b93a1;--color-text-faint:#5a616e;--color-accent:#6c8cff;--color-accent-fg:#0b0d10;--color-amber:#f0b429;--color-red:#f2545b;--color-green:#3fb950;--color-blue:#58a6ff}:root.light{--color-bg:#f6f7f9;--color-bg-elevated:#fff;--color-bg-hover:#eef0f3;--color-border:#dde1e7;--color-text:#14171c;--color-text-muted:#565e6b;--color-text-faint:#8b93a1;--color-accent:#3358e0;--color-accent-fg:#fff;--color-amber:#b3760a;--color-red:#c8323a;--color-green:#22863a;--color-blue:#0969da}*{box-sizing:border-box}html,body,#root{height:100%}body{background:var(--color-bg);color:var(--color-text);-webkit-font-smoothing:antialiased;margin:0;font-family:Inter,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:14px;overflow:hidden}code,pre,.font-mono{font-family:ui-monospace,SF Mono,Menlo,Consolas,Liberation Mono,monospace}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:8px}::-webkit-scrollbar-track{background:0 0}.markdown-body p{margin:0 0 .5em}.markdown-body p:last-child{margin-bottom:0}.markdown-body pre{background:var(--color-bg);border:1px solid var(--color-border);border-radius:6px;padding:.6em .8em;overflow-x:auto}.markdown-body code{background:var(--color-bg);border-radius:4px;padding:.1em .3em}.markdown-body pre code{background:0 0;padding:0}.markdown-body a{color:var(--color-blue)}.markdown-body ul,.markdown-body ol{margin:0 0 .5em;padding-left:1.4em}.markdown-body h1,.markdown-body h2,.markdown-body h3{margin:.6em 0 .3em;font-weight:600}.markdown-body blockquote{border-left:3px solid var(--color-border);color:var(--color-text-muted);margin:.5em 0;padding-left:.8em}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}
|
package/web/dist/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>ant-bot</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-BBZbK10k.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BKrFsCQD.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../packages/server/src/computer/browser.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { chromium } from 'playwright';\nimport type { BrowserContext, CDPSession, Page } from 'playwright';\nimport type { EventBus } from '../util/bus.js';\nimport { logger } from '../util/log.js';\n\nconst log = logger('browser');\n\n/* ------------------------------------------------------------------------------------------- *\n * Errors\n * ------------------------------------------------------------------------------------------- */\n\n/** Thrown when the browser cannot be launched (e.g. Chromium isn't installed). */\nexport class BrowserUnavailableError extends Error {\n constructor(public readonly reason: string) {\n super(`Browser is unavailable: ${reason}. Try: npx playwright install chromium`);\n this.name = 'BrowserUnavailableError';\n }\n}\n\n/** Thrown by ScreenLock when a bot's screen already has a computer-use task in flight. */\nexport class ScreenBusyError extends Error {\n constructor(public readonly botId: string) {\n super(`That bot's screen is already busy with another computer-use task. Wait for it to finish before starting another.`);\n this.name = 'ScreenBusyError';\n }\n}\n\n/** Thrown by normalizeUrl for disallowed / malformed URLs. */\nexport class InvalidUrlError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'InvalidUrlError';\n }\n}\n\n/** Thrown when an action targets a bot screen the human currently has taken over. */\nexport class ScreenTakenOverError extends Error {\n constructor() {\n super('The human has taken control of this screen; wait until they return it.');\n this.name = 'ScreenTakenOverError';\n }\n}\n\n/* ------------------------------------------------------------------------------------------- *\n * Pure helpers (no browser required) \u2014 exported for unit testing.\n * ------------------------------------------------------------------------------------------- */\n\n/**\n * Adds `https://` to bare domains/paths, rejects `javascript:` and `file:` URLs outright, and\n * otherwise passes the input through unchanged. Deliberately permissive about other schemes\n * (e.g. `data:`, `about:`) \u2014 computer-use tasks legitimately need to load those in tests and\n * sandboxes; the block list is specifically the two schemes that are dangerous or meaningless\n * for a screen-driving agent.\n */\nexport function normalizeUrl(input: string): string {\n const trimmed = (input ?? '').trim();\n if (!trimmed) throw new InvalidUrlError('URL is empty.');\n const schemeMatch = trimmed.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):/);\n if (!schemeMatch) return `https://${trimmed}`;\n const scheme = schemeMatch[1]!.toLowerCase();\n if (scheme === 'javascript') throw new InvalidUrlError('javascript: URLs are not allowed.');\n if (scheme === 'file') throw new InvalidUrlError('file: URLs are not allowed.');\n return trimmed;\n}\n\nexport interface BlockSignals {\n hasPasswordInput: boolean;\n iframeSrcs: string[];\n bodyText: string;\n}\n\nexport interface BlockDetection {\n kind: 'login' | 'captcha' | '2fa';\n message: string;\n}\n\n/**\n * Heuristic login-wall / CAPTCHA / 2FA detector over already-extracted page signals. Kept pure\n * (no Page dependency) so it can run without a browser in unit tests; `BrowserService.detectBlock`\n * gathers the signals from a live Page and delegates here.\n */\nexport function detectBlockFromSignals(signals: BlockSignals): BlockDetection | null {\n const iframeBlob = (signals.iframeSrcs ?? []).join(' ').toLowerCase();\n const body = signals.bodyText ?? '';\n\n if (/recaptcha/i.test(iframeBlob) || /hcaptcha/i.test(iframeBlob)) {\n return { kind: 'captcha', message: 'A CAPTCHA challenge (reCAPTCHA/hCaptcha) is present on this page.' };\n }\n if (/challenges\\.cloudflare\\.com|cf-challenge|turnstile/i.test(iframeBlob) || /checking your browser|cloudflare/i.test(body)) {\n return { kind: 'captcha', message: 'A Cloudflare browser challenge is present on this page.' };\n }\n if (/verify (your \\w+|it'?s you)|two-factor|one-time code/i.test(body)) {\n return { kind: '2fa', message: \"This page is asking for two-factor / one-time-code verification.\" };\n }\n if (signals.hasPasswordInput) {\n return { kind: 'login', message: 'This page has a password field \u2014 it looks like a login wall.' };\n }\n return null;\n}\n\n/**\n * Per-key mutex: `run` executes `fn` immediately if the key is free, otherwise rejects with\n * `ScreenBusyError` rather than queueing \u2014 mirrors \"one computer-use task per Bot screen at a\n * time\" (outline \u00A713): a second concurrent call is a caller bug, not something to serialize.\n */\nexport class ScreenLock {\n private busy = new Set<string>();\n\n isBusy(key: string): boolean {\n return this.busy.has(key);\n }\n\n async run<T>(key: string, fn: () => Promise<T>): Promise<T> {\n if (this.busy.has(key)) throw new ScreenBusyError(key);\n this.busy.add(key);\n try {\n return await fn();\n } finally {\n this.busy.delete(key);\n }\n }\n}\n\n/**\n * Frame-rate limiter for the screencast. `shouldEmit()` returns true at most once per\n * `1000/fps` ms according to the injected clock (defaults to `Date.now`), so tests can drive it\n * deterministically without real timers.\n */\nexport class FrameThrottle {\n private lastEmit = -Infinity;\n\n constructor(\n private readonly fps: number,\n private readonly clock: () => number = () => Date.now(),\n ) {}\n\n get intervalMs(): number {\n return 1000 / this.fps;\n }\n\n shouldEmit(): boolean {\n const now = this.clock();\n if (now - this.lastEmit >= this.intervalMs) {\n this.lastEmit = now;\n return true;\n }\n return false;\n }\n}\n\nfunction errMsg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/* ------------------------------------------------------------------------------------------- *\n * BrowserService\n * ------------------------------------------------------------------------------------------- */\n\nexport interface BrowserServiceDeps {\n profileDir: string;\n bus: EventBus;\n headless?: boolean;\n}\n\nexport interface ComputerPageStatus {\n botId: string;\n url: string;\n title: string;\n}\n\nexport interface BrowserStatus {\n available: boolean;\n reason?: string;\n mode: 'host';\n headless: boolean;\n pages: ComputerPageStatus[];\n}\n\nexport interface TakeOverResult {\n ok: boolean;\n mode: 'screencast-only' | 'window';\n message: string;\n}\n\ntype FrameListener = (jpegBase64: string, w: number, h: number) => void;\n\n/**\n * One Playwright persistent browser context shared by every Bot (\"the computer\"), with a\n * dedicated Page (\"screen\") per botId. Because all pages share one persistent context, cookies\n * and logins are shared across bots by design (outline \u00A75: \"one computer, shared by all your\n * Bots\") \u2014 this is intentional, not a bug.\n */\nexport class BrowserService {\n private context: BrowserContext | null = null;\n private launchPromise: Promise<BrowserContext> | null = null;\n private unavailableReason: string | undefined;\n\n private readonly headlessMode: boolean;\n private readonly pages = new Map<string, Page>();\n private readonly titleCache = new Map<string, string>();\n private readonly takenOver = new Set<string>();\n private readonly lock = new ScreenLock();\n\n private readonly screencastSessions = new Map<string, CDPSession>();\n private readonly screencastListeners = new Map<string, Set<FrameListener>>();\n private readonly screencastThrottles = new Map<string, FrameThrottle>();\n private readonly viewerCounts = new Map<string, number>();\n\n constructor(private readonly deps: BrowserServiceDeps) {\n this.headlessMode = deps.headless ?? true;\n }\n\n get isHeadless(): boolean {\n return this.headlessMode;\n }\n\n /** Lazily launches the shared persistent context. Concurrent callers share one launch. */\n private async ensureContext(): Promise<BrowserContext> {\n if (this.context) return this.context;\n if (this.launchPromise) return this.launchPromise;\n\n this.launchPromise = (async () => {\n try {\n fs.mkdirSync(this.deps.profileDir, { recursive: true });\n const ctx = await chromium.launchPersistentContext(this.deps.profileDir, {\n headless: this.headlessMode,\n viewport: { width: 1280, height: 800 },\n });\n this.context = ctx;\n ctx.on('close', () => {\n this.context = null;\n this.launchPromise = null;\n this.pages.clear();\n });\n return ctx;\n } catch (err) {\n this.unavailableReason = errMsg(err);\n this.launchPromise = null;\n throw new BrowserUnavailableError(this.unavailableReason);\n }\n })();\n return this.launchPromise;\n }\n\n /** Returns this bot's dedicated page, creating it lazily. Pages persist across turns. */\n async getPage(botId: string): Promise<Page> {\n const existing = this.pages.get(botId);\n if (existing && !existing.isClosed()) return existing;\n const ctx = await this.ensureContext();\n const page = await ctx.newPage();\n this.pages.set(botId, page);\n page.on('close', () => {\n if (this.pages.get(botId) === page) this.pages.delete(botId);\n });\n return page;\n }\n\n async closePage(botId: string): Promise<void> {\n const page = this.pages.get(botId);\n if (page) {\n await page.close().catch(() => {});\n this.pages.delete(botId);\n }\n this.titleCache.delete(botId);\n this.takenOver.delete(botId);\n }\n\n /** Serializes computer-use tasks per bot screen; a concurrent second call is rejected. */\n async withScreen<T>(botId: string, fn: (page: Page) => Promise<T>): Promise<T> {\n return this.lock.run(botId, async () => {\n if (this.takenOver.has(botId)) throw new ScreenTakenOverError();\n const page = await this.getPage(botId);\n return fn(page);\n });\n }\n\n private async orient(botId: string, page: Page): Promise<{ url: string; title: string }> {\n const url = page.url();\n let title = this.titleCache.get(botId) ?? '';\n try {\n title = await page.title();\n this.titleCache.set(botId, title);\n } catch {\n // page may be mid-navigation or closed; fall back to the cached title.\n }\n return { url, title };\n }\n\n private orientLine(o: { url: string; title: string }): string {\n return `URL: ${o.url}\\nTitle: ${o.title}`;\n }\n\n /** Gathers page signals and runs them through the pure detector. Never throws. */\n async detectBlock(page: Page): Promise<BlockDetection | null> {\n try {\n const hasPasswordInput = (await page.$$('input[type=\"password\"]').catch(() => [])).length > 0;\n const iframeSrcs = await page\n .$$eval('iframe', (els) => els.map((e) => e.getAttribute('src') ?? ''))\n .catch(() => [] as string[]);\n const bodyText = await page\n .evaluate(() => document.body?.innerText ?? '')\n .catch(() => '');\n return detectBlockFromSignals({ hasPasswordInput, iframeSrcs, bodyText: bodyText.slice(0, 4000) });\n } catch {\n return null;\n }\n }\n\n /** If a block is detected, publishes a warn notification and returns the STOP text to prepend. */\n private async checkBlock(botId: string, page: Page): Promise<string | null> {\n const block = await this.detectBlock(page);\n if (!block) return null;\n this.deps.bus.publish({\n type: 'notify',\n botId,\n threadId: null,\n level: 'warn',\n title: 'Browser needs a human',\n body: block.message,\n });\n return (\n `${block.message} STOP: do not attempt to solve or bypass this yourself \u2014 ` +\n `ask the human to take over the computer and wait for them to return control.`\n );\n }\n\n /* ---------------------------------------------------------------------------------------- *\n * Actions \u2014 each returns a short result string including the resulting URL + title, and is\n * safe to call even if the page has navigated away, closed, or errored mid-action.\n * ---------------------------------------------------------------------------------------- */\n\n async navigate(botId: string, url: string): Promise<string> {\n const target = normalizeUrl(url);\n return this.withScreen(botId, async (page) => {\n try {\n await page.goto(target, { waitUntil: 'domcontentloaded', timeout: 30000 });\n } catch (err) {\n return `Navigation to ${target} failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const block = await this.checkBlock(botId, page);\n const o = await this.orient(botId, page);\n return block ? `${block}\\n${this.orientLine(o)}` : `Navigated.\\n${this.orientLine(o)}`;\n });\n }\n\n async click(botId: string, selector: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.click(selector, { timeout: 10000 });\n } catch (err) {\n return `Click on \"${selector}\" failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const block = await this.checkBlock(botId, page);\n const o = await this.orient(botId, page);\n return block ? `${block}\\n${this.orientLine(o)}` : `Clicked \"${selector}\".\\n${this.orientLine(o)}`;\n });\n }\n\n async type(botId: string, selector: string, text: string, opts?: { submit?: boolean }): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n const isPassword = await page\n .$eval(selector, (el) => (el as HTMLInputElement).type === 'password')\n .catch(() => false);\n if (isPassword) {\n return (\n `Refused: \"${selector}\" looks like a password field. Never type credentials into the browser \u2014 ` +\n `ask the human to take over the computer instead.\\n${this.orientLine(await this.orient(botId, page))}`\n );\n }\n await page.fill(selector, text, { timeout: 10000 });\n if (opts?.submit) await page.press(selector, 'Enter');\n } catch (err) {\n return `Type into \"${selector}\" failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const block = await this.checkBlock(botId, page);\n const o = await this.orient(botId, page);\n return block ? `${block}\\n${this.orientLine(o)}` : `Typed into \"${selector}\".\\n${this.orientLine(o)}`;\n });\n }\n\n async pressKey(botId: string, key: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.keyboard.press(key);\n } catch (err) {\n return `Key press \"${key}\" failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n return `Pressed \"${key}\".\\n${this.orientLine(await this.orient(botId, page))}`;\n });\n }\n\n /** Returns visible text (page body, or a selector's text), capped at ~8000 characters. */\n async readText(botId: string, selector?: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n let text: string;\n try {\n text = selector\n ? ((await page.$eval(selector, (el) => (el as HTMLElement).innerText ?? '')) ?? '')\n : await page.evaluate(() => document.body?.innerText ?? '');\n } catch (err) {\n return `Read${selector ? ` of \"${selector}\"` : ''} failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const capped = text.length > 8000 ? `${text.slice(0, 8000)}\\n\u2026(truncated)` : text;\n return `${this.orientLine(await this.orient(botId, page))}\\n---\\n${capped}`;\n });\n }\n\n async readLinks(botId: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n let links: Array<{ text: string; href: string }>;\n try {\n links = await page.$$eval('a[href]', (els) =>\n els\n .slice(0, 200)\n .map((e) => ({ text: (e as HTMLElement).innerText.trim().slice(0, 120), href: (e as HTMLAnchorElement).href })),\n );\n } catch (err) {\n return `Reading links failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const body = links.map((l) => `- ${l.text || '(no text)'} -> ${l.href}`).join('\\n') || '(no links found)';\n return `${this.orientLine(await this.orient(botId, page))}\\n---\\n${body}`;\n });\n }\n\n /** Saves a PNG screenshot (to `filePath`, or a temp file if omitted) and returns its path. */\n async screenshot(botId: string, filePath?: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n const target = filePath ?? path.join(os.tmpdir(), `antbot-screenshot-${botId}-${Date.now()}.png`);\n try {\n fs.mkdirSync(path.dirname(target), { recursive: true });\n await page.screenshot({ path: target });\n } catch (err) {\n return `Screenshot failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n return `Screenshot saved to ${target}\\n${this.orientLine(await this.orient(botId, page))}`;\n });\n }\n\n async currentUrl(botId: string): Promise<string> {\n return this.withScreen(botId, async (page) => this.orientLine(await this.orient(botId, page)));\n }\n\n async waitFor(botId: string, selector: string, timeoutMs: number): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.waitForSelector(selector, { timeout: timeoutMs });\n } catch (err) {\n return `Waiting for \"${selector}\" timed out: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n return `Found \"${selector}\".\\n${this.orientLine(await this.orient(botId, page))}`;\n });\n }\n\n async scroll(botId: string, dy: number): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.mouse.wheel(0, dy);\n } catch (err) {\n return `Scroll failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n return `Scrolled by ${dy}px.\\n${this.orientLine(await this.orient(botId, page))}`;\n });\n }\n\n async goBack(botId: string): Promise<string> {\n return this.withScreen(botId, async (page) => {\n try {\n await page.goBack({ waitUntil: 'domcontentloaded', timeout: 15000 });\n } catch (err) {\n return `Go back failed: ${errMsg(err)}\\n${this.orientLine(await this.orient(botId, page))}`;\n }\n const block = await this.checkBlock(botId, page);\n const o = await this.orient(botId, page);\n return block ? `${block}\\n${this.orientLine(o)}` : `Went back.\\n${this.orientLine(o)}`;\n });\n }\n\n /* ---------------------------------------------------------------------------------------- *\n * Screencast \u2014 CDP-driven JPEG frames, throttled to ~4fps, reference-counted per bot so it\n * auto-stops once the last viewer detaches.\n * ---------------------------------------------------------------------------------------- */\n\n async startScreencast(botId: string, onFrame: FrameListener): Promise<() => void> {\n const page = await this.getPage(botId);\n\n let listeners = this.screencastListeners.get(botId);\n if (!listeners) {\n listeners = new Set();\n this.screencastListeners.set(botId, listeners);\n }\n listeners.add(onFrame);\n this.viewerCounts.set(botId, (this.viewerCounts.get(botId) ?? 0) + 1);\n\n if (!this.screencastSessions.has(botId)) {\n const ctx = await this.ensureContext();\n const session = await ctx.newCDPSession(page);\n const throttle = new FrameThrottle(4);\n this.screencastSessions.set(botId, session);\n this.screencastThrottles.set(botId, throttle);\n\n session.on('Page.screencastFrame', (evt) => {\n void session.send('Page.screencastFrameAck', { sessionId: evt.sessionId }).catch(() => {});\n if (!throttle.shouldEmit()) return;\n const w = evt.metadata?.deviceWidth ?? 0;\n const h = evt.metadata?.deviceHeight ?? 0;\n for (const l of listeners!) {\n try {\n l(evt.data, w, h);\n } catch (err) {\n log.warn('screencast frame listener threw', err);\n }\n }\n });\n\n await session.send('Page.startScreencast', { format: 'jpeg', quality: 60, maxWidth: 1280, everyNthFrame: 2 });\n }\n\n let stopped = false;\n return () => {\n if (stopped) return;\n stopped = true;\n listeners!.delete(onFrame);\n const remaining = Math.max(0, (this.viewerCounts.get(botId) ?? 1) - 1);\n this.viewerCounts.set(botId, remaining);\n if (remaining > 0) return;\n\n const session = this.screencastSessions.get(botId);\n this.screencastSessions.delete(botId);\n this.screencastThrottles.delete(botId);\n this.screencastListeners.delete(botId);\n if (session) {\n void session\n .send('Page.stopScreencast')\n .catch(() => {})\n .then(() => session.detach().catch(() => {}));\n }\n };\n }\n\n /* ---------------------------------------------------------------------------------------- *\n * Takeover \u2014 pauses agent-driven actions on a bot's screen for the human.\n * ---------------------------------------------------------------------------------------- */\n\n isTakenOver(botId: string): boolean {\n return this.takenOver.has(botId);\n }\n\n /**\n * Marks the screen as human-controlled. When headless, there is no window to bring forward\n * (and launching a second headed context on the same profile dir isn't possible \u2014 Chromium\n * locks the profile), so the human acts through the screencast view instead; interactive input\n * forwarding through that view is out of scope here. When headed, brings the real window to\n * the front for the human to drive directly.\n */\n async takeOver(botId: string): Promise<TakeOverResult> {\n this.takenOver.add(botId);\n if (this.headlessMode) {\n return {\n ok: true,\n mode: 'screencast-only',\n message:\n 'This computer is running headless, so there is no window to bring to the front. ' +\n 'Act through the screencast view for the blocked step (password, 2FA, CAPTCHA), then return control. ' +\n 'Never paste secrets into chat.',\n };\n }\n try {\n const page = await this.getPage(botId);\n await page.bringToFront();\n } catch (err) {\n log.warn('failed to bring page to front for takeover', err);\n }\n return {\n ok: true,\n mode: 'window',\n message: 'The browser window for this bot has been brought to the front. Complete the blocked step, then return control.',\n };\n }\n\n returnControl(botId: string): void {\n this.takenOver.delete(botId);\n }\n\n /* ---------------------------------------------------------------------------------------- */\n\n /** Never launches the browser. Reports optimistically until a launch attempt has failed. */\n status(): BrowserStatus {\n if (this.unavailableReason) {\n return { available: false, reason: this.unavailableReason, mode: 'host', headless: this.headlessMode, pages: [] };\n }\n const pages: ComputerPageStatus[] = [];\n if (this.context) {\n for (const [botId, page] of this.pages) {\n if (page.isClosed()) continue;\n pages.push({ botId, url: page.url(), title: this.titleCache.get(botId) ?? '' });\n }\n }\n return { available: true, mode: 'host', headless: this.headlessMode, pages };\n }\n\n async shutdown(): Promise<void> {\n for (const session of this.screencastSessions.values()) {\n await session\n .send('Page.stopScreencast')\n .catch(() => {})\n .then(() => session.detach().catch(() => {}));\n }\n this.screencastSessions.clear();\n this.screencastListeners.clear();\n this.screencastThrottles.clear();\n this.viewerCounts.clear();\n\n for (const page of this.pages.values()) {\n await page.close().catch(() => {});\n }\n this.pages.clear();\n this.titleCache.clear();\n this.takenOver.clear();\n\n if (this.context) {\n await this.context.close().catch(() => {});\n this.context = null;\n }\n this.launchPromise = null;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../packages/shared/src/limits.ts", "../../packages/shared/src/api.ts", "../../packages/shared/src/entities.ts", "../../packages/shared/src/events.ts"],
|
|
4
|
-
"sourcesContent": ["/** Operational limits \u2014 mirrors grok-bot-system-outline.md \u00A713. */\nexport const LIMITS = {\n MAX_BOTS_AND_GROUPS: 50,\n MIN_GROUP_MEMBERS: 2,\n MAX_GROUP_MEMBERS: 6,\n MAX_ROUTINES_PER_BOT: 50,\n ROUTINE_RUNS_RETAINED: 20,\n MAX_ATTACHMENTS_PER_MESSAGE: 6,\n MAX_ATTACHMENT_BYTES: 25 * 1024 * 1024,\n MAX_VIDEO_ATTACHMENT_BYTES: 200 * 1024 * 1024,\n MAX_BOT_TO_BOT_HOPS: 5,\n DEFAULT_MAX_CONCURRENT_SESSIONS: 2,\n APPROVAL_TIMEOUT_MS: 15 * 60 * 1000,\n TEACH_RECORDING_MAX_MS: 10 * 60 * 1000,\n} as const;\n\n/** Error codes returned by the service layer when a limit is violated. */\nexport const LIMIT_ERROR = {\n TOO_MANY_BOTS: 'TOO_MANY_BOTS',\n GROUP_SIZE: 'GROUP_SIZE',\n TOO_MANY_ROUTINES: 'TOO_MANY_ROUTINES',\n TOO_MANY_ATTACHMENTS: 'TOO_MANY_ATTACHMENTS',\n ATTACHMENT_TOO_LARGE: 'ATTACHMENT_TOO_LARGE',\n HOP_LIMIT: 'HOP_LIMIT',\n} as const;\nexport type LimitErrorCode = (typeof LIMIT_ERROR)[keyof typeof LIMIT_ERROR];\n\nexport class LimitError extends Error {\n constructor(\n public code: LimitErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'LimitError';\n }\n}\n", "import { z } from 'zod';\nimport {\n BotSchema, ThreadSchema, MessageSchema, ApprovalSchema, RuleSchema,\n SkillSchema, RoutineSchema, RoutineRunSchema, UsageRowSchema, ModelTierSchema,\n} from './entities.js';\n\nexport const CreateBotRequest = z.object({\n name: z.string().min(1).max(60),\n title: z.string().max(120).optional(),\n description: z.string().max(8000).optional(),\n avatarEmoji: z.string().max(8).optional(),\n modelTier: ModelTierSchema.optional(),\n});\nexport type CreateBotRequest = z.infer<typeof CreateBotRequest>;\n\nexport const UpdateBotRequest = CreateBotRequest.partial().extend({\n pinned: z.boolean().optional(),\n hidden: z.boolean().optional(),\n notifications: z.boolean().optional(),\n});\nexport type UpdateBotRequest = z.infer<typeof UpdateBotRequest>;\n\nexport const CreateThreadRequest = z.object({\n kind: z.enum(['dm', 'group']),\n title: z.string().optional(),\n memberBotIds: z.array(z.string()),\n});\nexport type CreateThreadRequest = z.infer<typeof CreateThreadRequest>;\n\nexport const PostMessageRequest = z.object({\n contentMd: z.string(),\n attachmentIds: z.array(z.string()).optional(),\n replyToId: z.string().nullable().optional(),\n /** explicit @-mention targets resolved by the client */\n mentionBotIds: z.array(z.string()).optional(),\n mentionEveryone: z.boolean().optional(),\n});\nexport type PostMessageRequest = z.infer<typeof PostMessageRequest>;\n\nexport const ApprovalDecisionRequest = z.object({\n decision: z.enum(['allow', 'deny']),\n alwaysRule: z\n .object({ toolPattern: z.string(), inputPattern: z.string().default(''), scopeNote: z.string().default('') })\n .optional(),\n});\nexport type ApprovalDecisionRequest = z.infer<typeof ApprovalDecisionRequest>;\n\nexport const CreateRuleRequest = z.object({\n kind: z.enum(['require', 'allow']),\n toolPattern: z.string().min(1),\n inputPattern: z.string().default(''),\n scopeNote: z.string().default(''),\n});\nexport type CreateRuleRequest = z.infer<typeof CreateRuleRequest>;\n\nexport const CreateRoutineRequest = z.object({\n botId: z.string(),\n name: z.string().min(1),\n cronExpr: z.string().min(1),\n timezone: z.string().optional(),\n instructionMd: z.string().min(1),\n enabled: z.boolean().optional(),\n});\nexport type CreateRoutineRequest = z.infer<typeof CreateRoutineRequest>;\n\nexport const CreateSkillRequest = z.object({\n name: z.string().min(1),\n description: z.string().default(''),\n bodyMd: z.string().min(1),\n source: z.enum(['user', 'taught', 'imported']).optional(),\n});\nexport type CreateSkillRequest = z.infer<typeof CreateSkillRequest>;\n\n/**\n * Field types, declared once and without defaults. `SettingsSchema` layers the\n * defaults on for reads; `SettingsPatchSchema` deliberately leaves them off.\n */\nconst settingsFields = {\n timezone: z.string(),\n maxConcurrentSessions: z.number().min(1).max(8),\n autoReviewEnabled: z.boolean(),\n theme: z.enum(['system', 'light', 'dark']),\n localExecution: z.enum(['ask', 'always', 'never']),\n dailyTokenBudget: z.number(),\n notificationsEnabled: z.boolean(),\n billingMode: z.enum(['subscription', 'api']),\n computerMode: z.enum(['host', 'container']),\n};\n\nexport const SettingsSchema = z.object({\n timezone: settingsFields.timezone.default('UTC'),\n maxConcurrentSessions: settingsFields.maxConcurrentSessions.default(2),\n autoReviewEnabled: settingsFields.autoReviewEnabled.default(true),\n theme: settingsFields.theme.default('system'),\n localExecution: settingsFields.localExecution.default('ask'),\n dailyTokenBudget: settingsFields.dailyTokenBudget.default(0),\n notificationsEnabled: settingsFields.notificationsEnabled.default(true),\n billingMode: settingsFields.billingMode.default('subscription'),\n computerMode: settingsFields.computerMode.default('host'),\n});\nexport type Settings = z.infer<typeof SettingsSchema>;\n\n/**\n * Body schema for `PATCH /api/settings`. It must NOT carry defaults: parsing a\n * one-field patch through a defaulted schema yields a complete object, and\n * persisting that would reset every setting the client didn't mention \u2014 including\n * `localExecution`, which is a security control (see docs/SECURITY.md).\n */\nexport const SettingsPatchSchema = z.object(settingsFields).partial();\nexport type SettingsPatch = z.infer<typeof SettingsPatchSchema>;\n\nexport const SearchResultSchema = z.object({\n kind: z.enum(['message', 'file', 'routine', 'bot']),\n id: z.string(),\n threadId: z.string().nullable(),\n botId: z.string().nullable(),\n title: z.string(),\n snippet: z.string(),\n createdAt: z.number(),\n});\nexport type SearchResult = z.infer<typeof SearchResultSchema>;\n\nexport type ApiBot = z.infer<typeof BotSchema>;\nexport type ApiThread = z.infer<typeof ThreadSchema>;\nexport type ApiMessage = z.infer<typeof MessageSchema>;\nexport type ApiApproval = z.infer<typeof ApprovalSchema>;\nexport type ApiRule = z.infer<typeof RuleSchema>;\nexport type ApiSkill = z.infer<typeof SkillSchema>;\nexport type ApiRoutine = z.infer<typeof RoutineSchema>;\nexport type ApiRoutineRun = z.infer<typeof RoutineRunSchema>;\nexport type ApiUsageRow = z.infer<typeof UsageRowSchema>;\n\nexport interface RosterEntry { bot: ApiBot; thread: ApiThread | null; lastMessageAt: number }\nexport interface ThreadWithMessages { thread: ApiThread; messages: ApiMessage[] }\nexport interface UsageSummary {\n totals: { inputTokens: number; outputTokens: number; cacheReadTokens: number };\n byBot: Array<{ botId: string; botName: string; inputTokens: number; outputTokens: number }>;\n byDay: Array<{ day: string; inputTokens: number; outputTokens: number }>;\n byModel: Array<{ model: string; inputTokens: number; outputTokens: number }>;\n}\n", "import { z } from 'zod';\n\nexport const BotStateSchema = z.enum([\n 'idle',\n 'queued',\n 'running',\n 'waiting_approval',\n 'waiting_input',\n 'interrupted',\n]);\nexport type BotState = z.infer<typeof BotStateSchema>;\n\nexport const AttentionSchema = z.enum(['none', 'unread', 'needs_attention']);\nexport type Attention = z.infer<typeof AttentionSchema>;\n\nexport const ModelTierSchema = z.enum(['sonnet', 'opus', 'haiku']);\nexport type ModelTier = z.infer<typeof ModelTierSchema>;\n\nexport const BotSchema = z.object({\n id: z.string(),\n slug: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),\n name: z.string().min(1).max(60),\n title: z.string().max(120).default(''),\n description: z.string().max(8000).default(''),\n avatarEmoji: z.string().max(8).default('\uD83E\uDD16'),\n modelTier: ModelTierSchema.default('sonnet'),\n pinned: z.boolean().default(false),\n hidden: z.boolean().default(false),\n notifications: z.boolean().default(true),\n sessionId: z.string().nullable().default(null),\n state: BotStateSchema.default('idle'),\n attention: AttentionSchema.default('none'),\n threadId: z.string().nullable().default(null),\n createdAt: z.number(),\n deletedAt: z.number().nullable().default(null),\n});\nexport type Bot = z.infer<typeof BotSchema>;\n\nexport const ThreadKindSchema = z.enum(['dm', 'group']);\nexport type ThreadKind = z.infer<typeof ThreadKindSchema>;\n\nexport const ThreadSchema = z.object({\n id: z.string(),\n kind: ThreadKindSchema,\n title: z.string().default(''),\n memberBotIds: z.array(z.string()).default([]),\n pinned: z.boolean().default(false),\n hidden: z.boolean().default(false),\n lastReadAt: z.number().default(0),\n createdAt: z.number(),\n});\nexport type Thread = z.infer<typeof ThreadSchema>;\n\n/** Cards render structured, non-prose content inside a message. */\nexport const CardSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('tool'),\n toolName: z.string(),\n summary: z.string(),\n input: z.unknown().optional(),\n result: z.string().optional(),\n status: z.enum(['running', 'ok', 'error', 'denied']),\n }),\n z.object({\n type: z.literal('file'),\n path: z.string(),\n name: z.string(),\n mime: z.string(),\n bytes: z.number(),\n action: z.enum(['created', 'modified']).default('created'),\n }),\n z.object({ type: z.literal('approval'), approvalId: z.string() }),\n z.object({ type: z.literal('handoff'), fromBotId: z.string(), toBotId: z.string(), note: z.string() }),\n z.object({ type: z.literal('error'), message: z.string() }),\n]);\nexport type Card = z.infer<typeof CardSchema>;\n\nexport const AuthorKindSchema = z.enum(['user', 'bot', 'system']);\nexport type AuthorKind = z.infer<typeof AuthorKindSchema>;\n\nexport const MessageSchema = z.object({\n id: z.string(),\n threadId: z.string(),\n authorKind: AuthorKindSchema,\n authorBotId: z.string().nullable().default(null),\n replyToId: z.string().nullable().default(null),\n contentMd: z.string().default(''),\n cards: z.array(CardSchema).default([]),\n streaming: z.boolean().default(false),\n createdAt: z.number(),\n});\nexport type Message = z.infer<typeof MessageSchema>;\n\nexport const AttachmentSchema = z.object({\n id: z.string(),\n messageId: z.string().nullable(),\n path: z.string(),\n name: z.string(),\n mime: z.string(),\n bytes: z.number(),\n createdAt: z.number(),\n});\nexport type Attachment = z.infer<typeof AttachmentSchema>;\n\nexport const ApprovalStatusSchema = z.enum(['pending', 'allowed', 'denied', 'expired']);\nexport type ApprovalStatus = z.infer<typeof ApprovalStatusSchema>;\n\nexport const ApprovalSchema = z.object({\n id: z.string(),\n botId: z.string(),\n threadId: z.string(),\n toolName: z.string(),\n inputSummary: z.string(),\n rawInput: z.unknown(),\n status: ApprovalStatusSchema.default('pending'),\n decidedBy: z.enum(['user', 'rule', 'auto_review']).nullable().default(null),\n reason: z.string().default(''),\n ruleId: z.string().nullable().default(null),\n createdAt: z.number(),\n decidedAt: z.number().nullable().default(null),\n});\nexport type Approval = z.infer<typeof ApprovalSchema>;\n\nexport const RuleKindSchema = z.enum(['require', 'allow']);\nexport type RuleKind = z.infer<typeof RuleKindSchema>;\n\nexport const RuleSchema = z.object({\n id: z.string(),\n kind: RuleKindSchema,\n /** Glob over tool name, e.g. \"Bash\", \"browser_*\", \"*\" */\n toolPattern: z.string().default('*'),\n /** Optional regex tested against the serialized tool input. */\n inputPattern: z.string().default(''),\n scopeNote: z.string().default(''),\n builtin: z.boolean().default(false),\n enabled: z.boolean().default(true),\n createdAt: z.number(),\n});\nexport type Rule = z.infer<typeof RuleSchema>;\n\nexport const SkillSchema = z.object({\n id: z.string(),\n slug: z.string(),\n name: z.string(),\n description: z.string().default(''),\n path: z.string(),\n source: z.enum(['user', 'taught', 'imported']).default('user'),\n createdAt: z.number(),\n});\nexport type Skill = z.infer<typeof SkillSchema>;\n\nexport const RoutineSchema = z.object({\n id: z.string(),\n botId: z.string(),\n name: z.string().min(1),\n cronExpr: z.string(),\n timezone: z.string().default('UTC'),\n instructionMd: z.string(),\n enabled: z.boolean().default(true),\n lastRunAt: z.number().nullable().default(null),\n nextRunAt: z.number().nullable().default(null),\n createdAt: z.number(),\n});\nexport type Routine = z.infer<typeof RoutineSchema>;\n\nexport const RoutineRunSchema = z.object({\n id: z.string(),\n routineId: z.string(),\n startedAt: z.number(),\n finishedAt: z.number().nullable().default(null),\n status: z.enum(['running', 'ok', 'failed', 'interrupted']),\n summary: z.string().default(''),\n threadId: z.string().nullable().default(null),\n isTest: z.boolean().default(false),\n});\nexport type RoutineRun = z.infer<typeof RoutineRunSchema>;\n\nexport const MailboxEntrySchema = z.object({\n id: z.string(),\n fromBotId: z.string(),\n toBotId: z.string(),\n contentMd: z.string(),\n hops: z.number().default(1),\n delivered: z.boolean().default(false),\n createdAt: z.number(),\n});\nexport type MailboxEntry = z.infer<typeof MailboxEntrySchema>;\n\nexport const UsageRowSchema = z.object({\n id: z.string(),\n botId: z.string(),\n turnId: z.string(),\n model: z.string(),\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheReadTokens: z.number().default(0),\n costEstimate: z.number().default(0),\n createdAt: z.number(),\n});\nexport type UsageRow = z.infer<typeof UsageRowSchema>;\n\nexport const TurnOriginSchema = z.enum(['user', 'bot', 'routine', 'system']);\nexport type TurnOrigin = z.infer<typeof TurnOriginSchema>;\n", "import { z } from 'zod';\nimport { BotStateSchema, AttentionSchema, CardSchema, MessageSchema, ApprovalSchema, RoutineRunSchema } from './entities.js';\n\n/** Every server\u2192client event carries {threadId, botId, seq} for ordering/reconciliation. */\nconst base = { seq: z.number(), threadId: z.string().nullable(), botId: z.string().nullable() };\n\nexport const ServerEventSchema = z.discriminatedUnion('type', [\n /** Connection handshake. Carries the current seq so a client can detect gaps. */\n z.object({ ...base, type: z.literal('hello') }),\n z.object({ ...base, type: z.literal('message.created'), message: MessageSchema }),\n z.object({ ...base, type: z.literal('message.delta'), messageId: z.string(), delta: z.string() }),\n z.object({ ...base, type: z.literal('message.done'), messageId: z.string(), contentMd: z.string() }),\n z.object({ ...base, type: z.literal('message.card'), messageId: z.string(), card: CardSchema, cardIndex: z.number() }),\n z.object({ ...base, type: z.literal('bot.state'), state: BotStateSchema, attention: AttentionSchema }),\n z.object({ ...base, type: z.literal('approval.pending'), approval: ApprovalSchema }),\n z.object({ ...base, type: z.literal('approval.resolved'), approval: ApprovalSchema }),\n z.object({ ...base, type: z.literal('routine.run'), run: RoutineRunSchema }),\n z.object({ ...base, type: z.literal('usage.tick'), inputTokens: z.number(), outputTokens: z.number(), model: z.string() }),\n z.object({ ...base, type: z.literal('notify'), title: z.string(), body: z.string(), level: z.enum(['info', 'warn', 'error']) }),\n z.object({ ...base, type: z.literal('secret.request'), requestId: z.string(), name: z.string(), reason: z.string() }),\n z.object({ ...base, type: z.literal('thread.updated'), threadId2: z.string() }),\n]);\nexport type ServerEvent = z.infer<typeof ServerEventSchema>;\nexport type ServerEventType = ServerEvent['type'];\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["z", "z", "z", "z"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../packages/server/src/skills/skills.ts", "../../packages/server/src/util/ids.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'node:fs';\nimport path from 'node:path';\nimport type { Store } from '../db/store.js';\nimport { slugify } from '../util/ids.js';\nimport type { Skill } from '@antbot/shared';\n\n/**\n * A skill is a directory `<skillsDir>/<slug>/SKILL.md` with a YAML-ish frontmatter block\n * (name, description) followed by a markdown body in the 6-part shape from outline \u00A78:\n * when to use it, required inputs and access, sequence of work, how to validate the result,\n * what to return, what requires approval.\n */\n\nexport const SKILL_TEMPLATE = `## When to use it\n\nDescribe the trigger: what request or situation should make a bot reach for this skill instead\nof improvising. Be specific enough that a bot with this skill enabled recognizes the moment.\n\n## Required inputs and access\n\nList what the skill needs before it can run: source systems, connectors/MCP servers, files,\ncredentials, or information the user must supply. Say what happens if something required is\nmissing.\n\n## Sequence of work\n\nWrite the ordered steps the bot should follow. Prefer \"gather \u2192 draft/reconcile \u2192 recommend\"\nover \"act immediately\" \u2014 automate preparation before execution.\n\n## How to validate the result\n\nState how the bot should check its own output before returning it: what to cross-check, what\ncounts as \"current\" data, and what stale-data policy applies. Per outline \u00A78: **if the source\ndata is unavailable, report the failure instead of using old data.**\n\n## What to return\n\nDescribe the shape of the deliverable: a document, a spreadsheet, a draft message, a linked\nwatch list, or a recommendation with evidence. Separate facts found, assumptions, actions\nalready taken, actions waiting for approval, and open questions where relevant.\n\n## What requires approval\n\nName the actions this skill must never take without an explicit human \"go ahead\": sending,\npublishing, purchasing, deleting, overwriting, or any production change. This section should\nnever be empty \u2014 every skill has an approval boundary.\n`;\n\nexport interface WriteSkillInput {\n name: string;\n description?: string;\n bodyMd: string;\n source?: 'user' | 'taught' | 'imported';\n}\n\nexport interface InstalledSkill {\n skill: Skill;\n executables: string[];\n manifestText: string;\n replaced: boolean;\n}\n\nexport interface ParsedSkillFile {\n name: string;\n description: string;\n bodyMd: string;\n}\n\n/** Parse the `---\\nname: \"...\"\\ndescription: \"...\"\\n---\\n<body>` shape. Pure, no I/O. */\nexport function parseFrontmatter(md: string): ParsedSkillFile {\n const m = md.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!m) return { name: '', description: '', bodyMd: md };\n const [, fm, rest] = m;\n const data: Record<string, string> = {};\n const lines = (fm ?? '').split(/\\r?\\n/);\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const idx = line.indexOf(':');\n if (idx === -1 || /^\\s/.test(line)) continue; // continuation lines are consumed below\n const key = line.slice(0, idx).trim();\n let value = line.slice(idx + 1).trim();\n\n // YAML block scalars: `>` folds newlines into spaces, `|` keeps them. Published\n // skills use both for long descriptions, and the description is what the model\n // matches on \u2014 dropping it to a bare \">\" makes the skill invisible.\n const block = /^([>|])([-+]?)$/.exec(value);\n if (block) {\n const folded = block[1] === '>';\n const collected: string[] = [];\n while (i + 1 < lines.length) {\n const next = lines[i + 1]!;\n if (next.trim() !== '' && !/^\\s/.test(next)) break; // next top-level key\n collected.push(next.trim());\n i++;\n }\n while (collected.length && collected[collected.length - 1] === '') collected.pop();\n value = folded\n ? collected.filter((l) => l !== '').join(' ')\n : collected.join('\\n');\n // A folded block separates paragraphs (blank lines) with a newline.\n if (folded && collected.includes('')) {\n value = collected\n .reduce<string[]>((acc, l) => {\n if (l === '') acc.push('');\n else if (acc.length && acc[acc.length - 1] !== '') acc[acc.length - 1] += ` ${l}`;\n else acc[acc.length - 1] = l;\n return acc;\n }, [''])\n .filter((para) => para !== '')\n .join('\\n');\n }\n data[key] = value;\n continue;\n }\n\n if (value.startsWith('\"') && value.endsWith('\"') && value.length >= 2) {\n value = value.slice(1, -1).replace(/\\\\\"/g, '\"');\n }\n data[key] = value;\n }\n return {\n name: data.name ?? '',\n description: data.description ?? '',\n bodyMd: (rest ?? '').replace(/^\\r?\\n/, ''),\n };\n}\n\n/** Render a SKILL.md file from its parts. Pure, no I/O. */\nexport function renderSkillFile(input: { name: string; description: string; bodyMd: string }): string {\n const esc = (s: string): string => s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n return `---\\nname: \"${esc(input.name)}\"\\ndescription: \"${esc(input.description)}\"\\n---\\n\\n${input.bodyMd.trim()}\\n`;\n}\n\n/**\n * Raised when a source resolves to more than one skill and the caller did not opt in.\n * Carries the names so the caller can tell the human (or the model) what to narrow to.\n */\nexport class MultipleSkillsError extends Error {\n constructor(\n readonly source: string,\n readonly names: string[],\n ) {\n super(`\"${source}\" contains ${names.length} skills, not one.`);\n this.name = 'MultipleSkillsError';\n }\n}\n\nexport class SkillStore {\n constructor(\n private store: Store,\n private skillsDir: string,\n ) {}\n\n private slugDir(slug: string): string {\n return path.join(this.skillsDir, slug);\n }\n\n /** Resolve a stored skill path and assert it is inside the skills dir (no path traversal). */\n private assertInsideSkillsDir(candidate: string): string {\n const root = path.resolve(this.skillsDir) + path.sep;\n const resolved = path.resolve(candidate);\n if (resolved !== path.resolve(this.skillsDir) && !resolved.startsWith(root)) {\n throw new Error(`Refusing to touch a skill path outside the skills directory: ${candidate}`);\n }\n return resolved;\n }\n\n /** Create (or overwrite by slug) a skill directory + SKILL.md, and register it. */\n writeSkill(input: WriteSkillInput): Skill {\n const existing = new Set(this.store.listSkills().map((s) => s.slug));\n const slug = slugify(input.name, existing);\n const dir = this.assertInsideSkillsDir(this.slugDir(slug));\n fs.mkdirSync(dir, { recursive: true });\n const content = renderSkillFile({\n name: input.name,\n description: input.description ?? '',\n bodyMd: input.bodyMd,\n });\n fs.writeFileSync(path.join(dir, 'SKILL.md'), content, 'utf8');\n return this.store.createSkill({\n slug,\n name: input.name,\n description: input.description,\n path: dir,\n source: input.source,\n });\n }\n\n /**\n * Install every skill found at `source` and register it. Existing slugs are replaced in\n * place so re-installing upgrades rather than accumulating copies.\n *\n * Throws `MultipleSkillsError` if `source` holds more than one skill unless\n * `allowMultiple` is set, so a caller cannot install a hundred skills by accident.\n */\n async installFromSource(\n source: string,\n opts: { allowMultiple?: boolean } = {},\n ): Promise<InstalledSkill[]> {\n const { stage, copyTree, renderManifest } = await import('./install.js');\n const parsed = (await import('./install.js')).parseSkillSource(source);\n const { staged, cleanup } = await stage(parsed);\n try {\n // Installing a whole monorepo when one skill was wanted is easy to do by accident and\n // tedious to undo, so a multi-skill source has to be asked for explicitly.\n if (staged.length > 1 && !opts.allowMultiple) {\n throw new MultipleSkillsError(source, staged.map((sk) => sk.name));\n }\n const out: InstalledSkill[] = [];\n for (const skill of staged) {\n const existing = this.store.getSkillBySlug(slugify(skill.name, new Set()));\n const others = new Set(this.store.listSkills().map((x) => x.slug));\n if (existing) others.delete(existing.slug);\n const slug = existing?.slug ?? slugify(skill.name, others);\n\n const dir = this.assertInsideSkillsDir(this.slugDir(slug));\n fs.rmSync(dir, { recursive: true, force: true });\n copyTree(skill.dir, dir);\n\n const registered = existing\n ? (this.store.updateSkill?.(existing.id, { name: skill.name, description: skill.description }) ?? existing)\n : this.store.createSkill({\n slug, name: skill.name, description: skill.description, path: dir, source: 'imported',\n });\n\n // Installed skills are held to the same spec as the ones ant-bot ships. This never\n // blocks an install \u2014 a third-party skill with a sloppy frontmatter still works \u2014 but\n // a `name` that does not match its directory makes the skill impossible for a bot to\n // enable, and silence about that is how it stays broken.\n const { validateSkillDir, formatSpecViolations } = await import('./spec.js');\n const specNotes = formatSpecViolations(validateSkillDir(dir));\n\n out.push({\n skill: registered,\n executables: skill.manifest.executables,\n manifestText: renderManifest(skill, dir) + specNotes,\n replaced: Boolean(existing),\n });\n }\n return out;\n } finally {\n cleanup();\n }\n }\n\n /** Read a skill's SKILL.md and return it with the parsed body (frontmatter stripped). */\n readSkill(id: string): (Skill & { bodyMd: string }) | null {\n const skill = this.store.getSkill(id);\n if (!skill) return null;\n const file = path.join(skill.path, 'SKILL.md');\n if (!fs.existsSync(file)) return { ...skill, bodyMd: '' };\n const raw = fs.readFileSync(file, 'utf8');\n const { bodyMd } = parseFrontmatter(raw);\n return { ...skill, bodyMd };\n }\n\n /** Remove a skill's directory and its db row. Guards against a maliciously escaped path. */\n deleteSkill(id: string): void {\n const skill = this.store.getSkill(id);\n if (!skill) return;\n const resolved = this.assertInsideSkillsDir(skill.path);\n fs.rmSync(resolved, { recursive: true, force: true });\n this.store.deleteSkill(id);\n }\n\n /**\n * Bring the registry back in line with what is actually on disk.\n *\n * A row can outlive its directory \u2014 a skill removed by hand, or a layout migration that\n * moved files without rewriting paths \u2014 and the UI then lists skills that cannot load.\n * Rows whose directory moved are repaired in place so bot assignments survive; rows with\n * nothing left on disk are dropped. Returns what it did, for the boot log.\n */\n reconcile(): { repaired: string[]; removed: string[] } {\n const repaired: string[] = [];\n const removed: string[] = [];\n for (const skill of this.store.listSkills()) {\n if (fs.existsSync(path.join(skill.path, 'SKILL.md'))) continue;\n const expected = path.join(this.skillsDir, skill.slug);\n if (fs.existsSync(path.join(expected, 'SKILL.md'))) {\n this.store.updateSkill(skill.id, { path: expected });\n repaired.push(skill.slug);\n } else {\n this.store.deleteSkill(skill.id);\n removed.push(skill.slug);\n }\n }\n return { repaired, removed };\n }\n\n /**\n * Re-read `name`/`description` from disk for the given slugs and update their rows.\n *\n * Registered names are not cosmetic \u2014 `manager.ts` hands them to the SDK as `enabledSkills`,\n * so a row whose name has drifted from its SKILL.md silently stops matching and the skill\n * quietly disappears from every bot that had it enabled. Any writer of a skill file that a\n * row already points at has to call this; `syncFromDisk` cannot, since it only ever looks at\n * slugs the db has never seen. Returns the slugs whose stored metadata actually changed.\n */\n refreshFromDisk(slugs: string[]): string[] {\n const changed: string[] = [];\n for (const slug of slugs) {\n const registered = this.store.getSkillBySlug(slug);\n if (!registered) continue;\n const file = path.join(this.skillsDir, slug, 'SKILL.md');\n if (!fs.existsSync(file)) continue;\n const { name, description } = parseFrontmatter(fs.readFileSync(file, 'utf8'));\n const nextName = name || registered.name;\n if (nextName === registered.name && description === (registered.description ?? '')) continue;\n this.store.updateSkill(registered.id, { name: nextName, description });\n changed.push(slug);\n }\n return changed;\n }\n\n /**\n * Scan the skills dir at boot and register any SKILL.md not yet known to the db, so users\n * can drop skills in by hand. Idempotent: already-registered slugs are left untouched.\n */\n syncFromDisk(): Skill[] {\n if (!fs.existsSync(this.skillsDir)) return [];\n const added: Skill[] = [];\n for (const entry of fs.readdirSync(this.skillsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const slug = entry.name;\n const dir = path.join(this.skillsDir, slug);\n const file = path.join(dir, 'SKILL.md');\n if (!fs.existsSync(file)) continue;\n if (this.store.getSkillBySlug(slug)) continue;\n const raw = fs.readFileSync(file, 'utf8');\n const { name, description } = parseFrontmatter(raw);\n const skill = this.store.createSkill({\n slug,\n name: name || slug,\n description,\n path: dir,\n source: 'imported',\n });\n added.push(skill);\n }\n return added;\n }\n}\n", "import { randomUUID } from 'node:crypto';\nexport const newId = (): string => randomUUID();\nexport const now = (): number => Date.now();\nexport function slugify(name: string, existing: Set<string> = new Set()): string {\n const base =\n name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40) || 'bot';\n let slug = base;\n let n = 2;\n while (existing.has(slug)) slug = `${base}-${n++}`;\n return slug;\n}\n"],
|
|
5
|
-
"mappings": ";;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;;;ACDjB,SAAS,kBAAkB;AACpB,IAAM,QAAQ,MAAc,WAAW;AACvC,IAAM,MAAM,MAAc,KAAK,IAAI;AACnC,SAAS,QAAQ,MAAc,WAAwB,oBAAI,IAAI,GAAW;AAC/E,QAAM,OACJ,KAAK,YAAY,EAAE,QAAQ,eAAe,GAAG,EAAE,QAAQ,YAAY,EAAE,EAAE,MAAM,GAAG,EAAE,KAAK;AACzF,MAAI,OAAO;AACX,MAAI,IAAI;AACR,SAAO,SAAS,IAAI,IAAI,EAAG,QAAO,GAAG,IAAI,IAAI,GAAG;AAChD,SAAO;AACT;;;ADGO,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwDvB,SAAS,iBAAiB,IAA6B;AAC5D,QAAM,IAAI,GAAG,MAAM,6CAA6C;AAChE,MAAI,CAAC,EAAG,QAAO,EAAE,MAAM,IAAI,aAAa,IAAI,QAAQ,GAAG;AACvD,QAAM,CAAC,EAAE,IAAI,IAAI,IAAI;AACrB,QAAM,OAA+B,CAAC;AACtC,QAAM,SAAS,MAAM,IAAI,MAAM,OAAO;AAEtC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,QAAI,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAG;AACpC,UAAM,MAAM,KAAK,MAAM,GAAG,GAAG,EAAE,KAAK;AACpC,QAAI,QAAQ,KAAK,MAAM,MAAM,CAAC,EAAE,KAAK;AAKrC,UAAM,QAAQ,kBAAkB,KAAK,KAAK;AAC1C,QAAI,OAAO;AACT,YAAM,SAAS,MAAM,CAAC,MAAM;AAC5B,YAAM,YAAsB,CAAC;AAC7B,aAAO,IAAI,IAAI,MAAM,QAAQ;AAC3B,cAAM,OAAO,MAAM,IAAI,CAAC;AACxB,YAAI,KAAK,KAAK,MAAM,MAAM,CAAC,MAAM,KAAK,IAAI,EAAG;AAC7C,kBAAU,KAAK,KAAK,KAAK,CAAC;AAC1B;AAAA,MACF;AACA,aAAO,UAAU,UAAU,UAAU,UAAU,SAAS,CAAC,MAAM,GAAI,WAAU,IAAI;AACjF,cAAQ,SACJ,UAAU,OAAO,CAAC,MAAM,MAAM,EAAE,EAAE,KAAK,GAAG,IAC1C,UAAU,KAAK,IAAI;AAEvB,UAAI,UAAU,UAAU,SAAS,EAAE,GAAG;AACpC,gBAAQ,UACL,OAAiB,CAAC,KAAK,MAAM;AAC5B,cAAI,MAAM,GAAI,KAAI,KAAK,EAAE;AAAA,mBAChB,IAAI,UAAU,IAAI,IAAI,SAAS,CAAC,MAAM,GAAI,KAAI,IAAI,SAAS,CAAC,KAAK,IAAI,CAAC;AAAA,cAC1E,KAAI,IAAI,SAAS,CAAC,IAAI;AAC3B,iBAAO;AAAA,QACT,GAAG,CAAC,EAAE,CAAC,EACN,OAAO,CAAC,SAAS,SAAS,EAAE,EAC5B,KAAK,IAAI;AAAA,MACd;AACA,WAAK,GAAG,IAAI;AACZ;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,UAAU,GAAG;AACrE,cAAQ,MAAM,MAAM,GAAG,EAAE,EAAE,QAAQ,QAAQ,GAAG;AAAA,IAChD;AACA,SAAK,GAAG,IAAI;AAAA,EACd;AACA,SAAO;AAAA,IACL,MAAM,KAAK,QAAQ;AAAA,IACnB,aAAa,KAAK,eAAe;AAAA,IACjC,SAAS,QAAQ,IAAI,QAAQ,UAAU,EAAE;AAAA,EAC3C;AACF;AAGO,SAAS,gBAAgB,OAAsE;AACpG,QAAM,MAAM,CAAC,MAAsB,EAAE,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK;AAC/E,SAAO;AAAA,SAAe,IAAI,MAAM,IAAI,CAAC;AAAA,gBAAoB,IAAI,MAAM,WAAW,CAAC;AAAA;AAAA;AAAA,EAAa,MAAM,OAAO,KAAK,CAAC;AAAA;AACjH;AAMO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,YACW,QACA,OACT;AACA,UAAM,IAAI,MAAM,cAAc,MAAM,MAAM,mBAAmB;AAHpD;AACA;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EALW;AAAA,EACA;AAKb;AAEO,IAAM,aAAN,MAAiB;AAAA,EACtB,YACU,OACA,WACR;AAFQ;AACA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA,EAGF,QAAQ,MAAsB;AACpC,WAAO,KAAK,KAAK,KAAK,WAAW,IAAI;AAAA,EACvC;AAAA;AAAA,EAGQ,sBAAsB,WAA2B;AACvD,UAAM,OAAO,KAAK,QAAQ,KAAK,SAAS,IAAI,KAAK;AACjD,UAAM,WAAW,KAAK,QAAQ,SAAS;AACvC,QAAI,aAAa,KAAK,QAAQ,KAAK,SAAS,KAAK,CAAC,SAAS,WAAW,IAAI,GAAG;AAC3E,YAAM,IAAI,MAAM,gEAAgE,SAAS,EAAE;AAAA,IAC7F;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,WAAW,OAA+B;AACxC,UAAM,WAAW,IAAI,IAAI,KAAK,MAAM,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACnE,UAAM,OAAO,QAAQ,MAAM,MAAM,QAAQ;AACzC,UAAM,MAAM,KAAK,sBAAsB,KAAK,QAAQ,IAAI,CAAC;AACzD,OAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACrC,UAAM,UAAU,gBAAgB;AAAA,MAC9B,MAAM,MAAM;AAAA,MACZ,aAAa,MAAM,eAAe;AAAA,MAClC,QAAQ,MAAM;AAAA,IAChB,CAAC;AACD,OAAG,cAAc,KAAK,KAAK,KAAK,UAAU,GAAG,SAAS,MAAM;AAC5D,WAAO,KAAK,MAAM,YAAY;AAAA,MAC5B;AAAA,MACA,MAAM,MAAM;AAAA,MACZ,aAAa,MAAM;AAAA,MACnB,MAAM;AAAA,MACN,QAAQ,MAAM;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,kBACJ,QACA,OAAoC,CAAC,GACV;AAC3B,UAAM,EAAE,OAAO,UAAU,eAAe,IAAI,MAAM,OAAO,uBAAc;AACvE,UAAM,UAAU,MAAM,OAAO,uBAAc,GAAG,iBAAiB,MAAM;AACrE,UAAM,EAAE,QAAQ,QAAQ,IAAI,MAAM,MAAM,MAAM;AAC9C,QAAI;AAGF,UAAI,OAAO,SAAS,KAAK,CAAC,KAAK,eAAe;AAC5C,cAAM,IAAI,oBAAoB,QAAQ,OAAO,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;AAAA,MACnE;AACA,YAAM,MAAwB,CAAC;AAC/B,iBAAW,SAAS,QAAQ;AAC1B,cAAM,WAAW,KAAK,MAAM,eAAe,QAAQ,MAAM,MAAM,oBAAI,IAAI,CAAC,CAAC;AACzE,cAAM,SAAS,IAAI,IAAI,KAAK,MAAM,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACjE,YAAI,SAAU,QAAO,OAAO,SAAS,IAAI;AACzC,cAAM,OAAO,UAAU,QAAQ,QAAQ,MAAM,MAAM,MAAM;AAEzD,cAAM,MAAM,KAAK,sBAAsB,KAAK,QAAQ,IAAI,CAAC;AACzD,WAAG,OAAO,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAC/C,iBAAS,MAAM,KAAK,GAAG;AAEvB,cAAM,aAAa,WACd,KAAK,MAAM,cAAc,SAAS,IAAI,EAAE,MAAM,MAAM,MAAM,aAAa,MAAM,YAAY,CAAC,KAAK,WAChG,KAAK,MAAM,YAAY;AAAA,UACrB;AAAA,UAAM,MAAM,MAAM;AAAA,UAAM,aAAa,MAAM;AAAA,UAAa,MAAM;AAAA,UAAK,QAAQ;AAAA,QAC7E,CAAC;AAML,cAAM,EAAE,kBAAkB,qBAAqB,IAAI,MAAM,OAAO,kBAAW;AAC3E,cAAM,YAAY,qBAAqB,iBAAiB,GAAG,CAAC;AAE5D,YAAI,KAAK;AAAA,UACP,OAAO;AAAA,UACP,aAAa,MAAM,SAAS;AAAA,UAC5B,cAAc,eAAe,OAAO,GAAG,IAAI;AAAA,UAC3C,UAAU,QAAQ,QAAQ;AAAA,QAC5B,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT,UAAE;AACA,cAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA,EAGA,UAAU,IAAiD;AACzD,UAAM,QAAQ,KAAK,MAAM,SAAS,EAAE;AACpC,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,OAAO,KAAK,KAAK,MAAM,MAAM,UAAU;AAC7C,QAAI,CAAC,GAAG,WAAW,IAAI,EAAG,QAAO,EAAE,GAAG,OAAO,QAAQ,GAAG;AACxD,UAAM,MAAM,GAAG,aAAa,MAAM,MAAM;AACxC,UAAM,EAAE,OAAO,IAAI,iBAAiB,GAAG;AACvC,WAAO,EAAE,GAAG,OAAO,OAAO;AAAA,EAC5B;AAAA;AAAA,EAGA,YAAY,IAAkB;AAC5B,UAAM,QAAQ,KAAK,MAAM,SAAS,EAAE;AACpC,QAAI,CAAC,MAAO;AACZ,UAAM,WAAW,KAAK,sBAAsB,MAAM,IAAI;AACtD,OAAG,OAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACpD,SAAK,MAAM,YAAY,EAAE;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,YAAuD;AACrD,UAAM,WAAqB,CAAC;AAC5B,UAAM,UAAoB,CAAC;AAC3B,eAAW,SAAS,KAAK,MAAM,WAAW,GAAG;AAC3C,UAAI,GAAG,WAAW,KAAK,KAAK,MAAM,MAAM,UAAU,CAAC,EAAG;AACtD,YAAM,WAAW,KAAK,KAAK,KAAK,WAAW,MAAM,IAAI;AACrD,UAAI,GAAG,WAAW,KAAK,KAAK,UAAU,UAAU,CAAC,GAAG;AAClD,aAAK,MAAM,YAAY,MAAM,IAAI,EAAE,MAAM,SAAS,CAAC;AACnD,iBAAS,KAAK,MAAM,IAAI;AAAA,MAC1B,OAAO;AACL,aAAK,MAAM,YAAY,MAAM,EAAE;AAC/B,gBAAQ,KAAK,MAAM,IAAI;AAAA,MACzB;AAAA,IACF;AACA,WAAO,EAAE,UAAU,QAAQ;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,gBAAgB,OAA2B;AACzC,UAAM,UAAoB,CAAC;AAC3B,eAAW,QAAQ,OAAO;AACxB,YAAM,aAAa,KAAK,MAAM,eAAe,IAAI;AACjD,UAAI,CAAC,WAAY;AACjB,YAAM,OAAO,KAAK,KAAK,KAAK,WAAW,MAAM,UAAU;AACvD,UAAI,CAAC,GAAG,WAAW,IAAI,EAAG;AAC1B,YAAM,EAAE,MAAM,YAAY,IAAI,iBAAiB,GAAG,aAAa,MAAM,MAAM,CAAC;AAC5E,YAAM,WAAW,QAAQ,WAAW;AACpC,UAAI,aAAa,WAAW,QAAQ,iBAAiB,WAAW,eAAe,IAAK;AACpF,WAAK,MAAM,YAAY,WAAW,IAAI,EAAE,MAAM,UAAU,YAAY,CAAC;AACrE,cAAQ,KAAK,IAAI;AAAA,IACnB;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAwB;AACtB,QAAI,CAAC,GAAG,WAAW,KAAK,SAAS,EAAG,QAAO,CAAC;AAC5C,UAAM,QAAiB,CAAC;AACxB,eAAW,SAAS,GAAG,YAAY,KAAK,WAAW,EAAE,eAAe,KAAK,CAAC,GAAG;AAC3E,UAAI,CAAC,MAAM,YAAY,EAAG;AAC1B,YAAM,OAAO,MAAM;AACnB,YAAM,MAAM,KAAK,KAAK,KAAK,WAAW,IAAI;AAC1C,YAAM,OAAO,KAAK,KAAK,KAAK,UAAU;AACtC,UAAI,CAAC,GAAG,WAAW,IAAI,EAAG;AAC1B,UAAI,KAAK,MAAM,eAAe,IAAI,EAAG;AACrC,YAAM,MAAM,GAAG,aAAa,MAAM,MAAM;AACxC,YAAM,EAAE,MAAM,YAAY,IAAI,iBAAiB,GAAG;AAClD,YAAM,QAAQ,KAAK,MAAM,YAAY;AAAA,QACnC;AAAA,QACA,MAAM,QAAQ;AAAA,QACd;AAAA,QACA,MAAM;AAAA,QACN,QAAQ;AAAA,MACV,CAAC;AACD,YAAM,KAAK,KAAK;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../packages/server/src/scheduler/scheduler.ts"],
|
|
4
|
-
"sourcesContent": ["import cron, { type ScheduledTask } from 'node-cron';\nimport type { Store } from '../db/store.js';\nimport type { EventBus } from '../util/bus.js';\nimport { logger } from '../util/log.js';\nimport type { Routine, Settings, TurnOrigin } from '@antbot/shared';\n\nconst log = logger('scheduler');\n\n/**\n * The subset of BotManager.enqueue the scheduler needs. Kept minimal and structural (rather than\n * importing BotManager directly) so tests can inject a fake manager without spawning real turns.\n */\nexport interface SchedulerEnqueueArgs {\n botId: string;\n threadId: string;\n prompt: string;\n origin: TurnOrigin;\n hops: number;\n priority?: number;\n onDone?: (summary: string, ok: boolean) => void;\n}\nexport interface SchedulerManager {\n enqueue(job: SchedulerEnqueueArgs): { id: string };\n}\n\nexport interface SchedulerDeps {\n store: Store;\n bus: EventBus;\n manager: SchedulerManager;\n getSettings: () => Settings;\n}\n\n/* ------------------------------- cron parsing ------------------------------- */\n\ninterface CronField {\n values: Set<number>;\n wildcard: boolean;\n}\n\ninterface ParsedCron {\n minute: CronField;\n hour: CronField;\n dayOfMonth: CronField;\n month: CronField;\n dayOfWeek: CronField;\n}\n\nfunction parseCronFieldPart(field: string, min: number, max: number): CronField {\n const trimmed = field.trim();\n if (trimmed === '*') {\n const values = new Set<number>();\n for (let v = min; v <= max; v++) values.add(v);\n return { values, wildcard: true };\n }\n const values = new Set<number>();\n for (const part of trimmed.split(',')) {\n const m = part.match(/^(\\*|\\d+)(?:-(\\d+))?(?:\\/(\\d+))?$/);\n if (!m) throw new Error(`Invalid cron field: \"${part}\"`);\n const [, startStr, endStr, stepStr] = m;\n const step = stepStr ? parseInt(stepStr, 10) : 1;\n let start: number;\n let end: number;\n if (startStr === '*') {\n start = min;\n end = max;\n } else {\n start = parseInt(startStr!, 10);\n end = endStr !== undefined ? parseInt(endStr, 10) : stepStr ? max : start;\n }\n for (let v = start; v <= end; v += step) values.add(v);\n }\n return { values, wildcard: false };\n}\n\n/** Parse a standard 5-field cron expression (minute hour dom month dow). Pure, no I/O. */\nexport function parseCronExpr(expr: string): ParsedCron {\n const parts = expr.trim().split(/\\s+/);\n if (parts.length !== 5) throw new Error(`Cron expression must have 5 fields: \"${expr}\"`);\n const [minute, hour, dayOfMonth, month, dayOfWeekRaw] = parts as [string, string, string, string, string];\n const dayOfWeek = parseCronFieldPart(dayOfWeekRaw, 0, 7);\n // normalize 7 (alt-Sunday) into 0\n if (dayOfWeek.values.has(7)) {\n dayOfWeek.values.delete(7);\n dayOfWeek.values.add(0);\n }\n return {\n minute: parseCronFieldPart(minute, 0, 59),\n hour: parseCronFieldPart(hour, 0, 23),\n dayOfMonth: parseCronFieldPart(dayOfMonth, 1, 31),\n month: parseCronFieldPart(month, 1, 12),\n dayOfWeek,\n };\n}\n\ninterface TzParts {\n month: number;\n day: number;\n hour: number;\n minute: number;\n weekday: number;\n}\n\nconst WEEKDAY_INDEX: Record<string, number> = { Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6 };\n\nfunction makeTzFormatter(timeZone: string): Intl.DateTimeFormat {\n return new Intl.DateTimeFormat('en-US', {\n timeZone,\n hour12: false,\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n weekday: 'short',\n });\n}\n\nfunction tzParts(dtf: Intl.DateTimeFormat, ms: number): TzParts {\n const parts = dtf.formatToParts(new Date(ms));\n const map: Record<string, string> = {};\n for (const p of parts) map[p.type] = p.value;\n let hour = parseInt(map.hour ?? '0', 10);\n if (hour === 24) hour = 0; // some ICU builds report midnight as \"24\" under hour12:false\n return {\n month: parseInt(map.month ?? '1', 10),\n day: parseInt(map.day ?? '1', 10),\n hour,\n minute: parseInt(map.minute ?? '0', 10),\n weekday: WEEKDAY_INDEX[map.weekday ?? 'Sun'] ?? 0,\n };\n}\n\nconst MAX_LOOKAHEAD_MINUTES = 366 * 24 * 60;\n\n/**\n * Compute the next fire time (ms, strictly after `fromMs`) for a 5-field cron expression in a\n * given IANA timezone. Implemented by iterating minute-by-minute over a bounded window \u2014 no\n * dependency on node-cron internals. Returns null if nothing matches within 366 days.\n */\nexport function nextRunAt(cronExpr: string, timezone: string, fromMs: number): number | null {\n const fields = parseCronExpr(cronExpr);\n const dtf = makeTzFormatter(timezone);\n const bothWildcard = fields.dayOfMonth.wildcard && fields.dayOfWeek.wildcard;\n\n let t = Math.floor(fromMs / 60000) * 60000 + 60000;\n for (let i = 0; i < MAX_LOOKAHEAD_MINUTES; i++, t += 60000) {\n const p = tzParts(dtf, t);\n if (!fields.minute.values.has(p.minute)) continue;\n if (!fields.hour.values.has(p.hour)) continue;\n if (!fields.month.values.has(p.month)) continue;\n const domMatch = fields.dayOfMonth.values.has(p.day);\n const dowMatch = fields.dayOfWeek.values.has(p.weekday);\n const dayOk = bothWildcard\n ? true\n : fields.dayOfMonth.wildcard\n ? dowMatch\n : fields.dayOfWeek.wildcard\n ? domMatch\n : domMatch || dowMatch;\n if (!dayOk) continue;\n return t;\n }\n return null;\n}\n\n/* ------------------------------- human summary ------------------------------- */\n\nconst DOW_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\n\n/** Render a short human string for common cron shapes; falls back to the raw expression. */\nexport function cronToHuman(expr: string): string {\n const parts = expr.trim().split(/\\s+/);\n if (parts.length !== 5) return expr;\n const [min, hour, dom, month, dow] = parts as [string, string, string, string, string];\n const pad = (n: string): string => n.padStart(2, '0');\n\n if (min.startsWith('*/') && hour === '*' && dom === '*' && month === '*' && dow === '*') {\n return `Every ${min.slice(2)} minutes`;\n }\n if (hour.startsWith('*/') && min === '0' && dom === '*' && month === '*' && dow === '*') {\n return `Every ${hour.slice(2)} hours`;\n }\n if (/^\\d+$/.test(min) && /^\\d+$/.test(hour)) {\n const time = `${pad(hour)}:${pad(min)}`;\n if (dom === '*' && month === '*') {\n if (dow === '*') return `Every day at ${time}`;\n if (dow === '1-5') return `Every weekday at ${time}`;\n if (dow === '0,6' || dow === '6,0') return `Every weekend day at ${time}`;\n if (/^\\d$/.test(dow)) return `Every ${DOW_NAMES[parseInt(dow, 10)]} at ${time}`;\n }\n if (/^\\d+$/.test(dom) && month === '*' && dow === '*') {\n return `Monthly on day ${dom} at ${time}`;\n }\n }\n return expr;\n}\n\n/* --------------------------------- away guard --------------------------------- */\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\n/**\n * Outline \u00A78: after a long absence, ask whether to keep routines running, and pause if there's\n * no response. `ok` under 7 days away, `ask` between 7 and 14 days, `pause` beyond 14 days.\n */\nexport function checkAwayGuard(lastUserActivityMs: number, nowMs: number): 'ok' | 'ask' | 'pause' {\n const gap = nowMs - lastUserActivityMs;\n if (gap > 14 * DAY_MS) return 'pause';\n if (gap > 7 * DAY_MS) return 'ask';\n return 'ok';\n}\n\n/* --------------------------------- prompt shape --------------------------------- */\n\n/** Build the turn prompt for a routine fire, per outline \u00A78 (naming + stale-data doctrine). */\nexport function buildRoutinePrompt(routine: Routine, isTest: boolean): string {\n const header = isTest\n ? `This is a **test run** of your routine \"${routine.name}\". Test runs perform real work \u2014 treat it like a live run, and flag anything before doing something irreversible.`\n : `This is a **scheduled run** of your routine \"${routine.name}\" (${routine.cronExpr}, ${routine.timezone}).`;\n return [\n header,\n '',\n 'If the source data is unavailable, report the failure instead of using old data.',\n '',\n '---',\n '',\n routine.instructionMd,\n ].join('\\n');\n}\n\n/* ---------------------------------- scheduler ---------------------------------- */\n\nexport class Scheduler {\n private tasks = new Map<string, ScheduledTask>();\n private paused = false;\n\n constructor(private deps: SchedulerDeps) {}\n\n /** Load every enabled routine and schedule it with node-cron. */\n start(): void {\n for (const routine of this.deps.store.listRoutines()) {\n if (routine.enabled) this.scheduleRoutine(routine);\n }\n }\n\n /** Cancel all scheduled tasks and release their timers. */\n stop(): void {\n for (const task of this.tasks.values()) {\n task.stop();\n void task.destroy();\n }\n this.tasks.clear();\n }\n\n /** Re-sync a single routine (call after create/update/delete/enable-toggle). */\n reload(routineId: string): void {\n this.unschedule(routineId);\n const routine = this.deps.store.getRoutine(routineId);\n if (routine?.enabled && !this.paused) this.scheduleRoutine(routine);\n }\n\n /** Re-sync every routine from scratch. */\n syncAll(): void {\n this.stop();\n this.start();\n }\n\n /** Pause every scheduled routine without forgetting its schedule (outline \u00A78 away-guard). */\n pauseAll(): void {\n this.paused = true;\n for (const task of this.tasks.values()) task.stop();\n }\n\n /** Resume every scheduled routine after a pause. */\n resumeAll(): void {\n this.paused = false;\n for (const task of this.tasks.values()) task.start();\n }\n\n private unschedule(routineId: string): void {\n const task = this.tasks.get(routineId);\n if (!task) return;\n task.stop();\n void task.destroy();\n this.tasks.delete(routineId);\n }\n\n private scheduleRoutine(routine: Routine): void {\n if (!cron.validate(routine.cronExpr)) {\n log.warn(`routine ${routine.id} has an invalid cron expression: \"${routine.cronExpr}\"`);\n return;\n }\n const task = cron.schedule(\n routine.cronExpr,\n () => {\n this.fire(routine.id, false);\n },\n { timezone: routine.timezone, unref: true },\n );\n if (this.paused) task.stop();\n this.tasks.set(routine.id, task);\n this.updateNextRunAt(routine);\n }\n\n private updateNextRunAt(routine: Routine): void {\n const next = nextRunAt(routine.cronExpr, routine.timezone, Date.now());\n this.deps.store.updateRoutine(routine.id, { nextRunAt: next });\n }\n\n /** Fire a routine now: starts a run record, publishes events, and enqueues the turn. */\n private fire(routineId: string, isTest: boolean): string {\n const { store, bus, manager } = this.deps;\n const routine = store.getRoutine(routineId);\n if (!routine) throw new Error(`Unknown routine: ${routineId}`);\n\n const bot = store.getBot(routine.botId);\n const run = store.startRun(routineId, isTest, bot?.threadId ?? undefined);\n bus.publish({ type: 'routine.run', threadId: bot?.threadId ?? null, botId: routine.botId, run });\n\n const next = isTest ? routine.nextRunAt : nextRunAt(routine.cronExpr, routine.timezone, Date.now());\n store.updateRoutine(routineId, { lastRunAt: run.startedAt, nextRunAt: next });\n\n if (!bot || !bot.threadId) {\n const failed = store.finishRun(run.id, 'failed', 'Owning bot no longer exists.');\n if (failed) bus.publish({ type: 'routine.run', threadId: null, botId: routine.botId, run: failed });\n return run.id;\n }\n\n manager.enqueue({\n botId: bot.id,\n threadId: bot.threadId,\n prompt: buildRoutinePrompt(routine, isTest),\n origin: 'routine',\n hops: 0,\n priority: 10,\n onDone: (summary, ok) => {\n const finished = store.finishRun(run.id, ok ? 'ok' : 'failed', summary);\n if (finished) bus.publish({ type: 'routine.run', threadId: bot.threadId, botId: routine.botId, run: finished });\n },\n });\n\n return run.id;\n }\n\n /** Fire a routine immediately as a test run (real work, marked `isTest`). Returns the run id. */\n testRun(routineId: string): string {\n return this.fire(routineId, true);\n }\n\n /**\n * Apply the outline \u00A78 away-guard: pause all routines beyond 14 days of inactivity, or notify\n * asking whether to keep them running between 7 and 14 days.\n */\n checkAndApplyAwayGuard(lastUserActivityMs: number, nowMs = Date.now()): 'ok' | 'ask' | 'pause' {\n const result = checkAwayGuard(lastUserActivityMs, nowMs);\n if (result === 'pause') {\n this.pauseAll();\n } else if (result === 'ask') {\n this.deps.bus.publish({\n type: 'notify',\n threadId: null,\n botId: null,\n title: 'Still away?',\n body: \"It's been a while since you were last active. Keep routines running, or pause them?\",\n level: 'warn',\n });\n }\n return result;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["values"]
|
|
7
|
-
}
|