@hasna/mementos 0.1.2 → 0.3.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 @@
1
+ /*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */@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-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--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:ui-sans-serif, system-ui, 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-red-500:oklch(63.7% .237 25.331);--color-orange-500:oklch(70.5% .213 47.604);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-teal-400:oklch(77.7% .152 181.912);--color-teal-500:oklch(70.4% .14 182.503);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-7xl:80rem;--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: 1.5 ;--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-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--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%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, 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;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{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]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border)}body{background-color:var(--background);color:var(--foreground);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}}@layer components;@layer utilities{.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.relative{position:relative}.end{inset-inline-end:var(--spacing)}.top-2\.5{top:calc(var(--spacing) * 2.5)}.right-2{right:calc(var(--spacing) * 2)}.right-2\.5{right:calc(var(--spacing) * 2.5)}.left-2{left:calc(var(--spacing) * 2)}.left-2\.5{left:calc(var(--spacing) * 2.5)}.z-10{z-index:10}.z-50{z-index:50}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing) * 1)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.-ml-2{margin-left:calc(var(--spacing) * -2)}.-ml-3{margin-left:calc(var(--spacing) * -3)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.table{display:table}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.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-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.h-2{height:calc(var(--spacing) * 2)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-24{height:calc(var(--spacing) * 24)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-full{height:100%}.h-px{height:1px}.max-h-96{max-height:calc(var(--spacing) * 96)}.min-h-screen{min-height:100vh}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-7{width:calc(var(--spacing) * 7)}.w-9{width:calc(var(--spacing) * 9)}.w-\[130px\]{width:130px}.w-\[140px\]{width:140px}.w-\[150px\]{width:150px}.w-full{width:100%}.w-max{width:max-content}.max-w-7xl{max-width:var(--container-7xl)}.max-w-\[120px\]{max-width:120px}.max-w-\[200px\]{max-width:200px}.max-w-\[250px\]{max-width:250px}.max-w-\[300px\]{max-width:300px}.max-w-max{max-width:max-content}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.min-w-\[8rem\]{min-width:8rem}.min-w-\[200px\]{min-width:200px}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.caption-bottom{caption-side:bottom}.translate-y-1{--tw-translate-y:calc(var(--spacing) * 1);translate:var(--tw-translate-x) var(--tw-translate-y)}.scale-0{--tw-scale-x:0%;--tw-scale-y:0%;--tw-scale-z:0%;scale:var(--tw-scale-x) var(--tw-scale-y)}.scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x) var(--tw-scale-y)}.rotate-0{rotate:none}.rotate-90{rotate:90deg}.animate-in{animation:.2s ease-out enter}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-0>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 0) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 0) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}: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-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)))}: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(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * 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-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.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-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-amber-500\/30{border-color:#f99c004d}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/30{border-color:color-mix(in oklab,var(--color-amber-500) 30%,transparent)}}.border-blue-500\/30{border-color:#3080ff4d}@supports (color:color-mix(in lab,red,red)){.border-blue-500\/30{border-color:color-mix(in oklab,var(--color-blue-500) 30%,transparent)}}.border-border{border-color:var(--border)}.border-gray-500\/30{border-color:#6a72824d}@supports (color:color-mix(in lab,red,red)){.border-gray-500\/30{border-color:color-mix(in oklab,var(--color-gray-500) 30%,transparent)}}.border-green-500\/30{border-color:#00c7584d}@supports (color:color-mix(in lab,red,red)){.border-green-500\/30{border-color:color-mix(in oklab,var(--color-green-500) 30%,transparent)}}.border-input{border-color:var(--input)}.border-purple-500\/30{border-color:#ac4bff4d}@supports (color:color-mix(in lab,red,red)){.border-purple-500\/30{border-color:color-mix(in oklab,var(--color-purple-500) 30%,transparent)}}.border-teal-500\/30{border-color:#00baa74d}@supports (color:color-mix(in lab,red,red)){.border-teal-500\/30{border-color:color-mix(in oklab,var(--color-teal-500) 30%,transparent)}}.border-transparent{border-color:#0000}.border-yellow-500\/30{border-color:#edb2004d}@supports (color:color-mix(in lab,red,red)){.border-yellow-500\/30{border-color:color-mix(in oklab,var(--color-yellow-500) 30%,transparent)}}.border-l-amber-500{border-left-color:var(--color-amber-500)}.bg-amber-500\/5{background-color:#f99c000d}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/5{background-color:color-mix(in oklab,var(--color-amber-500) 5%,transparent)}}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/10{background-color:color-mix(in oklab,var(--color-amber-500) 10%,transparent)}}.bg-amber-500\/15{background-color:#f99c0026}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/15{background-color:color-mix(in oklab,var(--color-amber-500) 15%,transparent)}}.bg-amber-600{background-color:var(--color-amber-600)}.bg-background{background-color:var(--background)}.bg-blue-500\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/10{background-color:color-mix(in oklab,var(--color-blue-500) 10%,transparent)}}.bg-blue-500\/15{background-color:#3080ff26}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/15{background-color:color-mix(in oklab,var(--color-blue-500) 15%,transparent)}}.bg-card{background-color:var(--card)}.bg-destructive{background-color:var(--destructive)}.bg-gray-500\/10{background-color:#6a72821a}@supports (color:color-mix(in lab,red,red)){.bg-gray-500\/10{background-color:color-mix(in oklab,var(--color-gray-500) 10%,transparent)}}.bg-gray-500\/15{background-color:#6a728226}@supports (color:color-mix(in lab,red,red)){.bg-gray-500\/15{background-color:color-mix(in oklab,var(--color-gray-500) 15%,transparent)}}.bg-green-500\/10{background-color:#00c7581a}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/10{background-color:color-mix(in oklab,var(--color-green-500) 10%,transparent)}}.bg-green-500\/15{background-color:#00c75826}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/15{background-color:color-mix(in oklab,var(--color-green-500) 15%,transparent)}}.bg-muted,.bg-muted\/30{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.bg-muted\/30{background-color:color-mix(in oklab,var(--muted) 30%,transparent)}}.bg-muted\/50{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.bg-muted\/50{background-color:color-mix(in oklab,var(--muted) 50%,transparent)}}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-purple-500\/10{background-color:#ac4bff1a}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/10{background-color:color-mix(in oklab,var(--color-purple-500) 10%,transparent)}}.bg-purple-500\/15{background-color:#ac4bff26}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/15{background-color:color-mix(in oklab,var(--color-purple-500) 15%,transparent)}}.bg-secondary{background-color:var(--secondary)}.bg-teal-500\/10{background-color:#00baa71a}@supports (color:color-mix(in lab,red,red)){.bg-teal-500\/10{background-color:color-mix(in oklab,var(--color-teal-500) 10%,transparent)}}.bg-teal-500\/15{background-color:#00baa726}@supports (color:color-mix(in lab,red,red)){.bg-teal-500\/15{background-color:color-mix(in oklab,var(--color-teal-500) 15%,transparent)}}.bg-transparent{background-color:#0000}.bg-yellow-500\/10{background-color:#edb2001a}@supports (color:color-mix(in lab,red,red)){.bg-yellow-500\/10{background-color:color-mix(in oklab,var(--color-yellow-500) 10%,transparent)}}.bg-yellow-500\/15{background-color:#edb20026}@supports (color:color-mix(in lab,red,red)){.bg-yellow-500\/15{background-color:color-mix(in oklab,var(--color-yellow-500) 15%,transparent)}}.p-1{padding:calc(var(--spacing) * 1)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:calc(var(--spacing) * 1)}.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)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-12{padding-block:calc(var(--spacing) * 12)}.pt-0{padding-top:calc(var(--spacing) * 0)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-8{padding-left:calc(var(--spacing) * 8)}.text-center{text-align:center}.text-left{text-align:left}.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))}.leading-none{--tw-leading:1;line-height:1}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.text-amber-400{color:var(--color-amber-400)}.text-amber-500{color:var(--color-amber-500)}.text-blue-400{color:var(--color-blue-400)}.text-blue-500{color:var(--color-blue-500)}.text-card-foreground{color:var(--card-foreground)}.text-foreground{color:var(--foreground)}.text-gray-400{color:var(--color-gray-400)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-muted-foreground,.text-muted-foreground\/50{color:var(--muted-foreground)}@supports (color:color-mix(in lab,red,red)){.text-muted-foreground\/50{color:color-mix(in oklab,var(--muted-foreground) 50%,transparent)}}.text-orange-500{color:var(--color-orange-500)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-purple-400{color:var(--color-purple-400)}.text-purple-500{color:var(--color-purple-500)}.text-red-500{color:var(--color-red-500)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-teal-400{color:var(--color-teal-400)}.text-teal-500{color:var(--color-teal-500)}.text-white{color:var(--color-white)}.text-yellow-400{color:var(--color-yellow-400)}.text-yellow-500{color:var(--color-yellow-500)}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px 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-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px 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-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px 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)}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.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))}.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}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--foreground)}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}@media(hover:hover){.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-amber-700:hover{background-color:var(--color-amber-700)}.hover\:bg-background\/50:hover{background-color:var(--background)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-background\/50:hover{background-color:color-mix(in oklab,var(--background) 50%,transparent)}}.hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab,var(--destructive) 90%,transparent)}}.hover\:bg-muted\/50:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab,var(--muted) 50%,transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--primary) 90%,transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,var(--secondary) 80%,transparent)}}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:bg-accent:focus{background-color:var(--accent)}.focus\:text-accent-foreground:focus{color:var(--accent-foreground)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.data-\[active\]\:bg-accent\/50[data-active]{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.data-\[active\]\:bg-accent\/50[data-active]{background-color:color-mix(in oklab,var(--accent) 50%,transparent)}}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[state\=open\]\:bg-accent\/50[data-state=open]{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.data-\[state\=open\]\:bg-accent\/50[data-state=open]{background-color:color-mix(in oklab,var(--accent) 50%,transparent)}}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--muted)}@media(min-width:40rem){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}}@media(min-width:48rem){.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}@media(prefers-color-scheme:dark){.dark\:scale-0{--tw-scale-x:0%;--tw-scale-y:0%;--tw-scale-z:0%;scale:var(--tw-scale-x) var(--tw-scale-y)}.dark\:scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x) var(--tw-scale-y)}.dark\:-rotate-90{rotate:-90deg}.dark\:rotate-0{rotate:none}.dark\:bg-input\/30{background-color:var(--input)}@supports (color:color-mix(in lab,red,red)){.dark\:bg-input\/30{background-color:color-mix(in oklab,var(--input) 30%,transparent)}}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:calc(var(--spacing) * 0)}.\[\&\>\[role\=checkbox\]\]\:translate-y-\[2px\]>[role=checkbox]{--tw-translate-y:2px;translate:var(--tw-translate-x) var(--tw-translate-y)}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\[\&\>svg\]\:size-4>svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\>svg\]\:shrink-0>svg{flex-shrink:0}.\[\&\>tr\]\:last\:border-b-0>tr:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}@keyframes enter{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes exit{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.95)}}:root{--radius:.625rem;--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(96.5% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(96.5% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(96.5% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(92.1% 0 0);--input:oklch(92.1% 0 0);--ring:oklch(70.8% 0 0)}.dark{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(17.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(17.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(98.5% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(39.6% .141 25.723);--border:oklch(26.9% 0 0);--input:oklch(26.9% 0 0);--ring:oklch(43.9% 0 0)}@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}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@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}
@@ -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>Mementos Dashboard</title>
7
- <script type="module" crossorigin src="/assets/index-C5oRjtKB.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-C8vbNL_5.css">
7
+ <script type="module" crossorigin src="/assets/index-DqyMbv89.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-UBCddFo_.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/dist/cli/index.js CHANGED
@@ -2298,6 +2298,36 @@ var init_types = __esm(() => {
2298
2298
  };
2299
2299
  });
2300
2300
 
2301
+ // src/lib/redact.ts
2302
+ function redactSecrets(text) {
2303
+ let result = text;
2304
+ for (const { pattern } of SECRET_PATTERNS) {
2305
+ pattern.lastIndex = 0;
2306
+ result = result.replace(pattern, REDACTED);
2307
+ }
2308
+ return result;
2309
+ }
2310
+ var REDACTED = "[REDACTED]", SECRET_PATTERNS;
2311
+ var init_redact = __esm(() => {
2312
+ SECRET_PATTERNS = [
2313
+ { name: "openai_key", pattern: /sk-[a-zA-Z0-9_-]{20,}/g },
2314
+ { name: "anthropic_key", pattern: /sk-ant-[a-zA-Z0-9_-]{20,}/g },
2315
+ { name: "generic_key", pattern: /(?:pk|tok|key|token|api[_-]?key)[_-][a-zA-Z0-9_-]{16,}/gi },
2316
+ { name: "aws_key", pattern: /AKIA[A-Z0-9]{16}/g },
2317
+ { name: "aws_secret", pattern: /(?<=AWS_SECRET_ACCESS_KEY\s*=\s*)[A-Za-z0-9/+=]{40}/g },
2318
+ { name: "github_token", pattern: /gh[ps]_[a-zA-Z0-9]{36,}/g },
2319
+ { name: "github_oauth", pattern: /gho_[a-zA-Z0-9]{36,}/g },
2320
+ { name: "npm_token", pattern: /npm_[a-zA-Z0-9]{36,}/g },
2321
+ { name: "bearer", pattern: /Bearer\s+[a-zA-Z0-9_\-.]{20,}/g },
2322
+ { name: "conn_string", pattern: /(?:postgres|postgresql|mysql|mongodb|redis|amqp|mqtt):\/\/[^\s"'`]+@[^\s"'`]+/gi },
2323
+ { name: "env_secret", pattern: /(?:SECRET|TOKEN|PASSWORD|PASSPHRASE|API_KEY|PRIVATE_KEY|AUTH|CREDENTIAL)[_A-Z]*\s*=\s*["']?[^\s"'\n]{8,}["']?/gi },
2324
+ { name: "stripe_key", pattern: /(?:sk|pk|rk)_(?:test|live)_[a-zA-Z0-9]{20,}/g },
2325
+ { name: "slack_token", pattern: /xox[bpras]-[a-zA-Z0-9-]{20,}/g },
2326
+ { name: "jwt", pattern: /eyJ[a-zA-Z0-9_-]{10,}\.eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/g },
2327
+ { name: "hex_secret", pattern: /(?<=(?:key|token|secret|password|hash)\s*[:=]\s*["']?)[0-9a-f]{32,}(?=["']?)/gi }
2328
+ ];
2329
+ });
2330
+
2301
2331
  // src/db/memories.ts
2302
2332
  function parseMemoryRow(row) {
2303
2333
  return {
@@ -2335,6 +2365,8 @@ function createMemory(input, dedupeMode = "merge", db) {
2335
2365
  const tags = input.tags || [];
2336
2366
  const tagsJson = JSON.stringify(tags);
2337
2367
  const metadataJson = JSON.stringify(input.metadata || {});
2368
+ const safeValue = redactSecrets(input.value);
2369
+ const safeSummary = input.summary ? redactSecrets(input.summary) : null;
2338
2370
  if (dedupeMode === "merge") {
2339
2371
  const existing = d.query(`SELECT id, version FROM memories
2340
2372
  WHERE key = ? AND scope = ?
@@ -2348,9 +2380,9 @@ function createMemory(input, dedupeMode = "merge", db) {
2348
2380
  pinned = COALESCE(pinned, 0),
2349
2381
  version = version + 1, updated_at = ?
2350
2382
  WHERE id = ?`, [
2351
- input.value,
2383
+ safeValue,
2352
2384
  input.category || "knowledge",
2353
- input.summary || null,
2385
+ safeSummary,
2354
2386
  tagsJson,
2355
2387
  input.importance ?? 5,
2356
2388
  metadataJson,
@@ -2529,7 +2561,7 @@ function updateMemory(id, input, db) {
2529
2561
  const params = [now()];
2530
2562
  if (input.value !== undefined) {
2531
2563
  sets.push("value = ?");
2532
- params.push(input.value);
2564
+ params.push(redactSecrets(input.value));
2533
2565
  }
2534
2566
  if (input.category !== undefined) {
2535
2567
  sets.push("category = ?");
@@ -2602,6 +2634,7 @@ function cleanExpiredMemories(db) {
2602
2634
  var init_memories = __esm(() => {
2603
2635
  init_types();
2604
2636
  init_database();
2637
+ init_redact();
2605
2638
  });
2606
2639
 
2607
2640
  // src/lib/poll.ts
@@ -2737,7 +2770,7 @@ var {
2737
2770
  init_database();
2738
2771
  init_memories();
2739
2772
  import chalk from "chalk";
2740
- import { readFileSync as readFileSync2 } from "fs";
2773
+ import { readFileSync as readFileSync2, existsSync as existsSync3, accessSync, constants as fsConstants } from "fs";
2741
2774
  import { dirname as dirname3, join as join3, resolve as resolve3 } from "path";
2742
2775
  import { fileURLToPath } from "url";
2743
2776
 
@@ -3048,7 +3081,9 @@ var DEFAULT_CONFIG = {
3048
3081
  sync_agents: ["claude", "codex", "gemini"],
3049
3082
  auto_cleanup: {
3050
3083
  enabled: true,
3051
- expired_check_interval: 3600
3084
+ expired_check_interval: 3600,
3085
+ unused_archive_days: 7,
3086
+ stale_deprioritize_days: 14
3052
3087
  }
3053
3088
  };
3054
3089
  function deepMerge(target, source) {
@@ -3142,12 +3177,187 @@ function archiveStale(staleDays, db) {
3142
3177
  AND COALESCE(accessed_at, created_at) < ?`, [timestamp, cutoff]);
3143
3178
  return result.changes;
3144
3179
  }
3180
+ function archiveUnused(days, db) {
3181
+ const d = db || getDatabase();
3182
+ const timestamp = now();
3183
+ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
3184
+ const result = d.run(`UPDATE memories
3185
+ SET status = 'archived', updated_at = ?
3186
+ WHERE status = 'active'
3187
+ AND pinned = 0
3188
+ AND access_count = 0
3189
+ AND created_at < ?`, [timestamp, cutoff]);
3190
+ return result.changes;
3191
+ }
3192
+ function deprioritizeStale(days, db) {
3193
+ const d = db || getDatabase();
3194
+ const timestamp = now();
3195
+ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
3196
+ const result = d.run(`UPDATE memories
3197
+ SET importance = MAX(importance - 1, 1),
3198
+ version = version + 1,
3199
+ updated_at = ?
3200
+ WHERE status = 'active'
3201
+ AND pinned = 0
3202
+ AND importance > 1
3203
+ AND COALESCE(accessed_at, updated_at) < ?`, [timestamp, cutoff]);
3204
+ return result.changes;
3205
+ }
3145
3206
  function runCleanup(config, db) {
3146
3207
  const d = db || getDatabase();
3147
3208
  const expired = cleanExpiredMemories(d);
3148
3209
  const evicted = enforceQuotas(config, d);
3149
3210
  const archived = archiveStale(90, d);
3150
- return { expired, evicted, archived };
3211
+ const unused_archived = archiveUnused(config.auto_cleanup.unused_archive_days ?? 7, d);
3212
+ const deprioritized = deprioritizeStale(config.auto_cleanup.stale_deprioritize_days ?? 14, d);
3213
+ return { expired, evicted, archived, unused_archived, deprioritized };
3214
+ }
3215
+
3216
+ // src/lib/injector.ts
3217
+ init_memories();
3218
+ class MemoryInjector {
3219
+ config;
3220
+ injectedIds = new Set;
3221
+ constructor(config) {
3222
+ this.config = config || loadConfig();
3223
+ }
3224
+ getInjectionContext(options = {}) {
3225
+ const maxTokens = options.max_tokens || this.config.injection.max_tokens;
3226
+ const minImportance = options.min_importance || this.config.injection.min_importance;
3227
+ const categories = options.categories || this.config.injection.categories;
3228
+ const db = options.db;
3229
+ const allMemories = [];
3230
+ const globalMems = listMemories({
3231
+ scope: "global",
3232
+ category: categories,
3233
+ min_importance: minImportance,
3234
+ status: "active",
3235
+ limit: 100
3236
+ }, db);
3237
+ allMemories.push(...globalMems);
3238
+ if (options.project_id) {
3239
+ const sharedMems = listMemories({
3240
+ scope: "shared",
3241
+ category: categories,
3242
+ min_importance: minImportance,
3243
+ status: "active",
3244
+ project_id: options.project_id,
3245
+ limit: 100
3246
+ }, db);
3247
+ allMemories.push(...sharedMems);
3248
+ }
3249
+ if (options.agent_id) {
3250
+ const privateMems = listMemories({
3251
+ scope: "private",
3252
+ category: categories,
3253
+ min_importance: minImportance,
3254
+ status: "active",
3255
+ agent_id: options.agent_id,
3256
+ limit: 100
3257
+ }, db);
3258
+ allMemories.push(...privateMems);
3259
+ }
3260
+ const seen = new Set;
3261
+ const unique = allMemories.filter((m) => {
3262
+ if (seen.has(m.id))
3263
+ return false;
3264
+ seen.add(m.id);
3265
+ return true;
3266
+ });
3267
+ if (unique.length === 0) {
3268
+ return "";
3269
+ }
3270
+ const totalCharBudget = maxTokens * 4;
3271
+ const footer = "Tip: Use memory_search for deeper lookup on specific topics.";
3272
+ const footerChars = footer.length;
3273
+ const keyBudget = Math.floor((totalCharBudget - footerChars) * 0.67);
3274
+ const recentBudget = Math.floor((totalCharBudget - footerChars) * 0.33);
3275
+ const keyRanked = [...unique].sort((a, b) => {
3276
+ if (a.pinned !== b.pinned)
3277
+ return a.pinned ? -1 : 1;
3278
+ if (b.importance !== a.importance)
3279
+ return b.importance - a.importance;
3280
+ return new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime();
3281
+ });
3282
+ const keyLines = [];
3283
+ const keyIds = new Set;
3284
+ let keyChars = 0;
3285
+ for (const m of keyRanked) {
3286
+ if (this.injectedIds.has(m.id))
3287
+ continue;
3288
+ const line = `- [${m.scope}/${m.category}] ${m.key}: ${m.value}`;
3289
+ if (keyChars + line.length > keyBudget)
3290
+ break;
3291
+ keyLines.push(line);
3292
+ keyIds.add(m.id);
3293
+ keyChars += line.length;
3294
+ }
3295
+ const recentRanked = [...unique].sort((a, b) => {
3296
+ const aTime = a.accessed_at ? new Date(a.accessed_at).getTime() : 0;
3297
+ const bTime = b.accessed_at ? new Date(b.accessed_at).getTime() : 0;
3298
+ return bTime - aTime;
3299
+ });
3300
+ const recentLines = [];
3301
+ let recentChars = 0;
3302
+ const maxRecent = 5;
3303
+ for (const m of recentRanked) {
3304
+ if (recentLines.length >= maxRecent)
3305
+ break;
3306
+ if (keyIds.has(m.id))
3307
+ continue;
3308
+ if (this.injectedIds.has(m.id))
3309
+ continue;
3310
+ const line = `- [${m.scope}/${m.category}] ${m.key}: ${m.value}`;
3311
+ if (recentChars + line.length > recentBudget)
3312
+ break;
3313
+ recentLines.push(line);
3314
+ recentChars += line.length;
3315
+ }
3316
+ if (keyLines.length === 0 && recentLines.length === 0) {
3317
+ return "";
3318
+ }
3319
+ const allInjectedMemoryIds = [
3320
+ ...keyIds,
3321
+ ...recentLines.map((_, i) => {
3322
+ let idx = 0;
3323
+ for (const m of recentRanked) {
3324
+ if (keyIds.has(m.id) || this.injectedIds.has(m.id))
3325
+ continue;
3326
+ if (idx === i)
3327
+ return m.id;
3328
+ idx++;
3329
+ }
3330
+ return "";
3331
+ })
3332
+ ].filter(Boolean);
3333
+ for (const id of allInjectedMemoryIds) {
3334
+ this.injectedIds.add(id);
3335
+ touchMemory(id, db);
3336
+ }
3337
+ const sections = [];
3338
+ if (keyLines.length > 0) {
3339
+ sections.push(`## Key Memories
3340
+ ${keyLines.join(`
3341
+ `)}`);
3342
+ }
3343
+ if (recentLines.length > 0) {
3344
+ sections.push(`## Recent Context
3345
+ ${recentLines.join(`
3346
+ `)}`);
3347
+ }
3348
+ sections.push(footer);
3349
+ return `<agent-memories>
3350
+ ${sections.join(`
3351
+
3352
+ `)}
3353
+ </agent-memories>`;
3354
+ }
3355
+ resetDedup() {
3356
+ this.injectedIds.clear();
3357
+ }
3358
+ getInjectedCount() {
3359
+ return this.injectedIds.size;
3360
+ }
3151
3361
  }
3152
3362
 
3153
3363
  // src/cli/index.tsx
@@ -3254,16 +3464,53 @@ function resolveMemoryId(partialId) {
3254
3464
  return id;
3255
3465
  }
3256
3466
  program2.name("mementos").description("Universal memory system for AI agents").version(getPackageVersion()).option("--project <path>", "Project path for scoping").option("--json", "Output as JSON").option("--agent <name>", "Agent name or ID").option("--session <id>", "Session ID");
3257
- program2.command("save <key> <value>").description("Save a memory (create or upsert)").option("-c, --category <cat>", "Category: preference, fact, knowledge, history").option("-s, --scope <scope>", "Scope: global, shared, private").option("--importance <n>", "Importance 1-10", parseInt).option("--tags <tags>", "Comma-separated tags").option("--summary <text>", "Brief summary").option("--ttl <ms>", "Time-to-live in milliseconds", parseInt).option("--source <src>", "Source: user, agent, system, auto, imported").action((key, value, opts) => {
3467
+ program2.command("save <key> <value>").description("Save a memory (create or upsert)").option("-c, --category <cat>", "Category: preference, fact, knowledge, history").option("-s, --scope <scope>", "Scope: global, shared, private").option("--importance <n>", "Importance 1-10", parseInt).option("--tags <tags>", "Comma-separated tags").option("--summary <text>", "Brief summary").option("--ttl <ms>", "Time-to-live in milliseconds", parseInt).option("--source <src>", "Source: user, agent, system, auto, imported").option("--template <name>", "Apply a template: correction, preference, decision, learning").action((key, value, opts) => {
3258
3468
  try {
3259
3469
  const globalOpts = program2.opts();
3470
+ const templates = {
3471
+ correction: {
3472
+ scope: "shared",
3473
+ category: "knowledge",
3474
+ importance: 9,
3475
+ tags: ["correction"]
3476
+ },
3477
+ preference: {
3478
+ scope: "global",
3479
+ category: "preference",
3480
+ importance: 8,
3481
+ tags: []
3482
+ },
3483
+ decision: {
3484
+ scope: "shared",
3485
+ category: "fact",
3486
+ importance: 8,
3487
+ tags: ["decision"]
3488
+ },
3489
+ learning: {
3490
+ scope: "shared",
3491
+ category: "knowledge",
3492
+ importance: 7,
3493
+ tags: ["learning"]
3494
+ }
3495
+ };
3496
+ let templateDefaults;
3497
+ if (opts.template) {
3498
+ const tpl = templates[opts.template];
3499
+ if (!tpl) {
3500
+ console.error(chalk.red(`Unknown template: ${opts.template}. Valid templates: ${Object.keys(templates).join(", ")}`));
3501
+ process.exit(1);
3502
+ }
3503
+ templateDefaults = tpl;
3504
+ }
3505
+ const explicitTags = opts.tags ? opts.tags.split(",").map((t) => t.trim()) : undefined;
3506
+ const mergedTags = explicitTags ? explicitTags : templateDefaults?.tags && templateDefaults.tags.length > 0 ? templateDefaults.tags : undefined;
3260
3507
  const input = {
3261
3508
  key,
3262
3509
  value,
3263
- category: opts.category,
3264
- scope: opts.scope,
3265
- importance: opts.importance,
3266
- tags: opts.tags ? opts.tags.split(",").map((t) => t.trim()) : undefined,
3510
+ category: opts.category ?? templateDefaults?.category,
3511
+ scope: opts.scope ?? templateDefaults?.scope,
3512
+ importance: opts.importance ?? templateDefaults?.importance,
3513
+ tags: mergedTags,
3267
3514
  summary: opts.summary,
3268
3515
  ttl_ms: opts.ttl,
3269
3516
  source: opts.source,
@@ -3298,20 +3545,38 @@ program2.command("recall <key>").description("Recall a memory by key").option("-
3298
3545
  projectId = project.id;
3299
3546
  }
3300
3547
  const memory = getMemoryByKey(key, opts.scope, agentId, projectId);
3301
- if (!memory) {
3548
+ if (memory) {
3549
+ touchMemory(memory.id);
3302
3550
  if (globalOpts.json) {
3303
- outputJson({ error: `No memory found for key: ${key}` });
3551
+ outputJson(memory);
3304
3552
  } else {
3305
- console.error(chalk.yellow(`No memory found for key: ${key}`));
3553
+ console.log(formatMemoryDetail(memory));
3306
3554
  }
3307
- process.exit(1);
3555
+ return;
3556
+ }
3557
+ const results = searchMemories(key, {
3558
+ scope: opts.scope,
3559
+ agent_id: agentId,
3560
+ project_id: projectId,
3561
+ limit: 1
3562
+ });
3563
+ if (results.length > 0) {
3564
+ const best = results[0];
3565
+ touchMemory(best.memory.id);
3566
+ if (globalOpts.json) {
3567
+ outputJson({ fuzzy_match: true, score: best.score, match_type: best.match_type, memory: best.memory });
3568
+ } else {
3569
+ console.log(chalk.yellow(`No exact match, showing best result (score: ${best.score.toFixed(2)}, match: ${best.match_type}):`));
3570
+ console.log(formatMemoryDetail(best.memory));
3571
+ }
3572
+ return;
3308
3573
  }
3309
- touchMemory(memory.id);
3310
3574
  if (globalOpts.json) {
3311
- outputJson(memory);
3575
+ outputJson({ error: `No memory found for key: ${key}` });
3312
3576
  } else {
3313
- console.log(formatMemoryDetail(memory));
3577
+ console.error(chalk.yellow(`No memory found for key: ${key}`));
3314
3578
  }
3579
+ process.exit(1);
3315
3580
  } catch (e) {
3316
3581
  handleError(e);
3317
3582
  }
@@ -3542,10 +3807,18 @@ program2.command("export").description("Export memories as JSON").option("-s, --
3542
3807
  handleError(e);
3543
3808
  }
3544
3809
  });
3545
- program2.command("import <file>").description("Import memories from a JSON file").option("--overwrite", "Overwrite existing memories (default: merge)").action((file, opts) => {
3810
+ program2.command("import [file]").description("Import memories from a JSON file or stdin (use '-' or pipe data)").option("--overwrite", "Overwrite existing memories (default: merge)").action(async (file, opts) => {
3546
3811
  try {
3547
3812
  const globalOpts = program2.opts();
3548
- const raw = readFileSync2(resolve3(file), "utf-8");
3813
+ let raw;
3814
+ if (file === "-" || !file && !process.stdin.isTTY) {
3815
+ raw = await Bun.stdin.text();
3816
+ } else if (file) {
3817
+ raw = readFileSync2(resolve3(file), "utf-8");
3818
+ } else {
3819
+ console.error(chalk.red("No input: provide a file path, use '-' for stdin, or pipe data."));
3820
+ process.exit(1);
3821
+ }
3549
3822
  const memories = JSON.parse(raw);
3550
3823
  if (!Array.isArray(memories)) {
3551
3824
  throw new Error("JSON file must contain an array of memories");
@@ -3574,9 +3847,11 @@ program2.command("clean").description("Remove expired memories and enforce quota
3574
3847
  outputJson(result);
3575
3848
  } else {
3576
3849
  console.log(chalk.bold("Cleanup complete:"));
3577
- console.log(` Expired removed: ${chalk.red(String(result.expired))}`);
3578
- console.log(` Evicted (quota): ${chalk.yellow(String(result.evicted))}`);
3579
- console.log(` Archived (stale): ${chalk.gray(String(result.archived))}`);
3850
+ console.log(` Expired removed: ${chalk.red(String(result.expired))}`);
3851
+ console.log(` Evicted (quota): ${chalk.yellow(String(result.evicted))}`);
3852
+ console.log(` Archived (stale): ${chalk.gray(String(result.archived))}`);
3853
+ console.log(` Archived (unused): ${chalk.gray(String(result.unused_archived))}`);
3854
+ console.log(` Deprioritized: ${chalk.blue(String(result.deprioritized))}`);
3580
3855
  }
3581
3856
  } catch (e) {
3582
3857
  handleError(e);
@@ -3860,6 +4135,156 @@ program2.command("bulk <action> <ids...>").description("Batch operations: forget
3860
4135
  handleError(e);
3861
4136
  }
3862
4137
  });
4138
+ program2.command("doctor").description("Run health checks on the mementos database").action(() => {
4139
+ const globalOpts = program2.opts();
4140
+ const checks = [];
4141
+ const dbPath = getDbPath();
4142
+ if (existsSync3(dbPath)) {
4143
+ try {
4144
+ accessSync(dbPath, fsConstants.R_OK | fsConstants.W_OK);
4145
+ checks.push({ name: "Database file", status: "ok", detail: dbPath });
4146
+ } catch {
4147
+ checks.push({ name: "Database file", status: "fail", detail: `Not readable/writable: ${dbPath}` });
4148
+ }
4149
+ } else {
4150
+ checks.push({ name: "Database file", status: "fail", detail: `Not found: ${dbPath}` });
4151
+ }
4152
+ try {
4153
+ const db = getDatabase();
4154
+ const migRow = db.query("SELECT MAX(id) as max_id FROM _migrations").get();
4155
+ const schemaVersion = migRow?.max_id ?? 0;
4156
+ checks.push({ name: "Schema version", status: schemaVersion > 0 ? "ok" : "warn", detail: `v${schemaVersion}` });
4157
+ const memCount = db.query("SELECT COUNT(*) as c FROM memories").get().c;
4158
+ const agentCount = db.query("SELECT COUNT(*) as c FROM agents").get().c;
4159
+ const projectCount = db.query("SELECT COUNT(*) as c FROM projects").get().c;
4160
+ checks.push({ name: "Memories", status: "ok", detail: String(memCount) });
4161
+ checks.push({ name: "Agents", status: "ok", detail: String(agentCount) });
4162
+ checks.push({ name: "Projects", status: "ok", detail: String(projectCount) });
4163
+ const orphanedTags = db.query("SELECT COUNT(*) as c FROM memory_tags WHERE memory_id NOT IN (SELECT id FROM memories)").get().c;
4164
+ checks.push({
4165
+ name: "Orphaned tags",
4166
+ status: orphanedTags > 0 ? "warn" : "ok",
4167
+ detail: orphanedTags > 0 ? `${orphanedTags} orphaned tag(s)` : "None"
4168
+ });
4169
+ const expiredCount = db.query("SELECT COUNT(*) as c FROM memories WHERE status != 'expired' AND expires_at IS NOT NULL AND expires_at < datetime('now')").get().c;
4170
+ checks.push({
4171
+ name: "Expired memories",
4172
+ status: expiredCount > 0 ? "warn" : "ok",
4173
+ detail: expiredCount > 0 ? `${expiredCount} expired but not cleaned up (run 'mementos clean')` : "None pending"
4174
+ });
4175
+ } catch (e) {
4176
+ checks.push({ name: "Database connection", status: "fail", detail: e instanceof Error ? e.message : String(e) });
4177
+ }
4178
+ if (globalOpts.json) {
4179
+ outputJson({ checks, healthy: checks.every((c) => c.status === "ok") });
4180
+ } else {
4181
+ console.log(chalk.bold(`
4182
+ Mementos Health Report
4183
+ `));
4184
+ for (const check of checks) {
4185
+ const icon = check.status === "ok" ? chalk.green("\u2713") : check.status === "warn" ? chalk.yellow("!") : chalk.red("\u2717");
4186
+ console.log(` ${icon} ${chalk.bold(check.name)}: ${check.detail}`);
4187
+ }
4188
+ const healthy = checks.every((c) => c.status === "ok");
4189
+ const warnings = checks.filter((c) => c.status === "warn").length;
4190
+ const failures = checks.filter((c) => c.status === "fail").length;
4191
+ console.log("");
4192
+ if (healthy) {
4193
+ console.log(chalk.green(" All checks passed."));
4194
+ } else {
4195
+ if (failures > 0)
4196
+ console.log(chalk.red(` ${failures} check(s) failed.`));
4197
+ if (warnings > 0)
4198
+ console.log(chalk.yellow(` ${warnings} warning(s).`));
4199
+ }
4200
+ console.log("");
4201
+ }
4202
+ });
4203
+ program2.command("show <id>").description("Show full detail of a memory by ID (supports partial IDs)").action((id) => {
4204
+ try {
4205
+ const globalOpts = program2.opts();
4206
+ const resolvedId = resolveMemoryId(id);
4207
+ const memory = getMemory(resolvedId);
4208
+ if (!memory) {
4209
+ if (globalOpts.json) {
4210
+ outputJson({ error: `Memory not found: ${id}` });
4211
+ } else {
4212
+ console.error(chalk.red(`Memory not found: ${id}`));
4213
+ }
4214
+ process.exit(1);
4215
+ }
4216
+ touchMemory(memory.id);
4217
+ if (globalOpts.json) {
4218
+ outputJson(memory);
4219
+ } else {
4220
+ console.log(formatMemoryDetail(memory));
4221
+ }
4222
+ } catch (e) {
4223
+ handleError(e);
4224
+ }
4225
+ });
4226
+ program2.command("history").description("List memories sorted by most recently accessed").option("--limit <n>", "Max results (default: 20)", parseInt).action((opts) => {
4227
+ try {
4228
+ const globalOpts = program2.opts();
4229
+ const limit = opts.limit || 20;
4230
+ const db = getDatabase();
4231
+ const rows = db.query("SELECT * FROM memories WHERE status = 'active' AND accessed_at IS NOT NULL ORDER BY accessed_at DESC LIMIT ?").all(limit);
4232
+ const memories = rows.map(parseMemoryRow);
4233
+ if (globalOpts.json) {
4234
+ outputJson(memories);
4235
+ return;
4236
+ }
4237
+ if (memories.length === 0) {
4238
+ console.log(chalk.yellow("No recently accessed memories."));
4239
+ return;
4240
+ }
4241
+ console.log(chalk.bold(`${memories.length} recently accessed memor${memories.length === 1 ? "y" : "ies"}:`));
4242
+ for (const m of memories) {
4243
+ const id = chalk.dim(m.id.slice(0, 8));
4244
+ const scope = colorScope(m.scope);
4245
+ const cat = colorCategory(m.category);
4246
+ const value = m.value.length > 60 ? m.value.slice(0, 60) + "..." : m.value;
4247
+ const accessed = m.accessed_at ? chalk.dim(m.accessed_at) : chalk.dim("never");
4248
+ console.log(`${id} [${scope}/${cat}] ${chalk.bold(m.key)} = ${value} ${accessed}`);
4249
+ }
4250
+ } catch (e) {
4251
+ handleError(e);
4252
+ }
4253
+ });
4254
+ program2.command("context").description("Output formatted injection context (for piping into agent prompts)").option("--agent <name>", "Agent ID for private memory scope").option("--project <path>", "Project path for shared memory scope").option("--max-tokens <n>", "Token budget for context", parseInt).option("--categories <cats>", "Comma-separated categories: preference, fact, knowledge, history").action((opts) => {
4255
+ try {
4256
+ const globalOpts = program2.opts();
4257
+ const agentId = opts.agent || globalOpts.agent;
4258
+ const projectPath = opts.project || globalOpts.project;
4259
+ let projectId;
4260
+ if (projectPath) {
4261
+ const project = getProject(resolve3(projectPath));
4262
+ if (project)
4263
+ projectId = project.id;
4264
+ }
4265
+ const categories = opts.categories ? opts.categories.split(",").map((c) => c.trim()) : undefined;
4266
+ const injector = new MemoryInjector;
4267
+ const context = injector.getInjectionContext({
4268
+ agent_id: agentId,
4269
+ project_id: projectId,
4270
+ max_tokens: opts.maxTokens,
4271
+ categories
4272
+ });
4273
+ if (globalOpts.json) {
4274
+ outputJson({
4275
+ context,
4276
+ injected_count: injector.getInjectedCount()
4277
+ });
4278
+ } else if (context) {
4279
+ console.log(context);
4280
+ } else {
4281
+ console.error(chalk.yellow("No memories matched the injection criteria."));
4282
+ process.exit(1);
4283
+ }
4284
+ } catch (e) {
4285
+ handleError(e);
4286
+ }
4287
+ });
3863
4288
  program2.command("mcp").description("Install mementos MCP server into Claude Code, Codex, or Gemini").option("--claude", "Install into Claude Code (~/.claude/.mcp.json)").option("--codex", "Install into Codex (~/.codex/config.toml)").option("--gemini", "Install into Gemini (~/.gemini/settings.json)").option("--all", "Install into all supported agents").option("--uninstall", "Remove mementos MCP from config").action((opts) => {
3864
4289
  const { readFileSync: readFileSync3, writeFileSync, existsSync: fileExists } = __require("fs");
3865
4290
  const { join: pathJoin } = __require("path");