mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(models): repair local model no-auth and overflow handling (#121790)
Preserve the internal null Authorization marker when resolving local no-auth provider headers, avoid classifying LM Studio prompt-template guidance as context overflow, and rebuild ai/llm-core package sources during pnpm dev/watch.
This commit is contained in:
committed by
GitHub
parent
abb856ece4
commit
ba58803997
@@ -319,6 +319,11 @@ export function resolveAiTransportHeaderSentinels(
|
|||||||
const host = getAiTransportHost();
|
const host = getAiTransportHost();
|
||||||
let resolvedHeaders: Record<string, string> | undefined;
|
let resolvedHeaders: Record<string, string> | undefined;
|
||||||
for (const [name, value] of Object.entries(headers)) {
|
for (const [name, value] of Object.entries(headers)) {
|
||||||
|
if (value === null) {
|
||||||
|
// applyLocalNoAuthHeaderOverride marks no-auth local providers with a
|
||||||
|
// runtime null marker outside the public string-only Model contract.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const resolved = host.resolveSecretSentinel(value);
|
const resolved = host.resolveSecretSentinel(value);
|
||||||
if (resolved !== value) {
|
if (resolved !== value) {
|
||||||
resolvedHeaders ??= { ...headers };
|
resolvedHeaders ??= { ...headers };
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ describe("prepareModelForSimpleCompletion", () => {
|
|||||||
expect(result).toBe(model);
|
expect(result).toBe(model);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("aliases a provider-owned stream when its wire-format api is already registered", async () => {
|
it("aliases a provider-owned stream while preserving its null auth-header marker", async () => {
|
||||||
const builtInStream = vi.fn(() => createAssistantMessageEventStream());
|
const builtInStream = vi.fn(() => createAssistantMessageEventStream());
|
||||||
apiRegistry.registerApiProvider(
|
apiRegistry.registerApiProvider(
|
||||||
{
|
{
|
||||||
@@ -260,6 +260,7 @@ describe("prepareModelForSimpleCompletion", () => {
|
|||||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
contextWindow: 32768,
|
contextWindow: 32768,
|
||||||
maxTokens: 2048,
|
maxTokens: 2048,
|
||||||
|
headers: { Authorization: null } as never,
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = prepareModelForSimpleCompletion({ model });
|
const result = prepareModelForSimpleCompletion({ model });
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ const RUN_NODE_PACKAGE_SOURCE_ROOTS = [
|
|||||||
// Root runtime code imports these package sources through tsconfig aliases,
|
// Root runtime code imports these package sources through tsconfig aliases,
|
||||||
// while pnpm dev/watch still runs the root dist entrypoint. Treat them like
|
// while pnpm dev/watch still runs the root dist entrypoint. Treat them like
|
||||||
// src/ so edits restart the same process that consumes them.
|
// src/ so edits restart the same process that consumes them.
|
||||||
|
"packages/ai/src",
|
||||||
"packages/gateway-client/src",
|
"packages/gateway-client/src",
|
||||||
"packages/gateway-protocol/src",
|
"packages/gateway-protocol/src",
|
||||||
"packages/markdown-core/src",
|
"packages/markdown-core/src",
|
||||||
|
"packages/llm-core/src",
|
||||||
"packages/media-core/src",
|
"packages/media-core/src",
|
||||||
"packages/media-generation-core/src",
|
"packages/media-generation-core/src",
|
||||||
"packages/media-understanding-common/src",
|
"packages/media-understanding-common/src",
|
||||||
|
|||||||
@@ -9,4 +9,12 @@ describe("isLikelyContextOverflowError", () => {
|
|||||||
),
|
),
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not mistake LM Studio prompt-template override guidance for overflow", () => {
|
||||||
|
expect(
|
||||||
|
isLikelyContextOverflowError(
|
||||||
|
'Error rendering prompt with jinja template: "Cannot apply filter upper to type UndefinedValue". You can override the prompt template in model settings.',
|
||||||
|
),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -133,6 +133,9 @@ export function isLikelyContextOverflowError(errorMessage?: string): boolean {
|
|||||||
if (isContextOverflowError(errorMessage)) {
|
if (isContextOverflowError(errorMessage)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (normalizeLowercaseStringOrEmpty(errorMessage).includes("prompt template")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (RATE_LIMIT_HINT_RE.test(errorMessage)) {
|
if (RATE_LIMIT_HINT_RE.test(errorMessage)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,14 @@ describe("bundled plugin assets", () => {
|
|||||||
expect(isRestartRelevantRunNodePath("extensions/discord/src/activities/http.ts")).toBe(true);
|
expect(isRestartRelevantRunNodePath("extensions/discord/src/activities/http.ts")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each(["packages/ai/src/host.ts", "packages/llm-core/src/types.ts"])(
|
||||||
|
"rebuilds the root runtime for %s",
|
||||||
|
(source) => {
|
||||||
|
expect(isBuildRelevantRunNodePath(source)).toBe(true);
|
||||||
|
expect(isRestartRelevantRunNodePath(source)).toBe(true);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
it("refreshes generated output metadata without recreating the watcher", async () => {
|
it("refreshes generated output metadata without recreating the watcher", async () => {
|
||||||
await withPluginAssetFixture(async (rootDir) => {
|
await withPluginAssetFixture(async (rootDir) => {
|
||||||
const packagePath = path.join(rootDir, "extensions", "canvas", "package.json");
|
const packagePath = path.join(rootDir, "extensions", "canvas", "package.json");
|
||||||
|
|||||||
Reference in New Issue
Block a user