Commit Graph
98 Commits
Author SHA1 Message Date
Rafli Ahmad Zulfikar c97963c4fb fix(translator): pass service_tier through OpenAI→Responses conversion
Forward the service_tier field from OpenAI requests into the Responses API payload so clients can select priority/default/flex tiers instead of the field being silently dropped.
2026-07-20 11:24:37 +07:00
Edison42 cef5dd4d61 fix(kiro): map GPT-5.6 reasoning effort fields
Route GPT-5.6 reasoning effort through Kiro's native reasoning.effort field instead of the legacy Claude output_config.effort path. GPT-5.6 models now emit reasoning.effort for low/medium/high/xhigh, with max mapped to the xhigh wire value.

Preserve the Responses API reasoning.effort through the OpenAI intermediate by copying it to reasoning_effort before the field is dropped. Skip legacy thinking_mode prompt tags when a supported native GPT effort is emitted, while keeping the legacy fallback for unsupported values (auto/minimal/ultra) and explicit disable semantics (none/off/disabled). Claude adaptive effort continues to use thinking plus output_config.effort.
2026-07-20 11:11:37 +07:00
Edison42 eb00222c4f fix(kiro): map GPT reasoning effort fields
GPT-5.6 via Kiro needs reasoning.effort while Claude uses output_config.effort.
Resolve the effort path per-model schema (like Kiro CLI/KAS) so GPT-5.6
receives the correct structured thinking level. Claude path unchanged.

- Add resolveKiroEffortPath returning "reasoning" | "output_config" | null
- buildKiroAdditionalModelRequestFields emits schema-specific shape
- Keep prompt tags for backward compatibility
- Add OpenAI/Claude translator coverage for GPT-5.6 effort mapping
2026-07-19 13:53:30 +07:00
Edison42 9c58ba645e fix(kiro): improve direct session cache reuse
Reshape Kiro direct requests so resumed client sessions reuse Kiro's
cache-affinity fields instead of starting unrelated CodeWhisperer
conversations.

- keep conversationState.conversationId stable when the client sends an
  explicit session id (x-session-id, session_id, conversation_id, Claude
  Code session metadata)
- add a stable conversationState.agentContinuationId per Kiro session
- send conversationState.agentTaskType: "vibe" and agentMode: "vibe",
  matching the normal Kiro CLI/KAS chat path
- move Kiro thinking instructions into Kiro-compatible systemPrompt /
  additionalModelRequestFields instead of generic top-level thinking
- keep volatile timestamp context out of the top-level systemPrompt; it
  remains only in user content fallback
- suppress additionalModelRequestFields for legacy 4.5-era Claude/Kiro
  models that reject it, while defaulting future Claude/Kiro model ids
  to supported
- preserve Kiro meteringEvent credit usage internally for accounting
  without leaking provider-specific fields into OpenAI-compatible usage
- prevent unrelated headerless Kiro requests from sharing one
  connection-wide continuation
- cap/evict continuation sessions so long-running processes do not grow
  the continuation map unbounded
- treat generated headerless Kiro sessions as one-shot so they do not
  evict real explicit-session continuations
- keep credit-only Kiro metering valid for internal persistence when
  token metrics are unavailable
2026-07-16 15:15:05 +07:00
decolua a6a41dfb3c Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	.gitignore
#	open-sse/handlers/chatCore.js
2026-07-16 11:59:46 +07:00
qianze e567ba800f fix(translator): strip client_metadata when converting openai-responses to openai
client_metadata is an OpenAI Responses API-specific field. When translating
openai-responses requests to openai (Chat Completions), it leaked through
to providers like NVIDIA, which rejected it with a 400 "Unsupported
parameter". Strip it in the Responses-specific cleanup block alongside
input, instructions, store, and reasoning.
2026-07-15 17:38:53 +07:00
Fadjrir Herlambang a11937cdd6 feat(grok-cli): add Grok CLI / Grok Build provider with OAuth device-code flow (#2502)
New OAuth provider routing through cli-chat-proxy.grok.com (OpenAI Responses
API), distinct from xai (api.x.ai) and grok-web (cookie SSO):

- Registry + GrokCliExecutor: Chat Completions -> Responses transform, CLI
  fingerprint headers, virtual effort models grok-4.5-{low,medium,high}
- OAuth device-code flow (auth.x.ai) with no-PKCE, shared xAI token refresh
- store=false multi-turn continuity via reasoning encrypted_content
- Quota tracker: on-demand window + prepaid balance on dashboard
- Connection test: 402 spending-limit = soft success (auth OK, out of credits)
- Alias/oauth/provider baselines + unit tests
2026-07-10 11:47:08 +07:00
DOMANHDUCandCursor 7610f28f42 fix(gemini-cli): raise output floor for thinking and add validated toolConfig (#2486)
Gemini CLI requests with small max_tokens spend the whole output budget on
thoughts after reasoning_effort maps to thinkingConfig, returning blank
content or finish=length. Raise maxOutputTokens floors per thinking level/
budget (clamped to caps.maxOutput). Also emit toolConfig
functionCallingConfig.mode=VALIDATED for Gemini CLI tool requests to avoid
MALFORMED_FUNCTION_CALL.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 11:32:11 +07:00
Samir AbisandCursor ddd5509e97 fix(openai-to-claude): unwrap bare {function:{…}} tools without parent type (#2473)
Translator only unwrapped tool.function when both tool.type==="function"
and tool.function were truthy. Loose/legacy OpenAI clients emit the bare
{ function: { name, parameters } } shape (no parent type), which fell
through and forwarded name: undefined upstream, rejected by strict
Anthropic-compatible gateways (MiniMax M3) as (2013) invalid tool type.

Unwrap tool.function whenever present. Built-in tools stay pass-through.
Adds regression coverage for the 4 tool shapes. See #2435.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 11:11:37 +07:00
nguyenha935andCursor 71cd5b2f23 fix(antigravity): align provider fingerprint with IDE Desktop 2.1.1 (#2389)
Match captured official Antigravity IDE traffic: cloudcode-pa host,
antigravity/ide/2.1.1 User-Agent, IDE-shaped agent requestId, and drop
router-only stream/usage headers plus the legacy double system prompt.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-08 10:17:47 +07:00
deranalabsandCursor a3cd7c82bc fix(translator): preserve developer instructions in openai-responses conversion (#2434)
Map role="developer" messages to top-level instructions alongside
role="system" in openaiToOpenAIResponsesRequest. Previously developer
messages matched no branch and were silently dropped from the Responses
request, losing GPT-5/Codex system-level prompts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 11:54:07 +07:00
46e6c01a01 fix(claude): reconcile max_tokens vs thinking budget and lift per-model ceiling (#2381)
On the translated OpenAI->Claude path, adjustMaxTokens capped max_tokens
before applyThinking set thinking.budget_tokens, so max-effort budget
(128000) could exceed a 64k-clamped max_tokens -> Anthropic 400.
prepareClaudeRequest now reconciles after the budget is known: prefer
raising max_tokens, only shrink budget when it meets/exceeds the ceiling.

Also lift the global 64000 cap: the ceiling is now the model's real
maxOutput, so high-output models (fable/mythos, opus-4.8/sonnet-4.6) get
their full budget. adjustMaxTokens gains an optional ceiling arg (default
unchanged, callers untouched); openai-to-claude passes the model maxOutput.

Native Claude Code passthrough is unaffected.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-05 17:38:16 +07:00
VitzS7andCursor 5041494e1c fix(kiro): deliver system prompt natively, add Opus 4.5/4.7/4.8, tolerate dash version ids (#2366)
- Pass system prompt via native systemInstruction field (+ <instructions> fallback)
  so Claude models stop treating it as info-only <system-reminder>
- Add Opus 4.5/4.7/4.8 (base/thinking/agentic/thinking+agentic) to Kiro registry
- normalizeModelId(): dash->dot version separator, scoped to Kiro provider only
- Replace <system-reminder> with <instructions> in claude-to-openai/openai-to-kiro

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-05 17:34:04 +07:00
Volodymyr SaakianandCursor abc0add031 fix(kiro): route IdC auth to regional CodeWhisperer surface (#2297)
IAM Identity Center (authMethod=idc) tokens failed every request with 403
"bearer token invalid". Treat idc like api_key/external_idp:

- executors/kiro.js: route idc to *.amazonaws.com CodeWhisperer surface,
  region-aware from credentials.region instead of hardcoded us-east-1.
- openai-to-kiro.js / claude-to-kiro.js: send resolved profileArn or empty
  for idc/external_idp, never the shared builder-id placeholder ARN.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 11:06:40 +07:00
Sahrul Ramadhan HardiansyahandCursor ce6120ce7b fix(translator): strict Anthropic content block compliance (#2225)
Filter empty text blocks from thoughtSignature-only parts, preserve
tool_calls when functionResponse and functionCall coexist in the same
content, and skip empty regular text parts before they reach Claude.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 10:58:39 +07:00
decoluaandCursor 749c2e3f9c fix(translator): map mid-conversation system message to user in claude-to-openai
Claude Code chèn role:system cuối messages[], trước đây bị map thành assistant
khiến hội thoại không kết thúc bằng user → provider OpenAI-compat (LiteLLM)
dịch ngược Anthropic trả 400 "assistant message prefill". Map system -> user
và wrap <system-reminder> để giữ ngữ nghĩa instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:53:26 +07:00
warelikandCursor 8d1db46beb fix(gemini): normalize contents to prevent 400 invalid_argument (#2192)
Merge adjacent same-role blocks and strip empty parts before sending to
Gemini, avoiding 400 INVALID_ARGUMENT on consecutive same-role messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:38:03 +07:00
WARELIKandCursor 2d94fffe3b fix(gemini): backfill thoughtSignature and suppress stream done sentinel
Backfill DEFAULT_THINKING_AG_SIGNATURE onto functionCall parts missing it
(client history replay) and on Claude tool_use blocks, fixing 400
INVALID_ARGUMENT from Gemini-family APIs. Suppress the OpenAI-style
data: [DONE] sentinel for antigravity/gemini/vertex to avoid parser crashes.

Fixes #2193.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 15:28:03 +07:00
ntdung6868andCursor 3a866fe18d fix(reasoning): preserve effort through Codex translations
Carry Claude reasoning_effort/reasoning into OpenAI Chat, map into
OpenAI Responses reasoning.effort, and keep request-level effort
(incl. xhigh) across tool-result turns instead of collapsing to high.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 12:06:35 +07:00
EdisonPVEandCursor 2ff11246ae fix(kiro): honor thinking effort budgets
Resolve the Kiro thinking budget from client intent (OpenAI reasoning_effort,
OpenAI Responses reasoning.effort, Claude output_config.effort, and Claude
thinking.budget_tokens) by reusing the shared thinkingUnified extractThinking
parser, then inject the resolved budget into the Kiro thinking system prefix.
Explicit none/off/disabled stops the prefix injection; synthetic -thinking
aliases keep the default budget.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-18 15:14:42 +07:00
decolua 3f9382dee4 Fix AG, Kiro, Xiaomi Provider 2026-06-18 14:58:00 +07:00
706e6513c9 feat(kiro): headless API-key auth + direct Claude/Kiro route
Adds long-lived API-key (ksk_) authentication for Kiro/AWS CodeWhisperer
and a direct claude:kiro / kiro:claude translation route that avoids the
lossy OpenAI two-hop pivot.

- translator: claude-to-kiro request + kiro-to-claude response translators,
  registered on the exact source:target pair (direct route ahead of the
  OpenAI pivot in index.js). claude-to-kiro uses shared schema constants
  (ROLE/CLAUDE_BLOCK/DEFAULT_IMAGE_MIME) per app convention.
- auth: POST /api/oauth/kiro/api-key imports + validates a key via
  ListAvailableProfiles, persists authMethod="api_key" (no refresh token).
- executor: send tokentype: API_KEY header and try *.amazonaws.com hosts
  first for api-key creds; OAuth keeps kiro.dev first.
- fix: never inject the default placeholder profileArn for api-key auth
  (CodeWhisperer 403s an ARN not owned by the key's account).
- ui: API Key method in the Kiro connect modal; surface api-key accounts
  on the Quota Tracker and provider count.
- stream: env-overridable TTFT vs stall timeouts + Kiro keepalive frame.
- tests: claude-kiro-direct + kiro-profile-arn (11 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 10:01:30 +07:00
decolua d03f9fb823 Enhance configuration and model capabilities 2026-06-16 23:32:28 +07:00
decolua b282f05549 Refactor 2026-06-15 18:18:04 +07:00
decoluaandCursor aba4c45da6 fix(translator): ESM-safe registry + tool-id pairing + responses max_tokens; add real-creds tests
- translator/index.js: replace require() with static side-effect imports (ESM-safe),
  lazy-init registry maps to survive circular import order
- openai-responses->openai: map max_output_tokens -> max_tokens (avoid leaking field upstream)
- gemini/antigravity -> openai: derive deterministic tool_call id from name so
  functionCall/functionResponse pair correctly (fixes provider tool-pairing 400s)
- add offline unit tests (finish-reason, usage, session-manager, ollama malformed args, const guard)
- add real-creds integration tests (provider-cases + all-formats matrix: 6 inbound formats x 4 scenarios)

Includes co-located provider registry refactor (pricing/capabilities/media providers) and sessionManager updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 11:38:43 +07:00
decoluaandCursor d3f61aac2f refactor(open-sse): translator DRY + schema enums, bug fixes, dead code cleanup
- Bug B1-B7: media UI m.kind||m.type, serviceKinds, gemini mediaPriority, schema kind, models/info lookup by kind
- Dead code D1-D6: safeParseJSON, drop PROVIDER_ENDPOINTS, orphan fetcher, GITHUB_CONFIG derive, getProviderConfig internal, legacy kiro file
- Translator concerns: toOpenAIUsage, toOpenAIFinish (gemini/kiro/ollama + fix kiro tool finish), thinking effort maps
- Reorg helpers/ → concerns/ (logic) + formats/ (per-format) + schema/ (pure enums: roles/blocks/finishReasons/defaults)
- Wire ~280 hardcoded role/block/finish/default literals to schema enums across 20+ files
- collapseTextParts + extractTextContent dedup
- Normalize translator fn names to openaiToXRequest / xToOpenAIResponse
- Golden tests lock behavior; 0 regression (byte-for-byte providers/alias, 26=26 known fails)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 18:49:38 +07:00
decoluaandCursor bb9e9aa91f refactor(open-sse): registry consolidation + DRY media/oauth/adhoc cleanup
- Single-source registry: oauth clientId/tokenUrl, usage URLs, image/embed
  configs, search defaultModel, codex fixedPort, google token url derive.
- Remove 29 unused OmniRoute providers (registry 100→71); media intact.
- De-adhoc: codex literals → registry format/oauth flags; reasoningInject,
  image/embed openrouter headers + xai bodyFields config-driven.
- Add REGISTRY_TEMPLATE.js + expand PROVIDER_DEFAULTS/schema JSDoc.
- Baselines updated; PROVIDERS 62 + alias 90 byte-for-byte, golden snapshots.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 13:15:48 +07:00
decoluaandCursor 252bf56a9f refactor(translator): P4 concern #2 encodeDataUri — dedupe base64 data-uri building
- imageHelper.encodeDataUri(mime, base64) replaces 5 inline `data:${m};base64,${d}` templates
- Applied to gemini/claude/antigravity request + gemini response translators
- Golden tests pass, identical output

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 21:23:32 +07:00
decoluaandCursor b87cf0c96a refactor(open-sse): extract safeParseJSON util, dedup tryParseJSON (B5)
Consolidate two tryParseJSON variants into helpers/jsonUtil.js with explicit
fallback param. Preserve exact per-call semantics: openai-to-claude passthrough
(fallback=str), geminiHelper null. geminiHelper keeps tryParseJSON re-export.
No behavior change; gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:45:10 +07:00
weimaozhenandCursor 0aaa5ab3c2 fix(claude-to-openai): strip Anthropic billing header from system prompt
Remove dynamic x-anthropic-billing-header lines from Claude system prompts
when translating to OpenAI format to keep prompt prefixes stable and improve
prompt cache hits.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 10:05:12 +07:00
decolua b309261166 enhance Kiro profile ARN resolution 2026-06-13 09:28:55 +07:00
Claude CodeandCursor c785051360 fix(claude): forced tool_choice 400 on cc/ OAuth route
convertOpenAIToolChoice mapped {type:"function"} verbatim and cloakClaudeTools
left tool_choice.name unsuffixed, both rejected by Claude on the cc/ path.
Map forced-function to {type:"tool",name}, allowlist Claude-valid types, and
suffix tool_choice.name when it targets a renamed client tool.

Fixes #1592

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:54:01 +07:00
8ad95542da fix(kiro): handle 400 on tool-bearing history without client tools
Kiro requires a non-empty currentMessage tools array whenever history
references any tool use, else returns "Improperly formed request" (400).
Clients trip this by omitting tools on follow-ups after client-side
compaction.

- flattenToolInteractions(): no client tools -> collapse tool_use/result
  to text so the "tools required" rule never fires
- reconcileOrphanedToolResults(): client tools -> salvage orphaned
  results as text, keep matched ones, guard co-located tools array
- safeJSONParse(): guard tool-call argument parsing against bad JSON
- merge consecutive user userInputMessageContext; null-guard
  currentMessage for assistant-only input

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 12:23:47 +07:00
decolua 9abbb8ad9b # v0.4.52 (2026-05-17)
## Features
- Add Vercel AI Gateway provider support (#1183)
- rtk: Kiro format tool result compression — handle conversationState.history & currentMessage, preserve error results, ~13.6% savings (#1194)

## Fixes
- openclaw: normalize agent.model object form `{primary, fallbacks}` before .startsWith → fix TypeError & 'not configured' status (#1216)
- Usage Details pagination: stay inside mobile viewport <640px (#1218)
- Fix test model error
- Fix MIMO provider in Codex
- Disable log file creation when using MITM AG
2026-05-17 16:37:26 +07:00
decolua 4a575f21a2 https://github.com/decolua/9router/pull/1167
https://github.com/decolua/9router/pull/1166
2026-05-16 11:20:08 +07:00
decolua ad661c1286 feat: enhance CommandCode integration with improved message handling 2026-05-07 23:02:07 +07:00
decolua b72a443bd3 feat: add CommandCode provider support 2026-05-07 23:01:33 +07:00
decolua a3032f7a3e Merge branch 'pr-779-review' 2026-04-28 10:16:23 +07:00
Manuel B. 58a821d687 fix: granular reasoning_effort handling for Claude models (#791)
- github.js: split thinking vs reasoning_effort stripping
  - thinking (Claude-native format) still stripped for all Claude on Copilot
  - reasoning_effort now passed through for Opus 4.6 and Sonnet 4.6
  - still stripped for Haiku 4.5 and Opus 4.7 (rejected upstream)
  - reasoning_effort "none" stripped for all models (not all support it)
- openai-to-claude.js: map reasoning_effort → thinking.budget_tokens
  for direct Anthropic backend (none→skip, low→4096, medium→8192,
  high→16384, xhigh→32768)

Previously reasoning_effort was stripped for ALL Claude models,
meaning Opus 4.6 via Copilot never received thinking configuration.

AI-generated commit by Claude Opus 4.6 (Anthropic)
2026-04-28 09:49:27 +07:00
lukmanfauzie c43f8c54d4 fix: Antigravity INVALID_ARGUMENT errors and Copilot agent mode parity 2026-04-26 19:53:08 +08:00
Anurag Saxena 37f7e97348 fix: force Agent mode in Cursor protobuf when User-Agent contains Claude Code (closes #643) (#692) 2026-04-22 10:24:58 +07:00
anuragg-saxenaa 6e8aaab299 fix: strip enumDescriptions from tool schema in antigravity-to-openai (closes #566)
Co-authored-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
Made-with: Cursor
2026-04-17 12:15:10 +07:00
Anurag Saxena 23abe1a7bb fix: merge consecutive userInputMessages in openai-to-kiro translator (closes #510) (#524) 2026-04-08 15:38:28 +07:00
decolua 1973fe5a83 fix(translator): correct thought signatures for AG, Gemini CLI, Vertex; fix missing Vertex response translator
- Add DEFAULT_THINKING_AG_SIGNATURE, DEFAULT_THINKING_GEMINI_CLI_SIGNATURE, DEFAULT_THINKING_VERTEX_SIGNATURE
- Rename DEFAULT_THINKING_GEMINI_SIGNATURE → DEFAULT_THINKING_AG_SIGNATURE for clarity
- Pass provider-specific signature into openaiToGeminiBase (AG vs Gemini CLI)
- Replace synthetic thoughtSignatures with Vertex-native signature in postProcessForVertex
- Register Vertex → OpenAI response translator (fixes empty Vertex streaming responses)

Made-with: Cursor
2026-04-05 00:38:36 +07:00
decolua 333e704b2a MODEL_CAPS 2026-04-04 23:24:24 +07:00
Anurag Saxena 5fe2c81cf9 fix: skip function_call items with empty/missing name to prevent Codex 400 error (closes #444) (#487) 2026-04-04 08:51:00 +07:00
decolua 93b8668e9e Fix AG 2026-04-01 11:48:38 +07:00
kwanLeeFrmVi 054facb08b fix(gemini): preserve thoughtSignature via tool_call ID smuggling + fix ELOCKED mutex
- Encode thoughtSignature into tool_call.id using _TSIG_ delimiter and base64url
- Decode _TSIG_ on request to restore thoughtSignature for Gemini multi-turn thinking
- Track pendingThoughtSignature across parts for deferred signature attachment
- Add LocalMutex (2-layer locking) to prevent ELOCKED on concurrent DB access
- Increase lockfile retries from 5 to 15 for multi-process robustness
- Restore db.json seed on first run to prevent ENOENT on lockfile.lock
- Use process.env.BASE_URL fallback in models test route
- Remove gemini-3-flash-lite-preview from provider models

Co-authored-by: kwanLeeFrmVi <quanle96@outlook.com>
Closes #450

Made-with: Cursor
2026-03-30 16:57:28 +07:00
kwanLeeFrmVi 1c160cc8d9 feat(claude-code): spoof TLS fingerprint and stabilize headers for Anthropic
- Add claudeHeaderCache.js to intercept and cache live Claude Code client headers
- Forward cached headers dynamically to api.anthropic.com via default.js
- Strip first-party identity headers (x-app, claude-code-* beta) for non-Anthropic upstreams
- Validate and sanitize tool call IDs to match Anthropic pattern (^[a-zA-Z0-9_-]+$)
- Skip thinking blocks when applying cache_control; fix max_tokens buffer (+1024)
- Strip cache_control from thinking blocks in openai-to-claude translator
- Comment out thoughtSignature in Gemini translator (kept for reference)
- Expand .gitignore to match all deploy*.sh variants

Co-authored-by: kwanLeeFrmVi <quanle96@outlook.com>
Closes #433

Made-with: Cursor
2026-03-30 16:27:28 +07:00
decolua abbf8ec86f feat: add GitLab Duo and CodeBuddy support, update observability settings 2026-03-30 11:28:07 +07:00