@hasna/conversations 0.1.18 → 0.1.20

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.1.18 | 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-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight: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;--tw-duration:initial}}}@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-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-500:oklch(63.7% .237 25.331);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-orange-800:oklch(47% .157 37.304);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-950:oklch(27.9% .077 45.635);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-green-900:oklch(39.3% .095 152.535);--color-green-950:oklch(26.6% .065 152.934);--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-blue-600:oklch(54.6% .245 262.881);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-950:oklch(25.7% .09 281.288);--color-purple-500:oklch(62.7% .265 303.9);--color-pink-500:oklch(65.6% .241 354.308);--color-rose-500:oklch(64.5% .246 16.439);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-900:oklch(20.8% .042 265.755);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-md:28rem;--container-lg:32rem;--container-6xl:72rem;--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-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-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{.pointer-events-none{pointer-events:none}.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}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.inset-y-0{inset-block:calc(var(--spacing)*0)}.top-2\.5{top:calc(var(--spacing)*2.5)}.top-4{top:calc(var(--spacing)*4)}.top-\[50\%\]{top:50%}.right-0{right:calc(var(--spacing)*0)}.right-4{right:calc(var(--spacing)*4)}.right-6{right:calc(var(--spacing)*6)}.bottom-6{bottom:calc(var(--spacing)*6)}.left-2{left:calc(var(--spacing)*2)}.left-3{left:calc(var(--spacing)*3)}.left-\[50\%\]{left:50%}.z-40{z-index:40}.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)}.my-2{margin-block:calc(var(--spacing)*2)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-4{margin-top:calc(var(--spacing)*4)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.table{display:table}.size-1\.5{width:calc(var(--spacing)*1.5);height:calc(var(--spacing)*1.5)}.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-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-8{width:calc(var(--spacing)*8);height:calc(var(--spacing)*8)}.size-9{width:calc(var(--spacing)*9);height:calc(var(--spacing)*9)}.size-10{width:calc(var(--spacing)*10);height:calc(var(--spacing)*10)}.h-5{height:calc(var(--spacing)*5)}.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-14{height:calc(var(--spacing)*14)}.h-px{height:1px}.min-h-screen{min-height:100vh}.w-10{width:calc(var(--spacing)*10)}.w-96{width:calc(var(--spacing)*96)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[calc\(100\%-2rem\)\]{max-width:calc(100% - 2rem)}.max-w-md{max-width:var(--container-md)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\[1\.25rem\]{min-width:1.25rem}.min-w-\[8rem\]{min-width:8rem}.flex-1{flex:1}.shrink-0{flex-shrink:0}.caption-bottom{caption-side:bottom}.translate-x-\[-50\%\]{--tw-translate-x:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\[-50\%\]{--tw-translate-y:-50%;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-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.auto-rows-min{grid-auto-rows:min-content}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-rows-\[auto_auto\]{grid-template-rows:auto auto}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.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)}.gap-6{gap:calc(var(--spacing)*6)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*.5)*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)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px*var(--tw-divide-y-reverse));border-bottom-width:calc(1px*calc(1 - var(--tw-divide-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y: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-0{border-style:var(--tw-border-style);border-width:0}.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{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-amber-300{border-color:var(--color-amber-300)}.border-border{border-color:var(--border)}.border-green-200{border-color:var(--color-green-200)}.border-green-300{border-color:var(--color-green-300)}.border-input{border-color:var(--input)}.border-muted{border-color:var(--muted)}.border-muted-foreground\/30{border-color:var(--muted-foreground)}@supports (color:color-mix(in lab,red,red)){.border-muted-foreground\/30{border-color:color-mix(in oklab,var(--muted-foreground)30%,transparent)}}.border-orange-300{border-color:var(--color-orange-300)}.border-red-200{border-color:var(--color-red-200)}.border-transparent{border-color:#0000}.bg-amber-100{background-color:var(--color-amber-100)}.bg-background{background-color:var(--background)}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-destructive{background-color:var(--destructive)}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-500{background-color:var(--color-green-500)}.bg-indigo-100{background-color:var(--color-indigo-100)}.bg-indigo-500{background-color:var(--color-indigo-500)}.bg-muted{background-color:var(--muted)}.bg-muted-foreground\/50{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab,red,red)){.bg-muted-foreground\/50{background-color:color-mix(in oklab,var(--muted-foreground)50%,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-orange-500{background-color:var(--color-orange-500)}.bg-pink-500{background-color:var(--color-pink-500)}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-purple-500{background-color:var(--color-purple-500)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-500{background-color:var(--color-red-500)}.bg-rose-500{background-color:var(--color-rose-500)}.bg-secondary{background-color:var(--secondary)}.bg-slate-100{background-color:var(--color-slate-100)}.bg-teal-500{background-color:var(--color-teal-500)}.bg-transparent{background-color:#0000}.p-1{padding:calc(var(--spacing)*1)}.p-2{padding:calc(var(--spacing)*2)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.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-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-6{padding-block:calc(var(--spacing)*6)}.py-8{padding-block:calc(var(--spacing)*8)}.pt-2{padding-top:calc(var(--spacing)*2)}.pr-2{padding-right:calc(var(--spacing)*2)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-4{padding-left:calc(var(--spacing)*4)}.pl-8{padding-left:calc(var(--spacing)*8)}.pl-9{padding-left:calc(var(--spacing)*9)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--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-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)}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.text-amber-700{color:var(--color-amber-700)}.text-blue-600{color:var(--color-blue-600)}.text-card-foreground{color:var(--card-foreground)}.text-destructive{color:var(--destructive)}.text-foreground{color:var(--foreground)}.text-green-700{color:var(--color-green-700)}.text-green-800{color:var(--color-green-800)}.text-indigo-700{color:var(--color-indigo-700)}.text-muted-foreground{color:var(--muted-foreground)}.text-orange-600{color:var(--color-orange-600)}.text-orange-700{color:var(--color-orange-700)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-slate-600{color:var(--color-slate-600)}.text-white{color:var(--color-white)}.italic{font-style:italic}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-70{opacity:.7}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-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-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)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);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-hidden{--tw-outline-style:none;outline-style:none}@media(forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-\[color\,box-shadow\]{transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.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))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media(hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}.last\:mb-0:last-child{margin-bottom:calc(var(--spacing)*0)}@media(hover:hover){.hover\:border-foreground\/20:hover{border-color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.hover\:border-foreground\/20:hover{border-color:color-mix(in oklab,var(--foreground)20%,transparent)}}.hover\:bg-accent:hover{background-color:var(--accent)}.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:hover,.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}.hover\:opacity-80:hover{opacity:.8}.hover\:opacity-100:hover{opacity:1}}.focus\:bg-accent:focus{background-color:var(--accent)}.focus\:text-accent-foreground:focus{color:var(--accent-foreground)}.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-hidden:focus{--tw-outline-style:none;outline-style:none}@media(forced-colors:active){.focus\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:ring-\[3px\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(3px + 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-destructive\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab,var(--ring)50%,transparent)}}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.has-\[\>svg\]\:px-2\.5:has(>svg){padding-inline:calc(var(--spacing)*2.5)}.has-\[\>svg\]\:px-3:has(>svg){padding-inline:calc(var(--spacing)*3)}.has-\[\>svg\]\:px-4:has(>svg){padding-inline:calc(var(--spacing)*4)}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[inset\]\:pl-8[data-inset]{padding-left:calc(var(--spacing)*8)}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation:.15s ease-in exit}.data-\[state\=open\]\:animate-in[data-state=open]{animation:.2s ease-out enter}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--muted)}@media(min-width:40rem){.sm\:max-w-lg{max-width:var(--container-lg)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}.sm\:text-left{text-align:left}}@media(min-width:48rem){.md\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}@media(min-width:64rem){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@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\:border-amber-800{border-color:var(--color-amber-800)}.dark\:border-green-800{border-color:var(--color-green-800)}.dark\:border-green-900{border-color:var(--color-green-900)}.dark\:border-input{border-color:var(--input)}.dark\:border-orange-800{border-color:var(--color-orange-800)}.dark\:border-red-900{border-color:var(--color-red-900)}.dark\:bg-amber-950{background-color:var(--color-amber-950)}.dark\:bg-destructive\/60{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\:bg-destructive\/60{background-color:color-mix(in oklab,var(--destructive)60%,transparent)}}.dark\:bg-green-950{background-color:var(--color-green-950)}.dark\:bg-indigo-950{background-color:var(--color-indigo-950)}.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)}}.dark\:bg-red-950{background-color:var(--color-red-950)}.dark\:bg-slate-900{background-color:var(--color-slate-900)}.dark\:text-amber-300{color:var(--color-amber-300)}.dark\:text-amber-400{color:var(--color-amber-400)}.dark\:text-blue-400{color:var(--color-blue-400)}.dark\:text-green-200{color:var(--color-green-200)}.dark\:text-green-300{color:var(--color-green-300)}.dark\:text-green-400{color:var(--color-green-400)}.dark\:text-indigo-300{color:var(--color-indigo-300)}.dark\:text-orange-400{color:var(--color-orange-400)}.dark\:text-red-200{color:var(--color-red-200)}.dark\:text-red-300{color:var(--color-red-300)}.dark\:text-slate-400{color:var(--color-slate-400)}@media(hover:hover){.dark\:hover\:bg-accent\/50:hover{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-accent\/50:hover{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.dark\:hover\:bg-input\/50:hover{background-color:var(--input)}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-input\/50:hover{background-color:color-mix(in oklab,var(--input)50%,transparent)}}}.dark\:focus-visible\:ring-destructive\/40:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\:focus-visible\:ring-destructive\/40:focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\[\&_svg\:not\(\[class\*\=\'text-\'\]\)\]\:text-muted-foreground svg:not([class*=text-]){color:var(--muted-foreground)}.\[\&_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)}.\[\&\>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-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-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}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}
@@ -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>Hasna Conversations</title>
7
- <script type="module" crossorigin src="/assets/index-CCdh63JU.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-VFT0_0LI.css">
7
+ <script type="module" crossorigin src="/assets/index-Bw0wMcXE.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-CF_GDtNp.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * Or use the interactive TUI:
10
10
  * conversations
11
11
  */
12
- export { sendMessage, readMessages, markRead, markSessionRead, markSpaceRead, markAllRead, getMessageById, searchMessages, exportMessages, deleteMessage, editMessage, pinMessage, unpinMessage, getPinnedMessages, getUnreadBlockers, } from "./lib/messages.js";
12
+ export { sendMessage, readMessages, markRead, markSessionRead, markSpaceRead, markAllRead, getMessageById, searchMessages, exportMessages, deleteMessage, editMessage, pinMessage, unpinMessage, getPinnedMessages, getUnreadBlockers, getThreadReplies, } from "./lib/messages.js";
13
13
  export { listSessions, getSession, } from "./lib/sessions.js";
14
14
  export { createSpace, updateSpace, archiveSpace, unarchiveSpace, listSpaces, getSpace, joinSpace, leaveSpace, getSpaceMembers, isSpaceMember, getSpaceDepth, } from "./lib/spaces.js";
15
15
  export { createProject, listProjects, getProject, getProjectByName, updateProject, deleteProject, } from "./lib/projects.js";
@@ -17,5 +17,6 @@ export { getDb, getDbPath, closeDb, } from "./lib/db.js";
17
17
  export { startPolling, useSpaceMessages, } from "./lib/poll.js";
18
18
  export { resolveIdentity, requireIdentity, } from "./lib/identity.js";
19
19
  export { addReaction, removeReaction, getReactions, getReactionSummary, } from "./lib/reactions.js";
20
+ export { fireWebhooks, } from "./lib/webhooks.js";
20
21
  export { heartbeat, getPresence, listAgents, removePresence, renameAgent, } from "./lib/presence.js";
21
22
  export type { Message, Session, Space, SpaceInfo, SpaceMember, Project, ProjectInfo, Priority, SendMessageOptions, ReadMessagesOptions, SearchMessagesOptions, AgentPresence, Reaction, Attachment, } from "./types.js";
package/dist/index.js CHANGED
@@ -204,6 +204,43 @@ function getDb() {
204
204
  if (!colNames2.includes("attachments")) {
205
205
  db.exec("ALTER TABLE messages ADD COLUMN attachments TEXT");
206
206
  }
207
+ if (!colNames2.includes("reply_to")) {
208
+ db.exec("ALTER TABLE messages ADD COLUMN reply_to INTEGER REFERENCES messages(id)");
209
+ db.exec("CREATE INDEX IF NOT EXISTS idx_messages_reply_to ON messages(reply_to)");
210
+ }
211
+ const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='messages_fts'").get();
212
+ if (!ftsExists) {
213
+ db.exec(`
214
+ CREATE VIRTUAL TABLE messages_fts USING fts5(
215
+ content, from_agent, to_agent, space,
216
+ content_rowid='id', content='messages'
217
+ )
218
+ `);
219
+ db.exec(`
220
+ INSERT INTO messages_fts(rowid, content, from_agent, to_agent, space)
221
+ SELECT id, content, from_agent, to_agent, space FROM messages
222
+ `);
223
+ db.exec(`
224
+ CREATE TRIGGER IF NOT EXISTS messages_fts_insert AFTER INSERT ON messages BEGIN
225
+ INSERT INTO messages_fts(rowid, content, from_agent, to_agent, space)
226
+ VALUES (new.id, new.content, new.from_agent, new.to_agent, new.space);
227
+ END
228
+ `);
229
+ db.exec(`
230
+ CREATE TRIGGER IF NOT EXISTS messages_fts_delete AFTER DELETE ON messages BEGIN
231
+ INSERT INTO messages_fts(messages_fts, rowid, content, from_agent, to_agent, space)
232
+ VALUES ('delete', old.id, old.content, old.from_agent, old.to_agent, old.space);
233
+ END
234
+ `);
235
+ db.exec(`
236
+ CREATE TRIGGER IF NOT EXISTS messages_fts_update AFTER UPDATE OF content ON messages BEGIN
237
+ INSERT INTO messages_fts(messages_fts, rowid, content, from_agent, to_agent, space)
238
+ VALUES ('delete', old.id, old.content, old.from_agent, old.to_agent, old.space);
239
+ INSERT INTO messages_fts(rowid, content, from_agent, to_agent, space)
240
+ VALUES (new.id, new.content, new.from_agent, new.to_agent, new.space);
241
+ END
242
+ `);
243
+ }
207
244
  return db;
208
245
  }
209
246
  function closeDb() {
@@ -2030,8 +2067,84 @@ var require_react = __commonJS((exports, module) => {
2030
2067
  init_db();
2031
2068
  import { randomUUID } from "crypto";
2032
2069
  import { mkdirSync as mkdirSync2, copyFileSync, statSync } from "fs";
2070
+ import { join as join3 } from "path";
2071
+ import { homedir as homedir3 } from "os";
2072
+
2073
+ // src/lib/webhooks.ts
2074
+ import { readFileSync } from "fs";
2033
2075
  import { join as join2 } from "path";
2034
2076
  import { homedir as homedir2 } from "os";
2077
+ var cachedConfig = null;
2078
+ var configLoadedAt = 0;
2079
+ var CONFIG_CACHE_MS = 1e4;
2080
+ function getConfigPath() {
2081
+ return process.env.CONVERSATIONS_CONFIG_PATH || join2(homedir2(), ".conversations", "config.json");
2082
+ }
2083
+ function loadConfig() {
2084
+ const now = Date.now();
2085
+ if (cachedConfig && now - configLoadedAt < CONFIG_CACHE_MS)
2086
+ return cachedConfig;
2087
+ try {
2088
+ const raw = readFileSync(getConfigPath(), "utf-8");
2089
+ cachedConfig = JSON.parse(raw);
2090
+ configLoadedAt = now;
2091
+ return cachedConfig;
2092
+ } catch {
2093
+ cachedConfig = {};
2094
+ configLoadedAt = now;
2095
+ return cachedConfig;
2096
+ }
2097
+ }
2098
+ function matchesEvent(webhook, msg) {
2099
+ for (const event of webhook.events) {
2100
+ if (event === "dm" && !msg.space)
2101
+ return true;
2102
+ if (event === "blocker" && msg.blocking)
2103
+ return true;
2104
+ if (event === "space" && msg.space)
2105
+ return true;
2106
+ if (event === "mention" && webhook.agent && msg.content.includes(`@${webhook.agent}`))
2107
+ return true;
2108
+ }
2109
+ return false;
2110
+ }
2111
+ function fireWebhooks(msg) {
2112
+ const config = loadConfig();
2113
+ if (!config.webhooks || config.webhooks.length === 0)
2114
+ return;
2115
+ for (const webhook of config.webhooks) {
2116
+ if (webhook.agent && msg.to_agent !== webhook.agent && !msg.space)
2117
+ continue;
2118
+ if (!matchesEvent(webhook, msg))
2119
+ continue;
2120
+ fetch(webhook.url, {
2121
+ method: "POST",
2122
+ headers: { "Content-Type": "application/json" },
2123
+ body: JSON.stringify({
2124
+ id: msg.id,
2125
+ from: msg.from_agent,
2126
+ to: msg.to_agent,
2127
+ space: msg.space,
2128
+ content: msg.content,
2129
+ priority: msg.priority,
2130
+ blocking: msg.blocking,
2131
+ created_at: msg.created_at
2132
+ })
2133
+ }).catch(() => {});
2134
+ }
2135
+ }
2136
+
2137
+ // src/lib/messages.ts
2138
+ function compactMessage(msg) {
2139
+ const result = {};
2140
+ for (const key of Object.keys(msg)) {
2141
+ const val = msg[key];
2142
+ if (val !== null && val !== undefined) {
2143
+ result[key] = val;
2144
+ }
2145
+ }
2146
+ return result;
2147
+ }
2035
2148
  function parseMessage(row) {
2036
2149
  let metadata = null;
2037
2150
  if (row.metadata) {
@@ -2053,13 +2166,14 @@ function parseMessage(row) {
2053
2166
  ...row,
2054
2167
  metadata,
2055
2168
  attachments,
2056
- blocking: !!row.blocking
2169
+ blocking: !!row.blocking,
2170
+ reply_to: row.reply_to || null
2057
2171
  };
2058
2172
  }
2059
2173
  function getAttachmentsDir() {
2060
2174
  if (process.env.CONVERSATIONS_ATTACHMENTS_DIR)
2061
2175
  return process.env.CONVERSATIONS_ATTACHMENTS_DIR;
2062
- return join2(homedir2(), ".conversations", "attachments");
2176
+ return join3(homedir3(), ".conversations", "attachments");
2063
2177
  }
2064
2178
  function guessMimeType(name) {
2065
2179
  const ext = name.split(".").pop()?.toLowerCase();
@@ -2095,19 +2209,20 @@ function sendMessage(opts) {
2095
2209
  const metadata = opts.metadata ? JSON.stringify(opts.metadata) : null;
2096
2210
  const normalizedPriority = opts.priority === "low" || opts.priority === "normal" || opts.priority === "high" || opts.priority === "urgent" ? opts.priority : "normal";
2097
2211
  const blocking = opts.blocking ? 1 : 0;
2212
+ const replyTo = opts.reply_to || null;
2098
2213
  const stmt = db2.prepare(`
2099
- INSERT INTO messages (session_id, from_agent, to_agent, space, content, priority, working_dir, repository, branch, metadata, blocking)
2100
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2214
+ INSERT INTO messages (session_id, from_agent, to_agent, space, content, priority, working_dir, repository, branch, metadata, blocking, reply_to)
2215
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2101
2216
  RETURNING *
2102
2217
  `);
2103
- const row = stmt.get(sessionId, opts.from, opts.to, opts.space || null, opts.content, normalizedPriority, opts.working_dir || null, opts.repository || null, opts.branch || null, metadata, blocking);
2218
+ const row = stmt.get(sessionId, opts.from, opts.to, opts.space || null, opts.content, normalizedPriority, opts.working_dir || null, opts.repository || null, opts.branch || null, metadata, blocking, replyTo);
2104
2219
  const message = parseMessage(row);
2105
2220
  if (opts.attachments && opts.attachments.length > 0) {
2106
- const attachmentsDir = join2(getAttachmentsDir(), String(message.id));
2221
+ const attachmentsDir = join3(getAttachmentsDir(), String(message.id));
2107
2222
  mkdirSync2(attachmentsDir, { recursive: true });
2108
2223
  const attachmentInfos = [];
2109
2224
  for (const att of opts.attachments) {
2110
- const destPath = join2(attachmentsDir, att.name);
2225
+ const destPath = join3(attachmentsDir, att.name);
2111
2226
  copyFileSync(att.source_path, destPath);
2112
2227
  const stat = statSync(destPath);
2113
2228
  attachmentInfos.push({
@@ -2121,6 +2236,7 @@ function sendMessage(opts) {
2121
2236
  db2.prepare("UPDATE messages SET attachments = ? WHERE id = ?").run(attachmentsJson, message.id);
2122
2237
  message.attachments = attachmentInfos;
2123
2238
  }
2239
+ fireWebhooks(message);
2124
2240
  return message;
2125
2241
  }
2126
2242
  function readMessages(opts = {}) {
@@ -2155,10 +2271,13 @@ function readMessages(opts = {}) {
2155
2271
  conditions.push("read_at IS NULL");
2156
2272
  }
2157
2273
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
2158
- const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? `LIMIT ${Math.floor(opts.limit)}` : "";
2274
+ const resolvedLimit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
2159
2275
  const order = opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
2160
- const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} ${limit}`).all(...params);
2161
- return rows.map(parseMessage);
2276
+ const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit}`).all(...params);
2277
+ const messages = rows.map(parseMessage);
2278
+ if (opts.compact)
2279
+ return messages.map(compactMessage);
2280
+ return messages;
2162
2281
  }
2163
2282
  function markRead(ids, reader) {
2164
2283
  const db2 = getDb();
@@ -2302,8 +2421,40 @@ function getUnreadBlockers(agent) {
2302
2421
  `).all(agent, agent);
2303
2422
  return rows.map(parseMessage);
2304
2423
  }
2424
+ function getThreadReplies(messageId) {
2425
+ const db2 = getDb();
2426
+ const rows = db2.prepare("SELECT * FROM messages WHERE reply_to = ? ORDER BY created_at ASC, id ASC").all(messageId);
2427
+ return rows.map(parseMessage);
2428
+ }
2305
2429
  function searchMessages(opts) {
2306
2430
  const db2 = getDb();
2431
+ const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
2432
+ try {
2433
+ const ftsConditions = [];
2434
+ const ftsParams = [];
2435
+ const words = opts.query.trim().split(/\s+/).filter(Boolean);
2436
+ const ftsQuery = words.map((w) => `"${w.replace(/"/g, '""')}"`).join(" ");
2437
+ ftsConditions.push("messages_fts MATCH ?");
2438
+ ftsParams.push(ftsQuery);
2439
+ let extraWhere = "";
2440
+ if (opts.space) {
2441
+ extraWhere += " AND m.space = ?";
2442
+ ftsParams.push(opts.space);
2443
+ }
2444
+ if (opts.from) {
2445
+ extraWhere += " AND m.from_agent = ?";
2446
+ ftsParams.push(opts.from);
2447
+ }
2448
+ if (opts.to) {
2449
+ extraWhere += " AND m.to_agent = ?";
2450
+ ftsParams.push(opts.to);
2451
+ }
2452
+ const rows2 = db2.prepare(`SELECT m.* FROM messages m
2453
+ JOIN messages_fts ON messages_fts.rowid = m.id
2454
+ WHERE ${ftsConditions.join(" AND ")}${extraWhere}
2455
+ ORDER BY m.created_at DESC, m.id DESC LIMIT ${limit}`).all(...ftsParams);
2456
+ return rows2.map(parseMessage);
2457
+ } catch {}
2307
2458
  const conditions = ["content LIKE ?"];
2308
2459
  const params = [`%${opts.query}%`];
2309
2460
  if (opts.space) {
@@ -2318,7 +2469,6 @@ function searchMessages(opts) {
2318
2469
  conditions.push("to_agent = ?");
2319
2470
  params.push(opts.to);
2320
2471
  }
2321
- const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 50;
2322
2472
  const where = `WHERE ${conditions.join(" AND ")}`;
2323
2473
  const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at DESC, id DESC LIMIT ${limit}`).all(...params);
2324
2474
  return rows.map(parseMessage);
@@ -2798,9 +2948,9 @@ function useSpaceMessages(spaceName) {
2798
2948
  return messages;
2799
2949
  }
2800
2950
  // src/lib/identity.ts
2801
- import { readFileSync, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
2802
- import { join as join3, dirname as dirname2 } from "path";
2803
- import { homedir as homedir3 } from "os";
2951
+ import { readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
2952
+ import { join as join4, dirname as dirname2 } from "path";
2953
+ import { homedir as homedir4 } from "os";
2804
2954
 
2805
2955
  // src/lib/names.ts
2806
2956
  var AGENT_NAMES = [
@@ -3152,7 +3302,7 @@ var AGENT_NAMES = [
3152
3302
  ];
3153
3303
 
3154
3304
  // src/lib/identity.ts
3155
- var AGENT_ID_FILE = join3(homedir3(), ".conversations", "agent-id");
3305
+ var AGENT_ID_FILE = join4(homedir4(), ".conversations", "agent-id");
3156
3306
  var cachedAutoName = null;
3157
3307
  function isNameTaken(name) {
3158
3308
  try {
@@ -3168,7 +3318,7 @@ function getAutoName() {
3168
3318
  if (cachedAutoName)
3169
3319
  return cachedAutoName;
3170
3320
  try {
3171
- const name2 = readFileSync(AGENT_ID_FILE, "utf-8").trim();
3321
+ const name2 = readFileSync2(AGENT_ID_FILE, "utf-8").trim();
3172
3322
  if (name2) {
3173
3323
  cachedAutoName = name2;
3174
3324
  return name2;
@@ -3345,6 +3495,7 @@ export {
3345
3495
  isSpaceMember,
3346
3496
  heartbeat,
3347
3497
  getUnreadBlockers,
3498
+ getThreadReplies,
3348
3499
  getSpaceMembers,
3349
3500
  getSpaceDepth,
3350
3501
  getSpace,
@@ -3358,6 +3509,7 @@ export {
3358
3509
  getMessageById,
3359
3510
  getDbPath,
3360
3511
  getDb,
3512
+ fireWebhooks,
3361
3513
  exportMessages,
3362
3514
  editMessage,
3363
3515
  deleteProject,
@@ -1,4 +1,6 @@
1
1
  import type { Message, SendMessageOptions, ReadMessagesOptions, SearchMessagesOptions } from "../types.js";
2
+ /** Strip null/undefined fields from a message for compact output. */
3
+ export declare function compactMessage(msg: Message): Partial<Message>;
2
4
  export declare function sendMessage(opts: SendMessageOptions): Message;
3
5
  export declare function readMessages(opts?: ReadMessagesOptions): Message[];
4
6
  export declare function markRead(ids: number[], reader: string): number;
@@ -25,4 +27,5 @@ export declare function getPinnedMessages(opts?: {
25
27
  limit?: number;
26
28
  }): Message[];
27
29
  export declare function getUnreadBlockers(agent: string): Message[];
30
+ export declare function getThreadReplies(messageId: number): Message[];
28
31
  export declare function searchMessages(opts: SearchMessagesOptions): Message[];
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Render inline markdown formatting for terminal output.
3
+ * Handles: inline code, bold+italic, bold, italic, strikethrough.
4
+ */
5
+ export declare const renderInline: (text: string) => string;
6
+ /**
7
+ * Render markdown content for terminal output.
8
+ * Handles: headings, bullet lists, ordered lists, blockquotes,
9
+ * code block markers, inline formatting.
10
+ */
11
+ export declare const renderContent: (content: string) => string;
@@ -0,0 +1,11 @@
1
+ import type { Message } from "../types.js";
2
+ export interface WebhookConfig {
3
+ url: string;
4
+ events: ("dm" | "blocker" | "space" | "mention")[];
5
+ agent?: string;
6
+ }
7
+ /**
8
+ * Fire webhooks for a message. Runs async, never blocks sendMessage.
9
+ * Matches webhooks by event type and optionally by agent (to_agent).
10
+ */
11
+ export declare function fireWebhooks(msg: Message): void;
@@ -0,0 +1 @@
1
+ export {};
package/dist/types.d.ts CHANGED
@@ -17,6 +17,7 @@ export interface Message {
17
17
  pinned_at: string | null;
18
18
  blocking: boolean;
19
19
  attachments: Attachment[] | null;
20
+ reply_to: number | null;
20
21
  }
21
22
  export interface Reaction {
22
23
  id: number;
@@ -89,6 +90,7 @@ export interface SendMessageOptions {
89
90
  name: string;
90
91
  source_path: string;
91
92
  }[];
93
+ reply_to?: number;
92
94
  }
93
95
  export interface ReadMessagesOptions {
94
96
  session_id?: string;
@@ -100,6 +102,7 @@ export interface ReadMessagesOptions {
100
102
  limit?: number;
101
103
  unread_only?: boolean;
102
104
  order?: "asc" | "desc";
105
+ compact?: boolean;
103
106
  }
104
107
  export interface SearchMessagesOptions {
105
108
  query: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/conversations",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "Real-time CLI messaging for AI agents",
5
5
  "type": "module",
6
6
  "bin": {