conductor-remote 1.112.0 → 1.113.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.
- package/README.md +6 -2
- package/dist/assets/{PierrePatch-Bzmaa7gu.js → PierrePatch-awVutyVW.js} +1 -1
- package/dist/assets/{index-9nM3BADp.js → index-DDm_FLf-.js} +39 -37
- package/dist/assets/index-MmdttBBU.css +1 -0
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/dist-node/src/mcp-tools.js +143 -1
- package/dist-node/src/routes.js +4 -0
- package/dist-node/src/server.js +37 -1
- package/dist-node/src/voice/broker.js +44 -7
- package/dist-node/src/voice/history.js +452 -0
- package/dist-node/src/voice/transcription.js +10 -0
- package/dist-node/src/voice/webrtc.js +3 -8
- package/docs/voice-setup.md +24 -0
- package/package.json +1 -1
- package/dist/assets/index-iryu1HEQ.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@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-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-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-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-outline-style:solid;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, -apple-system, "SF Pro Text", "Segoe UI", Roboto, sans-serif;--font-mono:ui-monospace, "SF Mono", "JetBrains Mono", "Fira Code", Menlo, monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-sm:24rem;--container-md:28rem;--container-xl:36rem;--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);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-xl:24px;--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);--color-bg:light-dark(#f5f6f8,#0a0b0e);--color-surface:light-dark(#fff,#14161b);--color-surface-2:light-dark(#eceef2,#1b1e26);--color-border:light-dark(#d4d7de,#262a33);--color-border-soft:light-dark(#e2e4e9,#1e222a);--color-text:light-dark(#1c1e24,#e7e9ee);--color-muted:light-dark(#626773,#8b909d);--color-faint:light-dark(#9499a4,#5c616d);--color-accent:light-dark(#6757d9,#8b7dff);--color-accent-soft:light-dark(#ebe9ff,#2a2650);--color-on-solid:light-dark(#fff,#101116);--color-provider-openai:light-dark(#17191f,#fff);--color-voice:light-dark(#14799d,#54c8f1);--color-voice-soft:light-dark(#dcf3fb,#102d38);--color-working:light-dark(#a65f00,#f5a623);--color-idle:light-dark(#167a52,#3ecf8e);--color-done:light-dark(#286bc0,#5b9dff);--color-context-initial:light-dark(#4b505c,#d7dae0);--color-context-chat:light-dark(#a83fa3,#ed7ce2);--color-context-tools:light-dark(#087f73,#35cdb8);--color-cold-cache:light-dark(#90611f,#d6a85f);--color-pr-merged:light-dark(#7b38b5,#ac47ff);--color-pr-draft:light-dark(#6e7075,#a4a3a2);--color-pr-attention:light-dark(#916b00,#facc15);--color-pr-mergeable:light-dark(#167b42,#49de80);--color-add:light-dark(#14784f,#3ecf8e);--color-del:light-dark(#c73c3c,#ff6b6b)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,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]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{-webkit-tap-highlight-color:transparent}html,body,#root{height:var(--app-height,100dvh)}html,body{overflow:hidden}@media(display-mode:standalone){html,body,#root{height:var(--app-height,100vh)}}html[data-standalone],html[data-standalone] body,html[data-standalone] #root{height:var(--app-height,100vh)}.app-height{height:var(--app-height,100dvh)}@media(display-mode:standalone){.app-height{height:var(--app-height,100vh)}}html[data-standalone] .app-height{height:var(--app-height,100vh)}@media(min-width:48rem){.app-height,html[data-standalone] .app-height{height:auto}}html{color-scheme:light dark;background:var(--color-bg)}html[data-theme=light]{color-scheme:light}html[data-theme=dark]{color-scheme:dark}body{background:var(--color-bg);color:var(--color-text);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;overscroll-behavior:none;margin:0}button{font:inherit;color:inherit;cursor:pointer}::-webkit-scrollbar{width:0;height:0}}@layer components{.card{align-items:center;gap:calc(var(--spacing) * 3);border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);padding-inline:calc(var(--spacing) * 4);padding-block:calc(var(--spacing) * 3.5);text-align:left;transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));display:flex}.card:active{background-color:var(--color-surface-2);scale:.985}.pill{padding-inline:calc(var(--spacing) * 3.5);padding-block:calc(var(--spacing) * 1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-muted);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));border-radius:3.40282e38px}.pill-active{background-color:var(--color-surface-2);color:var(--color-text)}.ctl{padding-inline:calc(var(--spacing) * 2);padding-block:var(--spacing);--tw-font-weight:var(--font-weight-medium);font-size:13px;font-weight:var(--font-weight-medium);color:var(--color-muted);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));border-radius:3.40282e38px}.ctl-on{background-color:var(--color-surface-2);color:var(--color-text)}.ctl-staged{background-color:var(--color-accent-soft);color:var(--color-accent)}.dot{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5);background-color:var(--color-faint);border-radius:3.40282e38px;flex-shrink:0}.dot-spinner{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5);animation:var(--animate-spin);border-style:var(--tw-border-style);--spin-color:var(--color-working);border-width:2px;border-color:var(--spin-color);border-radius:3.40282e38px;flex-shrink:0}@supports (color:color-mix(in lab,red,red)){.dot-spinner{border-color:color-mix(in srgb,var(--spin-color) 30%,transparent)}}.dot-spinner{border-top-color:var(--spin-color);border-right-color:var(--spin-color)}.dot-error{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5);border-style:var(--tw-border-style);border-width:2px;border-color:var(--color-del);color:var(--color-del);border-radius:3.40282e38px;flex-shrink:0;justify-content:center;align-items:center;display:flex}.dot-idle{background:var(--color-idle)}.dot-done{background:var(--color-done)}.typing-dot{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5);background-color:var(--color-muted);border-radius:3.40282e38px;animation:1.2s ease-in-out infinite typing}.typing-dot:nth-child(2){animation-delay:.15s}.typing-dot:nth-child(3){animation-delay:.3s}.md>:first-child{margin-top:0}.md>:last-child{margin-bottom:0}.md p{margin:.5em 0}.md h1,.md h2,.md h3,.md h4,.md h5,.md h6{margin:.9em 0 .4em;font-weight:600;line-height:1.3}.md h1{font-size:1.6em}.md h2{font-size:1.4em}.md h3{font-size:1.2em}.md h4{font-size:1.1em}.md ul,.md ol{margin:.5em 0;padding-left:1.4em}.md ul{list-style:outside}.md ol{list-style:decimal}.md li{margin:.3em 0}.md li>ul,.md li>ol{margin:.2em 0}.md code{background:light-dark(#eceef2cc,#1b1e26cc);border-radius:.3rem}@supports (color:color-mix(in lab,red,red)){.md code{background:color-mix(in srgb,var(--color-surface-2) 80%,transparent)}}.md code{font-family:var(--font-mono);padding:.1em .35em;font-size:.85em}.md pre{border:1px solid var(--color-border-soft);background:var(--color-bg);border-radius:.6rem;margin:.5em 0;padding:.6em .75em;overflow-x:auto}.md pre code{background:0 0;padding:0;font-size:12px;line-height:1.5}.md a{color:var(--color-accent);text-underline-offset:2px;text-decoration:underline}.md blockquote{border-left:2px solid var(--color-border);color:var(--color-muted);margin:.5em 0;padding-left:.75em}.md hr{border:0;border-top:1px solid var(--color-border-soft);margin:1.25em 0}.md img{border-radius:.6rem;max-width:100%;height:auto;margin:.5em 0;display:block}.md table{border-collapse:collapse;max-width:100%;margin:.5em 0;font-size:.9em;display:block;overflow-x:auto}.md th,.md td{border:1px solid var(--color-border);text-align:left;padding:.3em .6em}.md th{background:var(--color-surface-2);font-weight:600}.md strong{font-weight:600}.md input[type=checkbox]{margin-right:.4em}.hljs-comment,.hljs-quote{color:var(--color-faint);font-style:italic}.hljs-keyword,.hljs-literal,.hljs-type,.hljs-built_in,.hljs-selector-tag,.hljs-doctag,.hljs-meta .hljs-keyword{color:var(--color-accent)}.hljs-string,.hljs-regexp,.hljs-char.escape_,.hljs-addition,.hljs-meta .hljs-string{color:var(--color-add)}.hljs-number,.hljs-symbol,.hljs-bullet,.hljs-link,.hljs-meta,.hljs-template-variable{color:var(--color-working)}.hljs-title,.hljs-title.class_,.hljs-title.function_,.hljs-name,.hljs-section,.hljs-selector-id,.hljs-selector-class{color:var(--color-done)}.hljs-attr,.hljs-attribute,.hljs-property,.hljs-variable,.hljs-params,.hljs-subst,.hljs-template-tag{color:var(--color-text)}.hljs-deletion{color:var(--color-del)}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:600}}@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.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}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.inset-1{inset:var(--spacing)}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.-top-0\.5{top:calc(var(--spacing) * -.5)}.top-0{top:0}.top-0\.5{top:calc(var(--spacing) * .5)}.top-1{top:var(--spacing)}.top-1\.5{top:calc(var(--spacing) * 1.5)}.top-1\/2{top:50%}.top-full{top:100%}.-right-0\.5{right:calc(var(--spacing) * -.5)}.right-0{right:0}.right-1{right:var(--spacing)}.right-1\.5{right:calc(var(--spacing) * 1.5)}.right-2{right:calc(var(--spacing) * 2)}.right-3{right:calc(var(--spacing) * 3)}.-bottom-0\.5{bottom:calc(var(--spacing) * -.5)}.bottom-0{bottom:0}.bottom-full{bottom:100%}.-left-0\.5{left:calc(var(--spacing) * -.5)}.left-0{left:0}.left-0\.5{left:calc(var(--spacing) * .5)}.left-3{left:calc(var(--spacing) * 3)}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[1\]{z-index:1}.z-\[60\]{z-index:60}.m-0{margin:0}.mx-3{margin-inline:calc(var(--spacing) * 3)}.mx-auto{margin-inline:auto}.my-1\.5{margin-block:calc(var(--spacing) * 1.5)}.my-2{margin-block:calc(var(--spacing) * 2)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-7{margin-top:calc(var(--spacing) * 7)}.-mr-0\.5{margin-right:calc(var(--spacing) * -.5)}.-mr-1{margin-right:calc(var(--spacing) * -1)}.-mr-2{margin-right:calc(var(--spacing) * -2)}.mr-1{margin-right:var(--spacing)}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.mr-auto{margin-right:auto}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:var(--spacing)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.-ml-1{margin-left:calc(var(--spacing) * -1)}.ml-1{margin-left:var(--spacing)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-4{-webkit-line-clamp:4;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.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-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.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-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.size-16{width:calc(var(--spacing) * 16);height:calc(var(--spacing) * 16)}.size-20{width:calc(var(--spacing) * 20);height:calc(var(--spacing) * 20)}.size-60{width:calc(var(--spacing) * 60);height:calc(var(--spacing) * 60)}.size-\[15px\]{width:15px;height:15px}.size-\[17px\]{width:17px;height:17px}.size-\[18px\]{width:18px;height:18px}.size-\[30px\]{width:30px;height:30px}.size-full{width:100%;height:100%}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-11{height:calc(var(--spacing) * 11)}.h-12{height:calc(var(--spacing) * 12)}.h-\[15px\]{height:15px}.h-\[30px\]{height:30px}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-72{max-height:calc(var(--spacing) * 72)}.max-h-\[70\%\]{max-height:70%}.max-h-\[85dvh\]{max-height:85dvh}.max-h-\[calc\(100dvh-4rem\)\]{max-height:calc(100dvh - 4rem)}.max-h-full{max-height:100%}.min-h-0{min-height:0}.min-h-4{min-height:calc(var(--spacing) * 4)}.min-h-8{min-height:calc(var(--spacing) * 8)}.min-h-9{min-height:calc(var(--spacing) * 9)}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-14{min-height:calc(var(--spacing) * 14)}.min-h-40{min-height:calc(var(--spacing) * 40)}.min-h-48{min-height:calc(var(--spacing) * 48)}.w-0\.5{width:calc(var(--spacing) * .5)}.w-1{width:var(--spacing)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-9{width:calc(var(--spacing) * 9)}.w-11{width:calc(var(--spacing) * 11)}.w-12{width:calc(var(--spacing) * 12)}.w-60{width:calc(var(--spacing) * 60)}.w-64{width:calc(var(--spacing) * 64)}.w-\[6\.5rem\]{width:6.5rem}.w-\[85\%\]{width:85%}.w-full{width:100%}.max-w-20{max-width:calc(var(--spacing) * 20)}.max-w-28{max-width:calc(var(--spacing) * 28)}.max-w-36{max-width:calc(var(--spacing) * 36)}.max-w-40{max-width:calc(var(--spacing) * 40)}.max-w-56{max-width:calc(var(--spacing) * 56)}.max-w-64{max-width:calc(var(--spacing) * 64)}.max-w-72{max-width:calc(var(--spacing) * 72)}.max-w-80{max-width:calc(var(--spacing) * 80)}.max-w-\[70vw\]{max-width:70vw}.max-w-\[85\%\]{max-width:85%}.max-w-\[85vw\]{max-width:85vw}.max-w-\[88\%\]{max-width:88%}.max-w-\[92\%\]{max-width:92%}.max-w-full{max-width:100%}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:0}.min-w-5{min-width:calc(var(--spacing) * 5)}.min-w-8{min-width:calc(var(--spacing) * 8)}.min-w-9{min-width:calc(var(--spacing) * 9)}.min-w-10{min-width:calc(var(--spacing) * 10)}.min-w-28{min-width:calc(var(--spacing) * 28)}.min-w-44{min-width:calc(var(--spacing) * 44)}.min-w-52{min-width:calc(var(--spacing) * 52)}.min-w-max{min-width:max-content}.flex-1{flex:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-full{--tw-translate-x:-100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-0{--tw-translate-x:0;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-5{--tw-translate-x:calc(var(--spacing) * 5);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-0{--tw-translate-y:0;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-3{--tw-translate-y:calc(var(--spacing) * 3);translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.rotate-90{rotate:90deg}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-none{resize:none}.resize-y{resize:vertical}.scrollbar-thin{scrollbar-width:thin}.list-none{list-style-type:none}.appearance-none{appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.grid-cols-\[minmax\(0\,1fr\)_auto_auto\]{grid-template-columns:minmax(0,1fr) auto auto}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-0{gap:0}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-\[1\.5px\]{gap:1.5px}:where(.space-y-1\.25>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.25) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.25) * 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-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)))}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-x-5{column-gap:calc(var(--spacing) * 5)}:where(.-space-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * -1) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * -1) * calc(1 - var(--tw-space-x-reverse)))}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.gap-y-1{row-gap:var(--spacing)}.gap-y-2\.5{row-gap:calc(var(--spacing) * 2.5)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border-soft>:not(:last-child)){border-color:var(--color-border-soft)}.self-center{align-self:center}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.overscroll-contain{overscroll-behavior:contain}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-2xl{border-top-left-radius:var(--radius-2xl);border-top-right-radius:var(--radius-2xl)}.rounded-t-3xl{border-top-left-radius:var(--radius-3xl);border-top-right-radius:var(--radius-3xl)}.rounded-br-md{border-bottom-right-radius:var(--radius-md)}.rounded-bl-md{border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-x{border-inline-style:var(--tw-border-style);border-inline-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent{border-color:var(--color-accent)}.border-accent\/50{border-color:light-dark(#6757d980,#8b7dff80)}@supports (color:color-mix(in lab,red,red)){.border-accent\/50{border-color:color-mix(in oklab,var(--color-accent) 50%,transparent)}}.border-border{border-color:var(--color-border)}.border-border-soft{border-color:var(--color-border-soft)}.border-cold-cache\/20{border-color:light-dark(#90611f33,#d6a85f33)}@supports (color:color-mix(in lab,red,red)){.border-cold-cache\/20{border-color:color-mix(in oklab,var(--color-cold-cache) 20%,transparent)}}.border-del{border-color:var(--color-del)}.border-del\/30{border-color:light-dark(#c73c3c4d,#ff6b6b4d)}@supports (color:color-mix(in lab,red,red)){.border-del\/30{border-color:color-mix(in oklab,var(--color-del) 30%,transparent)}}.border-del\/40{border-color:light-dark(#c73c3c66,#ff6b6b66)}@supports (color:color-mix(in lab,red,red)){.border-del\/40{border-color:color-mix(in oklab,var(--color-del) 40%,transparent)}}.border-del\/50{border-color:light-dark(#c73c3c80,#ff6b6b80)}@supports (color:color-mix(in lab,red,red)){.border-del\/50{border-color:color-mix(in oklab,var(--color-del) 50%,transparent)}}.border-faint{border-color:var(--color-faint)}.border-pr-merged\/30{border-color:light-dark(#7b38b54d,#ac47ff4d)}@supports (color:color-mix(in lab,red,red)){.border-pr-merged\/30{border-color:color-mix(in oklab,var(--color-pr-merged) 30%,transparent)}}.border-voice\/25{border-color:light-dark(#14799d40,#54c8f140)}@supports (color:color-mix(in lab,red,red)){.border-voice\/25{border-color:color-mix(in oklab,var(--color-voice) 25%,transparent)}}.border-white\/80{border-color:#fffc}@supports (color:color-mix(in lab,red,red)){.border-white\/80{border-color:color-mix(in oklab,var(--color-white) 80%,transparent)}}.border-working\/30{border-color:light-dark(#a65f004d,#f5a6234d)}@supports (color:color-mix(in lab,red,red)){.border-working\/30{border-color:color-mix(in oklab,var(--color-working) 30%,transparent)}}.border-t-accent{border-top-color:var(--color-accent)}.border-t-text{border-top-color:var(--color-text)}.border-l-accent{border-left-color:var(--color-accent)}.bg-accent{background-color:var(--color-accent)}.bg-accent-soft{background-color:var(--color-accent-soft)}.bg-accent-soft\/90{background-color:light-dark(#ebe9ffe6,#2a2650e6)}@supports (color:color-mix(in lab,red,red)){.bg-accent-soft\/90{background-color:color-mix(in oklab,var(--color-accent-soft) 90%,transparent)}}.bg-accent\/10{background-color:light-dark(#6757d91a,#8b7dff1a)}@supports (color:color-mix(in lab,red,red)){.bg-accent\/10{background-color:color-mix(in oklab,var(--color-accent) 10%,transparent)}}.bg-accent\/25{background-color:light-dark(#6757d940,#8b7dff40)}@supports (color:color-mix(in lab,red,red)){.bg-accent\/25{background-color:color-mix(in oklab,var(--color-accent) 25%,transparent)}}.bg-add{background-color:var(--color-add)}.bg-add\/10{background-color:light-dark(#14784f1a,#3ecf8e1a)}@supports (color:color-mix(in lab,red,red)){.bg-add\/10{background-color:color-mix(in oklab,var(--color-add) 10%,transparent)}}.bg-bg{background-color:var(--color-bg)}.bg-bg\/80{background-color:light-dark(#f5f6f8cc,#0a0b0ecc)}@supports (color:color-mix(in lab,red,red)){.bg-bg\/80{background-color:color-mix(in oklab,var(--color-bg) 80%,transparent)}}.bg-bg\/90{background-color:light-dark(#f5f6f8e6,#0a0b0ee6)}@supports (color:color-mix(in lab,red,red)){.bg-bg\/90{background-color:color-mix(in oklab,var(--color-bg) 90%,transparent)}}.bg-black{background-color:var(--color-black)}.bg-black\/15{background-color:#00000026}@supports (color:color-mix(in lab,red,red)){.bg-black\/15{background-color:color-mix(in oklab,var(--color-black) 15%,transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black) 50%,transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab,red,red)){.bg-black\/60{background-color:color-mix(in oklab,var(--color-black) 60%,transparent)}}.bg-black\/65{background-color:#000000a6}@supports (color:color-mix(in lab,red,red)){.bg-black\/65{background-color:color-mix(in oklab,var(--color-black) 65%,transparent)}}.bg-black\/75{background-color:#000000bf}@supports (color:color-mix(in lab,red,red)){.bg-black\/75{background-color:color-mix(in oklab,var(--color-black) 75%,transparent)}}.bg-cold-cache\/8{background-color:light-dark(#90611f14,#d6a85f14)}@supports (color:color-mix(in lab,red,red)){.bg-cold-cache\/8{background-color:color-mix(in oklab,var(--color-cold-cache) 8%,transparent)}}.bg-cold-cache\/12{background-color:light-dark(#90611f1f,#d6a85f1f)}@supports (color:color-mix(in lab,red,red)){.bg-cold-cache\/12{background-color:color-mix(in oklab,var(--color-cold-cache) 12%,transparent)}}.bg-context-chat{background-color:var(--color-context-chat)}.bg-context-initial{background-color:var(--color-context-initial)}.bg-context-tools{background-color:var(--color-context-tools)}.bg-current{background-color:currentColor}.bg-del{background-color:var(--color-del)}.bg-del\/5{background-color:light-dark(#c73c3c0d,#ff6b6b0d)}@supports (color:color-mix(in lab,red,red)){.bg-del\/5{background-color:color-mix(in oklab,var(--color-del) 5%,transparent)}}.bg-del\/10{background-color:light-dark(#c73c3c1a,#ff6b6b1a)}@supports (color:color-mix(in lab,red,red)){.bg-del\/10{background-color:color-mix(in oklab,var(--color-del) 10%,transparent)}}.bg-del\/15{background-color:light-dark(#c73c3c26,#ff6b6b26)}@supports (color:color-mix(in lab,red,red)){.bg-del\/15{background-color:color-mix(in oklab,var(--color-del) 15%,transparent)}}.bg-inherit{background-color:inherit}.bg-pr-merged\/10{background-color:light-dark(#7b38b51a,#ac47ff1a)}@supports (color:color-mix(in lab,red,red)){.bg-pr-merged\/10{background-color:color-mix(in oklab,var(--color-pr-merged) 10%,transparent)}}.bg-pr-merged\/15{background-color:light-dark(#7b38b526,#ac47ff26)}@supports (color:color-mix(in lab,red,red)){.bg-pr-merged\/15{background-color:color-mix(in oklab,var(--color-pr-merged) 15%,transparent)}}.bg-surface{background-color:var(--color-surface)}.bg-surface-2{background-color:var(--color-surface-2)}.bg-surface-2\/60{background-color:light-dark(#eceef299,#1b1e2699)}@supports (color:color-mix(in lab,red,red)){.bg-surface-2\/60{background-color:color-mix(in oklab,var(--color-surface-2) 60%,transparent)}}.bg-surface\/40{background-color:light-dark(#fff6,#14161b66)}@supports (color:color-mix(in lab,red,red)){.bg-surface\/40{background-color:color-mix(in oklab,var(--color-surface) 40%,transparent)}}.bg-surface\/60{background-color:light-dark(#fff9,#14161b99)}@supports (color:color-mix(in lab,red,red)){.bg-surface\/60{background-color:color-mix(in oklab,var(--color-surface) 60%,transparent)}}.bg-surface\/70{background-color:light-dark(#ffffffb3,#14161bb3)}@supports (color:color-mix(in lab,red,red)){.bg-surface\/70{background-color:color-mix(in oklab,var(--color-surface) 70%,transparent)}}.bg-surface\/80{background-color:light-dark(#fffc,#14161bcc)}@supports (color:color-mix(in lab,red,red)){.bg-surface\/80{background-color:color-mix(in oklab,var(--color-surface) 80%,transparent)}}.bg-surface\/95{background-color:light-dark(#fffffff2,#14161bf2)}@supports (color:color-mix(in lab,red,red)){.bg-surface\/95{background-color:color-mix(in oklab,var(--color-surface) 95%,transparent)}}.bg-transparent{background-color:#0000}.bg-voice{background-color:var(--color-voice)}.bg-voice-soft{background-color:var(--color-voice-soft)}.bg-voice-soft\/60{background-color:light-dark(#dcf3fb99,#102d3899)}@supports (color:color-mix(in lab,red,red)){.bg-voice-soft\/60{background-color:color-mix(in oklab,var(--color-voice-soft) 60%,transparent)}}.bg-white{background-color:var(--color-white)}.bg-working{background-color:var(--color-working)}.bg-working\/5{background-color:light-dark(#a65f000d,#f5a6230d)}@supports (color:color-mix(in lab,red,red)){.bg-working\/5{background-color:color-mix(in oklab,var(--color-working) 5%,transparent)}}.bg-working\/10{background-color:light-dark(#a65f001a,#f5a6231a)}@supports (color:color-mix(in lab,red,red)){.bg-working\/10{background-color:color-mix(in oklab,var(--color-working) 10%,transparent)}}.stroke-accent{stroke:var(--color-accent)}.stroke-border{stroke:var(--color-border)}.stroke-context-chat{stroke:var(--color-context-chat)}.stroke-context-initial{stroke:var(--color-context-initial)}.stroke-context-tools{stroke:var(--color-context-tools)}.stroke-working{stroke:var(--color-working)}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-0{padding:0}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:var(--spacing)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-3\.5{padding:calc(var(--spacing) * 3.5)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.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:var(--spacing)}.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-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-7{padding-block:calc(var(--spacing) * 7)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-16{padding-block:calc(var(--spacing) * 16)}.py-px{padding-block:1px}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-2\.5{padding-top:calc(var(--spacing) * 2.5)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-1{padding-right:var(--spacing)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-3\.5{padding-right:calc(var(--spacing) * 3.5)}.pr-7{padding-right:calc(var(--spacing) * 7)}.pr-9{padding-right:calc(var(--spacing) * 9)}.pb-0\.5{padding-bottom:calc(var(--spacing) * .5)}.pb-1{padding-bottom:var(--spacing)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-2\.5{padding-bottom:calc(var(--spacing) * 2.5)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-2\.5{padding-left:calc(var(--spacing) * 2.5)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-3\.5{padding-left:calc(var(--spacing) * 3.5)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-8{padding-left:calc(var(--spacing) * 8)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-baseline{vertical-align:baseline}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.9em\]{font-size:.9em}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11\.5px\]{font-size:11.5px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13\.5px\]{font-size:13.5px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-\[1\.5\]{--tw-leading:1.5;line-height:1.5}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.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)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.\[overflow-wrap\:anywhere\]{overflow-wrap:anywhere}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--color-accent)}.text-add{color:var(--color-add)}.text-bg{color:var(--color-bg)}.text-black{color:var(--color-black)}.text-cold-cache{color:var(--color-cold-cache)}.text-del{color:var(--color-del)}.text-del\/80{color:light-dark(#c73c3ccc,#ff6b6bcc)}@supports (color:color-mix(in lab,red,red)){.text-del\/80{color:color-mix(in oklab,var(--color-del) 80%,transparent)}}.text-faint{color:var(--color-faint)}.text-muted{color:var(--color-muted)}.text-on-solid{color:var(--color-on-solid)}.text-pr-merged{color:var(--color-pr-merged)}.text-text{color:var(--color-text)}.text-voice{color:var(--color-voice)}.text-white{color:var(--color-white)}.text-working{color:var(--color-working)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.decoration-dotted{text-decoration-style:dotted}.underline-offset-2{text-underline-offset:2px}.\[color-scheme\:dark\]{color-scheme:dark}.opacity-0{opacity:0}.opacity-20{opacity:.2}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-100{opacity:1}.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-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_0_100vmax_rgba\(0\,0\,0\,0\.5\)\]{--tw-shadow:0 0 0 100vmax var(--tw-shadow-color,#00000080);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-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)}.ring,.ring-1{--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)}.ring-2{--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)}.shadow-black\/40{--tw-shadow-color:#0006}@supports (color:color-mix(in lab,red,red)){.shadow-black\/40{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-black) 40%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-black\/60{--tw-shadow-color:#0009}@supports (color:color-mix(in lab,red,red)){.shadow-black\/60{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-black) 60%, transparent) var(--tw-shadow-alpha), transparent)}}.ring-border{--tw-ring-color:var(--color-border)}.ring-surface{--tw-ring-color:var(--color-surface)}.blur{--tw-blur:blur(8px);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,)}.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{--tw-backdrop-blur:blur(8px);-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-xl{--tw-backdrop-blur:blur(var(--blur-xl));-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{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;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}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.\[--diffs-font-family\:var\(--font-mono\)\]{--diffs-font-family:var(--font-mono)}.\[--diffs-font-size\:11\.5px\]{--diffs-font-size:11.5px}.\[--diffs-line-height\:17\.25px\]{--diffs-line-height:17.25px}.group-open\/steps\:invisible:is(:where(.group\/steps):is([open],:popover-open,:open) *){visibility:hidden}.group-open\/steps\:rotate-90:is(:where(.group\/steps):is([open],:popover-open,:open) *),.group-open\/think\:rotate-90:is(:where(.group\/think):is([open],:popover-open,:open) *){rotate:90deg}.group-open\/tool\:invisible:is(:where(.group\/tool):is([open],:popover-open,:open) *){visibility:hidden}.group-open\/tool\:rotate-90:is(:where(.group\/tool):is([open],:popover-open,:open) *){rotate:90deg}.peer-focus-visible\:outline-2:is(:where(.peer):focus-visible~*){outline-style:var(--tw-outline-style);outline-width:2px}.peer-focus-visible\:outline-offset-2:is(:where(.peer):focus-visible~*){outline-offset:2px}.peer-focus-visible\:outline-accent:is(:where(.peer):focus-visible~*){outline-color:var(--color-accent)}.placeholder\:font-sans::placeholder{font-family:var(--font-sans)}.placeholder\:text-faint::placeholder{color:var(--color-faint)}@media(hover:hover){.hover\:bg-surface-2:hover{background-color:var(--color-surface-2)}.hover\:text-text:hover{color:var(--color-text)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-accent\/50:focus{border-color:light-dark(#6757d980,#8b7dff80)}@supports (color:color-mix(in lab,red,red)){.focus\:border-accent\/50:focus{border-color:color-mix(in oklab,var(--color-accent) 50%,transparent)}}.focus\:border-accent\/60:focus{border-color:light-dark(#6757d999,#8b7dff99)}@supports (color:color-mix(in lab,red,red)){.focus\:border-accent\/60:focus{border-color:color-mix(in oklab,var(--color-accent) 60%,transparent)}}.focus\:border-voice\/60:focus{border-color:light-dark(#14799d99,#54c8f199)}@supports (color:color-mix(in lab,red,red)){.focus\:border-voice\/60:focus{border-color:color-mix(in oklab,var(--color-voice) 60%,transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:bg-surface-2:focus-visible{background-color:var(--color-surface-2)}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:-outline-offset-2:focus-visible{outline-offset:-2px}.focus-visible\:outline-accent:focus-visible{outline-color:var(--color-accent)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\:scale-95:active{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x) var(--tw-scale-y)}.active\:scale-\[0\.97\]:active{scale:.97}.active\:scale-\[0\.985\]:active{scale:.985}.active\:bg-bg\/70:active{background-color:light-dark(#f5f6f8b3,#0a0b0eb3)}@supports (color:color-mix(in lab,red,red)){.active\:bg-bg\/70:active{background-color:color-mix(in oklab,var(--color-bg) 70%,transparent)}}.active\:bg-black\/70:active{background-color:#000000b3}@supports (color:color-mix(in lab,red,red)){.active\:bg-black\/70:active{background-color:color-mix(in oklab,var(--color-black) 70%,transparent)}}.active\:bg-cold-cache\/20:active{background-color:light-dark(#90611f33,#d6a85f33)}@supports (color:color-mix(in lab,red,red)){.active\:bg-cold-cache\/20:active{background-color:color-mix(in oklab,var(--color-cold-cache) 20%,transparent)}}.active\:bg-surface:active{background-color:var(--color-surface)}.active\:bg-surface-2:active{background-color:var(--color-surface-2)}.active\:text-text:active{color:var(--color-text)}.active\:opacity-70:active{opacity:.7}.active\:opacity-75:active{opacity:.75}.active\:opacity-80:active{opacity:.8}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:invisible:disabled{visibility:hidden}.disabled\:cursor-default:disabled{cursor:default}.disabled\:bg-surface-2:disabled{background-color:var(--color-surface-2)}.disabled\:text-faint:disabled{color:var(--color-faint)}.disabled\:text-faint\/40:disabled{color:light-dark(#9499a466,#5c616d66)}@supports (color:color-mix(in lab,red,red)){.disabled\:text-faint\/40:disabled{color:color-mix(in oklab,var(--color-faint) 40%,transparent)}}.disabled\:opacity-25:disabled{opacity:.25}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-35:disabled{opacity:.35}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.has-\[textarea\:focus\]\:border-accent\/60:has(:is(textarea:focus)){border-color:light-dark(#6757d999,#8b7dff99)}@supports (color:color-mix(in lab,red,red)){.has-\[textarea\:focus\]\:border-accent\/60:has(:is(textarea:focus)){border-color:color-mix(in oklab,var(--color-accent) 60%,transparent)}}@media(prefers-reduced-motion:reduce){.motion-reduce\:transition-none{transition-property:none}}@media not all and (min-width:340px){.max-\[340px\]\:hidden{display:none}}@media(min-width:360px){.min-\[360px\]\:size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}}@media(min-width:400px){.min-\[400px\]\:block{display:block}}@media(min-width:560px){.min-\[560px\]\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:48rem){.md\:static{position:static}.md\:inset-0{inset:0}.md\:inset-6{inset:calc(var(--spacing) * 6)}.md\:inset-x-auto{inset-inline:auto}.md\:inset-y-8{inset-block:calc(var(--spacing) * 8)}.md\:top-16{top:calc(var(--spacing) * 16)}.md\:left-1\/2{left:50%}.md\:z-auto{z-index:auto}.md\:m-auto{margin:auto}.md\:mb-6{margin-bottom:calc(var(--spacing) * 6)}.md\:block{display:block}.md\:flex{display:flex}.md\:hidden{display:none}.md\:h-fit{height:fit-content}.md\:max-h-\[70vh\]{max-height:70vh}.md\:w-72{width:calc(var(--spacing) * 72)}.md\:w-\[32rem\]{width:32rem}.md\:w-\[36rem\]{width:36rem}.md\:max-w-\[92vw\]{max-width:92vw}.md\:max-w-none{max-width:none}.md\:shrink-0{flex-shrink:0}.md\:-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.md\:translate-x-0{--tw-translate-x:0;translate:var(--tw-translate-x) var(--tw-translate-y)}.md\:rounded-2xl{border-radius:var(--radius-2xl)}.md\:rounded-3xl{border-radius:var(--radius-3xl)}.md\:border{border-style:var(--tw-border-style);border-width:1px}.md\:border-border{border-color:var(--color-border)}.md\:border-border-soft{border-color:var(--color-border-soft)}.md\:shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.md\:transition-none{transition-property:none}}@media(min-width:64rem){.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:w-80{width:calc(var(--spacing) * 80)}.lg\:w-\[380px\]{width:380px}.lg\:shrink-0{flex-shrink:0}.lg\:border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.lg\:border-border-soft{border-color:var(--color-border-soft)}}@media(min-width:80rem){.xl\:w-\[460px\]{width:460px}}.\[\&\:\:-webkit-details-marker\]\:hidden::-webkit-details-marker{display:none}}@keyframes typing{0%,60%,to{opacity:.35;transform:none}30%{opacity:1;transform:translateY(-3px)}}@keyframes fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.fade-in{animation:.18s ease-out fade-in}@media(prefers-reduced-motion:reduce){.fade-in{opacity:1;animation:none}.typing-dot{opacity:.6;animation:none}}.pt-safe{padding-top:max(env(safe-area-inset-top),.5rem)}.pb-safe{padding-bottom:max(env(safe-area-inset-bottom),.5rem)}html[data-keyboard] .pb-safe{padding-bottom:.5rem}@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-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-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-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@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}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}
|
package/dist/index.html
CHANGED
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
<title>Conductor Remote</title>
|
|
26
26
|
<!-- Runs before the module bundle so it can catch a stale shell that fails to boot. -->
|
|
27
27
|
<script src="/self-heal.js"></script>
|
|
28
|
-
<script type="module" crossorigin src="/assets/index-
|
|
29
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
28
|
+
<script type="module" crossorigin src="/assets/index-DDm_FLf-.js"></script>
|
|
29
|
+
<link rel="stylesheet" crossorigin href="/assets/index-MmdttBBU.css">
|
|
30
30
|
<link rel="manifest" href="/manifest.webmanifest"></head>
|
|
31
31
|
<body>
|
|
32
32
|
<div id="root"></div>
|
package/dist/sw.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const l=e||("document"in self?document.currentScript.src:"")||location.href;if(s[l])return;let o={};const
|
|
1
|
+
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const l=e||("document"in self?document.currentScript.src:"")||location.href;if(s[l])return;let o={};const t=e=>i(e,l),a={module:{uri:l},exports:o,require:t};s[l]=Promise.all(n.map(e=>a[e]||t(e))).then(e=>(r(...e),o))}}define(["./workbox-dcde9eb3"],function(e){"use strict";importScripts("/push-sw.js"),self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.clientsClaim(),e.precacheAndRoute([{url:"self-heal.js",revision:"49bd63adb25a09341f8d2610e8bd3c76"},{url:"push-sw.js",revision:"e7ef44deca46c0539e6ff7bba5eb815e"},{url:"index.html",revision:"ea31ef7e6fc1c359645d9ce940db4e03"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/pierre-shiki-wasm-C8ETeZem.js",revision:null},{url:"assets/pierre-light-480U9XYS.js",revision:null},{url:"assets/pierre-dark-CyvmCCZW.js",revision:null},{url:"assets/index-MmdttBBU.css",revision:null},{url:"assets/index-DDm_FLf-.js",revision:null},{url:"assets/PierrePatch-awVutyVW.js",revision:null},{url:"apple-touch-icon.png",revision:"1127bb396b4648add53dce3f22c92aee"},{url:"icon-192.png",revision:"c5e01ac58768627e18ee7b8b6a9239ef"},{url:"icon-512.png",revision:"a40638c55e310312457a621c9a0002c8"},{url:"icon-maskable-512.png",revision:"a9b0d962686287452216492cd2247499"},{url:"icon.svg",revision:"c1aee186821798733dd477e69a0ef243"},{url:"manifest.webmanifest",revision:"cf88fbc5755108a7fe0616fa160a8a15"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api\//]})),e.registerRoute(({url:e})=>e.pathname.startsWith("/assets/diff-syntax/"),new e.CacheFirst({cacheName:"diff-syntax",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:31536e3})]}),"GET")});
|
|
@@ -31,7 +31,7 @@ import { HIT_CLOSE, HIT_OPEN, isToolResult, timestampMs, workspaceTitle } from "
|
|
|
31
31
|
/** Versions we know how to speak. The client's choice wins when we know it. */
|
|
32
32
|
export const PROTOCOL_VERSIONS = ['2025-06-18', '2025-03-26', '2024-11-05'];
|
|
33
33
|
export const SERVER_INFO = { name: 'conductor-remote', version: '1' };
|
|
34
|
-
export const INSTRUCTIONS = 'Drives local Conductor agents through the conductor-remote relay. search_chats and read_chat reach archived workspaces, which is where most finished work lives. delegate_task operates only inside a Workflow already authorized from the phone: the current root envelope supplies its workflow id and phase capability, and the relay later drives the real Mac UI to launch the tracked child. MCP cannot start a Workflow, edit its frozen roles, or perform recovery actions. create_workspace opens its workspace link without direct UI control; requested agent settings and the first prompt are applied later through Conductor’s UI. plan_usage, dev_server status, dismiss_prompt, keep_awake and relay_logs touch no UI. Use dev_server instead of launching a long-lived development server from a shell: its start/stop actions use Conductor’s configured Run task, drive the real Mac UI and steal focus for a few seconds. send_prompt, split_chat, stop_turn, close_chat, set_agent_options, set_default_model, a live list_models call, set_workspace_status and archive_workspace also drive the real Mac UI and steal focus for a few seconds — confirm with the user before using them on a chat or workspace they did not name. archive_workspace also deletes the worktree and stops whatever is running there.';
|
|
34
|
+
export const INSTRUCTIONS = 'Drives local Conductor agents through the conductor-remote relay. search_chats and read_chat reach archived workspaces, which is where most finished work lives. list_voice_calls, search_voice_calls and read_voice_call read saved fleet-call transcripts without driving the UI. delegate_task operates only inside a Workflow already authorized from the phone: the current root envelope supplies its workflow id and phase capability, and the relay later drives the real Mac UI to launch the tracked child. MCP cannot start a Workflow, edit its frozen roles, or perform recovery actions. create_workspace opens its workspace link without direct UI control; requested agent settings and the first prompt are applied later through Conductor’s UI. plan_usage, dev_server status, dismiss_prompt, keep_awake and relay_logs touch no UI. Use dev_server instead of launching a long-lived development server from a shell: its start/stop actions use Conductor’s configured Run task, drive the real Mac UI and steal focus for a few seconds. send_prompt, split_chat, stop_turn, close_chat, set_agent_options, set_default_model, a live list_models call, set_workspace_status and archive_workspace also drive the real Mac UI and steal focus for a few seconds — confirm with the user before using them on a chat or workspace they did not name. archive_workspace also deletes the worktree and stops whatever is running there.';
|
|
35
35
|
/** Reads are quick; a UI write is measured in tens of seconds (writes.ts ▸ SEND_ATTEMPT_MS). */
|
|
36
36
|
export const READ_TIMEOUT_MS = 10_000;
|
|
37
37
|
export const WRITE_TIMEOUT_MS = 75_000;
|
|
@@ -143,6 +143,21 @@ function rejectUnknown(args, allowed) {
|
|
|
143
143
|
if (unknown.length)
|
|
144
144
|
throw new Error(`unknown ${unknown.length === 1 ? 'field' : 'fields'}: ${unknown.join(', ')}`);
|
|
145
145
|
}
|
|
146
|
+
function voiceCallHeader(call) {
|
|
147
|
+
return [
|
|
148
|
+
`call_id: ${call.callId}`,
|
|
149
|
+
`${new Date(call.startedAt).toISOString()} · ${call.status} · ${call.transport} · ${call.entryCount} entries`,
|
|
150
|
+
...(call.hasGaps ? ['! This transcript may have gaps from an interrupted connection.'] : []),
|
|
151
|
+
...(call.captureError ? [`! ${call.captureError}`] : [])
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
function voiceEntryFlags(entry) {
|
|
155
|
+
const flags = [
|
|
156
|
+
...(entry.transcriptionFailed ? ['audio could not be transcribed'] : entry.partial ? ['partial transcript'] : []),
|
|
157
|
+
...(entry.interrupted ? ['reply interrupted; generated text may include words not played'] : [])
|
|
158
|
+
];
|
|
159
|
+
return flags.length ? ` (${flags.join('; ')})` : '';
|
|
160
|
+
}
|
|
146
161
|
/** Build the tool set against a given relay transport. */
|
|
147
162
|
export function createTools(call) {
|
|
148
163
|
return [
|
|
@@ -298,6 +313,133 @@ export function createTools(call) {
|
|
|
298
313
|
return boundedTranscript(head, rendered, maxChars);
|
|
299
314
|
}
|
|
300
315
|
},
|
|
316
|
+
{
|
|
317
|
+
name: 'list_voice_calls',
|
|
318
|
+
description: 'List saved fleet voice calls on this Mac, newest first, with dates, previews and call_id values for read_voice_call. These transcripts are separate from Conductor chat history. Read-only; no live call or UI interaction.',
|
|
319
|
+
inputSchema: {
|
|
320
|
+
type: 'object',
|
|
321
|
+
properties: {
|
|
322
|
+
limit: { type: 'integer', description: 'Calls per page (default 20, max 50).' },
|
|
323
|
+
offset: {
|
|
324
|
+
type: 'integer',
|
|
325
|
+
description: 'Skip this many calls; use next_offset from the previous page (default 0).'
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
additionalProperties: false
|
|
329
|
+
},
|
|
330
|
+
run: async (args) => {
|
|
331
|
+
rejectUnknown(args, ['limit', 'offset']);
|
|
332
|
+
const limit = Math.min(50, Math.max(1, Math.floor(num(args.limit) ?? 20)));
|
|
333
|
+
const offset = Math.min(1_000_000, Math.max(0, Math.floor(num(args.offset) ?? 0)));
|
|
334
|
+
const params = new URLSearchParams({ limit: String(limit), offset: String(offset) });
|
|
335
|
+
const data = await call(`${routes.voiceHistory.path()}?${params}`);
|
|
336
|
+
if (!data.calls.length)
|
|
337
|
+
return 'No saved voice calls on this page. Only calls captured after transcript saving was enabled are available.';
|
|
338
|
+
return [
|
|
339
|
+
...data.calls.map(item => [...voiceCallHeader(item), clip(item.preview.replace(/\s+/g, ' '), 200)].join('\n')),
|
|
340
|
+
...(data.hasMore ? [`next_offset: ${offset + data.calls.length}`] : [])
|
|
341
|
+
].join('\n\n');
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
name: 'search_voice_calls',
|
|
346
|
+
description: 'Search caller and assistant text across saved fleet calls. Results include matching excerpts, call_id and item_id; pass those to read_voice_call as call_id and near to read surrounding decisions. Partial and interrupted text is labeled. Read-only; no UI interaction.',
|
|
347
|
+
inputSchema: {
|
|
348
|
+
type: 'object',
|
|
349
|
+
properties: {
|
|
350
|
+
query: {
|
|
351
|
+
type: 'string',
|
|
352
|
+
maxLength: 500,
|
|
353
|
+
description: 'Words ranked by relevance; quote an exact phrase. Uses the same query grammar as search_chats.'
|
|
354
|
+
},
|
|
355
|
+
call_id: { type: 'string', description: 'Optional: search only this saved call.' },
|
|
356
|
+
limit: { type: 'integer', description: 'Matching utterances per page (default 12, max 50).' },
|
|
357
|
+
offset: {
|
|
358
|
+
type: 'integer',
|
|
359
|
+
description: 'Skip this many hits; use next_offset from the previous page (default 0).'
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
required: ['query'],
|
|
363
|
+
additionalProperties: false
|
|
364
|
+
},
|
|
365
|
+
run: async (args) => {
|
|
366
|
+
rejectUnknown(args, ['query', 'call_id', 'limit', 'offset']);
|
|
367
|
+
const query = need(args, 'query');
|
|
368
|
+
if (query.length > 500)
|
|
369
|
+
throw new Error('query must be at most 500 characters');
|
|
370
|
+
const limit = Math.min(50, Math.max(1, Math.floor(num(args.limit) ?? 12)));
|
|
371
|
+
const offset = Math.min(1_000_000, Math.max(0, Math.floor(num(args.offset) ?? 0)));
|
|
372
|
+
const params = new URLSearchParams({ q: query, limit: String(limit), offset: String(offset) });
|
|
373
|
+
if (str(args.call_id))
|
|
374
|
+
params.set('callId', str(args.call_id));
|
|
375
|
+
const data = await call(`${routes.voiceSearch.path()}?${params}`);
|
|
376
|
+
if (!data.hits.length)
|
|
377
|
+
return `No saved voice transcript matches ${JSON.stringify(query)} on this page.`;
|
|
378
|
+
return [
|
|
379
|
+
...data.hits.map(hit => [
|
|
380
|
+
...voiceCallHeader(hit.call),
|
|
381
|
+
`item_id: ${hit.itemId} · ${new Date(hit.at).toISOString()}`,
|
|
382
|
+
`[${hit.role}]${voiceEntryFlags(hit)} ${clip(unmark(hit.snippet), 500)}`
|
|
383
|
+
].join('\n')),
|
|
384
|
+
...(data.hasMore ? [`next_offset: ${offset + data.hits.length}`] : [])
|
|
385
|
+
].join('\n\n');
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
name: 'read_voice_call',
|
|
390
|
+
description: 'Read a saved fleet-call transcript by call_id, with caller, orchestrator and tool activity in conversation order. Pass an item_id from search_voice_calls as near for surrounding context, or use older_item/newer_item from a previous read. Without near, reads the latest entries. Text can be clipped to max_chars; narrow the window or raise that budget to read more. Interrupted replies can include generated words the caller never heard. Read-only; no UI interaction.',
|
|
391
|
+
inputSchema: {
|
|
392
|
+
type: 'object',
|
|
393
|
+
properties: {
|
|
394
|
+
call_id: { type: 'string', description: 'From list_voice_calls or search_voice_calls.' },
|
|
395
|
+
near: { type: 'string', description: 'A transcript item_id from a search hit or previous read.' },
|
|
396
|
+
before: { type: 'integer', description: 'Entries before near (default 6, max 100).' },
|
|
397
|
+
after: { type: 'integer', description: 'Entries after near (default 6, max 100).' },
|
|
398
|
+
limit: { type: 'integer', description: 'Latest entries when near is omitted (default 20, max 200).' },
|
|
399
|
+
max_chars: { type: 'integer', description: 'Hard output budget (default 12000, min 1000, max 40000).' }
|
|
400
|
+
},
|
|
401
|
+
required: ['call_id'],
|
|
402
|
+
additionalProperties: false
|
|
403
|
+
},
|
|
404
|
+
run: async (args) => {
|
|
405
|
+
rejectUnknown(args, ['call_id', 'near', 'before', 'after', 'limit', 'max_chars']);
|
|
406
|
+
const callId = need(args, 'call_id');
|
|
407
|
+
const data = await call(routes.voiceTranscript.path(callId));
|
|
408
|
+
const entries = data.entries.filter(entry => entry.role !== 'relay');
|
|
409
|
+
const near = str(args.near);
|
|
410
|
+
const anchor = near ? entries.findIndex(entry => entry.id === near) : -1;
|
|
411
|
+
if (near && anchor === -1)
|
|
412
|
+
throw new Error('near item is not in that saved call');
|
|
413
|
+
const count = (value, fallback, max) => Math.min(max, Math.max(0, Math.floor(num(value) ?? fallback)));
|
|
414
|
+
const limit = Math.max(1, count(args.limit, 20, 200));
|
|
415
|
+
let start = near ? Math.max(0, anchor - count(args.before, 6, 100)) : Math.max(0, entries.length - limit);
|
|
416
|
+
let end = near ? Math.min(entries.length, anchor + count(args.after, 6, 100) + 1) : entries.length;
|
|
417
|
+
const maxChars = Math.max(1_000, count(args.max_chars, 12_000, 40_000));
|
|
418
|
+
const heading = (entry) => `[${entry.role}] item_id: ${entry.id} · ${new Date(entry.at).toISOString()}${voiceEntryFlags(entry)}\n`;
|
|
419
|
+
// Keep identities and caveats readable even for a tiny budget. Shrink the
|
|
420
|
+
// window around its anchor, then advertise the omitted sides for paging.
|
|
421
|
+
while (end - start > 1) {
|
|
422
|
+
const minRow = Math.max(...entries.slice(start, end).map(entry => heading(entry).length)) + 80;
|
|
423
|
+
if (voiceCallHeader(data).join('\n').length + 240 + (end - start) * (minRow + 2) <= maxChars)
|
|
424
|
+
break;
|
|
425
|
+
if (!near || anchor - start > end - anchor - 1)
|
|
426
|
+
start += 1;
|
|
427
|
+
else
|
|
428
|
+
end -= 1;
|
|
429
|
+
}
|
|
430
|
+
const selected = entries.slice(start, end);
|
|
431
|
+
const head = [
|
|
432
|
+
...voiceCallHeader(data),
|
|
433
|
+
`Showing ${selected.length} of ${entries.length} entries.`,
|
|
434
|
+
...(start > 0 && selected[0] ? [`older_item: ${selected[0].id} (use as near with before > 0)`] : []),
|
|
435
|
+
...(end < entries.length && selected.at(-1)
|
|
436
|
+
? [`newer_item: ${selected.at(-1).id} (use as near with after > 0)`]
|
|
437
|
+
: [])
|
|
438
|
+
];
|
|
439
|
+
const rendered = selected.map(entry => `${heading(entry)}${entry.text}`);
|
|
440
|
+
return boundedTranscript(head, rendered, maxChars);
|
|
441
|
+
}
|
|
442
|
+
},
|
|
301
443
|
{
|
|
302
444
|
name: 'list_workspaces',
|
|
303
445
|
description: 'List the live (non-archived) Conductor workspaces with what each one is doing right now: agent status, model, branch, PR state, and any prompt the relay is still holding for it. Use this to see what is running before starting or steering anything.',
|
package/dist-node/src/routes.js
CHANGED
|
@@ -60,6 +60,10 @@ export const routes = {
|
|
|
60
60
|
voiceCallReady: param('POST', '/api/voice/calls/:callId/ready'),
|
|
61
61
|
/** End one PWA-owned call. SIP calls remain owned by their phone leg. */
|
|
62
62
|
voiceCallEnd: param('DELETE', '/api/voice/calls/:callId'),
|
|
63
|
+
/** Durable call history remains readable even when voice is no longer configured. */
|
|
64
|
+
voiceHistory: flat('GET', '/api/voice/history'),
|
|
65
|
+
voiceTranscript: param('GET', '/api/voice/history/:callId'),
|
|
66
|
+
voiceSearch: flat('GET', '/api/voice/search'),
|
|
63
67
|
repoIcon: param('GET', '/api/repos/:repo/icon'),
|
|
64
68
|
/** A local image linked in chat Markdown, fetched with the phone's auth header. */
|
|
65
69
|
localImage: param('GET', '/api/local-images/:path'),
|
package/dist-node/src/server.js
CHANGED
|
@@ -48,6 +48,7 @@ import { VoiceBroker } from "./voice/broker.js";
|
|
|
48
48
|
import { openAIOriginForSipHost, readVoiceConfig, voicePort } from "./voice/config.js";
|
|
49
49
|
import { parseVoiceCallTarget, readVoiceChatContext, VoiceContextError } from "./voice/context.js";
|
|
50
50
|
import { createVoiceGateway } from "./voice/gateway.js";
|
|
51
|
+
import { MAX_VOICE_SEARCH_CHARS, VoiceHistory } from "./voice/history.js";
|
|
51
52
|
import { PreviewStore } from "./voice/preview.js";
|
|
52
53
|
import { createVoiceServer } from "./voice/server.js";
|
|
53
54
|
import { mintSipTicket, missingTicketConfig } from "./voice/ticket.js";
|
|
@@ -208,6 +209,8 @@ const voiceConfig = readVoiceConfig();
|
|
|
208
209
|
const voiceSafetyIdentifier = crypto.createHash('sha256').update(`conductor-remote:${cfg.token}`).digest('hex');
|
|
209
210
|
const voiceBoards = new Map();
|
|
210
211
|
const voicePreviews = new PreviewStore(path.join(stateDir(), 'voice-previews.json'));
|
|
212
|
+
const voiceHistory = new VoiceHistory(path.join(stateDir(), 'voice-history.db'));
|
|
213
|
+
process.on('exit', () => voiceHistory.close());
|
|
211
214
|
const voiceBroker = voiceConfig.openaiKey
|
|
212
215
|
? new VoiceBroker({
|
|
213
216
|
apiKey: voiceConfig.openaiKey,
|
|
@@ -217,6 +220,7 @@ const voiceBroker = voiceConfig.openaiKey
|
|
|
217
220
|
mcpUrl: voiceConfig.publicBaseUrl ? `${voiceConfig.publicBaseUrl}/mcp` : null,
|
|
218
221
|
mcpToken: voiceConfig.mcpToken,
|
|
219
222
|
stateFile: path.join(stateDir(), 'voice-calls.json'),
|
|
223
|
+
history: voiceHistory,
|
|
220
224
|
tools: callId => voiceToolsForCall(callId),
|
|
221
225
|
onClose: callId => voiceBoards.delete(callId)
|
|
222
226
|
})
|
|
@@ -2604,6 +2608,36 @@ const server = http.createServer(async (req, res) => {
|
|
|
2604
2608
|
}
|
|
2605
2609
|
});
|
|
2606
2610
|
}
|
|
2611
|
+
const voiceTranscript = routeParam(routes.voiceTranscript, req.method, pathname);
|
|
2612
|
+
if (isRoute(routes.voiceHistory, req.method, pathname) ||
|
|
2613
|
+
isRoute(routes.voiceSearch, req.method, pathname) ||
|
|
2614
|
+
voiceTranscript) {
|
|
2615
|
+
try {
|
|
2616
|
+
if (isRoute(routes.voiceSearch, req.method, pathname)) {
|
|
2617
|
+
const query = url.searchParams.get('q')?.trim() ?? '';
|
|
2618
|
+
if (!query || query.length > MAX_VOICE_SEARCH_CHARS)
|
|
2619
|
+
return json(req, res, 400, { error: `q must contain 1–${MAX_VOICE_SEARCH_CHARS} characters` });
|
|
2620
|
+
return json(req, res, 200, voiceHistory.search(query, {
|
|
2621
|
+
limit: Math.max(1, Math.min(50, Number(url.searchParams.get('limit')) || 12)),
|
|
2622
|
+
offset: Math.max(0, Math.min(1_000_000, Number(url.searchParams.get('offset')) || 0)),
|
|
2623
|
+
callId: url.searchParams.get('callId') || undefined
|
|
2624
|
+
}));
|
|
2625
|
+
}
|
|
2626
|
+
if (!voiceTranscript) {
|
|
2627
|
+
const limit = Math.max(1, Math.min(100, Number(url.searchParams.get('limit')) || 30));
|
|
2628
|
+
const offset = Math.max(0, Math.min(1_000_000, Number(url.searchParams.get('offset')) || 0));
|
|
2629
|
+
return json(req, res, 200, voiceHistory.list(Math.floor(limit), Math.floor(offset)));
|
|
2630
|
+
}
|
|
2631
|
+
const call = url.searchParams.get('summary') === '1'
|
|
2632
|
+
? voiceHistory.status(voiceTranscript)
|
|
2633
|
+
: voiceHistory.read(voiceTranscript);
|
|
2634
|
+
return call ? json(req, res, 200, call) : json(req, res, 404, { error: 'Saved voice call not found' });
|
|
2635
|
+
}
|
|
2636
|
+
catch (error) {
|
|
2637
|
+
console.warn('[voice] could not read call history:', error);
|
|
2638
|
+
return json(req, res, 503, { error: 'Call history is unavailable. Check the relay logs.' });
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2607
2641
|
// POST /api/voice/ticket — the native app presents the same relay bearer as
|
|
2608
2642
|
// the PWA, and receives only a two-minute SIP URI. The OpenAI key, webhook
|
|
2609
2643
|
// secret and marker key never leave this Mac.
|
|
@@ -2644,7 +2678,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
2644
2678
|
language: body.language,
|
|
2645
2679
|
context
|
|
2646
2680
|
}, voiceSafetyIdentifier);
|
|
2647
|
-
voiceBroker.registerWebRtc(call.callId);
|
|
2681
|
+
voiceBroker.registerWebRtc(call.callId, { voice: body.voice, language: body.language });
|
|
2648
2682
|
return json(req, res, 200, call);
|
|
2649
2683
|
}
|
|
2650
2684
|
catch (err) {
|
|
@@ -3841,6 +3875,8 @@ server.listen(cfg.port, cfg.host, () => {
|
|
|
3841
3875
|
voiceServer.listen(voicePort(), '127.0.0.1', () => {
|
|
3842
3876
|
console.info(` voice: 127.0.0.1:${voicePort()}${voiceBroker ? '' : ' (waiting for OpenAI config)'}`);
|
|
3843
3877
|
void voiceBroker?.restore();
|
|
3878
|
+
if (!voiceBroker)
|
|
3879
|
+
voiceHistory.recover();
|
|
3844
3880
|
});
|
|
3845
3881
|
if (orchestration.writable) {
|
|
3846
3882
|
setInterval(() => orchestration.heartbeatRelayInstance(relayIdentity), 2_000).unref();
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/** OpenAI SIP/WebRTC setup plus the authenticated sideband controller for one live call. */
|
|
2
|
+
import crypto from 'node:crypto';
|
|
2
3
|
import fs from 'node:fs';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import { VOICE_INSTRUCTIONS } from "./prompt.js";
|
|
5
6
|
import { VOICE_TOOL_NAMES } from "./tools.js";
|
|
7
|
+
import { voiceTranscription } from "./transcription.js";
|
|
6
8
|
/** Current Realtime call-accept shape, kept pure so upstream API drift has a snapshot-sized test. */
|
|
7
9
|
export function buildAcceptBody(input) {
|
|
8
10
|
return {
|
|
@@ -10,7 +12,7 @@ export function buildAcceptBody(input) {
|
|
|
10
12
|
model: input.model,
|
|
11
13
|
instructions: input.instructions,
|
|
12
14
|
max_output_tokens: 800,
|
|
13
|
-
audio: { output: { voice: input.voice } },
|
|
15
|
+
audio: { input: { transcription: voiceTranscription(input.language) }, output: { voice: input.voice } },
|
|
14
16
|
tools: [
|
|
15
17
|
{
|
|
16
18
|
type: 'mcp',
|
|
@@ -122,6 +124,7 @@ export class VoiceBroker {
|
|
|
122
124
|
callId,
|
|
123
125
|
model: this.deps.model,
|
|
124
126
|
voice: options.voice ?? this.deps.voice,
|
|
127
|
+
language: options.language,
|
|
125
128
|
mcpUrl: this.deps.mcpUrl,
|
|
126
129
|
mcpToken: this.deps.mcpToken,
|
|
127
130
|
instructions: options.instructions ?? this.deps.instructions ?? VOICE_INSTRUCTIONS
|
|
@@ -137,6 +140,14 @@ export class VoiceBroker {
|
|
|
137
140
|
greeted: false
|
|
138
141
|
});
|
|
139
142
|
this.persist();
|
|
143
|
+
this.deps.history?.start({
|
|
144
|
+
callId,
|
|
145
|
+
startedAt: this.now(),
|
|
146
|
+
transport: 'sip',
|
|
147
|
+
model: this.deps.model,
|
|
148
|
+
voice: options.voice ?? this.deps.voice,
|
|
149
|
+
language: options.language ?? 'auto'
|
|
150
|
+
});
|
|
140
151
|
this.attach(callId);
|
|
141
152
|
}
|
|
142
153
|
async reject(callId, statusCode = 603) {
|
|
@@ -150,8 +161,18 @@ export class VoiceBroker {
|
|
|
150
161
|
}
|
|
151
162
|
/** Reattach every call whose socket was alive when a self-update stopped this process. */
|
|
152
163
|
async restore() {
|
|
153
|
-
|
|
154
|
-
|
|
164
|
+
this.deps.history?.recover();
|
|
165
|
+
for (const call of this.calls.values()) {
|
|
166
|
+
this.deps.history?.start({
|
|
167
|
+
callId: call.callId,
|
|
168
|
+
startedAt: call.acceptedAt,
|
|
169
|
+
transport: call.mode === 'function' ? 'webrtc' : 'sip',
|
|
170
|
+
model: this.deps.model,
|
|
171
|
+
voice: this.deps.voice,
|
|
172
|
+
language: 'auto'
|
|
173
|
+
}, true);
|
|
174
|
+
this.attach(call.callId);
|
|
175
|
+
}
|
|
155
176
|
}
|
|
156
177
|
attach(callId) {
|
|
157
178
|
if (this.runtimes.has(callId))
|
|
@@ -163,6 +184,7 @@ export class VoiceBroker {
|
|
|
163
184
|
authorization: `Bearer ${this.deps.apiKey}`
|
|
164
185
|
});
|
|
165
186
|
const runtime = {
|
|
187
|
+
callId,
|
|
166
188
|
socket,
|
|
167
189
|
mode: call.mode,
|
|
168
190
|
ready: call.ready,
|
|
@@ -186,10 +208,11 @@ export class VoiceBroker {
|
|
|
186
208
|
});
|
|
187
209
|
socket.addEventListener('message', event => this.onEvent(callId, runtime, messageText(event.data)));
|
|
188
210
|
socket.addEventListener('error', () => this.log(`[voice] ${callId} observer socket error`));
|
|
189
|
-
socket.addEventListener('close',
|
|
211
|
+
socket.addEventListener('close', event => {
|
|
190
212
|
if (this.runtimes.get(callId) !== runtime)
|
|
191
213
|
return;
|
|
192
214
|
this.forget(callId, runtime);
|
|
215
|
+
this.deps.history?.finish(callId, event.code === 1000 ? 'ended' : 'interrupted');
|
|
193
216
|
this.log(`[voice] ${callId} observer closed`);
|
|
194
217
|
});
|
|
195
218
|
this.maybeStart(runtime);
|
|
@@ -229,9 +252,11 @@ export class VoiceBroker {
|
|
|
229
252
|
const text = runtime.pending.shift();
|
|
230
253
|
if (!text)
|
|
231
254
|
return;
|
|
255
|
+
const itemId = `relay_${crypto.randomBytes(10).toString('hex')}`;
|
|
256
|
+
this.deps.history?.internal(runtime.callId, itemId);
|
|
232
257
|
this.send(runtime, {
|
|
233
258
|
type: 'conversation.item.create',
|
|
234
|
-
item: { type: 'message', role: 'user', content: [{ type: 'input_text', text }] }
|
|
259
|
+
item: { id: itemId, type: 'message', role: 'user', content: [{ type: 'input_text', text }] }
|
|
235
260
|
});
|
|
236
261
|
this.createResponse(runtime);
|
|
237
262
|
}
|
|
@@ -319,6 +344,7 @@ export class VoiceBroker {
|
|
|
319
344
|
this.log(`[voice] ${callId} sent an unreadable observer event`);
|
|
320
345
|
return;
|
|
321
346
|
}
|
|
347
|
+
this.deps.history?.record(callId, event);
|
|
322
348
|
const type = event.type;
|
|
323
349
|
if (type === 'mcp_list_tools.completed') {
|
|
324
350
|
if (runtime.mode !== 'mcp')
|
|
@@ -390,7 +416,7 @@ export class VoiceBroker {
|
|
|
390
416
|
}
|
|
391
417
|
}
|
|
392
418
|
/** Attach the relay sideband before the browser receives its SDP answer. */
|
|
393
|
-
registerWebRtc(callId) {
|
|
419
|
+
registerWebRtc(callId, options = {}) {
|
|
394
420
|
this.calls.set(callId, {
|
|
395
421
|
callId,
|
|
396
422
|
acceptedAt: this.now(),
|
|
@@ -399,6 +425,14 @@ export class VoiceBroker {
|
|
|
399
425
|
greeted: false
|
|
400
426
|
});
|
|
401
427
|
this.persist();
|
|
428
|
+
this.deps.history?.start({
|
|
429
|
+
callId,
|
|
430
|
+
startedAt: this.now(),
|
|
431
|
+
transport: 'webrtc',
|
|
432
|
+
model: this.deps.model,
|
|
433
|
+
voice: options.voice ?? this.deps.voice,
|
|
434
|
+
language: options.language ?? 'auto'
|
|
435
|
+
});
|
|
402
436
|
this.attach(callId);
|
|
403
437
|
}
|
|
404
438
|
/** The browser calls this only after it has installed the remote SDP answer. */
|
|
@@ -425,11 +459,14 @@ export class VoiceBroker {
|
|
|
425
459
|
headers: { authorization: `Bearer ${this.deps.apiKey}` }
|
|
426
460
|
});
|
|
427
461
|
const runtime = this.runtimes.get(callId);
|
|
462
|
+
// Retire the observer before closing it: a synchronous close callback must
|
|
463
|
+
// not label this deliberate hang-up as a missing stretch of conversation.
|
|
464
|
+
this.forget(callId, runtime);
|
|
428
465
|
try {
|
|
429
466
|
runtime?.socket.close();
|
|
430
467
|
}
|
|
431
468
|
finally {
|
|
432
|
-
this.
|
|
469
|
+
this.deps.history?.finish(callId, response.ok ? 'ended' : 'interrupted');
|
|
433
470
|
}
|
|
434
471
|
if (!response.ok)
|
|
435
472
|
throw new Error(`OpenAI call hangup returned ${response.status}: ${await response.text()}`);
|