Skip to content

Commit b899689

Browse files
author
sjhu
committed
feat: sync zero-token upstream and restore onboard-auth modules
1 parent 5bdfacd commit b899689

38 files changed

Lines changed: 1543 additions & 314 deletions

src/agents/model-selection.ts

Lines changed: 195 additions & 118 deletions
Large diffs are not rendered by default.

src/agents/models-config.providers.ts

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { OpenClawConfig } from "../config/config.js";
22
import type { ModelDefinitionConfig } from "../config/types.models.js";
3-
import { resolvePluginProviders } from "../plugins/providers.js";
43
import {
54
DEFAULT_COPILOT_API_BASE_URL,
65
resolveCopilotApiToken,
@@ -775,27 +774,10 @@ export async function resolveImplicitProviders(params: {
775774
allowKeychainPrompt: false,
776775
});
777776

778-
// Load additional providers from plugins (only if they have auth credentials)
779-
// This allows plugins to extend the provider list beyond hardcoded providers
780-
const pluginProviders = resolvePluginProviders({
781-
config: params.config,
782-
workspaceDir: params.agentDir,
783-
});
784-
for (const pluginProvider of pluginProviders) {
785-
// Only add plugin providers that have auth credentials in the auth store
786-
// This maintains backward compatibility while allowing plugin extensions
787-
const hasAuth = listProfilesForProvider(authStore, pluginProvider.id).length > 0;
788-
if (!hasAuth) {
789-
continue;
790-
}
791-
// Convert ProviderPlugin to ProviderConfig
792-
providers[pluginProvider.id] = {
793-
baseUrl: pluginProvider.models?.baseUrl ?? "",
794-
apiKey: undefined,
795-
api: pluginProvider.id as any, // eslint-disable-line @typescript-eslint/no-explicit-any
796-
models: pluginProvider.models?.models ?? [],
797-
};
798-
}
777+
// Zero-token providers (deepseek-web, qwen-web, etc.) are added explicitly below
778+
// via build*WebProvider() functions — no plugin-based provider discovery here.
779+
// This avoids upstream's bundled-provider-compat logic that auto-enables
780+
// bundled plugins (e.g. anthropic) which are irrelevant for zero-token.
799781

800782
const minimaxKey =
801783
resolveEnvApiKeyVarName("minimax") ??

src/agents/pi-embedded-runner/compact.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ import { generateSecureToken } from "../../infra/secure-random.js";
2121
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
2222
import { type enqueueCommand, enqueueCommandInLane } from "../../process/command-queue.js";
2323
import { isCronSessionKey, isSubagentSessionKey } from "../../routing/session-key.js";
24-
import { resolveSignalReactionLevel } from "../../signal/reaction-level.js";
25-
import { resolveTelegramInlineButtonsScope } from "../../telegram/inline-buttons.js";
26-
import { resolveTelegramReactionLevel } from "../../telegram/reaction-level.js";
24+
import { createConfiguredOllamaStreamFn } from "../../plugin-sdk/ollama.js";
25+
import { resolveSignalReactionLevel } from "../../plugin-sdk/signal.js";
26+
import {
27+
resolveTelegramInlineButtonsScope,
28+
resolveTelegramReactionLevel,
29+
} from "../../plugin-sdk/telegram.js";
2730
import { buildTtsSystemPromptHint } from "../../tts/tts.js";
2831
import { resolveUserPath } from "../../utils.js";
2932
import { normalizeMessageChannel } from "../../utils/message-channel.js";
@@ -41,7 +44,6 @@ import { resolveOpenClawDocsPath } from "../docs-path.js";
4144
import { getApiKeyForModel, resolveModelAuthMode } from "../model-auth.js";
4245
import { supportsModelTools } from "../model-tool-support.js";
4346
import { ensureOpenClawModelsJson } from "../models-config.js";
44-
import { createConfiguredOllamaStreamFn } from "../ollama-stream.js";
4547
import { resolveOwnerDisplaySetting } from "../owner-display.js";
4648
import {
4749
ensureSessionHeader,
@@ -100,6 +102,7 @@ export type CompactEmbeddedPiSessionParams = {
100102
sessionId: string;
101103
runId?: string;
102104
sessionKey?: string;
105+
allowGatewaySubagentBinding?: boolean;
103106
messageChannel?: string;
104107
messageProvider?: string;
105108
agentAccountId?: string;
@@ -126,8 +129,9 @@ export type CompactEmbeddedPiSessionParams = {
126129
bashElevated?: ExecElevatedDefaults;
127130
customInstructions?: string;
128131
tokenBudget?: number;
132+
currentTokenCount?: number;
129133
force?: boolean;
130-
trigger?: "overflow" | "manual";
134+
trigger?: "overflow" | "manual" | "budget";
131135
diagId?: string;
132136
attempt?: number;
133137
maxAttempts?: number;
@@ -349,7 +353,7 @@ export async function compactEmbeddedPiSessionDirect(
349353
);
350354
}
351355
} else if (model.provider === "github-copilot") {
352-
const { resolveCopilotApiToken } = await import("../../providers/github-copilot-token.js");
356+
const { resolveCopilotApiToken } = await import("../../../extensions/github-copilot/token.js");
353357
const copilotToken = await resolveCopilotApiToken({
354358
githubToken: apiKeyInfo.apiKey,
355359
});
@@ -1060,3 +1064,4 @@ export async function compactEmbeddedPiSession(
10601064
}),
10611065
);
10621066
}
1067+
export { runPostCompactionSideEffects } from "./compaction-hooks.js";

src/agents/pi-embedded-runner/run/attempt.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ import type {
2121
} from "../../../plugins/types.js";
2222
import { isCronSessionKey, isSubagentSessionKey } from "../../../routing/session-key.js";
2323
import { joinPresentTextSegments } from "../../../shared/text/join-segments.js";
24-
import { resolveSignalReactionLevel } from "../../../signal/reaction-level.js";
25-
import { resolveTelegramInlineButtonsScope } from "../../../telegram/inline-buttons.js";
26-
import { resolveTelegramReactionLevel } from "../../../telegram/reaction-level.js";
24+
import { createConfiguredOllamaStreamFn } from "../../../plugin-sdk/ollama.js";
25+
import { resolveSignalReactionLevel } from "../../../plugin-sdk/signal.js";
26+
import {
27+
resolveTelegramInlineButtonsScope,
28+
resolveTelegramReactionLevel,
29+
} from "../../../plugin-sdk/telegram-runtime.js";
2730
import { buildTtsSystemPromptHint } from "../../../tts/tts.js";
2831
import { resolveUserPath } from "../../../utils.js";
2932
import { normalizeMessageChannel } from "../../../utils/message-channel.js";
@@ -51,7 +54,6 @@ import { resolveImageSanitizationLimits } from "../../image-sanitization.js";
5154
import { resolveModelAuthMode } from "../../model-auth.js";
5255
import { normalizeProviderId, resolveDefaultModelForAgent } from "../../model-selection.js";
5356
import { supportsModelTools } from "../../model-tool-support.js";
54-
import { createConfiguredOllamaStreamFn } from "../../ollama-stream.js";
5557
import { createOpenAIWebSocketStreamFn, releaseWsSession } from "../../openai-ws-stream.js";
5658
import { resolveOwnerDisplaySetting } from "../../owner-display.js";
5759
import {

src/agents/pi-embedded-runner/system-prompt.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export function buildEmbeddedSystemPrompt(params: {
5454
bootstrapTruncationWarningLines?: string[];
5555
memoryCitationsMode?: MemoryCitationsMode;
5656
}): string {
57-
return buildAgentSystemPrompt({
57+
const base = buildAgentSystemPrompt({
5858
workspaceDir: params.workspaceDir,
5959
defaultThinkLevel: params.defaultThinkLevel,
6060
reasoningLevel: params.reasoningLevel,
@@ -81,9 +81,13 @@ export function buildEmbeddedSystemPrompt(params: {
8181
userTime: params.userTime,
8282
userTimeFormat: params.userTimeFormat,
8383
contextFiles: params.contextFiles,
84-
bootstrapTruncationWarningLines: params.bootstrapTruncationWarningLines,
8584
memoryCitationsMode: params.memoryCitationsMode,
8685
});
86+
const lines = params.bootstrapTruncationWarningLines?.filter((l) => l.trim().length > 0) ?? [];
87+
if (lines.length === 0) {
88+
return base;
89+
}
90+
return `${lines.join("\n")}\n\n${base}`;
8791
}
8892

8993
export function createSystemPromptOverride(

src/agents/schema/clean-for-xai.ts

Lines changed: 10 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,13 @@
1-
// xAI rejects these JSON Schema validation keywords in tool definitions instead of
2-
// ignoring them, causing 502 errors for any request that includes them. Strip them
3-
// before sending to xAI directly, or via OpenRouter when the downstream model is xAI.
4-
export const XAI_UNSUPPORTED_SCHEMA_KEYWORDS = new Set([
5-
"minLength",
6-
"maxLength",
7-
"minItems",
8-
"maxItems",
9-
"minContains",
10-
"maxContains",
11-
]);
12-
13-
export function stripXaiUnsupportedKeywords(schema: unknown): unknown {
14-
if (!schema || typeof schema !== "object") {
15-
return schema;
16-
}
17-
if (Array.isArray(schema)) {
18-
return schema.map(stripXaiUnsupportedKeywords);
19-
}
20-
const obj = schema as Record<string, unknown>;
21-
const cleaned: Record<string, unknown> = {};
22-
for (const [key, value] of Object.entries(obj)) {
23-
if (XAI_UNSUPPORTED_SCHEMA_KEYWORDS.has(key)) {
24-
continue;
25-
}
26-
if (key === "properties" && value && typeof value === "object" && !Array.isArray(value)) {
27-
cleaned[key] = Object.fromEntries(
28-
Object.entries(value as Record<string, unknown>).map(([k, v]) => [
29-
k,
30-
stripXaiUnsupportedKeywords(v),
31-
]),
32-
);
33-
} else if (key === "items" && value && typeof value === "object") {
34-
cleaned[key] = Array.isArray(value)
35-
? value.map(stripXaiUnsupportedKeywords)
36-
: stripXaiUnsupportedKeywords(value);
37-
} else if ((key === "anyOf" || key === "oneOf" || key === "allOf") && Array.isArray(value)) {
38-
cleaned[key] = value.map(stripXaiUnsupportedKeywords);
39-
} else {
40-
cleaned[key] = value;
41-
}
42-
}
43-
return cleaned;
44-
}
45-
46-
export function isXaiProvider(modelProvider?: string, modelId?: string): boolean {
47-
const provider = modelProvider?.toLowerCase() ?? "";
48-
if (provider.includes("xai") || provider.includes("x-ai")) {
49-
return true;
50-
}
51-
const lowerModelId = modelId?.toLowerCase() ?? "";
52-
// OpenRouter proxies to xAI when the model id starts with "x-ai/"
53-
if (provider === "openrouter" && lowerModelId.startsWith("x-ai/")) {
54-
return true;
55-
}
56-
// Venice proxies to xAI/Grok models
57-
if (provider === "venice" && lowerModelId.includes("grok")) {
1+
/**
2+
* xAI / Grok OpenAI-compatible stacks sometimes need stream-level tool-call fixes.
3+
* Centralize provider detection so runner code can gate wrappers without importing
4+
* provider-specific modules.
5+
*/
6+
export function isXaiProvider(provider: string, modelId: string): boolean {
7+
const pid = provider.trim().toLowerCase();
8+
if (pid === "xai" || pid === "grok" || pid === "grok-web") {
589
return true;
5910
}
60-
return false;
11+
const mid = modelId.trim().toLowerCase();
12+
return mid.startsWith("grok-") || mid.includes("/grok-");
6113
}

0 commit comments

Comments
 (0)