pi2dsh 0.18.0 → 0.20.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 +46 -2
- package/README.zh.md +26 -0
- package/dist/{analyzer-BcuRfHLG.mjs → analyzer-BL7Nfvko.mjs} +2 -2
- package/dist/{analyzer-BcuRfHLG.mjs.map → analyzer-BL7Nfvko.mjs.map} +1 -1
- package/dist/cli.mjs +3 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/client.js +118 -1
- package/dist/compat/pi-coding-agent.d.mts +2 -2
- package/dist/compat/pi-coding-agent.mjs +2 -2
- package/dist/{mcp-config-NvRpjToH.mjs → compatibility-D_PV1zgF.mjs} +10 -187
- package/dist/compatibility-D_PV1zgF.mjs.map +1 -0
- package/dist/credentials-oauth.mjs +1 -1
- package/dist/host.d.mts +9 -2
- package/dist/host.d.mts.map +1 -1
- package/dist/host.mjs +7 -2
- package/dist/host.mjs.map +1 -1
- package/dist/index.d.mts +8 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +154 -8
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-config-C1K-IzzB.mjs +180 -0
- package/dist/mcp-config-C1K-IzzB.mjs.map +1 -0
- package/dist/{pi-coding-agent-DXJ_Jzo0.mjs → pi-coding-agent-CPXFo0UO.mjs} +0 -0
- package/dist/pi-coding-agent-CPXFo0UO.mjs.map +1 -0
- package/dist/{pi-coding-agent-69yY0ke-.d.mts → pi-coding-agent-Pvy0m9tS.d.mts} +6 -2
- package/dist/{pi-coding-agent-69yY0ke-.d.mts.map → pi-coding-agent-Pvy0m9tS.d.mts.map} +1 -1
- package/dist/{runtime-C-cmLDY0.mjs → runtime-CBZcd1uU.mjs} +592 -21
- package/dist/runtime-CBZcd1uU.mjs.map +1 -0
- package/dist/runtime.d.mts +106 -68
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +2 -2
- package/package.json +7 -2
- package/dist/mcp-config-NvRpjToH.mjs.map +0 -1
- package/dist/pi-coding-agent-DXJ_Jzo0.mjs.map +0 -1
- package/dist/runtime-C-cmLDY0.mjs.map +0 -1
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import { Dn as PiCapabilityError, En as CapabilityLedger, F as generateBranchSummary, b as Theme, d as ExtensionRunner, w as __runWithSubagentSessionFactory } from "./pi-coding-agent-CPXFo0UO.mjs";
|
|
3
3
|
import { t as getAgentDir } from "./pi-config-shim-CZ1wFzqM.mjs";
|
|
4
4
|
import { $ as AssistantMessageEventStream, S as getSupportedThinkingLevels, c as builtinProviders, et as isContextOverflow, o as __runWithPiAiRuntime, r as __createPiAiRuntimeRegistry } from "./pi-ai-DQPHUR9S.mjs";
|
|
5
5
|
import { W as getKeybindings, _t as stripTerminalSequences } from "./pi-tui-DruSeKmd.mjs";
|
|
6
|
+
import { r as piMcpConfigPaths, t as collectPiMcpServers } from "./mcp-config-C1K-IzzB.mjs";
|
|
6
7
|
import { c as resolvePiProviderAuth, i as oauthCredentialRef, l as storedOAuthCredential, n as joinSignals, o as providerSupportsOAuth, r as loginPiProvider, t as FileCredentialStore } from "./oauth-bridge-C_MAPMGA.mjs";
|
|
7
8
|
import { createRequire } from "node:module";
|
|
8
9
|
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
9
10
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, unlinkSync } from "node:fs";
|
|
10
11
|
import { basename, dirname, join, resolve } from "node:path";
|
|
11
12
|
import { fileURLToPath } from "node:url";
|
|
12
|
-
import { tmpdir } from "node:os";
|
|
13
|
+
import { homedir, tmpdir } from "node:os";
|
|
13
14
|
import { EventEmitter } from "node:events";
|
|
14
15
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
15
16
|
import { createJiti } from "jiti";
|
|
@@ -912,7 +913,21 @@ var PiBridgedAgentSession = class {
|
|
|
912
913
|
this.#restrictionDispose = toolsService.restrict({ allow: this.#activeToolNames.map(nativeToolNameOf).filter((name) => known.has(name)) });
|
|
913
914
|
} catch {}
|
|
914
915
|
}
|
|
915
|
-
|
|
916
|
+
/** Per-extension mount failures recorded at creation, for bindExtensions' onError. */
|
|
917
|
+
#extensionFailures = [];
|
|
918
|
+
adoptExtensionFailures(failures) {
|
|
919
|
+
this.#extensionFailures = failures;
|
|
920
|
+
}
|
|
921
|
+
async bindExtensions(bindings = {}) {
|
|
922
|
+
const onError = bindings.onError;
|
|
923
|
+
if (typeof onError !== "function") return;
|
|
924
|
+
for (const failure of this.#extensionFailures) try {
|
|
925
|
+
onError({
|
|
926
|
+
extensionPath: failure.name,
|
|
927
|
+
error: failure.error
|
|
928
|
+
});
|
|
929
|
+
} catch {}
|
|
930
|
+
}
|
|
916
931
|
async dispose() {
|
|
917
932
|
for (const dispose of this.#disposers.splice(0)) try {
|
|
918
933
|
dispose();
|
|
@@ -1068,8 +1083,23 @@ async function createBridgedAgentSession(host, options) {
|
|
|
1068
1083
|
}
|
|
1069
1084
|
const thinkingLevel = typeof options.thinkingLevel === "string" ? options.thinkingLevel : void 0;
|
|
1070
1085
|
host.adoptChildAgent?.(handle.agent, thinkingLevel);
|
|
1086
|
+
let extensionFailures = [];
|
|
1087
|
+
try {
|
|
1088
|
+
extensionFailures = await host.mountChildExtensions?.(handle.agent, options.resourceLoader) ?? [];
|
|
1089
|
+
} catch (error) {
|
|
1090
|
+
extensionFailures = [{
|
|
1091
|
+
name: "pi2dsh:child-extensions",
|
|
1092
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1093
|
+
}];
|
|
1094
|
+
}
|
|
1095
|
+
for (const failure of extensionFailures) {
|
|
1096
|
+
const message = `[pi2dsh] child extension ${JSON.stringify(failure.name)} did not mount: ${failure.error}`;
|
|
1097
|
+
host.cordis.logger?.warn?.(message);
|
|
1098
|
+
console.warn(message);
|
|
1099
|
+
}
|
|
1071
1100
|
const session = new PiBridgedAgentSession(host, handle, tools, thinkingLevel);
|
|
1072
1101
|
session.adoptRestriction(initialRestrictionDispose);
|
|
1102
|
+
session.adoptExtensionFailures(extensionFailures);
|
|
1073
1103
|
return { session };
|
|
1074
1104
|
}
|
|
1075
1105
|
//#endregion
|
|
@@ -1123,6 +1153,102 @@ var BrowserSurfaces = class {
|
|
|
1123
1153
|
imageToolNames() {
|
|
1124
1154
|
return [...this.#imageToolNames];
|
|
1125
1155
|
}
|
|
1156
|
+
#scene;
|
|
1157
|
+
#sceneRevision = 0;
|
|
1158
|
+
#sceneWidth = 100;
|
|
1159
|
+
openScene(packageName, factory, theme, keybindings, options) {
|
|
1160
|
+
this.#finishScene(void 0);
|
|
1161
|
+
return new Promise((resolve, reject) => {
|
|
1162
|
+
const run = {
|
|
1163
|
+
package: packageName,
|
|
1164
|
+
component: void 0,
|
|
1165
|
+
options,
|
|
1166
|
+
resolve,
|
|
1167
|
+
reject
|
|
1168
|
+
};
|
|
1169
|
+
this.#scene = run;
|
|
1170
|
+
const driver = { requestRender: () => this.#invalidateScene() };
|
|
1171
|
+
const done = (value) => {
|
|
1172
|
+
if (this.#scene !== run) return;
|
|
1173
|
+
this.#finishScene(value);
|
|
1174
|
+
};
|
|
1175
|
+
Promise.resolve().then(() => factory(driver, theme, keybindings, done)).then((component) => {
|
|
1176
|
+
if (this.#scene !== run) {
|
|
1177
|
+
component.dispose?.();
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
if (typeof component?.render !== "function") {
|
|
1181
|
+
this.#scene = void 0;
|
|
1182
|
+
this.#invalidateScene();
|
|
1183
|
+
console.warn(`[pi2dsh] web scene for ${packageName}: component lacks render(width)`);
|
|
1184
|
+
reject(/* @__PURE__ */ new TypeError("Pi custom component must implement render(width)"));
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
run.component = component;
|
|
1188
|
+
this.#invalidateScene();
|
|
1189
|
+
}, (error) => {
|
|
1190
|
+
if (this.#scene !== run) return;
|
|
1191
|
+
this.#scene = void 0;
|
|
1192
|
+
this.#invalidateScene();
|
|
1193
|
+
console.warn(`[pi2dsh] web scene for ${packageName}: component factory failed: ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
|
|
1194
|
+
reject(error);
|
|
1195
|
+
});
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
/** What the browser paints: the live component's frame, or a closed marker. */
|
|
1199
|
+
sceneSnapshot() {
|
|
1200
|
+
const scene = this.#scene;
|
|
1201
|
+
if (scene?.component === void 0) return {
|
|
1202
|
+
open: false,
|
|
1203
|
+
revision: this.#sceneRevision
|
|
1204
|
+
};
|
|
1205
|
+
const requested = (typeof scene.options?.overlayOptions === "function" ? scene.options.overlayOptions() : scene.options?.overlayOptions)?.width;
|
|
1206
|
+
const width = typeof requested === "number" && Number.isFinite(requested) && requested > 0 ? Math.min(this.#sceneWidth, Math.floor(requested)) : this.#sceneWidth;
|
|
1207
|
+
let lines;
|
|
1208
|
+
try {
|
|
1209
|
+
lines = scene.component.render(width);
|
|
1210
|
+
} catch (error) {
|
|
1211
|
+
const failed = this.#scene;
|
|
1212
|
+
this.#scene = void 0;
|
|
1213
|
+
this.#invalidateScene();
|
|
1214
|
+
console.warn(`[pi2dsh] web scene for ${scene.package}: render(width) failed: ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
|
|
1215
|
+
failed?.reject(error);
|
|
1216
|
+
return {
|
|
1217
|
+
open: false,
|
|
1218
|
+
revision: this.#sceneRevision
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
return {
|
|
1222
|
+
open: true,
|
|
1223
|
+
package: scene.package,
|
|
1224
|
+
revision: this.#sceneRevision,
|
|
1225
|
+
lines
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
/** Raw terminal input from the browser keyboard, verbatim into the component. */
|
|
1229
|
+
sceneInput(sequence, width) {
|
|
1230
|
+
if (typeof width === "number" && Number.isFinite(width)) this.#sceneWidth = Math.max(20, Math.min(400, Math.floor(width)));
|
|
1231
|
+
const component = this.#scene?.component;
|
|
1232
|
+
if (component === void 0 || sequence.length === 0) return;
|
|
1233
|
+
component.handleInput?.(sequence);
|
|
1234
|
+
component.invalidate?.();
|
|
1235
|
+
this.#invalidateScene();
|
|
1236
|
+
}
|
|
1237
|
+
/** The browser dismissed the overlay: resolve the Pi caller with undefined. */
|
|
1238
|
+
closeScene() {
|
|
1239
|
+
this.#finishScene(void 0);
|
|
1240
|
+
}
|
|
1241
|
+
#finishScene(value) {
|
|
1242
|
+
const scene = this.#scene;
|
|
1243
|
+
if (scene === void 0) return;
|
|
1244
|
+
this.#scene = void 0;
|
|
1245
|
+
scene.component?.dispose?.();
|
|
1246
|
+
this.#invalidateScene();
|
|
1247
|
+
scene.resolve(value);
|
|
1248
|
+
}
|
|
1249
|
+
#invalidateScene() {
|
|
1250
|
+
this.#sceneRevision += 1;
|
|
1251
|
+
}
|
|
1126
1252
|
/**
|
|
1127
1253
|
* Track one child session under its parent.
|
|
1128
1254
|
* @param parentSessionId - the session the panel floats over.
|
|
@@ -1442,7 +1568,7 @@ function publishAuthorization(url) {
|
|
|
1442
1568
|
function revokeAuthorization(path) {
|
|
1443
1569
|
pendingAuthorizations.delete(path.slice(18));
|
|
1444
1570
|
}
|
|
1445
|
-
function registerBrowserSurfaceRoute(ctx, registry) {
|
|
1571
|
+
function registerBrowserSurfaceRoute(ctx, registry, hooks) {
|
|
1446
1572
|
const web = ctx.get("webServer");
|
|
1447
1573
|
if (web === void 0 || typeof web.register !== "function") return false;
|
|
1448
1574
|
ctx.effect(() => web.register({
|
|
@@ -1467,6 +1593,63 @@ function registerBrowserSurfaceRoute(ctx, registry) {
|
|
|
1467
1593
|
response.end();
|
|
1468
1594
|
return;
|
|
1469
1595
|
}
|
|
1596
|
+
if (url.pathname === "/pi2dsh/mcp-state" && (method === "GET" || method === "HEAD")) {
|
|
1597
|
+
if (hooks?.mcpState === void 0) {
|
|
1598
|
+
response.writeHead(404);
|
|
1599
|
+
response.end();
|
|
1600
|
+
return;
|
|
1601
|
+
}
|
|
1602
|
+
const body = JSON.stringify(await hooks.mcpState(url.searchParams.get("session") ?? ""));
|
|
1603
|
+
response.writeHead(200, {
|
|
1604
|
+
"content-type": "application/json; charset=utf-8",
|
|
1605
|
+
"cache-control": "no-store"
|
|
1606
|
+
});
|
|
1607
|
+
response.end(method === "HEAD" ? void 0 : body);
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
if (url.pathname === "/pi2dsh/mcp-action" && method === "POST") {
|
|
1611
|
+
if (hooks?.mcpAction === void 0) {
|
|
1612
|
+
response.writeHead(404);
|
|
1613
|
+
response.end();
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
const chunks = [];
|
|
1617
|
+
const raw = await new Promise((settle) => {
|
|
1618
|
+
const stream = req;
|
|
1619
|
+
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
1620
|
+
stream.on("end", () => settle(Buffer.concat(chunks).toString("utf8")));
|
|
1621
|
+
});
|
|
1622
|
+
let outcome;
|
|
1623
|
+
try {
|
|
1624
|
+
const payload = JSON.parse(raw || "{}");
|
|
1625
|
+
if (typeof payload.session !== "string" || typeof payload.server !== "string" || typeof payload.disabled !== "boolean") throw new TypeError("mcp-action needs { session, server, disabled }");
|
|
1626
|
+
const scope = payload.scope === "global" ? "global" : "project";
|
|
1627
|
+
outcome = await hooks.mcpAction(payload.session, payload.server, payload.disabled, scope);
|
|
1628
|
+
} catch (error) {
|
|
1629
|
+
response.writeHead(400, { "content-type": "application/json; charset=utf-8" });
|
|
1630
|
+
response.end(JSON.stringify({ error: error instanceof Error ? error.message : String(error) }));
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
response.writeHead(200, { "content-type": "application/json; charset=utf-8" });
|
|
1634
|
+
response.end(JSON.stringify(outcome ?? { ok: true }));
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
if (method === "POST" && (url.pathname === "/pi2dsh/scene-input" || url.pathname === "/pi2dsh/scene-close")) {
|
|
1638
|
+
const chunks = [];
|
|
1639
|
+
const body = await new Promise((settle) => {
|
|
1640
|
+
const stream = req;
|
|
1641
|
+
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
1642
|
+
stream.on("end", () => settle(Buffer.concat(chunks).toString("utf8")));
|
|
1643
|
+
});
|
|
1644
|
+
if (url.pathname === "/pi2dsh/scene-close") registry.closeScene();
|
|
1645
|
+
else try {
|
|
1646
|
+
const payload = JSON.parse(body || "{}");
|
|
1647
|
+
if (typeof payload.sequence === "string") registry.sceneInput(payload.sequence, typeof payload.width === "number" ? payload.width : void 0);
|
|
1648
|
+
} catch {}
|
|
1649
|
+
response.writeHead(204);
|
|
1650
|
+
response.end();
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1470
1653
|
if (method !== "GET" && method !== "HEAD") {
|
|
1471
1654
|
response.writeHead(405);
|
|
1472
1655
|
response.end();
|
|
@@ -1512,11 +1695,13 @@ function registerBrowserSurfaceRoute(ctx, registry) {
|
|
|
1512
1695
|
const body = JSON.stringify(session === "" ? {
|
|
1513
1696
|
threads: [],
|
|
1514
1697
|
surfaces: [],
|
|
1515
|
-
entries: []
|
|
1698
|
+
entries: [],
|
|
1699
|
+
scene: registry.sceneSnapshot()
|
|
1516
1700
|
} : {
|
|
1517
1701
|
threads: registry.snapshot(session),
|
|
1518
1702
|
surfaces: registry.surfaces(session),
|
|
1519
1703
|
entries: registry.entries(session),
|
|
1704
|
+
scene: registry.sceneSnapshot(),
|
|
1520
1705
|
...registry.draftRequest(session) === void 0 ? {} : { draft: registry.draftRequest(session) }
|
|
1521
1706
|
});
|
|
1522
1707
|
response.writeHead(200, {
|
|
@@ -3001,7 +3186,7 @@ function registerPiProviderRoute(options) {
|
|
|
3001
3186
|
}
|
|
3002
3187
|
//#endregion
|
|
3003
3188
|
//#region src/tui-surfaces.ts
|
|
3004
|
-
function service(ctx, name) {
|
|
3189
|
+
function service$1(ctx, name) {
|
|
3005
3190
|
try {
|
|
3006
3191
|
return ctx.get(name, false);
|
|
3007
3192
|
} catch {
|
|
@@ -3048,6 +3233,8 @@ function preferredWidth(options) {
|
|
|
3048
3233
|
var TuiSurfaceAdapter = class {
|
|
3049
3234
|
packageName;
|
|
3050
3235
|
instanceKey;
|
|
3236
|
+
kind = "tuiScenes";
|
|
3237
|
+
nativeCommands = dshTuiLocalCommands();
|
|
3051
3238
|
sceneId;
|
|
3052
3239
|
scenes;
|
|
3053
3240
|
status;
|
|
@@ -3060,10 +3247,10 @@ var TuiSurfaceAdapter = class {
|
|
|
3060
3247
|
constructor(ctx, packageName, instanceKey) {
|
|
3061
3248
|
this.packageName = packageName;
|
|
3062
3249
|
this.instanceKey = instanceKey;
|
|
3063
|
-
const scenes = service(ctx, "tuiScenes");
|
|
3250
|
+
const scenes = service$1(ctx, "tuiScenes");
|
|
3064
3251
|
if (scenes === void 0) throw new Error("pi2dsh: dsh-TUI scene service is unavailable");
|
|
3065
3252
|
this.scenes = scenes;
|
|
3066
|
-
this.status = service(ctx, "tuiStatus");
|
|
3253
|
+
this.status = service$1(ctx, "tuiStatus");
|
|
3067
3254
|
this.sceneId = sceneIdFor(instanceKey === void 0 ? packageName : `${packageName}-${instanceKey}`);
|
|
3068
3255
|
this.unregisterScene = scenes.register({
|
|
3069
3256
|
id: this.sceneId,
|
|
@@ -3196,7 +3383,7 @@ function mountTuiSurfaceAdapter(ctx, packageName, publish, instanceKey) {
|
|
|
3196
3383
|
publish(void 0);
|
|
3197
3384
|
});
|
|
3198
3385
|
};
|
|
3199
|
-
if (service(ctx, "tuiScenes") !== void 0) {
|
|
3386
|
+
if (service$1(ctx, "tuiScenes") !== void 0) {
|
|
3200
3387
|
attach(ctx);
|
|
3201
3388
|
return;
|
|
3202
3389
|
}
|
|
@@ -3289,8 +3476,252 @@ function dshTuiLocalCommands() {
|
|
|
3289
3476
|
cachedTuiLocalCommands = tuiLocalCommandsForVersion(version);
|
|
3290
3477
|
return cachedTuiLocalCommands;
|
|
3291
3478
|
}
|
|
3292
|
-
|
|
3293
|
-
|
|
3479
|
+
/** Host-native command ownership, independent of the concrete TUI package. */
|
|
3480
|
+
function commandNameForTerminal(name, nativeCommands) {
|
|
3481
|
+
return nativeCommands?.has(name) === true ? `pi-${name}` : name;
|
|
3482
|
+
}
|
|
3483
|
+
/** Bridge fallback commands disappear when the active Host already owns one. */
|
|
3484
|
+
function shouldRegisterCompatibilityCommand(name, nativeCommands) {
|
|
3485
|
+
return nativeCommands?.has(name) !== true;
|
|
3486
|
+
}
|
|
3487
|
+
//#endregion
|
|
3488
|
+
//#region src/pi-component-relay.ts
|
|
3489
|
+
let relaySerial = 0;
|
|
3490
|
+
function relayId() {
|
|
3491
|
+
relaySerial += 1;
|
|
3492
|
+
return `pi2dsh-custom-${relaySerial}`;
|
|
3493
|
+
}
|
|
3494
|
+
/**
|
|
3495
|
+
* One Host-owned Pi component session expressed as data messages.
|
|
3496
|
+
*
|
|
3497
|
+
* The result value never crosses the presentation boundary: Pi's own `done`
|
|
3498
|
+
* callback completes it on the Host. Frames and input are deliberately plain
|
|
3499
|
+
* data so the presentation transport can change independently.
|
|
3500
|
+
*/
|
|
3501
|
+
var PiComponentRelay = class {
|
|
3502
|
+
sessionId = relayId();
|
|
3503
|
+
options;
|
|
3504
|
+
ready;
|
|
3505
|
+
result;
|
|
3506
|
+
component;
|
|
3507
|
+
invalidations = /* @__PURE__ */ new Set();
|
|
3508
|
+
resolveResult;
|
|
3509
|
+
rejectResult;
|
|
3510
|
+
revision = 0;
|
|
3511
|
+
closed = false;
|
|
3512
|
+
constructor(factory, theme, keybindings, options) {
|
|
3513
|
+
this.options = options;
|
|
3514
|
+
this.result = new Promise((resolve, reject) => {
|
|
3515
|
+
this.resolveResult = resolve;
|
|
3516
|
+
this.rejectResult = reject;
|
|
3517
|
+
});
|
|
3518
|
+
const driver = { requestRender: () => this.invalidate() };
|
|
3519
|
+
const done = (value) => this.close(value);
|
|
3520
|
+
this.ready = Promise.resolve().then(() => factory(driver, theme, keybindings, done)).then((component) => {
|
|
3521
|
+
if (this.closed) {
|
|
3522
|
+
component.dispose?.();
|
|
3523
|
+
return false;
|
|
3524
|
+
}
|
|
3525
|
+
if (typeof component?.render !== "function") throw new TypeError("Pi custom component must implement render(width)");
|
|
3526
|
+
this.component = component;
|
|
3527
|
+
this.invalidate();
|
|
3528
|
+
return true;
|
|
3529
|
+
}).catch((error) => {
|
|
3530
|
+
this.fail(error);
|
|
3531
|
+
return false;
|
|
3532
|
+
});
|
|
3533
|
+
}
|
|
3534
|
+
get active() {
|
|
3535
|
+
return !this.closed;
|
|
3536
|
+
}
|
|
3537
|
+
onInvalidate(listener) {
|
|
3538
|
+
this.invalidations.add(listener);
|
|
3539
|
+
return () => this.invalidations.delete(listener);
|
|
3540
|
+
}
|
|
3541
|
+
frame(request) {
|
|
3542
|
+
if (request.sessionId !== this.sessionId) throw new Error("stale Pi component render session");
|
|
3543
|
+
const width = Math.max(1, Math.floor(request.width));
|
|
3544
|
+
return {
|
|
3545
|
+
sessionId: this.sessionId,
|
|
3546
|
+
revision: this.revision,
|
|
3547
|
+
width,
|
|
3548
|
+
lines: this.component?.render(width) ?? []
|
|
3549
|
+
};
|
|
3550
|
+
}
|
|
3551
|
+
input(message) {
|
|
3552
|
+
if (message.sessionId !== this.sessionId || this.closed) return;
|
|
3553
|
+
this.component?.handleInput?.(message.data);
|
|
3554
|
+
}
|
|
3555
|
+
invalidate() {
|
|
3556
|
+
if (this.closed) return;
|
|
3557
|
+
this.revision += 1;
|
|
3558
|
+
for (const listener of this.invalidations) listener(this.revision);
|
|
3559
|
+
}
|
|
3560
|
+
close(value) {
|
|
3561
|
+
if (this.closed) return;
|
|
3562
|
+
this.closed = true;
|
|
3563
|
+
const component = this.component;
|
|
3564
|
+
this.component = void 0;
|
|
3565
|
+
component?.dispose?.();
|
|
3566
|
+
this.invalidations.clear();
|
|
3567
|
+
this.resolveResult(value);
|
|
3568
|
+
}
|
|
3569
|
+
fail(error) {
|
|
3570
|
+
if (this.closed) return;
|
|
3571
|
+
this.closed = true;
|
|
3572
|
+
const component = this.component;
|
|
3573
|
+
this.component = void 0;
|
|
3574
|
+
component?.dispose?.();
|
|
3575
|
+
this.invalidations.clear();
|
|
3576
|
+
this.rejectResult(error);
|
|
3577
|
+
}
|
|
3578
|
+
};
|
|
3579
|
+
//#endregion
|
|
3580
|
+
//#region src/pi-tui-extension-surface.ts
|
|
3581
|
+
function service(ctx) {
|
|
3582
|
+
try {
|
|
3583
|
+
return ctx.get("piTuiExtensions", false);
|
|
3584
|
+
} catch {
|
|
3585
|
+
return;
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
function statusId(packageName, instanceKey, key) {
|
|
3589
|
+
return `pi2dsh-status-${`${packageName}${instanceKey === void 0 ? "" : `-${instanceKey}`}-${key}`.toLowerCase().replace(/[^a-z0-9_-]+/gu, "-").replace(/^-+|-+$/gu, "") || "entry"}`;
|
|
3590
|
+
}
|
|
3591
|
+
function overlayOptions(options) {
|
|
3592
|
+
const raw = typeof options?.overlayOptions === "function" ? options.overlayOptions() : options?.overlayOptions;
|
|
3593
|
+
return raw === void 0 ? void 0 : { ...raw };
|
|
3594
|
+
}
|
|
3595
|
+
/** dsh-pi-tui backend over the public `piTuiExtensions` service. */
|
|
3596
|
+
var PiTuiExtensionSurfaceAdapter = class {
|
|
3597
|
+
extensionService;
|
|
3598
|
+
unstableFacade;
|
|
3599
|
+
packageName;
|
|
3600
|
+
instanceKey;
|
|
3601
|
+
kind = "piTuiExtensions";
|
|
3602
|
+
nativeCommands;
|
|
3603
|
+
statusHandles = /* @__PURE__ */ new Map();
|
|
3604
|
+
mounts = /* @__PURE__ */ new Set();
|
|
3605
|
+
disposed = false;
|
|
3606
|
+
constructor(extensionService, unstableFacade, nativeCommands, packageName, instanceKey) {
|
|
3607
|
+
this.extensionService = extensionService;
|
|
3608
|
+
this.unstableFacade = unstableFacade;
|
|
3609
|
+
this.packageName = packageName;
|
|
3610
|
+
this.instanceKey = instanceKey;
|
|
3611
|
+
this.nativeCommands = new Set(nativeCommands);
|
|
3612
|
+
}
|
|
3613
|
+
get available() {
|
|
3614
|
+
if (this.disposed) return false;
|
|
3615
|
+
try {
|
|
3616
|
+
return this.extensionService.api().capabilities.has("unstable.surface.handle");
|
|
3617
|
+
} catch {
|
|
3618
|
+
return false;
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
setStatus(key, text) {
|
|
3622
|
+
if (this.disposed) return;
|
|
3623
|
+
const id = statusId(this.packageName, this.instanceKey, key);
|
|
3624
|
+
const previous = this.statusHandles.get(id);
|
|
3625
|
+
if (text === void 0) {
|
|
3626
|
+
previous?.dispose();
|
|
3627
|
+
this.statusHandles.delete(id);
|
|
3628
|
+
return;
|
|
3629
|
+
}
|
|
3630
|
+
const value = {
|
|
3631
|
+
spans: [{
|
|
3632
|
+
text: String(text),
|
|
3633
|
+
tone: "textDim"
|
|
3634
|
+
}],
|
|
3635
|
+
minWidth: 4,
|
|
3636
|
+
importance: 50
|
|
3637
|
+
};
|
|
3638
|
+
if (previous !== void 0) {
|
|
3639
|
+
previous.replace(value);
|
|
3640
|
+
return;
|
|
3641
|
+
}
|
|
3642
|
+
if (!this.extensionService.api().capabilities.has("slot.chrome.footer.status")) return;
|
|
3643
|
+
this.statusHandles.set(id, this.extensionService.register("chrome.footer.status", {
|
|
3644
|
+
id,
|
|
3645
|
+
order: 500,
|
|
3646
|
+
description: `Pi status ${key} from ${this.packageName}`
|
|
3647
|
+
}, value));
|
|
3648
|
+
}
|
|
3649
|
+
async custom(factory, theme, keybindings, options) {
|
|
3650
|
+
if (!this.available) return void 0;
|
|
3651
|
+
for (const active of [...this.mounts]) active.relay.close(void 0);
|
|
3652
|
+
const relay = new PiComponentRelay(factory, theme, keybindings, options);
|
|
3653
|
+
const record = { relay };
|
|
3654
|
+
this.mounts.add(record);
|
|
3655
|
+
try {
|
|
3656
|
+
if (!await relay.ready || !relay.active) return await relay.result;
|
|
3657
|
+
if (this.disposed) {
|
|
3658
|
+
relay.close(void 0);
|
|
3659
|
+
return await relay.result;
|
|
3660
|
+
}
|
|
3661
|
+
const lease = this.unstableFacade.surface.handle.mountComponent({
|
|
3662
|
+
render: (width) => relay.frame({
|
|
3663
|
+
sessionId: relay.sessionId,
|
|
3664
|
+
width
|
|
3665
|
+
}).lines,
|
|
3666
|
+
handleInput: (data) => relay.input({
|
|
3667
|
+
sessionId: relay.sessionId,
|
|
3668
|
+
data
|
|
3669
|
+
}),
|
|
3670
|
+
dispose: () => relay.close(void 0)
|
|
3671
|
+
}, overlayOptions(options));
|
|
3672
|
+
record.lease = lease;
|
|
3673
|
+
const offInvalidate = relay.onInvalidate(() => lease.invalidate());
|
|
3674
|
+
const release = () => {
|
|
3675
|
+
offInvalidate();
|
|
3676
|
+
lease.close();
|
|
3677
|
+
};
|
|
3678
|
+
relay.result.then(release, release);
|
|
3679
|
+
if (!lease.active) relay.close(void 0);
|
|
3680
|
+
lease.focus();
|
|
3681
|
+
return await relay.result;
|
|
3682
|
+
} catch (error) {
|
|
3683
|
+
relay.fail(error);
|
|
3684
|
+
throw error;
|
|
3685
|
+
} finally {
|
|
3686
|
+
this.mounts.delete(record);
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
dispose() {
|
|
3690
|
+
if (this.disposed) return;
|
|
3691
|
+
this.disposed = true;
|
|
3692
|
+
for (const handle of this.statusHandles.values()) handle.dispose();
|
|
3693
|
+
this.statusHandles.clear();
|
|
3694
|
+
for (const active of this.mounts) {
|
|
3695
|
+
active.relay.close(void 0);
|
|
3696
|
+
active.lease?.close();
|
|
3697
|
+
}
|
|
3698
|
+
this.mounts.clear();
|
|
3699
|
+
}
|
|
3700
|
+
};
|
|
3701
|
+
/**
|
|
3702
|
+
* Build the optional backend from published public entry points.
|
|
3703
|
+
* Returns undefined when the service is absent or cannot provide the exact
|
|
3704
|
+
* raw-component capability; callers then keep the existing dsh-TUI/Web path.
|
|
3705
|
+
*/
|
|
3706
|
+
async function createPiTuiExtensionSurfaceAdapter(ctx, packageName, instanceKey) {
|
|
3707
|
+
const extensionService = service(ctx);
|
|
3708
|
+
if (extensionService === void 0) return void 0;
|
|
3709
|
+
const api = extensionService.api();
|
|
3710
|
+
if (api.apiVersion !== 1 || !api.capabilities.has("unstable.surface.handle")) {
|
|
3711
|
+
ctx.logger?.warn(`pi2dsh: piTuiExtensions cannot host Pi components (api=${api.apiVersion}, raw surface=${api.capabilities.has("unstable.surface.handle")})`);
|
|
3712
|
+
return;
|
|
3713
|
+
}
|
|
3714
|
+
try {
|
|
3715
|
+
const [hostModule, unstableModule] = await Promise.all([import("@xmoon76/dsh-pi-tui"), import("@xmoon76/dsh-pi-tui/extensions/unstable")]);
|
|
3716
|
+
if (unstableModule.UNSTABLE_API_LEVEL !== 1) {
|
|
3717
|
+
ctx.logger?.warn(`pi2dsh: unsupported dsh-pi-tui unstable API level ${unstableModule.UNSTABLE_API_LEVEL}`);
|
|
3718
|
+
return;
|
|
3719
|
+
}
|
|
3720
|
+
return new PiTuiExtensionSurfaceAdapter(extensionService, unstableModule.unstable(extensionService), hostModule.LOCAL_COMMANDS, packageName, instanceKey);
|
|
3721
|
+
} catch (error) {
|
|
3722
|
+
ctx.logger?.warn(`pi2dsh: could not attach the public piTuiExtensions backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
3723
|
+
return;
|
|
3724
|
+
}
|
|
3294
3725
|
}
|
|
3295
3726
|
//#endregion
|
|
3296
3727
|
//#region src/runtime.ts
|
|
@@ -3808,9 +4239,11 @@ function contextFor(ctx, state, agent, signal, command = false, sessionOverride)
|
|
|
3808
4239
|
setHeader: (factory) => putSurface(ctx, state, agent, "header", factory),
|
|
3809
4240
|
setTitle: (title) => putSurface(ctx, state, agent, "title", title),
|
|
3810
4241
|
custom: async (factory, options) => {
|
|
4242
|
+
if (typeof factory !== "function") return void 0;
|
|
3811
4243
|
const surfaces = state.tuiSurfaces;
|
|
3812
|
-
if (surfaces
|
|
3813
|
-
|
|
4244
|
+
if (surfaces !== void 0) return surfaces.custom(factory, state.theme, getKeybindings(), options);
|
|
4245
|
+
const browser = state.shared.browserSurfaces;
|
|
4246
|
+
if (browser !== void 0 && state.shared.browserSurfacesRouted === true) return browser.openScene(state.packageName, factory, state.theme, getKeybindings(), options);
|
|
3814
4247
|
},
|
|
3815
4248
|
pasteToEditor(text) {
|
|
3816
4249
|
const surfaces = state.shared.browserSurfaces;
|
|
@@ -4007,7 +4440,8 @@ function contextFor(ctx, state, agent, signal, command = false, sessionOverride)
|
|
|
4007
4440
|
},
|
|
4008
4441
|
ui,
|
|
4009
4442
|
get mode() {
|
|
4010
|
-
|
|
4443
|
+
if (state.tuiSurfaces?.available === true) return "tui";
|
|
4444
|
+
return state.shared.browserSurfaces !== void 0 && state.shared.browserSurfacesRouted === true ? "tui" : "rpc";
|
|
4011
4445
|
},
|
|
4012
4446
|
get hasUI() {
|
|
4013
4447
|
return state.tuiSurfaces?.available === true || humanAnswererAvailable(userQuestions, agent);
|
|
@@ -5121,6 +5555,59 @@ function oauthStoreOf(state) {
|
|
|
5121
5555
|
}
|
|
5122
5556
|
const COMPANION_ROUTE_PREFIX = "pi2dsh-companion/";
|
|
5123
5557
|
const SHARED_HOST_STATE = /* @__PURE__ */ new WeakMap();
|
|
5558
|
+
function registerChildExtensionCatalog(ctx, catalog) {
|
|
5559
|
+
sharedHostStateOf(ctx).childExtensions = catalog;
|
|
5560
|
+
}
|
|
5561
|
+
/** Read the installed-package catalog registered on shared host state, or undefined. */
|
|
5562
|
+
function getSharedChildExtensionCatalog(ctx) {
|
|
5563
|
+
return sharedHostStateOf(ctx).childExtensions;
|
|
5564
|
+
}
|
|
5565
|
+
/**
|
|
5566
|
+
* Which installed packages a creator's resource loader selects for its child
|
|
5567
|
+
* — the creator's OWN filter code decides (the loader's getExtensions applies
|
|
5568
|
+
* noExtensions and extensionsOverride), this only maps the surviving entry
|
|
5569
|
+
* paths back to package names. No loader at all means Pi's default: the full
|
|
5570
|
+
* discovered set (sdk.ts builds a default loader and loads everything).
|
|
5571
|
+
*/
|
|
5572
|
+
function resolveChildExtensionPackages(loader, catalog) {
|
|
5573
|
+
if (loader === void 0 || loader === null) return {
|
|
5574
|
+
names: [...new Set(catalog.packageByEntryPath.values())],
|
|
5575
|
+
failures: []
|
|
5576
|
+
};
|
|
5577
|
+
const getExtensions = loader.getExtensions;
|
|
5578
|
+
if (typeof getExtensions !== "function") return {
|
|
5579
|
+
names: [],
|
|
5580
|
+
failures: []
|
|
5581
|
+
};
|
|
5582
|
+
const names = /* @__PURE__ */ new Set();
|
|
5583
|
+
const failures = [];
|
|
5584
|
+
let entries;
|
|
5585
|
+
try {
|
|
5586
|
+
entries = getExtensions.call(loader)?.extensions ?? [];
|
|
5587
|
+
} catch (error) {
|
|
5588
|
+
return {
|
|
5589
|
+
names: [],
|
|
5590
|
+
failures: [{
|
|
5591
|
+
name: "resourceLoader.getExtensions",
|
|
5592
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5593
|
+
}]
|
|
5594
|
+
};
|
|
5595
|
+
}
|
|
5596
|
+
for (const entry of entries) {
|
|
5597
|
+
const path = entry?.path;
|
|
5598
|
+
if (typeof path !== "string" || path.length === 0) continue;
|
|
5599
|
+
const name = catalog.packageByEntryPath.get(resolve(path));
|
|
5600
|
+
if (name !== void 0) names.add(name);
|
|
5601
|
+
else failures.push({
|
|
5602
|
+
name: path,
|
|
5603
|
+
error: "not an installed DSH plugin — path-loaded extensions are not supported on this host; install it with `dsh plugin add <pkg>`"
|
|
5604
|
+
});
|
|
5605
|
+
}
|
|
5606
|
+
return {
|
|
5607
|
+
names: [...names],
|
|
5608
|
+
failures
|
|
5609
|
+
};
|
|
5610
|
+
}
|
|
5124
5611
|
/**
|
|
5125
5612
|
* Pi's provider ledger is layered, not flat (model-runtime.ts:742-786 at the
|
|
5126
5613
|
* pinned upstream): a builtin base map, an extension overlay where defined
|
|
@@ -5381,6 +5868,10 @@ async function materializeAttachmentImage(ctx, attachment) {
|
|
|
5381
5868
|
}
|
|
5382
5869
|
}
|
|
5383
5870
|
function ensureLoginCommand(ctx, state) {
|
|
5871
|
+
if (!shouldRegisterCompatibilityCommand("login", state.tuiSurfaces?.nativeCommands) && optionalService(ctx, "authorization") !== void 0) {
|
|
5872
|
+
logger(ctx).debug("[pi2dsh] native terminal owns /login and the authorization service is composed; Pi OAuth flows are available through it");
|
|
5873
|
+
return;
|
|
5874
|
+
}
|
|
5384
5875
|
const scoped = scopeOf(ctx);
|
|
5385
5876
|
const owner = typeof scoped === "object" && scoped !== null ? scoped : ctx;
|
|
5386
5877
|
const registered = state.shared.loginRegistered ??= /* @__PURE__ */ new WeakSet();
|
|
@@ -6166,9 +6657,9 @@ function normalizedPiCommandName(piName) {
|
|
|
6166
6657
|
}
|
|
6167
6658
|
function dshCommandName(ctx, state, piName) {
|
|
6168
6659
|
const validName = normalizedPiCommandName(piName);
|
|
6169
|
-
const name =
|
|
6660
|
+
const name = commandNameForTerminal(validName, state.tuiSurfaces?.nativeCommands);
|
|
6170
6661
|
if (name !== piName) {
|
|
6171
|
-
const reason = name === `pi-${validName}` ? `because
|
|
6662
|
+
const reason = name === `pi-${validName}` ? `because the active terminal reserves /${validName} for its native command (host commands win on collisions)` : "to satisfy DSH command naming";
|
|
6172
6663
|
logger(ctx).warn(`[pi2dsh] Pi command /${piName} registered as /${name} ${reason}`);
|
|
6173
6664
|
}
|
|
6174
6665
|
return name;
|
|
@@ -6654,6 +7145,12 @@ async function applyPiPackage(ctx, options) {
|
|
|
6654
7145
|
const shared = sharedHostStateOf(ctx);
|
|
6655
7146
|
const scopedOwner = options.ownerAgent ?? scopeOf(ctx);
|
|
6656
7147
|
const ownerAgent = typeof scopedOwner === "object" && scopedOwner !== null ? scopedOwner : void 0;
|
|
7148
|
+
if (ownerAgent !== void 0 && options.hostAnchor !== true) {
|
|
7149
|
+
shared.childPackageTools ??= /* @__PURE__ */ new WeakMap();
|
|
7150
|
+
const byPackage = shared.childPackageTools.get(ownerAgent) ?? /* @__PURE__ */ new Map();
|
|
7151
|
+
byPackage.set(options.manifest.package.name, runtimeTools);
|
|
7152
|
+
shared.childPackageTools.set(ownerAgent, byPackage);
|
|
7153
|
+
}
|
|
6657
7154
|
const state = {
|
|
6658
7155
|
shared,
|
|
6659
7156
|
packageName: options.manifest.package.name,
|
|
@@ -6716,9 +7213,17 @@ async function applyPiPackage(ctx, options) {
|
|
|
6716
7213
|
publishedOAuthKeys: shared.publishedOAuthKeys,
|
|
6717
7214
|
tuiSurfaces: void 0
|
|
6718
7215
|
};
|
|
6719
|
-
|
|
7216
|
+
const surfaceInstanceKey = typeof ownerAgent?.id === "string" ? ownerAgent.id : void 0;
|
|
7217
|
+
const piTuiSurface = await createPiTuiExtensionSurfaceAdapter(ctx, state.packageName, surfaceInstanceKey);
|
|
7218
|
+
if (piTuiSurface !== void 0) {
|
|
7219
|
+
state.tuiSurfaces = piTuiSurface;
|
|
7220
|
+
ctx.effect(() => () => {
|
|
7221
|
+
piTuiSurface.dispose();
|
|
7222
|
+
if (state.tuiSurfaces === piTuiSurface) state.tuiSurfaces = void 0;
|
|
7223
|
+
});
|
|
7224
|
+
} else mountTuiSurfaceAdapter(ctx, state.packageName, (adapter) => {
|
|
6720
7225
|
state.tuiSurfaces = adapter;
|
|
6721
|
-
},
|
|
7226
|
+
}, surfaceInstanceKey);
|
|
6722
7227
|
subscribeLifecycle(ctx, state);
|
|
6723
7228
|
subscribeInterceptors(ctx, state);
|
|
6724
7229
|
shared.providerBuiltins ??= /* @__PURE__ */ new Map();
|
|
@@ -6772,7 +7277,57 @@ async function applyPiPackage(ctx, options) {
|
|
|
6772
7277
|
});
|
|
6773
7278
|
}
|
|
6774
7279
|
const browserSurfaces = state.shared.browserSurfaces ??= new BrowserSurfaces();
|
|
6775
|
-
if (state.shared.browserSurfacesRouted !== true)
|
|
7280
|
+
if (state.shared.browserSurfacesRouted !== true) {
|
|
7281
|
+
const sessionCwd = (session) => {
|
|
7282
|
+
const cwd = ctx.get("sessions")?.get?.(session)?.header?.cwd;
|
|
7283
|
+
if (typeof cwd === "string" && cwd.length > 0) return cwd;
|
|
7284
|
+
return session === "" ? homedir() : process.cwd();
|
|
7285
|
+
};
|
|
7286
|
+
const globalLayerPaths = (cwd) => new Set(piMcpConfigPaths(cwd).slice(0, 4));
|
|
7287
|
+
state.shared.browserSurfacesRouted = registerBrowserSurfaceRoute(ctx, browserSurfaces, {
|
|
7288
|
+
async mcpState(session) {
|
|
7289
|
+
const cwd = sessionCwd(session);
|
|
7290
|
+
const globals = globalLayerPaths(cwd);
|
|
7291
|
+
const { servers, sources } = collectPiMcpServers(cwd);
|
|
7292
|
+
return {
|
|
7293
|
+
cwd,
|
|
7294
|
+
sources,
|
|
7295
|
+
servers: [...servers.values()].map((server) => ({
|
|
7296
|
+
name: server.name,
|
|
7297
|
+
transport: server.transport,
|
|
7298
|
+
target: server.transport === "stdio" ? [server.command, ...server.args ?? []].filter(Boolean).join(" ") : server.url ?? "",
|
|
7299
|
+
disabled: server.disabled,
|
|
7300
|
+
sourcePath: server.sourcePath,
|
|
7301
|
+
layer: globals.has(server.sourcePath) ? "global" : "project",
|
|
7302
|
+
envKeys: Object.keys(server.env ?? {}),
|
|
7303
|
+
headerKeys: Object.keys(server.headers ?? {})
|
|
7304
|
+
}))
|
|
7305
|
+
};
|
|
7306
|
+
},
|
|
7307
|
+
async mcpAction(session, server, disabled, scope) {
|
|
7308
|
+
const cwd = sessionCwd(session);
|
|
7309
|
+
const { servers } = collectPiMcpServers(cwd);
|
|
7310
|
+
if (!servers.has(server)) throw new TypeError(`unknown MCP server ${JSON.stringify(server)}`);
|
|
7311
|
+
const overridePath = scope === "global" ? [...globalLayerPaths(cwd)][3] : join(cwd, ".pi", "mcp.json");
|
|
7312
|
+
let current = {};
|
|
7313
|
+
try {
|
|
7314
|
+
current = JSON.parse(await readFile(overridePath, "utf8"));
|
|
7315
|
+
} catch {}
|
|
7316
|
+
const mcpServers = typeof current.mcpServers === "object" && current.mcpServers !== null ? current.mcpServers : {};
|
|
7317
|
+
mcpServers[server] = {
|
|
7318
|
+
...typeof mcpServers[server] === "object" && mcpServers[server] !== null ? mcpServers[server] : {},
|
|
7319
|
+
disabled
|
|
7320
|
+
};
|
|
7321
|
+
current.mcpServers = mcpServers;
|
|
7322
|
+
await mkdir(dirname(overridePath), { recursive: true });
|
|
7323
|
+
await writeFile(overridePath, `${JSON.stringify(current, null, 2)}\n`);
|
|
7324
|
+
return {
|
|
7325
|
+
ok: true,
|
|
7326
|
+
note: "run /reload (or restart the session) to apply"
|
|
7327
|
+
};
|
|
7328
|
+
}
|
|
7329
|
+
});
|
|
7330
|
+
}
|
|
6776
7331
|
ctx.effect(() => browserSurfaces.trackCompletions(state.packageName ?? "pi", async (trigger, query) => {
|
|
6777
7332
|
if (state.autocompleteProviders.length === 0) return [];
|
|
6778
7333
|
let provider = { getSuggestions: async () => null };
|
|
@@ -6882,6 +7437,21 @@ async function applyPiPackage(ctx, options) {
|
|
|
6882
7437
|
return state.bridge.readonlySessionManager(session, cwd);
|
|
6883
7438
|
},
|
|
6884
7439
|
resumeSessionIdFor: (file) => state.bridge.sessionIdOfArchiveFile(file),
|
|
7440
|
+
mountChildExtensions: async (childAgent, loader) => {
|
|
7441
|
+
const shared = sharedHostStateOf(ctx);
|
|
7442
|
+
const catalog = shared.childExtensions;
|
|
7443
|
+
if (catalog === void 0) return [];
|
|
7444
|
+
const { names, failures } = resolveChildExtensionPackages(loader, catalog);
|
|
7445
|
+
if (names.length === 0) return failures;
|
|
7446
|
+
const mountFailures = await catalog.mount(childAgent, names);
|
|
7447
|
+
const attachable = loader;
|
|
7448
|
+
if (typeof attachable?.attachChildToolResolver === "function") attachable.attachChildToolResolver((path) => {
|
|
7449
|
+
const packageName = catalog.packageByEntryPath.get(resolve(path));
|
|
7450
|
+
if (packageName === void 0) return void 0;
|
|
7451
|
+
return shared.childPackageTools?.get(childAgent)?.get(packageName);
|
|
7452
|
+
});
|
|
7453
|
+
return [...failures, ...mountFailures];
|
|
7454
|
+
},
|
|
6885
7455
|
sessionGoneFromPersistence: async (sessionId) => {
|
|
6886
7456
|
const persistence = optionalService(ctx, "sessionPersistence");
|
|
6887
7457
|
if (typeof persistence?.list !== "function") return void 0;
|
|
@@ -6950,6 +7520,7 @@ const runtimeInternals = {
|
|
|
6950
7520
|
currentPiModel,
|
|
6951
7521
|
lastRequestRouteOf,
|
|
6952
7522
|
resolveCallerRoute,
|
|
7523
|
+
resolveChildExtensionPackages,
|
|
6953
7524
|
dshToPiContent,
|
|
6954
7525
|
expandPrompt,
|
|
6955
7526
|
isKnownImageTool,
|
|
@@ -6960,6 +7531,6 @@ const runtimeInternals = {
|
|
|
6960
7531
|
textBlocks
|
|
6961
7532
|
};
|
|
6962
7533
|
//#endregion
|
|
6963
|
-
export {
|
|
7534
|
+
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 };
|
|
6964
7535
|
|
|
6965
|
-
//# sourceMappingURL=runtime-
|
|
7536
|
+
//# sourceMappingURL=runtime-CBZcd1uU.mjs.map
|