Keep native Bedrock implementation in standalone traces
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user