feature: add groq model privider#38496
Conversation
Greptile SummaryThis PR integrates Groq as a new LLM provider, following the established patterns used by xAI, Mistral, and other API-key-based providers across onboarding, credential storage, model configuration, and implicit provider resolution. Issues found:
Confidence Score: 1/5
Last reviewed commit: fde3dd1 |
src/commands/auth-choice-options.ts
Outdated
| choices: ["xai-api-key"], | ||
| }, | ||
| { | ||
| alue: "groq", |
There was a problem hiding this comment.
Typo: alue instead of value — TypeScript compile error
The property key is alue but the type annotation for AUTH_CHOICE_GROUP_DEFS requires the property value: AuthChoiceGroupId. TypeScript will reject this with two errors:
- Property 'value' is missing in the Groq group object.
- Object literal may only specify known properties, and 'alue' does not exist in the expected type.
This will prevent the project from building, and at runtime the Groq group would have value: undefined, causing buildAuthChoiceGroups() to produce an invalid group that can never be found by groups.find((group) => group.value === "groq").
| alue: "groq", | |
| value: "groq", |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/commands/auth-choice-options.ts
Line: 75
Comment:
**Typo: `alue` instead of `value` — TypeScript compile error**
The property key is `alue` but the type annotation for `AUTH_CHOICE_GROUP_DEFS` requires the property `value: AuthChoiceGroupId`. TypeScript will reject this with two errors:
1. *Property 'value' is missing* in the Groq group object.
2. *Object literal may only specify known properties, and 'alue' does not exist* in the expected type.
This will prevent the project from building, and at runtime the Groq group would have `value: undefined`, causing `buildAuthChoiceGroups()` to produce an invalid group that can never be found by `groups.find((group) => group.value === "groq")`.
```suggestion
value: "groq",
```
How can I resolve this? If you propose a fix, please make it concise.| const GROQ_BASE_URL = "https://api.groq.com/openai/v1"; | ||
| const GROQ_DEFAULT_MODEL_ID = "llama-3.3-70b-versatile"; | ||
| const GROQ_DEFAULT_CONTEXT_WINDOW = 131072; | ||
| const GROQ_DEFAULT_MAX_TOKENS = 8192; | ||
| const GROQ_DEFAULT_COST = { | ||
| input: 0, | ||
| output: 0, | ||
| cacheRead: 0, | ||
| cacheWrite: 0, | ||
| }; |
There was a problem hiding this comment.
Duplicated Groq constants across two files
These five constants (GROQ_BASE_URL, GROQ_DEFAULT_MODEL_ID, GROQ_DEFAULT_CONTEXT_WINDOW, GROQ_DEFAULT_MAX_TOKENS, GROQ_DEFAULT_COST) are defined identically in both this file and src/commands/onboard-auth.models.ts (where they are exported). If the model ID or base URL ever changes, both locations must be updated in sync — a maintenance risk that doesn't exist for other providers that share constants via a single source.
If the import direction doesn't cause a circular dependency, consider having models-config.providers.ts import the shared constants from onboard-auth.models.ts rather than re-declaring them locally.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/models-config.providers.ts
Line: 169-178
Comment:
**Duplicated Groq constants across two files**
These five constants (`GROQ_BASE_URL`, `GROQ_DEFAULT_MODEL_ID`, `GROQ_DEFAULT_CONTEXT_WINDOW`, `GROQ_DEFAULT_MAX_TOKENS`, `GROQ_DEFAULT_COST`) are defined identically in both this file and `src/commands/onboard-auth.models.ts` (where they are exported). If the model ID or base URL ever changes, both locations must be updated in sync — a maintenance risk that doesn't exist for other providers that share constants via a single source.
If the import direction doesn't cause a circular dependency, consider having `models-config.providers.ts` import the shared constants from `onboard-auth.models.ts` rather than re-declaring them locally.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fde3dd1e90
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
src/commands/auth-choice-options.ts
Outdated
| choices: ["xai-api-key"], | ||
| }, | ||
| { | ||
| alue: "groq", |
There was a problem hiding this comment.
Restore Groq group value key in auth choice defs
The Groq group object uses alue instead of value, so this provider group is missing its identifier. buildAuthChoiceGroups and promptAuthChoiceGrouped rely on group.value to build/select provider options, so interactive onboarding can return an undefined selection for Groq (and strict type-checking will also fail on this object shape). Rename this field to value so Groq is selectable like other groups.
Useful? React with 👍 / 👎.
|
The secrets job appears to be falling back to a full repository scan, |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 489f3a57d1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| optionKey: "groqApiKey", | ||
| authChoice: "groq-api-key", | ||
| cliFlag: "--groq-api-key", | ||
| cliOption: "--groq-api-key <key>", |
There was a problem hiding this comment.
Pass groq API key through onboard command options
Adding --groq-api-key here exposes a CLI flag that never reaches onboarding: register.onboard.ts builds the onboardCommand options object with xaiApiKey and litellmApiKey but omits groqApiKey entirely, so openclaw onboard --non-interactive --groq-api-key ... drops the provided key. In that path, Groq auth selection/inference in applyNonInteractiveAuthChoice cannot see the flag and will fail unless GROQ_API_KEY is separately set in the environment.
Useful? React with 👍 / 👎.
Verified: - pnpm install --frozen-lockfile - pnpm build - pnpm check - pnpm test:macmini
Merged via squash. Prepared head SHA: 6e235e7 Co-authored-by: obviyus <[email protected]> Co-authored-by: obviyus <[email protected]> Reviewed-by: @obviyus
…tic (openclaw#19736) * fix(matrix): remove memberCount heuristic from DM detection The memberCount === 2 check in isDirectMessage() misclassifies 2-person group rooms (admin channels, monitoring rooms) as DMs, routing them to the main session instead of their room-specific session. Matrix already distinguishes DMs from groups at the protocol level via m.direct account data and is_direct member state flags. Both are already checked by client.dms.isDm() and hasDirectFlag(). The memberCount heuristic only adds false positives for 2-person groups. Move resolveMemberCount() below the protocol-level checks so it is only reached for rooms not matched by m.direct or is_direct. This narrows its role to diagnostic logging for confirmed group rooms. Refs: openclaw#19739 * fix(matrix): add conservative fallback for broken DM flags Some homeservers (notably Continuwuity) have broken m.direct account data or never set is_direct on invite events. With the memberCount heuristic removed, these DMs are no longer detected. Add a conservative fallback that requires two signals before classifying as DM: memberCount === 2 AND no explicit m.room.name. Group rooms almost always have explicit names; DMs almost never do. Error handling distinguishes M_NOT_FOUND (missing state event, expected for unnamed rooms) from network/auth errors. Non-404 errors fall through to group classification rather than guessing. This is independently revertable — removing this commit restores pure protocol-based detection without any heuristic fallback. * fix(matrix): add parentPeer for DM room binding support Add parentPeer to DM routes so conversations are bindable by room ID while preserving DM trust semantics (secure 1:1, no group restrictions). Suggested by @KirillShchetinin. * fix(matrix): override DM detection for explicitly configured rooms Builds on @robertcorreiro's config-driven approach from openclaw#9106. Move resolveMatrixRoomConfig() before the DM check. If a room matches a non-wildcard config entry (matchSource === "direct") and was classified as DM, override the classification to group. This gives users a deterministic escape hatch for misclassified rooms. Wildcards are excluded from the override to avoid breaking DM routing when a "*" catch-all exists. roomConfig is gated behind isRoom so DMs never inherit group settings (skills, systemPrompt, autoReply). This commit is independently droppable if the scope is too broad. * test(matrix): add DM detection and config override tests - 15 unit tests for direct.ts: all detection paths, priority order, M_NOT_FOUND vs network error handling, edge cases (whitespace names, API failures) - 8 unit tests for rooms.ts: matchSource classification, wildcard safety for DM override, direct match priority over wildcard * Changelog: note matrix DM routing follow-up * fix(matrix): preserve DM fallback and room bindings --------- Co-authored-by: Tak Hoffman <[email protected]>
Merged via squash. Prepared head SHA: 54b1513 Co-authored-by: obviyus <[email protected]> Co-authored-by: obviyus <[email protected]> Reviewed-by: @obviyus
…#39752) Verified: - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: GazeKingNuWu <[email protected]> Co-authored-by: Tak Hoffman <[email protected]>
restartLaunchAgent was missing the launchctl enable call that installLaunchAgent already performs. launchd can persist a "disabled" state after bootout, causing bootstrap to silently fail and leaving the gateway unloaded until a manual reinstall. Fixes openclaw#39211 Co-Authored-By: Claude Opus 4.6 <[email protected]>
The repair/recovery path had the same missing `enable` guard as `restartLaunchAgent`. If launchd persists a "disabled" state after a previous `bootout`, the `bootstrap` call in `repairLaunchAgentBootstrap` fails silently, leaving the gateway unloaded in the recovery flow. Add the same `enable` guard before `bootstrap` that was already applied to `installLaunchAgent` and (in this PR) `restartLaunchAgent`. Co-Authored-By: Claude Opus 4.6 <[email protected]>
When a config-change restart hits the force-exit timeout, exit with code 1 instead of 0 so launchd/systemd treats it as a failure and triggers a clean process restart. Stop-timeout stays at exit(0) since graceful stops should not cause supervisor recovery. Closes openclaw#36822
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
28 similar comments
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1e6ae2b038
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| optionKey: "groqApiKey", | ||
| authChoice: "groq-api-key", | ||
| cliFlag: "--groq-api-key", | ||
| cliOption: "--groq-api-key <key>", | ||
| description: "Groq API key", |
There was a problem hiding this comment.
Remove duplicate Groq provider flag definition
This second groqApiKey entry makes ONBOARD_PROVIDER_AUTH_FLAGS.filter(...) return two matches when only --groq-api-key is provided, so non-interactive onboarding without explicit --auth-choice is rejected as “Multiple API key flags were provided” in runNonInteractiveOnboardingLocal. In other words, the new Groq inference path fails for the single-flag scenario it is meant to support.
Useful? React with 👍 / 👎.
| // discovers PIDs via the gateway port) can still manage the process. | ||
| // Without this, the process holds the lock but is not listening, | ||
| // forcing manual cleanup. (#35862) | ||
| await releaseLockIfHeld(); |
There was a problem hiding this comment.
Reacquire lock before in-process restart after start failure
After a post-initial startup failure, this branch releases the gateway lock and keeps the process alive; if the next restart uses the in-process path, handleRestartAfterServerClose skips lock reacquisition when hadLock is false, so the next start() can run without any lock held. This can leave a running gateway instance that no longer enforces single-instance locking (notably in fallback/no-respawn restart modes), which can cause duplicate gateway processes and unreliable daemon restart/stop behavior.
Useful? React with 👍 / 👎.
Summary
Describe the problem and fix in 2–5 bullets:
Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
List user-visible changes (including defaults/config).
If none, write
None.New auth choice: groq-api-key.
New CLI flag: --groq-api-key .
Groq now appears in onboarding auth-choice groups.
Non-interactive onboarding now supports Groq explicitly and via flag inference.
Default model is set to groq/llama-3.3-70b-versatile when Groq auth is selected.
Implicit providers now include groq when GROQ_API_KEY or a Groq auth profile exists.
Security Impact (required)
Yes/No)NYes/No)YYes/No)NYes/No)NYes/No)NYes, explain risk + mitigation:Risk: new Groq API key storage path could be misconfigured.
Mitigation: reused existing secret handling (buildApiKeyCredential, ref/plaintext modes, profile storage), no new custom secret path added.
Repro + Verification
Environment
Steps
Run onboarding with --auth-choice groq-api-key --groq-api-key (or interactive selection).
Verify auth.profiles["groq:default"] is created.
Verify default model/provider config includes Groq entries.
Expected
-Groq is configured like other API-key providers, including default model selection.
Actual
-Code paths are fully wired; local test execution was not possible in this environment due to missing Node toolchain binaries.
Evidence
Attach at least one:
Human Verification (required)
What you personally verified (not just CI), and how:
Compatibility / Migration
Yes/No)YYes/No)YYes/No)NFailure Recovery (if this breaks)
Risks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write
None.Issue
Fixes #21442