@hyav/pi-provider 0.1.7 → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  import type { ProviderConfig } from "@earendil-works/pi-coding-agent";
2
2
  import { validateProviderModelDrafts } from "./adapter-validation.ts";
3
- import { applyOfficialModelCosts, findOfficialMeta, type OfficialModelMeta } from "./official-pricing.ts";
3
+ import { mergeModelWithPiCatalog, type PiCatalogSnapshot, toPiCatalogSnapshot } from "./pi-model-metadata.ts";
4
4
  import { resolvePricingDetails } from "./pricing-adjustments.ts";
5
5
  import type { PiProviderDependencies } from "./runtime-config.ts";
6
6
  import type {
@@ -99,13 +99,6 @@ export function normalizeProviderModels(models: ProviderModelDraft[]): ProviderM
99
99
  });
100
100
  }
101
101
 
102
- function cloneQuality(quality: NonNullable<OfficialModelMeta["quality"]>): NonNullable<OfficialModelMeta["quality"]> {
103
- return quality.map((score) => ({
104
- ...score,
105
- ...(score.confidenceInterval ? { confidenceInterval: { ...score.confidenceInterval } } : {}),
106
- }));
107
- }
108
-
109
102
  function selectPricingAdjustment(
110
103
  adapter: ProviderAdapter,
111
104
  model: ProviderModelDraft,
@@ -114,56 +107,104 @@ function selectPricingAdjustment(
114
107
  return model.pricingAdjustment ?? policy?.models?.[model.id.trim()] ?? policy?.defaultAdjustment;
115
108
  }
116
109
 
110
+ function costsEqual(left: ProviderModelDraft["cost"], right: ProviderCost): boolean {
111
+ if (left === undefined) return false;
112
+ const candidate = left as Partial<ProviderCost>;
113
+ if (
114
+ candidate.input !== right.input ||
115
+ candidate.output !== right.output ||
116
+ candidate.cacheRead !== right.cacheRead ||
117
+ candidate.cacheWrite !== right.cacheWrite
118
+ ) {
119
+ return false;
120
+ }
121
+ const leftTiers = candidate.tiers ?? [];
122
+ const rightTiers = right.tiers ?? [];
123
+ return (
124
+ leftTiers.length === rightTiers.length &&
125
+ leftTiers.every((tier, index) => {
126
+ const normalized = rightTiers[index];
127
+ return (
128
+ normalized !== undefined &&
129
+ tier.inputTokensAbove === normalized.inputTokensAbove &&
130
+ tier.input === normalized.input &&
131
+ tier.output === normalized.output &&
132
+ tier.cacheRead === normalized.cacheRead &&
133
+ tier.cacheWrite === normalized.cacheWrite
134
+ );
135
+ })
136
+ );
137
+ }
138
+
139
+ function inputsEqual(left: ProviderModelDraft["input"], right: ProviderModel["input"]): boolean {
140
+ return Array.isArray(left) && left.length === right.length && left.every((value, index) => value === right[index]);
141
+ }
142
+
117
143
  function resolveModelRegistration(
118
144
  adapter: ProviderAdapter,
119
145
  runtime: PiProviderDependencies,
120
146
  modelDrafts: ProviderModelDraft[],
121
- officialPricing: Record<string, OfficialModelMeta>,
147
+ catalogSnapshot?: PiCatalogSnapshot | Record<string, unknown>,
122
148
  ): { models: ProviderModel[]; modelMetadata: Record<string, ProviderModelMetadata> } {
123
149
  validateProviderModelDrafts(modelDrafts, `Provider ${adapter.id}`);
124
- const enrichedDrafts = applyOfficialModelCosts(modelDrafts, officialPricing);
150
+ const catalog = toPiCatalogSnapshot(catalogSnapshot);
125
151
  const pricingPolicy = runtime.pricingPolicies?.[adapter.id] ?? adapter.pricing;
126
152
  const metadata: Record<string, ProviderModelMetadata> = {};
127
- const adjustedDrafts = enrichedDrafts.map((model, index) => {
128
- const modelId = model.id.trim();
129
- const originalDraft = modelDrafts[index];
130
- const officialMeta = findOfficialMeta(modelId, officialPricing);
131
- const fieldSources = {
132
- contextWindow:
133
- originalDraft?.contextWindow !== undefined
134
- ? ("provider" as const)
135
- : officialMeta?.contextWindow !== undefined
136
- ? ("official" as const)
137
- : ("default" as const),
138
- maxTokens:
139
- originalDraft?.maxTokens !== undefined
140
- ? ("provider" as const)
141
- : officialMeta?.maxTokens !== undefined
142
- ? ("official" as const)
143
- : ("default" as const),
144
- input:
145
- originalDraft?.input !== undefined
146
- ? ("provider" as const)
147
- : officialMeta?.input !== undefined
148
- ? ("official" as const)
149
- : ("default" as const),
150
- reasoning:
151
- originalDraft?.reasoning !== undefined
152
- ? ("provider" as const)
153
- : officialMeta?.reasoning !== undefined
154
- ? ("official" as const)
155
- : ("default" as const),
156
- };
153
+ const adjustedDrafts = modelDrafts.map((originalDraft) => {
154
+ const modelId = originalDraft.id.trim();
155
+ const useFallback = adapter.usePiModelMetaFallback ?? true;
156
+ const merged = mergeModelWithPiCatalog(originalDraft, catalog, {
157
+ useFallback,
158
+ currentProviderId: adapter.id,
159
+ });
160
+ const mergedDraft = merged.draft;
161
+ const fieldSources = { ...merged.fieldSources };
162
+
163
+ const normalizedModel = normalizeProviderModel(mergedDraft);
164
+ const normalizedCost = normalizeCost(mergedDraft.cost);
165
+
166
+ if (mergedDraft.contextWindow !== undefined && mergedDraft.contextWindow !== normalizedModel.contextWindow) {
167
+ fieldSources.contextWindow = "normalized";
168
+ }
169
+ if (mergedDraft.maxTokens !== undefined && mergedDraft.maxTokens !== normalizedModel.maxTokens) {
170
+ fieldSources.maxTokens = "normalized";
171
+ }
172
+ if (mergedDraft.input !== undefined && !inputsEqual(mergedDraft.input, normalizedModel.input)) {
173
+ fieldSources.input = "normalized";
174
+ }
175
+ if (mergedDraft.reasoning !== undefined && mergedDraft.reasoning !== normalizedModel.reasoning) {
176
+ fieldSources.reasoning = "normalized";
177
+ }
178
+ if (mergedDraft.cost !== undefined && !costsEqual(mergedDraft.cost, normalizedCost)) {
179
+ fieldSources.cost = "normalized";
180
+ }
181
+
157
182
  const source: ProviderPricingSource | "none" =
158
- model.cost === undefined ? "none" : (model.pricingSource ?? "provider");
159
- const pricing = resolvePricingDetails(model.cost, source, selectPricingAdjustment(adapter, model, pricingPolicy));
183
+ mergedDraft.cost === undefined
184
+ ? "none"
185
+ : (mergedDraft.pricingSource ??
186
+ (fieldSources.cost === "mixed"
187
+ ? "mixed"
188
+ : fieldSources.cost === "pi"
189
+ ? "pi"
190
+ : fieldSources.cost === "provider"
191
+ ? "provider"
192
+ : (originalDraft.pricingSource ?? "provider")));
193
+
194
+ const pricing = resolvePricingDetails(
195
+ mergedDraft.cost === undefined ? undefined : normalizedCost,
196
+ source,
197
+ selectPricingAdjustment(adapter, mergedDraft, pricingPolicy),
198
+ );
199
+ if (fieldSources.costBySku) {
200
+ pricing.costBySku = fieldSources.costBySku;
201
+ }
160
202
  metadata[modelId] = {
161
203
  pricing,
162
204
  fieldSources,
163
- ...(officialMeta?.quality ? { quality: cloneQuality(officialMeta.quality) } : {}),
164
205
  };
165
206
  return {
166
- ...model,
207
+ ...mergedDraft,
167
208
  ...(pricing.effectiveCost ? { cost: pricing.effectiveCost } : {}),
168
209
  };
169
210
  });
@@ -228,7 +269,6 @@ function getRegistrationState(adapter: ProviderAdapter): NonNullable<ProviderAda
228
269
  if (!registration) return undefined;
229
270
  registration.normalizedModels ??= [];
230
271
  registration.modelMetadata ??= {};
231
- registration.officialPricing ??= {};
232
272
  registration.activeRefreshes ??= 0;
233
273
  return registration;
234
274
  }
@@ -263,7 +303,7 @@ function shouldOmitOptionalApiKey(adapter: ProviderAdapter, runtime: PiProviderD
263
303
  export function prepareProviderRegistration(
264
304
  adapter: ProviderAdapter,
265
305
  runtime: PiProviderDependencies,
266
- officialPricing: Record<string, OfficialModelMeta> = {},
306
+ catalogSnapshot?: PiCatalogSnapshot | Record<string, unknown>,
267
307
  modelDrafts?: ProviderModelDraft[],
268
308
  ): ProviderConfig {
269
309
  const drafts =
@@ -271,18 +311,24 @@ export function prepareProviderRegistration(
271
311
  (adapter.registration?.normalizedModels === adapter.provider.models
272
312
  ? adapter.registration.modelDrafts
273
313
  : adapter.provider.models);
274
- const resolved = resolveModelRegistration(adapter, runtime, drafts, officialPricing);
314
+ const lifecycle = adapter.lifecycle ?? (adapter.provider.refreshModels as any)?.lifecycle;
315
+ if (lifecycle && drafts && drafts.length > 0) {
316
+ lifecycle.setModels(drafts, adapter.catalog?.source, adapter.catalog?.updatedAt);
317
+ }
318
+ const catalog = toPiCatalogSnapshot(catalogSnapshot);
319
+ const resolved = resolveModelRegistration(adapter, runtime, drafts, catalog);
275
320
  const existingRegistration = getRegistrationState(adapter);
276
321
  const registration: NonNullable<ProviderAdapter["registration"]> = existingRegistration ?? {
277
322
  modelDrafts: drafts,
278
323
  normalizedModels: [],
279
324
  modelMetadata: {},
280
- officialPricing,
325
+ piCatalog: catalog,
281
326
  activeRefreshes: 0,
282
327
  };
283
328
  registration.modelDrafts = drafts;
284
329
  registration.modelMetadata = resolved.modelMetadata;
285
- registration.officialPricing = officialPricing;
330
+ registration.piCatalog = catalog;
331
+ registration.officialPricing = catalogSnapshot as any;
286
332
  const models = replaceModels(registration.normalizedModels, resolved.models);
287
333
  const adapterOwnsCatalog = adapter.catalog !== undefined;
288
334
  adapter.registration = registration;
@@ -307,7 +353,12 @@ export function prepareProviderRegistration(
307
353
  registration.activeRefreshes++;
308
354
  try {
309
355
  const refreshedModels = await originalRefresh(options);
310
- const resolved = resolveModelRegistration(adapter, runtime, refreshedModels, registration.officialPricing);
356
+ const resolved = resolveModelRegistration(
357
+ adapter,
358
+ runtime,
359
+ refreshedModels,
360
+ registration.piCatalog ?? registration.officialPricing,
361
+ );
311
362
  const normalizedModels = replaceModels(registration.normalizedModels, resolved.models);
312
363
  registration.modelDrafts = refreshedModels;
313
364
  registration.modelMetadata = resolved.modelMetadata;
@@ -352,18 +403,22 @@ export function refreshProviderRegistrations(
352
403
  pi: ProviderRegistrationApi,
353
404
  providers: readonly ProviderAdapter[],
354
405
  runtime: PiProviderDependencies,
355
- officialPricing: Record<string, OfficialModelMeta>,
406
+ catalogSnapshot?: PiCatalogSnapshot | Record<string, unknown>,
356
407
  providerDrafts?: ReadonlyMap<ProviderAdapter, ProviderModelDraft[]>,
357
408
  ): void {
409
+ const catalog = toPiCatalogSnapshot(catalogSnapshot);
358
410
  for (const adapter of providers) {
359
411
  const registration = getRegistrationState(adapter);
360
- if (registration) registration.officialPricing = officialPricing;
412
+ if (registration) {
413
+ registration.piCatalog = catalog;
414
+ registration.officialPricing = catalogSnapshot as any;
415
+ }
361
416
  if (registration && registration.activeRefreshes > 0) {
362
417
  registration.deferredRegistration = () =>
363
- registerProviderAdapter(pi, adapter, runtime, officialPricing, providerDrafts?.get(adapter));
418
+ registerProviderAdapter(pi, adapter, runtime, catalogSnapshot, providerDrafts?.get(adapter));
364
419
  continue;
365
420
  }
366
- registerProviderAdapter(pi, adapter, runtime, officialPricing, providerDrafts?.get(adapter));
421
+ registerProviderAdapter(pi, adapter, runtime, catalogSnapshot, providerDrafts?.get(adapter));
367
422
  }
368
423
  }
369
424
 
@@ -371,10 +426,10 @@ export function registerProviderAdapter(
371
426
  pi: ProviderRegistrationApi,
372
427
  adapter: ProviderAdapter,
373
428
  runtime: PiProviderDependencies,
374
- officialPricing: Record<string, OfficialModelMeta> = {},
429
+ catalogSnapshot?: PiCatalogSnapshot | Record<string, unknown>,
375
430
  modelDrafts?: ProviderModelDraft[],
376
431
  ): ProviderConfig {
377
- const registeredProvider = prepareProviderRegistration(adapter, runtime, officialPricing, modelDrafts);
432
+ const registeredProvider = prepareProviderRegistration(adapter, runtime, catalogSnapshot, modelDrafts);
378
433
  // Pi merges re-registrations, so omission alone cannot clear a raw API key
379
434
  // left by the previous extension instance during /reload.
380
435
  if (registeredProvider.apiKey === undefined) pi.unregisterProvider?.(adapter.id);
@@ -18,7 +18,7 @@ export {
18
18
  defineStatusExtension,
19
19
  defineTunerExtension,
20
20
  } from "./adapter-extensions.ts";
21
- export { MAX_PROVIDER_MODEL_COUNT } from "./adapter-validation.ts";
21
+ export { MAX_PROVIDER_MODEL_COUNT, validateProviderModelDrafts } from "./adapter-validation.ts";
22
22
  export { createCatalogPreflightAdapter } from "./catalog-preflight.ts";
23
23
  export { withDeadline } from "./deadline.ts";
24
24
  export {
@@ -29,7 +29,15 @@ export {
29
29
  mergeDiagnosticHeaders,
30
30
  } from "./diagnostic-auth.ts";
31
31
  export { isProviderDataError, ProviderDataError } from "./errors.ts";
32
+ export type {
33
+ ModelCatalogDiagnostics,
34
+ ModelCatalogDiscoveryResult,
35
+ ModelCatalogLifecycle,
36
+ ModelCatalogLifecycleOptions,
37
+ } from "./model-catalog.ts";
38
+ export { createModelCatalogLifecycle } from "./model-catalog.ts";
32
39
  export { createOpenCodeCatalogPreflightAdapter } from "./opencode-preflight.ts";
40
+ export { isLegacyNormalizedModel, isLegacyNormalizedSnapshot } from "./pi-model-metadata.ts";
33
41
  export type {
34
42
  PreflightAdapter,
35
43
  PreflightContextLike,
@@ -41,10 +49,15 @@ export { parseRetryAfter } from "./retry-after.ts";
41
49
  export type { StatusContextLike } from "./status-manager.ts";
42
50
  export type {
43
51
  ActiveModel,
52
+ ModelCatalogSource,
44
53
  ModelCatalogStatus,
45
54
  ProviderAdapter,
55
+ ProviderCost,
46
56
  ProviderModel,
47
57
  ProviderModelDraft,
58
+ ProviderPricingAdjustment,
59
+ ProviderPricingPolicy,
60
+ ProviderPricingSource,
48
61
  ProviderRefreshContext,
49
62
  ProviderRequestAuth,
50
63
  StatusAdapter,
@@ -52,5 +65,7 @@ export type {
52
65
  StatusEntry,
53
66
  StatusSnapshot,
54
67
  StoredCredentialLike,
68
+ ThinkingLevel,
69
+ TunerAdapter,
55
70
  TunerContext,
56
71
  } from "./types.ts";
@@ -2,7 +2,6 @@ import { homedir } from "node:os";
2
2
  import { join } from "node:path";
3
3
  import { isValidTimeoutMs } from "./deadline.ts";
4
4
  import type { PiProviderDefinition } from "./definition.ts";
5
- import { getDefaultOpenRouterMetadataCachePath, OPENROUTER_MODELS_URL } from "./official-pricing.ts";
6
5
  import { validatePricingPolicy } from "./pricing-adjustments.ts";
7
6
  import type { ProviderPricingPolicy, StoredCredentialLike } from "./types.ts";
8
7
 
@@ -12,21 +11,26 @@ export interface PiProviderDependencies {
12
11
  modelDiscoveryTimeoutMs: number;
13
12
  statusRequestTimeoutMs: number;
14
13
  liveCheckRequestTimeoutMs: number;
15
- officialPricingUrl: string;
16
- officialPricingTimeoutMs: number;
17
- officialPricingCacheTtlMs: number;
18
- officialPricingMaxStaleMs: number;
19
- /** Resolved Pi agent directory; empty disables disk persistence of pricing metadata. */
14
+ /** Resolved Pi agent directory. */
20
15
  agentDir: string;
21
- /** Persistent cache for OpenRouter metadata used by the pricing fallback. */
22
- openRouterMetadataCachePath: string;
23
16
  /** Read Pi's stored credential metadata; injected by the Pi entrypoint. */
24
17
  readStoredCredential: (providerId: string) => StoredCredentialLike | undefined;
25
18
  /** Wrap ANSI-aware text to a render width; injected by the Pi entrypoint. */
26
19
  wrapTextWithAnsi: (text: string, width: number) => string[];
27
- enableOfficialPricingFallback: boolean;
28
20
  /** Optional Pi Provider-level price policies keyed by Provider ID. */
29
21
  pricingPolicies?: Record<string, ProviderPricingPolicy>;
22
+ /** @deprecated OpenRouter pricing metadata has been removed. */
23
+ officialPricingUrl?: string;
24
+ /** @deprecated No longer used. */
25
+ officialPricingTimeoutMs?: number;
26
+ /** @deprecated No longer used. */
27
+ officialPricingCacheTtlMs?: number;
28
+ /** @deprecated No longer used. */
29
+ officialPricingMaxStaleMs?: number;
30
+ /** @deprecated No longer used. */
31
+ openRouterMetadataCachePath?: string;
32
+ /** @deprecated No longer used. */
33
+ enableOfficialPricingFallback?: boolean;
30
34
  }
31
35
 
32
36
  export type PiProviderLoader = (runtime: PiProviderDependencies) => Promise<PiProviderDefinition>;
@@ -90,7 +94,7 @@ function defaultWrapTextWithAnsi(text: string, width: number): string[] {
90
94
  return chunks;
91
95
  }
92
96
 
93
- type DefaultDependencies = Omit<PiProviderDependencies, "agentDir" | "openRouterMetadataCachePath">;
97
+ type DefaultDependencies = Omit<PiProviderDependencies, "agentDir">;
94
98
 
95
99
  const defaultDependencies: DefaultDependencies = {
96
100
  fetch: globalThis.fetch,
@@ -98,25 +102,19 @@ const defaultDependencies: DefaultDependencies = {
98
102
  modelDiscoveryTimeoutMs: 3_000,
99
103
  statusRequestTimeoutMs: 8_000,
100
104
  liveCheckRequestTimeoutMs: 8_000,
101
- officialPricingUrl: OPENROUTER_MODELS_URL,
102
- officialPricingTimeoutMs: 3_000,
103
- officialPricingCacheTtlMs: 60 * 60 * 1_000,
104
- officialPricingMaxStaleMs: 24 * 60 * 60 * 1_000,
105
105
  readStoredCredential: () => undefined,
106
106
  wrapTextWithAnsi: defaultWrapTextWithAnsi,
107
- enableOfficialPricingFallback: true,
108
107
  pricingPolicies: {},
109
108
  };
110
109
 
111
110
  /**
112
- * Programmatic defaults keep the resolved agent directory and its pricing cache
113
- * path. The Pi entrypoint overrides `agentDir` with Pi's own resolution.
111
+ * Programmatic defaults keep the resolved agent directory.
112
+ * The Pi entrypoint overrides `agentDir` with Pi's own resolution.
114
113
  */
115
114
  export function getDefaultPiProviderDependencies(agentDir = resolveDefaultAgentDir()): PiProviderDependencies {
116
115
  return {
117
116
  ...defaultDependencies,
118
117
  agentDir,
119
- openRouterMetadataCachePath: getDefaultOpenRouterMetadataCachePath(agentDir),
120
118
  };
121
119
  }
122
120
 
@@ -127,23 +125,11 @@ export function validatePiProviderDependencies(runtime: PiProviderDependencies):
127
125
  ["modelDiscoveryTimeoutMs", runtime.modelDiscoveryTimeoutMs],
128
126
  ["statusRequestTimeoutMs", runtime.statusRequestTimeoutMs],
129
127
  ["liveCheckRequestTimeoutMs", runtime.liveCheckRequestTimeoutMs],
130
- ["officialPricingTimeoutMs", runtime.officialPricingTimeoutMs],
131
128
  ] as const) {
132
129
  if (!isValidTimeoutMs(value)) throw new Error(`Pi Provider ${name} must be a valid timeout`);
133
130
  }
134
- for (const [name, value] of [
135
- ["officialPricingCacheTtlMs", runtime.officialPricingCacheTtlMs],
136
- ["officialPricingMaxStaleMs", runtime.officialPricingMaxStaleMs],
137
- ] as const) {
138
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
139
- throw new Error(`Pi Provider ${name} must be a finite non-negative number`);
140
- }
141
- }
142
- if (typeof runtime.officialPricingUrl !== "string" || runtime.officialPricingUrl.trim() === "") {
143
- throw new Error("Pi Provider officialPricingUrl must be a non-empty string");
144
- }
145
- if (typeof runtime.openRouterMetadataCachePath !== "string") {
146
- throw new Error("Pi Provider openRouterMetadataCachePath must be a string");
131
+ if (typeof runtime.agentDir !== "string") {
132
+ throw new Error("Pi Provider agentDir must be a string");
147
133
  }
148
134
  if (typeof runtime.readStoredCredential !== "function") {
149
135
  throw new Error("Pi Provider readStoredCredential must be a function");
@@ -151,9 +137,6 @@ export function validatePiProviderDependencies(runtime: PiProviderDependencies):
151
137
  if (typeof runtime.wrapTextWithAnsi !== "function") {
152
138
  throw new Error("Pi Provider wrapTextWithAnsi must be a function");
153
139
  }
154
- if (typeof runtime.enableOfficialPricingFallback !== "boolean") {
155
- throw new Error("Pi Provider enableOfficialPricingFallback must be a boolean");
156
- }
157
140
  if (runtime.pricingPolicies !== undefined) {
158
141
  if (
159
142
  runtime.pricingPolicies === null ||
@@ -173,9 +156,6 @@ export function resolvePiProviderDependencies(
173
156
  dependencies: Partial<PiProviderDependencies> = {},
174
157
  ): PiProviderDependencies {
175
158
  const runtime = { ...getDefaultPiProviderDependencies(), ...dependencies };
176
- if (!Object.hasOwn(dependencies, "openRouterMetadataCachePath")) {
177
- runtime.openRouterMetadataCachePath = getDefaultOpenRouterMetadataCachePath(runtime.agentDir);
178
- }
179
159
  if (runtime.pricingPolicies === undefined) runtime.pricingPolicies = {};
180
160
  validatePiProviderDependencies(runtime);
181
161
  return runtime;
@@ -1,6 +1,7 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { loadPackageAdapterExtensions } from "./adapter-loader.ts";
3
3
  import { createPiProviderHost } from "./host.ts";
4
+ import type { PiCatalogSource } from "./pi-model-metadata.ts";
4
5
  import type { PiProviderDependencies } from "./runtime-config.ts";
5
6
  import type { StoredCredentialLike } from "./types.ts";
6
7
 
@@ -11,16 +12,20 @@ export interface PiProviderEntry {
11
12
  wrapTextWithAnsi: (text: string, width: number) => string[];
12
13
  adapterRoot?: string;
13
14
  dependencies?: Partial<PiProviderDependencies>;
15
+ piCatalogSource?: PiCatalogSource;
14
16
  }
15
17
 
16
18
  /** Runs the Pi Provider host and adapter discovery inside a single Jiti module graph. */
17
19
  export async function runPiProviderEntry(pi: ExtensionAPI, entry: PiProviderEntry): Promise<void> {
18
- const piProviderHost = createPiProviderHost({
19
- agentDir: entry.agentDir,
20
- readStoredCredential: entry.readStoredCredential,
21
- wrapTextWithAnsi: entry.wrapTextWithAnsi,
22
- ...entry.dependencies,
23
- });
20
+ const piProviderHost = createPiProviderHost(
21
+ {
22
+ agentDir: entry.agentDir,
23
+ readStoredCredential: entry.readStoredCredential,
24
+ wrapTextWithAnsi: entry.wrapTextWithAnsi,
25
+ ...entry.dependencies,
26
+ },
27
+ { piCatalogSource: entry.piCatalogSource },
28
+ );
24
29
  piProviderHost(pi);
25
30
  await loadPackageAdapterExtensions(pi, { agentDir: entry.agentDir, userRoot: entry.adapterRoot });
26
31
  }