conductor-remote 1.78.0 → 1.79.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 +2 -2
- package/dist/assets/index-CV2YpJf7.js +47 -0
- package/dist/assets/index-DaafT1eA.css +1 -0
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/dist-node/src/background-tasks.js +2 -1
- package/dist-node/src/conductor.applescript +153 -25
- package/dist-node/src/mcp-tools.js +36 -5
- package/dist-node/src/model-cache.js +20 -2
- package/dist-node/src/routes.js +2 -0
- package/dist-node/src/server.js +31 -3
- package/dist-node/src/shared.js +13 -0
- package/dist-node/src/writes.js +49 -7
- package/package.json +1 -1
- package/dist/assets/index-4cxcZbZe.js +0 -47
- package/dist/assets/index-BoeZwP2N.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-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;--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-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;--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:#0a0b0e;--color-surface:#14161b;--color-surface-2:#1b1e26;--color-border:#262a33;--color-border-soft:#1e222a;--color-text:#e7e9ee;--color-muted:#8b909d;--color-faint:#5c616d;--color-accent:#8b7dff;--color-accent-soft:#2a2650;--color-working:#f5a623;--color-idle:#3ecf8e;--color-done:#5b9dff;--color-pr-merged:#ac47ff;--color-pr-draft:#a4a3a2;--color-pr-attention:#facc15;--color-pr-mergeable:#49de80;--color-add:#3ecf8e;--color-del:#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{background:var(--color-bg)}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-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:#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{top:0}.top-0\.5{top:calc(var(--spacing) * .5)}.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-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{left:0}.left-0\.5{left:calc(var(--spacing) * .5)}.left-3{left:calc(var(--spacing) * 3)}.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-\[60\]{z-index:60}.col-span-3{grid-column:span 3/span 3}.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)}.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)}.-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)}.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)}.-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-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}.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-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-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-\[18px\]{width:18px;height:18px}.size-full{width:100%;height:100%}.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-12{height:calc(var(--spacing) * 12)}.h-\[15px\]{height:15px}.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}.min-h-0{min-height:0}.min-h-14{min-height:calc(var(--spacing) * 14)}.w-0\.5{width:calc(var(--spacing) * .5)}.w-1{width:var(--spacing)}.w-5{width:calc(var(--spacing) * 5)}.w-9{width:calc(var(--spacing) * 9)}.w-11{width:calc(var(--spacing) * 11)}.w-12{width:calc(var(--spacing) * 12)}.w-56{width:calc(var(--spacing) * 56)}.w-60{width:calc(var(--spacing) * 60)}.w-64{width:calc(var(--spacing) * 64)}.w-\[85\%\]{width:85%}.w-full{width:100%}.max-w-36{max-width:calc(var(--spacing) * 36)}.max-w-40{max-width:calc(var(--spacing) * 40)}.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-\[55vw\]{max-width:55vw}.max-w-\[70vw\]{max-width:70vw}.max-w-\[85\%\]{max-width:85%}.max-w-\[85vw\]{max-width:85vw}.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-xs{max-width:var(--container-xs)}.min-w-0{min-width:0}.min-w-5{min-width:calc(var(--spacing) * 5)}.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-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-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-none{resize:none}.scrollbar-thin{scrollbar-width:thin}.list-none{list-style-type:none}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.grid-cols-\[minmax\(0\,1fr\)_auto_auto\]{grid-template-columns:minmax(0,1fr) auto auto}.grid-cols-subgrid{grid-template-columns:subgrid}.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)))}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-y-1{row-gap:var(--spacing)}.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)}.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:#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-del\/30{border-color:#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:#ff6b6b66}@supports (color:color-mix(in lab,red,red)){.border-del\/40{border-color:color-mix(in oklab,var(--color-del) 40%,transparent)}}.border-faint{border-color:var(--color-faint)}.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-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:#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:#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:#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:#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:#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:#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\/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\/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-current{background-color:currentColor}.bg-del{background-color:var(--color-del)}.bg-del\/5{background-color:#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:#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:#ff6b6b26}@supports (color:color-mix(in lab,red,red)){.bg-del\/15{background-color:color-mix(in oklab,var(--color-del) 15%,transparent)}}.bg-pr-merged\/10{background-color:#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:#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:#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:#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:#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:#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\/95{background-color:#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-white{background-color:var(--color-white)}.bg-working{background-color:var(--color-working)}.bg-working\/10{background-color:#f5a6231a}@supports (color:color-mix(in lab,red,red)){.bg-working\/10{background-color:color-mix(in oklab,var(--color-working) 10%,transparent)}}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-0{padding:0}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.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-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-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)}.pr-1{padding-right:var(--spacing)}.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-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}.font-mono{font-family:var(--font-mono)}.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-\[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-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-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-del{color:var(--color-del)}.text-del\/80{color:#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-pr-merged{color:var(--color-pr-merged)}.text-text{color:var(--color-text)}.text-white{color:var(--color-white)}.text-working{color:var(--color-working)}.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-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-\[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-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{--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-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-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}.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\:underline:hover{text-decoration-line:underline}}.focus\:border-accent\/50:focus{border-color:#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\:outline-none:focus{--tw-outline-style:none;outline-style:none}.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)}.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\.985\]:active{scale:.985}.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-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-80:active{opacity:.8}.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:#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-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:#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:400px){.min-\[400px\]\:block{display:block}}@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\: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\: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-\[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\:static{position:static}.lg\:z-auto{z-index:auto}.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-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)}}
|
package/dist/index.html
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
<title>Conductor Remote</title>
|
|
14
14
|
<!-- Runs before the module bundle so it can catch a stale shell that fails to boot. -->
|
|
15
15
|
<script src="/self-heal.js"></script>
|
|
16
|
-
<script type="module" crossorigin src="/assets/index-
|
|
17
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
16
|
+
<script type="module" crossorigin src="/assets/index-CV2YpJf7.js"></script>
|
|
17
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DaafT1eA.css">
|
|
18
18
|
<link rel="manifest" href="/manifest.webmanifest"></head>
|
|
19
19
|
<body>
|
|
20
20
|
<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 o=e||("document"in self?document.currentScript.src:"")||location.href;if(s[o])return;let
|
|
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 o=e||("document"in self?document.currentScript.src:"")||location.href;if(s[o])return;let l={};const c=e=>i(e,o),t={module:{uri:o},exports:l,require:c};s[o]=Promise.all(n.map(e=>t[e]||c(e))).then(e=>(r(...e),l))}}define(["./workbox-9c191d2f"],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:"aa274c71195357e8140bfef5bf26f868"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/index-DaafT1eA.css",revision:null},{url:"assets/index-CV2YpJf7.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\//]}))});
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import { execFile } from 'node:child_process';
|
|
28
28
|
import { promisify } from 'node:util';
|
|
29
|
+
import { timestampMs } from "./shared.js";
|
|
29
30
|
const exec = promisify(execFile);
|
|
30
31
|
const str = (v) => (typeof v === 'string' && v.trim() ? v.trim() : undefined);
|
|
31
32
|
/**
|
|
@@ -55,7 +56,7 @@ export function openBackgroundTasks(rows, processStartedAt) {
|
|
|
55
56
|
open.delete(taskId);
|
|
56
57
|
}
|
|
57
58
|
else if (frame.subtype === 'task_started') {
|
|
58
|
-
if (
|
|
59
|
+
if (timestampMs(row.created_at) < processStartedAt)
|
|
59
60
|
continue;
|
|
60
61
|
const taskType = str(frame.task_type) ?? 'task';
|
|
61
62
|
open.set(taskId, {
|
|
@@ -1447,6 +1447,141 @@ on pickerShowsModel(popup, wanted)
|
|
|
1447
1447
|
return false
|
|
1448
1448
|
end pickerShowsModel
|
|
1449
1449
|
|
|
1450
|
+
on modelMenuItem(wanted)
|
|
1451
|
+
-- Resolve one model from the picker that is already open. The menu can append
|
|
1452
|
+
-- `NEW` to a freshly released model while the relay deliberately exposes the
|
|
1453
|
+
-- stable name without it, so the same unique-prefix rule as setModel applies.
|
|
1454
|
+
set chosen to missing value
|
|
1455
|
+
set loose to {}
|
|
1456
|
+
set wa to my webArea()
|
|
1457
|
+
tell application "System Events" to tell process "Conductor"
|
|
1458
|
+
repeat with m in (get UI elements of wa whose role is "AXMenu")
|
|
1459
|
+
repeat with mi in (get UI elements of m whose role is "AXMenuItem")
|
|
1460
|
+
set label to my firstLine(my tabLabel(mi))
|
|
1461
|
+
if label is wanted then
|
|
1462
|
+
set chosen to contents of mi
|
|
1463
|
+
else if label starts with wanted then
|
|
1464
|
+
set end of loose to contents of mi
|
|
1465
|
+
end if
|
|
1466
|
+
end repeat
|
|
1467
|
+
end repeat
|
|
1468
|
+
end tell
|
|
1469
|
+
if chosen is missing value and (count of loose) is 1 then set chosen to item 1 of loose
|
|
1470
|
+
if chosen is missing value then
|
|
1471
|
+
if (count of loose) > 1 then error "several models match " & wanted
|
|
1472
|
+
error "no model named " & wanted
|
|
1473
|
+
end if
|
|
1474
|
+
return chosen
|
|
1475
|
+
end modelMenuItem
|
|
1476
|
+
|
|
1477
|
+
on modelDefaultButton(menuItem)
|
|
1478
|
+
-- Every non-default row has a child star button named "Set <model> as
|
|
1479
|
+
-- default and select". The starred row has no button at all. Read the role and
|
|
1480
|
+
-- label together so an unrelated control a future picker grows cannot be
|
|
1481
|
+
-- mistaken for a global preference write.
|
|
1482
|
+
repeat with childNode in my axKids(menuItem)
|
|
1483
|
+
set childEl to contents of childNode
|
|
1484
|
+
if (my axRole(childEl)) is "AXButton" and (my axName(childEl)) contains " as default" then return childEl
|
|
1485
|
+
end repeat
|
|
1486
|
+
return missing value
|
|
1487
|
+
end modelDefaultButton
|
|
1488
|
+
|
|
1489
|
+
on modelMenuItems()
|
|
1490
|
+
set found to {}
|
|
1491
|
+
set wa to my webArea()
|
|
1492
|
+
tell application "System Events" to tell process "Conductor"
|
|
1493
|
+
repeat with m in (get UI elements of wa whose role is "AXMenu")
|
|
1494
|
+
set found to found & (get UI elements of m whose role is "AXMenuItem")
|
|
1495
|
+
end repeat
|
|
1496
|
+
end tell
|
|
1497
|
+
return found
|
|
1498
|
+
end modelMenuItems
|
|
1499
|
+
|
|
1500
|
+
on defaultModelInOpenPicker()
|
|
1501
|
+
-- The selected star is exposed by *removing* the star button from that row.
|
|
1502
|
+
-- Require exactly one such row. If managed settings disable every star, or a
|
|
1503
|
+
-- Conductor release changes this tree, failing closed is safer than reporting
|
|
1504
|
+
-- that whichever model was requested became the user's global default.
|
|
1505
|
+
set defaults to {}
|
|
1506
|
+
repeat with mi in my modelMenuItems()
|
|
1507
|
+
set menuItem to contents of mi
|
|
1508
|
+
if (my modelDefaultButton(menuItem)) is missing value then set end of defaults to my firstLine(my tabLabel(menuItem))
|
|
1509
|
+
end repeat
|
|
1510
|
+
if (count of defaults) is not 1 then error "couldn't identify Conductor's default model"
|
|
1511
|
+
return item 1 of defaults
|
|
1512
|
+
end defaultModelInOpenPicker
|
|
1513
|
+
|
|
1514
|
+
on modelPickerButton()
|
|
1515
|
+
set popup to missing value
|
|
1516
|
+
repeat with entry in my composerControls()
|
|
1517
|
+
set c to contents of entry
|
|
1518
|
+
if my tabLabel(c) contains "Change agent" then set popup to c
|
|
1519
|
+
end repeat
|
|
1520
|
+
if popup is missing value then error "couldn't find the model picker"
|
|
1521
|
+
return popup
|
|
1522
|
+
end modelPickerButton
|
|
1523
|
+
|
|
1524
|
+
on openModelPicker()
|
|
1525
|
+
set popup to my modelPickerButton()
|
|
1526
|
+
tell application "System Events" to tell process "Conductor"
|
|
1527
|
+
perform action "AXPress" of popup
|
|
1528
|
+
end tell
|
|
1529
|
+
delay 1.0
|
|
1530
|
+
end openModelPicker
|
|
1531
|
+
|
|
1532
|
+
on setDefaultModel(wanted)
|
|
1533
|
+
-- Conductor's star is one combined action: its accessible name is "Set … as
|
|
1534
|
+
-- default and select". Mirror that rather than pretending this only changes a
|
|
1535
|
+
-- preference — the target chat switches model too, and the picker label is
|
|
1536
|
+
-- read back below as the receipt for that half.
|
|
1537
|
+
set initialPopup to my modelPickerButton()
|
|
1538
|
+
set alreadySelected to my pickerShowsModel(initialPopup, wanted)
|
|
1539
|
+
tell application "System Events" to tell process "Conductor"
|
|
1540
|
+
perform action "AXPress" of initialPopup
|
|
1541
|
+
end tell
|
|
1542
|
+
delay 1.0
|
|
1543
|
+
try
|
|
1544
|
+
set chosen to my modelMenuItem(wanted)
|
|
1545
|
+
set chosenLabel to my firstLine(my tabLabel(chosen))
|
|
1546
|
+
set currentDefault to my defaultModelInOpenPicker()
|
|
1547
|
+
if currentDefault is chosenLabel then
|
|
1548
|
+
if alreadySelected then
|
|
1549
|
+
tell application "System Events" to key code 53
|
|
1550
|
+
return chosenLabel
|
|
1551
|
+
end if
|
|
1552
|
+
-- The star is already selected, but this chat is not. Its row is now
|
|
1553
|
+
-- the remaining half of Conductor's combined action.
|
|
1554
|
+
tell application "System Events" to tell process "Conductor"
|
|
1555
|
+
perform action "AXPress" of chosen
|
|
1556
|
+
end tell
|
|
1557
|
+
delay 0.8
|
|
1558
|
+
set selectedPopup to my modelPickerButton()
|
|
1559
|
+
if not my pickerShowsModel(selectedPopup, chosenLabel) then error "the model didn't switch to " & chosenLabel
|
|
1560
|
+
return chosenLabel
|
|
1561
|
+
end if
|
|
1562
|
+
set starButton to my modelDefaultButton(chosen)
|
|
1563
|
+
if starButton is missing value then error "the default-model star is missing for " & chosenLabel
|
|
1564
|
+
tell application "System Events" to tell process "Conductor"
|
|
1565
|
+
perform action "AXPress" of starButton
|
|
1566
|
+
end tell
|
|
1567
|
+
delay 0.8
|
|
1568
|
+
set selectedPopup to my modelPickerButton()
|
|
1569
|
+
if not my pickerShowsModel(selectedPopup, chosenLabel) then error "the model didn't switch to " & chosenLabel
|
|
1570
|
+
-- Re-open and read the star back. Pressing is fire-and-forget; the only safe
|
|
1571
|
+
-- success is the requested row becoming the unique one with no star button.
|
|
1572
|
+
my openModelPicker()
|
|
1573
|
+
set verified to my modelMenuItem(wanted)
|
|
1574
|
+
set verifiedLabel to my firstLine(my tabLabel(verified))
|
|
1575
|
+
set currentDefault to my defaultModelInOpenPicker()
|
|
1576
|
+
tell application "System Events" to key code 53
|
|
1577
|
+
if currentDefault is not verifiedLabel then error "Conductor didn't mark " & verifiedLabel & " as the default model"
|
|
1578
|
+
return verifiedLabel
|
|
1579
|
+
on error errText number errNum
|
|
1580
|
+
tell application "System Events" to key code 53
|
|
1581
|
+
error errText number errNum
|
|
1582
|
+
end try
|
|
1583
|
+
end setDefaultModel
|
|
1584
|
+
|
|
1450
1585
|
on setModel(wanted)
|
|
1451
1586
|
set popup to missing value
|
|
1452
1587
|
repeat with entry in my composerControls()
|
|
@@ -1499,32 +1634,25 @@ end setModel
|
|
|
1499
1634
|
|
|
1500
1635
|
on listModels()
|
|
1501
1636
|
-- Enumerate the picker rather than hard-coding a model list that would rot on
|
|
1502
|
-
-- every Conductor release.
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
tell application "System Events" to tell process "Conductor"
|
|
1510
|
-
perform action "AXPress" of popup
|
|
1511
|
-
end tell
|
|
1512
|
-
delay 1.0
|
|
1513
|
-
set labels to {}
|
|
1514
|
-
set wa to my webArea()
|
|
1515
|
-
tell application "System Events" to tell process "Conductor"
|
|
1516
|
-
repeat with m in (get UI elements of wa whose role is "AXMenu")
|
|
1517
|
-
repeat with mi in (get UI elements of m whose role is "AXMenuItem")
|
|
1518
|
-
set end of labels to my firstLine(my tabLabel(mi))
|
|
1519
|
-
end repeat
|
|
1637
|
+
-- every Conductor release. The first tagged line carries the unique starred
|
|
1638
|
+
-- row, followed by the ordinary labels. Opens the menu, reads, closes it again.
|
|
1639
|
+
my openModelPicker()
|
|
1640
|
+
try
|
|
1641
|
+
set labels to {}
|
|
1642
|
+
repeat with mi in my modelMenuItems()
|
|
1643
|
+
set end of labels to my firstLine(my tabLabel(mi))
|
|
1520
1644
|
end repeat
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1645
|
+
set defaultLabel to my defaultModelInOpenPicker()
|
|
1646
|
+
tell application "System Events" to key code 53
|
|
1647
|
+
set saved to AppleScript's text item delimiters
|
|
1648
|
+
set AppleScript's text item delimiters to linefeed
|
|
1649
|
+
set joined to labels as text
|
|
1650
|
+
set AppleScript's text item delimiters to saved
|
|
1651
|
+
return "__CONDUCTOR_DEFAULT_MODEL__" & tab & defaultLabel & linefeed & joined
|
|
1652
|
+
on error errText number errNum
|
|
1653
|
+
tell application "System Events" to key code 53
|
|
1654
|
+
error errText number errNum
|
|
1655
|
+
end try
|
|
1528
1656
|
end listModels
|
|
1529
1657
|
|
|
1530
1658
|
on applyAgentOptions()
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
*/
|
|
28
28
|
import { chatCursor, parseChatCursor } from "./chat-cursor.js";
|
|
29
29
|
import { routes } from "./routes.js";
|
|
30
|
-
import { HIT_CLOSE, HIT_OPEN, isToolResult, workspaceTitle } from "./shared.js";
|
|
30
|
+
import { HIT_CLOSE, HIT_OPEN, isToolResult, timestampMs, workspaceTitle } from "./shared.js";
|
|
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. create_workspace opens its workspace link without direct UI control; requested agent settings and the first prompt are applied later through Conductor’s UI. dismiss_prompt, keep_awake and relay_logs touch no UI. send_prompt, split_chat, stop_turn, set_agent_options, a live list_models call, set_workspace_status and archive_workspace drive the real Mac UI and steal focus for a few seconds — confirm with the user before using them on a chat 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. create_workspace opens its workspace link without direct UI control; requested agent settings and the first prompt are applied later through Conductor’s UI. dismiss_prompt, keep_awake and relay_logs touch no UI. send_prompt, split_chat, stop_turn, set_agent_options, set_default_model, a live list_models call, set_workspace_status and archive_workspace drive the real Mac UI and steal focus for a few seconds — confirm with the user before using them on a chat 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;
|
|
@@ -325,7 +325,7 @@ export function createTools(call) {
|
|
|
325
325
|
// A chat waiting on a background task reads `idle` in `status` and will resume
|
|
326
326
|
// itself; an agent that reads only the status would call it done and send a
|
|
327
327
|
// second prompt into the wait.
|
|
328
|
-
const waiting = (s.background_tasks ?? []).map(t => `\n waiting for task: ${t.description} (${Math.max(0, Math.round((Date.now() -
|
|
328
|
+
const waiting = (s.background_tasks ?? []).map(t => `\n waiting for task: ${t.description} (${Math.max(0, Math.round((Date.now() - timestampMs(t.since)) / 60_000))}m so far)`);
|
|
329
329
|
const glyph = s.status === 'working' ? '▶' : waiting.length ? '⧗' : '·';
|
|
330
330
|
return `${glyph} ${s.title ?? '(untitled)'} — ${s.status ?? '?'} · ${s.model ?? '?'}${ctx}\n session_id: ${s.id}${waiting.join('')}`;
|
|
331
331
|
})
|
|
@@ -579,14 +579,45 @@ export function createTools(call) {
|
|
|
579
579
|
if (!data.groups.length)
|
|
580
580
|
return 'no models are cached yet — read a chat’s live picker with session_id and workspace_id';
|
|
581
581
|
return data.groups
|
|
582
|
-
.map(group => `## ${group.agentType}\n${group.models.map(model => `- ${model}`).join('\n')}`)
|
|
582
|
+
.map(group => `## ${group.agentType}\n${group.models.map(model => `- ${model}${model === data.defaultModel ? ' ★ default' : ''}`).join('\n')}`)
|
|
583
583
|
.join('\n\n');
|
|
584
584
|
}
|
|
585
585
|
const workspaceId = need(args, 'workspace_id');
|
|
586
586
|
const data = await call(`${routes.models.path(sessionId)}?workspaceId=${encodeURIComponent(workspaceId)}`, { timeoutMs: WRITE_TIMEOUT_MS });
|
|
587
587
|
if (!data.ok)
|
|
588
588
|
throw new Error(data.error ?? 'could not read the model menu');
|
|
589
|
-
return data.models?.length
|
|
589
|
+
return data.models?.length
|
|
590
|
+
? data.models.map(model => `${model}${model === data.defaultModel ? ' ★ default' : ''}`).join('\n')
|
|
591
|
+
: 'the menu listed no models';
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
name: 'set_default_model',
|
|
596
|
+
description: 'Star a model as Conductor’s user-wide default. This mirrors the desktop picker’s combined “set as default and select” action, so it also switches the target chat to that model for its next turn. DRIVES THE REAL UI and changes a global preference — ask the user first.',
|
|
597
|
+
inputSchema: {
|
|
598
|
+
type: 'object',
|
|
599
|
+
properties: {
|
|
600
|
+
session_id: { type: 'string', description: 'Chat whose live model picker should be used.' },
|
|
601
|
+
workspace_id: {
|
|
602
|
+
type: 'string',
|
|
603
|
+
description: 'Required in practice — the relay asserts the pane against it before pressing.'
|
|
604
|
+
},
|
|
605
|
+
model: { type: 'string', description: 'A label from list_models. An unambiguous prefix is enough.' }
|
|
606
|
+
},
|
|
607
|
+
required: ['session_id', 'workspace_id', 'model']
|
|
608
|
+
},
|
|
609
|
+
run: async (args) => {
|
|
610
|
+
const sessionId = need(args, 'session_id');
|
|
611
|
+
const workspaceId = need(args, 'workspace_id');
|
|
612
|
+
const model = need(args, 'model');
|
|
613
|
+
const data = await call(routes.defaultModel.path(sessionId), {
|
|
614
|
+
method: routes.defaultModel.method,
|
|
615
|
+
body: { workspaceId, model },
|
|
616
|
+
timeoutMs: WRITE_TIMEOUT_MS
|
|
617
|
+
});
|
|
618
|
+
if (!data.ok)
|
|
619
|
+
throw new Error(data.error ?? 'the default model did not change');
|
|
620
|
+
return `${data.defaultModel ?? model} is now the default and selected for this chat`;
|
|
590
621
|
}
|
|
591
622
|
},
|
|
592
623
|
{
|
|
@@ -31,20 +31,28 @@ export class ModelCache {
|
|
|
31
31
|
list() {
|
|
32
32
|
return this.entries.map(entry => ({ ...entry, models: [...entry.models] }));
|
|
33
33
|
}
|
|
34
|
+
/** The newest live picker read wins when upgrading from caches that disagree. */
|
|
35
|
+
defaultModel() {
|
|
36
|
+
return [...this.entries].sort((a, b) => b.updatedAt - a.updatedAt).find(entry => entry.defaultModel)?.defaultModel;
|
|
37
|
+
}
|
|
34
38
|
/** Record the menu that was read from one chat. An empty or failed read changes nothing. */
|
|
35
|
-
remember(agentType, models) {
|
|
39
|
+
remember(agentType, models, defaultModel) {
|
|
36
40
|
const next = clean(models);
|
|
37
41
|
if (!next.length)
|
|
38
42
|
return;
|
|
39
43
|
const key = group(agentType ?? '');
|
|
44
|
+
const selectedDefault = clean(defaultModel ? [defaultModel] : [])[0] ?? this.defaultModel();
|
|
40
45
|
const entry = {
|
|
41
46
|
agentType: key,
|
|
42
47
|
// A live menu is authoritative. Replacing its group drops a model Conductor
|
|
43
48
|
// stopped offering instead of leaving a stale choice in a later workspace.
|
|
44
49
|
models: next,
|
|
50
|
+
defaultModel: selectedDefault,
|
|
45
51
|
updatedAt: Date.now()
|
|
46
52
|
};
|
|
47
|
-
this.entries = [...this.entries.filter(existing => existing.agentType !== key), entry]
|
|
53
|
+
this.entries = [...this.entries.filter(existing => existing.agentType !== key), entry]
|
|
54
|
+
.map(existing => ({ ...existing, defaultModel: selectedDefault ?? existing.defaultModel }))
|
|
55
|
+
.sort((a, b) => a.agentType.localeCompare(b.agentType));
|
|
48
56
|
this.save();
|
|
49
57
|
}
|
|
50
58
|
/** A model that Conductor accepted is also a useful choice for a later workspace. */
|
|
@@ -56,11 +64,20 @@ export class ModelCache {
|
|
|
56
64
|
const entry = {
|
|
57
65
|
agentType: key,
|
|
58
66
|
models: clean([...(current?.models ?? []), model]),
|
|
67
|
+
defaultModel: current?.defaultModel ?? this.defaultModel(),
|
|
59
68
|
updatedAt: Date.now()
|
|
60
69
|
};
|
|
61
70
|
this.entries = [...this.entries.filter(existing => existing.agentType !== key), entry].sort((a, b) => a.agentType.localeCompare(b.agentType));
|
|
62
71
|
this.save();
|
|
63
72
|
}
|
|
73
|
+
/** A successful star press is authoritative for every harness's copy of the same picker. */
|
|
74
|
+
rememberDefault(model) {
|
|
75
|
+
const selected = clean([model])[0];
|
|
76
|
+
if (!selected)
|
|
77
|
+
return;
|
|
78
|
+
this.entries = this.entries.map(entry => ({ ...entry, defaultModel: selected }));
|
|
79
|
+
this.save();
|
|
80
|
+
}
|
|
64
81
|
load() {
|
|
65
82
|
try {
|
|
66
83
|
const parsed = JSON.parse(fs.readFileSync(this.file, 'utf8'));
|
|
@@ -71,6 +88,7 @@ export class ModelCache {
|
|
|
71
88
|
.map(entry => ({
|
|
72
89
|
agentType: group(entry.agentType),
|
|
73
90
|
models: clean(entry.models.filter((model) => typeof model === 'string')),
|
|
91
|
+
defaultModel: typeof entry.defaultModel === 'string' ? clean([entry.defaultModel])[0] || undefined : undefined,
|
|
74
92
|
updatedAt: Number.isFinite(entry.updatedAt) ? entry.updatedAt : 0
|
|
75
93
|
}))
|
|
76
94
|
.filter(entry => entry.models.length);
|
package/dist-node/src/routes.js
CHANGED
|
@@ -96,6 +96,8 @@ export const routes = {
|
|
|
96
96
|
// ── chats ──
|
|
97
97
|
messages: param('GET', '/api/sessions/:sessionId/messages'),
|
|
98
98
|
models: param('GET', '/api/sessions/:sessionId/models'),
|
|
99
|
+
/** Star a model as the user's default; Conductor also selects it for this chat. */
|
|
100
|
+
defaultModel: param('POST', '/api/sessions/:sessionId/default-model'),
|
|
99
101
|
agent: param('POST', '/api/sessions/:sessionId/agent'),
|
|
100
102
|
stop: param('POST', '/api/sessions/:sessionId/stop'),
|
|
101
103
|
sendPrompt: param('POST', '/api/sessions/:sessionId/prompt'),
|
package/dist-node/src/server.js
CHANGED
|
@@ -32,7 +32,7 @@ import { discardStagedAttachment, materializeStagedAttachments, stageAttachment,
|
|
|
32
32
|
import { driftWarningLines, readExposeMode, tailscaleBin } from "./tailscale.js";
|
|
33
33
|
import { renderTranscript, transcriptThrough } from "./transcript.js";
|
|
34
34
|
import { autoJoinHotspotMode, currentSsid, looksLikeHotspot, preferredNetworks } from "./wifi.js";
|
|
35
|
-
import { archiveWorkspace, createWorkspace, describeActuator, EFFORT_LABELS, listAgentModels, lockBlocked, newChat, pickActuator, retryWontHelp, screenLocked, sendNeverStarted, setAgentOptions, setRestartGuard, setWorkspaceStatus, stopTurn, UiBusyError, uiQueueDepth, WORKSPACE_STATUS_LABELS, withUiPriority } from "./writes.js";
|
|
35
|
+
import { archiveWorkspace, createWorkspace, describeActuator, EFFORT_LABELS, listAgentModels, lockBlocked, newChat, pickActuator, retryWontHelp, screenLocked, sendNeverStarted, setAgentOptions, setDefaultModel, setRestartGuard, setWorkspaceStatus, stopTurn, UiBusyError, uiQueueDepth, WORKSPACE_STATUS_LABELS, withUiPriority } from "./writes.js";
|
|
36
36
|
// Before anything that logs: from here on every console line is also kept in memory for
|
|
37
37
|
// `GET /api/logs`, so the phone can read why a send failed without ssh-ing into the Mac.
|
|
38
38
|
installLogCapture();
|
|
@@ -870,7 +870,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
870
870
|
// GET /api/models — prior live picker reads, without activating Conductor. A
|
|
871
871
|
// new workspace has no chat yet, so this is its only safe source of choices.
|
|
872
872
|
if (isRoute(routes.modelCatalog, req.method, pathname)) {
|
|
873
|
-
return json(req, res, 200, { groups: modelCache.list() });
|
|
873
|
+
return json(req, res, 200, { groups: modelCache.list(), defaultModel: modelCache.defaultModel() });
|
|
874
874
|
}
|
|
875
875
|
// GET /api/settings — relay preferences plus what the phone needs to edit them:
|
|
876
876
|
// the SSIDs this Mac already holds credentials for, so the picker offers a choice
|
|
@@ -1362,9 +1362,37 @@ const server = http.createServer(async (req, res) => {
|
|
|
1362
1362
|
return json(req, res, 409, { error: located.error });
|
|
1363
1363
|
const result = await listAgentModels({ workspace: ws, sessionId, tab: located.tab });
|
|
1364
1364
|
if (result.ok && result.models)
|
|
1365
|
-
modelCache.remember(located.session?.agent_type, result.models);
|
|
1365
|
+
modelCache.remember(located.session?.agent_type, result.models, result.defaultModel);
|
|
1366
1366
|
return json(req, res, result.ok ? 200 : 502, result);
|
|
1367
1367
|
}
|
|
1368
|
+
// POST /api/sessions/:id/default-model { model, workspaceId? }
|
|
1369
|
+
// The picker star is a combined "set default and select" action, so this
|
|
1370
|
+
// changes both the user-wide default and this chat's model exactly as the
|
|
1371
|
+
// desktop control does.
|
|
1372
|
+
const defaultModelOf = routeParam(routes.defaultModel, req.method, pathname);
|
|
1373
|
+
if (defaultModelOf) {
|
|
1374
|
+
const sessionId = defaultModelOf;
|
|
1375
|
+
const body = JSON.parse((await readBody(req)) || '{}');
|
|
1376
|
+
if (typeof body.model !== 'string' || !body.model.trim()) {
|
|
1377
|
+
return json(req, res, 400, { error: 'model must be a picker label' });
|
|
1378
|
+
}
|
|
1379
|
+
const ws = typeof body.workspaceId === 'string'
|
|
1380
|
+
? reads.getWorkspace(body.workspaceId)
|
|
1381
|
+
: (reads.listWorkspaces().find(w => w.active_session_id === sessionId) ?? null);
|
|
1382
|
+
if (!ws)
|
|
1383
|
+
return json(req, res, 404, { error: 'workspace for session not found' });
|
|
1384
|
+
const located = locateChat(ws, sessionId);
|
|
1385
|
+
if ('error' in located)
|
|
1386
|
+
return json(req, res, 409, { error: located.error });
|
|
1387
|
+
const result = await setDefaultModel({ workspace: ws, sessionId, tab: located.tab }, body.model.trim());
|
|
1388
|
+
if (!result.ok || !result.model) {
|
|
1389
|
+
return json(req, res, 502, { ok: false, error: result.error ?? 'the default model did not change' });
|
|
1390
|
+
}
|
|
1391
|
+
const session = reads.listSessions(ws.id).find(row => row.id === sessionId);
|
|
1392
|
+
modelCache.rememberModel(session?.agent_type, result.model);
|
|
1393
|
+
modelCache.rememberDefault(result.model);
|
|
1394
|
+
return json(req, res, 200, { ok: true, defaultModel: result.model, session });
|
|
1395
|
+
}
|
|
1368
1396
|
// POST /api/sessions/:id/agent { effort?, plan?, fast?, model? }
|
|
1369
1397
|
// Drives the composer's own model/effort/plan/fast controls for one chat.
|
|
1370
1398
|
const agentOf = routeParam(routes.agent, req.method, pathname);
|
package/dist-node/src/shared.js
CHANGED
|
@@ -50,6 +50,19 @@ export function workspaceTitle(w) {
|
|
|
50
50
|
export function queryTokens(raw) {
|
|
51
51
|
return raw.toLowerCase().match(/[\p{L}\p{N}_]+/gu) ?? [];
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Parse one of Conductor's timestamps as an epoch.
|
|
55
|
+
*
|
|
56
|
+
* Its SQLite defaults/triggers use `datetime('now')`, which is UTC but serializes as
|
|
57
|
+
* `YYYY-MM-DD HH:MM:SS` with no zone. Other writers use ISO strings ending in `Z`.
|
|
58
|
+
* Browsers interpret the bare SQLite form as local time, making a fresh chat look two
|
|
59
|
+
* hours old in Oslo during summer. Add the zone only to that exact database shape;
|
|
60
|
+
* explicitly zoned ISO values and local wall-clock strings keep their native meaning.
|
|
61
|
+
*/
|
|
62
|
+
export function timestampMs(value) {
|
|
63
|
+
const sqliteUtc = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(value);
|
|
64
|
+
return Date.parse(sqliteUtc ? `${value.replace(' ', 'T')}Z` : value);
|
|
65
|
+
}
|
|
53
66
|
/**
|
|
54
67
|
* A temporary `NEW` marker in Conductor's picker is a badge, not part of the
|
|
55
68
|
* model name. The relay and phone use this value for the visible label and for
|