From 59576ee028df3dddea375889b6fe6387f85dc017 Mon Sep 17 00:00:00 2001 From: TShentu Date: Thu, 30 Apr 2026 15:45:43 +0800 Subject: [PATCH] [NEW][codex][1.0.1] fix description --- codex/Chart.yaml | 6 + codex/OlaresManifest.yaml | 104 +++++++++++++ codex/docker/Dockerfile | 54 +++++++ codex/docker/README.md | 43 ++++++ codex/i18n/en-US/OlaresManifest.yaml | 16 ++ codex/i18n/zh-CN/OlaresManifest.yaml | 16 ++ codex/owners | 7 + codex/templates/deployment.yaml | 218 +++++++++++++++++++++++++++ codex/templates/terminal.yaml | 129 ++++++++++++++++ codex/values.yaml | 1 + 10 files changed, 594 insertions(+) create mode 100644 codex/Chart.yaml create mode 100644 codex/OlaresManifest.yaml create mode 100644 codex/docker/Dockerfile create mode 100644 codex/docker/README.md create mode 100644 codex/i18n/en-US/OlaresManifest.yaml create mode 100644 codex/i18n/zh-CN/OlaresManifest.yaml create mode 100644 codex/owners create mode 100644 codex/templates/deployment.yaml create mode 100644 codex/templates/terminal.yaml create mode 100644 codex/values.yaml diff --git a/codex/Chart.yaml b/codex/Chart.yaml new file mode 100644 index 000000000..8588dd9f4 --- /dev/null +++ b/codex/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: '0.125.0' +description: OpenAI's lightweight coding agent that runs in your terminal +name: codex +type: application +version: 1.0.1 diff --git a/codex/OlaresManifest.yaml b/codex/OlaresManifest.yaml new file mode 100644 index 000000000..5d41c144c --- /dev/null +++ b/codex/OlaresManifest.yaml @@ -0,0 +1,104 @@ +olaresManifest.version: '0.11.0' +olaresManifest.type: app +metadata: + name: codex + icon: https://app.cdn.olares.com/appstore/codex/icon.png + description: OpenAI's lightweight coding agent that runs in your terminal + appid: codex + title: Codex CLI + version: 1.0.1 + categories: + - Developer Tools + - Productivity_v112 + - Utilities +entrances: +- name: terminal + host: terminal + port: 80 + title: Codex CLI + icon: https://app.cdn.olares.com/appstore/codex/icon.png + openMethod: window + authLevel: internal +spec: + versionName: '0.125.0' + fullDescription: | + **Overview** + Codex CLI is OpenAI's lightweight, open-source coding agent that runs locally in your terminal. It understands your codebase, executes routine tasks through natural language, and helps you ship faster while staying in flow. + + **Key Features** + - Terminal-native TUI with streaming tool output, slash commands, interrupt-and-redirect, and rich diff review. + - Real file edits, shell execution, git workflows, and test runs driven by natural language. + - MCP-compatible tool calling and reusable agent instructions via AGENTS.md / `.codex/skills`. + - Works with a ChatGPT Plus / Pro / Business / Edu / Enterprise plan (OAuth) or an OpenAI API key. + + **First-time Setup** + Open the `Codex CLI` entrance and run `codex` to launch the OAuth login flow ("Sign in with ChatGPT"), or set `OPENAI_API_KEY` in the app environment variables and restart. + + developer: OpenAI + website: https://chatgpt.com/codex + sourceCode: https://github.com/openai/codex + submitter: Olares + locale: + - en-US + - zh-CN + doc: https://github.com/openai/codex/tree/main/docs + license: + - text: Apache-2.0 + url: https://github.com/openai/codex/blob/main/LICENSE + requiredMemory: 1Gi + limitedMemory: 17Gi + requiredDisk: 1Gi + limitedDisk: 50Gi + requiredCpu: 500m + limitedCpu: 5 + supportArch: + - amd64 + - arm64 +permission: + appData: true + appCache: true + userData: + - Home +options: + allowMultipleInstall: true + apiTimeout: 0 + dependencies: + - name: olares + type: system + version: '>=1.12.5-0' +envs: + - envName: OPENAI_API_KEY + type: password + required: false + applyOnChange: true + editable: true + default: "" + description: "OpenAI API key (leave empty to use interactive 'Sign in with ChatGPT' OAuth login)" + - envName: OPENAI_BASE_URL + type: url + required: false + applyOnChange: true + editable: true + default: "" + description: "Custom OpenAI-compatible API endpoint (optional, for proxies or self-hosted gateways)" + - envName: CODEX_MODEL + type: string + required: false + applyOnChange: true + editable: true + default: "" + description: "Override the default model (e.g. gpt-5-codex). Leave empty to use the Codex default." + - envName: ALLOW_HOME_DIR_ACCESS + type: bool + required: false + applyOnChange: true + editable: true + default: "false" + description: "Allow Codex CLI to read/write the Olares Home directory" + - envName: ALLOW_EXTERNAL_DIR_ACCESS + type: bool + required: false + applyOnChange: true + editable: true + default: "false" + description: "Allow Codex CLI to read/write the Olares External directory" diff --git a/codex/docker/Dockerfile b/codex/docker/Dockerfile new file mode 100644 index 000000000..825350d87 --- /dev/null +++ b/codex/docker/Dockerfile @@ -0,0 +1,54 @@ +# Codex CLI base image for Olares. +# +# Scope: a thin Ubuntu 24.04 base with the minimum toolbox a Codex CLI +# terminal user expects (curl / git / less / procps / vim / jq), plus a +# non-root user (UID 1000) so the runtime Pod never needs root. +# +# The codex binary itself is NOT baked into this image. It is installed +# at runtime by the init-install-codex initContainer into the shared +# /opt/data PVC (under ~/.local/bin/codex). That keeps base-image size +# small and lets us bump codex versions without rebuilding the image. +# +# Build & push: +# docker buildx build \ +# --platform linux/amd64,linux/arm64 \ +# -t beclab/harveyff-codex-base:0.1.0 \ +# --push . +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 + +# Core toolbox expected by a Codex CLI terminal user. ripgrep is NOT +# installed here: the codex binary ships its own bundled search and +# installing the system one alongside can confuse its file search. +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + git \ + jq \ + less \ + locales \ + procps \ + tzdata \ + unzip \ + vim-tiny \ + xz-utils \ + && rm -rf /var/lib/apt/lists/* \ + && locale-gen C.UTF-8 \ + && (userdel -r ubuntu 2>/dev/null || true) \ + && (groupdel ubuntu 2>/dev/null || true) \ + && useradd --create-home --uid 1000 --shell /bin/bash codex \ + && mkdir -p /opt/data \ + && chown -R 1000:1000 /opt/data + +USER 1000:1000 +WORKDIR /opt/data + +ENV HOME=/opt/data \ + PATH=/opt/data/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ + TERM=xterm-256color + +CMD ["bash"] diff --git a/codex/docker/README.md b/codex/docker/README.md new file mode 100644 index 000000000..468dee065 --- /dev/null +++ b/codex/docker/README.md @@ -0,0 +1,43 @@ +# codex base image + +A thin Ubuntu 24.04 base image for the Olares `codex` app. + +## What it ships + +- `ca-certificates`, `curl`, `git`, `jq`, `less`, `procps`, `tzdata`, + `unzip`, `vim-tiny`, `xz-utils`, `locales` (C.UTF-8 pre-generated). +- A non-root user `codex` (UID 1000) with `HOME=/opt/data` and + `PATH` prepending `/opt/data/.local/bin`. +- No `codex` binary. The binary is installed at runtime by the + `init-install-codex` initContainer into the shared PVC so bumping + codex versions does not require rebuilding this image. + +## Build & push + +```bash +# Single-arch (local dev) +docker build -t beclab/harveyff-codex-base:0.1.0 . + +# Multi-arch release (recommended, matches chart supportArch) +docker buildx create --use --name codex-builder || true +docker buildx build \ + --platform linux/amd64,linux/arm64 \ + -t beclab/harveyff-codex-base:0.1.0 \ + --push . +``` + +## Bumping the image + +When bumping apt dependencies or base Ubuntu: + +1. Increment the tag: `0.1.0 -> 0.1.1` (or major if breaking). +2. Update both references in + `codex/templates/deployment.yaml` (initContainer + main container). +3. Bump `version` in `codex/Chart.yaml`. + +The `codex` binary itself (rust-v0.125.0 etc.) is controlled separately +by `appVersion` in `Chart.yaml` and `metadata.version` / +`spec.versionName` in `OlaresManifest.yaml`; it is pulled fresh from +the matching GitHub Release tarball whenever +`$HOME/.install-state/codex-` is missing, regardless of base +image tag. diff --git a/codex/i18n/en-US/OlaresManifest.yaml b/codex/i18n/en-US/OlaresManifest.yaml new file mode 100644 index 000000000..bf108c5a0 --- /dev/null +++ b/codex/i18n/en-US/OlaresManifest.yaml @@ -0,0 +1,16 @@ +metadata: + title: Codex CLI + description: OpenAI's lightweight coding agent that runs in your terminal +spec: + fullDescription: | + **Overview** + Codex CLI is OpenAI's lightweight, open-source coding agent that runs locally in your terminal. It understands your codebase, executes routine tasks through natural language, and helps you ship faster while staying in flow. + + **Key Features** + - Terminal-native TUI with streaming tool output, slash commands, interrupt-and-redirect, and rich diff review. + - Real file edits, shell execution, git workflows, and test runs driven by natural language. + - MCP-compatible tool calling and reusable agent instructions via AGENTS.md / `.codex/skills`. + - Works with a ChatGPT Plus / Pro / Business / Edu / Enterprise plan (OAuth) or an OpenAI API key. + + **First-time Setup** + Open the `Codex CLI` entrance and run `codex` to launch the OAuth login flow ("Sign in with ChatGPT"), or set `OPENAI_API_KEY` in the app environment variables and restart. diff --git a/codex/i18n/zh-CN/OlaresManifest.yaml b/codex/i18n/zh-CN/OlaresManifest.yaml new file mode 100644 index 000000000..60fee71e9 --- /dev/null +++ b/codex/i18n/zh-CN/OlaresManifest.yaml @@ -0,0 +1,16 @@ +metadata: + title: Codex CLI + description: OpenAI 官方原版的终端 AI 编码助手 +spec: + fullDescription: | + **概述** + Codex CLI 是 OpenAI 官方推出的开源终端智能编码助手。它能够理解你的代码库,通过自然语言执行日常任务,帮助你更高效地开发和保持专注。 + + **主要功能** + - 基于终端的原生 TUI,支持工具实时输出流、斜杠命令、中断与重定向、丰富的差异审查体验。 + - 可通过自然语言进行真实文件编辑、Shell 执行、Git 工作流和测试操作。 + - 兼容 MCP 工具调用,可复用 AGENTS.md / `.codex/skills` 中的智能体指令。 + - 支持通过 ChatGPT Plus / Pro / Business / Edu / Enterprise 计划(OAuth 登录)或 OpenAI API 密钥使用。 + + **首次设置** + 打开 `Codex CLI` 入口并运行 `codex`,开启 OAuth 登录流程(“使用 ChatGPT 登录”);也可在应用环境变量中配置 `OPENAI_API_KEY`,然后重启应用。 diff --git a/codex/owners b/codex/owners new file mode 100644 index 000000000..a95e7dd30 --- /dev/null +++ b/codex/owners @@ -0,0 +1,7 @@ +owners: +- 'LittleLollipop' +- 'TShentu' +- 'hysyeah' +- 'pengpeng' +- 'harveyff' +- 'lovehunter9' diff --git a/codex/templates/deployment.yaml b/codex/templates/deployment.yaml new file mode 100644 index 000000000..cc29097ab --- /dev/null +++ b/codex/templates/deployment.yaml @@ -0,0 +1,218 @@ +# Codex CLI on Olares +# +# Architecture: +# - Base image: beclab/harveyff-codex-base (Ubuntu 24.04 with +# common CLI deps pre-installed, non-root user UID 1000 baked in). +# - initContainers: +# * init-chmod-data (root): ensures /opt/data is owned by 1000:1000. +# * init-install-codex (UID 1000): downloads the codex native +# binary from the matching GitHub Release tarball into +# /opt/data/.local/bin/ on first run for this version, then +# leaves a versioned sentinel so subsequent restarts skip the +# download and start instantly. +# - Main container runs as UID 1000 with all Linux capabilities +# dropped and privilege escalation forbidden. The entrypoint is +# `sleep infinity`; the real work happens when the Olares terminal +# entrance kubectl-execs into this container. +# - /opt/data is the single source of truth: ~/.codex (sessions, +# auth.json, skills, config.toml) and .local/bin/codex. All +# persisted through the app-data-home hostPath volume. +# - Auto-updates are disabled de facto: upgrades go through chart +# version bumps, which change the sentinel filename and trigger a +# fresh download. +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + io.kompose.service: codex + name: "{{ .Release.Name }}" + namespace: "{{ .Release.Namespace }}" +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: codex + strategy: + type: Recreate + template: + metadata: + labels: + io.kompose.service: codex + bytetrade.io/terminal: codex + spec: + securityContext: + fsGroup: 1000 + + initContainers: + # Fix ownership of the PVC so the non-root runtime user can + # write to it. Root is required here because hostPath volumes + # land on disk with root ownership on first create. + - name: init-chmod-data + image: "beclab/ubuntu:24.04" + imagePullPolicy: IfNotPresent + securityContext: + runAsUser: 0 + runAsGroup: 0 + command: + - sh + - -c + - | + set -e + mkdir -p /opt/data/.local/bin /opt/data/.codex /opt/data/.install-state + chown -R 1000:1000 /opt/data + chmod -R 0755 /opt/data + echo "[init-chmod-data] /opt/data owned by 1000:1000" + resources: {} + volumeMounts: + - mountPath: /opt/data + name: app-data-home + + # First-run only (per appVersion): download the codex native + # binary from the matching GitHub Release tarball into the + # shared /opt/data PVC. Runs as UID 1000 since the installer + # only writes under $HOME. A versioned sentinel file makes + # subsequent Pod starts skip the download; bumping appVersion + # in Chart.yaml automatically forces a re-download. + - name: init-install-codex + image: "harveyff/codex-base:0.1.0-amd" + imagePullPolicy: IfNotPresent + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + env: + - name: HOME + value: /opt/data + - name: CODEX_VERSION + value: "{{ .Chart.AppVersion }}" + command: + - bash + - -c + - | + set -e + SENTINEL="$HOME/.install-state/codex-${CODEX_VERSION}" + mkdir -p "$HOME/.install-state" "$HOME/.local/bin" + + if [ -x "$HOME/.local/bin/codex" ] && [ -f "$SENTINEL" ]; then + echo "[init-install-codex] cached binary found (installed $(cat "$SENTINEL"))" + "$HOME/.local/bin/codex" --version + exit 0 + fi + + ARCH="$(uname -m)" + case "$ARCH" in + x86_64|amd64) TARGET="x86_64-unknown-linux-musl" ;; + aarch64|arm64) TARGET="aarch64-unknown-linux-musl" ;; + *) echo "[init-install-codex] unsupported arch: $ARCH" >&2; exit 1 ;; + esac + + URL="https://github.com/openai/codex/releases/download/rust-v${CODEX_VERSION}/codex-${TARGET}.tar.gz" + echo "[init-install-codex] downloading $URL" + + TMPDIR="$(mktemp -d)" + trap 'rm -rf "$TMPDIR"' EXIT + + curl -fSL --retry 5 --retry-delay 3 -o "$TMPDIR/codex.tar.gz" "$URL" + tar -xzf "$TMPDIR/codex.tar.gz" -C "$TMPDIR" + + # The release tarball contains a single binary entry whose + # name includes the target triple, e.g. codex-x86_64-unknown-linux-musl. + BIN="$(find "$TMPDIR" -maxdepth 2 -type f -name "codex-${TARGET}" | head -n1)" + if [ -z "$BIN" ]; then + echo "[init-install-codex] could not locate extracted codex binary" >&2 + ls -la "$TMPDIR" >&2 + exit 1 + fi + + install -m 0755 "$BIN" "$HOME/.local/bin/codex" + date -u +%Y-%m-%dT%H:%M:%SZ > "$SENTINEL" + echo "[init-install-codex] installed codex ${CODEX_VERSION} for ${TARGET}" + "$HOME/.local/bin/codex" --version + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 50m + memory: 128Mi + volumeMounts: + - mountPath: /opt/data + name: app-data-home + + containers: + # Workspace container. kubectl exec from the beclab terminal + # apiserver lands here as UID 1000. HOME/PATH are set on env so + # login / non-login / interactive / non-interactive shells all + # see the codex binary on PATH. + - name: codex + image: "harveyff/codex-base:0.1.0-amd" + imagePullPolicy: IfNotPresent + workingDir: /opt/data + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + env: + - name: TZ + value: Etc/UTC + - name: TERM + value: xterm-256color + - name: HOME + value: /opt/data + - name: PATH + value: "/opt/data/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + - name: CODEX_HOME + value: /opt/data/.codex + - name: OPENAI_API_KEY + value: "{{ .Values.olaresEnv.OPENAI_API_KEY }}" + - name: OPENAI_BASE_URL + value: "{{ .Values.olaresEnv.OPENAI_BASE_URL }}" + - name: CODEX_MODEL + value: "{{ .Values.olaresEnv.CODEX_MODEL }}" + command: + - sleep + - infinity + resources: + limits: + cpu: "4" + memory: 16Gi + requests: + cpu: 100m + memory: 256Mi + volumeMounts: + - mountPath: /opt/data + name: app-data-home + {{- if eq (toString .Values.olaresEnv.ALLOW_HOME_DIR_ACCESS) "true" }} + - mountPath: /home/userdata/home/ + name: olares-home-dir + {{- end }} + {{- if eq (toString .Values.olaresEnv.ALLOW_EXTERNAL_DIR_ACCESS) "true" }} + - mountPath: /home/userdata/external/ + name: olares-external-dir + {{- end }} + + restartPolicy: Always + volumes: + - name: app-data-home + hostPath: + path: "{{ .Values.userspace.appData }}/home" + type: DirectoryOrCreate + {{- if eq (toString .Values.olaresEnv.ALLOW_HOME_DIR_ACCESS) "true" }} + - name: olares-home-dir + hostPath: + path: "{{ .Values.userspace.userData }}" + type: DirectoryOrCreate + {{- end }} + {{- if eq (toString .Values.olaresEnv.ALLOW_EXTERNAL_DIR_ACCESS) "true" }} + - name: olares-external-dir + hostPath: + path: "{{ .Values.sharedlib }}" + type: DirectoryOrCreate + {{- end }} diff --git a/codex/templates/terminal.yaml b/codex/templates/terminal.yaml new file mode 100644 index 000000000..d825a19e2 --- /dev/null +++ b/codex/templates/terminal.yaml @@ -0,0 +1,129 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: terminal-account + namespace: {{ .Release.Namespace }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: pod-exec-manager + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "create", "delete"] + - apiGroups: [""] + resources: ["pods/exec"] + verbs: ["create"] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: pod-exec-binding + namespace: {{ .Release.Namespace }} +subjects: + - kind: ServiceAccount + name: terminal-account + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: pod-exec-manager + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + io.kompose.service: terminal + name: terminal + namespace: '{{ .Release.Namespace }}' +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: terminal + strategy: {} + template: + metadata: + labels: + io.kompose.service: terminal + spec: + serviceAccountName: terminal-account + containers: + - name: nginx + image: beclab/terminal:v0.0.9 + env: + - name: PGID + value: "1000" + - name: PUID + value: "1000" + - name: TZ + value: Etc/UTC + command: + - nginx + - -g + - "daemon off;" + securityContext: + privileged: false + resources: + limits: + cpu: 50m + memory: 100Mi + requests: + cpu: 5m + memory: 50Mi + ports: + - name: http + containerPort: 80 + protocol: TCP + - name: terminal + image: beclab/terminal:v0.0.9 + env: + - name: PGID + value: "1000" + - name: PUID + value: "1000" + - name: TZ + value: Etc/UTC + - name: DISPLAY + value: ":0" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + command: + - apiserver + args: + - --namespace={{ .Release.Namespace }} + - --pod=bytetrade.io/terminal=codex + - --container=codex + - --v=3 + securityContext: + privileged: false + resources: + limits: + cpu: 50m + memory: 512Mi + requests: + cpu: 5m + memory: 100Mi +--- +apiVersion: v1 +kind: Service +metadata: + name: terminal + namespace: {{ .Release.Namespace }} +spec: + type: ClusterIP + selector: + io.kompose.service: terminal + ports: + - name: terminal + protocol: TCP + port: 80 + targetPort: 80 diff --git a/codex/values.yaml b/codex/values.yaml new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/codex/values.yaml @@ -0,0 +1 @@ +