feat(provider): add GitLab Duo Agent provider (Agent Platform)#3060
feat(provider): add GitLab Duo Agent provider (Agent Platform)#3060jiwangyihao wants to merge 20 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 47c4dfa364
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
47c4dfa to
8e5917b
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8e5917b4b4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
8e5917b to
88ccafb
Compare
|
Addressed all three Codex suggestions (force-pushed, folded into the relevant atomic commits):
Also reverted an unrelated |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 88ccafb093
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
88ccafb to
33a0294
Compare
|
Follow-up on the latest Codex review (commit
All checks green: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 33a0294638
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
553c32c to
04111ca
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 04111ca8f7
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
04111ca to
c4e8f9f
Compare
|
Addressed the latest Codex review (P2, |
c4e8f9f to
5bca4f6
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5bca4f68fb
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
5bca4f6 to
cd8fcec
Compare
|
Addressed the latest Codex review:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cd8fcec68b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
cd8fcec to
90e8965
Compare
|
Addressed the 21:06 review:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 90e8965855
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
90e8965 to
20e3ebd
Compare
|
Addressed the broker-login P2: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20e3ebdcd7
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
20e3ebd to
a299e65
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a299e65909
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
wtf is gitlab doing? why two seperate providers? |
https://docs.gitlab.com/user/gitlab_duo/ Maybe you can see this. The old one already in omp is GitLab Duo Non-Agentic, and the one in this PR is GitLab Duo Agent. These two use different credit system (in my test is), and the GitLab Ultimate Trial subscription can only access GitLab Duo Agent. BTW, I may update a new change to this PR in hours, fix an issue I found a moment ago. |
|
CI follow-up: run This is a pre-existing upstream flake, not from this PR:
A re-run of that job (or the upstream flake fix landing on |
将 GitLab Duo Agent 的 goal 改为平权 ChatML 转录、system prompt 移入 inline flow system 槽;新增并行工具调用合并、用户打断 steering 重播种、通用错误重试一次、登录时启用 MCP/Beta 设置,并把 idle-timeout 恢复改为新建 workflow。
A resumed turn that held pending runMCPTool actions whose requestID could not be paired with a persisted tool result (id mismatch) silently created a fresh workflow while leaving the previous one running server-side. The stranded workflow's LangGraph still treated the tool call as in-flight, so the model never saw the result and re-issued the same call in a loop until the user interrupted. The unresolvable-batch path now follows the same cleanup as a mid-batch steer: stop the stranded workflow server-side and drop the resumable session before seeding the fresh workflow, whose goal transcript replays the full history including the unanswered tool result. Also require the server-assigned requestID on each runMCPTool action frame instead of synthesizing a random one: a fabricated non-empty id is silently discarded by the DWS executor outbox (misses the awaiting-futures map), which would strand the tool call. DWS always assigns a non-empty requestID (verified against contract.proto and the proto->JSON relay shape), so a genuinely missing id now fails the turn fast with diagnostics.
The 250ms action-flush window assumed DWS dispatches a model turn's parallel tool calls as a back-to-back burst of runMCPTool frames. A bare-request probe (hold the first action unanswered, watch for a second) proved the opposite: the inline ambient flow's ToolNode runs a serial `for tool_call: await tool.ainvoke(...)` loop and each MCP ainvoke blocks in put_action_and_wait_for_response until the client returns the matching actionResponse, so only one action is ever in flight per turn and the second is never dispatched until the first is answered. The batching window therefore only ever held one frame. Remove the batching machinery (GITLAB_DUO_WORKFLOW_ACTION_FLUSH_MS, the flush timer, pendingActionBatch, finishGitLabDuoWorkflowActionBatch) and restore the serial model: each runMCPTool frame finalizes its own assistant message (one done, one usage) and commits the single pending action; the action result settles immediately without closing the socket so the resume path reuses it. Update the test to assert the per-action contract and the CHANGELOG to describe the serial wire behavior.
Namespace auto-discovery ran on every turn. The root namespace is a function of the GitLab credential (account), not of the conversation or cwd, and the inline ambient flow never exposes namespace to the model, so re-discovering each request was pure overhead. Cache the discovered namespace per account, keyed by a non-reversible fingerprint of the credential plus base URL, in a module-level map that outlives any single conversation session. On auto-discovery the cached namespace is the first choice; only if its dependent direct_access / workflow-create calls later fail (revoked access, deleted group, membership change) is the cache invalidated and discovery rerun once. Explicit rootNamespaceId/namespaceId/project configuration (option or env) bypasses the cache and stays authoritative, preserving the current-credentials re-discovery contract for stale model metadata. Add tests: discovery runs once across two turns for the same account; a cached namespace that fails triggers exactly one re-discovery.
Namespace auto-discovery was already being moved to a per-account cache, but settings enablement (`ensureGitLabDuoWorkflowSettings`) still lived on the per-session provider state. That meant independent side-requests like compaction/handoff could still repeat the namespace settings PUT even though namespace is account-scoped and never exposed to the model. Promote the provider's account preparation state to a module-level per-account map keyed by a non-reversible fingerprint of the credential plus base URL: - keep the discovered namespace selection there, - move `settingsEnsured` there too. Auto-discovery now reuses the cached namespace across sessions/turns and settings enablement is sent at most once per account. If a cached namespace later fails in dependent direct_access/workflow-create calls, it is invalidated and re-discovered once. Explicit namespace/project config still bypasses the cache and stays authoritative. Add tests: namespace discovery runs once across two turns for the same account, re-discovers exactly once after a cached namespace fails, and Duo settings are enabled once per account rather than once per provider session.
- 修复 special.ts 重复 return 片段导致 catalog 无法解析 - stop/settings-enablement 改用 gitLabApiUrl 保留自托管相对路径 - 重放命中 action 早返回前清除 paused,避免续帧被缓冲到超时 - setupForNamespace 返回值改用具名 GitLabDuoWorkflowNamespaceSetup(去除 ReturnType) - toolChoice=none 的 side-request 不再向 Duo 暴露工具 - 套接字异常关闭(closed)也走 stop 清理,避免服务端工作流残留 - ProviderSessionState.close 关闭时发送 stop,避免会话销毁后残留工作流 - 命名空间/设置启用缓存按 (account, baseUrl, cwd) 分区 - 动态模型缓存按凭据+命名空间作用域分区 - resume 失败时丢弃 active 并 stop 工作流
driveOneTurn 原先固定轮询 30 个微任务等待 socket 创建;命名空间发现/ 直连/创建工作流链路较深,在高负载 CI runner 上 socket 尚未创建就放弃 等待,导致 onopen 丢失、流空转至 5s 超时。改为按真实截止时间轮询直到 socket 出现,未出现则显式抛错。
- catalog CHANGELOG 删除 rebase 重放进已发布 [16.1.4] 段落的重复 Claude 4.6 条目,使该段落与上游 main 完全一致(已发布段不可变) - Duo Agent finally 清理在最终 idle timeout(重试已耗尽)时也发送 stop PATCH,避免代理/LB 持续断连场景下服务端工作流残留 - auth-broker login 仅对 pasteCodeFlow provider 传入 onManualCodeInput,普通 loopback provider 不再让 readline 提示与 HTTP 回调竞争导致终端残留
- 动态模型缓存键改为镜像 discoverGitLabDuoWorkflowNamespace 真实解析输入: 内置发现只传 apiKey/baseUrl/fetch,原键里的 namespaceId/projectId/cwd 恒为 空,退化为 apiKey+baseUrl,导致同 token 下两个不同 group 的工作区互相复用 权威模型缓存。改为按 (凭据, baseUrl, 命名空间/项目 config 或同名环境变量, 有效 cwd) 指纹分区。 - 远程 host 比较改用 host(含端口)而非 hostname:同主机不同端口的自托管 GitLab 不再被误判为同实例,避免从错误远程推导项目路径。SCP 远程无端口概念,仍按裸 host 比较。新增跨端口远程不被当作工作区项目的回归测试。
- resumeGitLabDuoWorkflowSocket 在 closed/timeout 结果时也发送 stop PATCH: 预留会话在工具结果或暂停重放后若 WebSocket 在任何终态前返回 closed/timeout, 原先只 finalize 本地流并清 active,不发 fresh-workflow finally 同样会发的停止 请求,导致代理/服务端断连或 idle 超时后服务端工作流残留且本地已无句柄可停。 - AI CHANGELOG 把 GitLab Duo 条目从已发布 [16.1.8] 段移至 [Unreleased]: 已发布段不可变,新条目应入 Unreleased。移动后 [16.1.8] 与上游 main 一致。
- 自动项目发现优先复用命名空间解析所依据的项目(工作区 git remote 或显式 项目),而不是从 group 列表泛选;多项目 group 下不再把工作流 scope 到无关项目。 命名空间选择沿用 remote/project 来源的 projectPath,运行时据此 scope。 - Duo 设置启用仅在确定性尝试(任意 HTTP 响应,含 4xx)后才标记 ensured; 瞬时网络错误/5xx 返回 false,使后续 turn 可重试,避免 fresh 命名空间因一次 瞬时失败而永久跳过 PUT。 - agent CHANGELOG 把 cwd 转发条目从已发布 [16.1.8] 段移至 [Unreleased]; 移动后 [16.1.8] 与上游 main 一致。
机器人指出 gitlab-duo-agent 不在 models.json,fresh 安装(尚无带凭据的动态 发现/缓存)时内置 catalog 看不到默认模型。generator 现按 Sakana 同样方式播种 gitlab-duo-agent 的 fallback 模型(claude_sonnet_4_6_vertex):live aiChatAvailableModels 发现成功时其条目按 id 去重胜出,仅在无凭据/失败 regen 时落种子。 - generate-models.ts:导入 buildGitLabDuoWorkflowFallbackModel,在 authoritative 发现未命中时 push 种子。 - 重新生成 models.json,仅保留 gitlab-duo-agent provider 块的新增,其余 provider 数据维持基线不变(regen 在无凭据环境下未触碰其它 provider)。 - 新增针对 descriptor 的回归测试(非 bundled JSON):断言 manager options 暴露 fallback 静态模型,符合 AGENTS.md 要求。
机器人指出两处问题,本提交处理: 1) direct_access 带 body message 的错误丢弃了 response.status,导致 streaming auth-retry 路径(extractStatusFromAssistantError -> extractHttpStatusFromError)无法恢复状态、无法刷新/轮换过期 OAuth 或 配额受限的 broker 凭据。现在即便有 body message 也内嵌 HTTP <status>, 与 create 路径既有约定一致。新增 401 Unauthorized 回归测试断言状态可恢复, 并强化既有 403 配额测试。 2) generate-models 种子注释过度暗示生成期会跑 namespace-scoped 发现。 实际上 gitlab-duo-agent descriptor 故意不带 catalogDiscovery,被 isCatalogDescriptor 过滤排除在生成发现循环之外,因此生成期绝不会拉取 某账号的 aiChatAvailableModels,只播种通用 namespace-free fallback。 修正注释表述,新增两条针对 descriptor 的回归测试:断言 descriptor 无 catalogDiscovery(永不参与生成发现),以及 fallback 模型不带 gitlabDuoWorkflowRootNamespaceId。
机器人指出 agent.ts 的 #cwd 在构造时固定,/move 更新 SessionManager 与 进程 cwd 后不会重建 Agent,导致 GitLab Duo Agent 的 namespace/project 发现 持续读取旧仓库的 git remote。 按既有 resolver 模式(getReasoning/getServiceTier)修复: - Agent 新增可选 cwdResolver;构造时存入 #cwdResolver。 - AgentLoopConfig 新增 getCwd 每调用解析器,config 同时携带静态 cwd 与 getCwd。 - agent-loop 在 streamFunction 调用点计算 effectiveCwd = getCwd?.() ?? cwd, 每次 LLM 调用读取一次,因此运行中途的 /move 也能被工作区级 provider 发现 感知。 - sdk.ts 主 Agent 传入 cwdResolver: () => sessionManager.getCwd(),该值在 /move 时由 SessionManager.#cwd 更新。 新增针对可观测契约的回归测试(mock streamFn 记录 options.cwd):resolver 覆盖静态 cwd、resolver 返回 undefined 时回退静态 cwd、以及运行中途变更可被 逐次调用读取(模拟 /move)。
4d177cf to
a088037
Compare
|
Addressed the remaining current Codex thread. Fixed — Forward the live session cwd after moves (
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a0880370c1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
机器人指出之前的 CLI 侧 gating 是无效的:runLocalLogin 对非 paste-code provider 省略 onManualCodeInput,但 AuthStorage.login 仍以 ctrl.onManualCodeInput ?? manualCodeInput 注入默认值,因此 loopback OAuth provider 的 OAuthCallbackFlow 仍会让 readline 粘贴提示与 HTTP 回调竞争;回调先到时该提示悬挂,终端进入 脏/阻塞状态。 在唯一汇聚点 AuthStorage.login 做权威 gating: - 仅当 provider 属于 PASTE_CODE_LOGIN_PROVIDERS 时才合成默认 manualCodeInput; loopback provider 不再获得手动码竞争。 - 调用方显式传入的 onManualCodeInput 对任意 provider 仍被透传(逃生舱)。 - 该修复覆盖所有调用方,不止 auth-broker CLI。 - CLI 侧的 usesManualInput gating 保留为纵深防御,并更新注释指明 storage 层 才是权威闸门,纠正机器人指出的“只在此处省略”误导性表述。 新增针对 storage 契约的回归测试(auth-storage-manual-code-gate.test.ts): loopback provider 不被注入默认提示;显式提示对 loopback 仍透传;paste-code provider(gitlab-duo-agent)在调用方省略时被合成默认提示并经 onPrompt 路由。
|
Addressed the newest Codex thread. Fixed — Disable the default manual-code prompt for loopback logins (
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 61755d49c5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
CI follow-up: run This is an unrelated slow-test timeout, not from this PR:
I can't re-run the job (fork PR, no admin rights on the base repo). A maintainer re-run, or the next rebase/push, should clear it. All GitLab-Duo-relevant suites are green: ai gate/oauth/provider/provider-registry 79/79, catalog discovery 28/28, agent 27/27; |
机器人指出两处问题,本提交处理: 1) checkpoint 内容签名去重用的是全局文本相等,导致后续一个合法的新 agent 消息若文本与早先回合相同(例如两个回合都说 "Done"、或重复 reasoning), 因 previousContent 对新 messageKey 为 undefined 而被判为 duplicateContent, provider 不发 delta,用户丢失第二条消息。现在把内容签名作用域绑定到回合 位置(快照内 request/tool 边界计数):同一回合位置上重放的同文本(GitLab 跨收缩快照重命名 message_id 的情形)仍被去重,而位于更晚回合的新消息照常 发出。新增回合内重复文本回归测试;既有 rename 抑制与 pause/resume 测试不变。 2) coding-agent CHANGELOG 把 broker 登录修复条目误放在已发布的 [16.1.16] 段;按 AGENTS.md 已发布段不可变,移动到 [Unreleased] 的 ### Fixed。
|
Addressed the two newest Codex threads in Fixed — Scope checkpoint dedupe to replayed message identity (
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b7ab4b65a3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| }); | ||
| } | ||
| const projectPath = configuredProjectPath ?? discoveredProject?.path; | ||
| const projectId = configuredProjectId ?? discoveredProject?.id; |
There was a problem hiding this comment.
Resolve path-valued projectId before WebSocket routing
When callers set projectId/GITLAB_DUO_PROJECT_ID to a full path such as group/project—which namespace discovery explicitly accepts by carrying projectId.includes("/") as a project path—this assignment still treats that path as the numeric project id. The projectPath branch below resolves paths to a numeric id for WebSocket routing, while REST direct_access/create can keep using the path; skipping that lookup sends project_id=group/project on the WebSocket and can fail project-scoped Duo routing. Split path-valued configuredProjectId into the path flow before computing webSocketProjectId.
Useful? React with 👍 / 👎.
|
CI follow-up: run This is an unrelated ~31s Julia prelude slow-test timing out on a loaded runner, not from this PR:
I can't re-run the job (fork PR, no admin rights on the base repo). A maintainer re-run, or the next rebase/push, should clear it. All GitLab-Duo-relevant suites are green: ai provider 66/66 (incl. the new dedupe regression test), and |
What
Adds a new GitLab Duo Agent provider (
gitlab-duo-agent) that connects to GitLab's Duo Agent Platform via the Duo Workflow Service WebSocket, running an inline customambientflow. The existing AI Gateway proxy provider keeps its id (gitlab-duo) but is renamed for display to GitLab Duo Non-Agentic, matching GitLab's official "Agentic" / "Non-Agentic" classification.Main changes:
gitlab-duo-agent(packages/ai): full WebSocket protocol against the Duo Workflow Service, OAuth login via GitLab's official VS Code OAuth application (vscode://gitlab.gitlab-workflow/authenticationpaste-code callback), stream routing, andrunMCPToolaction bridging so OMP's local tools execute through the agent loop.ambientflow (flowConfigover the WebSocket, schemav1) instead of the built-inchatflow:gitlab_*tools stay hidden and the agent only sees OMP's MCP tools.on_agent_reasoning, mapping pre-tool-call commentary (message_sub_type: "reasoning") to thinking blocks — the chain-of-thought the official Duo CLI surfaces.DUO_AGENT_PLATFORMunit primitive.ambientflow requires a GitLab project server-side, but OMP has no project of its own. When none is configured, the provider discovers an accessible one (preferring a project under the resolved namespace group, then any membership project) and scopesdirect_access, workflow creation, and WebSocket routing to it.packages/catalog):gitlab-duo-agentmodel discovery via liveaiChatAvailableModels, staticcontextWindowresolution (Claude/Gemini → 1,000,000, default 200,000) so the context panel / usage percentage / auto-compaction work, and per-checkpointagent_context_usagemapped ontousage.input/totalTokens. Models are markedreasoning: falsebecause the Duo Agent Platform path exposes no client-controllable thinking knob (the underlying Anthropic model params are server-fixed), so OMP no longer shows a thinking-effort selector for them.workflowIDwhen the WebSocket silently goes half-open (proxy/LB drops the TCP link without deliveringclose/error), instead of hanging until the user presses Esc.cwdplumbing (packages/agent): threads the working directory into provider stream options so provider-side local tool execution targets the right workspace.Why
GitLab is steadily moving Duo onto the Agent Platform (the agentic flow stack served by
duo_workflow_service), and the older non-agentic AI Gateway proxy path is being deprecated. Two concrete reasons motivate a new provider rather than extending the old one:gitlab-duoprovider goes through the AI Gateway proxy, which bills against theai_gateway_proxy_usequota bucket. The Agent Platform path bills againstduo_agent_platform_workflow_on_execute— a different entitlement. GitLab Plans grant GitLab Credits to the Agent Platform bucket, so the old proxy provider cannot consume the credits a user's plan actually provides. This was verified empirically: the same OAuth credential reaches the proxy endpoint but returns402 USAGE_QUOTA_EXCEEDEDon the proxy bucket while the Agent Platform flow runs.The two providers are deliberately kept side by side (the old one renamed to clarify its "Non-Agentic" classification) rather than removing the proxy path, since it still serves the classic Duo Chat surface.
Testing
packages/ai:bun run check(biome + tsgo, 465 files) clean; 49 GitLab provider tests pass.packages/catalog:bun run check(92 files) clean; 20 GitLab discovery tests pass.packages/agentandpackages/coding-agent: typecheck clean.runMCPTool, reasoning→thinking blocks, per-checkpoint usage mapping, and idle-timeout reconnect).bun checkpasses