conductor-remote 1.16.1 → 1.18.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/dist/assets/index-BTmIqTa9.js +40 -0
- package/dist/assets/index-Dtq6pwjg.css +1 -0
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/dist-node/src/git.js +21 -1
- package/dist-node/src/merge.js +53 -0
- package/dist-node/src/pr.js +5 -1
- package/dist-node/src/reads.js +20 -3
- package/dist-node/src/server.js +10 -0
- package/dist-node/src/transcript.js +77 -52
- package/package.json +1 -1
- package/dist/assets/index-CkWIQoxg.js +0 -40
- package/dist/assets/index-DLTj56Tj.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-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-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-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;--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-relaxed:1.625;--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-conflicts:#fd9a00;--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:100dvh}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;overflow-x:hidden}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)}.dot{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5);background-color:var(--color-faint);--pulse-color:var(--color-working);border-radius:3.40282e38px;flex-shrink:0}.dot-pulse{box-shadow:0 0 0 0 var(--pulse-color)}@supports (color:color-mix(in lab,red,red)){.dot-pulse{box-shadow:0 0 color-mix(in srgb,var(--pulse-color) 60%,transparent)}}.dot-pulse{animation:1.6s ease-out infinite pulse}.dot-working{background:var(--color-working);box-shadow:0 0 #f5a62399}@supports (color:color-mix(in lab,red,red)){.dot-working{box-shadow:0 0 color-mix(in srgb,var(--color-working) 60%,transparent)}}.dot-working{animation:1.6s ease-out infinite pulse}.dot-idle{background:var(--color-idle)}.dot-done{background:var(--color-done)}.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.25em}.md h2{font-size:1.15em}.md h3{font-size:1.05em}.md ul,.md ol{margin:.5em 0;padding-left:1.4em}.md ul{list-style:outside}.md ol{list-style:decimal}.md li,.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:.75em 0}.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}}@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.top-0{top:0}.top-1\.5{top:calc(var(--spacing) * 1.5)}.top-full{top:100%}.-right-0\.5{right:calc(var(--spacing) * -.5)}.right-1\.5{right:calc(var(--spacing) * 1.5)}.right-2{right:calc(var(--spacing) * 2)}.-bottom-0\.5{bottom:calc(var(--spacing) * -.5)}.bottom-0{bottom:0}.left-0{left:0}.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}.mx-auto{margin-inline:auto}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.-mr-1{margin-right:calc(var(--spacing) * -1)}.mr-1{margin-right:var(--spacing)}.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)}.-ml-1{margin-left:calc(var(--spacing) * -1)}.ml-auto{margin-left:auto}.line-clamp-4{-webkit-line-clamp:4;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-1\.5\!{width:calc(var(--spacing) * 1.5)!important;height:calc(var(--spacing) * 1.5)!important}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.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-20{width:calc(var(--spacing) * 20);height:calc(var(--spacing) * 20)}.size-60{width:calc(var(--spacing) * 60);height:calc(var(--spacing) * 60)}.size-full{width:100%;height:100%}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing) * 40)}.w-1{width:var(--spacing)}.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-80{max-width:calc(var(--spacing) * 80)}.max-w-\[70vw\]{max-width:70vw}.max-w-\[85\%\]{max-width:85%}.max-w-\[92\%\]{max-width:92%}.max-w-full{max-width:100%}.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)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-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)}.-rotate-90{rotate:-90deg}.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-pointer{cursor:pointer}.resize-none{resize:none}.list-none{list-style-type:none}.flex-col{flex-direction:column}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.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\.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)}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.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-2{border-style:var(--tw-border-style);border-width:2px}.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-2{border-left-style:var(--tw-border-style);border-left-width:2px}.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-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)}.bg-accent{background-color:var(--color-accent)}.bg-accent-soft{background-color:var(--color-accent-soft)}.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-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-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-idle\/10{background-color:#3ecf8e1a}@supports (color:color-mix(in lab,red,red)){.bg-idle\/10{background-color:color-mix(in oklab,var(--color-idle) 10%,transparent)}}.bg-surface{background-color:var(--color-surface)}.bg-surface-2{background-color:var(--color-surface-2)}.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\/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-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-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-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)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-2\.5{padding-bottom:calc(var(--spacing) * 2.5)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-center{text-align:center}.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-\[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-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.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-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}.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-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-idle{color:var(--color-idle)}.text-muted{color:var(--color-muted)}.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}.underline-offset-2{text-underline-offset:2px}.\[color-scheme\:dark\]{color-scheme:dark}.opacity-60{opacity:.6}.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-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-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)}.ring-surface{--tw-ring-color:var(--color-surface)}.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-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\:rotate-90:is(:where(.group):is([open],:popover-open,:open) *){rotate:90deg}.placeholder\:font-sans::placeholder{font-family:var(--font-sans)}.placeholder\:text-faint::placeholder{color:var(--color-faint)}.focus-within\:border-accent\/60:focus-within{border-color:#8b7dff99}@supports (color:color-mix(in lab,red,red)){.focus-within\:border-accent\/60:focus-within{border-color:color-mix(in oklab,var(--color-accent) 60%,transparent)}}@media(hover:hover){.hover\:underline:hover{text-decoration-line:underline}}.active\:scale-90:active{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x) var(--tw-scale-y)}.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\: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,.disabled\:bg-surface-2:disabled{background-color:var(--color-surface-2)}.disabled\:text-faint:disabled{color:var(--color-faint)}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media(min-width:48rem){.md\:static{position:static}.md\:inset-0{inset:0}.md\:z-auto{z-index:auto}.md\:m-auto{margin:auto}.md\:block{display:block}.md\:hidden{display:none}.md\:h-fit{height:fit-content}.md\:w-72{width:calc(var(--spacing) * 72)}.md\:max-w-none{max-width:none}.md\:shrink-0{flex-shrink:0}.md\:translate-x-0{--tw-translate-x:0;translate:var(--tw-translate-x) var(--tw-translate-y)}.md\:rounded-3xl{border-radius:var(--radius-3xl)}.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 pulse{50%{opacity:.5}}@keyframes fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.fade-in{animation:.18s ease-out fade-in}.pt-safe{padding-top:max(env(safe-area-inset-top),.5rem)}.pb-safe{padding-bottom:max(env(safe-area-inset-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-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-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-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
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
|
12
12
|
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
|
|
13
13
|
<title>Conductor Remote</title>
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-BTmIqTa9.js"></script>
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Dtq6pwjg.css">
|
|
16
16
|
<link rel="manifest" href="/manifest.webmanifest"></head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="root"></div>
|
package/dist/sw.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
if(!self.define){let e,i={};const n=(n,s)=>(n=new URL(n+".js",s).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(s,o)=>{const r=e||("document"in self?document.currentScript.src:"")||location.href;if(i[r])return;let t={};const
|
|
1
|
+
if(!self.define){let e,i={};const n=(n,s)=>(n=new URL(n+".js",s).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(s,o)=>{const r=e||("document"in self?document.currentScript.src:"")||location.href;if(i[r])return;let t={};const l=e=>n(e,r),c={module:{uri:r},exports:t,require:l};i[r]=Promise.all(s.map(e=>c[e]||l(e))).then(e=>(o(...e),t))}}define(["./workbox-9c191d2f"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"index.html",revision:"f6f8ecb9ae2d872381f30361b5905ab7"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/index-Dtq6pwjg.css",revision:null},{url:"assets/index-BTmIqTa9.js",revision:null},{url:"apple-touch-icon.png",revision:"2b9301416b880d45d4bb655f2600d1f2"},{url:"icon-192.png",revision:"c5e01ac58768627e18ee7b8b6a9239ef"},{url:"icon-512.png",revision:"a40638c55e310312457a621c9a0002c8"},{url:"icon-maskable-512.png",revision:"a40638c55e310312457a621c9a0002c8"},{url:"icon.svg",revision:"c1aee186821798733dd477e69a0ef243"},{url:"manifest.webmanifest",revision:"cf88fbc5755108a7fe0616fa160a8a15"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api\//]}))});
|
package/dist-node/src/git.js
CHANGED
|
@@ -94,5 +94,25 @@ export async function workspaceDiff(worktree, base) {
|
|
|
94
94
|
const truncated = patch.length > MAX_PATCH_BYTES;
|
|
95
95
|
if (truncated)
|
|
96
96
|
patch = `${patch.slice(0, MAX_PATCH_BYTES)}\n\n… diff truncated (${patch.length} bytes) …`;
|
|
97
|
-
|
|
97
|
+
const { dirty, unpushed } = await localState(worktree);
|
|
98
|
+
return { base: ref, mergeBase, files, patch, truncated, dirty, unpushed };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Local publish state of the worktree: does it have uncommitted changes, and are
|
|
102
|
+
* there commits not yet on its remote-tracking branch? Together these drive the
|
|
103
|
+
* bar's "Commit & push" action (you must land local work before a PR reflects it).
|
|
104
|
+
*/
|
|
105
|
+
async function localState(worktree) {
|
|
106
|
+
const status = await git(worktree, ['status', '--porcelain']).catch(() => '');
|
|
107
|
+
const dirty = status.trim() !== '';
|
|
108
|
+
let unpushed = false;
|
|
109
|
+
try {
|
|
110
|
+
// `@{upstream}` throws when no upstream is configured — then there's nothing to compare against.
|
|
111
|
+
const count = (await git(worktree, ['rev-list', '--count', '@{upstream}..HEAD'])).trim();
|
|
112
|
+
unpushed = Number(count) > 0;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
unpushed = false;
|
|
116
|
+
}
|
|
117
|
+
return { dirty, unpushed };
|
|
98
118
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const exec = promisify(execFile);
|
|
4
|
+
async function gh(root, args) {
|
|
5
|
+
const { stdout } = await exec('gh', args, { cwd: root, encoding: 'utf8', timeout: 30_000 });
|
|
6
|
+
return stdout;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The repo's merge method, preferring squash (this project's convention), then a
|
|
10
|
+
* merge commit, then rebase — whichever GitHub allows for the repo. Defaults to
|
|
11
|
+
* squash if the query fails.
|
|
12
|
+
*/
|
|
13
|
+
async function preferredMethod(root) {
|
|
14
|
+
try {
|
|
15
|
+
const out = await gh(root, ['repo', 'view', '--json', 'squashMergeAllowed,mergeCommitAllowed,rebaseMergeAllowed']);
|
|
16
|
+
const a = JSON.parse(out);
|
|
17
|
+
if (a.squashMergeAllowed)
|
|
18
|
+
return 'squash';
|
|
19
|
+
if (a.mergeCommitAllowed)
|
|
20
|
+
return 'merge';
|
|
21
|
+
if (a.rebaseMergeAllowed)
|
|
22
|
+
return 'rebase';
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// gh missing / not a GitHub repo → fall back; the merge call will surface any real error.
|
|
26
|
+
}
|
|
27
|
+
return 'squash';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Merge the workspace's open PR. `gh pr merge <branch>` resolves the PR from its
|
|
31
|
+
* head branch, so we need no PR number. We don't `--delete-branch` (the worktree
|
|
32
|
+
* still has it checked out; Conductor deletes it on archive, not on merge) and
|
|
33
|
+
* push nothing — GitHub performs the merge. Any GitHub-side refusal (checks,
|
|
34
|
+
* reviews, conflicts, draft) comes back as a loud error.
|
|
35
|
+
*/
|
|
36
|
+
export async function mergePr(ws) {
|
|
37
|
+
const branch = ws.branch ?? '';
|
|
38
|
+
const root = ws.repo_root;
|
|
39
|
+
if (!branch)
|
|
40
|
+
return { ok: false, branch, error: 'workspace has no branch' };
|
|
41
|
+
if (!root)
|
|
42
|
+
return { ok: false, branch, error: 'repo root unresolved' };
|
|
43
|
+
const method = await preferredMethod(root);
|
|
44
|
+
try {
|
|
45
|
+
await gh(root, ['pr', 'merge', branch, `--${method}`]);
|
|
46
|
+
return { ok: true, branch, method };
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const stderr = err.stderr;
|
|
50
|
+
const message = (stderr || (err instanceof Error ? err.message : String(err))).trim();
|
|
51
|
+
return { ok: false, branch, method, error: message };
|
|
52
|
+
}
|
|
53
|
+
}
|
package/dist-node/src/pr.js
CHANGED
|
@@ -19,12 +19,16 @@ export function attachPrStatus(workspaces) {
|
|
|
19
19
|
const repos = new Set();
|
|
20
20
|
for (const w of workspaces) {
|
|
21
21
|
w.pr_status = null;
|
|
22
|
+
w.pr_number = null;
|
|
23
|
+
w.pr_url = null;
|
|
22
24
|
if (!w.branch || !w.repo_root)
|
|
23
25
|
continue;
|
|
24
26
|
repos.add(w.repo_root);
|
|
25
27
|
const pr = repoCache.get(w.repo_root)?.prs?.get(w.branch);
|
|
26
28
|
if (!pr)
|
|
27
29
|
continue;
|
|
30
|
+
w.pr_number = pr.number;
|
|
31
|
+
w.pr_url = pr.url;
|
|
28
32
|
if (pr.state === 'MERGED')
|
|
29
33
|
w.pr_status = 'merged';
|
|
30
34
|
else if (pr.state === 'OPEN') {
|
|
@@ -57,7 +61,7 @@ function refreshRepo(root) {
|
|
|
57
61
|
/** One `gh` call per repo → its PRs keyed by head branch. Never rejects. */
|
|
58
62
|
async function fetchRepoPRs(root) {
|
|
59
63
|
try {
|
|
60
|
-
const { stdout } = await exec('gh', ['pr', 'list', '--state', 'all', '--limit', '100', '--json', 'headRefName,state,isDraft,updatedAt'], { cwd: root, encoding: 'utf8', timeout: 15_000 });
|
|
64
|
+
const { stdout } = await exec('gh', ['pr', 'list', '--state', 'all', '--limit', '100', '--json', 'headRefName,number,url,state,isDraft,updatedAt'], { cwd: root, encoding: 'utf8', timeout: 15_000 });
|
|
61
65
|
const list = JSON.parse(stdout);
|
|
62
66
|
// Oldest first so the newest PR wins when a branch has been reused across PRs.
|
|
63
67
|
list.sort((a, b) => a.updatedAt.localeCompare(b.updatedAt));
|
package/dist-node/src/reads.js
CHANGED
|
@@ -90,19 +90,36 @@ export class Reads {
|
|
|
90
90
|
WHERE workspace_id = ? AND COALESCE(is_hidden, 0) = 0
|
|
91
91
|
ORDER BY created_at ASC`, [workspaceId]);
|
|
92
92
|
}
|
|
93
|
+
/** Session → worktree path, cached: it's stable for a session's lifetime and polled every tick. */
|
|
94
|
+
worktreeBySession = new Map();
|
|
95
|
+
sessionWorktree(sessionId) {
|
|
96
|
+
const cached = this.worktreeBySession.get(sessionId);
|
|
97
|
+
if (cached !== undefined)
|
|
98
|
+
return cached;
|
|
99
|
+
const rows = this.db.query(`SELECT w.directory_name, w.branch, r.name AS repo_name, r.root_path AS repo_root
|
|
100
|
+
FROM sessions s
|
|
101
|
+
JOIN workspaces w ON w.id = s.workspace_id
|
|
102
|
+
LEFT JOIN repos r ON r.id = w.repository_id
|
|
103
|
+
WHERE s.id = ? LIMIT 1`, [sessionId]);
|
|
104
|
+
const r = rows[0];
|
|
105
|
+
const worktree = r
|
|
106
|
+
? resolveWorktree(this.workspacesRoot, r.repo_name, r.directory_name, r.branch, r.repo_root)
|
|
107
|
+
: null;
|
|
108
|
+
this.worktreeBySession.set(sessionId, worktree);
|
|
109
|
+
return worktree;
|
|
110
|
+
}
|
|
93
111
|
/** Incremental transcript fetch. `afterRowid` is the cursor from a prior call. */
|
|
94
112
|
getMessages(sessionId, afterRowid = 0) {
|
|
95
113
|
const rows = this.db.query(`SELECT rowid, id, role, content, full_message, created_at, sent_at, queue_order
|
|
96
114
|
FROM session_messages
|
|
97
115
|
WHERE session_id = ? AND rowid > ?
|
|
98
116
|
ORDER BY rowid ASC`, [sessionId, afterRowid]);
|
|
117
|
+
const worktree = this.sessionWorktree(sessionId);
|
|
99
118
|
const entries = [];
|
|
100
119
|
let cursor = afterRowid;
|
|
101
120
|
for (const row of rows) {
|
|
102
121
|
cursor = row.rowid;
|
|
103
|
-
|
|
104
|
-
if (entry)
|
|
105
|
-
entries.push(entry);
|
|
122
|
+
entries.push(...parseMessage(row, worktree));
|
|
106
123
|
}
|
|
107
124
|
return { entries, cursor };
|
|
108
125
|
}
|
package/dist-node/src/server.js
CHANGED
|
@@ -7,6 +7,7 @@ import { startAutoUpdate, updateStatus } from "./autoupdate.js";
|
|
|
7
7
|
import { loadConfig } from "./config.js";
|
|
8
8
|
import { ConductorDb } from "./db.js";
|
|
9
9
|
import { workspaceDiff } from "./git.js";
|
|
10
|
+
import { mergePr } from "./merge.js";
|
|
10
11
|
import { attachPrStatus } from "./pr.js";
|
|
11
12
|
import { Reads } from "./reads.js";
|
|
12
13
|
import { describeActuator, newChat, pickActuator } from "./writes.js";
|
|
@@ -175,6 +176,15 @@ const server = http.createServer(async (req, res) => {
|
|
|
175
176
|
const diff = await workspaceDiff(ws.worktree, ws.baseBranch);
|
|
176
177
|
return json(req, res, 200, diff);
|
|
177
178
|
}
|
|
179
|
+
// POST /api/workspaces/:id/merge — merge the workspace's open PR (mirrors Conductor's merge button)
|
|
180
|
+
m = pathname.match(/^\/api\/workspaces\/([^/]+)\/merge$/);
|
|
181
|
+
if (req.method === 'POST' && m) {
|
|
182
|
+
const ws = reads.getWorkspace(decodeURIComponent(m[1]));
|
|
183
|
+
if (!ws)
|
|
184
|
+
return json(req, res, 404, { error: 'workspace not found' });
|
|
185
|
+
const result = await mergePr(ws);
|
|
186
|
+
return json(req, res, result.ok ? 200 : 409, result);
|
|
187
|
+
}
|
|
178
188
|
// GET /api/sessions/:id/messages?after=<rowid>
|
|
179
189
|
m = pathname.match(/^\/api\/sessions\/([^/]+)\/messages$/);
|
|
180
190
|
if (req.method === 'GET' && m) {
|
|
@@ -1,36 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Conductor stores each turn's raw Claude Code SDK stream JSON in
|
|
3
3
|
* `session_messages.content`. User-typed prompts are stored as plain text.
|
|
4
|
-
* This turns a row into
|
|
4
|
+
* This turns a row into compact, phone-renderable entries.
|
|
5
|
+
*
|
|
6
|
+
* Classification rule (verified against the whole DB): a JSON frame with
|
|
7
|
+
* `type:"user"` is ALWAYS tool plumbing — every one of them carries
|
|
8
|
+
* tool_result blocks, never the user's own words. Real prompts are the
|
|
9
|
+
* plain-text rows. Never render an SDK user frame as a user bubble.
|
|
5
10
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const inputStr = summarizeToolInput(b.input);
|
|
17
|
-
parts.push(inputStr ? `▸ ${b.name}: ${inputStr}` : `▸ ${b.name}`);
|
|
18
|
-
}
|
|
19
|
-
else if (b.type === 'tool_result') {
|
|
20
|
-
parts.push(summarizeToolResult(b.content));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return { text: parts.join('\n').trim(), tool };
|
|
11
|
+
const clip = (s, n) => (s.length > n ? `${s.slice(0, n)}…` : s);
|
|
12
|
+
const str = (v) => (typeof v === 'string' && v.trim() ? v.trim() : undefined);
|
|
13
|
+
/** Make tool details repo-relative: absolute worktree paths waste the whole line on a phone. */
|
|
14
|
+
function stripWorktree(s, worktree) {
|
|
15
|
+
if (!worktree)
|
|
16
|
+
return s;
|
|
17
|
+
// Conductor prefixes commands with `cd <worktree>` (newline- or &&-joined) — drop the whole clause.
|
|
18
|
+
if (s.startsWith(`cd ${worktree}`))
|
|
19
|
+
s = s.slice(`cd ${worktree}`.length).replace(/^\s*(&&)?\s*/, '');
|
|
20
|
+
return s.replaceAll(`${worktree}/`, '').replaceAll(worktree, '.');
|
|
24
21
|
}
|
|
25
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Mirror Conductor's one-line tool rows: the human description as the title
|
|
24
|
+
* (Bash always has one), the primary input as a mono detail. Tools without a
|
|
25
|
+
* recognizable primary input get the title alone — dumping raw JSON is noise.
|
|
26
|
+
*/
|
|
27
|
+
function summarizeToolUse(name, input, worktree) {
|
|
26
28
|
if (!input || typeof input !== 'object')
|
|
27
|
-
return
|
|
29
|
+
return { text: name };
|
|
28
30
|
const o = input;
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
31
|
+
const text = str(o.description) ?? name;
|
|
32
|
+
const detail = str(o.command) ?? str(o.file_path) ?? str(o.path) ?? str(o.pattern) ?? str(o.url) ?? str(o.skill) ?? str(o.prompt);
|
|
33
|
+
if (!detail || detail === text)
|
|
34
|
+
return { text };
|
|
35
|
+
return { text, detail: clip(stripWorktree(detail, worktree).replace(/\s+/g, ' '), 160) };
|
|
32
36
|
}
|
|
33
|
-
function
|
|
37
|
+
function resultText(content) {
|
|
34
38
|
let s = '';
|
|
35
39
|
if (typeof content === 'string')
|
|
36
40
|
s = content;
|
|
@@ -39,45 +43,66 @@ function summarizeToolResult(content) {
|
|
|
39
43
|
.map(c => (c && typeof c === 'object' && 'text' in c ? String(c.text) : ''))
|
|
40
44
|
.join('');
|
|
41
45
|
}
|
|
42
|
-
|
|
43
|
-
if (!s)
|
|
44
|
-
return '↳ (result)';
|
|
45
|
-
return `↳ ${s.length > 200 ? `${s.slice(0, 200)}…` : s}`;
|
|
46
|
+
return clip(s.replace(/<\/?tool_use_error>/g, '').trim(), 400);
|
|
46
47
|
}
|
|
47
|
-
export function parseMessage(row) {
|
|
48
|
+
export function parseMessage(row, worktree = null) {
|
|
48
49
|
const queued = row.queue_order !== null && row.sent_at === null;
|
|
49
|
-
const base = {
|
|
50
|
+
const base = { rowid: row.rowid, ts: row.created_at, queued };
|
|
50
51
|
const content = row.content ?? '';
|
|
51
|
-
// Plain user prompt (not SDK JSON).
|
|
52
|
+
// Plain user prompt (not SDK JSON) — the only source of real user bubbles.
|
|
52
53
|
if (!content.startsWith('{')) {
|
|
53
54
|
if (!content.trim())
|
|
54
|
-
return
|
|
55
|
-
return { ...base, role: 'user', text: content };
|
|
55
|
+
return [];
|
|
56
|
+
return [{ ...base, id: row.id, role: 'user', text: content }];
|
|
56
57
|
}
|
|
57
58
|
let parsed;
|
|
58
59
|
try {
|
|
59
60
|
parsed = JSON.parse(content);
|
|
60
61
|
}
|
|
61
62
|
catch {
|
|
62
|
-
return { ...base, role: 'system', text: content
|
|
63
|
+
return [{ ...base, id: row.id, role: 'system', text: clip(content, 200) }];
|
|
63
64
|
}
|
|
64
|
-
//
|
|
65
|
-
if (parsed.type === 'system'
|
|
66
|
-
return
|
|
67
|
-
if (parsed.type === 'result')
|
|
68
|
-
return null;
|
|
65
|
+
// Bookkeeping frames: hooks, init, token accounting, end-of-turn results.
|
|
66
|
+
if (parsed.type === 'system' || parsed.type === 'result')
|
|
67
|
+
return [];
|
|
69
68
|
const blocks = parsed.message?.content;
|
|
70
|
-
if (Array.isArray(blocks)) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
69
|
+
if (!Array.isArray(blocks)) {
|
|
70
|
+
if (parsed.type === 'user' || parsed.type === 'assistant')
|
|
71
|
+
return [];
|
|
72
|
+
// Unknown frame shape — keep a dim raw dump so Conductor drift stays visible.
|
|
73
|
+
return [{ ...base, id: row.id, role: 'system', text: clip(content, 200) }];
|
|
74
|
+
}
|
|
75
|
+
const entries = [];
|
|
76
|
+
const push = (e) => entries.push({ ...base, ...e, id: `${row.id}:${entries.length}` });
|
|
77
|
+
let pending = [];
|
|
78
|
+
const flush = () => {
|
|
79
|
+
const text = pending.join('\n').trim();
|
|
80
|
+
if (text)
|
|
81
|
+
push({ role: 'assistant', text });
|
|
82
|
+
pending = [];
|
|
83
|
+
};
|
|
84
|
+
for (const b of blocks) {
|
|
85
|
+
if (b.type === 'text' && typeof b.text === 'string') {
|
|
86
|
+
// Text inside an SDK user frame would be injected context, not the user.
|
|
87
|
+
if (parsed.type !== 'user')
|
|
88
|
+
pending.push(b.text);
|
|
89
|
+
}
|
|
90
|
+
else if (b.type === 'thinking') {
|
|
91
|
+
flush();
|
|
92
|
+
const text = str(b.thinking) ?? str(b.text);
|
|
93
|
+
if (text)
|
|
94
|
+
push({ role: 'thinking', text });
|
|
95
|
+
}
|
|
96
|
+
else if (b.type === 'tool_use' && typeof b.name === 'string') {
|
|
97
|
+
flush();
|
|
98
|
+
push({ role: 'tool', tool: b.name, ...summarizeToolUse(b.name, b.input, worktree) });
|
|
99
|
+
}
|
|
100
|
+
else if (b.type === 'tool_result' && b.is_error) {
|
|
101
|
+
// Successful results are noise on a phone; surface only failures.
|
|
102
|
+
flush();
|
|
103
|
+
push({ role: 'tool', error: true, text: resultText(b.content) || '(tool error)' });
|
|
104
|
+
}
|
|
79
105
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return { ...base, role: 'system', text: content.slice(0, 200) };
|
|
106
|
+
flush();
|
|
107
|
+
return entries;
|
|
83
108
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conductor-remote",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "yarn@4.15.0",
|
|
6
6
|
"description": "Phone control panel for local Conductor agents. Reads ride SQLite + git; prompts ride Conductor's own dispatch path.",
|