pi2dsh 0.3.0 → 0.3.1

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.
@@ -1,9 +1,11 @@
1
1
 
2
2
  import { t as getAgentDir } from "./pi-config-shim-CZ1wFzqM.mjs";
3
3
  import { E as __setSubagentSessionFactory, S as Theme, f as ExtensionRunner } from "./pi-coding-agent-Z1hTs61i.mjs";
4
+ import { a as storedOAuthCredential, i as resolveOAuthApiKey, n as loginPiProvider, r as providerSupportsOAuth, t as FileCredentialStore } from "./oauth-bridge-BpPrppjR.mjs";
5
+ import { r as builtinProviders } from "./pi-ai-CWFlgigJ.mjs";
4
6
  import { createRequire } from "node:module";
5
- import { access, mkdir, readFile, rename, writeFile } from "node:fs/promises";
6
- import { dirname, join } from "node:path";
7
+ import { access, readFile } from "node:fs/promises";
8
+ import { join } from "node:path";
7
9
  import { fileURLToPath } from "node:url";
8
10
  import { EventEmitter } from "node:events";
9
11
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -492,358 +494,6 @@ async function createBridgedAgentSession(host, options) {
492
494
  return { session: new PiBridgedAgentSession(host, handle, tools) };
493
495
  }
494
496
  //#endregion
495
- //#region src/compat/vendor/pi-ai-abort.ts
496
- function abortReason(signal) {
497
- if (signal.reason !== void 0) return signal.reason;
498
- const error = /* @__PURE__ */ new Error("The operation was aborted");
499
- error.name = "AbortError";
500
- return error;
501
- }
502
- /** Create an operation-local signal for public APIs whose signal is optional. */
503
- function operationSignal(signal) {
504
- return signal ?? new AbortController().signal;
505
- }
506
- /**
507
- * Stop waiting for an operation when its signal aborts while continuing to
508
- * observe the abandoned promise so a later rejection is always handled.
509
- */
510
- function raceWithAbortSignal(operation, signal) {
511
- if (signal.aborted) {
512
- operation.catch(() => {});
513
- return Promise.reject(abortReason(signal));
514
- }
515
- return new Promise((resolve, reject) => {
516
- let settled = false;
517
- const cleanup = () => signal.removeEventListener("abort", onAbort);
518
- const onAbort = () => {
519
- if (settled) return;
520
- settled = true;
521
- cleanup();
522
- reject(abortReason(signal));
523
- };
524
- signal.addEventListener("abort", onAbort, { once: true });
525
- operation.then((value) => {
526
- if (settled) return;
527
- settled = true;
528
- cleanup();
529
- resolve(value);
530
- }, (error) => {
531
- if (settled) return;
532
- settled = true;
533
- cleanup();
534
- reject(error);
535
- });
536
- if (signal.aborted) onAbort();
537
- });
538
- }
539
- //#endregion
540
- //#region src/compat/vendor/pi-ai-credential-store.ts
541
- /**
542
- * Default in-memory credential store. Apps inject persistent stores.
543
- * Keyed by `Provider.id`, one credential per provider; see `CredentialStore`.
544
- * Writes are serialized per provider through a promise chain.
545
- */
546
- var InMemoryCredentialStore = class {
547
- credentials = /* @__PURE__ */ new Map();
548
- chains = /* @__PURE__ */ new Map();
549
- /** Serialize tasks per provider id without releasing the chain before active work settles. */
550
- enqueue(providerId, task, options) {
551
- const signal = operationSignal(options?.signal);
552
- const previous = this.chains.get(providerId) ?? Promise.resolve();
553
- const queued = (async () => {
554
- await previous.catch(() => {});
555
- signal.throwIfAborted();
556
- return task();
557
- })();
558
- const tail = queued.catch(() => {});
559
- this.chains.set(providerId, tail);
560
- tail.then(() => {
561
- if (this.chains.get(providerId) === tail) this.chains.delete(providerId);
562
- });
563
- return raceWithAbortSignal(queued, signal);
564
- }
565
- async read(providerId, options) {
566
- options?.signal?.throwIfAborted();
567
- return this.credentials.get(providerId);
568
- }
569
- async list(options) {
570
- options?.signal?.throwIfAborted();
571
- return [...this.credentials].map(([providerId, credential]) => ({
572
- providerId,
573
- type: credential.type
574
- }));
575
- }
576
- modify(providerId, fn, options) {
577
- return this.enqueue(providerId, async () => {
578
- const current = this.credentials.get(providerId);
579
- const next = await fn(current);
580
- options?.signal?.throwIfAborted();
581
- if (next !== void 0) this.credentials.set(providerId, next);
582
- return next ?? current;
583
- }, options);
584
- }
585
- delete(providerId, options) {
586
- return this.enqueue(providerId, async () => {
587
- this.credentials.delete(providerId);
588
- }, options);
589
- }
590
- };
591
- //#endregion
592
- //#region src/compat/vendor/pi-ai-diagnostics.ts
593
- function formatThrownValue(value) {
594
- if (value instanceof Error) return value.message || value.name;
595
- if (typeof value === "string") return value;
596
- return String(value);
597
- }
598
- //#endregion
599
- //#region src/compat/vendor/pi-ai-auth-resolve.ts
600
- var ModelsError = class extends Error {
601
- code;
602
- constructor(code, message, options) {
603
- super(withCauseDetail(message, options?.cause), options);
604
- this.name = "ModelsError";
605
- this.code = code;
606
- }
607
- };
608
- /** Callers surface `error.message` only, so keep the underlying reason in it. */
609
- function withCauseDetail(message, cause) {
610
- if (cause === void 0 || cause === null) return message;
611
- const detail = formatThrownValue(cause).trim();
612
- if (!detail || message.includes(detail)) return message;
613
- return `${message}: ${detail}`;
614
- }
615
- /**
616
- * Auth resolution shared by the `Models` and `ImagesModels` collections.
617
- * A stored credential owns the provider: ambient/env is consulted only when
618
- * nothing is stored. No silent env fallback after a failed refresh or for a
619
- * credential type without a matching handler.
620
- */
621
- function resolveProviderAuth(provider, credentials, authContext, overrides) {
622
- const signal = operationSignal(overrides?.signal);
623
- return raceWithAbortSignal(resolveProviderAuthWithSignal(provider, credentials, authContext, overrides, signal), signal);
624
- }
625
- async function resolveProviderAuthWithSignal(provider, credentials, authContext, overrides, signal) {
626
- signal.throwIfAborted();
627
- const requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;
628
- if (overrides?.apiKey !== void 0 && provider.auth.apiKey) return resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {
629
- type: "api_key",
630
- key: overrides.apiKey,
631
- env: overrides.env
632
- }, signal);
633
- const stored = await readCredential(credentials, provider.id, signal);
634
- if (stored) {
635
- if (stored.type === "oauth" && provider.auth.oauth) return resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored, signal, overrides?.minOAuthValidityMs);
636
- if (stored.type === "api_key" && provider.auth.apiKey) {
637
- const credential = overrides?.env ? {
638
- ...stored,
639
- env: {
640
- ...stored.env,
641
- ...overrides.env
642
- }
643
- } : stored;
644
- return resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, credential, signal);
645
- }
646
- return;
647
- }
648
- return provider.auth.apiKey ? resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, void 0, signal) : void 0;
649
- }
650
- function overlayEnvAuthContext(base, env) {
651
- return {
652
- env: async (name) => env[name] || await base.env(name),
653
- fileExists: (path) => base.fileExists(path)
654
- };
655
- }
656
- const DEFAULT_OAUTH_MINIMUM_VALIDITY_MS = 3e5;
657
- const DEFAULT_OAUTH_REFRESH_TIMEOUT_MS = 15e3;
658
- /**
659
- * OAuth resolution with double-checked locking: tokens with less than five
660
- * minutes remaining lock, re-check expiry under the lock, refresh once
661
- * globally, and persist the rotated credential before release.
662
- */
663
- async function resolveStoredOAuth(credentials, providerId, oauth, stored, signal, minOAuthValidityMs) {
664
- const minimumValidityMs = Math.max(DEFAULT_OAUTH_MINIMUM_VALIDITY_MS, minOAuthValidityMs ?? 0);
665
- const expiresSoon = (credential) => Date.now() + minimumValidityMs >= credential.expires;
666
- let credential = stored;
667
- if (expiresSoon(credential)) {
668
- let post;
669
- try {
670
- post = await credentials.modify(providerId, async (current) => {
671
- if (current?.type !== "oauth") return void 0;
672
- if (!expiresSoon(current)) return void 0;
673
- try {
674
- const refreshSignal = AbortSignal.any([signal, AbortSignal.timeout(DEFAULT_OAUTH_REFRESH_TIMEOUT_MS)]);
675
- return await oauth.refresh(current, refreshSignal);
676
- } catch (error) {
677
- throw new ModelsError("oauth", `OAuth refresh failed for ${providerId}`, { cause: error });
678
- }
679
- }, { signal });
680
- } catch (error) {
681
- if (error instanceof ModelsError) throw error;
682
- throw new ModelsError("auth", `Credential store modify failed for ${providerId}`, { cause: error });
683
- }
684
- if (post?.type !== "oauth") return void 0;
685
- credential = post;
686
- if (minOAuthValidityMs !== void 0 && expiresSoon(credential)) throw new ModelsError("oauth", `OAuth refresh returned a token that expires too soon for ${providerId}`);
687
- }
688
- try {
689
- return {
690
- auth: await oauth.toAuth(credential),
691
- source: "OAuth"
692
- };
693
- } catch (error) {
694
- throw new ModelsError("oauth", `OAuth auth derivation failed for ${providerId}`, { cause: error });
695
- }
696
- }
697
- async function resolveApiKey(authContext, apiKey, providerId, credential, signal) {
698
- try {
699
- return await apiKey.resolve({
700
- ctx: authContext,
701
- credential,
702
- signal
703
- });
704
- } catch (error) {
705
- throw new ModelsError("auth", `API key auth failed for provider ${providerId}`, { cause: error });
706
- }
707
- }
708
- async function readCredential(credentials, providerId, signal) {
709
- try {
710
- return await credentials.read(providerId, { signal });
711
- } catch (error) {
712
- throw new ModelsError("auth", `Credential store read failed for ${providerId}`, { cause: error });
713
- }
714
- }
715
- //#endregion
716
- //#region src/compat/vendor/pi-oauth-adapt.ts
717
- function adaptOAuth(config) {
718
- return {
719
- name: config.name,
720
- isSubscription: config.isSubscription,
721
- login: async (callbacks) => {
722
- return {
723
- ...await config.login({
724
- onAuth: (info) => callbacks.notify({
725
- type: "auth_url",
726
- ...info
727
- }),
728
- onDeviceCode: (info) => callbacks.notify({
729
- type: "device_code",
730
- ...info
731
- }),
732
- onPrompt: (prompt) => callbacks.prompt({
733
- type: "text",
734
- ...prompt
735
- }),
736
- onProgress: (message) => callbacks.notify({
737
- type: "progress",
738
- message
739
- }),
740
- onManualCodeInput: () => callbacks.prompt({
741
- type: "manual_code",
742
- message: "Paste the authorization code"
743
- }),
744
- onSelect: (prompt) => callbacks.prompt({
745
- type: "select",
746
- ...prompt
747
- }),
748
- signal: callbacks.signal
749
- }),
750
- type: "oauth"
751
- };
752
- },
753
- refresh: async (credential, signal) => ({
754
- ...await config.refreshToken(credential, signal),
755
- type: "oauth"
756
- }),
757
- toAuth: async (credential) => ({ apiKey: config.getApiKey(credential) })
758
- };
759
- }
760
- //#endregion
761
- //#region src/oauth-bridge.ts
762
- var FileCredentialStore = class extends InMemoryCredentialStore {
763
- #path;
764
- constructor(path) {
765
- super();
766
- this.#path = path;
767
- try {
768
- const data = JSON.parse(readFileSync(path, "utf8"));
769
- for (const [providerId, credential] of Object.entries(data)) this.credentials.set(providerId, credential);
770
- } catch {}
771
- }
772
- get path() {
773
- return this.#path;
774
- }
775
- async #persist() {
776
- const credentials = this.credentials;
777
- const data = Object.fromEntries(credentials);
778
- await mkdir(dirname(this.#path), { recursive: true });
779
- const temp = `${this.#path}.tmp-${process.pid}-${Math.floor(Math.random() * 1e9).toString(36)}`;
780
- await writeFile(temp, `${JSON.stringify(data, null, 2)}\n`, { mode: 384 });
781
- await rename(temp, this.#path);
782
- }
783
- modify(providerId, fn, options) {
784
- return super.modify(providerId, async (current) => {
785
- const next = await fn(current);
786
- if (next !== void 0) {
787
- this.credentials.set(providerId, next);
788
- await this.#persist();
789
- }
790
- return next;
791
- }, options);
792
- }
793
- delete(providerId, options) {
794
- return super.delete(providerId, options).then(() => this.#persist());
795
- }
796
- };
797
- function oauthInteraction(ui, signal) {
798
- return {
799
- signal: signal ?? new AbortController().signal,
800
- async prompt(prompt) {
801
- if (prompt.type === "select") {
802
- const options = prompt.options ?? [];
803
- const picked = await ui.select(prompt.message, options.map((option) => option.label));
804
- return options.find((option) => option.label === picked)?.id ?? picked;
805
- }
806
- return ui.input(prompt.message, prompt.placeholder);
807
- },
808
- notify(event) {
809
- if (event.type === "auth_url") ui.notify(`Open this URL to authorize: ${event.url}${event.instructions !== void 0 ? `\n${event.instructions}` : ""}`);
810
- else if (event.type === "device_code") ui.notify(`Visit ${event.verificationUri} and enter code ${event.userCode}`);
811
- else if (event.message !== void 0) ui.notify(event.message);
812
- }
813
- };
814
- }
815
- function oauthConfigOf(providerConfig) {
816
- const oauth = providerConfig?.oauth;
817
- return typeof oauth === "object" && oauth !== null && typeof oauth.login === "function" ? oauth : void 0;
818
- }
819
- function oauthAdapterOf(oauthConfig) {
820
- if (typeof oauthConfig.toAuth === "function") return oauthConfig;
821
- return adaptOAuth(oauthConfig);
822
- }
823
- function providerSupportsOAuth(providerConfig) {
824
- return oauthConfigOf(providerConfig) !== void 0;
825
- }
826
- async function loginPiProvider(options) {
827
- const oauthConfig = oauthConfigOf(options.providerConfig);
828
- if (oauthConfig === void 0) throw new Error(`${options.providerName ?? options.providerId} does not support oauth login`);
829
- const credential = await oauthAdapterOf(oauthConfig).login(oauthInteraction(options.ui, options.signal));
830
- await options.store.modify(options.providerId, async () => credential);
831
- return credential;
832
- }
833
- async function resolveOAuthApiKey(options) {
834
- const oauthConfig = oauthConfigOf(options.providerConfig);
835
- if (oauthConfig === void 0) return void 0;
836
- return (await resolveProviderAuth({
837
- id: options.providerId,
838
- name: options.providerName ?? options.providerId,
839
- auth: { oauth: oauthAdapterOf(oauthConfig) }
840
- }, options.store, { env: async () => void 0 }, options.signal !== void 0 ? { signal: options.signal } : void 0))?.auth?.apiKey;
841
- }
842
- async function storedOAuthCredential(store, providerId) {
843
- const stored = await store.read(providerId, void 0);
844
- return stored?.type === "oauth" ? stored : void 0;
845
- }
846
- //#endregion
847
497
  //#region src/runtime.ts
848
498
  function logger(ctx) {
849
499
  const candidate = ctx.logger;
@@ -2123,6 +1773,12 @@ async function applyPiPackage(ctx, options) {
2123
1773
  };
2124
1774
  subscribeLifecycle(ctx, state);
2125
1775
  subscribeInterceptors(ctx, state);
1776
+ for (const provider of builtinProviders()) state.providers.set(provider.id, {
1777
+ name: provider.name,
1778
+ baseUrl: provider.baseUrl,
1779
+ oauth: provider.auth.oauth
1780
+ });
1781
+ ensureLoginCommand(ctx, state);
2126
1782
  if (options.manifest.skillDirs.length > 0) {
2127
1783
  if (ctx.get("skills") === void 0) logger(ctx).warn("[pi2dsh] migrated skills were not mounted because this DSH composition has no ctx.skills");
2128
1784
  else {
@@ -2161,4 +1817,4 @@ const runtimeInternals = {
2161
1817
  //#endregion
2162
1818
  export { normalizeToolSchema as n, runtimeInternals as r, applyPiPackage as t };
2163
1819
 
2164
- //# sourceMappingURL=runtime-oLd2EInK.mjs.map
1820
+ //# sourceMappingURL=runtime-6DefpI6h.mjs.map