Skip to content

Conversation

@vglafirov
Copy link
Contributor

@vglafirov vglafirov commented Jan 8, 2026

Add GitLab Duo Provider Support

Problem

In-line with GitLab's open-core strategy, we want to officially integrate GitLab Duo with OpenCode as a supported provider, operable with both GitLab.com and self-hosted GitLab instances. To streamline our users' journey across tools and enable access to GitLab's AI capabilities including agentic chat with native tool calling, GitLab is upstreaming the required provider packages to this repository.

Solution

This PR adds GitLab as a supported provider with three agentic chat model variants (Haiku, Sonnet, Opus), enabling seamless integration with GitLab.com and self-hosted instances.

Changes

Dependencies Added

Provider Implementation

  • Added GitLab to bundled providers in provider.ts
  • Implemented custom loader with multi-source auth (env, config, OAuth, PAT)
  • Registered three Claude-based models: haiku-4-5, sonnet-4-5, opus-4-5
  • OAuth token refresh support
  • Self-hosted GitLab instance support via GITLAB_INSTANCE_URL

Plugin Auto-Loading

  • GitLab auth/tools plugins load automatically when GitLab is configured
  • Checks environment variables, config, and auth.json
  • Respects OPENCODE_DISABLE_DEFAULT_PLUGINS flag

Tests

  • Added 8 provider-specific tests covering auth methods, config options, and model availability
  • All 619 existing tests pass

Files Changed

  • packages/opencode/package.json - Added 3 GitLab dependencies
  • packages/opencode/src/provider/provider.ts - GitLab provider implementation
  • packages/opencode/src/plugin/index.ts - Auto-loading logic
  • packages/opencode/test/provider/gitlab-duo.test.ts - New tests (8 tests)
  • packages/docs/essentials/gitlab-duo.mdx - Documentation

Usage

Basic setup with environment variable:

export GITLAB_TOKEN="glpat-xxxxxxxxxxxx"

Then use in config:

{
  "model": "gitlab/duo-chat-sonnet-4-5"
}

Self-hosted GitLab:

export GITLAB_INSTANCE_URL="https://gitlab.company.internal"
export GITLAB_TOKEN="glpat-xxxxxxxxxxxx"

Testing

  • All 619 existing tests pass
  • Added 8 provider-specific tests
  • Tested with GitLab.com and environment variable auth

Closes #7455

@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2026

The following comment was made by an LLM, it may be inaccurate:

No duplicate PRs found

@vglafirov
Copy link
Contributor Author

Related PR to models.dev registry: anomalyco/models.dev#616

@rekram1-node
Copy link
Collaborator

/review

@vglafirov
Copy link
Contributor Author

/review

@vglafirov
Copy link
Contributor Author

Closes #7455

@vglafirov
Copy link
Contributor Author

I am not sure why PR Standards check is failing. I've created an issue and linked it to this PR.

@rekram1-node
Copy link
Collaborator

@vglafirov apologies for delay I had this open on my computer but forgot to look at it

@vglafirov
Copy link
Contributor Author

@rekram1-node You recently merged Gitlab Duo PR on models.dev, but deployment pipeline is failing. If we get models deployed on models.dev, I can remove models from https://github.com/anomalyco/opencode/pull/7333/changes#diff-b0155a9e5561043f50ba86bc54d5fd59aa528c7af7c92b2f37585d80e792cd9aR740

PR to fix deployment issues: anomalyco/models.dev#631

@kamilchm
Copy link

kamilchm commented Jan 13, 2026

@vglafirov this is awesome — thanks for building it!
I have a self-hosted GitLab in my organization and would love to test the integration.
Is there any doc I should follow, or a quick minimal setup guide (env vars + callback URL/redirect URI + required scopes) to get it working?

@vglafirov
Copy link
Contributor Author

vglafirov commented Jan 13, 2026

@vglafirov this is awesome — thanks for building it! I have a self-hosted GitLab in my organization and would love to test the integration. Is there any doc I should follow, or a quick minimal setup guide (env vars + callback URL/redirect URI + required scopes) to get it working?

@kamilchm This PR contains documentation update: https://github.com/anomalyco/opencode/pull/7333/changes#diff-b5d5affc6941bf7bb19805cc8f556cd1b9ae73ffd99e520120700536b166f8c0

Also check published npm packages in comment above. They providing extensive documentation how to use this integration. Feel free to provide a feedback here or on repositories behind these npm packages. We haven't tested this on self-hosted instances yet, I am highly interesting to see if it works as expected. Thanks

@kamilchm
Copy link

Great, one more question: do I need snything special on the GitLab Server side? Version, features?

@vglafirov
Copy link
Contributor Author

Great, one more question: do I need snything special on the GitLab Server side? Version, features?

If you have self-hosted Duo, then I guess nothing special is needed, if not: https://docs.gitlab.com/administration/gitlab_duo_self_hosted/

@vglafirov
Copy link
Contributor Author

Can you link me to these packages you are adding? for some reason they aren't popping up when I try to search for them but that is likely me being an idiot

@rekram1-node I've fixed npmjs search problems. It was due to poor metadata. Packages are searcheble now :)

@rekram1-node
Copy link
Collaborator

Nice! let me review these packages and then I think this is basically good to go

Follow Copilot plugin pattern by removing @gitlab/opencode-gitlab-auth
and @gitlab/opencode-gitlab-plugin from package.json dependencies.

Plugins are now dynamically installed via BunProc.install() when GitLab
is configured, matching the established pattern for opencode-copilot-auth
and opencode-anthropic-auth.

Changes:
- Removed plugin packages from package.json dependencies
- Pinned plugin versions (1.3.0 and 1.1.0) in auto-loading logic
- Updated bun.lock to reflect dynamic installation approach
- Kept @gitlab/gitlab-ai-provider as it's statically imported

Addresses feedback from @rekram1-node on PR #7333
- Move @gitlab/[email protected] to BUILTIN array
- Make @gitlab/[email protected] opt-in (not auto-loaded)
- Remove custom GitLab plugin detection logic (~33 lines)
- Simplify auth to use Auth.get() instead of manual parsing (~45 lines)
- Add documentation for optional GitLab tools plugin
- Update test mocks to handle versioned builtin plugins

Net reduction: 63 lines (-99/+36)
All 660 tests passing
@vglafirov
Copy link
Contributor Author

@rekram1-node Refactored plugins loading. Please take a look again 🙏

@rekram1-node
Copy link
Collaborator

lookin

@rekram1-node rekram1-node merged commit 05867f9 into anomalyco:dev Jan 13, 2026
5 checks passed
dl-alexandre pushed a commit to dl-alexandre/opencode that referenced this pull request Jan 13, 2026
fwang pushed a commit that referenced this pull request Jan 14, 2026
shuv1337 added a commit to Latitudes-Dev/shuvcode that referenced this pull request Jan 14, 2026
Upstream changes:
- feat: add plan mode with enter/exit tools (anomalyco#8281)
- feat: Add GitLab Duo Agentic Chat Provider Support (anomalyco#7333)
- feat(desktop): Ask Question Tool Support (anomalyco#8232)
- feat: add Undertale and Deltarune built-in themes (anomalyco#8240)
- fix: Add Plugin Mocks to Provider Tests (anomalyco#8276)
- fix: update User-Agent string to latest Chrome version in webfetch (anomalyco#8284)
- fix(prompt-input): handle Shift+Enter before IME check
- fix(state): delete key from recordsByKey on instance disposal
- fix(mcp): close existing client before reassignment to prevent leaks

Resolved conflicts:
- bun.lock: regenerated with fork dependencies
- global-sync.tsx: adopted upstream variable naming (question instead of request)
- session/index.tsx: merged upstream workdir display with fork's ANSI terminal emulation
- amazon-bedrock.test.ts: added all mock modules (fork + upstream)
- vscode/package.json: kept fork branding, updated version

Fork commits included:
- refactor(tui): use SDK client for tool list dialog
- chore: update lockfile with fork dependencies
shuv1337 added a commit to Latitudes-Dev/shuvcode that referenced this pull request Jan 15, 2026
* sync

* sync

* Update Nix flake.lock and x86_64-linux hash

* Update aarch64-darwin hash

* fix(TUI): make tui work when OPENCODE_SERVER_PASSWORD is set (anomalyco#8179)

* chore: generate

* wip: black

* docs: Update plan mode restrictions (anomalyco#8290)

* docs: add 302ai provider (anomalyco#8142)

* fix: add missing metadata() and ask() defintions to ToolContext type (anomalyco#8269)

* fix(tui): track all timeouts in Footer to prevent memory leak (anomalyco#8255)

* fix: deduplicate file refs in sent prompts (anomalyco#8303)

* chore: generate

* wip: black

* wip: black

* release: v1.1.17

* add fullscreen view to permission prompt

* chore: generate

* fix(desktop): correct health check endpoint URL to /global/health (anomalyco#8231)

* feat(desktop): Adding Provider Icons (anomalyco#8215)

* chore: generate

* console: reduce desktop download cache ttl to 5 minutes

* fix(github): add persist-credentials: false to workflow templates (anomalyco#8202)

* release: v1.1.18

* fix(desktop): Revert provider icon on select model dialog (anomalyco#8245)

* feat: add Undertale and Deltarune built-in themes (anomalyco#8240)

* chore: generate

* feat(desktop): Ask Question Tool Support (anomalyco#8232)

* fix(mcp): close existing client before reassignment to prevent leaks (anomalyco#8253)

* fix(state): delete key from recordsByKey on instance disposal (anomalyco#8252)

* docs: document ~/.claude/CLAUDE.md compatibility behavior (anomalyco#8268)

* feat: Add GitLab Duo Agentic Chat Provider Support (anomalyco#7333)

Co-authored-by: Aiden Cline <[email protected]>
Co-authored-by: Aiden Cline <[email protected]>

* fix(cli): mcp auth duplicate radio button icon (anomalyco#8273)

* Update Nix flake.lock and x86_64-linux hash

* Update aarch64-darwin hash

* tweak: ensure external dir and bash tool invocations render workdir details

* tweak: external dir permission rendering in tui

* add family to gpt 5.2 codex in codex plugin

* fix(prompt-input): handle Shift+Enter before IME check to prevent stuck state (anomalyco#8275)

* feat: add plan mode with enter/exit tools (anomalyco#8281)

* chore: generate

* test: fix plan agent test path from .opencode/plan/* to .opencode/plans/*

* remove plan

* fix: update User-Agent string to latest Chrome version in webfetch (anomalyco#8284)

* fix: Add Plugin Mocks to Provider Tests (anomalyco#8276)

* chore: generate

* tweak: prompt for explore agent better

* do not allow agent to ask custom-less questions

* release: v1.1.19

* fix(TUI): make tui work when OPENCODE_SERVER_PASSWORD is set (anomalyco#8179)

* chore: generate

* docs: Update plan mode restrictions (anomalyco#8290)

* docs: add 302ai provider (anomalyco#8142)

* fix: add missing metadata() and ask() defintions to ToolContext type (anomalyco#8269)

* fix(tui): track all timeouts in Footer to prevent memory leak (anomalyco#8255)

* fix: deduplicate file refs in sent prompts (anomalyco#8303)

* chore: generate

* chore: generate

* Update Nix flake.lock and x86_64-linux hash

* Update aarch64-darwin hash

* fix(session): skip duplicate system prompt for Codex OAuth sessions (anomalyco#8357)

Co-authored-by: Claude <[email protected]>

* feat: show connected providers in /connect dialog (anomalyco#8351)

* fix(opencode): fix docker image after sst rename in tips (anomalyco#8376)

* chore: generate

* ignore: update download stats 2026-01-14

* docs(prd): mark codex token refresh PR task as complete

- PR created at #298
- Fix includes: write token refresh to openai provider ID, fallback to legacy codex entry
- Tests pass (744 pass, 1 skip, 0 fail)

* test(auth): verify backwards compatibility for OAuth metadata fields

- Add test confirming minimal OAuth results (without optional email, name,
  plan, orgName fields) persist correctly in auth storage
- All new metadata fields are optional in plugin types and auth schema
- Provider auth handler uses conditional checks before setting optional fields
- Verify 745 pass, 1 skip, 0 fail

* chore(prd): mark extractUserInfo tasks as complete

The extractUserInfo function is already implemented in codex.ts:92-105.
It parses id_token, extracts email, name, and accountId from claims,
and returns a UserInfo object. All tests pass.

* chore(prd): mark OAuth callback integration tasks as complete

OAuth callback already calls extractUserInfo(tokens) after token exchange and includes email, name, accountId in the success payload.

* fix(app): file listing  (anomalyco#8309)

* chore(prd): mark normalizePlanType tasks as complete

normalizePlanType function maps plan values to standardized tiers (free, plus, pro, team, enterprise, unknown) and handles case variations.

* feat(server): add GET /auth/info/:providerID endpoint for account metadata

- Added endpoint in server.ts that returns auth metadata (authenticated, type, email, plan, accountId)
- Returns 404 with authenticated: false if provider not found
- Generated openapi.json with new endpoint definition
- Regenerated SDK with auth.info method and types (AuthInfoData, AuthInfoResponses)
- Updated prd.json to mark SDK generation tasks as complete
- Tests pass: 745 pass, 1 skip, 0 fail

* chore(prd): mark PR merge and SDK tasks as complete

- Marked "Merge PR before starting Phase 1" as complete (PR #298 already merged)
- Updated verification steps for auth.info endpoint implementation

* chore(prd): mark legacy codex cleanup task as complete

- Verified migration copies codex to openai, Auth.remove('codex') available for manual cleanup
- Removal is intentionally manual to prevent data loss if migration fails

* chore: mark session complete

* chore(prd): mark background task implementation as complete

- Verified fetchChatGPTUserInfo background task at codex.ts:606-632
- Task spawns via 'void updatePlan().catch(() => {})' - non-blocking
- Updates auth metadata via auth.set when plan/orgName retrieved
- OAuth success returns immediately regardless of background task result

* chore(prd): mark manifest.ts creation as complete

- Verified manifest.ts exists with InstalledSkill and SkillManifest interfaces
- Implements loadManifest, saveManifest, getInstalled, addInstalled, removeInstalled
- Used by skill installer to track installed skills and their metadata

* chore(prd): mark skill index and installer files as complete

- Verified skill/index.ts exists with SkillIndex interface and caching logic
- Implements loadIndex (cache with TTL), buildIndex (fetch and write), search (fuzzysort)
- Verified skill/installer.ts exists with installSkill and uninstallSkill functions
- Copies skill files to SKILLS_DIR and updates manifest with installed metadata

* fix plan mode when not in git worktree

* chore(prd): mark github fetcher as complete

- Verified skill/fetcher/github.ts exists with 200 lines implementing git and tarball fetching
- fetchRegistry() entry point with hasGit() check and tarball fallback
- scanSkills() walks directories matching SKILL.md globs with minimatch
- parseSkillFile() extracts YAML frontmatter for skill metadata

* chore(prd): mark clawdhub and url fetchers as complete

- Verified skill/fetcher/clawdhub.ts exists with stub fetchRegistry returning []
- Verified skill/fetcher/url.ts exists with stub fetchRegistry returning []
- Both are TODO stubs awaiting API contract confirmation and implementation

* fix(ui): layout-bottom icons (anomalyco#8330)

* fix(desktop): "load more" button behavior in desktop sidebar (anomalyco#8430)

* chore: generate

* release: v1.1.20

* sync: record last synced tag v1.1.20

* fix: suppress TS2589 type recursion error in server route chain

---------

Co-authored-by: Frank <[email protected]>
Co-authored-by: Github Action <[email protected]>
Co-authored-by: Leonidas <[email protected]>
Co-authored-by: Eduard Voiculescu <[email protected]>
Co-authored-by: ⌞L⌝ <[email protected]>
Co-authored-by: Daniel M Brasil <[email protected]>
Co-authored-by: Daniel Sauer <[email protected]>
Co-authored-by: Felix Sanchez <[email protected]>
Co-authored-by: opencode <[email protected]>
Co-authored-by: Dax Raad <[email protected]>
Co-authored-by: usvimal <[email protected]>
Co-authored-by: Daniel Polito <[email protected]>
Co-authored-by: Brendan Allan <[email protected]>
Co-authored-by: cmdr-chara <[email protected]>
Co-authored-by: Zeke Sikelianos <[email protected]>
Co-authored-by: Vladimir Glafirov <[email protected]>
Co-authored-by: Aiden Cline <[email protected]>
Co-authored-by: Aiden Cline <[email protected]>
Co-authored-by: Dillon Mulroy <[email protected]>
Co-authored-by: Joe Harrison <[email protected]>
Co-authored-by: Dax <[email protected]>
Co-authored-by: Alan <[email protected]>
Co-authored-by: zerone0x <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Akshar Patel <[email protected]>
Co-authored-by: Goni Zahavy <[email protected]>
Co-authored-by: Filip <[email protected]>
Co-authored-by: Andrew Jazbec <[email protected]>
Co-authored-by: Shane Bishop <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE]: Add GitLab Duo Agentic Chat Provider Support

3 participants