xiaozuoassistant 0.1.64 β†’ 0.1.66

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
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.top-0{top:0}.z-10{z-index:10}.z-50{z-index:50}.z-\[60\]{z-index:60}.-m-6{margin:-1.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.h-16{height:4rem}.h-2{height:.5rem}.h-4{height:1rem}.h-8{height:2rem}.h-\[60vh\]{height:60vh}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[200px\]{max-height:200px}.max-h-\[70vh\]{max-height:70vh}.max-h-\[90vh\]{max-height:90vh}.min-h-\[100px\]{min-height:100px}.min-h-\[300px\]{min-height:300px}.min-h-\[50px\]{min-height:50px}.w-16{width:4rem}.w-28{width:7rem}.w-4{width:1rem}.w-8{width:2rem}.w-\[260px\]{width:260px}.w-full{width:100%}.w-screen{width:100vw}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-\[46vw\]{max-width:46vw}.max-w-\[85\%\]{max-width:85%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-bl-none{border-bottom-left-radius:0}.rounded-br-none{border-bottom-right-radius:0}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-black\/10{border-color:#0000001a}.border-blue-100{--tw-border-opacity: 1;border-color:rgb(219 234 254 / var(--tw-border-opacity, 1))}.border-blue-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-gray-700{--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.border-gray-800{--tw-border-opacity: 1;border-color:rgb(31 41 55 / var(--tw-border-opacity, 1))}.border-green-200{--tw-border-opacity: 1;border-color:rgb(187 247 208 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.bg-black\/20{background-color:#0003}.bg-black\/40{background-color:#0006}.bg-black\/50{background-color:#00000080}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-gray-800{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-teal-600{--tw-bg-opacity: 1;background-color:rgb(13 148 136 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/80{background-color:#fffc}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity, 1))}.fill-current{fill:currentColor}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-20{padding-top:5rem;padding-bottom:5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-2{padding-bottom:.5rem}.pt-2{padding-top:.5rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[15px\]{font-size:15px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.text-yellow-800{--tw-text-opacity: 1;color:rgb(133 77 14 / var(--tw-text-opacity, 1))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.accent-blue-600{accent-color:#2563eb}.opacity-0{opacity:0}.opacity-50{opacity:.5}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur: blur(12px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;line-height:1.5;font-weight:400;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.custom-scrollbar::-webkit-scrollbar{width:5px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background:#9b9b9b33;border-radius:10px}.custom-scrollbar::-webkit-scrollbar-thumb:hover{background:#9b9b9b66}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.selection\:bg-blue-100 *::-moz-selection{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.selection\:bg-blue-100 *::selection{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.selection\:text-blue-900 *::-moz-selection{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity, 1))}.selection\:text-blue-900 *::selection{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity, 1))}.selection\:bg-blue-100::-moz-selection{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.selection\:bg-blue-100::selection{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.selection\:text-blue-900::-moz-selection{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity, 1))}.selection\:text-blue-900::selection{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity, 1))}.placeholder\:text-gray-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.placeholder\:text-gray-400::placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.focus-within\:border-blue-400:focus-within{--tw-border-opacity: 1;border-color:rgb(96 165 250 / var(--tw-border-opacity, 1))}.focus-within\:ring-2:focus-within{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-within\:ring-blue-100:focus-within{--tw-ring-opacity: 1;--tw-ring-color: rgb(219 234 254 / var(--tw-ring-opacity, 1))}.hover\:bg-blue-50:hover{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-700:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-800:hover{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-800\/50:hover{background-color:#1f293780}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:bg-teal-700:hover{--tw-bg-opacity: 1;background-color:rgb(15 118 110 / var(--tw-bg-opacity, 1))}.hover\:text-blue-300:hover{--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.hover\:text-blue-700:hover{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-gray-800:hover{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.hover\:text-red-600:hover{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:shadow-sm:hover{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-0:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-70:disabled{opacity:.7}.group:hover .group-hover\:rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:border-gray-600{--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.group:hover .group-hover\:text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.group:hover .group-hover\:opacity-100{opacity:1}
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>πŸ‡</text></svg>" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>xiaozuoAssistant</title>
8
- <script type="module" crossorigin src="/assets/index-AWTkboCU.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-OCMDYWfd.css">
8
+ <script type="module" crossorigin src="/assets/index-o23m3BxJ.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-zJd3h_35.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
@@ -122,6 +122,60 @@ export class Brain {
122
122
  return '';
123
123
  }
124
124
  }
125
+ async extractKeyInformation(content, contextType) {
126
+ try {
127
+ const prompt = contextType === 'project'
128
+ ? 'Extract key project-related information, decisions, and tasks from the following conversation. Return a concise summary.'
129
+ : 'Extract key information, insights, and valuable knowledge from the following conversation. Return a concise summary suitable for long-term memory.';
130
+ const response = await this.openai.chat.completions.create({
131
+ model: config.llm.model,
132
+ messages: [
133
+ { role: 'system', content: prompt },
134
+ { role: 'user', content: content }
135
+ ],
136
+ temperature: 0.3
137
+ }, { timeout: config.llm.requestTimeoutMs ?? 600000 });
138
+ return response.choices[0].message.content || '';
139
+ }
140
+ catch (e) {
141
+ console.error('Key information extraction failed:', e);
142
+ return '';
143
+ }
144
+ }
145
+ async extractNotebookNotes(content, keywords) {
146
+ try {
147
+ const prompt = keywords
148
+ ? `You are a note-taker. Extract notes relevant to the following keywords: "${keywords}".`
149
+ : `You are a note-taker. Extract important notes, knowledge points, code snippets, or actionable items from the conversation.`;
150
+ const response = await this.openai.chat.completions.create({
151
+ model: config.llm.model,
152
+ messages: [
153
+ { role: 'system', content: `${prompt}
154
+ Return a JSON array of objects with "title" and "content" fields. If no relevant info, return empty array [].
155
+ Format: [{"title": "...", "content": "..."}]` },
156
+ { role: 'user', content: content }
157
+ ],
158
+ temperature: 0.3,
159
+ response_format: { type: 'json_object' }
160
+ }, { timeout: config.llm.requestTimeoutMs ?? 600000 });
161
+ const jsonStr = response.choices[0].message.content || '{"notes": []}';
162
+ try {
163
+ const parsed = JSON.parse(jsonStr);
164
+ if (Array.isArray(parsed))
165
+ return parsed;
166
+ if (parsed.notes && Array.isArray(parsed.notes))
167
+ return parsed.notes;
168
+ return [];
169
+ }
170
+ catch {
171
+ return [];
172
+ }
173
+ }
174
+ catch (e) {
175
+ console.error('Notebook note extraction failed:', e);
176
+ return [];
177
+ }
178
+ }
125
179
  async callLLM(messages) {
126
180
  const tools = skillRegistry.getToolsDefinition();
127
181
  // OpenAI SDK expects tools to be undefined if empty array, or valid tools array
@@ -105,6 +105,82 @@ ${recentMessages}
105
105
  this.structured.updateUserProfile(uid, key, value);
106
106
  }
107
107
  }
108
+ async runSessionArchiving() {
109
+ console.log('[MemoryManager] Running session archiving...');
110
+ const sessions = await this.listSessions();
111
+ const now = Date.now();
112
+ for (const session of sessions) {
113
+ try {
114
+ // Check if session has new activity since last archive
115
+ const lastArchived = session.lastArchivedAt || 0;
116
+ const lastActive = session.lastActiveAt || session.updatedAt || 0;
117
+ // If no new activity, skip
118
+ if (lastActive <= lastArchived)
119
+ continue;
120
+ // If less than 3 minutes since last archive, skip (though scheduler runs every 3 mins, so this check is redundant but safe)
121
+ // Actually, we want to archive if there is new content.
122
+ console.log(`[MemoryManager] Archiving session ${session.id} (Alias: ${session.alias || 'N/A'})...`);
123
+ const messages = await this.getHistory(session.id);
124
+ // Filter messages after lastArchived
125
+ const newMessages = messages.filter(m => (m.timestamp || 0) > lastArchived);
126
+ if (newMessages.length === 0) {
127
+ // Update lastArchivedAt to now to avoid re-checking empty interval
128
+ await this.updateSessionMeta(session.id, { lastArchivedAt: now });
129
+ continue;
130
+ }
131
+ const content = newMessages.map(m => `${m.role}: ${m.content}`).join('\n');
132
+ // 1. Memory Archiving (Project or General)
133
+ const projectIds = session.projectIds || (session.projectId ? [session.projectId] : []);
134
+ if (projectIds.length > 0) {
135
+ // Project Context
136
+ const projectInfo = await brain.extractKeyInformation(content, 'project');
137
+ if (projectInfo) {
138
+ for (const pid of projectIds) {
139
+ await this.vector.addMemory(projectInfo, 'project_archive', {
140
+ sessionId: session.id,
141
+ projectId: pid,
142
+ archivedAt: now
143
+ });
144
+ console.log(`[MemoryManager] Archived project info for Project ${pid}`);
145
+ }
146
+ }
147
+ }
148
+ else {
149
+ // General Context (No Project)
150
+ const generalInfo = await brain.extractKeyInformation(content, 'general');
151
+ if (generalInfo) {
152
+ await this.vector.addMemory(generalInfo, 'long_term', {
153
+ sessionId: session.id,
154
+ archivedAt: now,
155
+ source: 'auto_archive'
156
+ });
157
+ console.log(`[MemoryManager] Archived general info for Session ${session.id}`);
158
+ }
159
+ }
160
+ // 2. Notebook Memory Archiving
161
+ if (session.notebookId) {
162
+ const notebook = this.structured.getNotebook(session.notebookId);
163
+ if (notebook) {
164
+ // Extract notes regardless of keywords (Brain handles fallback)
165
+ const notes = await brain.extractNotebookNotes(content, notebook.keywords);
166
+ if (notes && notes.length > 0) {
167
+ for (const note of notes) {
168
+ if (!note.title || !note.content)
169
+ continue;
170
+ this.structured.createNote(require('uuid').v4(), session.notebookId, note.title, note.content);
171
+ console.log(`[MemoryManager] Created note "${note.title}" in Notebook ${notebook.name}`);
172
+ }
173
+ }
174
+ }
175
+ }
176
+ // Update lastArchivedAt
177
+ await this.updateSessionMeta(session.id, { lastArchivedAt: now });
178
+ }
179
+ catch (e) {
180
+ console.error(`[MemoryManager] Failed to archive session ${session.id}:`, e);
181
+ }
182
+ }
183
+ }
108
184
  // --- Maintenance ---
109
185
  // Managed by Scheduler
110
186
  async runMaintenance(input) {
@@ -112,6 +188,8 @@ ${recentMessages}
112
188
  const vectorMaxAgeDays = input?.vectorMaxAgeDays ?? 15;
113
189
  console.log(`[MemoryManager] Running maintenance (Sessions: ${sessionMaxAgeDays} days, Vector: ${vectorMaxAgeDays} days)...`);
114
190
  try {
191
+ // 0. Auto-archive active sessions
192
+ await this.runSessionArchiving();
115
193
  // 1. Clean up old sessions
116
194
  const deletedSessions = await this.shortTerm.cleanupOldSessions(sessionMaxAgeDays);
117
195
  if (deletedSessions > 0) {
@@ -128,7 +128,9 @@ export class ShortTermMemory {
128
128
  updatedAt: now,
129
129
  lastActiveAt: now,
130
130
  projectId: input?.projectId,
131
+ projectIds: input?.projectIds,
131
132
  notebookId: input?.notebookId,
133
+ lastArchivedAt: now,
132
134
  };
133
135
  await fs.ensureDir(meta.workspace);
134
136
  const sessionDir = this.getSessionDir(id);
@@ -168,7 +170,9 @@ export class ShortTermMemory {
168
170
  alias: patch.alias === null ? undefined : (patch.alias !== undefined ? (String(patch.alias).trim() || undefined) : current.alias),
169
171
  workspace: patch.workspace !== undefined ? normalizeWorkspace(String(patch.workspace)) : current.workspace,
170
172
  projectId: patch.projectId === null ? undefined : (patch.projectId !== undefined ? patch.projectId : current.projectId),
173
+ projectIds: patch.projectIds === null ? undefined : (patch.projectIds !== undefined ? patch.projectIds : current.projectIds),
171
174
  notebookId: patch.notebookId === null ? undefined : (patch.notebookId !== undefined ? patch.notebookId : current.notebookId),
175
+ lastArchivedAt: patch.lastArchivedAt !== undefined ? patch.lastArchivedAt : current.lastArchivedAt,
172
176
  updatedAt: Date.now()
173
177
  };
174
178
  await fs.ensureDir(next.workspace);
@@ -81,6 +81,7 @@ export class StructuredMemory {
81
81
  id TEXT PRIMARY KEY,
82
82
  name TEXT NOT NULL,
83
83
  description TEXT,
84
+ keywords TEXT,
84
85
  created_at INTEGER,
85
86
  updated_at INTEGER
86
87
  )
@@ -263,12 +264,12 @@ export class StructuredMemory {
263
264
  }));
264
265
  }
265
266
  // --- Notebooks ---
266
- createNotebook(id, name, description) {
267
+ createNotebook(id, name, description, keywords) {
267
268
  const now = Date.now();
268
269
  this.db.prepare(`
269
- INSERT INTO notebooks (id, name, description, created_at, updated_at)
270
- VALUES (?, ?, ?, ?, ?)
271
- `).run(id, name, description || null, now, now);
270
+ INSERT INTO notebooks (id, name, description, keywords, created_at, updated_at)
271
+ VALUES (?, ?, ?, ?, ?, ?)
272
+ `).run(id, name, description || null, keywords || null, now, now);
272
273
  }
273
274
  getNotebook(id) {
274
275
  const row = this.db.prepare('SELECT * FROM notebooks WHERE id = ?').get(id);
@@ -278,6 +279,7 @@ export class StructuredMemory {
278
279
  id: row.id,
279
280
  name: row.name,
280
281
  description: row.description,
282
+ keywords: row.keywords,
281
283
  createdAt: row.created_at,
282
284
  updatedAt: row.updated_at
283
285
  };
@@ -289,9 +291,9 @@ export class StructuredMemory {
289
291
  const next = { ...current, ...patch };
290
292
  const now = Date.now();
291
293
  this.db.prepare(`
292
- UPDATE notebooks SET name = ?, description = ?, updated_at = ?
294
+ UPDATE notebooks SET name = ?, description = ?, keywords = ?, updated_at = ?
293
295
  WHERE id = ?
294
- `).run(next.name, next.description || null, now, id);
296
+ `).run(next.name, next.description || null, next.keywords || null, now, id);
295
297
  }
296
298
  deleteNotebook(id) {
297
299
  this.db.prepare('DELETE FROM notebooks WHERE id = ?').run(id);
@@ -302,6 +304,7 @@ export class StructuredMemory {
302
304
  id: row.id,
303
305
  name: row.name,
304
306
  description: row.description,
307
+ keywords: row.keywords,
305
308
  createdAt: row.created_at,
306
309
  updatedAt: row.updated_at
307
310
  }));
@@ -82,7 +82,7 @@ export class VectorMemory {
82
82
  text,
83
83
  vector,
84
84
  metadata: {
85
- type,
85
+ type: type,
86
86
  timestamp: Date.now(),
87
87
  ...metadata
88
88
  }
@@ -18,6 +18,10 @@ export const initScheduler = () => {
18
18
  const sessionMaxAgeDays = config.scheduler?.sessionRetentionDays ?? 5;
19
19
  memoryManager.runMaintenance({ sessionMaxAgeDays, vectorMaxAgeDays: 15 });
20
20
  });
21
+ // Archive session memories every 3 minutes
22
+ cron.schedule('*/3 * * * *', () => {
23
+ memoryManager.runSessionArchiving();
24
+ });
21
25
  };
22
26
  export const runMaintenanceNow = () => {
23
27
  console.log('[Scheduler] Manually triggering maintenance...');
@@ -140,8 +140,15 @@ app.post('/api/sessions/:id/messages', async (req, res) => {
140
140
  // ζ›΄ζ–°δΌšθ―ε…ƒδΏ‘ζ―
141
141
  app.patch('/api/sessions/:id', async (req, res) => {
142
142
  try {
143
- const { alias, workspace, context, projectId, notebookId } = req.body || {};
144
- const meta = await memory.updateSessionMeta(req.params.id, { alias, workspace, context, projectId: projectId || null, notebookId: notebookId || null });
143
+ const { alias, workspace, context, projectId, projectIds, notebookId } = req.body || {};
144
+ const meta = await memory.updateSessionMeta(req.params.id, {
145
+ alias,
146
+ workspace,
147
+ context,
148
+ projectId: projectId || null,
149
+ projectIds: projectIds || null,
150
+ notebookId: notebookId || null
151
+ });
145
152
  res.json(meta);
146
153
  }
147
154
  catch (e) {
@@ -378,12 +385,12 @@ app.get('/api/notebooks', async (req, res) => {
378
385
  });
379
386
  app.post('/api/notebooks', async (req, res) => {
380
387
  try {
381
- const { id, name, description } = req.body;
388
+ const { id, name, description, keywords } = req.body;
382
389
  if (!id || !name) {
383
390
  res.status(400).json({ error: 'id and name are required' });
384
391
  return;
385
392
  }
386
- memory.structured.createNotebook(id, name, description);
393
+ memory.structured.createNotebook(id, name, description, keywords);
387
394
  const item = memory.structured.getNotebook(id);
388
395
  res.json(item);
389
396
  }
@@ -393,8 +400,8 @@ app.post('/api/notebooks', async (req, res) => {
393
400
  });
394
401
  app.patch('/api/notebooks/:id', async (req, res) => {
395
402
  try {
396
- const { name, description } = req.body;
397
- memory.structured.updateNotebook(req.params.id, { name, description });
403
+ const { name, description, keywords } = req.body;
404
+ memory.structured.updateNotebook(req.params.id, { name, description, keywords });
398
405
  const item = memory.structured.getNotebook(req.params.id);
399
406
  res.json(item);
400
407
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "xiaozuoassistant",
3
3
  "private": false,
4
4
  "description": "Your personal, locally-hosted AI assistant for office productivity.",
5
- "version": "0.1.64",
5
+ "version": "0.1.66",
6
6
  "author": "mantle.lau",
7
7
  "license": "MIT",
8
8
  "repository": {