Ensamblaje createAgentSession
createAgentSession es la entrada central del SDK. Toma AuthStorage, ModelRegistry, SettingsManager, SessionManager, ResourceLoader como servicios externos, más las definiciones de herramientas y el runner de extensiones, y los ensambla en un AgentSession usable. main.ts no la llama directamente, sino a través de createAgentSessionRuntime que pasa por createAgentSessionServices; pero los llamadores del SDK (que incrustan pi en otros programas) la usan tal cual.
Responsabilidades
- Resolución de servicios: cada servicio externo puede pasarse o crearse automáticamente; las rutas por defecto se basan en
agentDir(~/.pi/agent). Verpackages/coding-agent/src/core/sdk.ts:193-211. - Recuperación de modelo: si ya hay datos de sesión, recupera el
modeldel header de la sesión; si no, del settings; si no se puede recuperar, rellenamodelFallbackMessage. Verpackages/coding-agent/src/core/sdk.ts:214-248. - Clampeo de thinking level: toma el thinking level de la sesión o de settings, y luego
clampThinkingLevello acota al rango soportado por el modelo. Verpackages/coding-agent/src/core/sdk.ts:250-269. - Inyección de stream function: el
streamFndelAgentno llama astreamSimpledirectamente, sino que primero pide auth conmodelRegistry.getApiKeyAndHeadersy luego suma las cabeceras de telemetría degetAttributionHeaders. Verpackages/coding-agent/src/core/sdk.ts:328-346. - Envoltura de convertToLlm: cuando
blockImagesestá activo, reemplaza todoImageContentpor texto placeholder, leyendo settings de forma dinámica para que el cambio a mitad de sesión también aplique. Verpackages/coding-agent/src/core/sdk.ts:282-316. - Cabeceras de attribution: OpenRouter y Cloudflare reciben cabeceras HTTP específicas para clasificación. Ver
packages/coding-agent/src/core/sdk.ts:128-156.
Motivación de diseño
¿Por qué no dejar que el llamador haga new Agent y luego new AgentSession? Porque el ensamblaje involucra más de una decena de servicios con dependencias mutuas: auth determina si el modelo está disponible, modelo determina el rango de thinking level, settings determina retry/transport/steering, el resource loader carga extensiones e inyecta el extensionRunnerRef. Exponer todo eso al llamador es invitar a cada uno a pisar las mismas piedras. createAgentSession concentra las reglas de ensamblaje en una sola función; el llamador del SDK sólo pasa cwd y (opcional) model.
getAttributionHeaders se extrae aparte porque cada provider necesita cabeceras distintas: OpenRouter usa HTTP-Referer + X-OpenRouter-*, Cloudflare usa User-Agent. Centralizarlo evita que se desparrame por la ruta de stream.
Archivos clave
packages/coding-agent/src/core/sdk.ts:33-80—CreateAgentSessionOptions, todos los parámetros de ensamblaje (cwd, authStorage, modelRegistry, model, tools, scopedModels, customTools, resourceLoader, sessionManager, settingsManager).packages/coding-agent/src/core/sdk.ts:82-90—CreateAgentSessionResult:session+extensionsResult+ opcionalmodelFallbackMessage.packages/coding-agent/src/core/sdk.ts:124-126—getDefaultAgentDir, directorio global de configuración por defecto.packages/coding-agent/src/core/sdk.ts:128-156—getAttributionHeaders, cabeceras de telemetría específicas por provider.packages/coding-agent/src/core/sdk.ts:193-211— Inicio decreateAgentSession: resolución de servicios y valores por defecto.packages/coding-agent/src/core/sdk.ts:320-376— Constructornew Agent({...}), inyectandostreamFn,onPayload,onResponse,transformContext,steeringMode,transporty todos los parámetros de runtime.packages/coding-agent/src/core/sdk.ts:392-413— Al finalnew AgentSession({...})y devolución delCreateAgentSessionResult.packages/coding-agent/src/core/sdk.ts:108-120— Re-export de fábricas de herramientas; el llamador del SDK puede tomarcreateCodingToolsetc. directamente.
En el punto de inyección de streamFn se ve cómo un fallo de auth cortocircuita y cómo se combinan las cabeceras de attribution:
// packages/coding-agent/src/core/sdk.ts:328-346
streamFn: async (model, context, options) => {
const auth = await modelRegistry.getApiKeyAndHeaders(model);
if (!auth.ok) {
throw new Error(auth.error);
}
const providerRetrySettings = settingsManager.getProviderRetrySettings();
const attributionHeaders = getAttributionHeaders(model, settingsManager);
return streamSimple(model, context, {
...options,
apiKey: auth.apiKey,
timeoutMs: options?.timeoutMs ?? providerRetrySettings.timeoutMs,
// ...
headers:
attributionHeaders || auth.headers || options?.headers
? { ...attributionHeaders, ...auth.headers, ...options?.headers }
: undefined,
});
},La envoltura de convertToLlm reemplaza imágenes por un placeholder cuando blockImages está activo, y deduplica placeholders consecutivos:
// packages/coding-agent/src/core/sdk.ts:282-298
const convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {
const converted = convertToLlm(messages);
if (!settingsManager.getBlockImages()) {
return converted;
}
return converted.map((msg) => {
if (msg.role === "user" || msg.role === "toolResult") {
const content = msg.content;
if (Array.isArray(content)) {
const hasImages = content.some((c) => c.type === "image");
if (hasImages) {
const filteredContent = content
.map((c) =>
c.type === "image" ? { type: "text" as const, text: "Image reading is disabled." } : c,
)
// ... deduplica ...Flujo de datos
Orden de ensamblaje:
Límites y fallos
- Modelo no recuperable:
modelFallbackMessageavisa de "no se pudo recuperar el modelo guardado" y también de "no hay ningún modelo configurado"; ambos se devuelven y la UI decide cómo mostrarlo. Verpackages/coding-agent/src/core/sdk.ts:243-247. - Sin modelo, thinking off:
if (!model) thinkingLevel = "off", evita enviar parámetros de thinking con modelo vacío. - Sesión ya existente sin entrada thinking: al recuperar, se añade un
appendThinkingLevelChangepara que fork/resume posteriores tengan estado. Verpackages/coding-agent/src/core/sdk.ts:378-390. - transformContext de extensiones: si
extensionRunnerRef.currentno existe, devuelve los messages originales sin lanzar, permitiendo que funcione sin extensión atada.
Resumen
createAgentSession concentra las reglas de ensamblaje de más de una decena de servicios en una sola función; el llamador del SDK sólo pasa cwd y un model opcional. Los detalles hacia abajo en capa de orquestación AgentSession; las fábricas de herramientas en conjunto de herramientas read/bash/edit/write/grep/find/ls; la conversión de mensajes en tipos de mensaje y convertToLlm.