session-steward 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}@layer theme{:root,:host{--font-sans:Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-950:oklch(26.2% .051 172.552);--color-sky-400:oklch(74.6% .16 232.661);--color-rose-100:oklch(94.1% .03 12.58);--color-rose-200:oklch(89.2% .058 10.001);--color-rose-300:oklch(81% .117 11.638);--color-rose-400:oklch(71.2% .194 13.428);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--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-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-tight:-.025em;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-spin:spin 1s linear 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{.relative{position:relative}.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)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-1{margin-left:var(--spacing)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.size-1{width:var(--spacing);height:var(--spacing)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-3{height:calc(var(--spacing) * 3)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-9{height:calc(var(--spacing) * 9)}.h-\[76px\]{height:76px}.h-\[92px\]{height:92px}.h-full{height:100%}.min-h-12{min-height:calc(var(--spacing) * 12)}.min-h-14{min-height:calc(var(--spacing) * 14)}.min-h-\[70px\]{min-height:70px}.min-h-\[340px\]{min-height:340px}.min-h-\[360px\]{min-height:360px}.min-h-screen{min-height:100vh}.w-16{width:calc(var(--spacing) * 16)}.w-32{width:calc(var(--spacing) * 32)}.w-\[min\(50\%\,20rem\)\]{width:min(50%,20rem)}.w-\[min\(75\%\,30rem\)\]{width:min(75%,30rem)}.max-w-\[230px\]{max-width:230px}.max-w-\[1380px\]{max-width:1380px}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:0}.min-w-40{min-width:calc(var(--spacing) * 40)}.shrink-0{flex-shrink:0}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\[18px_minmax\(0\,1fr\)\]{grid-template-columns:18px minmax(0,1fr)}.grid-cols-\[20px_minmax\(0\,1fr\)_80px\]{grid-template-columns:20px minmax(0,1fr) 80px}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.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-end{justify-content:flex-end}.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-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * 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-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-white\/\[\.055\]>:not(:last-child)){border-color:#ffffff0e}@supports (color:color-mix(in lab, red, red)){:where(.divide-white\/\[\.055\]>:not(:last-child)){border-color:color-mix(in oklab, var(--color-white) 5.5%, transparent)}}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-amber-300\/15{border-color:#ffd23626}@supports (color:color-mix(in lab, red, red)){.border-amber-300\/15{border-color:color-mix(in oklab, var(--color-amber-300) 15%, transparent)}}.border-amber-300\/20{border-color:#ffd23633}@supports (color:color-mix(in lab, red, red)){.border-amber-300\/20{border-color:color-mix(in oklab, var(--color-amber-300) 20%, transparent)}}.border-emerald-300{border-color:var(--color-emerald-300)}.border-rose-400\/20{border-color:#ff667f33}@supports (color:color-mix(in lab, red, red)){.border-rose-400\/20{border-color:color-mix(in oklab, var(--color-rose-400) 20%, transparent)}}.border-white\/15{border-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.border-white\/15{border-color:color-mix(in oklab, var(--color-white) 15%, transparent)}}.border-white\/\[\.06\]{border-color:#ffffff0f}@supports (color:color-mix(in lab, red, red)){.border-white\/\[\.06\]{border-color:color-mix(in oklab, var(--color-white) 6%, transparent)}}.border-white\/\[\.07\]{border-color:#ffffff12}@supports (color:color-mix(in lab, red, red)){.border-white\/\[\.07\]{border-color:color-mix(in oklab, var(--color-white) 7.0%, transparent)}}.border-white\/\[\.08\]{border-color:#ffffff14}@supports (color:color-mix(in lab, red, red)){.border-white\/\[\.08\]{border-color:color-mix(in oklab, var(--color-white) 8%, transparent)}}.border-white\/\[\.055\]{border-color:#ffffff0e}@supports (color:color-mix(in lab, red, red)){.border-white\/\[\.055\]{border-color:color-mix(in oklab, var(--color-white) 5.5%, transparent)}}.bg-amber-300{background-color:var(--color-amber-300)}.bg-amber-300\/\[\.06\]{background-color:#ffd2360f}@supports (color:color-mix(in lab, red, red)){.bg-amber-300\/\[\.06\]{background-color:color-mix(in oklab, var(--color-amber-300) 6%, transparent)}}.bg-amber-300\/\[\.045\]{background-color:#ffd2360b}@supports (color:color-mix(in lab, red, red)){.bg-amber-300\/\[\.045\]{background-color:color-mix(in oklab, var(--color-amber-300) 4.5%, transparent)}}.bg-black\/10{background-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.bg-black\/10{background-color:color-mix(in oklab, var(--color-black) 10%, transparent)}}.bg-emerald-300{background-color:var(--color-emerald-300)}.bg-emerald-400{background-color:var(--color-emerald-400)}.bg-rose-400{background-color:var(--color-rose-400)}.bg-rose-400\/\[\.07\]{background-color:#ff667f12}@supports (color:color-mix(in lab, red, red)){.bg-rose-400\/\[\.07\]{background-color:color-mix(in oklab, var(--color-rose-400) 7.0%, transparent)}}.bg-sky-400{background-color:var(--color-sky-400)}.bg-white\/\[\.03\]{background-color:#ffffff08}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[\.03\]{background-color:color-mix(in oklab, var(--color-white) 3%, transparent)}}.bg-white\/\[\.07\]{background-color:#ffffff12}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[\.07\]{background-color:color-mix(in oklab, var(--color-white) 7.0%, transparent)}}.bg-white\/\[\.012\]{background-color:#ffffff03}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[\.012\]{background-color:color-mix(in oklab, var(--color-white) 1.2%, transparent)}}.bg-white\/\[\.025\]{background-color:#ffffff06}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[\.025\]{background-color:color-mix(in oklab, var(--color-white) 2.5%, transparent)}}.bg-white\/\[\.035\]{background-color:#ffffff09}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[\.035\]{background-color:color-mix(in oklab, var(--color-white) 3.5%, transparent)}}.p-3{padding:calc(var(--spacing) * 3)}.p-3\.5{padding:calc(var(--spacing) * 3.5)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-7{padding:calc(var(--spacing) * 7)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-\[1\.15rem\]{padding-block:1.15rem}.pt-4{padding-top:calc(var(--spacing) * 4)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pl-\[3\.4rem\]{padding-left:3.4rem}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.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-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-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.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-\[-\.035em\]{--tw-tracking:-.035em;letter-spacing:-.035em}.tracking-\[\.11em\]{--tw-tracking:.11em;letter-spacing:.11em}.tracking-\[\.12em\]{--tw-tracking:.12em;letter-spacing:.12em}.tracking-\[\.16em\]{--tw-tracking:.16em;letter-spacing:.16em}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.text-amber-100{color:var(--color-amber-100)}.text-amber-100\/75{color:#fef3c6bf}@supports (color:color-mix(in lab, red, red)){.text-amber-100\/75{color:color-mix(in oklab, var(--color-amber-100) 75%, transparent)}}.text-amber-100\/80{color:#fef3c6cc}@supports (color:color-mix(in lab, red, red)){.text-amber-100\/80{color:color-mix(in oklab, var(--color-amber-100) 80%, transparent)}}.text-amber-300{color:var(--color-amber-300)}.text-emerald-300{color:var(--color-emerald-300)}.text-emerald-400{color:var(--color-emerald-400)}.text-emerald-950{color:var(--color-emerald-950)}.text-rose-100{color:var(--color-rose-100)}.text-rose-200{color:var(--color-rose-200)}.text-rose-300{color:var(--color-rose-300)}.text-white{color:var(--color-white)}.text-zinc-100{color:var(--color-zinc-100)}.text-zinc-200{color:var(--color-zinc-200)}.text-zinc-300{color:var(--color-zinc-300)}.text-zinc-400{color:var(--color-zinc-400)}.text-zinc-500{color:var(--color-zinc-500)}.text-zinc-600{color:var(--color-zinc-600)}.text-zinc-700{color:var(--color-zinc-700)}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.group-hover\:translate-x-0\.5:is(:where(.group):hover *){--tw-translate-x:calc(var(--spacing) * .5);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-hover\:text-white:is(:where(.group):hover *){color:var(--color-white)}.group-hover\:text-zinc-400:is(:where(.group):hover *){color:var(--color-zinc-400)}}.last\:border-0:last-child{border-style:var(--tw-border-style);border-width:0}.last\:pb-0:last-child{padding-bottom:0}@media (width>=40rem){.sm\:block{display:block}.sm\:flex{display:flex}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-end{justify-content:flex-end}.sm\:p-5{padding:calc(var(--spacing) * 5)}.sm\:px-5{padding-inline:calc(var(--spacing) * 5)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:py-8{padding-block:calc(var(--spacing) * 8)}.sm\:pl-0{padding-left:0}.sm\:text-\[1\.75rem\]{font-size:1.75rem}}@media (width>=64rem){.lg\:hidden{display:none}.lg\:grid-cols-\[minmax\(0\,1fr\)_320px\]{grid-template-columns:minmax(0,1fr) 320px}.lg\:grid-cols-\[minmax\(280px\,1fr\)_190px_auto\]{grid-template-columns:minmax(280px,1fr) 190px auto}.lg\:items-end{align-items:flex-end}.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}}@media (width>=80rem){.xl\:grid-cols-\[minmax\(0\,1fr\)_340px\]{grid-template-columns:minmax(0,1fr) 340px}}}:root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;font-synthesis:none;text-rendering:optimizelegibility}*{box-sizing:border-box}body{background:#08090b;min-width:320px;margin:0}button,input,select{font:inherit}button{cursor:pointer}button:disabled{cursor:not-allowed}button:focus-visible,input:focus-visible,select:focus-visible{outline-offset:2px;outline:2px solid #34d399}::selection{color:#fff;background:#34d39947}.app-shell{background:radial-gradient(circle at 50% -12rem,#10b98109,#0000 28rem),#08090b;position:relative;overflow-x:hidden}.app-shell:before{pointer-events:none;content:"";background:linear-gradient(90deg,#0000,#34d39947,#0000);height:1px;position:fixed;top:0;left:0;right:0}.surface{background:#111216;border:1px solid #ffffff13;border-radius:1rem;box-shadow:inset 0 1px #ffffff06,0 14px 40px #0000001f}.brand-mark{color:#6ee7b7;background:linear-gradient(145deg,#34d39926,#10b9810b);border:1px solid #34d3992e;border-radius:.9rem;flex:none;place-items:center;width:2.8rem;height:2.8rem;display:grid;box-shadow:0 0 30px #10b9810f}.icon-tile{color:#a1a1aa;background:#ffffff09;border:1px solid #ffffff14;border-radius:.75rem;flex:none;place-items:center;width:2.4rem;height:2.4rem;display:grid}.eyebrow{letter-spacing:.12em;text-transform:uppercase;color:#a1a1aa;font-size:.72rem;font-weight:700;line-height:1rem}.source-badge,.selection-count{color:#a1a1aa;background:#ffffff0a;border:1px solid #ffffff14;border-radius:999px;font-size:.69rem;font-weight:650}.source-badge{padding:.15rem .45rem}.selection-count{color:#d4d4d8;padding:.42rem .65rem}.button{border:1px solid #0000;border-radius:.68rem;justify-content:center;align-items:center;gap:.45rem;min-height:2.35rem;padding:.55rem .8rem;font-size:.78rem;font-weight:650;line-height:1rem;transition:border-color .15s,background .15s,color .15s;display:inline-flex}.button:disabled{opacity:.42}.button.secondary{color:#e4e4e7;background:#ffffff0e;border-color:#ffffff14}.button.secondary:hover:not(:disabled){background:#ffffff17;border-color:#ffffff21}.button.ghost{color:#a1a1aa;background:0 0;border-color:#fff1}.button.ghost:hover:not(:disabled){color:#e4e4e7;background:#ffffff0a;border-color:#ffffff1f}.button.primary{color:#fff;background:#059669;border-color:#34d39940;box-shadow:0 8px 24px #05966921}.button.primary:hover:not(:disabled){background:#10b981}.button.danger{color:#fff;background:#dc2626d6;border-color:#f8717133;box-shadow:0 8px 24px #7f1d1d26}.button.danger:hover:not(:disabled){background:#dc2626}.icon-button{color:#71717a;background:0 0;border:1px solid #0000;border-radius:.55rem;flex:none;place-items:center;width:2rem;height:2rem;transition:all .15s;display:grid}.icon-button:hover:not(:disabled){color:#e4e4e7;background:#ffffff0d;border-color:#ffffff14}.field{letter-spacing:.025em;color:#a1a1aa;gap:.45rem;font-size:.74rem;font-weight:650;display:grid}.field>span{align-items:center;gap:.35rem;display:flex}.field input,.field select,.input-wrap{color:#f4f4f5;background:#0506088a;border:1px solid #ffffff17;border-radius:.7rem;width:100%;min-height:2.55rem;transition:border-color .15s,background .15s,box-shadow .15s}.field>input,.field select{padding:.65rem .75rem}.field input::placeholder{color:#52525b}.field input:hover,.field select:hover,.input-wrap:hover{border-color:#ffffff24}.field input:focus,.field select:focus,.input-wrap:focus-within{background:#050608bf;border-color:#34d3998c;box-shadow:0 0 0 3px #34d39912}.input-wrap{color:#52525b;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;padding:0 .75rem;display:grid}.input-wrap input{min-height:auto;box-shadow:none;background:0 0;border:0;border-radius:0;outline:0;padding:.65rem .6rem}.input-wrap button{color:#71717a;background:0 0;border:0;place-items:center;display:grid}.toggle{cursor:pointer;color:#a1a1aa;background:#ffffff06;border:1px solid #ffffff13;border-radius:.65rem;align-items:center;gap:.45rem;min-height:2.15rem;padding:.4rem .62rem;font-size:.72rem;font-weight:600;transition:all .15s;display:inline-flex}.toggle:hover{color:#d4d4d8;border-color:#ffffff21}.toggle input{opacity:0;pointer-events:none;position:absolute}.toggle-track{background:#3f3f46;border-radius:999px;width:1.55rem;height:.9rem;transition:all .15s;position:relative}.toggle-track span{background:#a1a1aa;border-radius:999px;width:.6rem;height:.6rem;transition:all .15s;position:absolute;top:.15rem;left:.15rem}.toggle-active{color:#a7f3d0;background:#10b98113;border-color:#34d39933}.toggle-active .toggle-track{background:#059669}.toggle-active .toggle-track span{background:#fff;left:.8rem}.selection-control{cursor:pointer;color:#d4d4d8;align-items:center;gap:.55rem;font-size:.74rem;font-weight:600;display:inline-flex}.selection-control input,.session-checkbox input{accent-color:#10b981;width:1rem;height:1rem;margin:0}.session-row{grid-template-columns:20px minmax(0,1fr) auto auto;align-items:center;gap:.7rem;min-height:76px;padding:.8rem 1rem;transition:background .15s,box-shadow .15s;display:grid;position:relative}.session-row:hover{background:#ffffff06}.session-row-inspected{background:#ffffff07;box-shadow:inset 3px 0 #71717a}.session-row-selected{background:#10b98107}.session-row-inspected.session-row-selected{background:#10b9810e;box-shadow:inset 3px 0 #34d399}.session-checkbox{cursor:pointer;place-items:center;display:grid}.session-row>button{color:inherit;background:0 0;border:0;padding:.2rem 0}.inspector,.inspector-backdrop{display:none}@media (width<=1023px){.inspector-open{z-index:40;max-height:min(36rem,100vh - 3rem);display:block;position:fixed;bottom:.75rem;left:.75rem;right:.75rem;overflow-y:auto;box-shadow:0 28px 90px #0000009e}.inspector-backdrop-open{z-index:39;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#00000094;border:0;width:100%;height:100%;display:block;position:fixed;inset:0}}@media (width>=1024px){.inspector{display:block;position:sticky;top:1.5rem}}.time-badge,.kind-label{white-space:nowrap;align-items:center;gap:.3rem;display:inline-flex}.time-badge{color:#a1a1aa;background:#ffffff07;border:1px solid #fff1;border-radius:999px;padding:.25rem .48rem;font-size:.63rem;font-weight:600}.kind-label{color:#71717a;font-size:.68rem}.page-button{color:#71717a;background:0 0;border:1px solid #0000;border-radius:.55rem;place-items:center;min-width:2rem;height:2rem;padding:0 .42rem;font-size:.7rem;transition:all .15s;display:grid}.page-button:hover:not(:disabled){color:#e4e4e7;background:#ffffff0b;border-color:#ffffff14}.page-button[aria-current=page]{color:#a7f3d0;background:#10b9811a;border-color:#34d39933}.page-button:disabled{opacity:.28}.status-pill{border:1px solid;border-radius:999px;align-items:center;gap:.5rem;min-height:2.25rem;padding:.48rem .7rem;font-size:.69rem;font-weight:650;transition:filter .15s;display:inline-flex}.status-pill:hover{filter:brightness(1.12)}.status-pill>span{background:currentColor;border-radius:999px;width:.42rem;height:.42rem;box-shadow:0 0 10px}.status-ready{color:#a7f3d0;background:#10b98114;border-color:#34d39938}.status-warning{color:#fde68a;background:#f59e0b14;border-color:#fbbf2438}.status-error{color:#fecdd3;background:#e11d4814;border-color:#fb718538}.compatibility-popover{z-index:30;-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);background:#0c0d0ffa;border:1px solid #ffffff17;border-radius:.9rem;width:min(25rem,100vw - 2rem);padding:1rem;position:absolute;top:calc(100% + .55rem);right:0;box-shadow:0 24px 70px #0000008c,inset 0 1px #ffffff09}.alert{border:1px solid;border-radius:.8rem;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:.65rem;margin-bottom:1.25rem;padding:.75rem .85rem;font-size:.78rem;display:grid}.alert button{color:currentColor;opacity:.65;background:0 0;border:0;place-items:center;display:grid}.alert-success{color:#a7f3d0;background:#10b98112;border-color:#34d39933}.alert-warning{color:#fde68a;background:#f59e0b12;border-color:#fbbf2433}.alert-error{color:#fecdd3;background:#e11d4812;border-color:#fb718533}.dialog-backdrop{z-index:50;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);background:#000000c7;place-items:center;padding:1rem;display:grid;position:fixed;inset:0;overflow-y:auto}.dialog-panel{background:linear-gradient(145deg,#121316,#0b0c0e);border:1px solid #ffffff1a;border-radius:1.15rem;width:100%;max-width:39rem;max-height:calc(100vh - 2rem);padding:1.4rem;overflow-y:auto;box-shadow:0 35px 100px #000000a6,inset 0 1px #ffffff0a}.scope-card{text-align:left;background:#ffffff05;border:1px solid #ffffff14;border-radius:.85rem;padding:.9rem;transition:all .15s}.scope-card:hover:not(:disabled){background:#ffffff08;border-color:#ffffff26}.scope-card-active{background:#10b98112;border-color:#34d39959;box-shadow:inset 0 0 0 1px #34d3990d}.skeleton{background:linear-gradient(90deg,#ffffff09,#ffffff13,#ffffff09) 0 0/200% 100%;animation:1.5s ease-in-out infinite shimmer}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@media (width>=640px){.session-row{padding-left:1.25rem;padding-right:1.25rem}.dialog-panel{padding:1.65rem}}@media (width<=639px){.surface{border-radius:.85rem}.session-row{grid-template-columns:20px minmax(0,1fr) auto;gap:.55rem}.session-row>div{max-width:5.2rem}.kind-label{display:none}.time-badge{background:0 0;border:0;padding-right:0}.compatibility-popover{width:auto;position:fixed;top:5.25rem;left:1rem;right:1rem}.dialog-backdrop{align-items:end;padding:0}.dialog-panel{border-bottom:0;border-left:0;border-right:0;border-radius:1.15rem 1.15rem 0 0;max-height:92vh}}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-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-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}
@@ -0,0 +1,3 @@
1
+ <!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><title>Session Steward</title> <script type="module" crossorigin src="/assets/index-DGVNvKX8.js"></script>
2
+ <link rel="stylesheet" crossorigin href="/assets/index-DTDZWQb9.css">
3
+ </head><body><div id="root"></div></body></html>
package/lib/cli.mjs ADDED
@@ -0,0 +1,579 @@
1
+ import { once } from "node:events";
2
+ import path from "node:path";
3
+ import readline from "node:readline/promises";
4
+ import process, { stdin as input, stdout as output } from "node:process";
5
+
6
+ import { getProvider } from "./providers/index.mjs";
7
+
8
+ const {
9
+ assertDeepCleanupSupported,
10
+ executeSessionDeletion,
11
+ formatSessionForJson,
12
+ getSessionRecord,
13
+ listSessions,
14
+ loadDeletionStore,
15
+ planSessionDeletion,
16
+ verifySessionDeletion,
17
+ } = getProvider("codex");
18
+
19
+ const PAGE_SIZE = 20;
20
+ const HELP_TEXT = `
21
+ Commands
22
+ search <text> Set the active search filter
23
+ search Clear the active search filter
24
+ sort <updated|created|name|cwd>
25
+ Change sort order
26
+ inspect <index|id-prefix> Show session details
27
+ delete <selector> [...] Delete one or more sessions
28
+ page <number> Jump to a page
29
+ next Next page
30
+ prev Previous page
31
+ internals Toggle subagent visibility
32
+ refresh Reload sessions from sqlite and disk
33
+ help Show this help
34
+ quit Exit
35
+
36
+ Selectors
37
+ 3 Single row by current page index
38
+ 2-5 Inclusive range by current page index
39
+ 019dd279 Session id prefix
40
+ delete 1 4-6 019dd26c
41
+ `.trim();
42
+
43
+ function truncate(value, maxLength) {
44
+ if (value.length <= maxLength) {
45
+ return value;
46
+ }
47
+
48
+ if (maxLength <= 3) {
49
+ return value.slice(0, maxLength);
50
+ }
51
+
52
+ return `${value.slice(0, maxLength - 3)}...`;
53
+ }
54
+
55
+ function pad(value, width) {
56
+ return value.padEnd(width, " ");
57
+ }
58
+
59
+ function relativeTime(timestampMs) {
60
+ if (!timestampMs) {
61
+ return "-";
62
+ }
63
+
64
+ const elapsedMs = Date.now() - timestampMs;
65
+ const elapsedMinutes = Math.max(0, Math.floor(elapsedMs / 60000));
66
+
67
+ if (elapsedMinutes < 1) {
68
+ return "now";
69
+ }
70
+
71
+ if (elapsedMinutes < 60) {
72
+ return `${elapsedMinutes}m`;
73
+ }
74
+
75
+ const elapsedHours = Math.floor(elapsedMinutes / 60);
76
+
77
+ if (elapsedHours < 24) {
78
+ return `${elapsedHours}h`;
79
+ }
80
+
81
+ const elapsedDays = Math.floor(elapsedHours / 24);
82
+
83
+ if (elapsedDays < 30) {
84
+ return `${elapsedDays}d`;
85
+ }
86
+
87
+ const elapsedMonths = Math.floor(elapsedDays / 30);
88
+
89
+ if (elapsedMonths < 12) {
90
+ return `${elapsedMonths}mo`;
91
+ }
92
+
93
+ return `${Math.floor(elapsedMonths / 12)}y`;
94
+ }
95
+
96
+ function absoluteTime(timestampMs) {
97
+ if (!timestampMs) {
98
+ return "-";
99
+ }
100
+
101
+ return new Date(timestampMs).toLocaleString();
102
+ }
103
+
104
+ function getCwdDisplay(record) {
105
+ if (!record.cwd) {
106
+ return "-";
107
+ }
108
+
109
+ return path.basename(record.cwd) || record.cwd;
110
+ }
111
+
112
+ function getMarkerText(record) {
113
+ const markers = [];
114
+
115
+ if (record.recordSource === "transcript") {
116
+ markers.push("orphan");
117
+ }
118
+
119
+ if (record.rolloutMissing) {
120
+ markers.push("missing-file");
121
+ }
122
+
123
+ if (record.isFork && !record.isSubagent) {
124
+ markers.push("fork");
125
+ }
126
+
127
+ if (record.isSubagent) {
128
+ const subagentLabel = record.agentNickname || record.agentRole || "subagent";
129
+ markers.push(`sub:${subagentLabel}`);
130
+ } else if (record.childThreadIds.length > 0) {
131
+ markers.push(`subagents:${record.childThreadIds.length}`);
132
+ }
133
+
134
+ if (record.archived) {
135
+ markers.push("archived");
136
+ }
137
+
138
+ return markers.join(", ");
139
+ }
140
+
141
+ function printScreen({ codexHome, result, search, showInternals, sort }) {
142
+ if (output.isTTY) {
143
+ output.write("\x1Bc");
144
+ }
145
+
146
+ output.write("Session Steward\n");
147
+ output.write(
148
+ `Home: ${codexHome} | Sessions: ${result.total} | Page: ${result.page}/${result.pageCount}\n`,
149
+ );
150
+ output.write(
151
+ `Sort: ${sort} | Search: ${search || "-"} | Internals: ${showInternals ? "shown" : "hidden"}\n`,
152
+ );
153
+ output.write(
154
+ "Commands: search | sort | inspect | delete | page | next | prev | internals | refresh | help | quit\n\n",
155
+ );
156
+
157
+ output.write(
158
+ `${pad("#", 4)} ${pad("Name", 64)} ${pad("Updated", 8)} ${pad("Cwd", 20)} Markers\n`,
159
+ );
160
+ output.write(`${"-".repeat(4)} ${"-".repeat(64)} ${"-".repeat(8)} ${"-".repeat(20)} ${"-".repeat(24)}\n`);
161
+
162
+ if (result.records.length === 0) {
163
+ output.write("No sessions match the current view.\n");
164
+ return;
165
+ }
166
+
167
+ result.records.forEach((record, index) => {
168
+ const rowNumber = index + 1;
169
+ output.write(
170
+ `${pad(String(rowNumber), 4)} ${pad(truncate(record.displayName, 64), 64)} ${pad(relativeTime(record.updatedAtMs), 8)} ${pad(truncate(getCwdDisplay(record), 20), 20)} ${truncate(getMarkerText(record), 24)}\n`,
171
+ );
172
+ });
173
+ }
174
+
175
+ function parseCommand(inputValue) {
176
+ const trimmed = inputValue.trim();
177
+
178
+ if (!trimmed) {
179
+ return {
180
+ args: [],
181
+ name: "",
182
+ };
183
+ }
184
+
185
+ const [name, ...args] = trimmed.split(/\s+/u);
186
+
187
+ return {
188
+ args,
189
+ name: name.toLowerCase(),
190
+ };
191
+ }
192
+
193
+ function parseSelectors(selectors, records) {
194
+ const resolvedIds = new Set();
195
+ const flatSelectors = selectors
196
+ .flatMap((selector) => selector.split(","))
197
+ .map((selector) => selector.trim())
198
+ .filter(Boolean);
199
+
200
+ for (const selector of flatSelectors) {
201
+ if (/^\d+$/u.test(selector)) {
202
+ const rowIndex = Number.parseInt(selector, 10) - 1;
203
+ const record = records[rowIndex];
204
+
205
+ if (!record) {
206
+ throw new Error(`No session exists at row ${selector}.`);
207
+ }
208
+
209
+ resolvedIds.add(record.id);
210
+ continue;
211
+ }
212
+
213
+ if (/^\d+-\d+$/u.test(selector)) {
214
+ const [startText, endText] = selector.split("-");
215
+ const start = Number.parseInt(startText, 10);
216
+ const end = Number.parseInt(endText, 10);
217
+
218
+ if (start > end) {
219
+ throw new Error(`Invalid range: ${selector}.`);
220
+ }
221
+
222
+ for (let index = start; index <= end; index += 1) {
223
+ const record = records[index - 1];
224
+
225
+ if (!record) {
226
+ throw new Error(`No session exists at row ${index}.`);
227
+ }
228
+
229
+ resolvedIds.add(record.id);
230
+ }
231
+
232
+ continue;
233
+ }
234
+
235
+ const matches = records.filter((record) => record.id.startsWith(selector));
236
+
237
+ if (matches.length === 0) {
238
+ throw new Error(`No session id starts with "${selector}".`);
239
+ }
240
+
241
+ if (matches.length > 1) {
242
+ throw new Error(`Session id prefix "${selector}" is ambiguous.`);
243
+ }
244
+
245
+ resolvedIds.add(matches[0].id);
246
+ }
247
+
248
+ return [...resolvedIds];
249
+ }
250
+
251
+ function printInspect(record, deletionPlan) {
252
+ output.write("\n");
253
+ output.write(`${record.displayName}\n`);
254
+ output.write(`${"-".repeat(record.displayName.length)}\n`);
255
+ output.write(`Id: ${record.id}\n`);
256
+ output.write(`Updated: ${absoluteTime(record.updatedAtMs)}\n`);
257
+ output.write(`Created: ${absoluteTime(record.createdAtMs)}\n`);
258
+ output.write(`Cwd: ${record.cwd || "-"}\n`);
259
+ output.write(`Transcript: ${record.rolloutPath || "-"}\n`);
260
+ output.write(`Title source: ${record.titleSource}\n`);
261
+ output.write(`Parent: ${record.parentThreadId || "-"}\n`);
262
+ output.write(`Children: ${record.childThreadIds.length}\n`);
263
+ output.write(`Forked from: ${record.forkedFromId || "-"}\n`);
264
+ output.write(`Agent nickname: ${record.agentNickname || "-"}\n`);
265
+ output.write(`Agent role: ${record.agentRole || "-"}\n`);
266
+ output.write(`Markers: ${getMarkerText(record) || "-"}\n`);
267
+ output.write(`Delete sessions: ${deletionPlan.ids.length}\n`);
268
+ output.write(`Delete transcripts: ${deletionPlan.transcriptPaths.length}\n`);
269
+ output.write(`Delete session index rows: ${deletionPlan.sessionIndexMatchCount}\n`);
270
+ output.write(`Delete history rows: ${deletionPlan.historyMatchCount}\n`);
271
+ output.write(`Delete spawn edges: ${deletionPlan.spawnEdgeCount}\n`);
272
+ output.write(`Delete log rows: ${deletionPlan.logRowCount}\n`);
273
+ }
274
+
275
+ function printDeletionPreview(plan) {
276
+ output.write("\nDelete preview\n");
277
+ output.write("--------------\n");
278
+ output.write(`Sessions: ${plan.ids.length}\n`);
279
+ output.write(`Cascaded subagents: ${plan.childCount}\n`);
280
+ output.write(`Transcripts: ${plan.transcriptPaths.length}\n`);
281
+ output.write(`Session index rows: ${plan.sessionIndexMatchCount}\n`);
282
+ output.write(`History rows: ${plan.historyMatchCount}\n`);
283
+ output.write(`Spawn edges: ${plan.spawnEdgeCount}\n`);
284
+ output.write(`Log rows: ${plan.logRowCount}\n`);
285
+
286
+ for (const record of plan.records.slice(0, 20)) {
287
+ output.write(`- ${record.displayName} (${record.id})\n`);
288
+ }
289
+
290
+ if (plan.records.length > 20) {
291
+ output.write(`- and ${plan.records.length - 20} more\n`);
292
+ }
293
+ }
294
+
295
+ async function pause(rl) {
296
+ await rl.question("\nPress Enter to continue...");
297
+ }
298
+
299
+ function printHelp() {
300
+ output.write(`\n${HELP_TEXT}\n`);
301
+ }
302
+
303
+ function validateSort(value) {
304
+ return ["updated", "created", "name", "cwd"].includes(value)
305
+ ? value
306
+ : "updated";
307
+ }
308
+
309
+ async function refreshPage(state) {
310
+ state.result = await listSessions({
311
+ codexHome: state.codexHome,
312
+ includeInternals: state.showInternals,
313
+ page: state.page,
314
+ pageSize: PAGE_SIZE,
315
+ search: state.search,
316
+ sort: state.sort,
317
+ });
318
+ state.page = state.result.page;
319
+ }
320
+
321
+ async function printJson(options) {
322
+ const writeChunk = async (chunk) => {
323
+ if (!output.write(chunk)) await once(output, "drain");
324
+ };
325
+ const limit = Number.isFinite(options.limit) && options.limit > 0 ? options.limit : Infinity;
326
+ let page = 1;
327
+ let written = 0;
328
+ let first = true;
329
+ await writeChunk("[\n");
330
+
331
+ while (written < limit) {
332
+ const result = await listSessions({
333
+ codexHome: options.codexHome,
334
+ includeInternals: Boolean(options.includeInternals),
335
+ page,
336
+ pageSize: Math.min(100, limit - written),
337
+ search: options.search || "",
338
+ sort: validateSort(options.sort || "updated"),
339
+ });
340
+
341
+ for (const record of result.records) {
342
+ if (written >= limit) break;
343
+ await writeChunk(`${first ? "" : ",\n"}${JSON.stringify(formatSessionForJson(record), null, 2)}`);
344
+ first = false;
345
+ written += 1;
346
+ }
347
+
348
+ if (page >= result.pageCount || result.records.length === 0) break;
349
+ page += 1;
350
+ }
351
+
352
+ await writeChunk("\n]\n");
353
+ }
354
+
355
+ async function runInteractive(state) {
356
+ const rl = readline.createInterface({
357
+ input,
358
+ output,
359
+ });
360
+
361
+ try {
362
+ while (true) {
363
+ await refreshPage(state);
364
+ printScreen({
365
+ codexHome: state.codexHome,
366
+ result: state.result,
367
+ search: state.search,
368
+ showInternals: state.showInternals,
369
+ sort: state.sort,
370
+ });
371
+
372
+ const commandInput = await rl.question("\nsession-steward> ");
373
+ const command = parseCommand(commandInput);
374
+
375
+ if (!command.name) {
376
+ continue;
377
+ }
378
+
379
+ if (["q", "quit", "exit"].includes(command.name)) {
380
+ break;
381
+ }
382
+
383
+ if (["help", "h", "?"].includes(command.name)) {
384
+ printHelp();
385
+ await pause(rl);
386
+ continue;
387
+ }
388
+
389
+ if (["refresh", "r"].includes(command.name)) {
390
+ state.page = 1;
391
+ continue;
392
+ }
393
+
394
+ if (["internals", "toggle-internals"].includes(command.name)) {
395
+ state.showInternals = !state.showInternals;
396
+ state.page = 1;
397
+ continue;
398
+ }
399
+
400
+ if (["search", "s"].includes(command.name)) {
401
+ state.search = command.args.join(" ");
402
+ state.page = 1;
403
+ continue;
404
+ }
405
+
406
+ if (command.name === "sort") {
407
+ state.sort = validateSort(command.args[0] ?? "updated");
408
+ state.page = 1;
409
+ continue;
410
+ }
411
+
412
+ if (["next", "n"].includes(command.name)) {
413
+ state.page += 1;
414
+ continue;
415
+ }
416
+
417
+ if (["prev", "p"].includes(command.name)) {
418
+ state.page = Math.max(1, state.page - 1);
419
+ continue;
420
+ }
421
+
422
+ if (command.name === "page") {
423
+ const requestedPage = Number.parseInt(command.args[0] ?? "1", 10);
424
+ state.page = Number.isFinite(requestedPage) && requestedPage > 0 ? requestedPage : 1;
425
+ continue;
426
+ }
427
+
428
+ if (command.name === "inspect") {
429
+ try {
430
+ const sessionIds = parseSelectors(command.args, state.result.records);
431
+
432
+ if (sessionIds.length !== 1) {
433
+ throw new Error("`inspect` accepts exactly one selector.");
434
+ }
435
+
436
+ const record = await getSessionRecord({ codexHome: state.codexHome, id: sessionIds[0] });
437
+ const deletionStore = await loadDeletionStore({
438
+ codexHome: state.codexHome,
439
+ recordIds: sessionIds,
440
+ });
441
+ const deletionPlan = await planSessionDeletion({
442
+ recordIds: sessionIds,
443
+ store: deletionStore,
444
+ });
445
+
446
+ printInspect(record, deletionPlan);
447
+ } catch (error) {
448
+ output.write(`\n${error instanceof Error ? error.message : String(error)}\n`);
449
+ }
450
+
451
+ await pause(rl);
452
+ continue;
453
+ }
454
+
455
+ if (command.name === "delete") {
456
+ try {
457
+ const sessionIds = parseSelectors(command.args, state.result.records);
458
+ await assertDeepCleanupSupported({ codexHome: state.codexHome });
459
+ const deletionStore = await loadDeletionStore({
460
+ codexHome: state.codexHome,
461
+ recordIds: sessionIds,
462
+ });
463
+ const deletionPlan = await planSessionDeletion({
464
+ recordIds: sessionIds,
465
+ store: deletionStore,
466
+ });
467
+
468
+ printDeletionPreview(deletionPlan);
469
+ output.write(
470
+ "\nClose the selected Codex sessions before continuing. Active-session detection is unavailable.\n",
471
+ );
472
+
473
+ const confirmationToken =
474
+ deletionPlan.ids.length > 1 || deletionPlan.childCount > 0
475
+ ? `DELETE ${deletionPlan.ids.length}`
476
+ : "DELETE";
477
+ const response = await rl.question(
478
+ `\nType "${confirmationToken}" to confirm: `,
479
+ );
480
+
481
+ if (response.trim() !== confirmationToken) {
482
+ output.write("Delete cancelled.\n");
483
+ await pause(rl);
484
+ continue;
485
+ }
486
+
487
+ let cancelRequested = false;
488
+ let canCancel = true;
489
+ let lastMessage = "";
490
+ const handleInterrupt = () => {
491
+ if (canCancel) {
492
+ cancelRequested = true;
493
+ output.write("\nCancellation requested. Finishing the current safe step.\n");
494
+ } else {
495
+ output.write("\nCleanup is already applying changes and will finish safely.\n");
496
+ }
497
+ };
498
+ process.on("SIGINT", handleInterrupt);
499
+ let result;
500
+
501
+ try {
502
+ result = await executeSessionDeletion({
503
+ onProgress: ({ canCancel: nextCanCancel, message }) => {
504
+ canCancel = nextCanCancel;
505
+ if (message !== lastMessage) {
506
+ output.write(`${message}...\n`);
507
+ lastMessage = message;
508
+ }
509
+ },
510
+ plan: deletionPlan,
511
+ shouldCancel: () => cancelRequested,
512
+ store: deletionStore,
513
+ });
514
+ } finally {
515
+ process.off("SIGINT", handleInterrupt);
516
+ }
517
+ const verification = await verifySessionDeletion({
518
+ plan: deletionPlan,
519
+ scope: "deep",
520
+ store: deletionStore,
521
+ });
522
+
523
+ if (verification.complete) {
524
+ output.write(
525
+ `Deleted and verified ${result.deletedIds.length} sessions and ${result.deletedTranscriptPaths.length} transcripts.\n`,
526
+ );
527
+ } else {
528
+ output.write(
529
+ `Cleanup finished, but some selected artifacts remain. Backup: ${result.backupDirectory}\n`,
530
+ );
531
+ }
532
+
533
+ if (result.skippedTranscriptPaths.length > 0) {
534
+ output.write(
535
+ `Skipped ${result.skippedTranscriptPaths.length} missing transcript paths.\n`,
536
+ );
537
+ }
538
+
539
+ state.page = 1;
540
+ } catch (error) {
541
+ output.write(`\n${error instanceof Error ? error.message : String(error)}\n`);
542
+ await pause(rl);
543
+ }
544
+
545
+ continue;
546
+ }
547
+
548
+ output.write(`\nUnknown command: ${command.name}\n`);
549
+ await pause(rl);
550
+ }
551
+ } finally {
552
+ rl.close();
553
+ }
554
+ }
555
+
556
+ export async function runCli(options) {
557
+ if (options.help) {
558
+ output.write(
559
+ "Usage: session-steward-cli [--codex-home <path>] [--json] [--include-internals] [--search <text>] [--sort <updated|created|name|cwd>] [--limit <n>]\n",
560
+ );
561
+ return;
562
+ }
563
+
564
+ if (options.json) {
565
+ await printJson(options);
566
+ return;
567
+ }
568
+
569
+ const state = {
570
+ codexHome: path.resolve(options.codexHome),
571
+ page: 1,
572
+ result: null,
573
+ search: options.search || "",
574
+ showInternals: Boolean(options.includeInternals),
575
+ sort: validateSort(options.sort || "updated"),
576
+ };
577
+
578
+ await runInteractive(state);
579
+ }
@@ -0,0 +1,35 @@
1
+ import {
2
+ assertDeepCleanupSupported,
3
+ diagnoseStorageCompatibility,
4
+ executeSessionDeletion,
5
+ fingerprintSessionDeletion,
6
+ filterAndSortSessions,
7
+ formatSessionForJson,
8
+ getSessionRecord,
9
+ listSessions,
10
+ loadDeletionStore,
11
+ loadSessionStore,
12
+ planSessionDeletion,
13
+ preflightSessionDeletion,
14
+ restoreSessionDeletionBackup,
15
+ verifySessionDeletion,
16
+ } from "./store.mjs";
17
+
18
+ export const codexProvider = Object.freeze({
19
+ id: "codex",
20
+ displayName: "Codex",
21
+ assertDeepCleanupSupported,
22
+ diagnoseStorageCompatibility,
23
+ executeSessionDeletion,
24
+ fingerprintSessionDeletion,
25
+ filterAndSortSessions,
26
+ formatSessionForJson,
27
+ getSessionRecord,
28
+ listSessions,
29
+ loadDeletionStore,
30
+ loadSessionStore,
31
+ planSessionDeletion,
32
+ preflightSessionDeletion,
33
+ restoreSessionDeletionBackup,
34
+ verifySessionDeletion,
35
+ });