Keep native Bedrock implementation in standalone traces

This commit is contained in:
amosblomqvist
2026-10-28 04:54:57 +02:00
parent f84bef1f91
commit fb7341d82b
3 changed files with 21 additions and 12 deletions
+13 -8
View File
@@ -1,7 +1,7 @@
/** /**
* OFFLINE native Pi Google initialization gate (no generation or provider calls). * OFFLINE native Pi Google/Bedrock initialization gate (no generation or provider calls).
* Unlike /api/models, this traverses Pi's lazy adapter and constructs GoogleGenAI. * Unlike /api/models, this traverses Pi's lazy adapters and constructs real SDK clients.
* The real onPayload hook throws a unique sentinel BEFORE generateContentStream. * The real onPayload hook throws a unique sentinel BEFORE SDK request dispatch.
* All file modules must resolve inside the payload, including nested dependencies. * All file modules must resolve inside the payload, including nested dependencies.
* *
* node scripts/smoke-provider-runtime.mjs [--standalone <dir>] [--runtime <Node/Electron>] * node scripts/smoke-provider-runtime.mjs [--standalone <dir>] [--runtime <Node/Electron>]
@@ -81,17 +81,22 @@ async function probe(standalone) {
const entry = pathToFileURL(path.join(root, "node_modules/@earendil-works/pi-ai/dist/index.js")); const entry = pathToFileURL(path.join(root, "node_modules/@earendil-works/pi-ai/dist/index.js"));
const { createModels } = await import(entry.href); const { createModels } = await import(entry.href);
const models = createModels(); const models = createModels();
for (const [name, factory] of [["google", "googleProvider"], ["opencode", "opencodeProvider"], ["opencode-go", "opencodeGoProvider"]]) { for (const [name, factory, api, label] of [
["google", "googleProvider", "google-generative-ai", "Google"],
["opencode", "opencodeProvider", "google-generative-ai", "Google"],
["opencode-go", "opencodeGoProvider", "google-generative-ai", "Google"],
["amazon-bedrock", "amazonBedrockProvider", "bedrock-converse-stream", "Bedrock"],
]) {
const provider = (await import(new URL(`providers/${name}.js`, entry).href))[factory](); const provider = (await import(new URL(`providers/${name}.js`, entry).href))[factory]();
models.setProvider(provider); models.setProvider(provider);
const model = provider.getModels().find((candidate) => candidate.api === "google-generative-ai"); const model = provider.getModels().find((candidate) => candidate.api === api);
assert.ok(model, `${name}: missing Google-backed catalog model`); assert.ok(model, `${name}: missing ${api} catalog model`);
const sentinel = `LH_OFFLINE_ON_PAYLOAD_${randomUUID()}`; const sentinel = `LH_OFFLINE_ON_PAYLOAD_${randomUUID()}`;
let reached = 0; let reached = 0;
const result = await models.streamSimple(model, { messages: [{ role: "user", content: "Offline initialization only", timestamp: 0 }] }, { const result = await models.streamSimple(model, { messages: [{ role: "user", content: "Offline initialization only", timestamp: 0 }] }, {
apiKey: "dummy-offline-provider-gate-not-a-key", apiKey: "dummy-offline-provider-gate-not-a-key",
onPayload(payload, selected) { onPayload(payload, selected) {
assert.equal(selected.api, "google-generative-ai"); assert.equal(selected.api, api);
assert.ok(payload && typeof payload === "object"); assert.ok(payload && typeof payload === "object");
reached++; reached++;
throw new Error(sentinel); throw new Error(sentinel);
@@ -101,7 +106,7 @@ async function probe(standalone) {
assert.equal(result.stopReason, "error"); assert.equal(result.stopReason, "error");
assert.equal(result.errorMessage, sentinel, `${name}: unexpected initialization error`); assert.equal(result.errorMessage, sentinel, `${name}: unexpected initialization error`);
noNetwork(); noNetwork();
console.log(`[smoke-provider-runtime] ${name}: native lazy Google adapter reached onPayload; generation stopped`); console.log(`[smoke-provider-runtime] ${name}: native lazy ${label} adapter reached onPayload; generation stopped`);
} }
// Exercise the public lazy OAuth surface offline. toAuth evaluates the // Exercise the public lazy OAuth surface offline. toAuth evaluates the
// real flow module and its imports but neither logs in nor refreshes. // real flow module and its imports but neither logs in nor refreshes.
+5 -2
View File
@@ -8,7 +8,7 @@ import { openAICodexResponsesApi } from "@earendil-works/pi-ai/api/openai-codex-
import { azureOpenAIResponsesApi } from "@earendil-works/pi-ai/api/azure-openai-responses.lazy"; import { azureOpenAIResponsesApi } from "@earendil-works/pi-ai/api/azure-openai-responses.lazy";
import { googleGenerativeAIApi } from "@earendil-works/pi-ai/api/google-generative-ai.lazy"; import { googleGenerativeAIApi } from "@earendil-works/pi-ai/api/google-generative-ai.lazy";
import { googleVertexApi } from "@earendil-works/pi-ai/api/google-vertex.lazy"; import { googleVertexApi } from "@earendil-works/pi-ai/api/google-vertex.lazy";
import { bedrockConverseStreamApi } from "@earendil-works/pi-ai/api/bedrock-converse-stream.lazy"; import { lazyApi } from "@earendil-works/pi-ai/api/lazy";
import { mistralConversationsApi } from "@earendil-works/pi-ai/api/mistral-conversations.lazy"; import { mistralConversationsApi } from "@earendil-works/pi-ai/api/mistral-conversations.lazy";
import { piMessagesApi } from "@earendil-works/pi-ai/api/pi-messages.lazy"; import { piMessagesApi } from "@earendil-works/pi-ai/api/pi-messages.lazy";
import { resolveCustomValue, type CustomProviderConfig } from "../core/custom-providers.ts"; import { resolveCustomValue, type CustomProviderConfig } from "../core/custom-providers.ts";
@@ -21,7 +21,10 @@ const apis: Record<string, ProviderStreams> = {
"azure-openai-responses": azureOpenAIResponsesApi(), "azure-openai-responses": azureOpenAIResponsesApi(),
"google-generative-ai": googleGenerativeAIApi(), "google-generative-ai": googleGenerativeAIApi(),
"google-vertex": googleVertexApi(), "google-vertex": googleVertexApi(),
"bedrock-converse-stream": bedrockConverseStreamApi(), // Pi's Bedrock wrapper intentionally hides its Node-only import from
// bundlers. Give this server's standalone tracer a literal public import;
// Pi still owns both lazy forwarding and the unchanged native transport.
"bedrock-converse-stream": lazyApi(() => import("@earendil-works/pi-ai/api/bedrock-converse-stream")),
"mistral-conversations": mistralConversationsApi(), "mistral-conversations": mistralConversationsApi(),
"pi-messages": piMessagesApi(), "pi-messages": piMessagesApi(),
}; };
+3 -2
View File
@@ -1,4 +1,4 @@
/** Real installed Pi/Google SDK only; no provider stubs, keys, or generation. */ /** Real installed Pi/Google/Bedrock SDKs only; no provider stubs, keys, or generation. */
import assert from "node:assert/strict"; import assert from "node:assert/strict";
import { spawnSync } from "node:child_process"; import { spawnSync } from "node:child_process";
import * as fs from "node:fs"; import * as fs from "node:fs";
@@ -12,11 +12,12 @@ const checkout = fileURLToPath(new URL("..", import.meta.url));
const run = (payload: string) => spawnSync(process.execPath, [script, "--standalone", payload], { encoding: "utf8", timeout: 40_000 }); const run = (payload: string) => spawnSync(process.execPath, [script, "--standalone", payload], { encoding: "utf8", timeout: 40_000 });
describe("offline native Pi Google initialization gate", () => { describe("offline native Pi Google initialization gate", () => {
it("reaches the sentinel for direct Google and Google-backed OpenCode adapters using the real SDK", () => { it("reaches the sentinel for Google, Google-backed OpenCode and Bedrock adapters using the real SDKs", () => {
// This is an unbundled positive control, NOT proof of standalone completeness. // This is an unbundled positive control, NOT proof of standalone completeness.
const result = run(checkout); const result = run(checkout);
assert.equal(result.status, 0, String(result.stderr)); assert.equal(result.status, 0, String(result.stderr));
for (const provider of ["google", "opencode", "opencode-go"]) assert.ok(String(result.stdout).includes(`${provider}: native lazy Google adapter reached onPayload`)); for (const provider of ["google", "opencode", "opencode-go"]) assert.ok(String(result.stdout).includes(`${provider}: native lazy Google adapter reached onPayload`));
assert.ok(String(result.stdout).includes("amazon-bedrock: native lazy Bedrock adapter reached onPayload"));
assert.match(String(result.stdout), /zero network attempts/); assert.match(String(result.stdout), /zero network attempts/);
}); });
it("rejects a missing Pi entry instead of treating any error as success", () => { it("rejects a missing Pi entry instead of treating any error as success", () => {