Skip to content

Cursor/connect tool wizard - #6277

Closed
Sivyer9303 wants to merge 12 commits into
QuantumNous:mainfrom
Sivyer9303:cursor/connect-tool-wizard
Closed

Cursor/connect tool wizard#6277
Sivyer9303 wants to merge 12 commits into
QuantumNous:mainfrom
Sivyer9303:cursor/connect-tool-wizard

Conversation

@Sivyer9303

@Sivyer9303 Sivyer9303 commented Jul 18, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • Closes # (如有)

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

(请在此粘贴截图、关键日志或测试报告,以证明变更生效)

Summary by CodeRabbit

  • New Features
    • Added a Connect Tool wizard to create API keys and configure supported client applications.
    • Added multi-architecture Docker image publishing for AMD64 and ARM64.
    • Added redemption-code export as a downloadable text file after creation.
    • Redemption-code search now supports full redemption keys, including dashed formats.
    • API key creation responses now include the generated key details.
  • Improvements
    • Pricing data now supports endpoint-specific group availability.
    • Updated interface text and translations across supported languages.

Sivyer9303 and others added 12 commits July 8, 2026 16:36
Enable multi-arch image publishing to ghcr.io on version tags and manual dispatch.

Co-authored-by: Cursor <cursoragent@cursor.com>
Checkout the triggering commit directly instead of treating the image tag as a git ref.

Co-authored-by: Cursor <cursoragent@cursor.com>
Docker requires lowercase registry paths; normalize github.repository before tagging.

Co-authored-by: Cursor <cursoragent@cursor.com>
The create_manifests job needs write access to publish multi-arch tags.

Co-authored-by: Cursor <cursoragent@cursor.com>
Create a token with the selected group and open CC Switch or Cherry Studio via deep link, returning the plaintext key from AddToken for one-click setup.

Co-authored-by: Cursor <cursoragent@cursor.com>
Expose enable_groups_by_endpoint in pricing and narrow the wizard to Anthropic/OpenAI models for the selected protocol and group.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds a connect-tool wizard with endpoint-aware pricing, API-key creation and client import URLs. It also adds exact redemption-key search, redemption-code export, a multi-architecture GHCR workflow, and supporting localization updates.

Changes

Connect tool integration

Layer / File(s) Summary
Pricing and API contracts
model/pricing.go, controller/token.go, web/default/src/features/keys/types.ts, web/default/src/features/keys/api.ts
Pricing exposes endpoint-specific groups, and API-key creation returns the generated token data.
Endpoint matching and import helpers
web/default/src/features/keys/lib/connect-tool.ts
Provider matching, group/model filtering, model recommendations, server lookup, key normalization, and CC Switch/Cherry Studio import URLs are added.
Connect-tool wizard
web/default/src/features/keys/components/api-keys-primary-buttons.tsx, web/default/src/features/keys/components/api-keys-dialogs.tsx, web/default/src/features/keys/components/dialogs/connect-tool-dialog.tsx
Users can select a provider, group, model, and configuration tool, create an API key, and open the selected client.
Connect-tool localization
web/default/src/i18n/locales/*, web/default/src/i18n/static-keys.ts
Wizard labels, status messages, errors, fallback instructions, and model-selection text are localized.

Redemption workflows

Layer / File(s) Summary
Redemption-code search
model/redemption.go, model/redemption_test.go, web/default/src/features/redemption-codes/components/redemptions-table.tsx
Search now recognizes full hexadecimal redemption keys, including dashed input, while rejecting partial keys; the toolbar text reflects redemption-code search.
Redemption-code export
web/default/src/features/redemption-codes/components/redemptions-mutate-drawer.tsx, web/default/src/i18n/locales/*
After creation, an alert offers a sanitized .txt download containing the generated redemption codes.

Container publishing

Layer / File(s) Summary
Multi-architecture GHCR publishing
.github/workflows/docker-ghcr-custom.yml
Tagged and manual workflow runs build amd64 and arm64 images, push architecture tags, and publish versioned and latest multi-architecture manifests.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant ConnectToolDialog
  participant PricingAPI
  participant ToolApplication
  Operator->>ConnectToolDialog: select provider, group, model, and client
  ConnectToolDialog->>PricingAPI: create API key
  PricingAPI-->>ConnectToolDialog: return key data
  ConnectToolDialog->>ToolApplication: open import URL
  ConnectToolDialog-->>Operator: show manual key instructions
Loading

Possibly related PRs

Suggested reviewers: calcium-ion

Poem

I’m a rabbit with keys in my paws,
Connecting tools without pauses.
Codes hop to files, images take flight,
Groups guide models to configure just right.
GHCR shines under moonlit skies—
Binky-approved workflows arise!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: adding a Cursor/connect tool wizard.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Warning

⚠️ This pull request shows signs of AI-generated slop (description_diff_mismatch, ai_padded_prose). It has been flagged by CodeRabbit slop detection and should be reviewed carefully.

@Sivyer9303

Copy link
Copy Markdown
Author

lgtm

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/docker-ghcr-custom.yml:
- Around line 17-19: Remove the workflow-level packages: write permission from
the permissions block in docker-ghcr-custom.yml, leaving only contents: read.
Preserve the existing job-level packages: write declarations in
build_single_arch and create_manifests.
- Around line 61-64: Update the actions/checkout step in the Check out workflow
action to explicitly disable credential persistence by setting
persist-credentials to false alongside fetch-depth, preventing the GITHUB_TOKEN
from being stored in .git/config.
- Around line 30-37: Remove direct GitHub expression interpolation from every
run block in the workflow, especially the tag/image handling around TAG and
IMAGE_NAME. Map required github context values, including workflow_dispatch
image_tag, repository, event name, and ref, through step-level env variables,
then reference quoted shell variables in the scripts. Update remaining steps to
use "$TAG" and "$IMAGE_NAME" instead of interpolated context or env expressions
while preserving the existing outputs and GITHUB_ENV behavior.

In `@model/redemption.go`:
- Around line 79-103: Update the redemption query construction to reuse the
existing commonKeyCol symbol from model/main.go instead of locally selecting
keyCol via a PostgreSQL check. Normalize normalizedKey to lowercase before
validating and comparing it, while preserving the existing exact-key detection
and query branches.

In
`@web/default/src/features/redemption-codes/components/redemptions-mutate-drawer.tsx`:
- Around line 96-104: Update downloadRedemptionCodes to append the created
anchor to document.body before invoking anchor.click(), then remove that same
anchor immediately afterward while preserving the existing download and URL
cleanup behavior.

In `@web/default/src/i18n/locales/ja.json`:
- Line 2503: Update the Japanese translation for the “Loading available
providers...” key to use provider terminology consistently, replacing “タイプ” with
“プロバイダー” or the intended “プロバイダータイプ” wording while preserving the existing
loading-message style.

In `@web/default/src/i18n/locales/zh-TW.json`:
- Line 121: Replace the English values for all referenced new entries in the
zh-TW locale with reviewed Traditional Chinese translations, including the
connect-tool wizard strings. Preserve interpolation tokens and punctuation, and
update the line 1439 translation to explicitly include the meaning “as a text
file.”
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 428aec85-6a0b-47ed-9c58-30f39bee1b71

📥 Commits

Reviewing files that changed from the base of the PR and between 923a17c and 21c1f69.

📒 Files selected for processing (23)
  • .github/workflows/docker-ghcr-custom.yml
  • controller/token.go
  • model/pricing.go
  • model/redemption.go
  • model/redemption_test.go
  • web/default/src/features/keys/api.ts
  • web/default/src/features/keys/components/api-keys-dialogs.tsx
  • web/default/src/features/keys/components/api-keys-primary-buttons.tsx
  • web/default/src/features/keys/components/dialogs/connect-tool-dialog.tsx
  • web/default/src/features/keys/lib/connect-tool.ts
  • web/default/src/features/keys/types.ts
  • web/default/src/features/pricing/types.ts
  • web/default/src/features/redemption-codes/components/redemptions-mutate-drawer.tsx
  • web/default/src/features/redemption-codes/components/redemptions-table.tsx
  • web/default/src/i18n/locales/_reports/_sync-report.json
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/vi.json
  • web/default/src/i18n/locales/zh-TW.json
  • web/default/src/i18n/locales/zh.json
  • web/default/src/i18n/static-keys.ts

Comment on lines +17 to +19
permissions:
contents: read
packages: write

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Scope down workflow-level permissions.

packages: write at the workflow level grants it to every job, including prepare, which only writes $GITHUB_OUTPUT. The build_single_arch and create_manifests jobs already declare packages: write at job scope, so the workflow default can be contents: read.

🔒 Proposed fix
 permissions:
   contents: read
-  packages: write
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions:
contents: read
packages: write
permissions:
contents: read
🧰 Tools
🪛 zizmor (1.26.1)

[error] 19-19: overly broad permissions (excessive-permissions): packages: write is overly broad at the workflow level

(excessive-permissions)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/docker-ghcr-custom.yml around lines 17 - 19, Remove the
workflow-level packages: write permission from the permissions block in
docker-ghcr-custom.yml, leaving only contents: read. Preserve the existing
job-level packages: write declarations in build_single_arch and
create_manifests.

Source: Linters/SAST tools

Comment on lines +30 to +37
run: |
echo "image_name=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG="${{ github.event.inputs.image_tag }}"
else
TAG=${GITHUB_REF#refs/tags/}
fi
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Avoid injecting GitHub context directly into run: shell (template injection).

${{ github.event.inputs.image_tag }} (and the other ${{ ... }} expansions in run: blocks such as Lines 68, 72, 108-109, 124-125, 137-154) is expanded into the shell before execution. A crafted workflow_dispatch input or tag ref can break out and execute arbitrary commands on the runner. Map the context to env: and reference shell variables instead.

🔒 Proposed fix (env mapping)
       - id: meta
+        env:
+          REPOSITORY: ${{ github.repository }}
+          EVENT_NAME: ${{ github.event_name }}
+          IMAGE_TAG_INPUT: ${{ github.event.inputs.image_tag }}
         run: |
-          echo "image_name=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
-          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
-            TAG="${{ github.event.inputs.image_tag }}"
+          echo "image_name=$(echo "$REPOSITORY" | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
+          if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
+            TAG="$IMAGE_TAG_INPUT"
           else
             TAG=${GITHUB_REF#refs/tags/}
           fi
           echo "tag=${TAG}" >> "$GITHUB_OUTPUT"

Apply the same treatment to the remaining run: steps: they already set TAG/IMAGE_NAME into $GITHUB_ENV, so use "$TAG"/"$IMAGE_NAME" in the scripts rather than ${{ env.TAG }}/${{ env.IMAGE_NAME }}.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
run: |
echo "image_name=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG="${{ github.event.inputs.image_tag }}"
else
TAG=${GITHUB_REF#refs/tags/}
fi
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
env:
REPOSITORY: ${{ github.repository }}
EVENT_NAME: ${{ github.event_name }}
IMAGE_TAG_INPUT: ${{ github.event.inputs.image_tag }}
run: |
echo "image_name=$(echo "$REPOSITORY" | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
TAG="$IMAGE_TAG_INPUT"
else
TAG=${GITHUB_REF#refs/tags/}
fi
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
🧰 Tools
🪛 zizmor (1.26.1)

[error] 33-33: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/docker-ghcr-custom.yml around lines 30 - 37, Remove direct
GitHub expression interpolation from every run block in the workflow, especially
the tag/image handling around TAG and IMAGE_NAME. Map required github context
values, including workflow_dispatch image_tag, repository, event name, and ref,
through step-level env variables, then reference quoted shell variables in the
scripts. Update remaining steps to use "$TAG" and "$IMAGE_NAME" instead of
interpolated context or env expressions while preserving the existing outputs
and GITHUB_ENV behavior.

Source: Linters/SAST tools

Comment on lines +61 to +64
- name: Check out
uses: actions/checkout@v4
with:
fetch-depth: 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Disable credential persistence on checkout.

This checkout runs on a job that logs into GHCR and pushes images; leaving persist-credentials at its default writes the GITHUB_TOKEN into .git/config, where later steps could exfiltrate it. Set persist-credentials: false.

🔒 Proposed fix
       - name: Check out
         uses: actions/checkout@v4
         with:
           fetch-depth: 0
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Check out
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check out
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 61-64: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/docker-ghcr-custom.yml around lines 61 - 64, Update the
actions/checkout step in the Check out workflow action to explicitly disable
credential persistence by setting persist-credentials to false alongside
fetch-depth, preventing the GITHUB_TOKEN from being stored in .git/config.

Source: Linters/SAST tools

Comment thread model/redemption.go
Comment on lines +79 to +103
keyCol := "`key`"
if common.UsingMainDatabase(common.DatabaseTypePostgreSQL) {
keyCol = `"key"`
}
normalizedKey := strings.ReplaceAll(strings.TrimSpace(keyword), "-", "")
exactKeyMatch := len(normalizedKey) == 32
if exactKeyMatch {
_, decodeErr := hex.DecodeString(normalizedKey)
exactKeyMatch = decodeErr == nil
}

if id, err := strconv.Atoi(keyword); err == nil {
query = query.Where("id = ? OR name LIKE ?", id, keyword+"%")
if exactKeyMatch {
query = query.Where(
fmt.Sprintf("id = ? OR name LIKE ? OR %s = ?", keyCol),
id, keyword+"%", normalizedKey,
)
} else {
query = query.Where("id = ? OR name LIKE ?", id, keyword+"%")
}
} else if exactKeyMatch {
query = query.Where(
fmt.Sprintf("name LIKE ? OR %s = ?", keyCol),
keyword+"%", normalizedKey,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use commonKeyCol and normalize key casing for robust matching.

As per coding guidelines, use the commonKeyCol variable from model/main.go to handle database-specific column quoting for reserved words, rather than manually duplicating the DatabaseTypePostgreSQL check.

Additionally, consider converting the normalized key to lowercase. PostgreSQL's exact match is case-sensitive, so if a user searches using an uppercase hex key, the match might fail depending on how it's stored.

♻️ Proposed refactor
-		keyCol := "`key`"
-		if common.UsingMainDatabase(common.DatabaseTypePostgreSQL) {
-			keyCol = `"key"`
-		}
-		normalizedKey := strings.ReplaceAll(strings.TrimSpace(keyword), "-", "")
+		normalizedKey := strings.ToLower(strings.ReplaceAll(strings.TrimSpace(keyword), "-", ""))
 		exactKeyMatch := len(normalizedKey) == 32
 		if exactKeyMatch {
 			_, decodeErr := hex.DecodeString(normalizedKey)
 			exactKeyMatch = decodeErr == nil
 		}
 
 		if id, err := strconv.Atoi(keyword); err == nil {
 			if exactKeyMatch {
 				query = query.Where(
-					fmt.Sprintf("id = ? OR name LIKE ? OR %s = ?", keyCol),
+					fmt.Sprintf("id = ? OR name LIKE ? OR %s = ?", commonKeyCol),
 					id, keyword+"%", normalizedKey,
 				)
 			} else {
 				query = query.Where("id = ? OR name LIKE ?", id, keyword+"%")
 			}
 		} else if exactKeyMatch {
 			query = query.Where(
-				fmt.Sprintf("name LIKE ? OR %s = ?", keyCol),
+				fmt.Sprintf("name LIKE ? OR %s = ?", commonKeyCol),
 				keyword+"%", normalizedKey,
 			)
 		} else {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
keyCol := "`key`"
if common.UsingMainDatabase(common.DatabaseTypePostgreSQL) {
keyCol = `"key"`
}
normalizedKey := strings.ReplaceAll(strings.TrimSpace(keyword), "-", "")
exactKeyMatch := len(normalizedKey) == 32
if exactKeyMatch {
_, decodeErr := hex.DecodeString(normalizedKey)
exactKeyMatch = decodeErr == nil
}
if id, err := strconv.Atoi(keyword); err == nil {
query = query.Where("id = ? OR name LIKE ?", id, keyword+"%")
if exactKeyMatch {
query = query.Where(
fmt.Sprintf("id = ? OR name LIKE ? OR %s = ?", keyCol),
id, keyword+"%", normalizedKey,
)
} else {
query = query.Where("id = ? OR name LIKE ?", id, keyword+"%")
}
} else if exactKeyMatch {
query = query.Where(
fmt.Sprintf("name LIKE ? OR %s = ?", keyCol),
keyword+"%", normalizedKey,
)
normalizedKey := strings.ToLower(strings.ReplaceAll(strings.TrimSpace(keyword), "-", ""))
exactKeyMatch := len(normalizedKey) == 32
if exactKeyMatch {
_, decodeErr := hex.DecodeString(normalizedKey)
exactKeyMatch = decodeErr == nil
}
if id, err := strconv.Atoi(keyword); err == nil {
if exactKeyMatch {
query = query.Where(
fmt.Sprintf("id = ? OR name LIKE ? OR %s = ?", commonKeyCol),
id, keyword+"%", normalizedKey,
)
} else {
query = query.Where("id = ? OR name LIKE ?", id, keyword+"%")
}
} else if exactKeyMatch {
query = query.Where(
fmt.Sprintf("name LIKE ? OR %s = ?", commonKeyCol),
keyword+"%", normalizedKey,
)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@model/redemption.go` around lines 79 - 103, Update the redemption query
construction to reuse the existing commonKeyCol symbol from model/main.go
instead of locally selecting keyCol via a PostgreSQL check. Normalize
normalizedKey to lowercase before validating and comparing it, while preserving
the existing exact-key detection and query branches.

Source: Coding guidelines

Comment on lines +96 to +104
function downloadRedemptionCodes(keys: string[], filename: string) {
const blob = new Blob([keys.join('\n')], { type: 'text/plain;charset=utf-8' })
const url = URL.createObjectURL(blob)
const anchor = document.createElement('a')
anchor.href = url
anchor.download = filename
anchor.click()
URL.revokeObjectURL(url)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Append the anchor element to the document body before clicking.

In some browsers, particularly Firefox, calling .click() on an unattached anchor element is silently ignored, preventing the file from downloading. Append the anchor to document.body before clicking, and remove it immediately after to ensure cross-browser compatibility.

🐛 Proposed fix
 function downloadRedemptionCodes(keys: string[], filename: string) {
   const blob = new Blob([keys.join('\n')], { type: 'text/plain;charset=utf-8' })
   const url = URL.createObjectURL(blob)
   const anchor = document.createElement('a')
   anchor.href = url
   anchor.download = filename
+  document.body.appendChild(anchor)
   anchor.click()
+  document.body.removeChild(anchor)
   URL.revokeObjectURL(url)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function downloadRedemptionCodes(keys: string[], filename: string) {
const blob = new Blob([keys.join('\n')], { type: 'text/plain;charset=utf-8' })
const url = URL.createObjectURL(blob)
const anchor = document.createElement('a')
anchor.href = url
anchor.download = filename
anchor.click()
URL.revokeObjectURL(url)
}
function downloadRedemptionCodes(keys: string[], filename: string) {
const blob = new Blob([keys.join('\n')], { type: 'text/plain;charset=utf-8' })
const url = URL.createObjectURL(blob)
const anchor = document.createElement('a')
anchor.href = url
anchor.download = filename
document.body.appendChild(anchor)
anchor.click()
document.body.removeChild(anchor)
URL.revokeObjectURL(url)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@web/default/src/features/redemption-codes/components/redemptions-mutate-drawer.tsx`
around lines 96 - 104, Update downloadRedemptionCodes to append the created
anchor to document.body before invoking anchor.click(), then remove that same
anchor immediately afterward while preserving the existing download and URL
cleanup behavior.

"Load template...": "テンプレートをロード...",
"Loader": "ローダー",
"Loading": "読み込み中",
"Loading available providers...": "利用可能なタイプを読み込み中…",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Translate “providers” consistently.

The source key says “Loading available providers...”, but the Japanese value says “loading available types.” Use 利用可能なプロバイダーを読み込み中… (or 利用可能なプロバイダータイプを読み込み中… if that is the intended UI concept) so the translation matches the actual wizard state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/i18n/locales/ja.json` at line 2503, Update the Japanese
translation for the “Loading available providers...” key to use provider
terminology consistently, replacing “タイプ” with “プロバイダー” or the intended
“プロバイダータイプ” wording while preserving the existing loading-message style.

"80,443,8080": "80,443,8080",
"A billing multiplier. Lower ratios mean lower API call costs.": "收費乘數,倍率越低,API 呼叫費用越低。",
"A focused home for keys, balance, routing, and service health.": "集中展示金鑰、餘額、路由和服務健康狀態。",
"A recommended model is selected automatically. You can change it.": "A recommended model is selected automatically. You can change it.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Localize the new zh-TW values before merging.

These entries render English strings in the Traditional Chinese locale, including most of the new connect-tool wizard. Line 1439 also omits “as a text file” from the source meaning. Replace the English values with reviewed Traditional Chinese translations while preserving interpolation and punctuation.

Also applies to: 391-391, 955-955, 988-988, 1023-1023, 1124-1124, 1136-1136, 1439-1439, 2272-2272, 2503-2503, 2897-2897, 2960-2962, 3353-3353, 3550-3550, 4028-4028

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/i18n/locales/zh-TW.json` at line 121, Replace the English
values for all referenced new entries in the zh-TW locale with reviewed
Traditional Chinese translations, including the connect-tool wizard strings.
Preserve interpolation tokens and punctuation, and update the line 1439
translation to explicitly include the meaning “as a text file.”

Source: Coding guidelines

@Sivyer9303 Sivyer9303 closed this Jul 18, 2026
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.

1 participant