From 37be0281422c25c8a743e43d56a5dc960042ee6f Mon Sep 17 00:00:00 2001 From: Pan YANG Date: Sun, 2 Aug 2026 19:51:11 +0800 Subject: [PATCH] feat(clis): add localized Codex landing page --- content/clis/de/codex-cli.md | 75 +++ content/clis/en/codex-cli.md | 75 +++ content/clis/es/codex-cli.md | 75 +++ content/clis/fr/codex-cli.md | 75 +++ content/clis/id/codex-cli.md | 75 +++ content/clis/ja/codex-cli.md | 75 +++ content/clis/ko/codex-cli.md | 75 +++ content/clis/pt/codex-cli.md | 75 +++ content/clis/ru/codex-cli.md | 75 +++ content/clis/tr/codex-cli.md | 75 +++ content/clis/zh-Hans/codex-cli.md | 75 +++ content/clis/zh-Hant/codex-cli.md | 75 +++ data/$schemas/cli-landing-pages.schema.json | 96 +++ data/data-health.json | 44 +- data/generated/cli-landing-pages.json | 590 ++++++++++++++++++ docs/DATA-HEALTH.md | 22 +- manifests/$schemas/cli.schema.json | 4 + manifests/$schemas/ref/entity.schema.json | 4 +- manifests/clis/codex-cli.json | 57 +- .../generate/generate-cli-landing-pages.ts | 70 +++ scripts/validate/lib/i18n-placeholders.ts | 12 +- src/app/[locale]/clis/[slug]/page.tsx | 86 ++- src/components/product/CLILandingPage.tsx | 382 ++++++++++++ src/components/product/ProductPricing.tsx | 45 +- src/components/product/RelatedProducts.tsx | 45 +- src/lib/content/cli-landing-markdown.ts | 164 +++++ src/lib/content/cli-landing-pages.ts | 11 + src/lib/metadata/schemas/builders.ts | 37 +- src/types/manifests.ts | 1 + tests/metadata.offers.test.ts | 29 + tests/validate/cli-landing-pages.test.ts | 93 +++ tests/validate/manifests.sources.test.ts | 81 +++ translations/de/components/product.json | 19 + translations/en/components/product.json | 21 +- translations/es/components/product.json | 19 + translations/fr/components/product.json | 19 + translations/id/components/product.json | 19 + translations/ja/components/product.json | 19 + translations/ko/components/product.json | 19 + translations/pt/components/product.json | 19 + translations/ru/components/product.json | 19 + translations/tr/components/product.json | 19 + translations/zh-Hans/components/product.json | 19 + translations/zh-Hant/components/product.json | 19 + 44 files changed, 2907 insertions(+), 96 deletions(-) create mode 100644 content/clis/de/codex-cli.md create mode 100644 content/clis/en/codex-cli.md create mode 100644 content/clis/es/codex-cli.md create mode 100644 content/clis/fr/codex-cli.md create mode 100644 content/clis/id/codex-cli.md create mode 100644 content/clis/ja/codex-cli.md create mode 100644 content/clis/ko/codex-cli.md create mode 100644 content/clis/pt/codex-cli.md create mode 100644 content/clis/ru/codex-cli.md create mode 100644 content/clis/tr/codex-cli.md create mode 100644 content/clis/zh-Hans/codex-cli.md create mode 100644 content/clis/zh-Hant/codex-cli.md create mode 100644 data/$schemas/cli-landing-pages.schema.json create mode 100644 data/generated/cli-landing-pages.json create mode 100644 scripts/generate/generate-cli-landing-pages.ts create mode 100644 src/components/product/CLILandingPage.tsx create mode 100644 src/lib/content/cli-landing-markdown.ts create mode 100644 src/lib/content/cli-landing-pages.ts create mode 100644 tests/metadata.offers.test.ts create mode 100644 tests/validate/cli-landing-pages.test.ts create mode 100644 tests/validate/manifests.sources.test.ts diff --git a/content/clis/de/codex-cli.md b/content/clis/de/codex-cli.md new file mode 100644 index 00000000..54b5ca39 --- /dev/null +++ b/content/clis/de/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI ist OpenAIs offizieller Coding-Agent zum Prüfen, Bearbeiten und Ausführen von Code direkt im Terminal. + +## introduction + +Er arbeitet mit lokalen Projekten, bietet Kontrolle über Modelle und Berechtigungen und unterstützt interaktive Aufgaben sowie wiederholbare Skripte und CI-Workflows. + +## capabilities.items.0.title + +Codebasis verstehen + +## capabilities.items.0.description + +Projektdateien prüfen und Fragen im Kontext des Projekts beantworten. + +## capabilities.items.1.title + +Code bearbeiten und debuggen + +## capabilities.items.1.description + +Gezielte Änderungen vornehmen, Probleme finden und lokale Prüfungen ausführen. + +## capabilities.items.2.title + +Befehle ausführen und automatisieren + +## capabilities.items.2.description + +Shell-Werkzeuge interaktiv nutzen oder codex exec aus Skripten und CI-Pipelines aufrufen. + +## verification.description + +Produktangaben werden mit offizieller Dokumentation, Preisseiten und dem Upstream-Repository abgeglichen. + +## faq.items.0.question + +Gibt es eine Codex CLI von OpenAI? + +## faq.items.0.answer + +Ja. Codex CLI ist OpenAIs Kommandozeilen-Agent zum Prüfen, Bearbeiten und Ausführen von Code in lokalen Projekten. + +## faq.items.1.question + +Wie installiere ich Codex CLI? + +## faq.items.1.answer + +Nutzen Sie den Installationsbefehl für Ihr Betriebssystem, führen Sie codex im Projektverzeichnis aus und melden Sie sich mit ChatGPT oder einem API-Schlüssel an. + +## faq.items.2.question + +Kann Codex CLI Dateien ändern und Befehle ausführen? + +## faq.items.2.answer + +Ja. Im Rahmen der gewählten Berechtigungen kann Codex Dateien prüfen und ändern, lokale Werkzeuge starten und Tests ausführen. + +## faq.items.3.question + +Welche Betriebssysteme unterstützt Codex CLI? + +## faq.items.3.answer + +Das aktuelle Manifest nennt macOS, Windows und Linux samt Installations- und Startbefehlen. + +## faq.items.4.question + +Ist Codex CLI kostenlos? + +## faq.items.4.answer + +Codex ist in mehreren ChatGPT-Tarifen einschließlich Free verfügbar und kann mit nutzungsabhängig abgerechnetem API-Schlüssel verwendet werden. Limits und Funktionen unterscheiden sich. diff --git a/content/clis/en/codex-cli.md b/content/clis/en/codex-cli.md new file mode 100644 index 00000000..9a88ac34 --- /dev/null +++ b/content/clis/en/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI is OpenAI’s official coding agent for inspecting, editing, and running code from your terminal. + +## introduction + +It works against your local repository, lets you control models and permissions, and supports interactive tasks as well as repeatable scripts and CI workflows. + +## capabilities.items.0.title + +Understand your codebase + +## capabilities.items.0.description + +Inspect project files and answer questions with repository context. + +## capabilities.items.1.title + +Edit and debug code + +## capabilities.items.1.description + +Make focused changes, find issues, and run checks in your local environment. + +## capabilities.items.2.title + +Run commands and automate + +## capabilities.items.2.description + +Use shell tools interactively or call codex exec from scripts and CI pipelines. + +## verification.description + +Product facts are checked against official documentation, pricing pages, and the upstream repository. + +## faq.items.0.question + +Does OpenAI have a Codex CLI? + +## faq.items.0.answer + +Yes. Codex CLI is OpenAI’s command-line coding agent for inspecting, editing, and running code in local repositories. + +## faq.items.1.question + +How do I install Codex CLI? + +## faq.items.1.answer + +Use the install command shown for your operating system, then run codex from a project directory and sign in with ChatGPT or an API key. + +## faq.items.2.question + +Can Codex CLI edit files and run commands? + +## faq.items.2.answer + +Yes. It can inspect and modify files, run local tools, and execute checks subject to the permissions you choose. + +## faq.items.3.question + +Which operating systems does Codex CLI support? + +## faq.items.3.answer + +The current manifest lists macOS, Windows, and Linux, with installation and launch commands for each platform. + +## faq.items.4.question + +Is Codex CLI free? + +## faq.items.4.answer + +Codex is available through several ChatGPT plans, including Free, and can also use an API key with usage-based billing. Limits and features vary by plan. diff --git a/content/clis/es/codex-cli.md b/content/clis/es/codex-cli.md new file mode 100644 index 00000000..db453e59 --- /dev/null +++ b/content/clis/es/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI es el agente de programación oficial de OpenAI para inspeccionar, editar y ejecutar código desde la terminal. + +## introduction + +Trabaja con tu repositorio local, te permite controlar los modelos y los permisos, y admite tanto tareas interactivas como scripts repetibles y flujos de trabajo de CI. + +## capabilities.items.0.title + +Comprender tu base de código + +## capabilities.items.0.description + +Inspecciona los archivos del proyecto y responde preguntas teniendo en cuenta el contexto del repositorio. + +## capabilities.items.1.title + +Editar y depurar código + +## capabilities.items.1.description + +Realiza cambios específicos, encuentra problemas y ejecuta comprobaciones en tu entorno local. + +## capabilities.items.2.title + +Ejecutar comandos y automatizar + +## capabilities.items.2.description + +Usa herramientas de shell de forma interactiva o llama a codex exec desde scripts y canalizaciones de CI. + +## verification.description + +Los datos del producto se contrastan con la documentación oficial, las páginas de precios y el repositorio original. + +## faq.items.0.question + +¿OpenAI ofrece Codex CLI? + +## faq.items.0.answer + +Sí. Codex CLI es el agente de programación de línea de comandos de OpenAI para inspeccionar, editar y ejecutar código en repositorios locales. + +## faq.items.1.question + +¿Cómo instalo Codex CLI? + +## faq.items.1.answer + +Usa el comando de instalación indicado para tu sistema operativo, ejecuta codex desde el directorio de un proyecto e inicia sesión con ChatGPT o una API key. + +## faq.items.2.question + +¿Codex CLI puede editar archivos y ejecutar comandos? + +## faq.items.2.answer + +Sí. Puede inspeccionar y modificar archivos, usar herramientas locales y ejecutar comprobaciones de acuerdo con los permisos que elijas. + +## faq.items.3.question + +¿Qué sistemas operativos admite Codex CLI? + +## faq.items.3.answer + +El manifest actual incluye macOS, Windows y Linux, con comandos de instalación y ejecución para cada plataforma. + +## faq.items.4.question + +¿Codex CLI es gratuito? + +## faq.items.4.answer + +Codex está disponible con varios planes de ChatGPT, incluido Free, y también puede usar una API key con facturación por uso. Los límites y las funciones varían según el plan. diff --git a/content/clis/fr/codex-cli.md b/content/clis/fr/codex-cli.md new file mode 100644 index 00000000..664d034f --- /dev/null +++ b/content/clis/fr/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI est l’agent de programmation officiel d’OpenAI pour inspecter, modifier et exécuter du code depuis votre terminal. + +## introduction + +Il travaille sur votre dépôt local, vous permet de contrôler les modèles et les autorisations, et prend en charge aussi bien les tâches interactives que les scripts reproductibles et les workflows de CI. + +## capabilities.items.0.title + +Comprendre votre base de code + +## capabilities.items.0.description + +Inspectez les fichiers du projet et obtenez des réponses qui tiennent compte du contexte du dépôt. + +## capabilities.items.1.title + +Modifier et déboguer le code + +## capabilities.items.1.description + +Apportez des modifications ciblées, détectez les problèmes et lancez des vérifications dans votre environnement local. + +## capabilities.items.2.title + +Exécuter des commandes et automatiser + +## capabilities.items.2.description + +Utilisez les outils du shell de manière interactive ou appelez codex exec depuis des scripts et des pipelines de CI. + +## verification.description + +Les informations sur le produit sont vérifiées à partir de la documentation officielle, des pages tarifaires et du dépôt d’origine. + +## faq.items.0.question + +OpenAI propose-t-il Codex CLI ? + +## faq.items.0.answer + +Oui. Codex CLI est l’agent de programmation en ligne de commande d’OpenAI pour inspecter, modifier et exécuter du code dans des dépôts locaux. + +## faq.items.1.question + +Comment installer Codex CLI ? + +## faq.items.1.answer + +Utilisez la commande d’installation indiquée pour votre système d’exploitation, puis lancez codex depuis le répertoire d’un projet et connectez-vous avec ChatGPT ou une API key. + +## faq.items.2.question + +Codex CLI peut-il modifier des fichiers et exécuter des commandes ? + +## faq.items.2.answer + +Oui. Il peut inspecter et modifier des fichiers, utiliser des outils locaux et lancer des vérifications selon les autorisations que vous choisissez. + +## faq.items.3.question + +Quels systèmes d’exploitation Codex CLI prend-il en charge ? + +## faq.items.3.answer + +Le manifest actuel répertorie macOS, Windows et Linux, avec les commandes d’installation et de lancement pour chaque plateforme. + +## faq.items.4.question + +Codex CLI est-il gratuit ? + +## faq.items.4.answer + +Codex est proposé dans plusieurs offres ChatGPT, dont Free, et peut aussi utiliser une API key avec une facturation à l’usage. Les limites et les fonctionnalités varient selon l’offre. diff --git a/content/clis/id/codex-cli.md b/content/clis/id/codex-cli.md new file mode 100644 index 00000000..847f3f92 --- /dev/null +++ b/content/clis/id/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI adalah agen coding resmi OpenAI untuk memeriksa, mengedit, dan menjalankan kode dari terminal Anda. + +## introduction + +Codex CLI bekerja pada repositori lokal, memungkinkan Anda mengendalikan model dan izin, serta mendukung tugas interaktif, skrip berulang, dan alur kerja CI. + +## capabilities.items.0.title + +Memahami basis kode Anda + +## capabilities.items.0.description + +Periksa file proyek dan jawab pertanyaan dengan mempertimbangkan konteks repositori. + +## capabilities.items.1.title + +Mengedit dan men-debug kode + +## capabilities.items.1.description + +Lakukan perubahan terarah, temukan masalah, dan jalankan pemeriksaan di lingkungan lokal Anda. + +## capabilities.items.2.title + +Menjalankan perintah dan mengotomatiskan tugas + +## capabilities.items.2.description + +Gunakan alat shell secara interaktif atau panggil codex exec dari skrip dan pipeline CI. + +## verification.description + +Fakta produk diperiksa berdasarkan dokumentasi resmi, halaman harga, dan repositori sumber. + +## faq.items.0.question + +Apakah OpenAI memiliki Codex CLI? + +## faq.items.0.answer + +Ya. Codex CLI adalah agen coding baris perintah OpenAI untuk memeriksa, mengedit, dan menjalankan kode dalam repositori lokal. + +## faq.items.1.question + +Bagaimana cara menginstal Codex CLI? + +## faq.items.1.answer + +Gunakan perintah instalasi yang ditampilkan untuk sistem operasi Anda, lalu jalankan codex dari direktori proyek dan masuk dengan ChatGPT atau API key. + +## faq.items.2.question + +Apakah Codex CLI dapat mengedit file dan menjalankan perintah? + +## faq.items.2.answer + +Ya. Codex CLI dapat memeriksa dan mengubah file, menjalankan alat lokal, serta melakukan pemeriksaan sesuai izin yang Anda pilih. + +## faq.items.3.question + +Sistem operasi apa saja yang didukung Codex CLI? + +## faq.items.3.answer + +Manifest saat ini mencantumkan macOS, Windows, dan Linux, beserta perintah instalasi dan peluncuran untuk setiap platform. + +## faq.items.4.question + +Apakah Codex CLI gratis? + +## faq.items.4.answer + +Codex tersedia melalui beberapa paket ChatGPT, termasuk Free, dan juga dapat menggunakan API key dengan penagihan berbasis pemakaian. Batas dan fitur berbeda-beda menurut paket. diff --git a/content/clis/ja/codex-cli.md b/content/clis/ja/codex-cli.md new file mode 100644 index 00000000..2d8efb12 --- /dev/null +++ b/content/clis/ja/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI は、ターミナルからコードの調査、編集、実行を行える OpenAI 公式のコーディングエージェントです。 + +## introduction + +ローカルリポジトリを対象に動作し、モデルと権限を管理でき、対話型タスクに加えて反復可能なスクリプトや CI ワークフローにも対応します。 + +## capabilities.items.0.title + +コードベースを理解する + +## capabilities.items.0.description + +プロジェクトのファイルを調査し、リポジトリの文脈に基づいて質問に回答します。 + +## capabilities.items.1.title + +コードを編集・デバッグする + +## capabilities.items.1.description + +目的を絞った変更を行い、問題を見つけ、ローカル環境でチェックを実行します。 + +## capabilities.items.2.title + +コマンドを実行し、自動化する + +## capabilities.items.2.description + +シェルツールを対話的に使用したり、スクリプトや CI パイプラインから codex exec を呼び出したりできます。 + +## verification.description + +製品情報は、公式ドキュメント、料金ページ、アップストリームリポジトリと照合しています。 + +## faq.items.0.question + +OpenAI に Codex CLI はありますか? + +## faq.items.0.answer + +はい。Codex CLI は、ローカルリポジトリ内のコードを調査、編集、実行するための OpenAI のコマンドライン型コーディングエージェントです。 + +## faq.items.1.question + +Codex CLI はどのようにインストールしますか? + +## faq.items.1.answer + +お使いのオペレーティングシステム向けに表示されたインストールコマンドを使用し、プロジェクトディレクトリで codex を実行して、ChatGPT または API key でサインインします。 + +## faq.items.2.question + +Codex CLI はファイルの編集やコマンドの実行ができますか? + +## faq.items.2.answer + +はい。選択した権限の範囲内で、ファイルの調査と変更、ローカルツールの実行、チェックの実施が可能です。 + +## faq.items.3.question + +Codex CLI はどのオペレーティングシステムに対応していますか? + +## faq.items.3.answer + +現在のマニフェストには macOS、Windows、Linux が記載されており、各プラットフォーム向けのインストールコマンドと起動コマンドも掲載されています。 + +## faq.items.4.question + +Codex CLI は無料ですか? + +## faq.items.4.answer + +Codex は Free を含む複数の ChatGPT プランで利用でき、従量課金の API key も使用できます。利用上限と機能はプランによって異なります。 diff --git a/content/clis/ko/codex-cli.md b/content/clis/ko/codex-cli.md new file mode 100644 index 00000000..37c063df --- /dev/null +++ b/content/clis/ko/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI는 터미널에서 코드를 살펴보고 편집하며 실행할 수 있는 OpenAI의 공식 코딩 에이전트입니다. + +## introduction + +로컬 저장소를 대상으로 작동하며 모델과 권한을 제어할 수 있고, 대화형 작업뿐 아니라 반복 가능한 스크립트와 CI 워크플로도 지원합니다. + +## capabilities.items.0.title + +코드베이스 이해 + +## capabilities.items.0.description + +프로젝트 파일을 살펴보고 저장소의 맥락을 바탕으로 질문에 답합니다. + +## capabilities.items.1.title + +코드 편집 및 디버깅 + +## capabilities.items.1.description + +필요한 부분을 정확히 변경하고 문제를 찾아 로컬 환경에서 검사를 실행합니다. + +## capabilities.items.2.title + +명령 실행 및 자동화 + +## capabilities.items.2.description + +셸 도구를 대화형으로 사용하거나 스크립트와 CI 파이프라인에서 codex exec를 호출할 수 있습니다. + +## verification.description + +제품 정보는 공식 문서, 가격 페이지, 업스트림 저장소와 대조해 확인합니다. + +## faq.items.0.question + +OpenAI에서 Codex CLI를 제공하나요? + +## faq.items.0.answer + +예. Codex CLI는 로컬 저장소의 코드를 살펴보고 편집하며 실행하기 위한 OpenAI의 명령줄 코딩 에이전트입니다. + +## faq.items.1.question + +Codex CLI는 어떻게 설치하나요? + +## faq.items.1.answer + +사용 중인 운영체제에 표시된 설치 명령을 사용한 다음, 프로젝트 디렉터리에서 codex를 실행하고 ChatGPT 또는 API key로 로그인하세요. + +## faq.items.2.question + +Codex CLI로 파일을 편집하고 명령을 실행할 수 있나요? + +## faq.items.2.answer + +예. 선택한 권한 범위 안에서 파일을 살펴보고 수정하며, 로컬 도구와 검사를 실행할 수 있습니다. + +## faq.items.3.question + +Codex CLI는 어떤 운영체제를 지원하나요? + +## faq.items.3.answer + +현재 매니페스트에는 macOS, Windows, Linux와 각 플랫폼의 설치 및 실행 명령이 등록되어 있습니다. + +## faq.items.4.question + +Codex CLI는 무료인가요? + +## faq.items.4.answer + +Codex는 Free를 포함한 여러 ChatGPT 플랜에서 사용할 수 있으며, 사용량 기반 요금이 적용되는 API key도 이용할 수 있습니다. 한도와 기능은 플랜에 따라 다릅니다. diff --git a/content/clis/pt/codex-cli.md b/content/clis/pt/codex-cli.md new file mode 100644 index 00000000..132ea49d --- /dev/null +++ b/content/clis/pt/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +O Codex CLI é o agente de programação oficial da OpenAI para inspecionar, editar e executar código pelo terminal. + +## introduction + +Ele trabalha no seu repositório local, permite controlar modelos e permissões e oferece suporte tanto a tarefas interativas quanto a scripts repetíveis e fluxos de CI. + +## capabilities.items.0.title + +Entender sua base de código + +## capabilities.items.0.description + +Inspecione os arquivos do projeto e responda a perguntas usando o contexto do repositório. + +## capabilities.items.1.title + +Editar e depurar código + +## capabilities.items.1.description + +Faça alterações pontuais, encontre problemas e execute verificações no seu ambiente local. + +## capabilities.items.2.title + +Executar comandos e automatizar + +## capabilities.items.2.description + +Use ferramentas de shell de forma interativa ou chame codex exec em scripts e pipelines de CI. + +## verification.description + +Os dados do produto são conferidos com a documentação oficial, as páginas de preços e o repositório original. + +## faq.items.0.question + +A OpenAI oferece o Codex CLI? + +## faq.items.0.answer + +Sim. O Codex CLI é o agente de programação por linha de comando da OpenAI para inspecionar, editar e executar código em repositórios locais. + +## faq.items.1.question + +Como instalo o Codex CLI? + +## faq.items.1.answer + +Use o comando de instalação exibido para o seu sistema operacional. Depois, execute codex em um diretório de projeto e entre com o ChatGPT ou uma API key. + +## faq.items.2.question + +O Codex CLI pode editar arquivos e executar comandos? + +## faq.items.2.answer + +Sim. Ele pode inspecionar e modificar arquivos, executar ferramentas locais e realizar verificações dentro das permissões que você escolher. + +## faq.items.3.question + +Quais sistemas operacionais o Codex CLI suporta? + +## faq.items.3.answer + +O manifesto atual lista macOS, Windows e Linux, com comandos de instalação e inicialização para cada plataforma. + +## faq.items.4.question + +O Codex CLI é gratuito? + +## faq.items.4.answer + +O Codex está disponível em vários planos do ChatGPT, inclusive o Free, e também pode usar uma API key com cobrança por uso. Os limites e recursos variam conforme o plano. diff --git a/content/clis/ru/codex-cli.md b/content/clis/ru/codex-cli.md new file mode 100644 index 00000000..513e7762 --- /dev/null +++ b/content/clis/ru/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI — официальный агент OpenAI для программирования, который позволяет анализировать и редактировать код, а также запускать его из терминала. + +## introduction + +Он работает с вашим локальным репозиторием, позволяет управлять моделями и разрешениями и поддерживает как интерактивные задачи, так и повторяемые сценарии и процессы CI. + +## capabilities.items.0.title + +Понимать вашу кодовую базу + +## capabilities.items.0.description + +Анализировать файлы проекта и отвечать на вопросы с учётом контекста репозитория. + +## capabilities.items.1.title + +Редактировать и отлаживать код + +## capabilities.items.1.description + +Вносить точечные изменения, находить проблемы и запускать проверки в вашей локальной среде. + +## capabilities.items.2.title + +Выполнять команды и автоматизировать задачи + +## capabilities.items.2.description + +Использовать инструменты командной оболочки в интерактивном режиме или вызывать codex exec из сценариев и конвейеров CI. + +## verification.description + +Сведения о продукте сверяются с официальной документацией, страницами с ценами и исходным репозиторием. + +## faq.items.0.question + +Есть ли у OpenAI Codex CLI? + +## faq.items.0.answer + +Да. Codex CLI — агент OpenAI для программирования в командной строке, который анализирует, редактирует и запускает код в локальных репозиториях. + +## faq.items.1.question + +Как установить Codex CLI? + +## faq.items.1.answer + +Выполните команду установки для своей операционной системы, затем запустите codex из каталога проекта и войдите с помощью ChatGPT или API key. + +## faq.items.2.question + +Может ли Codex CLI редактировать файлы и выполнять команды? + +## faq.items.2.answer + +Да. Он может анализировать и изменять файлы, запускать локальные инструменты и выполнять проверки в рамках выбранных вами разрешений. + +## faq.items.3.question + +Какие операционные системы поддерживает Codex CLI? + +## faq.items.3.answer + +В текущем манифесте указаны macOS, Windows и Linux, а также команды установки и запуска для каждой платформы. + +## faq.items.4.question + +Можно ли пользоваться Codex CLI бесплатно? + +## faq.items.4.answer + +Codex доступен в нескольких тарифах ChatGPT, включая Free, а также может работать с API key с оплатой по фактическому использованию. Лимиты и возможности зависят от тарифа. diff --git a/content/clis/tr/codex-cli.md b/content/clis/tr/codex-cli.md new file mode 100644 index 00000000..768d7e74 --- /dev/null +++ b/content/clis/tr/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI, kodu terminalinizden incelemek, düzenlemek ve çalıştırmak için OpenAI'ın resmi kodlama ajanıdır. + +## introduction + +Yerel deponuzda çalışır, modelleri ve izinleri denetlemenize olanak tanır; etkileşimli görevlerin yanı sıra tekrarlanabilir betikleri ve CI iş akışlarını da destekler. + +## capabilities.items.0.title + +Kod tabanınızı anlar + +## capabilities.items.0.description + +Proje dosyalarını inceler ve depo bağlamını kullanarak soruları yanıtlar. + +## capabilities.items.1.title + +Kodu düzenler ve hataları ayıklar + +## capabilities.items.1.description + +Hedefli değişiklikler yapar, sorunları bulur ve yerel ortamınızda kontrolleri çalıştırır. + +## capabilities.items.2.title + +Komutları çalıştırır ve otomasyon sağlar + +## capabilities.items.2.description + +Kabuk araçlarını etkileşimli olarak kullanın veya betiklerden ve CI işlem hatlarından codex exec çağırın. + +## verification.description + +Ürün bilgileri resmi belgeler, fiyatlandırma sayfaları ve kaynak depo ile karşılaştırılarak doğrulanır. + +## faq.items.0.question + +OpenAI'ın bir Codex CLI aracı var mı? + +## faq.items.0.answer + +Evet. Codex CLI, yerel depolardaki kodu incelemek, düzenlemek ve çalıştırmak için OpenAI'ın komut satırı kodlama ajanıdır. + +## faq.items.1.question + +Codex CLI'yi nasıl kurarım? + +## faq.items.1.answer + +Sisteminiz için gösterilen kurulum komutunu kullanın, ardından bir proje dizininden codex komutunu çalıştırın ve ChatGPT ya da bir API key ile oturum açın. + +## faq.items.2.question + +Codex CLI dosyaları düzenleyip komutları çalıştırabilir mi? + +## faq.items.2.answer + +Evet. Seçtiğiniz izinler kapsamında dosyaları inceleyip değiştirebilir, yerel araçları çalıştırabilir ve kontrolleri yürütebilir. + +## faq.items.3.question + +Codex CLI hangi işletim sistemlerini destekliyor? + +## faq.items.3.answer + +Güncel katalog kaydında macOS, Windows ve Linux ile her platforma ait kurulum ve başlatma komutları listelenir. + +## faq.items.4.question + +Codex CLI ücretsiz mi? + +## faq.items.4.answer + +Codex, Free dahil çeşitli ChatGPT planlarıyla kullanılabilir ve kullanıma dayalı faturalandırılan bir API key ile de çalışabilir. Sınırlar ve özellikler plana göre değişir. diff --git a/content/clis/zh-Hans/codex-cli.md b/content/clis/zh-Hans/codex-cli.md new file mode 100644 index 00000000..cbcd18dc --- /dev/null +++ b/content/clis/zh-Hans/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI 是 OpenAI 的官方命令行编码 Agent,可直接在终端中检查、编辑和运行代码。 + +## introduction + +它面向本地代码仓库工作,可控制模型与权限,既支持交互式任务,也支持可重复执行的脚本和 CI 工作流。 + +## capabilities.items.0.title + +理解代码库 + +## capabilities.items.0.description + +检查项目文件,并结合仓库上下文回答问题。 + +## capabilities.items.1.title + +编辑和调试代码 + +## capabilities.items.1.description + +完成聚焦的修改、定位问题,并在本地环境中运行检查。 + +## capabilities.items.2.title + +运行命令并自动化 + +## capabilities.items.2.description + +交互式使用 Shell 工具,或在脚本与 CI 流水线中调用 codex exec。 + +## verification.description + +产品事实已经对照官方文档、定价页面和上游代码仓库进行核验。 + +## faq.items.0.question + +OpenAI 有 Codex CLI 吗? + +## faq.items.0.answer + +有。Codex CLI 是 OpenAI 的命令行编码 Agent,可在本地仓库中检查、编辑和运行代码。 + +## faq.items.1.question + +如何安装 Codex CLI? + +## faq.items.1.answer + +使用页面中对应操作系统的安装命令,然后在项目目录中运行 codex,并使用 ChatGPT 或 API key 登录。 + +## faq.items.2.question + +Codex CLI 能编辑文件和运行命令吗? + +## faq.items.2.answer + +可以。它能在你授予的权限范围内检查和修改文件、运行本地工具并执行检查。 + +## faq.items.3.question + +Codex CLI 支持哪些操作系统? + +## faq.items.3.answer + +当前 manifest 列出了 macOS、Windows 和 Linux,并提供各平台的安装与启动命令。 + +## faq.items.4.question + +Codex CLI 免费吗? + +## faq.items.4.answer + +Codex 可通过包括免费版在内的多种 ChatGPT 套餐使用,也可使用按量计费的 API key。不同套餐的限额和功能有所不同。 diff --git a/content/clis/zh-Hant/codex-cli.md b/content/clis/zh-Hant/codex-cli.md new file mode 100644 index 00000000..35b02a87 --- /dev/null +++ b/content/clis/zh-Hant/codex-cli.md @@ -0,0 +1,75 @@ +## answer + +Codex CLI 是 OpenAI 的官方命令列程式設計 Agent,可直接在終端中檢查、編輯和執行程式碼。 + +## introduction + +它針對本機程式碼儲存庫工作,可控制模型與權限,既支援互動式任務,也支援可重複執行的指令碼和 CI 工作流程。 + +## capabilities.items.0.title + +理解程式碼庫 + +## capabilities.items.0.description + +檢查專案檔案,並結合儲存庫上下文回答問題。 + +## capabilities.items.1.title + +編輯和偵錯程式碼 + +## capabilities.items.1.description + +完成聚焦的修改、找出問題,並在本機環境中執行檢查。 + +## capabilities.items.2.title + +執行命令並自動化 + +## capabilities.items.2.description + +互動式使用 Shell 工具,或在指令碼與 CI 流程中呼叫 codex exec。 + +## verification.description + +產品事實已對照官方文件、定價頁面和上游程式碼儲存庫進行核驗。 + +## faq.items.0.question + +OpenAI 有 Codex CLI 嗎? + +## faq.items.0.answer + +有。Codex CLI 是 OpenAI 的命令列程式設計 Agent,可在本機儲存庫中檢查、編輯和執行程式碼。 + +## faq.items.1.question + +如何安裝 Codex CLI? + +## faq.items.1.answer + +使用頁面中對應作業系統的安裝命令,接著在專案目錄中執行 codex,並使用 ChatGPT 或 API key 登入。 + +## faq.items.2.question + +Codex CLI 能編輯檔案和執行命令嗎? + +## faq.items.2.answer + +可以。它能在你授予的權限範圍內檢查和修改檔案、執行本機工具並進行檢查。 + +## faq.items.3.question + +Codex CLI 支援哪些作業系統? + +## faq.items.3.answer + +目前 manifest 列出了 macOS、Windows 和 Linux,並提供各平台的安裝與啟動命令。 + +## faq.items.4.question + +Codex CLI 免費嗎? + +## faq.items.4.answer + +Codex 可透過包括免費版在內的多種 ChatGPT 方案使用,也可使用按量計費的 API key。不同方案的限額和功能有所不同。 diff --git a/data/$schemas/cli-landing-pages.schema.json b/data/$schemas/cli-landing-pages.schema.json new file mode 100644 index 00000000..ffd1fe73 --- /dev/null +++ b/data/$schemas/cli-landing-pages.schema.json @@ -0,0 +1,96 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://aicodingstack.io/schemas/data/cli-landing-pages.schema.json", + "title": "Generated CLI landing-page content", + "type": "object", + "required": ["en", "de", "es", "fr", "id", "ja", "ko", "pt", "ru", "tr", "zh-Hans", "zh-Hant"], + "properties": { + "en": { "$ref": "#/$defs/localePages" }, + "de": { "$ref": "#/$defs/localePages" }, + "es": { "$ref": "#/$defs/localePages" }, + "fr": { "$ref": "#/$defs/localePages" }, + "id": { "$ref": "#/$defs/localePages" }, + "ja": { "$ref": "#/$defs/localePages" }, + "ko": { "$ref": "#/$defs/localePages" }, + "pt": { "$ref": "#/$defs/localePages" }, + "ru": { "$ref": "#/$defs/localePages" }, + "tr": { "$ref": "#/$defs/localePages" }, + "zh-Hans": { "$ref": "#/$defs/localePages" }, + "zh-Hant": { "$ref": "#/$defs/localePages" } + }, + "additionalProperties": false, + "$defs": { + "nonEmptyString": { + "type": "string", + "minLength": 1 + }, + "landingItem": { + "type": "object", + "required": ["title", "description"], + "properties": { + "title": { "$ref": "#/$defs/nonEmptyString" }, + "description": { "$ref": "#/$defs/nonEmptyString" } + }, + "additionalProperties": false + }, + "faqItem": { + "type": "object", + "required": ["question", "answer"], + "properties": { + "question": { "$ref": "#/$defs/nonEmptyString" }, + "answer": { "$ref": "#/$defs/nonEmptyString" } + }, + "additionalProperties": false + }, + "content": { + "type": "object", + "required": ["answer", "introduction", "capabilities", "verification", "faq"], + "properties": { + "answer": { "$ref": "#/$defs/nonEmptyString" }, + "introduction": { "$ref": "#/$defs/nonEmptyString" }, + "capabilities": { + "type": "object", + "required": ["items"], + "properties": { + "items": { + "type": "array", + "minItems": 3, + "maxItems": 3, + "items": { "$ref": "#/$defs/landingItem" } + } + }, + "additionalProperties": false + }, + "verification": { + "type": "object", + "required": ["description"], + "properties": { + "description": { "$ref": "#/$defs/nonEmptyString" } + }, + "additionalProperties": false + }, + "faq": { + "type": "object", + "required": ["items"], + "properties": { + "items": { + "type": "array", + "minItems": 4, + "items": { "$ref": "#/$defs/faqItem" } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "localePages": { + "type": "object", + "minProperties": 1, + "patternProperties": { + "^[a-z0-9]+(?:-[a-z0-9]+)*$": { "$ref": "#/$defs/content" } + }, + "additionalProperties": false + } + } +} diff --git a/data/data-health.json b/data/data-health.json index 4d206a88..c8daec19 100644 --- a/data/data-health.json +++ b/data/data-health.json @@ -73,59 +73,59 @@ }, "translationsByLocale": { "de": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 39, - "matchingEnglishPercent": 8.3 + "matchingEnglishPercent": 8.1 }, "es": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 25, - "matchingEnglishPercent": 5.3 + "matchingEnglishPercent": 5.2 }, "fr": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 36, - "matchingEnglishPercent": 7.7 + "matchingEnglishPercent": 7.5 }, "id": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 30, - "matchingEnglishPercent": 6.4 + "matchingEnglishPercent": 6.2 }, "ja": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 23, - "matchingEnglishPercent": 4.9 + "matchingEnglishPercent": 4.8 }, "ko": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 23, - "matchingEnglishPercent": 4.9 + "matchingEnglishPercent": 4.8 }, "pt": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 31, - "matchingEnglishPercent": 6.6 + "matchingEnglishPercent": 6.4 }, "ru": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 23, - "matchingEnglishPercent": 4.9 + "matchingEnglishPercent": 4.8 }, "tr": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 26, - "matchingEnglishPercent": 5.5 + "matchingEnglishPercent": 5.4 }, "zh-Hans": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 22, - "matchingEnglishPercent": 4.7 + "matchingEnglishPercent": 4.6 }, "zh-Hant": { - "totalStrings": 470, + "totalStrings": 481, "matchingEnglish": 22, - "matchingEnglishPercent": 4.7 + "matchingEnglishPercent": 4.6 } }, "issues": [] diff --git a/data/generated/cli-landing-pages.json b/data/generated/cli-landing-pages.json new file mode 100644 index 00000000..9382a687 --- /dev/null +++ b/data/generated/cli-landing-pages.json @@ -0,0 +1,590 @@ +{ + "en": { + "codex-cli": { + "answer": "Codex CLI is OpenAI’s official coding agent for inspecting, editing, and running code from your terminal.", + "introduction": "It works against your local repository, lets you control models and permissions, and supports interactive tasks as well as repeatable scripts and CI workflows.", + "capabilities": { + "items": [ + { + "title": "Understand your codebase", + "description": "Inspect project files and answer questions with repository context." + }, + { + "title": "Edit and debug code", + "description": "Make focused changes, find issues, and run checks in your local environment." + }, + { + "title": "Run commands and automate", + "description": "Use shell tools interactively or call codex exec from scripts and CI pipelines." + } + ] + }, + "verification": { + "description": "Product facts are checked against official documentation, pricing pages, and the upstream repository." + }, + "faq": { + "items": [ + { + "question": "Does OpenAI have a Codex CLI?", + "answer": "Yes. Codex CLI is OpenAI’s command-line coding agent for inspecting, editing, and running code in local repositories." + }, + { + "question": "How do I install Codex CLI?", + "answer": "Use the install command shown for your operating system, then run codex from a project directory and sign in with ChatGPT or an API key." + }, + { + "question": "Can Codex CLI edit files and run commands?", + "answer": "Yes. It can inspect and modify files, run local tools, and execute checks subject to the permissions you choose." + }, + { + "question": "Which operating systems does Codex CLI support?", + "answer": "The current manifest lists macOS, Windows, and Linux, with installation and launch commands for each platform." + }, + { + "question": "Is Codex CLI free?", + "answer": "Codex is available through several ChatGPT plans, including Free, and can also use an API key with usage-based billing. Limits and features vary by plan." + } + ] + } + } + }, + "de": { + "codex-cli": { + "answer": "Codex CLI ist OpenAIs offizieller Coding-Agent zum Prüfen, Bearbeiten und Ausführen von Code direkt im Terminal.", + "introduction": "Er arbeitet mit lokalen Projekten, bietet Kontrolle über Modelle und Berechtigungen und unterstützt interaktive Aufgaben sowie wiederholbare Skripte und CI-Workflows.", + "capabilities": { + "items": [ + { + "title": "Codebasis verstehen", + "description": "Projektdateien prüfen und Fragen im Kontext des Projekts beantworten." + }, + { + "title": "Code bearbeiten und debuggen", + "description": "Gezielte Änderungen vornehmen, Probleme finden und lokale Prüfungen ausführen." + }, + { + "title": "Befehle ausführen und automatisieren", + "description": "Shell-Werkzeuge interaktiv nutzen oder codex exec aus Skripten und CI-Pipelines aufrufen." + } + ] + }, + "verification": { + "description": "Produktangaben werden mit offizieller Dokumentation, Preisseiten und dem Upstream-Repository abgeglichen." + }, + "faq": { + "items": [ + { + "question": "Gibt es eine Codex CLI von OpenAI?", + "answer": "Ja. Codex CLI ist OpenAIs Kommandozeilen-Agent zum Prüfen, Bearbeiten und Ausführen von Code in lokalen Projekten." + }, + { + "question": "Wie installiere ich Codex CLI?", + "answer": "Nutzen Sie den Installationsbefehl für Ihr Betriebssystem, führen Sie codex im Projektverzeichnis aus und melden Sie sich mit ChatGPT oder einem API-Schlüssel an." + }, + { + "question": "Kann Codex CLI Dateien ändern und Befehle ausführen?", + "answer": "Ja. Im Rahmen der gewählten Berechtigungen kann Codex Dateien prüfen und ändern, lokale Werkzeuge starten und Tests ausführen." + }, + { + "question": "Welche Betriebssysteme unterstützt Codex CLI?", + "answer": "Das aktuelle Manifest nennt macOS, Windows und Linux samt Installations- und Startbefehlen." + }, + { + "question": "Ist Codex CLI kostenlos?", + "answer": "Codex ist in mehreren ChatGPT-Tarifen einschließlich Free verfügbar und kann mit nutzungsabhängig abgerechnetem API-Schlüssel verwendet werden. Limits und Funktionen unterscheiden sich." + } + ] + } + } + }, + "es": { + "codex-cli": { + "answer": "Codex CLI es el agente de programación oficial de OpenAI para inspeccionar, editar y ejecutar código desde la terminal.", + "introduction": "Trabaja con tu repositorio local, te permite controlar los modelos y los permisos, y admite tanto tareas interactivas como scripts repetibles y flujos de trabajo de CI.", + "capabilities": { + "items": [ + { + "title": "Comprender tu base de código", + "description": "Inspecciona los archivos del proyecto y responde preguntas teniendo en cuenta el contexto del repositorio." + }, + { + "title": "Editar y depurar código", + "description": "Realiza cambios específicos, encuentra problemas y ejecuta comprobaciones en tu entorno local." + }, + { + "title": "Ejecutar comandos y automatizar", + "description": "Usa herramientas de shell de forma interactiva o llama a codex exec desde scripts y canalizaciones de CI." + } + ] + }, + "verification": { + "description": "Los datos del producto se contrastan con la documentación oficial, las páginas de precios y el repositorio original." + }, + "faq": { + "items": [ + { + "question": "¿OpenAI ofrece Codex CLI?", + "answer": "Sí. Codex CLI es el agente de programación de línea de comandos de OpenAI para inspeccionar, editar y ejecutar código en repositorios locales." + }, + { + "question": "¿Cómo instalo Codex CLI?", + "answer": "Usa el comando de instalación indicado para tu sistema operativo, ejecuta codex desde el directorio de un proyecto e inicia sesión con ChatGPT o una API key." + }, + { + "question": "¿Codex CLI puede editar archivos y ejecutar comandos?", + "answer": "Sí. Puede inspeccionar y modificar archivos, usar herramientas locales y ejecutar comprobaciones de acuerdo con los permisos que elijas." + }, + { + "question": "¿Qué sistemas operativos admite Codex CLI?", + "answer": "El manifest actual incluye macOS, Windows y Linux, con comandos de instalación y ejecución para cada plataforma." + }, + { + "question": "¿Codex CLI es gratuito?", + "answer": "Codex está disponible con varios planes de ChatGPT, incluido Free, y también puede usar una API key con facturación por uso. Los límites y las funciones varían según el plan." + } + ] + } + } + }, + "fr": { + "codex-cli": { + "answer": "Codex CLI est l’agent de programmation officiel d’OpenAI pour inspecter, modifier et exécuter du code depuis votre terminal.", + "introduction": "Il travaille sur votre dépôt local, vous permet de contrôler les modèles et les autorisations, et prend en charge aussi bien les tâches interactives que les scripts reproductibles et les workflows de CI.", + "capabilities": { + "items": [ + { + "title": "Comprendre votre base de code", + "description": "Inspectez les fichiers du projet et obtenez des réponses qui tiennent compte du contexte du dépôt." + }, + { + "title": "Modifier et déboguer le code", + "description": "Apportez des modifications ciblées, détectez les problèmes et lancez des vérifications dans votre environnement local." + }, + { + "title": "Exécuter des commandes et automatiser", + "description": "Utilisez les outils du shell de manière interactive ou appelez codex exec depuis des scripts et des pipelines de CI." + } + ] + }, + "verification": { + "description": "Les informations sur le produit sont vérifiées à partir de la documentation officielle, des pages tarifaires et du dépôt d’origine." + }, + "faq": { + "items": [ + { + "question": "OpenAI propose-t-il Codex CLI ?", + "answer": "Oui. Codex CLI est l’agent de programmation en ligne de commande d’OpenAI pour inspecter, modifier et exécuter du code dans des dépôts locaux." + }, + { + "question": "Comment installer Codex CLI ?", + "answer": "Utilisez la commande d’installation indiquée pour votre système d’exploitation, puis lancez codex depuis le répertoire d’un projet et connectez-vous avec ChatGPT ou une API key." + }, + { + "question": "Codex CLI peut-il modifier des fichiers et exécuter des commandes ?", + "answer": "Oui. Il peut inspecter et modifier des fichiers, utiliser des outils locaux et lancer des vérifications selon les autorisations que vous choisissez." + }, + { + "question": "Quels systèmes d’exploitation Codex CLI prend-il en charge ?", + "answer": "Le manifest actuel répertorie macOS, Windows et Linux, avec les commandes d’installation et de lancement pour chaque plateforme." + }, + { + "question": "Codex CLI est-il gratuit ?", + "answer": "Codex est proposé dans plusieurs offres ChatGPT, dont Free, et peut aussi utiliser une API key avec une facturation à l’usage. Les limites et les fonctionnalités varient selon l’offre." + } + ] + } + } + }, + "id": { + "codex-cli": { + "answer": "Codex CLI adalah agen coding resmi OpenAI untuk memeriksa, mengedit, dan menjalankan kode dari terminal Anda.", + "introduction": "Codex CLI bekerja pada repositori lokal, memungkinkan Anda mengendalikan model dan izin, serta mendukung tugas interaktif, skrip berulang, dan alur kerja CI.", + "capabilities": { + "items": [ + { + "title": "Memahami basis kode Anda", + "description": "Periksa file proyek dan jawab pertanyaan dengan mempertimbangkan konteks repositori." + }, + { + "title": "Mengedit dan men-debug kode", + "description": "Lakukan perubahan terarah, temukan masalah, dan jalankan pemeriksaan di lingkungan lokal Anda." + }, + { + "title": "Menjalankan perintah dan mengotomatiskan tugas", + "description": "Gunakan alat shell secara interaktif atau panggil codex exec dari skrip dan pipeline CI." + } + ] + }, + "verification": { + "description": "Fakta produk diperiksa berdasarkan dokumentasi resmi, halaman harga, dan repositori sumber." + }, + "faq": { + "items": [ + { + "question": "Apakah OpenAI memiliki Codex CLI?", + "answer": "Ya. Codex CLI adalah agen coding baris perintah OpenAI untuk memeriksa, mengedit, dan menjalankan kode dalam repositori lokal." + }, + { + "question": "Bagaimana cara menginstal Codex CLI?", + "answer": "Gunakan perintah instalasi yang ditampilkan untuk sistem operasi Anda, lalu jalankan codex dari direktori proyek dan masuk dengan ChatGPT atau API key." + }, + { + "question": "Apakah Codex CLI dapat mengedit file dan menjalankan perintah?", + "answer": "Ya. Codex CLI dapat memeriksa dan mengubah file, menjalankan alat lokal, serta melakukan pemeriksaan sesuai izin yang Anda pilih." + }, + { + "question": "Sistem operasi apa saja yang didukung Codex CLI?", + "answer": "Manifest saat ini mencantumkan macOS, Windows, dan Linux, beserta perintah instalasi dan peluncuran untuk setiap platform." + }, + { + "question": "Apakah Codex CLI gratis?", + "answer": "Codex tersedia melalui beberapa paket ChatGPT, termasuk Free, dan juga dapat menggunakan API key dengan penagihan berbasis pemakaian. Batas dan fitur berbeda-beda menurut paket." + } + ] + } + } + }, + "ja": { + "codex-cli": { + "answer": "Codex CLI は、ターミナルからコードの調査、編集、実行を行える OpenAI 公式のコーディングエージェントです。", + "introduction": "ローカルリポジトリを対象に動作し、モデルと権限を管理でき、対話型タスクに加えて反復可能なスクリプトや CI ワークフローにも対応します。", + "capabilities": { + "items": [ + { + "title": "コードベースを理解する", + "description": "プロジェクトのファイルを調査し、リポジトリの文脈に基づいて質問に回答します。" + }, + { + "title": "コードを編集・デバッグする", + "description": "目的を絞った変更を行い、問題を見つけ、ローカル環境でチェックを実行します。" + }, + { + "title": "コマンドを実行し、自動化する", + "description": "シェルツールを対話的に使用したり、スクリプトや CI パイプラインから codex exec を呼び出したりできます。" + } + ] + }, + "verification": { + "description": "製品情報は、公式ドキュメント、料金ページ、アップストリームリポジトリと照合しています。" + }, + "faq": { + "items": [ + { + "question": "OpenAI に Codex CLI はありますか?", + "answer": "はい。Codex CLI は、ローカルリポジトリ内のコードを調査、編集、実行するための OpenAI のコマンドライン型コーディングエージェントです。" + }, + { + "question": "Codex CLI はどのようにインストールしますか?", + "answer": "お使いのオペレーティングシステム向けに表示されたインストールコマンドを使用し、プロジェクトディレクトリで codex を実行して、ChatGPT または API key でサインインします。" + }, + { + "question": "Codex CLI はファイルの編集やコマンドの実行ができますか?", + "answer": "はい。選択した権限の範囲内で、ファイルの調査と変更、ローカルツールの実行、チェックの実施が可能です。" + }, + { + "question": "Codex CLI はどのオペレーティングシステムに対応していますか?", + "answer": "現在のマニフェストには macOS、Windows、Linux が記載されており、各プラットフォーム向けのインストールコマンドと起動コマンドも掲載されています。" + }, + { + "question": "Codex CLI は無料ですか?", + "answer": "Codex は Free を含む複数の ChatGPT プランで利用でき、従量課金の API key も使用できます。利用上限と機能はプランによって異なります。" + } + ] + } + } + }, + "ko": { + "codex-cli": { + "answer": "Codex CLI는 터미널에서 코드를 살펴보고 편집하며 실행할 수 있는 OpenAI의 공식 코딩 에이전트입니다.", + "introduction": "로컬 저장소를 대상으로 작동하며 모델과 권한을 제어할 수 있고, 대화형 작업뿐 아니라 반복 가능한 스크립트와 CI 워크플로도 지원합니다.", + "capabilities": { + "items": [ + { + "title": "코드베이스 이해", + "description": "프로젝트 파일을 살펴보고 저장소의 맥락을 바탕으로 질문에 답합니다." + }, + { + "title": "코드 편집 및 디버깅", + "description": "필요한 부분을 정확히 변경하고 문제를 찾아 로컬 환경에서 검사를 실행합니다." + }, + { + "title": "명령 실행 및 자동화", + "description": "셸 도구를 대화형으로 사용하거나 스크립트와 CI 파이프라인에서 codex exec를 호출할 수 있습니다." + } + ] + }, + "verification": { + "description": "제품 정보는 공식 문서, 가격 페이지, 업스트림 저장소와 대조해 확인합니다." + }, + "faq": { + "items": [ + { + "question": "OpenAI에서 Codex CLI를 제공하나요?", + "answer": "예. Codex CLI는 로컬 저장소의 코드를 살펴보고 편집하며 실행하기 위한 OpenAI의 명령줄 코딩 에이전트입니다." + }, + { + "question": "Codex CLI는 어떻게 설치하나요?", + "answer": "사용 중인 운영체제에 표시된 설치 명령을 사용한 다음, 프로젝트 디렉터리에서 codex를 실행하고 ChatGPT 또는 API key로 로그인하세요." + }, + { + "question": "Codex CLI로 파일을 편집하고 명령을 실행할 수 있나요?", + "answer": "예. 선택한 권한 범위 안에서 파일을 살펴보고 수정하며, 로컬 도구와 검사를 실행할 수 있습니다." + }, + { + "question": "Codex CLI는 어떤 운영체제를 지원하나요?", + "answer": "현재 매니페스트에는 macOS, Windows, Linux와 각 플랫폼의 설치 및 실행 명령이 등록되어 있습니다." + }, + { + "question": "Codex CLI는 무료인가요?", + "answer": "Codex는 Free를 포함한 여러 ChatGPT 플랜에서 사용할 수 있으며, 사용량 기반 요금이 적용되는 API key도 이용할 수 있습니다. 한도와 기능은 플랜에 따라 다릅니다." + } + ] + } + } + }, + "pt": { + "codex-cli": { + "answer": "O Codex CLI é o agente de programação oficial da OpenAI para inspecionar, editar e executar código pelo terminal.", + "introduction": "Ele trabalha no seu repositório local, permite controlar modelos e permissões e oferece suporte tanto a tarefas interativas quanto a scripts repetíveis e fluxos de CI.", + "capabilities": { + "items": [ + { + "title": "Entender sua base de código", + "description": "Inspecione os arquivos do projeto e responda a perguntas usando o contexto do repositório." + }, + { + "title": "Editar e depurar código", + "description": "Faça alterações pontuais, encontre problemas e execute verificações no seu ambiente local." + }, + { + "title": "Executar comandos e automatizar", + "description": "Use ferramentas de shell de forma interativa ou chame codex exec em scripts e pipelines de CI." + } + ] + }, + "verification": { + "description": "Os dados do produto são conferidos com a documentação oficial, as páginas de preços e o repositório original." + }, + "faq": { + "items": [ + { + "question": "A OpenAI oferece o Codex CLI?", + "answer": "Sim. O Codex CLI é o agente de programação por linha de comando da OpenAI para inspecionar, editar e executar código em repositórios locais." + }, + { + "question": "Como instalo o Codex CLI?", + "answer": "Use o comando de instalação exibido para o seu sistema operacional. Depois, execute codex em um diretório de projeto e entre com o ChatGPT ou uma API key." + }, + { + "question": "O Codex CLI pode editar arquivos e executar comandos?", + "answer": "Sim. Ele pode inspecionar e modificar arquivos, executar ferramentas locais e realizar verificações dentro das permissões que você escolher." + }, + { + "question": "Quais sistemas operacionais o Codex CLI suporta?", + "answer": "O manifesto atual lista macOS, Windows e Linux, com comandos de instalação e inicialização para cada plataforma." + }, + { + "question": "O Codex CLI é gratuito?", + "answer": "O Codex está disponível em vários planos do ChatGPT, inclusive o Free, e também pode usar uma API key com cobrança por uso. Os limites e recursos variam conforme o plano." + } + ] + } + } + }, + "ru": { + "codex-cli": { + "answer": "Codex CLI — официальный агент OpenAI для программирования, который позволяет анализировать и редактировать код, а также запускать его из терминала.", + "introduction": "Он работает с вашим локальным репозиторием, позволяет управлять моделями и разрешениями и поддерживает как интерактивные задачи, так и повторяемые сценарии и процессы CI.", + "capabilities": { + "items": [ + { + "title": "Понимать вашу кодовую базу", + "description": "Анализировать файлы проекта и отвечать на вопросы с учётом контекста репозитория." + }, + { + "title": "Редактировать и отлаживать код", + "description": "Вносить точечные изменения, находить проблемы и запускать проверки в вашей локальной среде." + }, + { + "title": "Выполнять команды и автоматизировать задачи", + "description": "Использовать инструменты командной оболочки в интерактивном режиме или вызывать codex exec из сценариев и конвейеров CI." + } + ] + }, + "verification": { + "description": "Сведения о продукте сверяются с официальной документацией, страницами с ценами и исходным репозиторием." + }, + "faq": { + "items": [ + { + "question": "Есть ли у OpenAI Codex CLI?", + "answer": "Да. Codex CLI — агент OpenAI для программирования в командной строке, который анализирует, редактирует и запускает код в локальных репозиториях." + }, + { + "question": "Как установить Codex CLI?", + "answer": "Выполните команду установки для своей операционной системы, затем запустите codex из каталога проекта и войдите с помощью ChatGPT или API key." + }, + { + "question": "Может ли Codex CLI редактировать файлы и выполнять команды?", + "answer": "Да. Он может анализировать и изменять файлы, запускать локальные инструменты и выполнять проверки в рамках выбранных вами разрешений." + }, + { + "question": "Какие операционные системы поддерживает Codex CLI?", + "answer": "В текущем манифесте указаны macOS, Windows и Linux, а также команды установки и запуска для каждой платформы." + }, + { + "question": "Можно ли пользоваться Codex CLI бесплатно?", + "answer": "Codex доступен в нескольких тарифах ChatGPT, включая Free, а также может работать с API key с оплатой по фактическому использованию. Лимиты и возможности зависят от тарифа." + } + ] + } + } + }, + "tr": { + "codex-cli": { + "answer": "Codex CLI, kodu terminalinizden incelemek, düzenlemek ve çalıştırmak için OpenAI'ın resmi kodlama ajanıdır.", + "introduction": "Yerel deponuzda çalışır, modelleri ve izinleri denetlemenize olanak tanır; etkileşimli görevlerin yanı sıra tekrarlanabilir betikleri ve CI iş akışlarını da destekler.", + "capabilities": { + "items": [ + { + "title": "Kod tabanınızı anlar", + "description": "Proje dosyalarını inceler ve depo bağlamını kullanarak soruları yanıtlar." + }, + { + "title": "Kodu düzenler ve hataları ayıklar", + "description": "Hedefli değişiklikler yapar, sorunları bulur ve yerel ortamınızda kontrolleri çalıştırır." + }, + { + "title": "Komutları çalıştırır ve otomasyon sağlar", + "description": "Kabuk araçlarını etkileşimli olarak kullanın veya betiklerden ve CI işlem hatlarından codex exec çağırın." + } + ] + }, + "verification": { + "description": "Ürün bilgileri resmi belgeler, fiyatlandırma sayfaları ve kaynak depo ile karşılaştırılarak doğrulanır." + }, + "faq": { + "items": [ + { + "question": "OpenAI'ın bir Codex CLI aracı var mı?", + "answer": "Evet. Codex CLI, yerel depolardaki kodu incelemek, düzenlemek ve çalıştırmak için OpenAI'ın komut satırı kodlama ajanıdır." + }, + { + "question": "Codex CLI'yi nasıl kurarım?", + "answer": "Sisteminiz için gösterilen kurulum komutunu kullanın, ardından bir proje dizininden codex komutunu çalıştırın ve ChatGPT ya da bir API key ile oturum açın." + }, + { + "question": "Codex CLI dosyaları düzenleyip komutları çalıştırabilir mi?", + "answer": "Evet. Seçtiğiniz izinler kapsamında dosyaları inceleyip değiştirebilir, yerel araçları çalıştırabilir ve kontrolleri yürütebilir." + }, + { + "question": "Codex CLI hangi işletim sistemlerini destekliyor?", + "answer": "Güncel katalog kaydında macOS, Windows ve Linux ile her platforma ait kurulum ve başlatma komutları listelenir." + }, + { + "question": "Codex CLI ücretsiz mi?", + "answer": "Codex, Free dahil çeşitli ChatGPT planlarıyla kullanılabilir ve kullanıma dayalı faturalandırılan bir API key ile de çalışabilir. Sınırlar ve özellikler plana göre değişir." + } + ] + } + } + }, + "zh-Hans": { + "codex-cli": { + "answer": "Codex CLI 是 OpenAI 的官方命令行编码 Agent,可直接在终端中检查、编辑和运行代码。", + "introduction": "它面向本地代码仓库工作,可控制模型与权限,既支持交互式任务,也支持可重复执行的脚本和 CI 工作流。", + "capabilities": { + "items": [ + { + "title": "理解代码库", + "description": "检查项目文件,并结合仓库上下文回答问题。" + }, + { + "title": "编辑和调试代码", + "description": "完成聚焦的修改、定位问题,并在本地环境中运行检查。" + }, + { + "title": "运行命令并自动化", + "description": "交互式使用 Shell 工具,或在脚本与 CI 流水线中调用 codex exec。" + } + ] + }, + "verification": { + "description": "产品事实已经对照官方文档、定价页面和上游代码仓库进行核验。" + }, + "faq": { + "items": [ + { + "question": "OpenAI 有 Codex CLI 吗?", + "answer": "有。Codex CLI 是 OpenAI 的命令行编码 Agent,可在本地仓库中检查、编辑和运行代码。" + }, + { + "question": "如何安装 Codex CLI?", + "answer": "使用页面中对应操作系统的安装命令,然后在项目目录中运行 codex,并使用 ChatGPT 或 API key 登录。" + }, + { + "question": "Codex CLI 能编辑文件和运行命令吗?", + "answer": "可以。它能在你授予的权限范围内检查和修改文件、运行本地工具并执行检查。" + }, + { + "question": "Codex CLI 支持哪些操作系统?", + "answer": "当前 manifest 列出了 macOS、Windows 和 Linux,并提供各平台的安装与启动命令。" + }, + { + "question": "Codex CLI 免费吗?", + "answer": "Codex 可通过包括免费版在内的多种 ChatGPT 套餐使用,也可使用按量计费的 API key。不同套餐的限额和功能有所不同。" + } + ] + } + } + }, + "zh-Hant": { + "codex-cli": { + "answer": "Codex CLI 是 OpenAI 的官方命令列程式設計 Agent,可直接在終端中檢查、編輯和執行程式碼。", + "introduction": "它針對本機程式碼儲存庫工作,可控制模型與權限,既支援互動式任務,也支援可重複執行的指令碼和 CI 工作流程。", + "capabilities": { + "items": [ + { + "title": "理解程式碼庫", + "description": "檢查專案檔案,並結合儲存庫上下文回答問題。" + }, + { + "title": "編輯和偵錯程式碼", + "description": "完成聚焦的修改、找出問題,並在本機環境中執行檢查。" + }, + { + "title": "執行命令並自動化", + "description": "互動式使用 Shell 工具,或在指令碼與 CI 流程中呼叫 codex exec。" + } + ] + }, + "verification": { + "description": "產品事實已對照官方文件、定價頁面和上游程式碼儲存庫進行核驗。" + }, + "faq": { + "items": [ + { + "question": "OpenAI 有 Codex CLI 嗎?", + "answer": "有。Codex CLI 是 OpenAI 的命令列程式設計 Agent,可在本機儲存庫中檢查、編輯和執行程式碼。" + }, + { + "question": "如何安裝 Codex CLI?", + "answer": "使用頁面中對應作業系統的安裝命令,接著在專案目錄中執行 codex,並使用 ChatGPT 或 API key 登入。" + }, + { + "question": "Codex CLI 能編輯檔案和執行命令嗎?", + "answer": "可以。它能在你授予的權限範圍內檢查和修改檔案、執行本機工具並進行檢查。" + }, + { + "question": "Codex CLI 支援哪些作業系統?", + "answer": "目前 manifest 列出了 macOS、Windows 和 Linux,並提供各平台的安裝與啟動命令。" + }, + { + "question": "Codex CLI 免費嗎?", + "answer": "Codex 可透過包括免費版在內的多種 ChatGPT 方案使用,也可使用按量計費的 API key。不同方案的限額和功能有所不同。" + } + ] + } + } + } +} diff --git a/docs/DATA-HEALTH.md b/docs/DATA-HEALTH.md index 0a22a955..8c371630 100644 --- a/docs/DATA-HEALTH.md +++ b/docs/DATA-HEALTH.md @@ -37,17 +37,17 @@ Exact English matches are a triage signal; product names and technical terms can | Locale | Comparable strings | Exact English matches | Match rate | | --- | ---: | ---: | ---: | -| de | 470 | 39 | 8.3% | -| es | 470 | 25 | 5.3% | -| fr | 470 | 36 | 7.7% | -| id | 470 | 30 | 6.4% | -| ja | 470 | 23 | 4.9% | -| ko | 470 | 23 | 4.9% | -| pt | 470 | 31 | 6.6% | -| ru | 470 | 23 | 4.9% | -| tr | 470 | 26 | 5.5% | -| zh-Hans | 470 | 22 | 4.7% | -| zh-Hant | 470 | 22 | 4.7% | +| de | 481 | 39 | 8.1% | +| es | 481 | 25 | 5.2% | +| fr | 481 | 36 | 7.5% | +| id | 481 | 30 | 6.2% | +| ja | 481 | 23 | 4.8% | +| ko | 481 | 23 | 4.8% | +| pt | 481 | 31 | 6.4% | +| ru | 481 | 23 | 4.8% | +| tr | 481 | 26 | 5.4% | +| zh-Hans | 481 | 22 | 4.6% | +| zh-Hant | 481 | 22 | 4.6% | ## Backlog by Issue Type diff --git a/manifests/$schemas/cli.schema.json b/manifests/$schemas/cli.schema.json index 33475a5e..de4bebc7 100644 --- a/manifests/$schemas/cli.schema.json +++ b/manifests/$schemas/cli.schema.json @@ -8,6 +8,10 @@ { "type": "object", "properties": { + "landingPage": { + "type": "boolean", + "description": "Whether this CLI uses the search-focused landing page template" + }, "latestVersion": { "type": "string", "minLength": 1, diff --git a/manifests/$schemas/ref/entity.schema.json b/manifests/$schemas/ref/entity.schema.json index e1b2adad..df51aa41 100644 --- a/manifests/$schemas/ref/entity.schema.json +++ b/manifests/$schemas/ref/entity.schema.json @@ -80,7 +80,9 @@ "type": "array", "description": "Manifest fields supported by this source; omit when it supports the whole record", "items": { - "type": "string" + "type": "string", + "minLength": 1, + "pattern": "^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$" }, "minItems": 1, "uniqueItems": true diff --git a/manifests/clis/codex-cli.json b/manifests/clis/codex-cli.json index c61b3ca0..2e30c36d 100644 --- a/manifests/clis/codex-cli.json +++ b/manifests/clis/codex-cli.json @@ -40,9 +40,10 @@ } }, "verified": true, - "lastVerifiedAt": "2026-07-31", + "lastVerifiedAt": "2026-08-01", "verifiedBy": "codex-agent", "confidence": "high", + "landingPage": true, "websiteUrl": "https://openai.com/codex", "docsUrl": "https://developers.openai.com/codex/cli", "vendor": "OpenAI", @@ -65,6 +66,13 @@ "per": "month", "category": "Individual" }, + { + "name": "ChatGPT Go", + "value": 8, + "currency": "USD", + "per": "month", + "category": "Individual" + }, { "name": "ChatGPT Plus", "value": 20, @@ -73,21 +81,35 @@ "category": "Individual" }, { - "name": "ChatGPT Pro", - "value": 200, + "name": "ChatGPT Pro (from)", + "value": 100, "currency": "USD", "per": "month", "category": "Individual" }, { - "name": "ChatGPT Business", - "value": 30, + "name": "API Key", + "value": null, + "currency": null, + "per": "usage-based", + "category": "Developer" + }, + { + "name": "ChatGPT Business (annual)", + "value": 20, + "currency": "USD", + "per": "user/month", + "category": "Business" + }, + { + "name": "ChatGPT Business (monthly)", + "value": 25, "currency": "USD", "per": "user/month", "category": "Business" }, { - "name": "ChatGPT Enterprise", + "name": "ChatGPT Enterprise & Edu", "value": null, "currency": null, "per": "custom", @@ -97,7 +119,7 @@ "resourceUrls": { "download": "https://developers.openai.com/codex/cli", "changelog": "https://github.com/openai/codex/releases", - "pricing": "https://chatgpt.com/codex/pricing/", + "pricing": "https://developers.openai.com/codex/pricing", "issue": "https://github.com/openai/codex/issues" }, "communityUrls": { @@ -140,18 +162,31 @@ } ], "sources": [ + { + "url": "https://developers.openai.com/codex/cli", + "title": "Codex CLI documentation", + "fields": ["description", "docsUrl", "platforms", "resourceUrls.download"] + }, { "url": "https://github.com/openai/codex", - "title": "Codex CLI github community", - "fields": ["githubUrl", "license", "sourceCode", "communityUrls.github"] + "title": "OpenAI Codex on GitHub", + "fields": [ + "communityUrls.github", + "githubUrl", + "license", + "releaseTracking", + "resourceUrls.changelog", + "resourceUrls.issue", + "sourceCode" + ] }, { "url": "https://openai.com/news", - "title": "Codex CLI blog community", + "title": "OpenAI News", "fields": ["communityUrls.blog"] }, { - "url": "https://chatgpt.com/codex/pricing/", + "url": "https://developers.openai.com/codex/pricing", "title": "Codex pricing", "fields": ["pricing", "resourceUrls.pricing"] } diff --git a/scripts/generate/generate-cli-landing-pages.ts b/scripts/generate/generate-cli-landing-pages.ts new file mode 100644 index 00000000..1abaa46c --- /dev/null +++ b/scripts/generate/generate-cli-landing-pages.ts @@ -0,0 +1,70 @@ +#!/usr/bin/env node + +import fs from 'node:fs' +import path from 'node:path' +import { locales } from '../../src/i18n/config' +import { + type CLILandingContent, + parseCLILandingMarkdown, +} from '../../src/lib/content/cli-landing-markdown' + +interface CLIManifestSummary { + id: string + landingPage?: boolean +} + +const rootDir = path.resolve(import.meta.dirname, '../..') +const manifestDir = path.join(rootDir, 'manifests', 'clis') +const contentDir = path.join(rootDir, 'content', 'clis') +const outputFile = path.join(rootDir, 'data', 'generated', 'cli-landing-pages.json') + +const landingPageIds = fs + .readdirSync(manifestDir) + .filter(file => file.endsWith('.json')) + .map( + file => JSON.parse(fs.readFileSync(path.join(manifestDir, file), 'utf8')) as CLIManifestSummary + ) + .filter(manifest => manifest.landingPage) + .map(manifest => manifest.id) + .sort() + +if (landingPageIds.length === 0) { + throw new Error('No CLI manifests have landingPage enabled') +} + +const generated = Object.fromEntries( + locales.map(locale => { + const localeDirectory = path.join(contentDir, locale) + const expectedFiles = new Set(landingPageIds.map(id => `${id}.md`)) + const actualFiles = fs.existsSync(localeDirectory) + ? fs + .readdirSync(localeDirectory) + .filter(file => file.endsWith('.md')) + .sort() + : [] + const unexpectedFiles = actualFiles.filter(file => !expectedFiles.has(file)) + + if (unexpectedFiles.length > 0) { + throw new Error(`${locale}: landing-page content has no enabled manifest: ${unexpectedFiles}`) + } + + const localeContent: Record = {} + for (const id of landingPageIds) { + const filePath = path.join(localeDirectory, `${id}.md`) + if (!fs.existsSync(filePath)) { + throw new Error(`${locale}: missing CLI landing-page content for ${id}`) + } + + localeContent[id] = parseCLILandingMarkdown( + fs.readFileSync(filePath, 'utf8'), + path.relative(rootDir, filePath) + ) + } + + return [locale, localeContent] + }) +) + +fs.mkdirSync(path.dirname(outputFile), { recursive: true }) +fs.writeFileSync(outputFile, `${JSON.stringify(generated, null, 2)}\n`) +console.log(`✓ Generated CLI landing-page content (${locales.length} locales)`) diff --git a/scripts/validate/lib/i18n-placeholders.ts b/scripts/validate/lib/i18n-placeholders.ts index 5e150d95..e85df344 100644 --- a/scripts/validate/lib/i18n-placeholders.ts +++ b/scripts/validate/lib/i18n-placeholders.ts @@ -30,6 +30,7 @@ const URL_OR_PATH_PREFIX = /^(?:https?:\/\/|mailto:|tel:|\/|#)/i const PLACEHOLDER_PATTERN = /\{[^{}]+\}/g const ENGLISH_WORD_PATTERN = /[A-Za-z][A-Za-z'’-]*/g const MARKDOWN_PREFIX = /^(?:#{1,6}\s+|>\s*|[-+*]\s+|\d+[.)]\s+)/ +const KEYED_CONTENT_HEADING = /^##\s+[a-z][a-zA-Z0-9]*(?:\.(?:[a-zA-Z][a-zA-Z0-9]*|\d+))*\s*$/ function normalizeText(value: string): string { return value.trim().replace(/\s+/g, ' ') @@ -98,6 +99,10 @@ function listFiles(directory: string, extension: string, root = directory): stri return files.sort() } +function listMarkdownFiles(directory: string): string[] { + return [...listFiles(directory, '.md'), ...listFiles(directory, '.mdx')].sort() +} + function readJson(filePath: string): unknown { return JSON.parse(fs.readFileSync(filePath, 'utf8')) as unknown } @@ -216,6 +221,11 @@ export function extractMdxProseUnits(content: string): Map { continue } + if (KEYED_CONTENT_HEADING.test(trimmed)) { + finishParagraph() + continue + } + if (!trimmed) { finishParagraph() continue @@ -250,7 +260,7 @@ export function findContentExactEnglishCandidates( for (const contentType of contentTypes) { const englishDirectory = path.join(contentDirectory, contentType, defaultLocale) - for (const relativeFile of listFiles(englishDirectory, '.mdx')) { + for (const relativeFile of listMarkdownFiles(englishDirectory)) { const englishMdx = matter.read(path.join(englishDirectory, relativeFile)) const englishFrontmatter = new Map() collectStringLeaves(englishMdx.data, '', englishFrontmatter) diff --git a/src/app/[locale]/clis/[slug]/page.tsx b/src/app/[locale]/clis/[slug]/page.tsx index 95c41f0f..06b5b6d5 100644 --- a/src/app/[locale]/clis/[slug]/page.tsx +++ b/src/app/[locale]/clis/[slug]/page.tsx @@ -1,7 +1,9 @@ import { notFound } from 'next/navigation' import { getTranslations } from 'next-intl/server' +import { JsonLd } from '@/components/JsonLd' import { BackToNavigation } from '@/components/navigation/BackToNavigation' import { Breadcrumb } from '@/components/navigation/Breadcrumb' +import { CLILandingPage } from '@/components/product/CLILandingPage' import { CommunityLinks } from '@/components/product/CommunityLinks' import { ProductCommands } from '@/components/product/ProductCommands' import { ProductHero } from '@/components/product/ProductHero' @@ -10,12 +12,13 @@ import { RelatedProducts } from '@/components/product/RelatedProducts' import { ResourceLinks } from '@/components/product/ResourceLinks' import type { Locale } from '@/i18n/config' import { PageLayout } from '@/layouts/PageLayout' +import { getCLILandingContent } from '@/lib/content/cli-landing-pages' import { getCLI, getRelatedProducts } from '@/lib/data/fetchers' import { clisData as clis } from '@/lib/generated' import { getGithubStars } from '@/lib/generated/github-stars' import { translateLicenseText } from '@/lib/license' import { generateSoftwareDetailMetadata } from '@/lib/metadata' -import { generateSoftwareDetailSchema } from '@/lib/metadata/schemas' +import { generateFAQPageSchema, generateSoftwareDetailSchema } from '@/lib/metadata/schemas' export const revalidate = 3600 @@ -69,6 +72,7 @@ export default async function CLIPage({ } const tShared = await getTranslations({ locale, namespace: 'shared' }) + const landingContent = cli.landingPage ? getCLILandingContent(cli.id, locale as Locale) : null // Transform URLs for component props const websiteUrl = cli.websiteUrl || cli.resourceUrls?.download || undefined @@ -95,6 +99,14 @@ export default async function CLIPage({ // Fetch related products const relatedProducts = await getRelatedProducts(cli.relatedProducts || [], locale as Locale) + const faqSchema = landingContent + ? await generateFAQPageSchema( + landingContent.faq.items.map(item => ({ + question: item.question, + answer: item.answer, + })) + ) + : null // Breadcrumb items const breadcrumbItems = [ @@ -105,37 +117,51 @@ export default async function CLIPage({ return ( + {faqSchema && } -
- p.os)} - websiteUrl={websiteUrl} - docsUrl={docsUrl} - downloadUrl={downloadUrl} - /> - - - - - - - - - - - - +
+ {landingContent ? ( + + ) : ( +
+ p.os)} + websiteUrl={websiteUrl} + docsUrl={docsUrl} + downloadUrl={downloadUrl} + /> + + + + + + + + + + + + +
+ )}
) diff --git a/src/components/product/CLILandingPage.tsx b/src/components/product/CLILandingPage.tsx new file mode 100644 index 00000000..c9bf5058 --- /dev/null +++ b/src/components/product/CLILandingPage.tsx @@ -0,0 +1,382 @@ +import { + ArrowRight, + ExternalLink, + FilePenLine, + GitCompareArrows, + Plus, + SearchCode, + Terminal, +} from 'lucide-react' +import { useTranslations } from 'next-intl' +import type { ReactNode } from 'react' +import { DeprecatedBadge } from '@/components/controls/DeprecatedBadge' +import { VerifiedBadge } from '@/components/controls/VerifiedBadge' +import { ProductPricing } from '@/components/product/ProductPricing' +import { RelatedProducts, type RelatedProductsProps } from '@/components/product/RelatedProducts' +import { Link } from '@/i18n/navigation' +import type { CLILandingContent } from '@/lib/content/cli-landing-pages' +import { renderLicense } from '@/lib/license' +import type { ManifestCLI } from '@/types/manifests' + +export interface CLILandingPageProps { + cli: ManifestCLI + content: CLILandingContent + locale: string + githubStars: number | null + pricingUrl?: string + relatedProducts: RelatedProductsProps['products'] +} + +interface FactRowProps { + label: string + children: ReactNode +} + +const capabilityIcons = [SearchCode, FilePenLine, Terminal] + +function getFirstCommand( + cli: ManifestCLI, + field: 'installCommand' | 'launchCommand' +): string | null { + return cli[field] ?? cli.platforms.find(platform => platform[field])?.[field] ?? null +} + +function formatDate(date: string, locale: string): string { + return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format( + new Date(`${date}T00:00:00Z`) + ) +} + +function sourceLabel(url: string): string { + try { + return new URL(url).hostname.replace(/^www\./, '') + } catch { + return url + } +} + +function FactRow({ label, children }: FactRowProps) { + return ( +
+
{label}
+
{children}
+
+ ) +} + +export function CLILandingPage({ + cli, + content, + locale, + githubStars, + pricingUrl, + relatedProducts, +}: CLILandingPageProps) { + const tShared = useTranslations('shared') + const tComponent = useTranslations('components.product') + const installCommand = getFirstCommand(cli, 'installCommand') + const launchCommand = getFirstCommand(cli, 'launchCommand') + const confidenceLabels = { + high: tComponent('cliLanding.verification.confidenceValues.high'), + medium: tComponent('cliLanding.verification.confidenceValues.medium'), + low: tComponent('cliLanding.verification.confidenceValues.low'), + } + + const linkCandidates = [ + { label: tShared('terms.visitWebsite'), url: cli.websiteUrl }, + { label: tShared('terms.documentation'), url: cli.docsUrl }, + { label: 'GitHub', url: cli.githubUrl }, + { label: tShared('actions.download'), url: cli.resourceUrls.download }, + { label: tComponent('resourceLinks.changelog'), url: cli.resourceUrls.changelog }, + { label: tShared('terms.pricing'), url: cli.resourceUrls.pricing }, + { label: tComponent('resourceLinks.issue'), url: cli.resourceUrls.issue }, + ].filter((link): link is { label: string; url: string } => Boolean(link.url)) + const officialLinks = linkCandidates.filter( + (link, index) => linkCandidates.findIndex(candidate => candidate.url === link.url) === index + ) + const communityLinkCandidates = [ + { label: tShared('platforms.linkedin'), url: cli.communityUrls.linkedin }, + { label: tShared('platforms.twitter'), url: cli.communityUrls.twitter }, + { label: tShared('platforms.github'), url: cli.communityUrls.github }, + { label: tShared('platforms.youtube'), url: cli.communityUrls.youtube }, + { label: tShared('platforms.discord'), url: cli.communityUrls.discord }, + { label: tShared('platforms.reddit'), url: cli.communityUrls.reddit }, + { label: tComponent('communityLinks.blog'), url: cli.communityUrls.blog }, + ].filter((link): link is { label: string; url: string } => Boolean(link.url)) + const communityLinks = communityLinkCandidates.filter( + (link, index) => + !officialLinks.some(officialLink => officialLink.url === link.url) && + communityLinkCandidates.findIndex(candidate => candidate.url === link.url) === index + ) + + return ( + <> +
+
+
+
+
+ {cli.vendor} + + {tShared('categories.singular.cli')} + {cli.verified && } + {cli.deprecated && } +
+ +

+ {cli.name} +

+

+ {content.answer} +

+

+ {content.introduction} +

+ +
+ + {tShared('terms.visitWebsite')} + + + {tComponent('cliLanding.comparisonAction')} +
+
+ + {(installCommand || launchCommand) && ( +
+
+ + {cli.name} +
+
+ {installCommand && ( +
+

+ {tComponent('productCommands.install')} +

+
+                        $ 
+                        {installCommand}
+                      
+
+ )} + {launchCommand && ( +
+

+ {tComponent('productCommands.launch')} +

+
+                        $ 
+                        {launchCommand}
+                      
+
+ )} +
+
+ )} +
+
+
+ +
+
+
+

+ {tComponent('cliLanding.capabilitiesTitle', { product: cli.name })} +

+
+ {content.capabilities.items.map((item, index) => { + const Icon = capabilityIcons[index] ?? Terminal + return ( +
+
+ ) + })} +
+
+ + + + + +
+

+ {tComponent('cliLanding.faqTitle')} +

+
+ {content.faq.items.map(item => ( +
+ + {item.question} + +

+ {item.answer} +

+
+ ))} +
+
+
+ + +
+ + ) +} diff --git a/src/components/product/ProductPricing.tsx b/src/components/product/ProductPricing.tsx index 925b5b19..291b6437 100644 --- a/src/components/product/ProductPricing.tsx +++ b/src/components/product/ProductPricing.tsx @@ -4,6 +4,7 @@ import { getPricingSummary, type PricingBoundary, type PricingTier } from '@/lib export interface ProductPricingProps { pricing: PricingTier[] pricingUrl?: string + variant?: 'default' | 'compact' } type PricingSummaryValueProps = { @@ -62,13 +63,55 @@ function PricingTierValue({ tier }: { tier: PricingTier }) { return } -export function ProductPricing({ pricing, pricingUrl }: ProductPricingProps) { +export function ProductPricing({ pricing, pricingUrl, variant = 'default' }: ProductPricingProps) { const tShared = useTranslations('shared') if (!pricing || pricing.length === 0) { return null } + if (variant === 'compact') { + return ( +
+

+ {tShared('terms.pricing')} +

+ +
+ {pricing.map(tier => ( +
+
+ {tier.category && ( +

+ {tier.category} +

+ )} +

{tier.name}

+
+

+ +

+
+ ))} +
+ + {pricingUrl && ( + + {tShared('actions.viewFullDetails')} + + )} +
+ ) + } + return (
diff --git a/src/components/product/RelatedProducts.tsx b/src/components/product/RelatedProducts.tsx index 22379663..aa4f78d4 100644 --- a/src/components/product/RelatedProducts.tsx +++ b/src/components/product/RelatedProducts.tsx @@ -1,5 +1,6 @@ 'use client' +import { ArrowRight } from 'lucide-react' import { useTranslations } from 'next-intl' import { Link } from '@/i18n/navigation' import type { @@ -14,6 +15,7 @@ export interface RelatedProductsProps { type: 'ide' | 'cli' | 'extension' | 'desktop' data: ManifestIDE | ManifestCLI | ManifestExtension | ManifestDesktop | null }> + variant?: 'default' | 'compact' } /** @@ -22,7 +24,7 @@ export interface RelatedProductsProps { * This component is intentionally defensive: it filters out null product data and returns `null` * when there is nothing meaningful to display, so callers don't need conditional rendering. */ -export function RelatedProducts({ products = [] }: RelatedProductsProps) { +export function RelatedProducts({ products = [], variant = 'default' }: RelatedProductsProps) { const tComponent = useTranslations('components.product') const tShared = useTranslations('shared') @@ -83,6 +85,47 @@ export function RelatedProducts({ products = [] }: RelatedProductsProps) { } } + if (variant === 'compact') { + return ( +
+

+ {tComponent('relatedProducts.title')} +

+ +
+ {validProducts.map(({ type, data }) => { + if (!data) return null + + return ( + +
+

+ {getTypeLabel(type)} · {data.vendor} +

+

+ {data.name} +

+

+ {data.description} +

+
+
+
+ ) + } + return (
diff --git a/src/lib/content/cli-landing-markdown.ts b/src/lib/content/cli-landing-markdown.ts new file mode 100644 index 00000000..36a9cf96 --- /dev/null +++ b/src/lib/content/cli-landing-markdown.ts @@ -0,0 +1,164 @@ +export interface CLILandingItem { + title: string + description: string +} + +export interface CLILandingFAQItem { + question: string + answer: string +} + +export interface CLILandingContent { + answer: string + introduction: string + capabilities: { + items: CLILandingItem[] + } + verification: { + description: string + } + faq: { + items: CLILandingFAQItem[] + } +} + +const KEY_HEADING_PATTERN = /^##\s+([a-z][a-zA-Z0-9]*(?:\.(?:[a-zA-Z][a-zA-Z0-9]*|\d+))*)\s*$/ + +function escapeRegExp(value: string): string { + return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') +} + +function parseSections(markdown: string, source: string): Map { + const sections = new Map() + let currentKey: string | null = null + let currentLines: string[] = [] + + const finishSection = (): void => { + if (!currentKey) return + + const value = currentLines.join('\n').trim() + if (!value) { + throw new Error(`${source}: section ${currentKey} is empty`) + } + if (sections.has(currentKey)) { + throw new Error(`${source}: duplicate section ${currentKey}`) + } + + sections.set(currentKey, value) + } + + for (const line of markdown.replace(/\r\n/g, '\n').split('\n')) { + if (line.startsWith('## ')) { + finishSection() + const match = line.match(KEY_HEADING_PATTERN) + if (!match?.[1]) { + throw new Error(`${source}: invalid keyed heading ${JSON.stringify(line)}`) + } + currentKey = match[1] + currentLines = [] + continue + } + + if (/^#{2,6}\s/.test(line)) { + throw new Error(`${source}: only level-two keyed headings are allowed`) + } + + if (!currentKey && line.trim()) { + throw new Error(`${source}: content must start with a level-two keyed heading`) + } + + if (currentKey) { + currentLines.push(line) + } + } + + finishSection() + return sections +} + +function requiredSection( + sections: Map, + consumed: Set, + key: string, + source: string +): string { + const value = sections.get(key) + if (!value) { + throw new Error(`${source}: missing section ${key}`) + } + consumed.add(key) + return value +} + +function indexedItems( + sections: Map, + consumed: Set, + prefix: string, + fields: readonly [keyof T & string, keyof T & string], + source: string +): T[] { + const indexes = new Set() + const pattern = new RegExp(`^${escapeRegExp(prefix)}\\.(\\d+)\\.(?:${fields.join('|')})$`) + + for (const key of sections.keys()) { + const match = key.match(pattern) + if (match?.[1]) indexes.add(Number(match[1])) + } + + const orderedIndexes = [...indexes].sort((left, right) => left - right) + if (orderedIndexes.length === 0 || orderedIndexes.some((index, position) => index !== position)) { + throw new Error(`${source}: ${prefix} indexes must be contiguous and start at 0`) + } + + return orderedIndexes.map( + index => + Object.fromEntries( + fields.map(field => { + const key = `${prefix}.${index}.${field}` + return [field, requiredSection(sections, consumed, key, source)] + }) + ) as T + ) +} + +export function parseCLILandingMarkdown( + markdown: string, + source = 'CLI landing-page Markdown' +): CLILandingContent { + const sections = parseSections(markdown, source) + const consumed = new Set() + const get = (key: string): string => requiredSection(sections, consumed, key, source) + + const content: CLILandingContent = { + answer: get('answer'), + introduction: get('introduction'), + capabilities: { + items: indexedItems( + sections, + consumed, + 'capabilities.items', + ['title', 'description'], + source + ), + }, + verification: { + description: get('verification.description'), + }, + faq: { + items: indexedItems( + sections, + consumed, + 'faq.items', + ['question', 'answer'], + source + ), + }, + } + + const unexpectedKeys = [...sections.keys()].filter(key => !consumed.has(key)) + if (unexpectedKeys.length > 0) { + throw new Error(`${source}: unknown sections: ${unexpectedKeys.join(', ')}`) + } + + return content +} diff --git a/src/lib/content/cli-landing-pages.ts b/src/lib/content/cli-landing-pages.ts new file mode 100644 index 00000000..9987caac --- /dev/null +++ b/src/lib/content/cli-landing-pages.ts @@ -0,0 +1,11 @@ +import type { Locale } from '@/i18n/config' +import type { CLILandingContent } from '@/lib/content/cli-landing-markdown' +import landingPages from '../../../data/generated/cli-landing-pages.json' + +export type { CLILandingContent } from '@/lib/content/cli-landing-markdown' + +const contentByLocale = landingPages as Record> + +export function getCLILandingContent(slug: string, locale: Locale): CLILandingContent | null { + return contentByLocale[locale]?.[slug] ?? null +} diff --git a/src/lib/metadata/schemas/builders.ts b/src/lib/metadata/schemas/builders.ts index 09742683..30567e3f 100644 --- a/src/lib/metadata/schemas/builders.ts +++ b/src/lib/metadata/schemas/builders.ts @@ -103,23 +103,26 @@ export function buildOffersSchema( ): SchemaOffer | SchemaOffer[] | undefined { if (!pricing || pricing.length === 0) return undefined - const offers = pricing.map(tier => { - const offer: SchemaOffer = { - '@type': 'Offer', - price: tier.value !== null ? tier.value.toString() : '0', - priceCurrency: tier.currency || 'USD', - } - - if (tier.name) offer.name = tier.name - if (tier.category) offer.category = tier.category - if (tier.value === 0 || tier.value === null) { - offer.price = '0' - offer.availability = 'https://schema.org/InStock' - } - - return offer - }) - + const offers = pricing + .filter(tier => tier.value !== null) + .map(tier => { + const offer: SchemaOffer = { + '@type': 'Offer', + price: tier.value?.toString() ?? '0', + priceCurrency: tier.currency || 'USD', + } + + if (tier.name) offer.name = tier.name + if (tier.category) offer.category = tier.category + if (tier.value === 0) { + offer.price = '0' + offer.availability = 'https://schema.org/InStock' + } + + return offer + }) + + if (offers.length === 0) return undefined return offers.length === 1 ? offers[0] : offers } diff --git a/src/types/manifests.ts b/src/types/manifests.ts index 5102e461..35f4ce6f 100644 --- a/src/types/manifests.ts +++ b/src/types/manifests.ts @@ -230,6 +230,7 @@ export interface ManifestBaseApp extends ManifestBaseProduct { * Extends: ManifestBaseApp */ export interface ManifestCLI extends ManifestBaseApp { + landingPage?: boolean resourceUrls: ManifestResourceUrls & { download: string } } diff --git a/tests/metadata.offers.test.ts b/tests/metadata.offers.test.ts new file mode 100644 index 00000000..4004a1c6 --- /dev/null +++ b/tests/metadata.offers.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, it } from 'vitest' +import { buildOffersSchema } from '@/lib/metadata/schemas' + +describe('structured pricing offers', () => { + it('keeps a published free tier while omitting unknown and usage-based prices', () => { + expect( + buildOffersSchema([ + { name: 'Free', value: 0, currency: 'USD', per: 'month' }, + { name: 'API Key', value: null, currency: null, per: 'usage-based' }, + { name: 'Enterprise', value: null, currency: null, per: 'custom' }, + ]) + ).toEqual({ + '@type': 'Offer', + name: 'Free', + price: '0', + priceCurrency: 'USD', + availability: 'https://schema.org/InStock', + }) + }) + + it('returns no offer when no numeric price is published', () => { + expect( + buildOffersSchema([ + { name: 'API Key', value: null, per: 'usage-based' }, + { name: 'Enterprise', value: null, per: 'custom' }, + ]) + ).toBeUndefined() + }) +}) diff --git a/tests/validate/cli-landing-pages.test.ts b/tests/validate/cli-landing-pages.test.ts new file mode 100644 index 00000000..17cc3fb3 --- /dev/null +++ b/tests/validate/cli-landing-pages.test.ts @@ -0,0 +1,93 @@ +import fs from 'node:fs' +import path from 'node:path' +import Ajv2020 from 'ajv/dist/2020.js' +import { describe, expect, it } from 'vitest' +import { locales } from '@/i18n/config' +import { type CLILandingContent, parseCLILandingMarkdown } from '@/lib/content/cli-landing-markdown' +import generatedContent from '../../data/generated/cli-landing-pages.json' + +interface CLIManifestSummary { + id: string + landingPage?: boolean +} + +function readJson(filePath: string): T { + return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T +} + +describe('CLI landing-page content', () => { + const rootDir = process.cwd() + const manifestDir = path.join(rootDir, 'manifests', 'clis') + const landingPageIds = fs + .readdirSync(manifestDir) + .filter(file => file.endsWith('.json')) + .map(file => readJson(path.join(manifestDir, file))) + .filter(manifest => manifest.landingPage) + .map(manifest => manifest.id) + + it('matches the generated-data schema', () => { + const schema = readJson>( + path.join(rootDir, 'data', '$schemas', 'cli-landing-pages.schema.json') + ) + const validate = new Ajv2020({ allErrors: true }).compile(schema) + + expect(validate(generatedContent), JSON.stringify(validate.errors, null, 2)).toBe(true) + }) + + it('provides valid keyed Markdown for every enabled CLI and locale', () => { + expect(landingPageIds.length).toBeGreaterThan(0) + const generatedByLocale = generatedContent as Record< + (typeof locales)[number], + Record + > + + for (const locale of locales) { + for (const id of landingPageIds) { + const filePath = path.join(rootDir, 'content', 'clis', locale, `${id}.md`) + expect( + fs.existsSync(filePath), + `${locale} is missing content/clis/${locale}/${id}.md` + ).toBe(true) + + const content = parseCLILandingMarkdown( + fs.readFileSync(filePath, 'utf8'), + path.relative(rootDir, filePath) + ) + expect(content.answer.trim().length).toBeGreaterThan(40) + expect(content.capabilities.items).toHaveLength(3) + expect(content.faq.items.length).toBeGreaterThanOrEqual(4) + expect(generatedByLocale[locale][id]).toEqual(content) + } + } + }) + + it('keeps UI copy in translations and product editorial content in Markdown', () => { + for (const locale of locales) { + const pageTranslations = readJson>( + path.join(rootDir, 'translations', locale, 'pages', 'clis.json') + ) + const componentTranslations = readJson>( + path.join(rootDir, 'translations', locale, 'components', 'product.json') + ) + expect(componentTranslations).toHaveProperty('cliLanding.labels.publisher') + expect(componentTranslations).toHaveProperty('cliLanding.capabilitiesTitle') + expect(componentTranslations).toHaveProperty('cliLanding.comparisonAction') + expect(componentTranslations).toHaveProperty('cliLanding.verification.title') + expect(componentTranslations).toHaveProperty('cliLanding.faqTitle') + expect(pageTranslations).not.toHaveProperty('landingPage') + expect(pageTranslations).not.toHaveProperty('landingPages') + } + }) + + it('rejects duplicate and unknown Markdown keys', () => { + const englishFile = path.join(rootDir, 'content', 'clis', 'en', 'codex-cli.md') + const markdown = fs.readFileSync(englishFile, 'utf8') + + expect(() => + parseCLILandingMarkdown(`${markdown}\n## answer\n\nDuplicate`, englishFile) + ).toThrow('duplicate section answer') + expect(() => + parseCLILandingMarkdown(`${markdown}\n## capabilities.typo\n\nUnknown`, englishFile) + ).toThrow('unknown sections: capabilities.typo') + }) +}) diff --git a/tests/validate/manifests.sources.test.ts b/tests/validate/manifests.sources.test.ts new file mode 100644 index 00000000..be53983b --- /dev/null +++ b/tests/validate/manifests.sources.test.ts @@ -0,0 +1,81 @@ +import fs from 'node:fs' +import path from 'node:path' +import { describe, expect, it } from 'vitest' + +const MANIFEST_CATEGORIES = [ + 'clis', + 'desktops', + 'ides', + 'extensions', + 'models', + 'providers', + 'vendors', +] as const + +interface ManifestSourceRecord { + fields?: string[] +} + +interface ManifestRecord { + id?: string + sources?: ManifestSourceRecord[] + [key: string]: unknown +} + +function sourceFieldExists(manifest: ManifestRecord, fieldPath: string): boolean { + let value: unknown = manifest + + for (const segment of fieldPath.split('.')) { + if (value === null || typeof value !== 'object' || !Object.hasOwn(value, segment)) { + return false + } + value = (value as Record)[segment] + } + + return true +} + +describe('manifest source field paths', () => { + it('resolves every declared source field to the manifest it supports', () => { + const failures: string[] = [] + + for (const category of MANIFEST_CATEGORIES) { + const directory = path.join(process.cwd(), 'manifests', category) + const files = fs + .readdirSync(directory) + .filter(file => file.endsWith('.json')) + .sort() + + for (const file of files) { + const manifest = JSON.parse( + fs.readFileSync(path.join(directory, file), 'utf8') + ) as ManifestRecord + + manifest.sources?.forEach((source, sourceIndex) => { + source.fields?.forEach(fieldPath => { + if (!sourceFieldExists(manifest, fieldPath)) { + failures.push( + `${category}/${file} sources[${sourceIndex}].fields references missing path "${fieldPath}"` + ) + } + }) + }) + } + } + + expect(failures).toEqual([]) + }) + + it('accepts nested and null fields but rejects misspelled paths', () => { + const manifest: ManifestRecord = { + pricing: [], + resourceUrls: { pricing: null }, + } + const misspelledPricing = 'pricing'.replace('i', '') + + expect(sourceFieldExists(manifest, 'pricing')).toBe(true) + expect(sourceFieldExists(manifest, 'resourceUrls.pricing')).toBe(true) + expect(sourceFieldExists(manifest, misspelledPricing)).toBe(false) + expect(sourceFieldExists(manifest, `resourceUrls.${misspelledPricing}`)).toBe(false) + }) +}) diff --git a/translations/de/components/product.json b/translations/de/components/product.json index efb5690a..0aa22261 100644 --- a/translations/de/components/product.json +++ b/translations/de/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "Anbieter", + "verified": "Zuletzt geprüft", + "confidence": "Vertrauensniveau" + }, + "capabilitiesTitle": "Was kann {product}?", + "comparisonAction": "CLI-Vergleich öffnen", + "verification": { + "title": "Quellen und Prüfung", + "reviewedBy": "Geprüft von", + "confidenceValues": { + "high": "Hoch", + "medium": "Mittel", + "low": "Niedrig" + } + }, + "faqTitle": "Häufig gestellte Fragen" } } diff --git a/translations/en/components/product.json b/translations/en/components/product.json index a49aace0..97d68ff0 100644 --- a/translations/en/components/product.json +++ b/translations/en/components/product.json @@ -108,5 +108,24 @@ } }, "vendorModels": {}, - "vendorProducts": {} + "vendorProducts": {}, + "cliLanding": { + "labels": { + "publisher": "Publisher", + "verified": "Last verified", + "confidence": "Confidence" + }, + "capabilitiesTitle": "What can {product} do?", + "comparisonAction": "Open CLI comparison", + "verification": { + "title": "Sources and verification", + "reviewedBy": "Reviewed by", + "confidenceValues": { + "high": "High", + "medium": "Medium", + "low": "Low" + } + }, + "faqTitle": "Frequently asked questions" + } } diff --git a/translations/es/components/product.json b/translations/es/components/product.json index 798ceb10..643c3c0d 100644 --- a/translations/es/components/product.json +++ b/translations/es/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "Editor", + "verified": "Última verificación", + "confidence": "Nivel de confianza" + }, + "capabilitiesTitle": "¿Qué puede hacer {product}?", + "comparisonAction": "Abrir la comparación de CLI", + "verification": { + "title": "Fuentes y verificación", + "reviewedBy": "Revisado por", + "confidenceValues": { + "high": "Alto", + "medium": "Medio", + "low": "Bajo" + } + }, + "faqTitle": "Preguntas frecuentes" } } diff --git a/translations/fr/components/product.json b/translations/fr/components/product.json index eef28109..d26d58e2 100644 --- a/translations/fr/components/product.json +++ b/translations/fr/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "Éditeur", + "verified": "Dernière vérification", + "confidence": "Niveau de confiance" + }, + "capabilitiesTitle": "Que peut faire {product} ?", + "comparisonAction": "Ouvrir le comparatif des CLI", + "verification": { + "title": "Sources et vérification", + "reviewedBy": "Vérifié par", + "confidenceValues": { + "high": "Élevé", + "medium": "Moyen", + "low": "Faible" + } + }, + "faqTitle": "Questions fréquentes" } } diff --git a/translations/id/components/product.json b/translations/id/components/product.json index f7f25332..3e56eea3 100644 --- a/translations/id/components/product.json +++ b/translations/id/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "Penerbit", + "verified": "Terakhir diverifikasi", + "confidence": "Tingkat keyakinan" + }, + "capabilitiesTitle": "Apa yang dapat dilakukan {product}?", + "comparisonAction": "Buka perbandingan CLI", + "verification": { + "title": "Sumber dan verifikasi", + "reviewedBy": "Ditinjau oleh", + "confidenceValues": { + "high": "Tinggi", + "medium": "Sedang", + "low": "Rendah" + } + }, + "faqTitle": "Pertanyaan umum" } } diff --git a/translations/ja/components/product.json b/translations/ja/components/product.json index daf7f414..30cb5759 100644 --- a/translations/ja/components/product.json +++ b/translations/ja/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "提供元", + "verified": "最終確認日", + "confidence": "信頼度" + }, + "capabilitiesTitle": "{product} でできること", + "comparisonAction": "CLI 比較を開く", + "verification": { + "title": "情報源と検証", + "reviewedBy": "確認者", + "confidenceValues": { + "high": "高", + "medium": "中", + "low": "低" + } + }, + "faqTitle": "よくある質問" } } diff --git a/translations/ko/components/product.json b/translations/ko/components/product.json index c9ea4638..de42edd5 100644 --- a/translations/ko/components/product.json +++ b/translations/ko/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "제공사", + "verified": "최종 확인일", + "confidence": "신뢰도" + }, + "capabilitiesTitle": "{product}로 할 수 있는 일", + "comparisonAction": "CLI 비교 열기", + "verification": { + "title": "출처 및 검증", + "reviewedBy": "검토자", + "confidenceValues": { + "high": "높음", + "medium": "보통", + "low": "낮음" + } + }, + "faqTitle": "자주 묻는 질문" } } diff --git a/translations/pt/components/product.json b/translations/pt/components/product.json index dcf9e6f7..d99b588c 100644 --- a/translations/pt/components/product.json +++ b/translations/pt/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "Fornecedor", + "verified": "Última verificação", + "confidence": "Nível de confiança" + }, + "capabilitiesTitle": "O que o {product} pode fazer?", + "comparisonAction": "Abrir comparação de CLI", + "verification": { + "title": "Fontes e verificação", + "reviewedBy": "Revisado por", + "confidenceValues": { + "high": "Alta", + "medium": "Média", + "low": "Baixa" + } + }, + "faqTitle": "Perguntas frequentes" } } diff --git a/translations/ru/components/product.json b/translations/ru/components/product.json index e1c02866..a758aa3f 100644 --- a/translations/ru/components/product.json +++ b/translations/ru/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "Разработчик", + "verified": "Последняя проверка", + "confidence": "Уровень доверия" + }, + "capabilitiesTitle": "Что умеет {product}?", + "comparisonAction": "Открыть сравнение CLI", + "verification": { + "title": "Источники и проверка", + "reviewedBy": "Проверено", + "confidenceValues": { + "high": "Высокий", + "medium": "Средний", + "low": "Низкий" + } + }, + "faqTitle": "Часто задаваемые вопросы" } } diff --git a/translations/tr/components/product.json b/translations/tr/components/product.json index 093ef6f5..c3bfdd85 100644 --- a/translations/tr/components/product.json +++ b/translations/tr/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "Yayıncı", + "verified": "Son doğrulama", + "confidence": "Güven düzeyi" + }, + "capabilitiesTitle": "{product} neler yapabilir?", + "comparisonAction": "CLI karşılaştırmasını aç", + "verification": { + "title": "Kaynaklar ve doğrulama", + "reviewedBy": "Kontrol eden", + "confidenceValues": { + "high": "Yüksek", + "medium": "Orta", + "low": "Düşük" + } + }, + "faqTitle": "Sık sorulan sorular" } } diff --git a/translations/zh-Hans/components/product.json b/translations/zh-Hans/components/product.json index 11182d26..0b68bb0e 100644 --- a/translations/zh-Hans/components/product.json +++ b/translations/zh-Hans/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "发布方", + "verified": "最后验证", + "confidence": "置信度" + }, + "capabilitiesTitle": "{product} 能做什么?", + "comparisonAction": "打开 CLI 比较", + "verification": { + "title": "来源与验证", + "reviewedBy": "审查方", + "confidenceValues": { + "high": "高", + "medium": "中", + "low": "低" + } + }, + "faqTitle": "常见问题" } } diff --git a/translations/zh-Hant/components/product.json b/translations/zh-Hant/components/product.json index eae2c3cc..fcc4288b 100644 --- a/translations/zh-Hant/components/product.json +++ b/translations/zh-Hant/components/product.json @@ -106,5 +106,24 @@ } } } + }, + "cliLanding": { + "labels": { + "publisher": "發布方", + "verified": "最後驗證", + "confidence": "可信度" + }, + "capabilitiesTitle": "{product} 能做什麼?", + "comparisonAction": "開啟 CLI 比較", + "verification": { + "title": "來源與驗證", + "reviewedBy": "檢閱方", + "confidenceValues": { + "high": "高", + "medium": "中", + "low": "低" + } + }, + "faqTitle": "常見問題" } }