* Lazily create (or return existing) session for a channel.
(
adapter: RuntimePlatform,
channelId: string,
)
| 495 | * Lazily create (or return existing) session for a channel. |
| 496 | */ |
| 497 | private async getOrCreateSession( |
| 498 | adapter: RuntimePlatform, |
| 499 | channelId: string, |
| 500 | ): Promise<ChannelSession> { |
| 501 | const existing = this.channels.get(channelId); |
| 502 | if (existing) return existing; |
| 503 | |
| 504 | const pendingCreation = this.pendingSessionCreations.get(channelId); |
| 505 | if (pendingCreation) return pendingCreation; |
| 506 | |
| 507 | const createSessionPromise = (async () => { |
| 508 | const { rootDir, provider, modelId, baseUrl } = this.options; |
| 509 | |
| 510 | // Use the shared AuthStorage instance (supports both API Key and OAuth) |
| 511 | const authStorage = this.authStorage; |
| 512 | |
| 513 | const modelRegistry = ModelRegistry.create(authStorage); |
| 514 | |
| 515 | // When a custom base URL is provided, register a custom model entry with the |
| 516 | // correct API protocol. Most proxies/local endpoints use the Completions API, |
| 517 | // so default to "openai-completions" unless the user explicitly chose "openai-responses". |
| 518 | if (baseUrl && modelId) { |
| 519 | const customModel = createCustomProviderModelConfig( |
| 520 | this.options, |
| 521 | modelRegistry, |
| 522 | ); |
| 523 | log( |
| 524 | `[PackAgent] Registering custom model: `, |
| 525 | JSON.stringify(customModel), |
| 526 | ); |
| 527 | modelRegistry.registerProvider(provider, { |
| 528 | baseUrl, |
| 529 | apiKey: this.options.apiKey, |
| 530 | models: [customModel], |
| 531 | }); |
| 532 | } |
| 533 | |
| 534 | const resolvedModel = modelRegistry.find(provider, modelId); |
| 535 | const model = |
| 536 | resolvedModel && baseUrl && !this.options.apiProtocol |
| 537 | ? { ...resolvedModel, baseUrl } |
| 538 | : resolvedModel; |
| 539 | if (resolvedModel && baseUrl) { |
| 540 | log( |
| 541 | `[PackAgent] Resolved ${provider}/${modelId} api=${resolvedModel.api} baseUrl=${baseUrl}`, |
| 542 | ); |
| 543 | } |
| 544 | |
| 545 | const sessionDir = path.resolve(rootDir, "data", "sessions", channelId); |
| 546 | fs.mkdirSync(sessionDir, { recursive: true }); |
| 547 | const sessionManager = SessionManager.continueRecent(rootDir, sessionDir); |
| 548 | log(`[PackAgent] Session dir: ${sessionDir}`); |
| 549 | |
| 550 | const workspaceDir = path.resolve( |
| 551 | rootDir, |
| 552 | "data", |
| 553 | "workspaces", |
| 554 | channelId, |
no test coverage detected