coderouter-cli 2.15.0__py3-none-any.whl → 2.16.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
coderouter/vscode_init.py CHANGED
@@ -112,6 +112,37 @@ _MANAGED_ENV_KEYS: tuple[str, ...] = (
112
112
  "CODEROUTER_MODE",
113
113
  )
114
114
 
115
+ # v2.16.0: Claude Code settings for a gateway that is not api.anthropic.com.
116
+ # Written by default (``--no-claude-code-env`` opts out):
117
+ #
118
+ # * ``ENABLE_TOOL_SEARCH=false`` — 2.1.304 turned tool search on behind a
119
+ # custom ANTHROPIC_BASE_URL. Only api.anthropic.com runs the search; the
120
+ # gateway would answer 400 on every session's first request and Claude
121
+ # Code would retry without it. Saying so up front skips that round trip.
122
+ # * ``CLAUDE_CODE_AUTO_MODE_SERVER=0`` — on gateways auto mode defaults to
123
+ # the server-side permission classifier, which a local backend does not
124
+ # provide; ``0`` keeps the classifier client-side (its requests then go
125
+ # through CodeRouter like any other request).
126
+ # * ``CLAUDE_CODE_MAX_CONTEXT_TOKENS`` — only when ``--max-context-tokens``
127
+ # is given. Since 2.1.285 Claude Code assumes a 1M window behind a
128
+ # gateway for Opus 4.7+ / Sonnet 5+ / Fable ids, so auto-compaction would
129
+ # wait far past what a local model holds.
130
+ CLAUDE_CODE_ENV_KEYS: tuple[str, ...] = (
131
+ "ENABLE_TOOL_SEARCH",
132
+ "CLAUDE_CODE_AUTO_MODE_SERVER",
133
+ "CLAUDE_CODE_MAX_CONTEXT_TOKENS",
134
+ )
135
+
136
+
137
+ def claude_code_env(*, max_context_tokens: int | None = None) -> dict[str, str]:
138
+ """v2.16.0: the Claude Code env vars ``vscode-init`` writes by default."""
139
+ env = {"ENABLE_TOOL_SEARCH": "false", "CLAUDE_CODE_AUTO_MODE_SERVER": "0"}
140
+ if max_context_tokens is not None:
141
+ if max_context_tokens <= 0:
142
+ raise ValueError("max_context_tokens must be positive")
143
+ env["CLAUDE_CODE_MAX_CONTEXT_TOKENS"] = str(max_context_tokens)
144
+ return env
145
+
115
146
 
116
147
  @dataclass(frozen=True)
117
148
  class FileOutcome:
@@ -155,6 +186,7 @@ def run_vscode_init(
155
186
  with_envrc: bool = False,
156
187
  dry_run: bool = False,
157
188
  force: bool = False,
189
+ extra_env: dict[str, str] | None = None,
158
190
  ) -> VSCodeInitResult:
159
191
  """Scaffold VSCode workspace settings for CodeRouter.
160
192
 
@@ -182,6 +214,9 @@ def run_vscode_init(
182
214
  When true, existing conflicting values are overwritten. Without
183
215
  this flag, a conflict is reported with a diff and the file is
184
216
  left untouched.
217
+ extra_env:
218
+ v2.16.0: additional variables to write next to the base ones
219
+ (the CLI passes :func:`claude_code_env`). Same conflict rules.
185
220
 
186
221
  Raises
187
222
  ------
@@ -205,6 +240,7 @@ def run_vscode_init(
205
240
  profile=profile,
206
241
  force=force,
207
242
  dry_run=dry_run,
243
+ extra_env=extra_env,
208
244
  )
209
245
  )
210
246
 
@@ -217,6 +253,7 @@ def run_vscode_init(
217
253
  profile=profile,
218
254
  force=force,
219
255
  dry_run=dry_run,
256
+ extra_env=extra_env,
220
257
  )
221
258
  )
222
259
 
@@ -235,6 +272,7 @@ def _apply_settings_json(
235
272
  profile: str | None,
236
273
  force: bool,
237
274
  dry_run: bool,
275
+ extra_env: dict[str, str] | None = None,
238
276
  ) -> FileOutcome:
239
277
  desired_env: dict[str, str] = {
240
278
  "ANTHROPIC_BASE_URL": base_url,
@@ -242,6 +280,8 @@ def _apply_settings_json(
242
280
  }
243
281
  if profile:
244
282
  desired_env["CODEROUTER_MODE"] = profile
283
+ if extra_env:
284
+ desired_env.update(extra_env)
245
285
 
246
286
  old_text = ""
247
287
  if path.exists():
@@ -401,6 +441,7 @@ def _apply_envrc(
401
441
  profile: str | None,
402
442
  force: bool,
403
443
  dry_run: bool,
444
+ extra_env: dict[str, str] | None = None,
404
445
  ) -> FileOutcome:
405
446
  """Write (or refresh) the managed block in ``.envrc``.
406
447
 
@@ -413,7 +454,7 @@ def _apply_envrc(
413
454
  which now *appends* the block rather than replacing the file. The
414
455
  operator's lines survive either way.
415
456
  """
416
- block = _render_envrc_block(base_url=base_url, profile=profile)
457
+ block = _render_envrc_block(base_url=base_url, profile=profile, extra_env=extra_env)
417
458
 
418
459
  old_text = ""
419
460
  if path.exists():
@@ -467,7 +508,7 @@ def _apply_envrc(
467
508
  before.rstrip("\n") + ("\n\n" if before.strip() else "")
468
509
  ) + block + ("\n\n" + after.lstrip("\n") if after.strip() else "\n")
469
510
 
470
- conflicts = _unmanaged_conflicts(outside)
511
+ conflicts = _unmanaged_conflicts(outside, extra_keys=tuple(extra_env or ()))
471
512
  if conflicts:
472
513
  # direnv applies exports in order, so a duplicate outside the
473
514
  # fence would silently win or lose depending on placement.
@@ -568,7 +609,9 @@ def _split_managed_block(text: str) -> tuple[str, str] | None:
568
609
  return text[:start], text[end + len(_ENVRC_END) :].lstrip("\n")
569
610
 
570
611
 
571
- def _render_envrc_block(*, base_url: str, profile: str | None) -> str:
612
+ def _render_envrc_block(
613
+ *, base_url: str, profile: str | None, extra_env: dict[str, str] | None = None
614
+ ) -> str:
572
615
  """The fenced block CodeRouter owns, markers included."""
573
616
  lines = [
574
617
  _ENVRC_BEGIN,
@@ -579,18 +622,25 @@ def _render_envrc_block(*, base_url: str, profile: str | None) -> str:
579
622
  ]
580
623
  if profile:
581
624
  lines.append(f'export CODEROUTER_MODE="{profile}"')
625
+ for key, value in (extra_env or {}).items():
626
+ lines.append(f'export {key}="{value}"')
582
627
  lines.append(_ENVRC_END)
583
628
  return "\n".join(lines)
584
629
 
585
630
 
586
- def _unmanaged_conflicts(outside_text: str) -> list[str]:
587
- """Managed variables the operator exports outside our block."""
631
+ def _unmanaged_conflicts(outside_text: str, *, extra_keys: tuple[str, ...] = ()) -> list[str]:
632
+ """Managed variables the operator exports outside our block.
633
+
634
+ v2.16.0: ``extra_keys`` (the Claude Code variables this run writes) are
635
+ checked too — but only when this run writes them, so an operator who
636
+ passed ``--no-claude-code-env`` can keep their own exports.
637
+ """
588
638
  found: list[str] = []
589
639
  for line in outside_text.splitlines():
590
640
  stripped = line.strip()
591
641
  if stripped.startswith("#"):
592
642
  continue
593
- for var in _MANAGED_ENVRC_VARS:
643
+ for var in (*_MANAGED_ENVRC_VARS, *extra_keys):
594
644
  if stripped.startswith((f"export {var}=", f"{var}=")) and var not in found:
595
645
  found.append(var)
596
646
  return found
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: coderouter-cli
3
- Version: 2.15.0
3
+ Version: 2.16.0
4
4
  Summary: Local-first, free-first, fallback-built-in LLM router. Claude Code / OpenAI compatible.
5
5
  Project-URL: Homepage, https://github.com/zephel01/CodeRouter
6
6
  Project-URL: Repository, https://github.com/zephel01/CodeRouter
@@ -66,7 +66,7 @@ Description-Content-Type: text/markdown
66
66
  ## 何ができるか — 30 秒で
67
67
 
68
68
  ```
69
- あなたのエージェント (Claude Code / codex / agy)
69
+ あなたのエージェント (Claude Code / agy ほか ※)
70
70
  │
71
71
  ▼
72
72
  ┌─ CodeRouter ─┐
@@ -76,6 +76,8 @@ Description-Content-Type: text/markdown
76
76
  └──────────────┘
77
77
  ```
78
78
 
79
+ ※ 現行の codex CLI は Responses API(`/v1/responses`)専用になったため、CodeRouter 経由ではまだ使えません(対応予定)。直結の代替手順 → [quickstart Pattern B](./docs/start/quickstart.md#pattern-b-codex-cli-で使う)
80
+
79
81
  **やってくれること:**
80
82
 
81
83
  - ローカルモデルが壊した tool calling を Claude Code に届く前に修復する
@@ -118,6 +120,8 @@ uvx --from coderouter-cli coderouter serve --port 8088
118
120
 
119
121
  恒久インストールしたい場合: `uv tool install coderouter-cli`
120
122
 
123
+ > **パッケージ名に注意**: PyPI のパッケージ名は **`coderouter-cli`** です。PyPI の `coderouter`(名前だけ同じ)は別の製品なので、`pip install coderouter` と打たないでください。
124
+
121
125
  ---
122
126
 
123
127
  ## Claude Code で使う
@@ -143,7 +147,7 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
143
147
  | Claude Code + ローカル Ollama で tool calling が壊れる | **必須** — tool 修復 (+ 必要なら wire 変換) |
144
148
  | Claude Code + ローカルで長時間回すと止まる | **必須級** — 6 系統ガード + self-healing |
145
149
  | Ollama v0.14+ / LM Studio にネイティブ直結で動いてる | **便利** — 直結に無い fallback / ガード / 診断を追加 (passthrough で翻訳ゼロ) |
146
- | codex / agy + Ollama 直繋ぎで動いてる | オプション — フォールバックが欲しいなら |
150
+ | codex / agy + Ollama 直繋ぎで動いてる | オプション — フォールバックが欲しいなら(codex は `/v1/responses` 対応後) |
147
151
  | Claude API を直接叩いてて問題ない | 不要 |
148
152
 
149
153
  詳細は → [要否判定ガイド](./docs/start/when-do-i-need-coderouter.md)
@@ -156,7 +160,7 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
156
160
 
157
161
  | 機能 | 何をしてくれるか |
158
162
  |---|---|
159
- | **Tool-call 修復** | ローカルモデルがテキストで吐いた JSON を正しい tool_use ブロックに復元 |
163
+ | **Tool-call 修復** | ローカルモデルがテキストで吐いた JSON を正しい tool_use ブロックに復元。実測は [修復ベンチ](./benchmarks/tool-repair/README.md)(壊れた tool call を出す 4 モデルで成功率 0% → 80〜100%、回帰コーパスで誤修復 0 件。CI でゲート) |
160
164
  | **3 層フォールバック** | ローカル → 無料クラウド → 有料の順に自動切替 |
161
165
  | **出力フィルタ** | `<think>` タグ漏れ、stop marker 漏れ、byte-fallback (`<0xNN>`) を自動除去/修復 |
162
166
  | **Wire 翻訳** | Anthropic 形式 ↔ OpenAI 形式を自動変換 (ネイティブ `/v1/messages` 対応 backend は passthrough で翻訳ゼロ) |
@@ -333,6 +337,14 @@ CodeRouter は backend ルーター層として独立して動きます。`OPENA
333
337
 
334
338
  シークレットは環境変数に置きます。[`docs/security.md`](./docs/guides/security.md) に完全な方針と報告手順があります。
335
339
 
340
+ リリースは多層で守っています。どれか 1 つを根拠に「安全」とは言いません(正規のパイプラインでビルドされた汚染版が出た例があります)。
341
+
342
+ - PyPI へは Trusted Publishing(OIDC)で公開し、長期の API トークンを置かない
343
+ - PyPI 側の公開許可は `release.yml` の `pypi` 環境に限定している
344
+ - タグは事前検査スクリプトを通してから打つ(version・CHANGELOG・main の一致を機械的に確認)
345
+ - 実行時の依存は 5 個に絞っている
346
+ - 各リリースに SBOM(CycloneDX)を添付する
347
+
336
348
  ## License
337
349
 
338
350
  MIT
@@ -1,11 +1,12 @@
1
1
  coderouter/__init__.py,sha256=ghdjPrLtnRzY8fyQ4CJZI1UJKADyNTLtA3G7se8H7Ns,696
2
2
  coderouter/__main__.py,sha256=-LCgxJnvgUV240HjQKv7ly-mn2NuKHpC4nCpvTHjeSU,130
3
- coderouter/cli.py,sha256=Nbx1ur_HnssFtuM48yPELwhY40veVNnTAfK7OVF2uVc,42400
3
+ coderouter/cli.py,sha256=-QPJ2wTJIpa4TvIFObNaV4hyv_OeDtoLebc692ZWYQA,44775
4
4
  coderouter/cli_stats.py,sha256=CCjzc1G4hTRHZ2gG1XhxhDpUkJnnl3NXbcbp1T18jpg,29894
5
5
  coderouter/cost.py,sha256=32h6uzb4nxh2eA5d2Hn3kD9yJbtis6CFDAbeIy5KRkM,7431
6
6
  coderouter/credentials.py,sha256=R_PdrcA941_jJX_U8hxrjPDTCVVzLd4dsw2c00KwAwE,12991
7
- coderouter/doctor.py,sha256=wmPunlvqm2s7x3VGLjexqHPLD2oejwE3Mu04V8y-xn4,89869
7
+ coderouter/doctor.py,sha256=0EUqKaEw2GaqX6zGKjR-bVDdlmBznFIklSz3yIoQbE0,91969
8
8
  coderouter/doctor_apply.py,sha256=tZT3bEd1G6t67YRhf1TGY4NlSvZuJJbnEqN-3AKy8Hc,29972
9
+ coderouter/doctor_claude_code.py,sha256=15ZdyUg0M_wZGEBN9Q3eb_D75lncqxQi1dNV6irWh2U,6621
9
10
  coderouter/env_security.py,sha256=FEBZnXfJ0xE39kmMMn39zk0W_DRRnmcB_REmP9f4xWo,14796
10
11
  coderouter/errors.py,sha256=Xmq67lheyw8iv3Ox39jh2c4tvNI5RcUR4QkoxVDN6l4,1130
11
12
  coderouter/gguf_introspect.py,sha256=Scu0JjUfLHj7T7TL0HQIm1AZcGYrXsjkaMMSN9HkTro,16121
@@ -20,23 +21,23 @@ coderouter/rollback.py,sha256=Bqxx1MALTDLYc0BtGMEMqRyiZIWFoAZJH_RBQw-M5ow,7675
20
21
  coderouter/secret_redaction.py,sha256=Rg71gqKN6jnybZ6UvCvXIvnThI9uRBvmOqC2grSUSUk,23159
21
22
  coderouter/token_estimation.py,sha256=7klQYA4FIg1vtjQGWAhwiBhiLwyz8KTetrLVXFJLGIc,16957
22
23
  coderouter/token_estimation_accurate.py,sha256=GTfzrBVnvAGjeVzmzAeUdOYZvWZKLAxcxPpFiJGlzjk,4609
23
- coderouter/vscode_init.py,sha256=ZEROtETsHjyBkLzZKPnF-zsBpLJx4ph0vmgyty6kNYQ,33433
24
+ coderouter/vscode_init.py,sha256=rs3S0FOuPFZhhDvE547Zonhj98al66Jc8G1wvBnFq40,35915
24
25
  coderouter/adapters/__init__.py,sha256=7dIDSZ-FE_0iSqLSDc_lK1idRdLTKcM2hP9tCJipgPI,463
25
- coderouter/adapters/anthropic_native.py,sha256=JxOaU-ymU1K3Tnvhufi_li1qChW69XtUszKJ2DdFlDQ,29936
26
- coderouter/adapters/base.py,sha256=qW0QMbO08Dw2ZDruL9rCvCxA0FXhKnSodlK9g-8Y350,13535
27
- coderouter/adapters/openai_compat.py,sha256=Kl5AACqOHxTPUn8c-4IFu4ug9_E3loLKTm2yYmvalho,23872
26
+ coderouter/adapters/anthropic_native.py,sha256=fYM4uXdYYvXfYBgz2dPjdPwv-yKY7XfnXp18YZNCsjg,30185
27
+ coderouter/adapters/base.py,sha256=8TxlhYwrLk6hFg3_j84yoJq-55QxDmyfo0BLeTcRMro,14573
28
+ coderouter/adapters/openai_compat.py,sha256=-6jD8RLjlocmnGCkGWm6C0j5fLumadJb9J-wZW4a-GQ,24121
28
29
  coderouter/adapters/registry.py,sha256=XNc1wmFv_oZlqKS0rA693TRDdbq1sZ-OIcofXOVOtq0,3680
29
30
  coderouter/config/__init__.py,sha256=FODEn74fN-qZnt4INPSHswqhOlEgpL6-_onxsitSx8g,274
30
31
  coderouter/config/capability_registry.py,sha256=RZgzHF54dXy0CCDocRCz2ee21qXGbbgTSKTkRI9iLL4,16936
31
32
  coderouter/config/env_file.py,sha256=CoMK27fuAXm-NtoLzXb8yN2E-wDFjHQuFwiIlmgTBQw,10356
32
33
  coderouter/config/loader.py,sha256=7FoJXWaO_vN9FAjUStJDwI4aAYcUQQgMJtq5BNy8Pnc,12419
33
- coderouter/config/schemas.py,sha256=0NM5KtVGsjH8BPBeBfgM-ItfOYQKhyI-P_3EbJjIaps,146436
34
+ coderouter/config/schemas.py,sha256=pabFnhY070rWhzl9JF9jqyfRGhrD4VSwIC-xWsHGskc,148608
34
35
  coderouter/data/__init__.py,sha256=uNyfD9jaCvTWsBAWtaw1Fr25OSxzv3psGMfBjT1z0Cc,328
35
36
  coderouter/data/model-capabilities.yaml,sha256=S9jt6SC6-3s2-icZ_n-a14iEMnc2yB1C2R6q-N_tZWQ,19309
36
37
  coderouter/guards/__init__.py,sha256=5qliYBqygvVPneej7nx0uSjxDKsz7t8VzvrDgVBJlvU,1170
37
38
  coderouter/guards/_fingerprint.py,sha256=qsgNzIq9jv3FHrKL39nGJARp0cMenpN_QmWoJu87vU4,4835
38
39
  coderouter/guards/backend_health.py,sha256=GLUVQ5BhU6i8Cxz_FrgIMs5AZ-YSKAW8veFWgvn9GFI,12565
39
- coderouter/guards/context_budget.py,sha256=gw3MkiHDjpLmQTlTdJT6gRAxYEnoU0xmwSvPZk_miOQ,23059
40
+ coderouter/guards/context_budget.py,sha256=zbplo_1G54kHITdr4kkgUxjQX20Y8MN2Z4XdxETAGwI,23834
40
41
  coderouter/guards/continuous_probe.py,sha256=WIfS-apVMWXGv7bPBxxkJssePa95I4fT0mi4PNqK5iE,12181
41
42
  coderouter/guards/drift_actions.py,sha256=A6pY5CR480Ct5rCVyjlBvjPFVc93eu_r5qcUpK9mWKc,3602
42
43
  coderouter/guards/drift_detection.py,sha256=lW45EZDGRleDUTstw_CHlfUiwLUrlDHX8g7ncuOYNEw,13962
@@ -45,12 +46,14 @@ coderouter/guards/memory_pressure.py,sha256=9Xm-b7rv9Td5kPNmAFoL3sNmaOR5zT8NLdn6
45
46
  coderouter/guards/self_healing.py,sha256=XeUlgFWGqMQ5E9YvvzR2CsHRJOAJEyDChqRN0xmZ0vo,16841
46
47
  coderouter/guards/tool_loop.py,sha256=EzeMcmU7BLeTW2jsRVevU81l5rhWcn1oUr7EpzgXjVM,15209
47
48
  coderouter/ingress/__init__.py,sha256=WQsCH2CGJCAhy0mS6GSEdeYZRkkQu2OHDsP4CJWTLug,155
48
- coderouter/ingress/anthropic_routes.py,sha256=wlOb7ChWHMvuERR0lj8TF4MfPis2ZKegceoak4eREes,31131
49
+ coderouter/ingress/anthropic_errors.py,sha256=SYmcqHeQWuiAsgBjquOemmv_KIr23WTyWtjohuzLOLg,7352
50
+ coderouter/ingress/anthropic_routes.py,sha256=O2ejNl8SdXaMt-EArgsPa47NHxzvIRtVOeHMr5kJApM,39963
49
51
  coderouter/ingress/app.py,sha256=ZOx7dSvMxaWS4CzXOOEwgzFuycAVgAeWKCN6lFNF-F0,22433
50
52
  coderouter/ingress/dashboard_routes.py,sha256=nPW5_pJe27-hzqCs4sqVVn0BrgXB_7Wcd4qZ6cirvWo,26736
51
53
  coderouter/ingress/launcher_routes.py,sha256=uP_Otp9JE0fydUt1YP-wYcnS8Kj5RPLNIFf88YpfkPM,141535
52
54
  coderouter/ingress/metrics_routes.py,sha256=4s_f9CY8nVIdQBfXxyUMlN7r5_cXHOaAu7PvNbUuoxg,4609
53
55
  coderouter/ingress/openai_routes.py,sha256=9DHVtGe1mpcUBH3ziDL4RGpEA-LzjyANpBIN3Kfbpxc,14193
56
+ coderouter/ingress/tool_search.py,sha256=JYnJ8SUqPmBfZmsl41TdBQNnux0mwbidKdsr5qn15Hk,3753
54
57
  coderouter/ingress/ui_auth.py,sha256=uCWB5IaMQRNFYdY39FQ5DDVhsoRQJoqimZNSAu_QK_Q,3742
55
58
  coderouter/metrics/__init__.py,sha256=7Es351DPS7yLM0yVF_F0eesmiD83n7Zzhie44chht38,1465
56
59
  coderouter/metrics/collector.py,sha256=-744UrUS6_aEY7hbwuvoX0Nn7wuOsQ57IIVr52nPe2M,63268
@@ -64,7 +67,7 @@ coderouter/routing/adaptive.py,sha256=G2o377twGSjbUh65wiIFx6klnpFGjsD_nI3oDvcBwh
64
67
  coderouter/routing/auto_router.py,sha256=y4v0c8u5F9f98Vmhx1vRcKPiOgAvpzbFqr6TIh058h0,13341
65
68
  coderouter/routing/budget.py,sha256=PblmVKJGs_BwNa9uDHAA8hmZ4XIVKv38mHAeU0V3OMs,8451
66
69
  coderouter/routing/capability.py,sha256=rRQhzTgQYFTFDNYcSLKvq3xjdw6B1w7T-3jS7PTMI14,27864
67
- coderouter/routing/fallback.py,sha256=Hzy-_2_zK64GUqGGcOZP-RgOq8wZ4PdBpVu4OBTx8dM,172282
70
+ coderouter/routing/fallback.py,sha256=0tN6LPFijZ5cZ-Fc2VpipIVvFHpgCgNCx1COXfenxgs,172687
68
71
  coderouter/routing/fallback_trace.py,sha256=0BysXY1CZqSvVTuePbgmHbu1AKkHLMX7hsuG6rKlDdE,19787
69
72
  coderouter/state/__init__.py,sha256=XoGcPmmBQSiZWML2S0juSveQ78xfhtdeCliNnVyzu7E,1088
70
73
  coderouter/state/audit_log.py,sha256=CEFNJht2WZ8mqesI8CzeuL63NfzFzAZ7wF88auyl6l0,11444
@@ -77,8 +80,8 @@ coderouter/translation/anthropic.py,sha256=ZQQGS9itN_3o7IKD68lKr5gR_Kem32Jsd7OcG
77
80
  coderouter/translation/convert.py,sha256=VrstDAMsUpcQ1VgMTn_-ETp1OjGX8v0ZGhCkcd4icyU,53037
78
81
  coderouter/translation/tool_repair.py,sha256=1p8rmdyyscGX2g0DDOYitMnLv-nKfR1SLuLaRB4z7GM,64244
79
82
  coderouter/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
- coderouter_cli-2.15.0.dist-info/METADATA,sha256=1TbuS8h0n05w9EzQ25lzLSF38CH05QLjz1tLjY-3nR0,16897
81
- coderouter_cli-2.15.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
82
- coderouter_cli-2.15.0.dist-info/entry_points.txt,sha256=-dnLfD1YZ2WjH2zSdNCvlO65wYltM9bsHt9Fhg3yGss,51
83
- coderouter_cli-2.15.0.dist-info/licenses/LICENSE,sha256=wkEzoR86jFw33jvfOHjULqmkGEfxTFMgMaJnpR8mPRw,1065
84
- coderouter_cli-2.15.0.dist-info/RECORD,,
83
+ coderouter_cli-2.16.0.dist-info/METADATA,sha256=qGzoESa_lbm11v64IwRodTt2j1HC7uOd2-hvsXN1ETg,18221
84
+ coderouter_cli-2.16.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
85
+ coderouter_cli-2.16.0.dist-info/entry_points.txt,sha256=-dnLfD1YZ2WjH2zSdNCvlO65wYltM9bsHt9Fhg3yGss,51
86
+ coderouter_cli-2.16.0.dist-info/licenses/LICENSE,sha256=wkEzoR86jFw33jvfOHjULqmkGEfxTFMgMaJnpR8mPRw,1065
87
+ coderouter_cli-2.16.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.32.0
2
+ Generator: hatchling 1.32.4
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any