pi2dsh 0.20.0 → 0.22.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 +9 -6
- package/README.zh.md +8 -5
- package/dist/{analyzer-BL7Nfvko.mjs → analyzer-LD53mBKa.mjs} +2 -2
- package/dist/{analyzer-BL7Nfvko.mjs.map → analyzer-LD53mBKa.mjs.map} +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/{compatibility-D_PV1zgF.mjs → compatibility-PfLsrQPc.mjs} +6 -6
- package/dist/compatibility-PfLsrQPc.mjs.map +1 -0
- package/dist/host.mjs +1 -1
- package/dist/index.d.mts +10 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +12 -5
- package/dist/index.mjs.map +1 -1
- package/dist/{runtime-CBZcd1uU.mjs → runtime-BVrvJuiO.mjs} +137 -12
- package/dist/runtime-BVrvJuiO.mjs.map +1 -0
- package/dist/runtime.d.mts +17 -1
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +1 -1
- package/package.json +1 -8
- package/dist/client.js +0 -829
- package/dist/compatibility-D_PV1zgF.mjs.map +0 -1
- package/dist/runtime-CBZcd1uU.mjs.map +0 -1
|
@@ -963,6 +963,7 @@ async function createBridgedAgentSession(host, options) {
|
|
|
963
963
|
const providedManager = options.sessionManager;
|
|
964
964
|
const archiveFile = typeof providedManager?.getSessionFile === "function" ? providedManager.getSessionFile() : void 0;
|
|
965
965
|
const resumeSessionId = host.resumeSessionIdFor?.(archiveFile);
|
|
966
|
+
const sideline = providedManager !== void 0 && archiveFile === void 0;
|
|
966
967
|
subagentSerial += 1;
|
|
967
968
|
const sessionId = `pi2dsh-sub-${Date.now().toString(36)}-${subagentSerial}`;
|
|
968
969
|
let handle;
|
|
@@ -1076,7 +1077,7 @@ async function createBridgedAgentSession(host, options) {
|
|
|
1076
1077
|
version: 2,
|
|
1077
1078
|
mode: "continuable",
|
|
1078
1079
|
provider: "pi2dsh",
|
|
1079
|
-
label: childLabel(options.label, host.packageName)
|
|
1080
|
+
label: `${sideline ? "Side: " : ""}${childLabel(options.label, host.packageName)}`
|
|
1080
1081
|
});
|
|
1081
1082
|
} catch (error) {
|
|
1082
1083
|
host.cordis.logger?.warn?.(`[pi2dsh] child session could not record its subagent identity: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -1139,7 +1140,16 @@ function messageText(message) {
|
|
|
1139
1140
|
*/
|
|
1140
1141
|
var BrowserSurfaces = class {
|
|
1141
1142
|
#byParent = /* @__PURE__ */ new Map();
|
|
1143
|
+
#commandRunners = /* @__PURE__ */ new Map();
|
|
1142
1144
|
#surfaces = /* @__PURE__ */ new Map();
|
|
1145
|
+
/**
|
|
1146
|
+
* Retained components from `(tui, theme) => Component` factories, keyed by
|
|
1147
|
+
* their slot (session + package + widget key). Retained because the driver
|
|
1148
|
+
* handed to the factory must stay LIVE: requestRender re-renders this
|
|
1149
|
+
* component into its slot for as long as the package holds the handle.
|
|
1150
|
+
* Replacing or clearing the slot disposes the previous component.
|
|
1151
|
+
*/
|
|
1152
|
+
#factoryComponents = /* @__PURE__ */ new Map();
|
|
1143
1153
|
#entrySources = /* @__PURE__ */ new Map();
|
|
1144
1154
|
#draftRequests = /* @__PURE__ */ new Map();
|
|
1145
1155
|
#liveDrafts = /* @__PURE__ */ new Map();
|
|
@@ -1267,6 +1277,32 @@ var BrowserSurfaces = class {
|
|
|
1267
1277
|
};
|
|
1268
1278
|
}
|
|
1269
1279
|
/**
|
|
1280
|
+
* Register the executor for one package's Pi commands on one session, so
|
|
1281
|
+
* product UI (a side-chat window's input, its action buttons) can run the
|
|
1282
|
+
* package's OWN command handlers — the same code path the composer takes.
|
|
1283
|
+
* Generic by construction: the runner closure carries the package runtime;
|
|
1284
|
+
* this registry only routes (session, package) to it.
|
|
1285
|
+
* @param sessionId - the root session the package is mounted for.
|
|
1286
|
+
* @param packageName - the Pi package owning the commands.
|
|
1287
|
+
* @param runner - executes one registered Pi command by its Pi name.
|
|
1288
|
+
* @returns a disposer that unregisters the runner.
|
|
1289
|
+
*/
|
|
1290
|
+
registerCommandRunner(sessionId, packageName, runner) {
|
|
1291
|
+
const runners = this.#commandRunners.get(sessionId) ?? /* @__PURE__ */ new Map();
|
|
1292
|
+
runners.set(packageName, runner);
|
|
1293
|
+
this.#commandRunners.set(sessionId, runners);
|
|
1294
|
+
return () => {
|
|
1295
|
+
const live = this.#commandRunners.get(sessionId);
|
|
1296
|
+
if (live === void 0) return;
|
|
1297
|
+
if (live.get(packageName) === runner) live.delete(packageName);
|
|
1298
|
+
if (live.size === 0) this.#commandRunners.delete(sessionId);
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
/** The registered runner for (session, package), when one is mounted. */
|
|
1302
|
+
commandRunner(sessionId, packageName) {
|
|
1303
|
+
return this.#commandRunners.get(sessionId)?.get(packageName);
|
|
1304
|
+
}
|
|
1305
|
+
/**
|
|
1270
1306
|
* The panel's view of one parent session.
|
|
1271
1307
|
* @param parentSessionId - session the browser is currently showing.
|
|
1272
1308
|
* @returns every side thread opened under it, oldest first.
|
|
@@ -1314,11 +1350,56 @@ var BrowserSurfaces = class {
|
|
|
1314
1350
|
setWidget(sessionId, packageName, key, content, theme) {
|
|
1315
1351
|
if (sessionId.length === 0) return;
|
|
1316
1352
|
const view = this.#view(sessionId, packageName);
|
|
1353
|
+
const slot = `${sessionId}${packageName ?? "pi"}${key}`;
|
|
1354
|
+
this.#factoryComponents.get(slot)?.dispose?.();
|
|
1355
|
+
this.#factoryComponents.delete(slot);
|
|
1356
|
+
if (typeof content === "function") {
|
|
1357
|
+
this.#mountFactory(slot, content, theme, (text) => {
|
|
1358
|
+
const live = this.#view(sessionId, packageName);
|
|
1359
|
+
if (text === void 0) delete live.widgets[key];
|
|
1360
|
+
else live.widgets[key] = text;
|
|
1361
|
+
});
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1317
1364
|
const text = surfaceText(content, theme);
|
|
1318
1365
|
if (text === void 0) delete view.widgets[key];
|
|
1319
1366
|
else view.widgets[key] = text;
|
|
1320
1367
|
}
|
|
1321
1368
|
/**
|
|
1369
|
+
* Mount one `(tui, theme) => Component` factory: run it with a live driver,
|
|
1370
|
+
* render the retained component now, and re-render it into the same slot on
|
|
1371
|
+
* every requestRender. A factory or render that throws leaves the slot
|
|
1372
|
+
* empty — the package's own bug stays its own — but a RETAINED handle keeps
|
|
1373
|
+
* working for the component's lifetime.
|
|
1374
|
+
* @param slot - identity for the retained component (dispose-on-replace).
|
|
1375
|
+
* @param factory - the package's factory, exactly as passed to setWidget.
|
|
1376
|
+
* @param theme - the bridge's headless theme.
|
|
1377
|
+
* @param store - writes rendered text (or undefined to clear) into the slot.
|
|
1378
|
+
*/
|
|
1379
|
+
#mountFactory(slot, factory, theme, store) {
|
|
1380
|
+
let component;
|
|
1381
|
+
const render = () => {
|
|
1382
|
+
if (component === void 0) return;
|
|
1383
|
+
if (this.#factoryComponents.get(slot) !== component) return;
|
|
1384
|
+
store(surfaceText(component, theme));
|
|
1385
|
+
};
|
|
1386
|
+
const driver = { requestRender: () => {
|
|
1387
|
+
render();
|
|
1388
|
+
} };
|
|
1389
|
+
try {
|
|
1390
|
+
component = factory(driver, theme);
|
|
1391
|
+
} catch {
|
|
1392
|
+
store(void 0);
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
if (component === null || typeof component?.render !== "function") {
|
|
1396
|
+
store(void 0);
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
this.#factoryComponents.set(slot, component);
|
|
1400
|
+
render();
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1322
1403
|
* Record one simple presentation call (working chrome, title, header,
|
|
1323
1404
|
* footer). The value is a string, a Pi component, a working-indicator
|
|
1324
1405
|
* options object, or a header/footer factory; each renders to text here so
|
|
@@ -1634,6 +1715,34 @@ function registerBrowserSurfaceRoute(ctx, registry, hooks) {
|
|
|
1634
1715
|
response.end(JSON.stringify(outcome ?? { ok: true }));
|
|
1635
1716
|
return;
|
|
1636
1717
|
}
|
|
1718
|
+
if (url.pathname === "/pi2dsh/pi-command" && method === "POST") {
|
|
1719
|
+
const chunks = [];
|
|
1720
|
+
const raw = await new Promise((settle) => {
|
|
1721
|
+
const stream = req;
|
|
1722
|
+
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
1723
|
+
stream.on("end", () => settle(Buffer.concat(chunks).toString("utf8")));
|
|
1724
|
+
});
|
|
1725
|
+
try {
|
|
1726
|
+
const payload = JSON.parse(raw || "{}");
|
|
1727
|
+
if (typeof payload.session !== "string" || typeof payload.package !== "string" || typeof payload.command !== "string") throw new TypeError("pi-command needs { session, package, command }");
|
|
1728
|
+
const runner = registry.commandRunner(payload.session, payload.package);
|
|
1729
|
+
if (runner === void 0) {
|
|
1730
|
+
response.writeHead(404, { "content-type": "application/json; charset=utf-8" });
|
|
1731
|
+
response.end(JSON.stringify({ error: `no ${payload.package} command runner mounted for this session` }));
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
const notice = await runner(payload.command, typeof payload.args === "string" ? payload.args : "");
|
|
1735
|
+
response.writeHead(200, { "content-type": "application/json; charset=utf-8" });
|
|
1736
|
+
response.end(JSON.stringify({
|
|
1737
|
+
ok: true,
|
|
1738
|
+
...notice === void 0 ? {} : { notice }
|
|
1739
|
+
}));
|
|
1740
|
+
} catch (error) {
|
|
1741
|
+
response.writeHead(400, { "content-type": "application/json; charset=utf-8" });
|
|
1742
|
+
response.end(JSON.stringify({ error: error instanceof Error ? error.message : String(error) }));
|
|
1743
|
+
}
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1637
1746
|
if (method === "POST" && (url.pathname === "/pi2dsh/scene-input" || url.pathname === "/pi2dsh/scene-close")) {
|
|
1638
1747
|
const chunks = [];
|
|
1639
1748
|
const body = await new Promise((settle) => {
|
|
@@ -4174,7 +4283,7 @@ function projectDialogPrompt(title, supplementalDetail, linkMode) {
|
|
|
4174
4283
|
...detail.length === 0 ? {} : { detail }
|
|
4175
4284
|
};
|
|
4176
4285
|
}
|
|
4177
|
-
function contextFor(ctx, state, agent, signal, command = false, sessionOverride) {
|
|
4286
|
+
function contextFor(ctx, state, agent, signal, command = false, sessionOverride, headlessUi = false) {
|
|
4178
4287
|
const notices = [];
|
|
4179
4288
|
const userQuestions = optionalService(ctx, "userQuestions");
|
|
4180
4289
|
const dialogLinkMode = optionalService(ctx, "tuiScenes") === void 0 ? "markdown" : "terminal";
|
|
@@ -4240,6 +4349,7 @@ function contextFor(ctx, state, agent, signal, command = false, sessionOverride)
|
|
|
4240
4349
|
setTitle: (title) => putSurface(ctx, state, agent, "title", title),
|
|
4241
4350
|
custom: async (factory, options) => {
|
|
4242
4351
|
if (typeof factory !== "function") return void 0;
|
|
4352
|
+
if (headlessUi) return void 0;
|
|
4243
4353
|
const surfaces = state.tuiSurfaces;
|
|
4244
4354
|
if (surfaces !== void 0) return surfaces.custom(factory, state.theme, getKeybindings(), options);
|
|
4245
4355
|
const browser = state.shared.browserSurfaces;
|
|
@@ -4456,7 +4566,7 @@ function contextFor(ctx, state, agent, signal, command = false, sessionOverride)
|
|
|
4456
4566
|
scopedModels: [],
|
|
4457
4567
|
thinkingLevel: thinkingLevelOf(state, agent),
|
|
4458
4568
|
isIdle: () => command,
|
|
4459
|
-
isProjectTrusted: () =>
|
|
4569
|
+
isProjectTrusted: () => agent !== void 0 && contextCwd.length > 0,
|
|
4460
4570
|
signal,
|
|
4461
4571
|
abort: () => {
|
|
4462
4572
|
const target = agent;
|
|
@@ -5872,16 +5982,16 @@ function ensureLoginCommand(ctx, state) {
|
|
|
5872
5982
|
logger(ctx).debug("[pi2dsh] native terminal owns /login and the authorization service is composed; Pi OAuth flows are available through it");
|
|
5873
5983
|
return;
|
|
5874
5984
|
}
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
const registered = state.shared.loginRegistered ??= /* @__PURE__ */ new WeakSet();
|
|
5878
|
-
if (registered.has(owner)) return;
|
|
5879
|
-
registered.add(owner);
|
|
5985
|
+
if (state.shared.loginCommandRegistered === true) return;
|
|
5986
|
+
state.shared.loginCommandRegistered = true;
|
|
5880
5987
|
try {
|
|
5881
5988
|
registerLoginCommand(ctx, state);
|
|
5989
|
+
ctx.effect(() => () => {
|
|
5990
|
+
state.shared.loginCommandRegistered = false;
|
|
5991
|
+
});
|
|
5882
5992
|
} catch (error) {
|
|
5883
|
-
|
|
5884
|
-
logger(ctx).warn(`[pi2dsh] /login
|
|
5993
|
+
state.shared.loginCommandRegistered = false;
|
|
5994
|
+
logger(ctx).warn(`[pi2dsh] /login could not be registered; provider logins remain available on the host's own sign-in surface (${error instanceof Error ? error.message : String(error)})`);
|
|
5885
5995
|
}
|
|
5886
5996
|
}
|
|
5887
5997
|
/**
|
|
@@ -7277,7 +7387,7 @@ async function applyPiPackage(ctx, options) {
|
|
|
7277
7387
|
});
|
|
7278
7388
|
}
|
|
7279
7389
|
const browserSurfaces = state.shared.browserSurfaces ??= new BrowserSurfaces();
|
|
7280
|
-
if (state.shared.browserSurfacesRouted !== true) {
|
|
7390
|
+
if (options.config?.browserPresentation === true && state.shared.browserSurfacesRouted !== true) {
|
|
7281
7391
|
const sessionCwd = (session) => {
|
|
7282
7392
|
const cwd = ctx.get("sessions")?.get?.(session)?.header?.cwd;
|
|
7283
7393
|
if (typeof cwd === "string" && cwd.length > 0) return cwd;
|
|
@@ -7383,6 +7493,21 @@ async function applyPiPackage(ctx, options) {
|
|
|
7383
7493
|
}
|
|
7384
7494
|
return rendered;
|
|
7385
7495
|
}));
|
|
7496
|
+
const runnerSessionId = ownerAgent === void 0 ? "" : String(agentSession(ownerAgent)?.id ?? "");
|
|
7497
|
+
if (runnerSessionId.length > 0) {
|
|
7498
|
+
const disposeRunner = browserSurfaces.registerCommandRunner(runnerSessionId, state.packageName, async (name, args) => {
|
|
7499
|
+
const live = state.commands.get(name);
|
|
7500
|
+
if (live === void 0) throw new Error(`${state.packageName} has no command ${JSON.stringify(name)}`);
|
|
7501
|
+
const commandContext = contextFor(ctx, state, ownerAgent, void 0, true, void 0, true);
|
|
7502
|
+
await runInPiRuntime(state, ownerAgent, async () => {
|
|
7503
|
+
await ensurePiSessionStarted(ctx, state, ownerAgent, void 0);
|
|
7504
|
+
await live.handler(args, commandContext);
|
|
7505
|
+
});
|
|
7506
|
+
const notices = commandContext.__notices;
|
|
7507
|
+
return notices.length > 0 ? notices.join("\n") : void 0;
|
|
7508
|
+
});
|
|
7509
|
+
ctx.effect(() => disposeRunner);
|
|
7510
|
+
}
|
|
7386
7511
|
state.subagentSessionFactory = async (subagentOptions) => {
|
|
7387
7512
|
const created = await createBridgedAgentSession(subagentHost(), subagentOptions);
|
|
7388
7513
|
const parent = agentSession(currentAgent(state));
|
|
@@ -7533,4 +7658,4 @@ const runtimeInternals = {
|
|
|
7533
7658
|
//#endregion
|
|
7534
7659
|
export { overlayProviderConfig as a, runtimeInternals as c, normalizeToolSchema as i, getSharedChildExtensionCatalog as n, registerChildExtensionCatalog as o, mergeProviderRegistration as r, registerVisionCompanions as s, applyPiPackage as t };
|
|
7535
7660
|
|
|
7536
|
-
//# sourceMappingURL=runtime-
|
|
7661
|
+
//# sourceMappingURL=runtime-BVrvJuiO.mjs.map
|