From 65436b58dd34fdf9292d8e272c7b3f6be3a8af9e Mon Sep 17 00:00:00 2001 From: Igor Soarez Date: Sat, 31 Oct 2026 14:56:54 +0000 Subject: pirc-extension 0.1.9-dev+846aa4a29376 --- package.json | 2 +- pirc.js | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 1fb1f09..c61fde1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pirc-extension", - "version": "0.1.9-dev+382e7ab10913", + "version": "0.1.9-dev+846aa4a29376", "description": "PiRC: puts every interactive pi session on a PiRC relay", "license": "MIT", "homepage": "https://pirc.dev", diff --git a/pirc.js b/pirc.js index 40ed15b..b2fb299 100644 --- a/pirc.js +++ b/pirc.js @@ -1,4 +1,4 @@ -// PiRC extension 0.1.9-dev+382e7ab10913. Third-party code in this file: @bufbuild/protobuf@2.16.0, ws@8.22.0; see NOTICE. +// PiRC extension 0.1.9-dev+846aa4a29376. Third-party code in this file: @bufbuild/protobuf@2.16.0, ws@8.22.0; see NOTICE. import { createRequire as __pircCreateRequire } from "node:module"; const require = __pircCreateRequire(import.meta.url); var __create = Object.create; @@ -8266,6 +8266,14 @@ var Live = class { working = false; compacting = false; unconfirmed = []; + // pi refuses prompts while it compacts; as its terminal does with what is + // typed meanwhile, these wait, in order, until it has finished. + held = []; + releasing; + // Sent the first to an idle pi: the rest wait for its run to start, or + // for as long as a prompt may take to, not counting a compaction first. + starting = false; + startTimer; // A Compact being run, answered when pi finishes it. compaction; // A NewSession, Fork, Clone, Resume, Reload or NavigateTree under way @@ -8331,6 +8339,9 @@ var Live = class { clearTimeout(this.pendingTimer); clearTimeout(this.deltaTimer); for (const p of this.progress.values()) clearTimeout(p.timer); + clearImmediate(this.releasing); + clearTimeout(this.startTimer); + this.held = []; for (const u of this.unconfirmed.splice(0)) { clearTimeout(u.timer); u.respond(errorReply(u.requestId, 7 /* SESSION_GONE */, "the session ended before the prompt ran")); @@ -8536,6 +8547,11 @@ var Live = class { } else if (!this.compaction) { this.compacting = false; } + if (working) { + clearTimeout(this.startTimer); + this.starting = false; + } + this.release(); if (working === this.working) return; this.working = working; this.emit({ case: "workingChanged", value: { working } }); @@ -8549,12 +8565,15 @@ var Live = class { // run (pi compacts first when the context is full) pauses its deadline. onCompactStart() { for (const u of this.unconfirmed) clearTimeout(u.timer); + clearTimeout(this.startTimer); if (this.compacting) return; this.compacting = true; this.onAnnouncementChanged(); } onCompactEnd() { if (!this.sink.questions().length) for (const u of this.unconfirmed) this.armConfirm(u); + if (this.starting) this.armStart(); + this.release(); if (!this.compacting) return; this.compacting = false; this.onAnnouncementChanged(); @@ -8589,6 +8608,34 @@ var Live = class { if (i < 0) return void 0; return this.prompts.splice(i, 1)[0].requestId; } + // Sends the held prompts once pi has finished compacting: pi clears its + // compaction only after its hooks return, so not before then. An idle pi + // starts a run with the first; the rest go once it has, as pi queues + // only what comes mid-run. + release() { + if (this.held.length === 0 || this.releasing || this.starting) return; + this.releasing = setImmediate(this.guard("release", () => { + this.releasing = void 0; + while (this.held.length > 0 && !this.compacting && !this.starting && !this.disposed) { + const idle = this.ctx.isIdle(); + const h = this.held.shift(); + this.prunePrompts(); + this.prompts.push({ requestId: h.requestId, text: h.text, images: h.images, at: Date.now() }); + this.pi.sendUserMessage(h.content, { deliverAs: h.deliverAs, expandPromptTemplates: true }); + if (idle) { + this.starting = true; + this.armStart(); + } + } + })); + } + armStart() { + clearTimeout(this.startTimer); + this.startTimer = setTimeout(this.guard("start", () => { + this.starting = false; + this.release(); + }), CONFIRM_MS); + } // Answers Accepted to the unconfirmed prompts `which` picks. confirm(which) { const keep = []; @@ -8617,7 +8664,7 @@ var Live = class { busy() { if (this.compacting || this.compaction) return "pi is compacting the session"; if (this.replacement) return this.replacement.which === "tree" ? "the session is moving in its tree" : "the session is being replaced"; - if (this.unconfirmed.length > 0) return "a prompt is starting"; + if (this.unconfirmed.length > 0 || this.held.length > 0) return "a prompt is starting"; if (this.working || !this.ctx.isIdle()) return "the agent is working; stop it first"; return void 0; } @@ -8664,16 +8711,17 @@ var Live = class { const refused = name === void 0 ? void 0 : refusedCommand(name); if (refused) return respond(errorReply(requestId, 4 /* INVALID */, refused)); const command = images.length === 0 && this.isCommand(text); - if (!command && this.compacting) { - return respond(errorReply(requestId, 8 /* BUSY */, "pi is compacting the session; try again when it finishes")); - } if (!command && !this.ctx.model) return respond(errorReply(requestId, 13 /* PI_FAILED */, "no model is selected in pi")); - const idle = this.ctx.isIdle(); const content = images.length === 0 ? text : [ ...text ? [{ type: "text", text }] : [], ...images.map((i) => ({ type: "image", mimeType: i.mimeType, data: Buffer.from(i.data).toString("base64") })) ]; const deliverAs = delivery === 1 /* STEER */ ? "steer" : "followUp"; + if (!command && (this.compacting || this.held.length > 0)) { + this.held.push({ requestId, text, images: images.length > 0, content, deliverAs }); + return respond(accepted(requestId)); + } + const idle = this.ctx.isIdle(); this.prunePrompts(); if (!command) this.prompts.push({ requestId, text, images: images.length > 0, at: Date.now() }); this.pi.sendUserMessage(content, { deliverAs, expandPromptTemplates: true }); @@ -9366,7 +9414,7 @@ var Host = class _Host { }; // extension/src/index.ts -var EXTENSION_VERSION = true ? "0.1.9-dev+382e7ab10913" : "dev"; +var EXTENSION_VERSION = true ? "0.1.9-dev+846aa4a29376" : "dev"; function piVersion() { try { let dir = dirname3(realpathSync(process.argv[1])); @@ -9381,7 +9429,7 @@ function piVersion() { } return "unknown"; } -var LOAD = true ? "0.1.9-dev+382e7ab10913" : `dev ${randomBytes4(4).toString("hex")}`; +var LOAD = true ? "0.1.9-dev+846aa4a29376" : `dev ${randomBytes4(4).toString("hex")}`; var KEY = /* @__PURE__ */ Symbol.for("pirc.extension"); var proc = globalThis[KEY] ??= {}; if (!proc.host || proc.load !== LOAD) { -- cgit v1.2.3