Skip to content

fix(zai): reject onboarding command auth profiles#97344

Closed
LZY3538 wants to merge 2 commits into
openclaw:mainfrom
LZY3538:codex/zai-auth-profile-command-key
Closed

fix(zai): reject onboarding command auth profiles#97344
LZY3538 wants to merge 2 commits into
openclaw:mainfrom
LZY3538:codex/zai-auth-profile-command-key

Conversation

@LZY3538

@LZY3538 LZY3538 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Related: #97313

What Problem This Solves

Fixes the Z.AI command-string auth-profile pollution path where users could end up with zai:default storing onboarding command text such as openclaw onboard --auth-choice zai-coding-global as the API key, causing provider calls to use that command string as the bearer token instead of a real key.

Why This Change Was Made

The setup guard is owned by the Z.AI provider: interactive and non-interactive Z.AI API-key auth now reject onboarding command text before the value can be persisted.

The doctor path is split by ownership:

  • Core doctor still performs generic static API-key profile surfacing.
  • Static API-key doctor surfacing calls the provider opt-in hook buildStaticAuthProfileDoctorHint.
  • OAuth repair hints continue to use the existing buildAuthDoctorHint hook only.
  • Z.AI owns the provider-specific static predicate and recovery copy through buildStaticAuthProfileDoctorHint.
  • OAuth-only sibling hooks such as Anthropic and OpenAI are no longer touched by static API-key doctor checks.

This addresses the ClawSweeper hook-contract review: the existing OAuth hook contract is unchanged, and static API-key doctor hints use a separate opt-in seam.

The latest update also addresses the remaining merge blockers:

  • Z.AI command detection now handles documented non-interactive command variants such as openclaw onboard --non-interactive --auth-choice zai-coding-global --zai-api-key "$ZAI_API_KEY", plus --auth-choice=zai-coding-global.
  • Provider SDK docs and architecture internals docs now list buildStaticAuthProfileDoctorHint and distinguish it from OAuth-only buildAuthDoctorHint.

This PR does not change sub-agent fallback behavior or broader key-rotation semantics; those remain with the linked issue scope.

User Impact

Users get an immediate setup error if they paste an OpenClaw onboarding command where a Z.AI API key is expected. Existing polluted zai:default profiles can be surfaced by doctor as static [invalid_api_key] with a provider-owned re-authentication hint, instead of repeatedly failing as an opaque Z.AI 401.

Evidence

Red/green proof from the initial fix:

.\node_modules\.bin\vitest.CMD run extensions/zai/index.test.ts src/agents/auth-profiles.doctor.test.ts --reporter=verbose

Before the fix, the new regression tests failed because Z.AI returned a profile with key: "openclaw onboard --auth-choice zai-coding-global" and doctor returned an empty hint. After the fix: 2 files passed, 19 tests passed.

Focused proof before later Windows runner hangs:

.\node_modules\.bin\vitest.CMD run src/commands/doctor-auth.profile-health.test.ts --reporter=verbose
.\node_modules\.bin\vitest.CMD run extensions/zai/index.test.ts src/agents/auth-profiles.doctor.test.ts src/commands/doctor-auth.profile-health.test.ts --reporter=verbose

Results from earlier successful runs: doctor-auth profile health passed 1 file / 6 tests, then the combined focused proof passed 3 files / 25 tests.

Fresh checks after replacing the widened hook design with a static-specific opt-in hook:

rg -n "issueKind|ProviderStaticAuthProfileDoctorHintContext" src extensions -g "*.ts"
npx oxfmt --check extensions/anthropic/index.test.ts extensions/anthropic/register.runtime.ts extensions/openai/openai-chatgpt-provider.ts extensions/openai/openai-provider.test.ts extensions/zai/index.ts extensions/zai/index.test.ts src/agents/auth-profiles/doctor.ts src/plugins/types.ts src/plugins/provider-runtime.ts src/plugins/provider-runtime.runtime.ts src/plugins/provider-runtime.test.ts src/commands/doctor-auth.profile-health.test.ts
npx oxlint extensions/anthropic/index.test.ts extensions/anthropic/register.runtime.ts extensions/openai/openai-chatgpt-provider.ts extensions/openai/openai-provider.test.ts extensions/zai/index.ts extensions/zai/index.test.ts src/agents/auth-profiles/doctor.ts src/plugins/types.ts src/plugins/provider-runtime.ts src/plugins/provider-runtime.runtime.ts src/plugins/provider-runtime.test.ts src/commands/doctor-auth.profile-health.test.ts
node scripts/plugin-sdk-surface-report.mjs --check
node --import tsx -e "await import('./src/agents/auth-profiles/doctor.ts'); await import('./src/commands/doctor-auth.ts'); await import('./extensions/zai/index.ts'); await import('./src/plugins/provider-runtime.ts'); console.log('imports passed');"
node --import tsx -e "import plugin from './extensions/zai/index.ts'; import { registerSingleProviderPlugin } from 'openclaw/plugin-sdk/plugin-test-runtime'; const provider = await registerSingleProviderPlugin(plugin); const store = { version: 1, profiles: { 'zai:default': { type: 'api_key', provider: 'zai', key: 'openclaw onboard --auth-choice zai-coding-global' } } }; const hint = provider.buildStaticAuthProfileDoctorHint?.({ provider: 'zai', profileId: 'zai:default', store }); if (hint !== 'Z.AI auth profile zai:default contains an onboarding command instead of an API key. Re-authenticate with a real key: openclaw onboard --auth-choice zai-coding-global.') throw new Error(String(hint)); if (provider.buildAuthDoctorHint?.({ provider: 'zai', profileId: 'zai:default', store }) !== undefined) throw new Error('unexpected oauth hook hint'); console.log('zai static opt-in hook assertion passed');"
git diff --check

All exited 0. The rg command exited 1 with no matches, confirming the temporary issueKind design and temporary static context type are gone. plugin-sdk-surface-report.mjs --check passed with unchanged public package SDK export count and package-exported forbidden subpaths: 0.

Fresh checks after the documented command-variant and docs follow-up:

npx oxfmt --check extensions/zai/index.ts extensions/zai/index.test.ts docs/plugins/sdk-provider-plugins.md docs/plugins/architecture-internals.md
npx oxlint extensions/zai/index.ts extensions/zai/index.test.ts
pnpm docs:list
pnpm docs:check-mdx
node scripts/plugin-sdk-surface-report.mjs --check
node --import tsx -e "import plugin from './extensions/zai/index.ts'; import { registerSingleProviderPlugin } from 'openclaw/plugin-sdk/plugin-test-runtime'; const provider = await registerSingleProviderPlugin(plugin); const method = provider.auth.find((entry) => entry.wizard?.choiceId === 'zai-coding-global'); if (!method) throw new Error('missing zai auth method'); const commands = ['openclaw onboard --auth-choice zai-coding-global', 'openclaw onboard --non-interactive --auth-choice zai-coding-global --zai-api-key $ZAI_API_KEY', 'openclaw onboard --non-interactive --auth-choice=zai-coding-global --zai-api-key $ZAI_API_KEY']; for (const command of commands) { await method.run({ config: {}, prompter: { confirm: async () => false, select: async (_params, fallback) => fallback, text: async () => command, note: async () => undefined }, runtime: { log: () => {}, error: () => {}, exit: () => {} }, isRemote: false, openUrl: async () => undefined, oauth: { createVpsAwareHandlers: () => ({}) } }).then(() => { throw new Error('accepted command: ' + command); }, (err) => { if (!String(err?.message ?? err).includes('Z.AI API key cannot be an OpenClaw onboarding command.')) throw err; }); } const store = { version: 1, profiles: { 'zai:default': { type: 'api_key', provider: 'zai', key: commands[1] } } }; const hint = provider.buildStaticAuthProfileDoctorHint?.({ provider: 'zai', profileId: 'zai:default', store }); if (hint !== 'Z.AI auth profile zai:default contains an onboarding command instead of an API key. Re-authenticate with a real key: openclaw onboard --auth-choice zai-coding-global.') throw new Error(String(hint)); console.log('zai documented command variant assertions passed');"
git diff --check

All exited 0. pnpm docs:check-mdx passed for 684 files.

Current Windows proof gap:

node scripts/run-vitest.mjs extensions/zai/index.test.ts --reporter=verbose
node scripts/run-vitest.mjs extensions/zai/index.test.ts src/agents/auth-profiles.doctor.test.ts src/commands/doctor-auth.profile-health.test.ts --reporter=verbose

These did not complete on this Windows worktree; the focused Z.AI test wrapper was stopped after 150 seconds with no output. Raw Vitest reruns also previously hung during Rolldown/Vitest initialization with repeated [PLUGIN_TIMINGS] warnings and no test failure summary. The focused suites above passed before this runner issue, and the fresh direct provider assertions plus lint/format/import/docs/surface checks cover the latest code movement.

Validation note: I do not have a live Z.AI / GLM-5.2 credential, so this PR proves the local auth-profile root cause with seeded/plugin/doctor-path evidence rather than a live network call.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling extensions: zai size: S labels Jun 28, 2026
@clawsweeper

clawsweeper Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 28, 2026, 8:40 AM ET / 12:40 UTC.

Summary
The PR adds Z.AI onboarding-command rejection for API-key setup plus a provider-owned static auth-profile doctor hook, tests, and provider SDK docs.

PR surface: Source +112, Tests +169, Docs +3. Total +284 across 11 files.

Reproducibility: yes. at source level: current main accepts non-empty Z.AI API-key input and can persist onboarding command text through the setup path. I did not run a live Z.AI credential repro in this read-only review.

Review metrics: 1 noteworthy metric.

  • Provider API surface: 1 optional hook added, 0 removed. The diff expands the provider plugin contract, so maintainers should notice and accept the compatibility surface before merge.

Stored data model
Persistent data-model change detected: migration/backfill/repair: src/agents/auth-profiles/doctor.ts, migration/backfill/repair: src/commands/doctor-auth.profile-health.test.ts, migration/backfill/repair: src/commands/doctor-auth.ts, migration/backfill/repair: src/plugins/provider-runtime.test.ts, unknown-data-model-change: src/commands/doctor-auth.profile-health.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #97313
Summary: This PR is a candidate fix for the command-string auth-profile pollution root cause documented in the linked issue, while the broader stale profile, key-rotation, doctor --fix, and fallback scope remains with the issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Get maintainer acceptance for the optional static provider doctor hook before merge.
  • Rerun the focused doctor/Z.AI tests on a healthy lane if maintainers want stronger latest-head test proof.

Risk before merge

  • [P1] The new optional buildStaticAuthProfileDoctorHint hook expands the provider plugin contract and core doctor invocation path, so maintainers need to accept that API direction before merge.
  • [P1] The contributor’s latest focused Vitest rerun still hung on their Windows worktree, so the latest-head proof relies on terminal assertions, lint/docs checks, and earlier focused test passes rather than a completed latest-head focused Vitest run.

Maintainer options:

  1. Confirm the static doctor hook contract (recommended)
    A maintainer can accept the optional provider hook as the intended plugin API seam and merge this narrow bug fix with the broader linked issue still open.
  2. Replace the hook direction
    If maintainers do not want a new provider API, ask for a rewrite that keeps Z.AI input rejection and uses an already-approved doctor seam for surfacing polluted profiles.
  3. Pause for broader auth-profile scoping
    If static doctor hints are too narrow for the linked auth-profile problem, pause this PR until the remaining key-rotation and doctor-repair behavior is scoped.

Next step before merge

  • [P2] Manual review is appropriate because the remaining blocker is maintainer API acceptance for a new optional provider hook, not a mechanical code repair.

Security
Cleared: The diff changes auth validation, provider hook plumbing, doctor output, docs, and tests without adding dependencies, workflows, permissions, secret exposure, or new code-execution paths.

Review details

Best possible solution:

Land the provider-owned Z.AI guard and static doctor hook after maintainer API acceptance, while leaving the linked broader auth-profile issue open for key-rotation and fallback behavior.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: current main accepts non-empty Z.AI API-key input and can persist onboarding command text through the setup path. I did not run a live Z.AI credential repro in this read-only review.

Is this the best way to solve the issue?

Mostly yes: putting command detection in the Z.AI provider and keeping core doctor generic is the right ownership shape. The remaining question is whether maintainers want the new optional static doctor hook as the permanent plugin API.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 08d15ec32db3.

Label changes

Label justifications:

  • P1: The PR targets a user-facing Z.AI auth-provider failure where a polluted saved credential can make provider calls fail with 401s.
  • merge-risk: 🚨 compatibility: The diff adds a new optional provider hook and calls it from core doctor, expanding the plugin API and upgrade surface.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body and follow-up comments include terminal after-fix proof for seeded Z.AI command rejection, static doctor hints, docs checks, lint, imports, and SDK surface checks, with the live Z.AI credential gap clearly scoped.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and follow-up comments include terminal after-fix proof for seeded Z.AI command rejection, static doctor hints, docs checks, lint, imports, and SDK surface checks, with the live Z.AI credential gap clearly scoped.
Evidence reviewed

PR surface:

Source +112, Tests +169, Docs +3. Total +284 across 11 files.

View PR surface stats
Area Files Added Removed Net
Source 6 115 3 +112
Tests 3 170 1 +169
Docs 2 67 64 +3
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 11 352 68 +284

What I checked:

  • Current main accepts non-empty API-key input: The shared API-key validator on current main accepts any non-empty normalized string, so onboarding command text can pass generic setup validation. (src/plugins/provider-auth-input.ts:57, 08d15ec32db3)
  • Current Z.AI setup captures and stores generic API-key input: Current main's Z.AI interactive setup obtains the API key through the generic prompt/option helper and later builds the saved zai:default credential from the captured input. (extensions/zai/index.ts:218, 08d15ec32db3)
  • PR head rejects command-looking Z.AI input before persistence: PR head adds command detection and rejects matching Z.AI onboarding command strings before the interactive setup returns a profile or the non-interactive path upserts one. (extensions/zai/index.ts:126, c3a15b443c36)
  • PR head surfaces static API-key doctor hints generically: The new doctor helper iterates static API-key profiles and emits an invalid static profile line only when the owning provider hook returns repair text. (src/agents/auth-profiles/doctor.ts:27, c3a15b443c36)
  • Provider API surface expands: PR head adds optional buildStaticAuthProfileDoctorHint to ProviderPlugin, making the change compatibility-sensitive even though existing plugins are not forced to implement it. (src/plugins/types.ts:1780, c3a15b443c36)
  • Docs list the new hook separately from OAuth hints: The provider SDK docs distinguish OAuth buildAuthDoctorHint from static API-key buildStaticAuthProfileDoctorHint in the provider hook table. Public docs: docs/plugins/sdk-provider-plugins.md. (docs/plugins/sdk-provider-plugins.md:640, c3a15b443c36)

Likely related people:

  • giodl73-repo: Current blame for the Z.AI setup function, auth-profile doctor helper, and provider type surface points to the recent doctor state-integrity work merged in cb4244f. (role: recent area contributor; confidence: high; commits: cb4244fe15e3; files: extensions/zai/index.ts, src/agents/auth-profiles/doctor.ts, src/plugins/types.ts)
  • vincentkoc: Merged auth-profile write-locking work in fix(auth): serialize auth login writes #82569 touched Z.AI setup and shared provider auth write paths. (role: auth-profile setup contributor; confidence: high; commits: 17b96587a8d2, 913f6017dde0, f6c20fced6e2; files: extensions/zai/index.ts, src/agents/auth-profiles/profiles.ts, src/plugins/provider-auth-choice.ts)
  • steipete: Merged hosted-provider work in feat: add hosted model providers #88247 changed provider docs, provider surfaces, and auth doctor behavior adjacent to this new hook contract. (role: adjacent provider hook contributor; confidence: medium; commits: 8192d5203729, 355d6c806c79, c9714b9fcaf9; files: src/agents/auth-profiles/doctor.ts, docs/plugins/reference.md, extensions/qwen/index.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. labels Jun 28, 2026
@LZY3538
LZY3538 force-pushed the codex/zai-auth-profile-command-key branch from 558e5bb to ad55223 Compare June 28, 2026 02:34
@openclaw-barnacle openclaw-barnacle Bot added the commands Command implementations label Jun 28, 2026
@LZY3538

LZY3538 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the ClawSweeper finding about the Z.AI doctor hint being routed only through the OAuth/token formatter.

What changed:

  • noteAuthProfileHealthForTarget now emits static Z.AI API-key command-text profiles through the actual auth health note path as static [invalid_api_key].
  • Added a doctor-auth.profile-health regression for the static API-key path.
  • Updated the PR body with fresh doctor-output proof from the exported auth doctor path using the real terminal note renderer.

Known proof gap: the full source node scripts/run-node.mjs doctor --non-interactive command hung on this Windows worktree during source-runner build activity and was stopped; no live Z.AI key is available.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 28, 2026
@LZY3538
LZY3538 marked this pull request as ready for review June 28, 2026 03:48
@LZY3538
LZY3538 requested a review from a team as a code owner June 28, 2026 03:48
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 28, 2026
@LZY3538
LZY3538 force-pushed the codex/zai-auth-profile-command-key branch from ad55223 to 7705005 Compare June 28, 2026 09:01
@LZY3538

LZY3538 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the latest ClawSweeper owner-boundary finding.

What changed in 7705005d2b:

  • Removed the Z.AI command regex and Z.AI recovery copy from core auth-profile doctor code.
  • Kept core doctor generic: it now surfaces static API-key provider hook hints as static [invalid_api_key].
  • Moved the Z.AI polluted-profile predicate and recovery message into the Z.AI provider buildAuthDoctorHint hook.
  • Updated tests so core verifies provider-hook surfacing and the Z.AI provider verifies its own doctor hint.

Fresh checks are in the PR body. The Windows Vitest runner still hung locally, so I included that as a proof gap rather than presenting it as passing.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jun 28, 2026
@LZY3538

LZY3538 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Addressed the latest hook-contract review by replacing the widened buildAuthDoctorHint / issueKind design with a separate static-profile opt-in hook:

  • buildAuthDoctorHint is back to the existing OAuth repair-hint contract with no issueKind parameter.
  • Static API-key doctor surfacing now calls buildStaticAuthProfileDoctorHint only.
  • Z.AI implements the new static hook for the onboarding-command polluted profile case.
  • Removed the temporary Anthropic/OpenAI production guards and tests because static doctor checks no longer call their OAuth-only hooks.
  • Added runtime forwarding and provider-runtime coverage for the new hook.

Fresh proof after the update:

rg -n "issueKind|ProviderStaticAuthProfileDoctorHintContext" src extensions -g "*.ts"
npx oxfmt --check extensions/anthropic/index.test.ts extensions/anthropic/register.runtime.ts extensions/openai/openai-chatgpt-provider.ts extensions/openai/openai-provider.test.ts extensions/zai/index.ts extensions/zai/index.test.ts src/agents/auth-profiles/doctor.ts src/plugins/types.ts src/plugins/provider-runtime.ts src/plugins/provider-runtime.runtime.ts src/plugins/provider-runtime.test.ts src/commands/doctor-auth.profile-health.test.ts
npx oxlint extensions/anthropic/index.test.ts extensions/anthropic/register.runtime.ts extensions/openai/openai-chatgpt-provider.ts extensions/openai/openai-provider.test.ts extensions/zai/index.ts extensions/zai/index.test.ts src/agents/auth-profiles/doctor.ts src/plugins/types.ts src/plugins/provider-runtime.ts src/plugins/provider-runtime.runtime.ts src/plugins/provider-runtime.test.ts src/commands/doctor-auth.profile-health.test.ts
node scripts/plugin-sdk-surface-report.mjs --check
node --import tsx -e "await import('./src/agents/auth-profiles/doctor.ts'); await import('./src/commands/doctor-auth.ts'); await import('./extensions/zai/index.ts'); await import('./src/plugins/provider-runtime.ts'); console.log('imports passed');"
node --import tsx -e "import plugin from './extensions/zai/index.ts'; import { registerSingleProviderPlugin } from 'openclaw/plugin-sdk/plugin-test-runtime'; const provider = await registerSingleProviderPlugin(plugin); const store = { version: 1, profiles: { 'zai:default': { type: 'api_key', provider: 'zai', key: 'openclaw onboard --auth-choice zai-coding-global' } } }; const hint = provider.buildStaticAuthProfileDoctorHint?.({ provider: 'zai', profileId: 'zai:default', store }); if (hint !== 'Z.AI auth profile zai:default contains an onboarding command instead of an API key. Re-authenticate with a real key: openclaw onboard --auth-choice zai-coding-global.') throw new Error(String(hint)); if (provider.buildAuthDoctorHint?.({ provider: 'zai', profileId: 'zai:default', store }) !== undefined) throw new Error('unexpected oauth hook hint'); console.log('zai static opt-in hook assertion passed');"
git diff --check

All exited 0; rg found no matches. plugin-sdk-surface-report.mjs --check passed with unchanged public package SDK export count and package-exported forbidden subpaths: 0.

@clawsweeper

clawsweeper Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 28, 2026
@LZY3538
LZY3538 force-pushed the codex/zai-auth-profile-command-key branch from d93ffc7 to 3171578 Compare June 28, 2026 11:15
@openclaw-barnacle openclaw-barnacle Bot added the docs Improvements or additions to documentation label Jun 28, 2026
@LZY3538

LZY3538 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Addressed the two remaining merge blockers from the latest review:

  • Broadened Z.AI onboarding-command detection so documented non-interactive variants are rejected, including openclaw onboard --non-interactive --auth-choice zai-coding-global ... and --auth-choice=zai-coding-global.
  • Added regression coverage for those command variants through the Z.AI setup path and the static auth-profile doctor hook.
  • Documented buildStaticAuthProfileDoctorHint in both provider hook tables: docs/plugins/sdk-provider-plugins.md and docs/plugins/architecture-internals.md.
  • Kept buildAuthDoctorHint documented as OAuth refresh repair guidance, with static API-key repair guidance isolated to the new opt-in hook.

Fresh proof after this update:

npx oxfmt --check extensions/zai/index.ts extensions/zai/index.test.ts docs/plugins/sdk-provider-plugins.md docs/plugins/architecture-internals.md
npx oxlint extensions/zai/index.ts extensions/zai/index.test.ts
pnpm docs:list
pnpm docs:check-mdx
node scripts/plugin-sdk-surface-report.mjs --check
node --import tsx -e "import plugin from './extensions/zai/index.ts'; import { registerSingleProviderPlugin } from 'openclaw/plugin-sdk/plugin-test-runtime'; const provider = await registerSingleProviderPlugin(plugin); const method = provider.auth.find((entry) => entry.wizard?.choiceId === 'zai-coding-global'); if (!method) throw new Error('missing zai auth method'); const commands = ['openclaw onboard --auth-choice zai-coding-global', 'openclaw onboard --non-interactive --auth-choice zai-coding-global --zai-api-key $ZAI_API_KEY', 'openclaw onboard --non-interactive --auth-choice=zai-coding-global --zai-api-key $ZAI_API_KEY']; for (const command of commands) { await method.run({ config: {}, prompter: { confirm: async () => false, select: async (_params, fallback) => fallback, text: async () => command, note: async () => undefined }, runtime: { log: () => {}, error: () => {}, exit: () => {} }, isRemote: false, openUrl: async () => undefined, oauth: { createVpsAwareHandlers: () => ({}) } }).then(() => { throw new Error('accepted command: ' + command); }, (err) => { if (!String(err?.message ?? err).includes('Z.AI API key cannot be an OpenClaw onboarding command.')) throw err; }); } const store = { version: 1, profiles: { 'zai:default': { type: 'api_key', provider: 'zai', key: commands[1] } } }; const hint = provider.buildStaticAuthProfileDoctorHint?.({ provider: 'zai', profileId: 'zai:default', store }); if (hint !== 'Z.AI auth profile zai:default contains an onboarding command instead of an API key. Re-authenticate with a real key: openclaw onboard --auth-choice zai-coding-global.') throw new Error(String(hint)); console.log('zai documented command variant assertions passed');"
git diff --check

All exited 0. pnpm docs:check-mdx passed for 684 files. node scripts/run-vitest.mjs extensions/zai/index.test.ts --reporter=verbose still hung on this Windows worktree and was stopped after 150 seconds with no output, consistent with the previous local Vitest runner gap documented in the PR body.

@clawsweeper

clawsweeper Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 28, 2026
@LZY3538

LZY3538 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Addressed the latest finding:

  • Added the existing buildProviderAuthDoctorHintWithPlugin export back to the doctor-auth.profile-health.test.ts provider-runtime mock.
  • Reset it in beforeEach alongside the new static hook mock so existing OAuth doctor paths keep their generic fallback behavior during this focused test file.

Fresh proof after this narrow test-mock repair:

npx oxfmt --check src/commands/doctor-auth.profile-health.test.ts
npx oxlint src/commands/doctor-auth.profile-health.test.ts
git diff --check

All exited 0.

I also retried the requested focused test:

node scripts/run-vitest.mjs src/commands/doctor-auth.profile-health.test.ts --reporter=verbose

It still hung on this Windows worktree with no output and was stopped after roughly 120 seconds, matching the previously documented local Vitest runner gap.

@clawsweeper

clawsweeper Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 28, 2026
@vincentkoc

Copy link
Copy Markdown
Member

Closing this as superseded by the canonical shared-auth fix in #97520, which landed as fb7e10e. That path puts malformed onboarding-command API key rejection in the shared credential eligibility boundary and keeps the ZAI-specific work from diverging. Thanks for the fix work here.

@vincentkoc vincentkoc closed this Jun 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling commands Command implementations docs Improvements or additions to documentation extensions: zai merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants