fix: pass parent modelRuntime so extension providers work in ralpi sessions

ralpi's runAgentSession was letting createAgentSession create a fresh
ModelRuntime from models.json only. This excluded extension-registered
providers like neuralwatt, whose streamSimple wrapper handles:
- 429 rate-limit header parsing (concurrent/TPM/admission/RPM)
- Rate-limit error normalization for Pi's retry logic
- Context-overflow error normalization

Without the wrapper, neuralwatt rate-limit and context-overflow errors
surfaced as raw unrecoverable errors instead of being retried by Pi's
built-in retry. Now passes ctx.modelRegistry.runtime (the underlying
ModelRuntime) through to createAgentSession.
This commit is contained in:
2026-07-17 11:11:21 -04:00
parent 087c64ff18
commit 008489a91b
2 changed files with 15 additions and 1 deletions

View File

@@ -3,7 +3,10 @@ import * as path from "node:path";
import type { Task, Project, Reflection, ToolUsage } from "./types"; import type { Task, Project, Reflection, ToolUsage } from "./types";
import type { RalpiConfig } from "./types"; import type { RalpiConfig } from "./types";
import type { ProgressTracker } from "./progress"; import type { ProgressTracker } from "./progress";
import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; import type {
ExtensionContext,
ModelRuntime,
} from "@earendil-works/pi-coding-agent";
import { buildTaskPrompt, buildReviewPrompt, MAX_DIFF_BYTES } from "./prompts"; import { buildTaskPrompt, buildReviewPrompt, MAX_DIFF_BYTES } from "./prompts";
import { extractReflection } from "./reflection"; import { extractReflection } from "./reflection";
import { import {
@@ -291,6 +294,8 @@ export async function runTask(
undefined, // no abort signal undefined, // no abort signal
assignedModel ?? config.model, assignedModel ?? config.model,
config.thinkingLevel, config.thinkingLevel,
false, // noSkills — task sessions need skills
(ctx.modelRegistry as any).runtime as ModelRuntime,
); );
const durationMs = Date.now() - startMs; const durationMs = Date.now() - startMs;
@@ -713,6 +718,7 @@ async function executeTask(
"", "",
"Stage only the files relevant to this task with `git add <files>`, then create a meaningful git commit.", "Stage only the files relevant to this task with `git add <files>`, then create a meaningful git commit.",
"Use a descriptive commit message and follow conventional commits format.", "Use a descriptive commit message and follow conventional commits format.",
"Do NOT include the task number, task ID, or any ralpi task reference in the commit message. The commit message must describe only the work done — never mention the task ID (e.g. `task 03`, `#3`, etc.).",
"", "",
"### Current Changes (git status --porcelain)", "### Current Changes (git status --porcelain)",
"```text", "```text",
@@ -1061,6 +1067,7 @@ async function runFollowUpSession(
model, model,
config.thinkingLevel, config.thinkingLevel,
true, // noSkills — follow-up sessions don't need the skills catalog true, // noSkills — follow-up sessions don't need the skills catalog
(ctx.modelRegistry as any).runtime as ModelRuntime,
); );
if (result.success) break; if (result.success) break;

View File

@@ -14,6 +14,7 @@ import {
getAgentDir, getAgentDir,
SessionManager, SessionManager,
SettingsManager, SettingsManager,
type ModelRuntime,
} from "@earendil-works/pi-coding-agent"; } from "@earendil-works/pi-coding-agent";
// ─── Directory Helpers ─────────────────────────────────────────────────────── // ─── Directory Helpers ───────────────────────────────────────────────────────
@@ -512,6 +513,11 @@ export async function runAgentSession(
* focused follow-up sessions (commit/review) that don't need skills — * focused follow-up sessions (commit/review) that don't need skills —
* keeps the context lean and avoids dragging in unrelated overhead. */ * keeps the context lean and avoids dragging in unrelated overhead. */
noSkills = false, noSkills = false,
/** Parent session's model runtime. Must be passed so extension-registered
* providers (e.g., neuralwatt with its streamSimple wrapper for 429
* rate-limit normalization) are available. When omitted, the SDK creates
* a fresh runtime from models.json only — extension providers are lost. */
modelRuntime?: ModelRuntime,
): Promise<{ ): Promise<{
success: boolean; success: boolean;
text: string; text: string;
@@ -556,6 +562,7 @@ export async function runAgentSession(
sessionManager: SessionManager.inMemory(), sessionManager: SessionManager.inMemory(),
resourceLoader: loader, resourceLoader: loader,
settingsManager: SettingsManager.create(cwd, getAgentDir()), settingsManager: SettingsManager.create(cwd, getAgentDir()),
modelRuntime,
tools: ["read", "bash", "edit", "write", "grep", "find", "ls"], tools: ["read", "bash", "edit", "write", "grep", "find", "ls"],
model: model as any, model: model as any,
thinkingLevel: thinkingLevel as any, thinkingLevel: thinkingLevel as any,