pi2dsh 0.22.0 → 0.24.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 +8 -5
- package/README.zh.md +6 -3
- package/dist/{analyzer-LD53mBKa.mjs → analyzer-DqsrD1FG.mjs} +2 -2
- package/dist/{analyzer-LD53mBKa.mjs.map → analyzer-DqsrD1FG.mjs.map} +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/{compatibility-PfLsrQPc.mjs → compatibility-CZ0QpE76.mjs} +4 -4
- package/dist/compatibility-CZ0QpE76.mjs.map +1 -0
- package/dist/host.mjs +1 -1
- package/dist/index.mjs +5 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{runtime-BVrvJuiO.mjs → runtime-BiHMcD_8.mjs} +235 -127
- package/dist/runtime-BiHMcD_8.mjs.map +1 -0
- package/dist/runtime.d.mts +75 -47
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +1 -1
- package/package.json +12 -12
- package/dist/compatibility-PfLsrQPc.mjs.map +0 -1
- package/dist/runtime-BVrvJuiO.mjs.map +0 -1
|
@@ -1139,6 +1139,8 @@ function messageText(message) {
|
|
|
1139
1139
|
* is one surface, however many Pi packages contribute threads to it.
|
|
1140
1140
|
*/
|
|
1141
1141
|
var BrowserSurfaces = class {
|
|
1142
|
+
/** Last time a browser client touched the /pi2dsh route (ms epoch). */
|
|
1143
|
+
lastClientContactMs;
|
|
1142
1144
|
#byParent = /* @__PURE__ */ new Map();
|
|
1143
1145
|
#commandRunners = /* @__PURE__ */ new Map();
|
|
1144
1146
|
#surfaces = /* @__PURE__ */ new Map();
|
|
@@ -1163,102 +1165,6 @@ var BrowserSurfaces = class {
|
|
|
1163
1165
|
imageToolNames() {
|
|
1164
1166
|
return [...this.#imageToolNames];
|
|
1165
1167
|
}
|
|
1166
|
-
#scene;
|
|
1167
|
-
#sceneRevision = 0;
|
|
1168
|
-
#sceneWidth = 100;
|
|
1169
|
-
openScene(packageName, factory, theme, keybindings, options) {
|
|
1170
|
-
this.#finishScene(void 0);
|
|
1171
|
-
return new Promise((resolve, reject) => {
|
|
1172
|
-
const run = {
|
|
1173
|
-
package: packageName,
|
|
1174
|
-
component: void 0,
|
|
1175
|
-
options,
|
|
1176
|
-
resolve,
|
|
1177
|
-
reject
|
|
1178
|
-
};
|
|
1179
|
-
this.#scene = run;
|
|
1180
|
-
const driver = { requestRender: () => this.#invalidateScene() };
|
|
1181
|
-
const done = (value) => {
|
|
1182
|
-
if (this.#scene !== run) return;
|
|
1183
|
-
this.#finishScene(value);
|
|
1184
|
-
};
|
|
1185
|
-
Promise.resolve().then(() => factory(driver, theme, keybindings, done)).then((component) => {
|
|
1186
|
-
if (this.#scene !== run) {
|
|
1187
|
-
component.dispose?.();
|
|
1188
|
-
return;
|
|
1189
|
-
}
|
|
1190
|
-
if (typeof component?.render !== "function") {
|
|
1191
|
-
this.#scene = void 0;
|
|
1192
|
-
this.#invalidateScene();
|
|
1193
|
-
console.warn(`[pi2dsh] web scene for ${packageName}: component lacks render(width)`);
|
|
1194
|
-
reject(/* @__PURE__ */ new TypeError("Pi custom component must implement render(width)"));
|
|
1195
|
-
return;
|
|
1196
|
-
}
|
|
1197
|
-
run.component = component;
|
|
1198
|
-
this.#invalidateScene();
|
|
1199
|
-
}, (error) => {
|
|
1200
|
-
if (this.#scene !== run) return;
|
|
1201
|
-
this.#scene = void 0;
|
|
1202
|
-
this.#invalidateScene();
|
|
1203
|
-
console.warn(`[pi2dsh] web scene for ${packageName}: component factory failed: ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
|
|
1204
|
-
reject(error);
|
|
1205
|
-
});
|
|
1206
|
-
});
|
|
1207
|
-
}
|
|
1208
|
-
/** What the browser paints: the live component's frame, or a closed marker. */
|
|
1209
|
-
sceneSnapshot() {
|
|
1210
|
-
const scene = this.#scene;
|
|
1211
|
-
if (scene?.component === void 0) return {
|
|
1212
|
-
open: false,
|
|
1213
|
-
revision: this.#sceneRevision
|
|
1214
|
-
};
|
|
1215
|
-
const requested = (typeof scene.options?.overlayOptions === "function" ? scene.options.overlayOptions() : scene.options?.overlayOptions)?.width;
|
|
1216
|
-
const width = typeof requested === "number" && Number.isFinite(requested) && requested > 0 ? Math.min(this.#sceneWidth, Math.floor(requested)) : this.#sceneWidth;
|
|
1217
|
-
let lines;
|
|
1218
|
-
try {
|
|
1219
|
-
lines = scene.component.render(width);
|
|
1220
|
-
} catch (error) {
|
|
1221
|
-
const failed = this.#scene;
|
|
1222
|
-
this.#scene = void 0;
|
|
1223
|
-
this.#invalidateScene();
|
|
1224
|
-
console.warn(`[pi2dsh] web scene for ${scene.package}: render(width) failed: ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
|
|
1225
|
-
failed?.reject(error);
|
|
1226
|
-
return {
|
|
1227
|
-
open: false,
|
|
1228
|
-
revision: this.#sceneRevision
|
|
1229
|
-
};
|
|
1230
|
-
}
|
|
1231
|
-
return {
|
|
1232
|
-
open: true,
|
|
1233
|
-
package: scene.package,
|
|
1234
|
-
revision: this.#sceneRevision,
|
|
1235
|
-
lines
|
|
1236
|
-
};
|
|
1237
|
-
}
|
|
1238
|
-
/** Raw terminal input from the browser keyboard, verbatim into the component. */
|
|
1239
|
-
sceneInput(sequence, width) {
|
|
1240
|
-
if (typeof width === "number" && Number.isFinite(width)) this.#sceneWidth = Math.max(20, Math.min(400, Math.floor(width)));
|
|
1241
|
-
const component = this.#scene?.component;
|
|
1242
|
-
if (component === void 0 || sequence.length === 0) return;
|
|
1243
|
-
component.handleInput?.(sequence);
|
|
1244
|
-
component.invalidate?.();
|
|
1245
|
-
this.#invalidateScene();
|
|
1246
|
-
}
|
|
1247
|
-
/** The browser dismissed the overlay: resolve the Pi caller with undefined. */
|
|
1248
|
-
closeScene() {
|
|
1249
|
-
this.#finishScene(void 0);
|
|
1250
|
-
}
|
|
1251
|
-
#finishScene(value) {
|
|
1252
|
-
const scene = this.#scene;
|
|
1253
|
-
if (scene === void 0) return;
|
|
1254
|
-
this.#scene = void 0;
|
|
1255
|
-
scene.component?.dispose?.();
|
|
1256
|
-
this.#invalidateScene();
|
|
1257
|
-
scene.resolve(value);
|
|
1258
|
-
}
|
|
1259
|
-
#invalidateScene() {
|
|
1260
|
-
this.#sceneRevision += 1;
|
|
1261
|
-
}
|
|
1262
1168
|
/**
|
|
1263
1169
|
* Track one child session under its parent.
|
|
1264
1170
|
* @param parentSessionId - the session the panel floats over.
|
|
@@ -1298,9 +1204,20 @@ var BrowserSurfaces = class {
|
|
|
1298
1204
|
if (live.size === 0) this.#commandRunners.delete(sessionId);
|
|
1299
1205
|
};
|
|
1300
1206
|
}
|
|
1301
|
-
/**
|
|
1207
|
+
/**
|
|
1208
|
+
* The registered runner for (session, package), when one is mounted.
|
|
1209
|
+
*
|
|
1210
|
+
* An empty sessionId means "any session where the package is mounted":
|
|
1211
|
+
* session-free product UI (a Settings page) invoking a package command
|
|
1212
|
+
* whose effect is global state — the handler itself is the package's own
|
|
1213
|
+
* either way, and every mounted copy routes to the same package storage.
|
|
1214
|
+
*/
|
|
1302
1215
|
commandRunner(sessionId, packageName) {
|
|
1303
|
-
return this.#commandRunners.get(sessionId)?.get(packageName);
|
|
1216
|
+
if (sessionId !== "") return this.#commandRunners.get(sessionId)?.get(packageName);
|
|
1217
|
+
for (const runners of this.#commandRunners.values()) {
|
|
1218
|
+
const runner = runners.get(packageName);
|
|
1219
|
+
if (runner !== void 0) return runner;
|
|
1220
|
+
}
|
|
1304
1221
|
}
|
|
1305
1222
|
/**
|
|
1306
1223
|
* The panel's view of one parent session.
|
|
@@ -1659,6 +1576,7 @@ function registerBrowserSurfaceRoute(ctx, registry, hooks) {
|
|
|
1659
1576
|
const response = res;
|
|
1660
1577
|
const method = String(req.method ?? "GET");
|
|
1661
1578
|
const url = new URL(String(req.url ?? "/"), "http://pi2dsh.invalid");
|
|
1579
|
+
registry.lastClientContactMs = Date.now();
|
|
1662
1580
|
if (method === "POST" && url.pathname === "/pi2dsh/editor-draft") {
|
|
1663
1581
|
const chunks = [];
|
|
1664
1582
|
const body = await new Promise((settle) => {
|
|
@@ -1715,6 +1633,46 @@ function registerBrowserSurfaceRoute(ctx, registry, hooks) {
|
|
|
1715
1633
|
response.end(JSON.stringify(outcome ?? { ok: true }));
|
|
1716
1634
|
return;
|
|
1717
1635
|
}
|
|
1636
|
+
if (url.pathname === "/pi2dsh/login-state" && (method === "GET" || method === "HEAD")) {
|
|
1637
|
+
if (hooks?.loginState === void 0) {
|
|
1638
|
+
response.writeHead(404);
|
|
1639
|
+
response.end();
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
1642
|
+
const body = JSON.stringify(await hooks.loginState());
|
|
1643
|
+
response.writeHead(200, {
|
|
1644
|
+
"content-type": "application/json; charset=utf-8",
|
|
1645
|
+
"cache-control": "no-store"
|
|
1646
|
+
});
|
|
1647
|
+
response.end(method === "HEAD" ? void 0 : body);
|
|
1648
|
+
return;
|
|
1649
|
+
}
|
|
1650
|
+
if (url.pathname === "/pi2dsh/login-action" && method === "POST") {
|
|
1651
|
+
if (hooks?.loginAction === void 0) {
|
|
1652
|
+
response.writeHead(404);
|
|
1653
|
+
response.end();
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
const chunks = [];
|
|
1657
|
+
const raw = await new Promise((settle) => {
|
|
1658
|
+
const stream = req;
|
|
1659
|
+
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
1660
|
+
stream.on("end", () => settle(Buffer.concat(chunks).toString("utf8")));
|
|
1661
|
+
});
|
|
1662
|
+
let outcome;
|
|
1663
|
+
try {
|
|
1664
|
+
const payload = JSON.parse(raw || "{}");
|
|
1665
|
+
if (typeof payload.action !== "string") throw new TypeError("login-action needs { action }");
|
|
1666
|
+
outcome = await hooks.loginAction(payload.action, typeof payload.provider === "string" ? payload.provider : "", typeof payload.value === "string" ? payload.value : "");
|
|
1667
|
+
} catch (error) {
|
|
1668
|
+
response.writeHead(400, { "content-type": "application/json; charset=utf-8" });
|
|
1669
|
+
response.end(JSON.stringify({ error: error instanceof Error ? error.message : String(error) }));
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
response.writeHead(200, { "content-type": "application/json; charset=utf-8" });
|
|
1673
|
+
response.end(JSON.stringify(outcome ?? { ok: true }));
|
|
1674
|
+
return;
|
|
1675
|
+
}
|
|
1718
1676
|
if (url.pathname === "/pi2dsh/pi-command" && method === "POST") {
|
|
1719
1677
|
const chunks = [];
|
|
1720
1678
|
const raw = await new Promise((settle) => {
|
|
@@ -1743,22 +1701,6 @@ function registerBrowserSurfaceRoute(ctx, registry, hooks) {
|
|
|
1743
1701
|
}
|
|
1744
1702
|
return;
|
|
1745
1703
|
}
|
|
1746
|
-
if (method === "POST" && (url.pathname === "/pi2dsh/scene-input" || url.pathname === "/pi2dsh/scene-close")) {
|
|
1747
|
-
const chunks = [];
|
|
1748
|
-
const body = await new Promise((settle) => {
|
|
1749
|
-
const stream = req;
|
|
1750
|
-
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
1751
|
-
stream.on("end", () => settle(Buffer.concat(chunks).toString("utf8")));
|
|
1752
|
-
});
|
|
1753
|
-
if (url.pathname === "/pi2dsh/scene-close") registry.closeScene();
|
|
1754
|
-
else try {
|
|
1755
|
-
const payload = JSON.parse(body || "{}");
|
|
1756
|
-
if (typeof payload.sequence === "string") registry.sceneInput(payload.sequence, typeof payload.width === "number" ? payload.width : void 0);
|
|
1757
|
-
} catch {}
|
|
1758
|
-
response.writeHead(204);
|
|
1759
|
-
response.end();
|
|
1760
|
-
return;
|
|
1761
|
-
}
|
|
1762
1704
|
if (method !== "GET" && method !== "HEAD") {
|
|
1763
1705
|
response.writeHead(405);
|
|
1764
1706
|
response.end();
|
|
@@ -1804,13 +1746,11 @@ function registerBrowserSurfaceRoute(ctx, registry, hooks) {
|
|
|
1804
1746
|
const body = JSON.stringify(session === "" ? {
|
|
1805
1747
|
threads: [],
|
|
1806
1748
|
surfaces: [],
|
|
1807
|
-
entries: []
|
|
1808
|
-
scene: registry.sceneSnapshot()
|
|
1749
|
+
entries: []
|
|
1809
1750
|
} : {
|
|
1810
1751
|
threads: registry.snapshot(session),
|
|
1811
1752
|
surfaces: registry.surfaces(session),
|
|
1812
1753
|
entries: registry.entries(session),
|
|
1813
|
-
scene: registry.sceneSnapshot(),
|
|
1814
1754
|
...registry.draftRequest(session) === void 0 ? {} : { draft: registry.draftRequest(session) }
|
|
1815
1755
|
});
|
|
1816
1756
|
response.writeHead(200, {
|
|
@@ -3060,6 +3000,9 @@ const DSH_COMPAT_FIELD_PROTOCOLS = {
|
|
|
3060
3000
|
supportsDeveloperRole: COMPLETIONS_AND_RESPONSES,
|
|
3061
3001
|
supportsReasoningEffort: COMPLETIONS,
|
|
3062
3002
|
supportsUsageInStreaming: COMPLETIONS,
|
|
3003
|
+
supportsFinishReason: COMPLETIONS,
|
|
3004
|
+
chatTemplateArgs: COMPLETIONS,
|
|
3005
|
+
supportsThinkingTokenBudget: COMPLETIONS,
|
|
3063
3006
|
maxTokensField: COMPLETIONS,
|
|
3064
3007
|
requiresToolResultName: COMPLETIONS,
|
|
3065
3008
|
requiresAssistantAfterToolResult: COMPLETIONS,
|
|
@@ -4352,8 +4295,6 @@ function contextFor(ctx, state, agent, signal, command = false, sessionOverride,
|
|
|
4352
4295
|
if (headlessUi) return void 0;
|
|
4353
4296
|
const surfaces = state.tuiSurfaces;
|
|
4354
4297
|
if (surfaces !== void 0) return surfaces.custom(factory, state.theme, getKeybindings(), options);
|
|
4355
|
-
const browser = state.shared.browserSurfaces;
|
|
4356
|
-
if (browser !== void 0 && state.shared.browserSurfacesRouted === true) return browser.openScene(state.packageName, factory, state.theme, getKeybindings(), options);
|
|
4357
4298
|
},
|
|
4358
4299
|
pasteToEditor(text) {
|
|
4359
4300
|
const surfaces = state.shared.browserSurfaces;
|
|
@@ -4550,11 +4491,10 @@ function contextFor(ctx, state, agent, signal, command = false, sessionOverride,
|
|
|
4550
4491
|
},
|
|
4551
4492
|
ui,
|
|
4552
4493
|
get mode() {
|
|
4553
|
-
|
|
4554
|
-
return state.shared.browserSurfaces !== void 0 && state.shared.browserSurfacesRouted === true ? "tui" : "rpc";
|
|
4494
|
+
return state.tuiSurfaces?.available === true ? "tui" : "rpc";
|
|
4555
4495
|
},
|
|
4556
4496
|
get hasUI() {
|
|
4557
|
-
return state.tuiSurfaces?.available === true || humanAnswererAvailable(userQuestions, agent);
|
|
4497
|
+
return state.tuiSurfaces?.available === true || humanAnswererAvailable(userQuestions, agent, state.shared);
|
|
4558
4498
|
},
|
|
4559
4499
|
cwd: contextCwd,
|
|
4560
4500
|
sessionManager: session === void 0 ? state.bridge.readonlySessionManager({
|
|
@@ -6047,6 +5987,37 @@ async function supersedeActiveLogin(state) {
|
|
|
6047
5987
|
* @param config - the provider config, whose oauth block made it loginable.
|
|
6048
5988
|
* @returns whether this call put a route in place.
|
|
6049
5989
|
*/
|
|
5990
|
+
/**
|
|
5991
|
+
* Mount-time route restore that tolerates composition order.
|
|
5992
|
+
*
|
|
5993
|
+
* The credentials service (credentials-local) can compose AFTER a
|
|
5994
|
+
* zero-package profile's host mount — probing immediately loses that race and
|
|
5995
|
+
* a stored login silently produces no route: an engine-only profile with a
|
|
5996
|
+
* valid auth.json hit MISSING_CREDENTIAL on every turn, while installing any
|
|
5997
|
+
* Pi package shifted mount timing enough to mask the bug (2026-08-30,
|
|
5998
|
+
* community/full-audit-work/zero-package-oauth-bug.md). When the service is
|
|
5999
|
+
* already there the restore stays awaited — that is mount readiness, see the
|
|
6000
|
+
* caller's comment. Otherwise the official inject seam re-runs it the moment
|
|
6001
|
+
* the service composes, the same pattern maybeProjectAuthorizationFlow uses.
|
|
6002
|
+
*/
|
|
6003
|
+
async function restoreLoggedInRouteWhenReady(ctx, state, name, config) {
|
|
6004
|
+
if (optionalService(ctx, "credentials") !== void 0) {
|
|
6005
|
+
await ensureLoggedInProviderRoute(ctx, state, name, config);
|
|
6006
|
+
return;
|
|
6007
|
+
}
|
|
6008
|
+
const shared = state.shared;
|
|
6009
|
+
shared.routeRestoreArmedIds ??= /* @__PURE__ */ new Set();
|
|
6010
|
+
if (shared.routeRestoreArmedIds.has(name)) return;
|
|
6011
|
+
const inject = ctx.inject;
|
|
6012
|
+
if (typeof inject !== "function") {
|
|
6013
|
+
await ensureLoggedInProviderRoute(ctx, state, name, config);
|
|
6014
|
+
return;
|
|
6015
|
+
}
|
|
6016
|
+
shared.routeRestoreArmedIds.add(name);
|
|
6017
|
+
inject.call(ctx, ["credentials"], (scope) => {
|
|
6018
|
+
ensureLoggedInProviderRoute(scope, state, name, config).catch((error) => logger(ctx).warn(`[pi2dsh] could not restore the route for logged-in provider ${JSON.stringify(name)}: ${error instanceof Error ? error.message : String(error)}`));
|
|
6019
|
+
});
|
|
6020
|
+
}
|
|
6050
6021
|
async function ensureLoggedInProviderRoute(ctx, state, name, config) {
|
|
6051
6022
|
if (!providerSupportsOAuth(config)) return false;
|
|
6052
6023
|
if (providerCarriesTransport(config) || state.providerRouteDisposers.has(name)) return false;
|
|
@@ -6358,11 +6329,16 @@ async function projectAuthorizationFlow(scope, state, providerId) {
|
|
|
6358
6329
|
throw error;
|
|
6359
6330
|
}
|
|
6360
6331
|
},
|
|
6361
|
-
deviceCode:
|
|
6332
|
+
deviceCode: (title, detail, signal) => {
|
|
6362
6333
|
session.notify({
|
|
6363
6334
|
message: String(title),
|
|
6364
6335
|
code: String(detail)
|
|
6365
6336
|
});
|
|
6337
|
+
return new Promise((resolve) => {
|
|
6338
|
+
if (!(signal instanceof AbortSignal)) return;
|
|
6339
|
+
if (signal.aborted) resolve();
|
|
6340
|
+
else signal.addEventListener("abort", () => resolve(), { once: true });
|
|
6341
|
+
});
|
|
6366
6342
|
}
|
|
6367
6343
|
};
|
|
6368
6344
|
const canonical = canonicalOf();
|
|
@@ -6855,11 +6831,18 @@ function sessionNameOf(ctx, state, session) {
|
|
|
6855
6831
|
* @param userQuestions - the mounted question service, if any.
|
|
6856
6832
|
* @param agent - the agent whose turn this context belongs to.
|
|
6857
6833
|
*/
|
|
6858
|
-
function humanAnswererAvailable(userQuestions, agent) {
|
|
6834
|
+
function humanAnswererAvailable(userQuestions, agent, shared) {
|
|
6859
6835
|
if (userQuestions === void 0) return false;
|
|
6860
6836
|
if (isSubagentOrigin(agent)) return false;
|
|
6861
6837
|
const service = userQuestions;
|
|
6862
|
-
if (typeof service.registerProvider !== "function")
|
|
6838
|
+
if (typeof service.registerProvider !== "function") {
|
|
6839
|
+
const events = service.ctx?.events;
|
|
6840
|
+
if (typeof events?.dispatch === "function") try {
|
|
6841
|
+
if (events.dispatch("pi2dsh:hasui-probe", ["user-questions/request"]).length > 0) return true;
|
|
6842
|
+
} catch {}
|
|
6843
|
+
const last = shared?.browserSurfaces?.lastClientContactMs;
|
|
6844
|
+
return typeof last === "number" && Date.now() - last < 15e3;
|
|
6845
|
+
}
|
|
6863
6846
|
let dispose;
|
|
6864
6847
|
try {
|
|
6865
6848
|
dispose = service.registerProvider({ ask: async () => {
|
|
@@ -7352,7 +7335,7 @@ async function applyPiPackage(ctx, options) {
|
|
|
7352
7335
|
}
|
|
7353
7336
|
ensureLoginCommand(ctx, state);
|
|
7354
7337
|
for (const [name, config] of [...state.providers]) try {
|
|
7355
|
-
await
|
|
7338
|
+
await restoreLoggedInRouteWhenReady(ctx, state, name, config);
|
|
7356
7339
|
} catch (error) {
|
|
7357
7340
|
logger(ctx).warn(`[pi2dsh] could not restore the route for logged-in provider ${JSON.stringify(name)}: ${error instanceof Error ? error.message : String(error)}`);
|
|
7358
7341
|
}
|
|
@@ -7435,6 +7418,131 @@ async function applyPiPackage(ctx, options) {
|
|
|
7435
7418
|
ok: true,
|
|
7436
7419
|
note: "run /reload (or restart the session) to apply"
|
|
7437
7420
|
};
|
|
7421
|
+
},
|
|
7422
|
+
async loginState() {
|
|
7423
|
+
const flow = state.shared.browserLogin;
|
|
7424
|
+
return {
|
|
7425
|
+
providers: await Promise.all([...state.providers.entries()].filter(([, config]) => providerSupportsOAuth(config)).map(async ([id, config]) => ({
|
|
7426
|
+
id,
|
|
7427
|
+
name: config.oauth?.name ?? id,
|
|
7428
|
+
signedIn: await storedOAuthCredential(oauthStoreOf(state), id).then((c) => c !== void 0, () => false)
|
|
7429
|
+
}))),
|
|
7430
|
+
...flow === void 0 ? {} : { flow: {
|
|
7431
|
+
provider: flow.provider,
|
|
7432
|
+
providerName: flow.providerName,
|
|
7433
|
+
notices: flow.notices,
|
|
7434
|
+
...flow.question === void 0 ? {} : { question: {
|
|
7435
|
+
id: flow.question.id,
|
|
7436
|
+
kind: flow.question.kind,
|
|
7437
|
+
title: flow.question.title,
|
|
7438
|
+
...flow.question.placeholder === void 0 ? {} : { placeholder: flow.question.placeholder },
|
|
7439
|
+
...flow.question.options === void 0 ? {} : { options: flow.question.options }
|
|
7440
|
+
} },
|
|
7441
|
+
...flow.done === void 0 ? {} : { done: flow.done }
|
|
7442
|
+
} }
|
|
7443
|
+
};
|
|
7444
|
+
},
|
|
7445
|
+
async loginAction(action, provider, value) {
|
|
7446
|
+
const shared = state.shared;
|
|
7447
|
+
if (action === "dismiss") {
|
|
7448
|
+
shared.browserLogin = void 0;
|
|
7449
|
+
return { ok: true };
|
|
7450
|
+
}
|
|
7451
|
+
if (action === "answer") {
|
|
7452
|
+
const flow = shared.browserLogin;
|
|
7453
|
+
if (flow?.answer === void 0) throw new TypeError("no login question is waiting for an answer");
|
|
7454
|
+
const settle = flow.answer;
|
|
7455
|
+
flow.answer = void 0;
|
|
7456
|
+
delete flow.question;
|
|
7457
|
+
settle(value);
|
|
7458
|
+
return { ok: true };
|
|
7459
|
+
}
|
|
7460
|
+
if (action === "cancel") {
|
|
7461
|
+
const cancelled = await supersedeActiveLogin(state);
|
|
7462
|
+
const flow = shared.browserLogin;
|
|
7463
|
+
if (flow !== void 0 && flow.done === void 0) flow.done = {
|
|
7464
|
+
ok: false,
|
|
7465
|
+
summary: "Login cancelled"
|
|
7466
|
+
};
|
|
7467
|
+
return {
|
|
7468
|
+
ok: true,
|
|
7469
|
+
...cancelled === void 0 ? {} : { cancelled }
|
|
7470
|
+
};
|
|
7471
|
+
}
|
|
7472
|
+
const config = state.providers.get(provider);
|
|
7473
|
+
if (config === void 0 || !providerSupportsOAuth(config)) throw new TypeError(`unknown OAuth provider ${JSON.stringify(provider)}`);
|
|
7474
|
+
const providerName = config.oauth?.name ?? provider;
|
|
7475
|
+
if (action === "signout") {
|
|
7476
|
+
await oauthStoreOf(state).delete(provider);
|
|
7477
|
+
if (!providerCarriesTransport(config)) retireSharedProviderRoute(shared, provider);
|
|
7478
|
+
return {
|
|
7479
|
+
ok: true,
|
|
7480
|
+
signedOut: provider
|
|
7481
|
+
};
|
|
7482
|
+
}
|
|
7483
|
+
if (action !== "begin") throw new TypeError(`unknown login action ${JSON.stringify(action)}`);
|
|
7484
|
+
let questionSeq = 0;
|
|
7485
|
+
const flow = {
|
|
7486
|
+
provider,
|
|
7487
|
+
providerName,
|
|
7488
|
+
notices: []
|
|
7489
|
+
};
|
|
7490
|
+
shared.browserLogin = flow;
|
|
7491
|
+
const ask = (kind, title, extras, signal) => new Promise((resolve) => {
|
|
7492
|
+
const id = ++questionSeq;
|
|
7493
|
+
flow.question = {
|
|
7494
|
+
id,
|
|
7495
|
+
kind,
|
|
7496
|
+
title,
|
|
7497
|
+
...extras
|
|
7498
|
+
};
|
|
7499
|
+
flow.answer = (answered) => {
|
|
7500
|
+
resolve(answered);
|
|
7501
|
+
};
|
|
7502
|
+
const withdraw = () => {
|
|
7503
|
+
if (flow.question?.id !== id) return;
|
|
7504
|
+
delete flow.question;
|
|
7505
|
+
flow.answer = void 0;
|
|
7506
|
+
resolve(void 0);
|
|
7507
|
+
};
|
|
7508
|
+
if (signal !== void 0) {
|
|
7509
|
+
if (signal.aborted) withdraw();
|
|
7510
|
+
else signal.addEventListener("abort", withdraw, { once: true });
|
|
7511
|
+
}
|
|
7512
|
+
});
|
|
7513
|
+
runProviderLogin(ctx, state, provider, config, {
|
|
7514
|
+
notify: (message) => {
|
|
7515
|
+
flow.notices.push({ message: String(message) });
|
|
7516
|
+
},
|
|
7517
|
+
input: (title, placeholder, signal) => ask("input", String(title), typeof placeholder === "string" && placeholder.length > 0 ? { placeholder } : {}, signal),
|
|
7518
|
+
select: (title, options, signal) => ask("select", String(title), { options: options.map((option) => String(option)) }, signal),
|
|
7519
|
+
deviceCode: (title, detail, signal) => {
|
|
7520
|
+
const code = /`([^`]+)`/u.exec(String(detail))?.[1];
|
|
7521
|
+
flow.notices.push({
|
|
7522
|
+
message: String(title),
|
|
7523
|
+
...code === void 0 ? {} : { code }
|
|
7524
|
+
});
|
|
7525
|
+
return new Promise((resolve) => {
|
|
7526
|
+
if (!(signal instanceof AbortSignal)) return;
|
|
7527
|
+
if (signal.aborted) resolve();
|
|
7528
|
+
else signal.addEventListener("abort", () => resolve(), { once: true });
|
|
7529
|
+
});
|
|
7530
|
+
}
|
|
7531
|
+
}).then((summary) => {
|
|
7532
|
+
if (shared.browserLogin === flow) flow.done = {
|
|
7533
|
+
ok: true,
|
|
7534
|
+
summary
|
|
7535
|
+
};
|
|
7536
|
+
}, (error) => {
|
|
7537
|
+
if (shared.browserLogin === flow) flow.done = {
|
|
7538
|
+
ok: false,
|
|
7539
|
+
summary: error instanceof Error ? error.message : String(error)
|
|
7540
|
+
};
|
|
7541
|
+
});
|
|
7542
|
+
return {
|
|
7543
|
+
ok: true,
|
|
7544
|
+
started: provider
|
|
7545
|
+
};
|
|
7438
7546
|
}
|
|
7439
7547
|
});
|
|
7440
7548
|
}
|
|
@@ -7658,4 +7766,4 @@ const runtimeInternals = {
|
|
|
7658
7766
|
//#endregion
|
|
7659
7767
|
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 };
|
|
7660
7768
|
|
|
7661
|
-
//# sourceMappingURL=runtime-
|
|
7769
|
+
//# sourceMappingURL=runtime-BiHMcD_8.mjs.map
|