Skip to content

codex: Unicode property escapeを含むtool schemaのpatternを除去して502を修正 - #2

Merged
t3ta merged 6 commits into
feat/gpt-6-astrafrom
fix/codex-strip-unicode-property-patterns
Sep 9, 2026
Merged

t3ta merged 6 commits into
feat/gpt-6-astrafrom
fix/codex-strip-unicode-property-patterns

Conversation

@t3ta

@t3ta t3ta commented Sep 9, 2026

Copy link
Copy Markdown
Owner

問題

claude-codex 経由のセッションが 502 で落ちる。エラー実体は ~/.local/state/claude-code-proxy/errors/ に記録されていた:

status 502 / model gpt-6-astra / provider codex
Invalid schema for function 'Artifact':
'^(?!__.*__$)[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}"\\./[\]]{1,200}$' is not a 'regex'.

これは Claude Code の Artifact ツールの field パラメータ(write_dbstr_replace 用)の pattern そのもの。ツール定義に載っているだけでリクエスト全体が弾かれるため、そのターンは必ず失敗する。

原因

read_tools が Anthropic の input_schema を無加工で Responses API の parameters に転送していた(Read ツールの description 補強を除く)。Responses API はツールスキーマの pattern を検証し、Unicode property escape (\p{...} / \P{...}) を含むものを is not a 'regex' で拒否する。

稼働中の proxy に最小ツール定義を投げて切り分けた結果:

送った pattern 結果
^[a-z]{1,10}$ OK
^(?!__).{1,10}$(lookahead のみ) OK
^[^\p{Cc}]{1,10}$ 502 拒否
^\P{Cc}{1,10}$ 502 拒否
items にネストした \p{} 502 拒否(再帰的に検査される)
pattern キー自体を削除 OK

犯人は lookahead ではなく \p{...} / \P{...} のみ。ネストしていても弾かれる。

変更

ツールスキーマを再帰的に走査し、Unicode property escape を含む pattern だけを落とす。

  • pattern はモデルが生成する引数への制約でしかないので、削除してもツールはそのまま使える。ターンごと失う方が損失が大きい。
  • Responses API が受理する pattern(lookahead を含む)は温存する。
  • リテラルのバックスラッシュに続く p\\p{L})は property escape と誤認しない。
  • 適用先は codex provider の関数ツール経路のみ。

検証

  • cargo test --lib providers::codex::translate::request — 33 passed
  • 追加テスト: Artifact の実 pattern とネストした items 内の pattern が除去され、^[0-9a-f]{32}$ と lookahead 付き pattern は保持されること/リテラルバックスラッシュの判定
  • 実機確認: 同一リクエスト(Artifact の実スキーマ入り)を未修正の 0.1.17-codex.5(稼働中 :18765)と本ビルド(:18766)に投げ、前者は 502、後者は end_turn で正常応答
  • cargo fmt --check / cargo clippy — 本 PR で触った request.rs に指摘なし(kimi/translate/accumulate.rs の fmt と cursor/sse.rs 等の clippy 指摘はベースブランチ由来で本 PR の対象外)

マージ後に必要な作業

  1. v0.1.17-codex.6 タグを打ってリリース
  2. claude-codex 側の pin 更新(install.sh:12bin/claude-codex-doctor:202v0.1.17-codex.5
  3. 反映後、全 claude-codex セッションを止めて共有 proxy を再起動

補足(本 PR の対象外)

read_output_formatjson_schema 経路(text.format.schema)も同じ無加工転送で、strict: true で送られる。同種の欠陥を持つ可能性はあるが、今回は再現・検証できていないためスコープ外とした。

🤖 Generated with Claude Code

https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv

Claude Code の Artifact ツールは field パラメータの JSON Schema に
`^(?!__.*__$)[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}"\\./[\]]{1,200}$` を持つ。
Responses API のスキーマ検証は `\p{...}` / `\P{...}` を受け付けず、
`Invalid schema for function 'Artifact': ... is not a 'regex'` で
リクエスト全体を弾くため、プロキシは 502 を返してターンが失敗していた。

read_tools は input_schema を無加工で parameters に転送していたので、
ツールスキーマを再帰的に走査してサポート外の pattern だけを落とす。
pattern はモデルが生成する引数への制約でしかなく、削除してもツールは
そのまま使える。lookahead は Responses API に受理されるため温存し、
リテラルのバックスラッシュに続く `p` は property escape と誤認しない。

未修正の 0.1.17-codex.5 と本ビルドに同一リクエストを投げて、前者が
502、後者が正常応答になることを実機で確認済み。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-09T08:37:56.108445Z 7b05c90 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a2699ae75

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/providers/codex/translate/request.rs Outdated
PR #2 のレビュー指摘 (P2) の対応。strip_unsupported_patterns が JSON 値を
無差別に再帰していたため、enum / const / default / examples に置かれた
インスタンスデータまでスキーマとして扱っていた。`"enum": [{"pattern": "\p{L}"}]`
のように pattern キーを持つオブジェクトが許容値である場合、それを {} へ
書き換えるとツールの許容引数そのものが変わってしまう。

サブスキーマを持つキーワード (properties / patternProperties / items /
prefixItems / anyOf / oneOf / allOf / $defs / definitions / dependentSchemas /
additionalProperties / propertyNames / contains / if / then / else / not 等)
だけを辿り、インスタンスデータには立ち入らない。items は 2020-12 の単一
スキーマと draft-07 のタプルの両方を扱う。additionalProperties: false の
ような非スキーマ値は object でないため素通りする。

実機確認: Artifact の実スキーマは本ビルドでも従来どおり通る。enum に
オブジェクトを含むスキーマは修正前の codex.5 でも同じく Responses API に
拒否されるため、本変更による差異ではない (codex.5 は enum 内の pattern を
消していたが、それでも拒否されており改変は副作用でしかなかった)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv
@t3ta

t3ta commented Sep 9, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f661341fb2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/providers/codex/translate/request.rs
PR #2 のレビュー指摘 (P2) の対応。`"dependencies": {"foo": {"properties":
{"bar": {"pattern": "\p{L}"}}}}` のような draft-07 の schema dependency を
走査していなかったため、そこに置かれたサポート外の pattern がそのまま
上流へ渡り、同じ 502 を引き起こしうる状態だった。tuple 形式の items を
明示的に扱っている以上、同じ draft-07 の dependencies も揃えるべき。

SUBSCHEMA_MAP_KEYS に dependencies を追加する。property dependency は
名前の配列であってオブジェクトではないため、strip_unsupported_patterns が
そのまま素通りする(特別扱い不要)。

テストに schema dependency と property dependency の両方を追加した。
dependencies を外すと当該テストが落ちることを確認済み。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv
@t3ta

t3ta commented Sep 9, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e070699275

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/providers/codex/translate/request.rs
Comment thread src/providers/codex/translate/request.rs
PR #2 のレビュー指摘 (P2 2件) の対応。

contentSchema: 2019-09/2020-12 のキーワードで、JSON を含む文字列の中身を
記述するサブスキーマを持つ。unevaluatedProperties や prefixItems を既に
扱っている以上ここも揃える必要があり、走査対象に追加する。

patternProperties: マップのキー自体が正規表現であり、キーに \p{...} が
入っていると値をいくらサニタイズしても同じ is not a 'regex' で弾かれる。
サポート外のキーを持つエントリはキーごと削除する。上流に渡せない制約で
ある以上、残してもリクエスト全体を失うだけのため。サポート済みのキーは
残し、その値は従来どおり再帰する。

テストを追加し、それぞれの対応を外すと当該テストが落ちることを確認済み。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv
@t3ta

t3ta commented Sep 9, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 526b531017

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/providers/codex/translate/request.rs Outdated
PR #2 のレビュー指摘 (P2) の対応。前段の実装はサポート外のキーを持つ
エントリを丸ごと削除していたが、additionalProperties: false と併用されて
いる場合、そのエントリは当該の動的プロパティを許可し記述する唯一の
サブスキーマである。削除するとかつてマッチしていたキーがすべて拒否され、
そのキーが必須なら充足不能なスキーマになり、502 は避けられてもツール
コールを生成できなくなる。

キーごと削除するのをやめ、Responses API が受理する ^.*$ へ値スキーマを
移す。置換後のキーは元より広くマッチするが、それは上流が元から強制でき
なかった制約を緩めるだけである。^.*$ が既に存在する場合はそれが全キーを
覆うため、既存のサブスキーマをそのまま残す。

テストを再キー方式に更新し、既存 ^.*$ との衝突ケースも追加した。退避を
外すと当該テストが落ちることを確認済み。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv
@t3ta

t3ta commented Sep 9, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a22b9fa1fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/providers/codex/translate/request.rs Outdated
PR #2 のレビュー指摘 (P2) の対応。キーを ^.*$ へ退避する前段の実装は、
兄弟エントリと重なったときに壊れる。^\p{L}+$ が string を、^[0-9]+$ が
number を要求している状況で前者を ^.*$ にすると、数値キーが両方に
マッチして充足不能になる。未サポートのエントリが複数ある場合に最初の
値スキーマしか残らない実装上の欠陥もあった。

削除・再キーのどちらもスキーマの意味を保てないため、キーには手を加えず
そのまま転送する方針に戻す。未サポートなキーを持つスキーマは上流で
拒否されるが、リクエストが正しく失敗するのは黙って歪んだスキーマを
送るより健全である。値のサブスキーマは従来どおりサニタイズする。

判断の経緯を strip_unsupported_patterns の doc コメントに残し、キーが
素通りすることを固定するテストに差し替えた。contentSchema・dependencies・
instance data の保護は影響を受けない。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv
@t3ta

t3ta commented Sep 9, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 7b05c9056c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@t3ta
t3ta merged commit d655f4c into feat/gpt-6-astra Sep 9, 2026
1 check passed
@t3ta
t3ta deleted the fix/codex-strip-unicode-property-patterns branch September 9, 2026 08:40
t3ta added a commit that referenced this pull request Sep 9, 2026
* codex: Unicode property escapeを含むtool schemaのpatternを除去して502を修正

fork の d655f4c (#2) を upstream v0.1.37 へ移植。

Claude Code の Artifact ツールは field パラメータの JSON Schema に
`^(?!__.*__$)[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}"\\./[\]]{1,200}$` を持つ。
Responses API のスキーマ検証は `\p{...}` / `\P{...}` を受け付けず、
`Invalid schema for function 'Artifact': ... is not a 'regex'` で
リクエスト全体を弾くため、プロキシは 502 を返してターンが失敗する
(upstream issue raine#141 と同じ事象)。

read_tools は input_schema を無加工で parameters に転送していたので、
ツールスキーマのサブスキーマ位置だけを再帰的に走査してサポート外の
pattern を落とす。enum / const / default / examples はインスタンス
データを持ち、そこでの pattern キーは制約ではなく許容値そのものなので
立ち入らない。patternProperties のキーは正規表現だが、削除も再キーも
スキーマの意味を保てないためそのまま転送する。

バージョンを 0.1.37-codex.1 とする。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv

* codex: auth をプロセス内キャッシュし上流の並行数を制限する

fork の c2eefec を upstream v0.1.37 へ移植。

get_auth() は上流リクエストのたびに /usr/bin/security を起動して macOS
Keychain を読んでいたため、並行リクエストが集中すると1リクエストにつき
1子プロセスが生まれ、プロセスのファイルディスクリプタ上限を使い切って
(EMFILE) 偽の 401 で認証が失敗し、リスナーごと落ちることがあった。短い
TTL のメモリキャッシュを置き、並行バーストを 1 回の keychain 読み取りに
畳み込む。自前のトークン更新時は write-through するため、更新直後の値は
TTL に関係なく即座に見える。

あわせて CCP_CODEX_MAX_CONCURRENT (既定 8) を追加し、開始中の上流
リクエスト数を制限する。ChatGPT はサブスクリプションの過剰な並行接続を
WebSocket ハンドシェイクの 401 で拒否するため、多数の並列エージェントが
共有プロキシに集中すると踏む。

upstream 側への適応:
- refresh_lock はプロセス全体で共有する CODEX_REFRESH_LOCK を使う
  upstream の実装をそのまま残し、キャッシュ用フィールドのみ追加した。
- 並行数の permit は handle_messages から handle_messages_inner へ移した。
  upstream が会話 identity 対応で本体をこちらへ集約したため。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv

* chore: fork 向けに release ワークフローを調整する

fork の 639123f のうち CI 部分を upstream v0.1.37 へ移植。

release ジョブを既定の GITHUB_TOKEN (top-level の contents: write) に
向ける。upstream の RELEASE_TOKEN シークレットは fork には無い。

homebrew-tap 更新ジョブを削除する。raine の tap を更新するもので、この
fork には関係しない。

バージョンの引き上げは移植済みのため、この移植では CI 部分のみ扱う。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv

* codex: permitをストリームタスクへ渡しauth読み取りを直列化する

PR #3 のレビュー指摘 (P1/P2) の対応。どちらも fork が v0.1.17 の時点から
抱えていた既存の欠陥で、移植で新たに作ったものではない。

P1: 並行数の permit をストリームタスクが保持する

ストリーミングでは live_stream_response が最初の意味のある出力で復帰し、
remaining_live_stream_response がまだ生きている上流接続を spawn した
タスクへ移す。permit をハンドラのスコープに置いていたため最初のチャンク
で解放され、CCP_CODEX_MAX_CONCURRENT を超える長時間ストリームが接続を
維持できてしまい、この limiter が防ぐはずの並行由来 401 を後続の
ハンドシェイクが踏みうる状態だった。

permit を live_stream_response → live_stream_response_once →
remaining_live_stream_response へ渡し、spawn したタスクへ move する。
リトライは permit を使い回すため、実際にストリームが始まったときだけ
消費する。

P2: キャッシュミス時の読み取りを直列化する

cold または期限切れのキャッシュでは、並行リクエストが揃って cache_get()
の None を観測してから誰も cache_store() に到達しておらず、各呼び出しが
独立に永続ストアを読んで macOS では /usr/bin/security を起動していた。
十分な規模のバーストでは、このキャッシュが防ぐはずの FD 枯渇を再現する。

ミス経路を single-flight ロックで保護し、ロック取得後にキャッシュを再確認
する。ロックはブロッキングなストア読み取りの周りだけで保持し、await を
跨がない。

いずれもテストを追加し、修正を外すと落ちることを確認済み。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv

* codex: compaction より前に並行数の permit を取得する

PR #3 のレビュー指摘 (P2) の対応。

CCP_CODEX_SERVER_COMPACTION=true で compact-boundary リクエストが来ると、
request_compaction が permit 取得より前に post_codex_for_owner を呼んで
いた。全 permit が埋まっている状況でも compaction リクエストが上限の外で
開始でき、CCP_CODEX_MAX_CONCURRENT + 1 本の接続が成立して、この limiter
が防ぐはずの並行由来の失敗を再現しうる状態だった。

permit の取得を compaction 分岐より前へ移し、以降の生成まで保持する。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Roy4wexpCM7KiEnkiMDMmv

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant