pi2dsh 0.15.2 → 0.16.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.
Files changed (63) hide show
  1. package/README.md +41 -60
  2. package/README.zh.md +34 -54
  3. package/dist/{analyzer-C5FQXB7R.mjs → analyzer-dRAMYI3l.mjs} +2 -2
  4. package/dist/{analyzer-C5FQXB7R.mjs.map → analyzer-dRAMYI3l.mjs.map} +1 -1
  5. package/dist/cli.mjs +2 -3
  6. package/dist/cli.mjs.map +1 -1
  7. package/dist/compat/pi-ai.d.mts +1 -1
  8. package/dist/compat/pi-ai.mjs +1 -2
  9. package/dist/compat/pi-coding-agent.mjs +1 -1
  10. package/dist/credentials-oauth.d.mts +8 -2
  11. package/dist/credentials-oauth.d.mts.map +1 -1
  12. package/dist/credentials-oauth.mjs +134 -1
  13. package/dist/credentials-oauth.mjs.map +1 -0
  14. package/dist/{google-generative-ai-2gCFYp-t.mjs → google-generative-ai-Dpb_X-Kt.mjs} +2 -2
  15. package/dist/{google-generative-ai-2gCFYp-t.mjs.map → google-generative-ai-Dpb_X-Kt.mjs.map} +1 -1
  16. package/dist/{google-shared-75IdVyrx.mjs → google-shared-CL1Za-ev.mjs} +12 -12
  17. package/dist/{google-shared-75IdVyrx.mjs.map → google-shared-CL1Za-ev.mjs.map} +1 -1
  18. package/dist/{google-vertex-Bhyo4z2i.mjs → google-vertex-BXRKa49Y.mjs} +2 -2
  19. package/dist/{google-vertex-Bhyo4z2i.mjs.map → google-vertex-BXRKa49Y.mjs.map} +1 -1
  20. package/dist/host.mjs +1 -1
  21. package/dist/index.d.mts.map +1 -1
  22. package/dist/index.mjs +3 -4
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/{compatibility-DVMqXJux.mjs → mcp-config-2s_i_H3R.mjs} +180 -3
  25. package/dist/mcp-config-2s_i_H3R.mjs.map +1 -0
  26. package/dist/{mistral-conversations-DJyeTo8C.mjs → mistral-conversations-D-Kf38nj.mjs} +5491 -407
  27. package/dist/mistral-conversations-D-Kf38nj.mjs.map +1 -0
  28. package/dist/{multipart-parser-SRcGkVuX.mjs → multipart-parser-CBAi6PxA.mjs} +2 -2
  29. package/dist/{multipart-parser-SRcGkVuX.mjs.map → multipart-parser-CBAi6PxA.mjs.map} +1 -1
  30. package/dist/{credentials-oauth-Didpkkjx.mjs → oauth-bridge-C_MAPMGA.mjs} +11 -88
  31. package/dist/oauth-bridge-C_MAPMGA.mjs.map +1 -0
  32. package/dist/oauth-bridge-hOnT3acY.d.mts +34 -0
  33. package/dist/oauth-bridge-hOnT3acY.d.mts.map +1 -0
  34. package/dist/{otel-CBhmS-NR.mjs → otel-EL651-JR.mjs} +2 -2
  35. package/dist/{otel-CBhmS-NR.mjs.map → otel-EL651-JR.mjs.map} +1 -1
  36. package/dist/{pi-ai-DpqiLdPA.mjs → pi-ai-DQPHUR9S.mjs} +252 -7
  37. package/dist/pi-ai-DQPHUR9S.mjs.map +1 -0
  38. package/dist/{pi-ai-ZU5MelXy.d.mts → pi-ai-hGbYES_v.d.mts} +2 -2
  39. package/dist/{pi-ai-ZU5MelXy.d.mts.map → pi-ai-hGbYES_v.d.mts.map} +1 -1
  40. package/dist/{pi-coding-agent-DK8hbJP5.mjs → pi-coding-agent-f3_hNCpd.mjs} +0 -0
  41. package/dist/{pi-coding-agent-DK8hbJP5.mjs.map → pi-coding-agent-f3_hNCpd.mjs.map} +1 -1
  42. package/dist/{runtime-BlbKWw7W.mjs → runtime-C6_pOPmL.mjs} +198 -47
  43. package/dist/runtime-C6_pOPmL.mjs.map +1 -0
  44. package/dist/runtime.d.mts +29 -47
  45. package/dist/runtime.d.mts.map +1 -1
  46. package/dist/runtime.mjs +1 -1
  47. package/dist/{from-BCscBQ9P.mjs → src-85HOaW5W.mjs} +1185 -10
  48. package/dist/src-85HOaW5W.mjs.map +1 -0
  49. package/package.json +28 -21
  50. package/dist/compatibility-DVMqXJux.mjs.map +0 -1
  51. package/dist/completionchunk-Dhk56lZl.mjs +0 -5212
  52. package/dist/completionchunk-Dhk56lZl.mjs.map +0 -1
  53. package/dist/credentials-oauth-Didpkkjx.mjs.map +0 -1
  54. package/dist/from-BCscBQ9P.mjs.map +0 -1
  55. package/dist/mcp-config-jmzbgdHa.mjs +0 -181
  56. package/dist/mcp-config-jmzbgdHa.mjs.map +0 -1
  57. package/dist/mistral-conversations-DJyeTo8C.mjs.map +0 -1
  58. package/dist/openai-responses-BRdGpBX6.mjs +0 -251
  59. package/dist/openai-responses-BRdGpBX6.mjs.map +0 -1
  60. package/dist/pi-ai-DpqiLdPA.mjs.map +0 -1
  61. package/dist/runtime-BlbKWw7W.mjs.map +0 -1
  62. package/dist/src-DlTagfW5.mjs +0 -1186
  63. package/dist/src-DlTagfW5.mjs.map +0 -1
@@ -1,9 +1,9 @@
1
1
 
2
- import { En as PiCapabilityError, F as generateBranchSummary, Tn as CapabilityLedger, b as Theme, d as ExtensionRunner, w as __runWithSubagentSessionFactory } from "./pi-coding-agent-DK8hbJP5.mjs";
2
+ import { En as PiCapabilityError, F as generateBranchSummary, Tn as CapabilityLedger, b as Theme, d as ExtensionRunner, w as __runWithSubagentSessionFactory } from "./pi-coding-agent-f3_hNCpd.mjs";
3
3
  import { t as getAgentDir } from "./pi-config-shim-CZ1wFzqM.mjs";
4
- import { $ as isContextOverflow, Q as AssistantMessageEventStream, S as getSupportedThinkingLevels, c as builtinProviders, o as __runWithPiAiRuntime, r as __createPiAiRuntimeRegistry } from "./pi-ai-DpqiLdPA.mjs";
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 { a as FileCredentialStore, c as providerSupportsOAuth, i as oauthCredentialRef, l as resolvePiProviderAuth, o as joinSignals, s as loginPiProvider, u as storedOAuthCredential } from "./credentials-oauth-Didpkkjx.mjs";
6
+ 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
7
  import { createRequire } from "node:module";
8
8
  import { access, mkdir, readFile, writeFile } from "node:fs/promises";
9
9
  import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
@@ -5172,6 +5172,197 @@ async function discoverProviderModels(ctx, state, name, value) {
5172
5172
  if (state.shared.providerModelDiscoveries.get(name) === task) state.shared.providerModelDiscoveries.delete(name);
5173
5173
  }
5174
5174
  }
5175
+ /**
5176
+ * Run one provider's own OAuth login end to end — the shared spine behind
5177
+ * the /login command and the DSH authorization-seam flow. Owns the
5178
+ * host-wide single-flight (the fixed callback port), the short-link
5179
+ * publication, and the post-login route + catalog refresh.
5180
+ * @returns the user-facing summary line.
5181
+ */
5182
+ async function runProviderLogin(ctx, state, providerId, config, ui, externalSignal) {
5183
+ const oauthName = config.oauth?.name ?? providerId;
5184
+ const superseded = await supersedeActiveLogin(state);
5185
+ if (superseded !== void 0) ui.notify(`Cancelled the ${superseded} login that was still waiting.`);
5186
+ const active = {
5187
+ providerName: oauthName,
5188
+ controller: new AbortController(),
5189
+ finished: Promise.resolve(),
5190
+ published: []
5191
+ };
5192
+ if (externalSignal !== void 0) {
5193
+ if (externalSignal.aborted) active.controller.abort();
5194
+ else externalSignal.addEventListener("abort", () => active.controller.abort(), { once: true });
5195
+ }
5196
+ const attempt = loginPiProvider({
5197
+ open: openBrowser,
5198
+ shorten: (url) => {
5199
+ const path = publishAuthorization(url);
5200
+ const web = ctx.get("webServer");
5201
+ if (path === void 0 || web?.port === void 0) return void 0;
5202
+ active.published.push(path);
5203
+ return `http://${web.host === "0.0.0.0" || web.host === void 0 ? "127.0.0.1" : web.host}:${web.port}${path}`;
5204
+ },
5205
+ providerId,
5206
+ providerName: oauthName,
5207
+ providerConfig: config,
5208
+ store: oauthStoreOf(state),
5209
+ ui,
5210
+ signal: active.controller.signal
5211
+ });
5212
+ active.finished = attempt.then(() => void 0, () => void 0);
5213
+ state.shared.activeLogin = active;
5214
+ try {
5215
+ await attempt;
5216
+ } finally {
5217
+ for (const path of active.published) revokeAuthorization(path);
5218
+ if (state.shared.activeLogin === active) state.shared.activeLogin = void 0;
5219
+ }
5220
+ const declared = await ensureLoggedInProviderRoute(ctx, state, providerId, config);
5221
+ const discovered = await discoverProviderModels(ctx, state, providerId, config) ?? (declared ? await llmOf(ctx)?.listModels(providerId).then((list) => list.length).catch(() => void 0) : void 0);
5222
+ const models = discovered === void 0 ? "" : `; ${discovered} models available`;
5223
+ ui.notify(`Logged in to ${oauthName}${models}`);
5224
+ return `Logged in to ${oauthName}${models}`;
5225
+ }
5226
+ /**
5227
+ * Project one provider's OAuth login onto DSH's official authorization seam
5228
+ * (`ctx.authorization`, 0.1.1 line). The flow runs the SAME login spine as
5229
+ * /login; the DSH sign-in surface supplies the interaction. On hosts without
5230
+ * the seam (rc.8 line) this is a no-op and /login stays the only entry.
5231
+ *
5232
+ * The credential itself stays in the bridge's Pi-format store — the DSH
5233
+ * credential record written at the end is the seam's commit witness (the
5234
+ * service verifies it observed a record update for the flow's key), and the
5235
+ * official sign-out (`deleteRecord`) is mirrored back into the Pi store by
5236
+ * the watcher below.
5237
+ *
5238
+ * Same id under another scope (the official llm-pi-ai catalog registers
5239
+ * sign-ins for its whole catalog) is NOT a conflict: flows are keyed by
5240
+ * scope/id exactly so registrars can coexist, and the credential spaces
5241
+ * really are separate — signing in through the official flow lands a record
5242
+ * only llm-pi-ai routes can use, while this flow authorizes the routes the
5243
+ * bridge actually serves (package transports and logged-in builtins).
5244
+ * Standing down here would leave those routes unreachable from the native
5245
+ * surface. The label carries "(pi2dsh)" so a future surface shows whose
5246
+ * sign-in each entry is. Only our own exact key is defended: a collision on
5247
+ * `pi2dsh/<id>` throws in registerFlow and degrades to /login-only.
5248
+ *
5249
+ * Composition order is not ours to assume: the stock 0.1.1 compositions ship
5250
+ * the authorization package without composing it, so the service may appear
5251
+ * (or bounce) at any time after this provider registers. The official
5252
+ * pattern — the one llm-pi-ai itself uses — is `ctx.inject(['authorization',
5253
+ * ...], cb)`: cordis mounts the callback when the services are present,
5254
+ * disposes everything it registered when they leave, and mounts it again if
5255
+ * they return. The scope hangs off the CALLING ctx, so a flow projected for
5256
+ * a package's provider dies with that package, and a built-in entry's flow
5257
+ * dies with the engine.
5258
+ */
5259
+ function maybeProjectAuthorizationFlow(ctx, state, providerId) {
5260
+ const shared = state.shared;
5261
+ shared.authorizationArmedIds ??= /* @__PURE__ */ new Set();
5262
+ if (shared.authorizationArmedIds.has(providerId)) return;
5263
+ const inject = ctx.inject;
5264
+ if (typeof inject !== "function") return;
5265
+ shared.authorizationArmedIds.add(providerId);
5266
+ inject.call(ctx, ["authorization", "credentials"], (scope) => {
5267
+ projectAuthorizationFlow(scope, state, providerId);
5268
+ });
5269
+ }
5270
+ /** The per-mount half: services are present on `scope`, register the flow and
5271
+ * this provider's sign-out mirror. Everything registered here is disposed by
5272
+ * cordis with the scope. */
5273
+ async function projectAuthorizationFlow(scope, state, providerId) {
5274
+ const shared = state.shared;
5275
+ const ctx = scope;
5276
+ const authorization = optionalService(ctx, "authorization");
5277
+ const credentials = optionalService(ctx, "credentials");
5278
+ if (authorization === void 0 || credentials === void 0) return;
5279
+ try {
5280
+ const { credentialKey, isCredentialKeySegment } = await import("@deepseek-ai/dsh-credentials");
5281
+ if (credentialKey === void 0 || isCredentialKeySegment === void 0) return;
5282
+ if (!isCredentialKeySegment(providerId)) {
5283
+ logger(ctx).warn(`[pi2dsh] provider ${JSON.stringify(providerId)} cannot appear on the DSH sign-in surface (its id is outside the credential-key grammar); /login still works`);
5284
+ return;
5285
+ }
5286
+ const canonicalOf = () => shared.providers.get(providerId) ?? {};
5287
+ const labelOf = () => canonicalOf().oauth?.name ?? providerId;
5288
+ const key = credentialKey("pi2dsh", providerId);
5289
+ authorization.registerFlow({
5290
+ key,
5291
+ label: `${labelOf()} (pi2dsh)`,
5292
+ methods: [{
5293
+ id: "oauth",
5294
+ label: `Sign in to ${labelOf()}`
5295
+ }],
5296
+ run: async (session) => {
5297
+ const ui = {
5298
+ notify: (message) => {
5299
+ session.notify({ message: String(message) });
5300
+ },
5301
+ input: async (title, _placeholder, promptSignal) => {
5302
+ try {
5303
+ return await session.prompt({
5304
+ kind: "text",
5305
+ message: String(title),
5306
+ ...promptSignal instanceof AbortSignal ? { signal: promptSignal } : {}
5307
+ });
5308
+ } catch (error) {
5309
+ if (promptSignal instanceof AbortSignal && promptSignal.aborted) return void 0;
5310
+ throw error;
5311
+ }
5312
+ },
5313
+ select: async (title, options, promptSignal) => {
5314
+ try {
5315
+ return await session.prompt({
5316
+ kind: "select",
5317
+ message: String(title),
5318
+ options: options.map((option) => ({
5319
+ id: String(option),
5320
+ label: String(option)
5321
+ })),
5322
+ ...promptSignal instanceof AbortSignal ? { signal: promptSignal } : {}
5323
+ });
5324
+ } catch (error) {
5325
+ if (promptSignal instanceof AbortSignal && promptSignal.aborted) return void 0;
5326
+ throw error;
5327
+ }
5328
+ },
5329
+ deviceCode: async (title, detail) => {
5330
+ session.notify({
5331
+ message: String(title),
5332
+ code: String(detail)
5333
+ });
5334
+ }
5335
+ };
5336
+ const canonical = canonicalOf();
5337
+ if (!providerSupportsOAuth(canonical)) throw new Error(`${providerId} no longer supports OAuth login`);
5338
+ await runProviderLogin(ctx, state, providerId, canonical, ui, session.signal);
5339
+ await credentials.modifyRecord(key, async () => ({
5340
+ kind: "grant",
5341
+ payload: {
5342
+ provider: providerId,
5343
+ managedBy: "pi2dsh"
5344
+ }
5345
+ }));
5346
+ }
5347
+ });
5348
+ ctx.on("credentials/record-updated", (eventKey) => {
5349
+ (async () => {
5350
+ try {
5351
+ if (String(eventKey) !== String(key)) return;
5352
+ if (await credentials.readRecord(key) !== void 0) return;
5353
+ await oauthStoreOf(state).delete(providerId);
5354
+ const canonical = shared.providers.get(providerId);
5355
+ if (canonical !== void 0 && !providerCarriesTransport(canonical)) retireSharedProviderRoute(shared, providerId);
5356
+ logger(ctx).info(`[pi2dsh] signed out of ${providerId}: the DSH credential record was deleted, so the bridge's stored login was removed`);
5357
+ } catch (error) {
5358
+ logger(ctx).warn(`[pi2dsh] sign-out mirror failed: ${error instanceof Error ? error.message : String(error)}`);
5359
+ }
5360
+ })();
5361
+ });
5362
+ } catch (error) {
5363
+ logger(ctx).warn(`[pi2dsh] could not project ${JSON.stringify(providerId)} onto the DSH sign-in surface: ${error instanceof Error ? error.message : String(error)}; /login still works`);
5364
+ }
5365
+ }
5175
5366
  function registerLoginCommand(ctx, state) {
5176
5367
  registerCommand(ctx, state, {
5177
5368
  name: "login",
@@ -5187,49 +5378,7 @@ function registerLoginCommand(ctx, state) {
5187
5378
  const providerId = resolveOfferedChoice(answer, oauthProviders);
5188
5379
  const config = providerId === void 0 ? void 0 : state.providers.get(providerId);
5189
5380
  if (providerId === void 0 || config === void 0 || !providerSupportsOAuth(config)) throw new Error(`unknown OAuth provider ${JSON.stringify(answer)}; available: ${oauthProviders.join(", ")}`);
5190
- const oauthName = config.oauth?.name ?? providerId;
5191
- const commandSignal = commandContext.signal;
5192
- const superseded = await supersedeActiveLogin(state);
5193
- if (superseded !== void 0) ui.notify(`Cancelled the ${superseded} login that was still waiting.`);
5194
- const active = {
5195
- providerName: oauthName,
5196
- controller: new AbortController(),
5197
- finished: Promise.resolve(),
5198
- published: []
5199
- };
5200
- if (commandSignal !== void 0) {
5201
- if (commandSignal.aborted) active.controller.abort();
5202
- else commandSignal.addEventListener("abort", () => active.controller.abort(), { once: true });
5203
- }
5204
- const attempt = loginPiProvider({
5205
- open: openBrowser,
5206
- shorten: (url) => {
5207
- const path = publishAuthorization(url);
5208
- const web = ctx.get("webServer");
5209
- if (path === void 0 || web?.port === void 0) return void 0;
5210
- active.published.push(path);
5211
- return `http://${web.host === "0.0.0.0" || web.host === void 0 ? "127.0.0.1" : web.host}:${web.port}${path}`;
5212
- },
5213
- providerId,
5214
- providerName: oauthName,
5215
- providerConfig: config,
5216
- store: oauthStoreOf(state),
5217
- ui,
5218
- signal: active.controller.signal
5219
- });
5220
- active.finished = attempt.then(() => void 0, () => void 0);
5221
- state.shared.activeLogin = active;
5222
- try {
5223
- await attempt;
5224
- } finally {
5225
- for (const path of active.published) revokeAuthorization(path);
5226
- if (state.shared.activeLogin === active) state.shared.activeLogin = void 0;
5227
- }
5228
- const declared = await ensureLoggedInProviderRoute(ctx, state, providerId, config);
5229
- const discovered = await discoverProviderModels(ctx, state, providerId, config) ?? (declared ? await llmOf(ctx)?.listModels(providerId).then((list) => list.length).catch(() => void 0) : void 0);
5230
- const models = discovered === void 0 ? "" : `; ${discovered} models available`;
5231
- ui.notify(`Logged in to ${oauthName}${models}`);
5232
- return `Logged in to ${oauthName}${models}`;
5381
+ return await runProviderLogin(ctx, state, providerId, config, ui, commandContext.signal);
5233
5382
  }
5234
5383
  });
5235
5384
  }
@@ -5733,6 +5882,7 @@ function createPiApi(ctx, state) {
5733
5882
  const canonical = state.shared.providers.get(name) ?? value;
5734
5883
  if (providerSupportsOAuth(canonical)) {
5735
5884
  ensureLoginCommand(ctx, state);
5885
+ maybeProjectAuthorizationFlow(ctx, state, name);
5736
5886
  logger(ctx).info(`[pi2dsh] Pi provider ${JSON.stringify(name)} supports OAuth — log in with /login ${name}`);
5737
5887
  }
5738
5888
  if (registerSharedProviderRoute(ctx, state, name, canonical) !== void 0) {
@@ -6105,6 +6255,7 @@ async function applyPiPackage(ctx, options) {
6105
6255
  shared.providerBuiltins.set(provider.id, config);
6106
6256
  recomposeSharedProvider(shared, provider.id);
6107
6257
  }
6258
+ maybeProjectAuthorizationFlow(ctx, state, provider.id);
6108
6259
  }
6109
6260
  ensureLoginCommand(ctx, state);
6110
6261
  for (const [name, config] of [...state.providers]) try {
@@ -6286,4 +6437,4 @@ const runtimeInternals = {
6286
6437
  //#endregion
6287
6438
  export { registerVisionCompanions as a, overlayProviderConfig as i, mergeProviderRegistration as n, runtimeInternals as o, normalizeToolSchema as r, applyPiPackage as t };
6288
6439
 
6289
- //# sourceMappingURL=runtime-BlbKWw7W.mjs.map
6440
+ //# sourceMappingURL=runtime-C6_pOPmL.mjs.map