-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Add ZhipuClient for Z.ai GLM models with thinking control #1677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Z.ai's GLM-4.7 uses a proprietary `thinking` parameter that isn't part of the OpenAI spec. This adds a dedicated example client that uses the OpenAI SDK's extra body API to control it, so users don't need to fork CustomOpenAIClient. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 02030f8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Greptile OverviewGreptile SummaryAdds
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Stagehand
participant ZhipuOpenAIClient
participant OpenAI SDK
participant Z.ai API
User->>Stagehand: new Stagehand({ llmClient: ZhipuOpenAIClient })
User->>Stagehand: act() or extract()
Stagehand->>ZhipuOpenAIClient: createChatCompletion(options)
ZhipuOpenAIClient->>ZhipuOpenAIClient: Format messages & build request body
ZhipuOpenAIClient->>OpenAI SDK: client.chat.completions.create(body, { body: { thinking: { type } } })
OpenAI SDK->>Z.ai API: POST /api/coding/paas/v4/chat/completions<br/>(with thinking parameter in extra_body)
Z.ai API-->>OpenAI SDK: ChatCompletion response
OpenAI SDK-->>ZhipuOpenAIClient: response
ZhipuOpenAIClient->>ZhipuOpenAIClient: Parse & validate response
ZhipuOpenAIClient-->>Stagehand: Formatted response with usage
Stagehand-->>User: Result
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3 files reviewed, no comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 issues found across 3 files
Confidence score: 3/5
- Two concrete issues in
packages/core/examples/external_clients/zhipuOpenAI.tscan break tool calling and message role handling, so there is some user-impacting risk. inputSchemais used instead ofparametersin the tool definition, which can cause function/tool calling to silently fail at runtime.- Non-array message content is always mapped to
role: "user", so system/assistant messages with string content lose their role and can distort conversation behavior. - Pay close attention to
packages/core/examples/external_clients/zhipuOpenAI.ts- tool schema field and message role mapping.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="packages/core/examples/external_clients/zhipuOpenAI.ts">
<violation number="1" location="packages/core/examples/external_clients/zhipuOpenAI.ts:147">
P1: Non-array message content always gets mapped to `role: "user"`, discarding the original role. System and assistant messages with string content will be sent as user messages, breaking the conversation structure. Preserve the original `message.role`.</violation>
<violation number="2" location="packages/core/examples/external_clients/zhipuOpenAI.ts:196">
P1: `inputSchema` is not a valid field in the OpenAI function tool definition — it should be `parameters`. This will cause tool/function calling to silently fail because the API won't receive the parameter schema.</violation>
</file>
Architecture diagram
sequenceDiagram
participant User as Example/User Script
participant SH as Stagehand (Core)
participant ZC as NEW: ZhipuOpenAIClient
participant OAI as OpenAI SDK
participant API as Zhipu AI API (z.ai)
Note over User,API: Initialization with ZH_API_KEY and enableThinking toggle
User->>SH: act() / extract()
SH->>ZC: createChatCompletion(options)
ZC->>ZC: Format messages (User/Assistant/System)
opt If options.response_model
ZC->>ZC: Convert Zod schema to JSON Schema string
ZC->>ZC: Append schema prompt to messages
end
ZC->>OAI: chat.completions.create(body, request_options)
Note right of ZC: NEW: Injects "thinking" param<br/>via extra_body in request_options
OAI->>API: POST /chat/completions (with thinking: {type: "enabled|disabled"})
API-->>OAI: ChatCompletion Response
OAI-->>ZC: ChatCompletion Response
alt If options.response_model (Structured Output)
ZC->>ZC: JSON.parse(content)
alt Validation Success
ZC-->>SH: Return parsed data + usage
else Validation Failure (Retry logic)
Note over ZC: CHANGED: Validates against Zod schema
ZC->>ZC: retry (decrement retries)
ZC-->>User: Throw CreateChatCompletionResponseError (after 3 attempts)
end
else Simple String Output
ZC-->>SH: Return string content + usage
end
SH-->>User: Return action result / extracted data
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
- Preserve original role for string-content system/assistant messages instead of always mapping to "user" - Use `parameters` instead of `inputSchema` in tool definitions to match the OpenAI API spec - Add changeset for version bump Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `extraBody` option to CustomOpenAIClient so subclasses can inject provider-specific request body params via the OpenAI SDK's extra body API - Rewrite ZhipuOpenAIClient as a thin subclass (~15 lines vs ~250 cloned) - Fix pre-existing bugs in CustomOpenAIClient: - `inputSchema` → `parameters` in tool definitions (OpenAI API spec) - Preserve original role for string-content system/assistant messages Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The OpenAI-compatible API is an implementation detail, not part of the user-facing name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
inputSchema was intentional for backwards compatibility with OpenAI-compatible providers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="packages/core/examples/external_clients/customOpenAI.ts">
<violation number="1">
P0: Bug: This change renames `parameters` to `inputSchema`, but the OpenAI **Chat Completions** API expects `parameters` in function tool definitions. `inputSchema` is used by the separate **Responses API** — since this code calls `client.chat.completions.create()`, this will break tool/function calling. The PR description says the fix should be `inputSchema → parameters`, but the diff goes the wrong direction.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| // Note added for revisiting this scaffold for an improved version based on llm/aisdk.ts | ||
| export { AISdkClient } from "../../../../examples/external_clients/aisdk"; | ||
| export { CustomOpenAIClient } from "../../../../examples/external_clients/customOpenAI"; | ||
| export { ZhipuClient } from "../../../../examples/external_clients/zhipuOpenAI"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blocker: We shouldn't be exporting example clients from the public API — it implies a maintenance commitment for what are meant to be copy-and-customize templates. Discussed live with @seanmcguire12 — need to figure out the right pattern before merging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
84d9c90 to
02030f8
Compare
Summary
extraBodyoption toCustomOpenAIClientso subclasses can inject provider-specific request body params via the OpenAI SDK's extra body APIZhipuClientas a thin subclass (~15 lines) for Z.ai (Zhipu AI) GLM models (e.g. GLM-4.7), withenableThinkingtoggleCustomOpenAIClient: preserves original role for string-content system/assistant messages instead of forcing all to "user"ZhipuClientfrom@browserbasehq/stagehandexamples/custom_client_zhipu.tsContext
A community user was trying to disable thinking/reasoning for GLM-4.7 via
CustomOpenAIClientbut had no way to inject the Z.ai-specificthinkingparameter without forking the client. This gives them a drop-in solution:The
extraBodyoption onCustomOpenAIClientalso enables the same pattern for any other OpenAI-compatible provider with non-standard params — no cloning needed.Test plan
pnpm buildpasses —ZhipuClientappears indist/index.d.ts🤖 Generated with Claude Code