@@ -94,9 +94,18 @@ function effortLevels(model: PiModel): PiEffort[] {
9494 return level !== 'xhigh' || mapped !== undefined ;
9595 } ) ;
9696}
97- function modelOptions ( models : PiModel [ ] ) {
97+ /**
98+ * How a session names a model on the wire. An account-bound session speaks the account's own
99+ * vocabulary — endpoint-owned ids, unprefixed — because that is the list the client picks from;
100+ * qualifying them leaves the picker unable to match the id the session reflects back at it.
101+ */
102+ function advertisedModelId ( model : PiModel , accountProvider : string | undefined ) : string {
103+ return model . provider === accountProvider ? model . id : `${ model . provider } /${ model . id } ` ;
104+ }
105+
106+ function modelOptions ( models : PiModel [ ] , accountProvider ?: string ) {
98107 return models . map ( ( model ) => ( {
99- id : ` ${ model . provider } / ${ model . id } ` ,
108+ id : advertisedModelId ( model , accountProvider ) ,
100109 label : model . name ,
101110 description : `${ model . provider } /${ model . id } ` ,
102111 effortLevels : effortLevels ( model ) ,
@@ -177,14 +186,21 @@ function createConfiguredRegistry(
177186 opts : Pick < AgentStartCatalogOptions , 'model' | 'config' > ,
178187 fallbackProvider ?: string ,
179188) {
180- const authStorage = pi . AuthStorage . create ( ) ;
181- const modelRegistry = pi . ModelRegistry . create ( authStorage ) ;
182189 const cred = readAgentCredential ( opts . config ) ;
190+ const key = cred . apiKey ?? cred . authToken ;
191+ // Pi reads a provider's endpoint params only off a *stored* credential — `setRuntimeApiKey` carries
192+ // no env and `registerProvider` has no env field — so seed the store instead. In-memory, because
193+ // `set()` on the file-backed store would leave the account's secret in ~/.pi/agent/auth.json.
194+ const seeded =
195+ key && cred . knownProvider && cred . providerEnv
196+ ? { [ cred . knownProvider ] : { type : 'api_key' as const , key, env : cred . providerEnv } }
197+ : undefined ;
198+ const authStorage = seeded ? pi . AuthStorage . inMemory ( seeded ) : pi . AuthStorage . create ( ) ;
199+ const modelRegistry = pi . ModelRegistry . create ( authStorage ) ;
183200 const ref = opts . model
184201 ? resolveModelRef ( modelRegistry , opts . model , cred , fallbackProvider )
185202 : null ;
186203
187- const key = cred . apiKey ?? cred . authToken ;
188204 // An explicit model fixes routing; without one, resume evidence outranks the account default.
189205 const provider =
190206 ref ?. provider ??
@@ -194,12 +210,13 @@ function createConfiguredRegistry(
194210 if ( ! provider && ( key || cred . baseUrl ) ) {
195211 throw new Error ( 'pi: cannot target credential without a provider/model' ) ;
196212 }
197- if ( key && provider ) authStorage . setRuntimeApiKey ( provider , key ) ;
198- if ( cred . baseUrl ) {
213+ if ( key && provider && ! seeded ) authStorage . setRuntimeApiKey ( provider , key ) ;
214+ if ( ! seeded && cred . baseUrl ) {
199215 // baseUrl override only: a models-less registerProvider rewrites the URL and leaves each
200216 // model's wire at pi's built-in value, so this works exactly when that provider's built-in
201217 // wire already matches the endpoint. Pointing a provider at a differently-shaped endpoint is
202218 // not expressible without supplying full model metadata (see @linkcode/providers AGENTS.md).
219+ // A seeded provider is the escape hatch: it templates its own per-model URL from the env above.
203220 modelRegistry . registerProvider ( provider , {
204221 baseUrl : cred . baseUrl ,
205222 ...( key && { apiKey : key } ) ,
@@ -254,8 +271,8 @@ export class PiAdapter extends BaseAgentAdapter {
254271
255272 override async startCatalog ( opts : AgentStartCatalogOptions = { } ) : Promise < AgentStartCatalog > {
256273 const pi = await this . importSdk ( ) ;
257- const { modelRegistry } = createConfiguredRegistry ( pi , opts ) ;
258- const models = modelOptions ( modelRegistry . getAvailable ( ) ) ;
274+ const { modelRegistry, credential } = createConfiguredRegistry ( pi , opts ) ;
275+ const models = modelOptions ( modelRegistry . getAvailable ( ) , credential . knownProvider ) ;
259276 return {
260277 models,
261278 policies : [ ...POLICIES ] ,
@@ -374,14 +391,17 @@ export class PiAdapter extends BaseAgentAdapter {
374391 if ( this . lifecycle === generation && this . session === session ) this . handleEvent ( ev ) ;
375392 } ) ;
376393 const runningModel = session . model ?? model ;
377- if ( runningModel ) this . emitModel ( `${ runningModel . provider } /${ runningModel . id } ` ) ;
394+ if ( runningModel ) {
395+ this . emitModel ( advertisedModelId ( runningModel , this . credential . knownProvider ) ) ;
396+ }
378397 this . emitModels (
379398 modelOptions (
380399 this . credentialProviderId
381400 ? modelRegistry
382401 . getAvailable ( )
383402 . filter ( ( item ) => item . provider === this . credentialProviderId )
384403 : modelRegistry . getAvailable ( ) ,
404+ this . credential . knownProvider ,
385405 ) ,
386406 ) ;
387407 this . emitApprovalPolicy ( { availablePolicies : [ ...POLICIES ] , currentPolicyId : this . policyId } ) ;
@@ -476,7 +496,9 @@ export class PiAdapter extends BaseAgentAdapter {
476496 const model = registry . find ( ref . provider , ref . modelId ) ;
477497 if ( ! model ) throw new Error ( `pi: unknown model '${ value } '` ) ;
478498 await session . setModel ( model ) ;
479- if ( session . model ) this . emitModel ( `${ session . model . provider } /${ session . model . id } ` ) ;
499+ if ( session . model ) {
500+ this . emitModel ( advertisedModelId ( session . model , this . credential . knownProvider ) ) ;
501+ }
480502 if ( isEffort ( session . thinkingLevel ) ) this . emitEffort ( session . thinkingLevel ) ;
481503 }
482504
0 commit comments