@a-t-h-i/bot-lobby 0.6.52 → 0.6.53
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/package.json +1 -1
- package/src/lobby/runtime.ts +2 -1
- package/src/lobby/service.ts +51 -3
- package/src/webui/api/sessions.ts +1 -2
- package/src/webui/dev/fake-service.ts +1 -1
- package/webui/dist/assets/{TerminalView-DhNPNk-y.js → TerminalView-CbRc77C8.js} +1 -1
- package/webui/dist/assets/{index-DlWB1k1P.js → index-Cca5uEVs.js} +7 -7
- package/webui/dist/assets/index-DsVdXmh5.css +2 -0
- package/webui/dist/build.json +6 -6
- package/webui/dist/index.html +2 -2
- package/webui/dist/assets/index-BV_h7eLF.css +0 -2
package/package.json
CHANGED
package/src/lobby/runtime.ts
CHANGED
|
@@ -27,7 +27,7 @@ import { PullsState } from "./pulls.ts";
|
|
|
27
27
|
import { PullReviews } from "./pr-review.ts";
|
|
28
28
|
import { KnowledgeBook } from "./knowledge.ts";
|
|
29
29
|
import type { LobbyService } from "./host.ts";
|
|
30
|
-
import { backgroundSessions, createLobbyService, lobbyNotify, lobbyProfile, plannerDeps, resumeSession, reviewProfile, seatProfile, setServiceState, savePlan as serviceSavePlan, answerPanel as serviceAnswerPanel } from "./service.ts";
|
|
30
|
+
import { backgroundSessions, carryHandOff, createLobbyService, lobbyNotify, lobbyProfile, plannerDeps, resumeSession, reviewProfile, seatProfile, setServiceState, savePlan as serviceSavePlan, answerPanel as serviceAnswerPanel } from "./service.ts";
|
|
31
31
|
import { lobbyTopics } from "./topics.ts";
|
|
32
32
|
export { backgroundSessions, setSessionLauncher } from "./service.ts";
|
|
33
33
|
import { deliverComments, onOwnerEvent } from "../pi/owner.ts";
|
|
@@ -208,6 +208,7 @@ export function startLobbyService(pi: ExtensionAPI, ctx: ExtensionContext, confi
|
|
|
208
208
|
lobbyFeed.seedChat(chatFromEntries(ctx.sessionManager.getBranch(), Number.POSITIVE_INFINITY));
|
|
209
209
|
state.unsubscribeFeed = lobbyFeed.onChange(() => lobbyTopics.bump("lobby"));
|
|
210
210
|
carryOn(state);
|
|
211
|
+
carryHandOff(state);
|
|
211
212
|
onRunUpdates((runs) => {
|
|
212
213
|
lobbyFeed.runs(runs);
|
|
213
214
|
lobbyTopics.bump("tasks");
|
package/src/lobby/service.ts
CHANGED
|
@@ -600,20 +600,68 @@ function sendToSession(state: Runtime, sessionId: string, text: string): string
|
|
|
600
600
|
* task no session owns is claimed instead.
|
|
601
601
|
*/
|
|
602
602
|
async function switchTo(state: Runtime, target: SwitchTarget): Promise<string> {
|
|
603
|
-
if (!state.ctx.isIdle()) return "this window's oracle is working — stop it, then switch";
|
|
604
603
|
if (target.claimTaskId) {
|
|
604
|
+
if (!state.ctx.isIdle()) return "this window's oracle is working — stop it, then take the task over here";
|
|
605
605
|
state.pi.sendUserMessage(`/bot-lobby claim ${target.claimTaskId}`, { expandPromptTemplates: true });
|
|
606
606
|
return `taking ${target.claimTaskId} over in this window`;
|
|
607
607
|
}
|
|
608
|
+
// A window at work hands its session to the background (it carries on there) and then switches.
|
|
609
|
+
const leaving = state.ctx.isIdle() ? undefined : await stepAside(state);
|
|
610
|
+
if (typeof leaving === "string") return leaving;
|
|
608
611
|
let file = target.background?.sessionFile;
|
|
609
612
|
if (target.background) {
|
|
610
613
|
target.background.stop();
|
|
611
614
|
await target.background.whenExited();
|
|
612
615
|
}
|
|
613
616
|
file ??= target.sessionId ? await chats.locate(target.sessionId) : undefined;
|
|
614
|
-
if (!file)
|
|
617
|
+
if (!file) {
|
|
618
|
+
if (leaving) handOff = undefined;
|
|
619
|
+
return `could not find ${target.name}'s session file — /resume lists every saved session`;
|
|
620
|
+
}
|
|
615
621
|
state.pi.sendUserMessage(`/bot-lobby switch ${file}`, { expandPromptTemplates: true });
|
|
616
|
-
return `switching this window to ${target.name}…`;
|
|
622
|
+
return leaving ? `${leaving.name} carries on in the background; switching this window to ${target.name}…` : `switching this window to ${target.name}…`;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/** The session this window was working in when it switched away, started in the background once the switch lands. */
|
|
626
|
+
let handOff: { file: string; name: string; message: string } | undefined;
|
|
627
|
+
|
|
628
|
+
/** How long a stopped turn gets to wind down before the switch gives up. */
|
|
629
|
+
const STEP_ASIDE_MS = 10_000;
|
|
630
|
+
|
|
631
|
+
/** Stop this window's turn and keep its session to carry on in the background; the hand-off, or why not. */
|
|
632
|
+
async function stepAside(state: Runtime): Promise<{ name: string } | string> {
|
|
633
|
+
const file = state.ctx.sessionManager.getSessionFile?.();
|
|
634
|
+
if (!file) return "this window's session is not saved yet — stop the oracle, then switch";
|
|
635
|
+
const name = state.pi.getSessionName() ?? "this window's session";
|
|
636
|
+
const task = ownedTask(state.root, state.configDir, state.ctx.sessionManager.getSessionId());
|
|
637
|
+
state.ctx.abort();
|
|
638
|
+
const deadline = Date.now() + STEP_ASIDE_MS;
|
|
639
|
+
while (!state.ctx.isIdle()) {
|
|
640
|
+
if (Date.now() > deadline) return "the oracle did not stop in time — try the switch again";
|
|
641
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
642
|
+
}
|
|
643
|
+
const message = task && !TERMINAL_STATES.includes(task.state) && !task.paused
|
|
644
|
+
? `bot-lobby: you were moved to the background while you worked on ${task.id}; your last turn was cut off. Read where the task stands with the orchestrate tool (action=status), run again any step that was cut off, and carry on.`
|
|
645
|
+
: "bot-lobby: you were moved to the background while you worked, and your last turn was cut off. Carry on where you left off.";
|
|
646
|
+
handOff = { file, name, message };
|
|
647
|
+
return { name };
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/** Once this window runs its new session, carry the one it left on in the background (see `stepAside`). */
|
|
651
|
+
export function carryHandOff(state: Runtime): void {
|
|
652
|
+
const pending = handOff;
|
|
653
|
+
handOff = undefined;
|
|
654
|
+
if (!pending) return;
|
|
655
|
+
if (state.ctx.sessionManager.getSessionFile?.() === pending.file) {
|
|
656
|
+
lobbyFeed.log("LOBBY", "the switch did not happen; the oracle was stopped — send a message to carry on", "warning");
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
try {
|
|
660
|
+
sessionRegistry().start(state.ctx.cwd, { name: pending.name, projectRoot: state.root, onDialog: dialogTracker(state), ask: askForSession, sessionFile: pending.file, message: pending.message });
|
|
661
|
+
lobbyFeed.log("LOBBY", `${pending.name} carries on in the background`, "success");
|
|
662
|
+
} catch (error) {
|
|
663
|
+
lobbyFeed.log("LOBBY", `could not carry ${pending.name} on in the background — ${(error as Error).message}; /resume finds it`, "warning");
|
|
664
|
+
}
|
|
617
665
|
}
|
|
618
666
|
|
|
619
667
|
/** Why a task cannot be archived or deleted now: a running session drives it. */
|
|
@@ -88,10 +88,9 @@ export function sessionsMessage(body: { key?: string; sessionId?: string; text:
|
|
|
88
88
|
return { notice: ctx.service.sendToSession(body.sessionId!, text) };
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
/** Run a session in this window (stopping its background process first). */
|
|
91
|
+
/** Run a session in this window (stopping its background process first); a window at work carries its own session on in the background. */
|
|
92
92
|
export async function sessionsSwitch(body: { key?: string; sessionId?: string; claimTaskId?: string }, ctx: ApiContext): Promise<{ notice: string }> {
|
|
93
93
|
if (!body.key && !body.sessionId && !body.claimTaskId) fail(400, "bad_request", "a session key, id or task is required");
|
|
94
|
-
if (ctx.service.masterBusy()) return { notice: "this window's oracle is working — stop it, then switch" };
|
|
95
94
|
if (body.claimTaskId) {
|
|
96
95
|
const task = ctx.service.tasks().find((entry) => entry.id === body.claimTaskId);
|
|
97
96
|
if (!task) fail(404, "not_found", `no task ${body.claimTaskId}`);
|
|
@@ -572,7 +572,7 @@ export function createFixtureService(name: string, feed = new LobbyFeed()): Lobb
|
|
|
572
572
|
issues: fakeIssues((fixture.mockIssues ?? []).map((issue) => ({ ...issue }))),
|
|
573
573
|
sessionChat: () => [],
|
|
574
574
|
hasOlderChat: () => false,
|
|
575
|
-
switchTo: async (target: { name: string }) => `switching this window to ${target.name}
|
|
575
|
+
switchTo: async (target: { name: string }) => (fixture.status.busy ? `${sessionName ?? "this window's session"} carries on in the background; switching this window to ${target.name}…` : `switching this window to ${target.name}…`),
|
|
576
576
|
} as unknown as LobbyService;
|
|
577
577
|
seedPrompts(service, fixture);
|
|
578
578
|
return service;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as e,i as t,n,o as r,r as i,t as a}from"./index-
|
|
1
|
+
import{a as e,i as t,n,o as r,r as i,t as a}from"./index-Cca5uEVs.js";var o=r(e(),1),s=Object.defineProperty,c=Object.getOwnPropertyDescriptor,l=(e,t)=>{for(var n in t)s(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,r)=>{for(var i=r>1?void 0:r?c(t,n):t,a=e.length-1,o;a>=0;a--)(o=e[a])&&(i=(r?o(t,n,i):o(i))||i);return r&&i&&s(t,n,i),i},d=(e,t)=>(n,r)=>t(n,r,e),f=`Terminal input`,p={get:()=>f,set:e=>f=e},m=`Too much output to announce, navigate to rows manually to read`,h={get:()=>m,set:e=>m=e};function g(e){return e.replace(/\r?\n/g,`\r`)}function _(e,t){return t?`\x1B[200~`+e+`\x1B[201~`:e}function ee(e,t){e.clipboardData&&e.clipboardData.setData(`text/plain`,t.selectionText),e.preventDefault()}function te(e,t,n,r){e.stopPropagation(),e.clipboardData&&ne(e.clipboardData.getData(`text/plain`),t,n,r)}function ne(e,t,n,r){e=g(e),e=_(e,n.decPrivateModes.bracketedPasteMode&&r.rawOptions.ignoreBracketedPasteMode!==!0),n.triggerDataEvent(e,!0),t.value=``}function re(e,t,n){let r=n.getBoundingClientRect(),i=e.clientX-r.left-10,a=e.clientY-r.top-10;t.style.width=`20px`,t.style.height=`20px`,t.style.left=`${i}px`,t.style.top=`${a}px`,t.style.zIndex=`1000`,t.focus()}function ie(e,t,n,r,i){re(e,t,n),i&&r.rightClickSelect(e),t.value=r.selectionText,t.select()}function ae(e){return e>65535?(e-=65536,String.fromCharCode((e>>10)+55296)+String.fromCharCode(e%1024+56320)):String.fromCharCode(e)}function oe(e,t=0,n=e.length){let r=``;for(let i=t;i<n;++i){let t=e[i];t>65535?(t-=65536,r+=String.fromCharCode((t>>10)+55296)+String.fromCharCode(t%1024+56320)):r+=String.fromCharCode(t)}return r}var se=class{constructor(){this._interim=0}clear(){this._interim=0}decode(e,t){let n=e.length;if(!n)return 0;let r=0,i=0;if(this._interim){let n=e.charCodeAt(i++);56320<=n&&n<=57343?t[r++]=(this._interim-55296)*1024+n-56320+65536:(t[r++]=this._interim,t[r++]=n),this._interim=0}for(let a=i;a<n;++a){let i=e.charCodeAt(a);if(55296<=i&&i<=56319){if(++a>=n)return this._interim=i,r;let o=e.charCodeAt(a);56320<=o&&o<=57343?t[r++]=(i-55296)*1024+o-56320+65536:(t[r++]=i,t[r++]=o);continue}i!==65279&&(t[r++]=i)}return r}},ce=class{constructor(){this.interim=new Uint8Array(3)}clear(){this.interim.fill(0)}decode(e,t){let n=e.length;if(!n)return 0;let r=0,i,a,o,s,c=0,l=0;if(this.interim[0]){let i=!1,a=this.interim[0];a&=(a&224)==192?31:(a&240)==224?15:7;let o=0,s;for(;(s=this.interim[++o]&63)&&o<4;)a<<=6,a|=s;let c=(this.interim[0]&224)==192?2:(this.interim[0]&240)==224?3:4,u=c-o;for(;l<u;){if(l>=n)return 0;if(s=e[l++],(s&192)!=128){l--,i=!0;break}this.interim[o++]=s,a<<=6,a|=s&63}i||(c===2?a<128?l--:t[r++]=a:c===3?a<2048||a>=55296&&a<=57343||a===65279||(t[r++]=a):a<65536||a>1114111||(t[r++]=a)),this.interim.fill(0)}let u=n-4,d=l;for(;d<n;){for(;d<u&&!((i=e[d])&128)&&!((a=e[d+1])&128)&&!((o=e[d+2])&128)&&!((s=e[d+3])&128);)t[r++]=i,t[r++]=a,t[r++]=o,t[r++]=s,d+=4;if(i=e[d++],i<128)t[r++]=i;else if((i&224)==192){if(d>=n)return this.interim[0]=i,r;if(a=e[d++],(a&192)!=128){d--;continue}if(c=(i&31)<<6|a&63,c<128){d--;continue}t[r++]=c}else if((i&240)==224){if(d>=n)return this.interim[0]=i,r;if(a=e[d++],(a&192)!=128){d--;continue}if(d>=n)return this.interim[0]=i,this.interim[1]=a,r;if(o=e[d++],(o&192)!=128){d--;continue}if(c=(i&15)<<12|(a&63)<<6|o&63,c<2048||c>=55296&&c<=57343||c===65279)continue;t[r++]=c}else if((i&248)==240){if(d>=n)return this.interim[0]=i,r;if(a=e[d++],(a&192)!=128){d--;continue}if(d>=n)return this.interim[0]=i,this.interim[1]=a,r;if(o=e[d++],(o&192)!=128){d--;continue}if(d>=n)return this.interim[0]=i,this.interim[1]=a,this.interim[2]=o,r;if(s=e[d++],(s&192)!=128){d--;continue}if(c=(i&7)<<18|(a&63)<<12|(o&63)<<6|s&63,c<65536||c>1114111)continue;t[r++]=c}}return r}},v=``,le=` `,ue=class e{constructor(){this.fg=0,this.bg=0,this.extended=new de}static toColorRGB(e){return[e>>>16&255,e>>>8&255,e&255]}static fromColorRGB(e){return(e[0]&255)<<16|(e[1]&255)<<8|e[2]&255}clone(){let t=new e;return t.fg=this.fg,t.bg=this.bg,t.extended=this.extended.clone(),t}isInverse(){return this.fg&67108864}isBold(){return this.fg&134217728}isUnderline(){return this.hasExtendedAttrs()&&this.extended.underlineStyle!==0?1:this.fg&268435456}isBlink(){return this.fg&536870912}isInvisible(){return this.fg&1073741824}isItalic(){return this.bg&67108864}isDim(){return this.bg&134217728}isStrikethrough(){return this.fg&2147483648}isProtected(){return this.bg&536870912}isOverline(){return this.bg&1073741824}getFgColorMode(){return this.fg&50331648}getBgColorMode(){return this.bg&50331648}isFgRGB(){return(this.fg&50331648)==50331648}isBgRGB(){return(this.bg&50331648)==50331648}isFgPalette(){return(this.fg&50331648)==16777216||(this.fg&50331648)==33554432}isBgPalette(){return(this.bg&50331648)==16777216||(this.bg&50331648)==33554432}isFgDefault(){return!(this.fg&50331648)}isBgDefault(){return!(this.bg&50331648)}isAttributeDefault(){return this.fg===0&&this.bg===0}getFgColor(){switch(this.fg&50331648){case 16777216:case 33554432:return this.fg&255;case 50331648:return this.fg&16777215;default:return-1}}getBgColor(){switch(this.bg&50331648){case 16777216:case 33554432:return this.bg&255;case 50331648:return this.bg&16777215;default:return-1}}hasExtendedAttrs(){return this.bg&268435456}updateExtended(){this.extended.isEmpty()?this.bg&=-268435457:this.bg|=268435456}getUnderlineColor(){if(this.bg&268435456&&~this.extended.underlineColor)switch(this.extended.underlineColor&50331648){case 16777216:case 33554432:return this.extended.underlineColor&255;case 50331648:return this.extended.underlineColor&16777215;default:return this.getFgColor()}return this.getFgColor()}getUnderlineColorMode(){return this.bg&268435456&&~this.extended.underlineColor?this.extended.underlineColor&50331648:this.getFgColorMode()}isUnderlineColorRGB(){return this.bg&268435456&&~this.extended.underlineColor?(this.extended.underlineColor&50331648)==50331648:this.isFgRGB()}isUnderlineColorPalette(){return this.bg&268435456&&~this.extended.underlineColor?(this.extended.underlineColor&50331648)==16777216||(this.extended.underlineColor&50331648)==33554432:this.isFgPalette()}isUnderlineColorDefault(){return this.bg&268435456&&~this.extended.underlineColor?!(this.extended.underlineColor&50331648):this.isFgDefault()}getUnderlineStyle(){return this.fg&268435456?this.bg&268435456?this.extended.underlineStyle:1:0}getUnderlineVariantOffset(){return this.extended.underlineVariantOffset}},de=class e{constructor(e=0,t=0){this._ext=0,this._urlId=0,this._ext=e,this._urlId=t}get ext(){return this._urlId?this._ext&-469762049|this.underlineStyle<<26:this._ext}set ext(e){this._ext=e}get underlineStyle(){return this._urlId?5:(this._ext&469762048)>>26}set underlineStyle(e){this._ext&=-469762049,this._ext|=e<<26&469762048}get underlineColor(){return this._ext&67108863}set underlineColor(e){this._ext&=-67108864,this._ext|=e&67108863}get urlId(){return this._urlId}set urlId(e){this._urlId=e}get underlineVariantOffset(){let e=(this._ext&3758096384)>>29;return e<0?e^4294967288:e}set underlineVariantOffset(e){this._ext&=536870911,this._ext|=e<<29&3758096384}clone(){return new e(this._ext,this._urlId)}isEmpty(){return this.underlineStyle===0&&this._urlId===0}},y=class e extends ue{constructor(){super(...arguments),this.content=0,this.fg=0,this.bg=0,this.extended=new de,this.combinedData=``}static fromCharData(t){let n=new e;return n.setFromCharData(t),n}isCombined(){return this.content&2097152}getWidth(){return this.content>>22}getChars(){return this.content&2097152?this.combinedData:this.content&2097151?ae(this.content&2097151):``}getCode(){return this.isCombined()?this.combinedData.charCodeAt(this.combinedData.length-1):this.content&2097151}setFromCharData(e){this.fg=e[0],this.bg=0;let t=!1;if(e[1].length>2)t=!0;else if(e[1].length===2){let n=e[1].charCodeAt(0);if(55296<=n&&n<=56319){let r=e[1].charCodeAt(1);56320<=r&&r<=57343?this.content=(n-55296)*1024+r-56320+65536|e[2]<<22:t=!0}else t=!0}else this.content=e[1].charCodeAt(0)|e[2]<<22;t&&(this.combinedData=e[1],this.content=2097152|e[2]<<22)}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}},fe=`di$target`,pe=`di$dependencies`,me=new Map;function b(e){return e[pe]||[]}function x(e){if(me.has(e))return me.get(e);let t=function(e,n,r){if(arguments.length!==3)throw Error(`@IServiceName-decorator can only be used to decorate a parameter`);he(t,e,r)};return t._id=e,me.set(e,t),t}function he(e,t,n){t[fe]===t?t[pe].push({id:e,index:n}):(t[pe]=[{id:e,index:n}],t[fe]=t)}var S=x(`BufferService`),ge=x(`CoreMouseService`),_e=x(`CoreService`),C=x(`CharsetService`),ve=x(`InstantiationService`),w=x(`LogService`),T=x(`OptionsService`),ye=x(`OscLinkService`),be=x(`UnicodeService`),xe=x(`DecorationService`),Se=class{constructor(e,t,n){this._bufferService=e,this._optionsService=t,this._oscLinkService=n}provideLinks(e,t){let n=this._bufferService.buffer.lines.get(e-1);if(!n){t(void 0);return}let r=[],i=this._optionsService.rawOptions.linkHandler,a=new y,o=n.getTrimmedLength(),s=-1,c=-1,l=!1;for(let t=0;t<o;t++)if(c!==-1||n.hasContent(t)){if(n.loadCell(t,a),a.hasExtendedAttrs()&&a.extended.urlId){if(c===-1){c=t,s=a.extended.urlId;continue}l=a.extended.urlId!==s}else c!==-1&&(l=!0);if(l||c!==-1&&t===o-1){let n=this._oscLinkService.getLinkData(s)?.uri;if(n){let a={start:{x:c+1,y:e},end:{x:t+ +(!l&&t===o-1),y:e}},s=!1;if(!i?.allowNonHttpProtocols)try{let e=new URL(n);[`http:`,`https:`].includes(e.protocol)||(s=!0)}catch{s=!0}s||r.push({text:n,range:a,activate:(e,t)=>i?i.activate(e,t,a):Ce(e,t),hover:(e,t)=>i?.hover?.(e,t,a),leave:(e,t)=>i?.leave?.(e,t,a)})}l=!1,a.hasExtendedAttrs()&&a.extended.urlId?(c=t,s=a.extended.urlId):(c=-1,s=-1)}}t(r)}};Se=u([d(0,S),d(1,T),d(2,ye)],Se);function Ce(e,t){if(confirm(`Do you want to navigate to ${t}?
|
|
2
2
|
|
|
3
3
|
WARNING: This link could potentially be dangerous`)){let e=window.open();if(e){try{e.opener=null}catch{}e.location.href=t}else console.warn(`Opening link blocked as opener could not be cleared`)}}var we=x(`CharSizeService`),Te=x(`CoreBrowserService`),Ee=x(`MouseService`),De=x(`RenderService`),Oe=x(`SelectionService`),ke=x(`CharacterJoinerService`),Ae=x(`ThemeService`),je=x(`LinkProviderService`),Me=new class{constructor(){this.listeners=[],this.unexpectedErrorHandler=function(e){setTimeout(()=>{throw e.stack?Re.isErrorNoTelemetry(e)?new Re(e.message+`
|
|
4
4
|
|