clauderipple 0.8.10 → 0.9.1

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.
Files changed (69) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.es.md +21 -15
  3. package/README.ja.md +13 -9
  4. package/README.ko.md +23 -9
  5. package/README.md +26 -11
  6. package/README.pt-BR.md +21 -15
  7. package/README.zh-CN.md +13 -9
  8. package/dist/app/package.json +1 -1
  9. package/dist/cli/src/codex.js +3 -1
  10. package/dist/cli/src/settings.js +5 -2
  11. package/dist/mod/.claude-plugin/plugin.json +9 -1
  12. package/dist/mod/hooks/cache.ts +60 -0
  13. package/dist/mod/hooks/compact.ts +40 -0
  14. package/dist/mod/hooks/handoff.ts +43 -0
  15. package/dist/mod/hooks/i18n.ts +2716 -0
  16. package/dist/mod/hooks/judge.ts +242 -0
  17. package/dist/mod/hooks/ladder.js +179 -0
  18. package/dist/mod/hooks/ladder.ts +174 -0
  19. package/dist/mod/hooks/modes.ts +93 -0
  20. package/dist/mod/hooks/register.tsx +1458 -256
  21. package/dist/mod/hooks/session.ts +62 -0
  22. package/dist/mod/hooks/settings.js +342 -0
  23. package/dist/mod/hooks/settings.ts +321 -0
  24. package/dist/mod/hooks/stats.ts +59 -0
  25. package/dist/mod/hooks/ui/agents.tsx +138 -0
  26. package/dist/mod/hooks/ui/alerts.tsx +373 -0
  27. package/dist/mod/hooks/ui/art.ts +628 -0
  28. package/dist/mod/hooks/ui/band.tsx +836 -0
  29. package/dist/mod/hooks/ui/kit.tsx +258 -0
  30. package/dist/mod/hooks/ui/log.tsx +109 -0
  31. package/dist/mod/hooks/ui/parts.tsx +217 -0
  32. package/dist/mod/hooks/ui/ripple.ts +614 -0
  33. package/dist/mod/hooks/ui/settings.tsx +376 -0
  34. package/dist/mod/hooks/ui/setup.tsx +148 -0
  35. package/dist/mod/hooks/ui/theme.ts +217 -0
  36. package/dist/mod/hooks/ui/view.ts +371 -0
  37. package/dist/mod/hooks/worker.ts +1 -1
  38. package/dist/mod/hooks/workers.ts +217 -0
  39. package/dist/mod/tests/register.test.tsx +1730 -0
  40. package/dist/mod/tests/ui.test.tsx +853 -0
  41. package/dist/mod/tsconfig.json +2 -1
  42. package/dist/mod/types/index.d.ts +320 -1
  43. package/dist/router/src/admin.js +170 -52
  44. package/dist/router/src/agents.js +24 -5
  45. package/dist/router/src/bootstrap.js +4 -2
  46. package/dist/router/src/config.js +3 -0
  47. package/dist/router/src/health.js +33 -0
  48. package/dist/router/src/index.js +1 -0
  49. package/dist/router/src/ingress/models.js +4 -1
  50. package/dist/router/src/mod-settings.js +120 -0
  51. package/dist/router/src/model-policy.js +6 -0
  52. package/dist/router/src/model-scores.js +159 -0
  53. package/dist/router/src/picker.js +7 -0
  54. package/dist/router/src/providers/chatgpt/index.js +23 -5
  55. package/dist/router/src/providers/chatgpt/translate.js +4 -1
  56. package/dist/router/src/providers/google/index.js +8 -3
  57. package/dist/router/src/providers/openai/index.js +6 -1
  58. package/dist/router/src/providers/openai/translate.js +6 -1
  59. package/dist/router/src/proxy.js +62 -24
  60. package/dist/router/src/requestlog.js +78 -20
  61. package/dist/router/src/version.js +1 -1
  62. package/dist/ui/app.js +908 -209
  63. package/dist/ui/favicon-32.png +0 -0
  64. package/dist/ui/favicon.svg +12 -0
  65. package/dist/ui/i18n.js +919 -233
  66. package/dist/ui/index.html +159 -87
  67. package/dist/ui/style.css +789 -410
  68. package/docs/ARCHITECTURE.md +141 -0
  69. package/package.json +7 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,65 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.1 — 2026-10-14
4
+
5
+ ### Added
6
+
7
+ - **The request log records more of each request** (`logs/requests.jsonl`, #55). Every new field is
8
+ optional, so older records and readers keep working.
9
+ - Anthropic's request id or the message id, to match a row to the transcript, subagents included.
10
+ - Why a request ended before reaching a model, with the right provider instead of `anthropic`.
11
+ - Whether a call was the auto-mode classifier or a web search.
12
+ - An explicit `cacheWrite: 0`.
13
+ - The service tier that was asked for and the one the provider served. This shows whether a Fast
14
+ request was honoured (#54).
15
+
16
+ ### Fixed
17
+
18
+ - Saving the mod settings failed on Windows with `EPERM … fsync` since 0.9.0 (#53).
19
+ - "Haiku returned no verdict" appeared now and then. When Haiku breaks the end of its JSON, the
20
+ verdict's complete fields are now read instead of the whole answer being dropped (#53).
21
+ - A response over 64KiB that arrived in one piece (every compressed answer, for one) lost its usage
22
+ and stop reason in the request log.
23
+ - Alert cards centre their buttons when the title takes two lines.
24
+ - Ripple Remote no longer lists a resumed session's old halves, and a host restart no longer marks
25
+ idle sessions as just used.
26
+
27
+ ## 0.9.0 — 2026-10-13
28
+
29
+ ### Added
30
+
31
+ - **The ripple mod.** A band above the Code tab's prompt shows reasoning effort, context, the
32
+ cache timer, and which model answered each request with its cache hit. Log opens the request
33
+ log, ⚙ opens quick settings, and the dashboard has a mod page with every setting.
34
+ - **Effort picked per prompt.** A small judge model (Haiku 5.5 or Jev) reads the prompt and the
35
+ recent turns, then sets low through max. Pick an effort yourself whenever you want; Auto comes
36
+ back when you switch it on.
37
+ - **Workers picked per task.** The main chat hands work to `ripple:auto`, and the judge decides
38
+ how hard each task is and sends it to the matching rung: light work to DeepSeek or GLM, hard work
39
+ to GPT or Opus. Rungs, candidate models and named modes (prefer or avoid a model, eager
40
+ delegation, switch off at a quota reset) are set on the dashboard. Every pick is kept in
41
+ `logs/worker-picks.jsonl`.
42
+ - **Warnings that save tokens.** Cards appear when the prompt cache has gone cold on a big chat,
43
+ when the context gets heavy, and when a plan window passes 80%. Each card offers compact or a
44
+ handoff.
45
+ - **Handoff to a fresh session.** A handoff writes a summary and opens a new session in the same
46
+ folder with it in the prompt box. The current chat is left as it is.
47
+ - **리플이**, the mascot, on the band and every card, acting out what the band is doing. Mod text
48
+ in six languages, following the Mac's system language.
49
+ - **Artificial Analysis scores** for every routable model, refreshed daily, used to rank worker
50
+ candidates by measured cost.
51
+ - A provider that answers 402 or says its quota is exhausted is skipped for a while.
52
+
53
+ ### Changed
54
+
55
+ - Dashboard settings are rebuilt in the style of macOS System Settings.
56
+ - The mod's settings live in the router, so every session follows a change at once.
57
+
58
+ ### Fixed
59
+
60
+ - Judge-only models such as Jev no longer appear in pickers, worker lists or Codex.
61
+ - The install script works under macOS `/bin/sh` again.
62
+
3
63
  ## 0.8.10 — 2026-10-10
4
64
 
5
65
  ### Added
package/README.es.md CHANGED
@@ -1,7 +1,3 @@
1
- <p align="center">
2
- <img src="docs/media/icon.png" width="128" alt="ClaudeRipple">
3
- </p>
4
-
5
1
  <h1 align="center">ClaudeRipple</h1>
6
2
 
7
3
  <p align="center"><a href="README.md">English</a> · <a href="README.ko.md">한국어</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <b>Español</b> · <a href="README.pt-BR.md">Português (BR)</a></p>
@@ -26,16 +22,24 @@
26
22
  </p>
27
23
 
28
24
  <p align="center">
29
- <img src="docs/media/tour.png" width="880" alt="Recorrido por la configuración de ClaudeRipple: estado, asignación de modelos, proveedores, clientes, registro de solicitudes">
25
+ <a href="https://github.com/PBJ-2/clauderipple/releases/download/v0.9.0/clauderipple-demo.mp4"><img src="docs/media/demo.webp" width="880" alt="Recorrido de un minuto: otros modelos en el propio menú de modelos de Claude Desktop, el esfuerzo ajustado en cada prompt y cada subagente enviado al modelo adecuado. Haz clic para ver el vídeo completo."></a><br>
26
+ <sub>Recorrido de un minuto: otros modelos en el propio menú de modelos de Claude Desktop, el esfuerzo ajustado en cada prompt y cada subagente enviado al modelo adecuado. Haz clic para ver el vídeo completo.</sub>
30
27
  </p>
31
28
 
32
29
  <table align="center">
33
30
  <tr>
34
- <td align="center" width="34%"><img src="docs/media/picker-zoom.png" width="300" alt="Nombres reales en el selector de Claude Desktop"><br><sub>Modelos GPT con su nombre real en el selector de Claude Desktop</sub></td>
35
- <td align="center" width="66%"><img src="docs/media/luna-answer.png" alt="GPT-5.6 Luna respondiendo en la pestaña Code de Claude Desktop"><br><sub>GPT-5.6 Luna respondiendo en la pestaña Code, con el esfuerzo que elegiste</sub></td>
31
+ <td align="center" width="34%"><img src="docs/media/picker.png" width="300" alt="GPT, DeepSeek, GLM y Gemini en el propio menú de modelos de Claude Desktop"><br><sub>GPT, DeepSeek, GLM y Gemini en el propio menú de modelos de Claude Desktop</sub></td>
32
+ <td align="center" width="66%"><img src="docs/media/answer.png" alt="GPT-6 Astra trabajando en la pestaña Code, con cada solicitud registrada a la derecha"><br><sub>GPT-6 Astra trabajando en la pestaña Code, con cada solicitud registrada a la derecha</sub></td>
33
+ </tr>
34
+ <tr>
35
+ <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="Subagentes con DeepSeek y GLM, identificados en el panel de tareas"><br><sub>Subagentes con DeepSeek y GLM, identificados en el panel de tareas</sub></td>
36
+ </tr>
37
+ <tr>
38
+ <td colspan="2" align="center"><img src="docs/media/mod-band.png" alt="El mod ripple: esfuerzo, contexto, temporizador de caché y qué modelo respondió, con su acierto de caché"><br><sub>El mod ripple: esfuerzo, contexto, temporizador de caché y qué modelo respondió, con su acierto de caché</sub></td>
36
39
  </tr>
37
40
  <tr>
38
- <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="Subagentes con GPT-5.6 Terra y Sol, identificados en el panel de tareas en segundo plano"><br><sub>Subagentes con GPT-5.6 Terra y Sol, identificados en el panel de tareas en segundo plano</sub></td>
41
+ <td align="center" width="50%"><img src="docs/media/mod-alerts.png" alt="Avisos cuando la caché se enfría o un límite está cerca, y traspaso a un chat nuevo"><br><sub>Avisos cuando la caché se enfría o un límite está cerca, y traspaso a un chat nuevo</sub></td>
42
+ <td align="center" width="50%"><img src="docs/media/mod-settings.png" alt="Ajustes rápidos: esfuerzo automático, el juez, modos de workers"><br><sub>Ajustes rápidos: esfuerzo automático, el juez, modos de workers</sub></td>
39
43
  </tr>
40
44
  </table>
41
45
 
@@ -304,13 +308,15 @@ los modelos que asignas van a tu proveedor, y todo lo demás va a Anthropic byte
304
308
  la última hora.
305
309
  - **Etiquetas de subagentes.** El panel de tareas en segundo plano muestra
306
310
  `Terra·high · Review` en lugar de un genérico "Agent".
307
- - **La ruta, donde escribes.** Un mod de Claude Code añade una línea encima del prompt:
308
- adónde fue tu última solicitud, su esfuerzo, el acierto de caché y el tiempo. `Log` (o
309
- `/ripple-log`) abre el registro de solicitudes en un panel lateral, con colores según el
310
- proveedor y el resultado; `×` (o `/ripple-bar`) oculta la línea. El mismo mod mantiene a
311
- un worker en su propio modelo cuando la llamada a Agent indica otro, y lee su marcador
312
- `[[ripple: name@level]]` esté donde esté en el prompt. Un solo interruptor en la
313
- pantalla Clientes, o `clauderipple mod on`.
311
+ - **El mod ripple, encima del prompt.** Una banda muestra el esfuerzo de razonamiento, el
312
+ contexto, el temporizador de caché y qué modelo respondió tu última solicitud, con su
313
+ acierto de caché. Un pequeño modelo juez (Haiku 5.5 o Jev) lee cada prompt junto con los
314
+ turnos recientes y fija el esfuerzo, de low a max. El trabajo delegado va a `ripple:auto`,
315
+ y el juez envía cada tarea a un worker según su dificultad: lo ligero a DeepSeek o GLM, lo
316
+ difícil a GPT u Opus. Unas tarjetas avisan cuando la caché se ha enfriado, el contexto pesa
317
+ demasiado o una ventana del plan pasa del 80 %, y ofrecen compactar o traspasar a una sesión
318
+ nueva en la misma carpeta. `Log` (o `/ripple-log`) abre el registro de solicitudes en un
319
+ panel lateral. Un solo interruptor en la pantalla Clientes, o `clauderipple mod on`.
314
320
  - **Imágenes con tu suscripción de ChatGPT.** `clauderipple image "<prompt>"`, con
315
321
  imágenes de referencia y fondos transparentes. A los subagentes se les explica cómo
316
322
  hacerlo, así que un worker de GPT o DeepSeek puede crear una imagen y verla sin una
package/README.ja.md CHANGED
@@ -1,7 +1,3 @@
1
- <p align="center">
2
- <img src="docs/media/icon.png" width="128" alt="ClaudeRipple">
3
- </p>
4
-
5
1
  <h1 align="center">ClaudeRipple</h1>
6
2
 
7
3
  <p align="center"><a href="README.md">English</a> · <a href="README.ko.md">한국어</a> · <a href="README.zh-CN.md">简体中文</a> · <b>日本語</b> · <a href="README.es.md">Español</a> · <a href="README.pt-BR.md">Português (BR)</a></p>
@@ -25,16 +21,24 @@
25
21
  </p>
26
22
 
27
23
  <p align="center">
28
- <img src="docs/media/tour.png" width="880" alt="ClaudeRippleの設定画面:ステータス、モデルマッピング、プロバイダー、クライアント、リクエストログ">
24
+ <a href="https://github.com/PBJ-2/clauderipple/releases/download/v0.9.0/clauderipple-demo.mp4"><img src="docs/media/demo.webp" width="880" alt="1分ツアー:Claude Desktop自身のモデルメニューに他のモデルが並び、プロンプトごとに推論強度を決め、サブエージェントは合うモデルに振り分けます。クリックで全編を再生。"></a><br>
25
+ <sub>1分ツアー:Claude Desktop自身のモデルメニューに他のモデルが並び、プロンプトごとに推論強度を決め、サブエージェントは合うモデルに振り分けます。クリックで全編を再生。</sub>
29
26
  </p>
30
27
 
31
28
  <table align="center">
32
29
  <tr>
33
- <td align="center" width="34%"><img src="docs/media/picker-zoom.png" width="300" alt="Claude Desktopのピッカーに実際の名前で表示"><br><sub>Claude DesktopのピッカーにGPTモデルが実際の名前で並ぶ</sub></td>
34
- <td align="center" width="66%"><img src="docs/media/luna-answer.png" alt="Claude DesktopのCodeタブで応答するGPT-5.6 Luna"><br><sub>選んだ推論強度で、Codeタブから応答するGPT-5.6 Luna</sub></td>
30
+ <td align="center" width="34%"><img src="docs/media/picker.png" width="300" alt="Claude Desktop本来のモデルメニューにGPT・DeepSeek・GLM・Gemini"><br><sub>Claude Desktop本来のモデルメニューにGPT・DeepSeek・GLM・Gemini</sub></td>
31
+ <td align="center" width="66%"><img src="docs/media/answer.png" alt="Codeタブで作業するGPT-6 Astra、右側にすべてのリクエストログ"><br><sub>Codeタブで作業するGPT-6 Astra、右側にすべてのリクエストログ</sub></td>
32
+ </tr>
33
+ <tr>
34
+ <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="DeepSeekとGLMで動くサブエージェント。タスクパネルに実際の名前で表示"><br><sub>DeepSeekとGLMで動くサブエージェント。タスクパネルに実際の名前で表示</sub></td>
35
+ </tr>
36
+ <tr>
37
+ <td colspan="2" align="center"><img src="docs/media/mod-band.png" alt="rippleモッド:推論強度、コンテキスト、キャッシュタイマー、実際に応答したモデルとキャッシュヒット率"><br><sub>rippleモッド:推論強度、コンテキスト、キャッシュタイマー、実際に応答したモデルとキャッシュヒット率</sub></td>
35
38
  </tr>
36
39
  <tr>
37
- <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="GPT-5.6 TerraとSolで動くサブエージェント。バックグラウンドタスクパネルにモデル名が表示される"><br><sub>GPT-5.6 TerraとSolで動くサブエージェント。バックグラウンドタスクパネルにモデル名が表示される</sub></td>
40
+ <td align="center" width="50%"><img src="docs/media/mod-alerts.png" alt="キャッシュが冷えたり上限が近づくと警告、新しいチャットへの引き継ぎ"><br><sub>キャッシュが冷えたり上限が近づくと警告、新しいチャットへの引き継ぎ</sub></td>
41
+ <td align="center" width="50%"><img src="docs/media/mod-settings.png" alt="クイック設定:自動推論強度、判定モデル、ワーカーモード"><br><sub>クイック設定:自動推論強度、判定モデル、ワーカーモード</sub></td>
38
42
  </tr>
39
43
  </table>
40
44
 
@@ -167,7 +171,7 @@ Claude Codeのシステムプロンプトとツールの説明はClaude向けに
167
171
  - **設計段階で正しさを確保**。プロンプトキャッシュを保持(Anthropicのキャッシュブレークポイントと、安定したOpenAIのプレフィックス)、Claude Codeのサーバー側スレッドを処理、ツール呼び出しと画像を往復で変換、推論強度を各モデルが受け付ける範囲に調整、互換ベンダー向けにはAnthropic専用のリクエストフィールドを除去。
168
172
  - **本物のリクエストログ**。誰が依頼し、どのモデルが応答したか、入力 / キャッシュ / 出力のトークン数、レイテンシ、ステータスをリクエストごとに記録し、直近1時間のサマリーも表示します。
169
173
  - **サブエージェントの名前タグ**。バックグラウンドタスクパネルに、汎用の「Agent」ではなく`Terra·high · Review`のように表示されます。
170
- - **入力する場所にルートを表示**。Claude Codeのmodがプロンプトの上に1行を表示します。直前のリクエストの行き先、推論強度、キャッシュヒット率、所要時間です。`Log`(または`/ripple-log`)でリクエストログをサイドペインに開き、プロバイダーと結果ごとに色分けして表示します。`×`(または`/ripple-bar`)でこの行を隠せます。同じmodは、Agent呼び出しで別のモデルが指定されてもワーカーを自分のモデルのまま動かし、`[[ripple: name@level]]`マーカーがプロンプトのどこにあっても読み取ります。「クライアント」画面のスイッチ1つ、または`clauderipple mod on`で有効にできます。
174
+ - **プロンプトの上のrippleモッド**。帯1本に推論強度、コンテキスト、キャッシュタイマー、直前のリクエストに実際に応答したモデルとキャッシュヒット率を表示します。小さな判定モデル(Haiku 5.5またはJev)がプロンプトごとに直近の会話と合わせて読み、lowからmaxまで推論強度を決めます。任せた作業は`ripple:auto`に渡り、判定モデルが難しさに応じてワーカーを選びます。軽い作業はDeepSeekやGLM、難しい作業はGPTやOpusへ。キャッシュが冷えたとき、コンテキストが重くなったとき、プランの上限が80%を超えたときにカードで知らせ、圧縮か、同じフォルダの新しいセッションへの引き継ぎを提案します。`Log`(または`/ripple-log`)でリクエストログをサイドペインに開きます。「クライアント」画面のスイッチ1つ、または`clauderipple mod on`で有効にできます。
171
175
  - **ChatGPTのサブスクリプションで画像を生成**。`clauderipple image "<prompt>"`で、参照画像や透明背景にも対応します。サブエージェントにもやり方が伝えられているので、GPTやDeepSeekのワーカーでも、画像ツールなしで画像を作って確認できます。
172
176
  - **必要なら軽量なワーカーを**。スイッチ1つで、生成されるサブエージェントに、セッションのすべてのMCPサーバーとプラグインではなく、ワーカーが使うツールだけを渡します。あるワーカーの最初のリクエストは33kトークンから9kトークンに減りました。
173
177
  - **ターミナルを使いたくない人のために**。ワンクリックの接続テストとモデル検出付きのプロバイダープリセット、ドロップダウンによるモデルマッピング、自動保存、韓国語と英語のUI。独自のランタイムを同梱し、初回起動時に自らセットアップするメニューバーアプリ。署名・公証済みです。
package/README.ko.md CHANGED
@@ -1,5 +1,9 @@
1
1
  <p align="center">
2
- <img src="docs/media/icon.png" width="128" alt="ClaudeRipple">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="brand/mark-dark.svg">
4
+ <source media="(prefers-color-scheme: light)" srcset="brand/mark.svg">
5
+ <img src="brand/mark.svg" width="120" height="120" alt="ClaudeRipple 마스코트 리플이: 속이 빈 파문 고리에 물마루가 말려 오른 모습">
6
+ </picture>
3
7
  </p>
4
8
 
5
9
  <h1 align="center">ClaudeRipple</h1>
@@ -25,16 +29,24 @@
25
29
  </p>
26
30
 
27
31
  <p align="center">
28
- <img src="docs/media/tour.png" width="880" alt="ClaudeRipple 설정 화면: 상태, 모델 매핑, 프로바이더, 클라이언트, 요청 로그">
32
+ <a href="https://github.com/PBJ-2/clauderipple/releases/download/v0.9.0/clauderipple-demo.mp4"><img src="docs/media/demo.webp" width="880" alt="1분 둘러보기: Claude Desktop의 모델 메뉴에 다른 모델이 들어가고, 프롬프트마다 추론 강도를 정하고, 서브에이전트는 맞는 모델로 보냅니다. 누르면 전체 영상이 열립니다."></a><br>
33
+ <sub>1분 둘러보기: Claude Desktop의 모델 메뉴에 다른 모델이 들어가고, 프롬프트마다 추론 강도를 정하고, 서브에이전트는 맞는 모델로 보냅니다. 누르면 전체 영상이 열립니다.</sub>
29
34
  </p>
30
35
 
31
36
  <table align="center">
32
37
  <tr>
33
- <td align="center" width="34%"><img src="docs/media/picker-zoom.png" width="300" alt="Claude Desktop 피커에 실제 이름으로"><br><sub>Claude Desktop 피커에 GPT 모델이 실제 이름으로</sub></td>
34
- <td align="center" width="66%"><img src="docs/media/luna-answer.png" alt="Code 탭에서 답하는 GPT-5.6 Luna"><br><sub>Code 탭에서 고른 추론 강도 그대로 답하는 GPT-5.6 Luna</sub></td>
38
+ <td align="center" width="34%"><img src="docs/media/picker.png" width="300" alt="Claude Desktop의 원래 모델 메뉴에 GPT·DeepSeek·GLM·Gemini"><br><sub>Claude Desktop의 원래 모델 메뉴에 GPT·DeepSeek·GLM·Gemini</sub></td>
39
+ <td align="center" width="66%"><img src="docs/media/answer.png" alt="Code 탭에서 일하는 GPT-6 Astra, 오른쪽에는 모든 요청 기록"><br><sub>Code 탭에서 일하는 GPT-6 Astra, 오른쪽에는 모든 요청 기록</sub></td>
35
40
  </tr>
36
41
  <tr>
37
- <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="백그라운드 작업 패널에 실제 모델 이름으로 표시된 서브에이전트"><br><sub>GPT-5.6 Terra·Sol로 도는 서브에이전트, 작업 패널에 실제 이름으로</sub></td>
42
+ <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="DeepSeek·GLM으로 도는 서브에이전트, 작업 패널에 실제 이름으로"><br><sub>DeepSeek·GLM으로 도는 서브에이전트, 작업 패널에 실제 이름으로</sub></td>
43
+ </tr>
44
+ <tr>
45
+ <td colspan="2" align="center"><img src="docs/media/mod-band.png" alt="리플 모드: 추론 강도, 컨텍스트, 캐시 타이머, 실제로 답한 모델과 캐시 적중률"><br><sub>리플 모드: 추론 강도, 컨텍스트, 캐시 타이머, 실제로 답한 모델과 캐시 적중률</sub></td>
46
+ </tr>
47
+ <tr>
48
+ <td align="center" width="50%"><img src="docs/media/mod-alerts.png" alt="캐시가 식거나 한도가 가까우면 경고, 새 대화로 인수인계"><br><sub>캐시가 식거나 한도가 가까우면 경고, 새 대화로 인수인계</sub></td>
49
+ <td align="center" width="50%"><img src="docs/media/mod-settings.png" alt="빠른 설정: 자동 추론 강도, 판정 모델, 워커 모드"><br><sub>빠른 설정: 자동 추론 강도, 판정 모델, 워커 모드</sub></td>
38
50
  </tr>
39
51
  </table>
40
52
 
@@ -237,10 +249,12 @@ ClaudeRipple은 Claude Code 프로세스만 신뢰하는 작은 HTTPS 프록시
237
249
  서버 측 스레드 처리, 도구 호출과 이미지 왕복, 모델이 받는 범위로 추론 강도 클램프, 호환 벤더에는 Anthropic 전용 필드 제거.
238
250
  - **제대로 된 요청 로그.** 누가 물었고 어떤 모델이 답했는지, 입력·캐시·출력 토큰, 지연, 상태를 요청마다. 한 시간 요약 포함.
239
251
  - **서브에이전트 이름표.** 백그라운드 작업 패널에 "Agent" 대신 `Terra·high · Review`가 보입니다.
240
- - **입력창에서 보이는 경로.** Claude Code mod가 입력창 위에 한 줄을 띄웁니다. 마지막 요청이 어디로 갔는지, 추론 강도·캐시
241
- 적중률·시간까지. `Log`(또는 `/ripple-log`)로 요청 로그를 옆 패널에 프로바이더·결과별 색으로 띄우고, `×`(또는
242
- `/ripple-bar`)로 줄을 숨깁니다. 같은 mod가 Agent 호출에 다른 모델이 붙어도 워커를 제 모델로 돌리고,
243
- `[[ripple: 이름@강도]]` 표식을 프롬프트 어디에 두든 읽습니다. 클라이언트 화면의 스위치 하나, 또는 `clauderipple mod on`.
252
+ - **입력창 위의 리플 모드.** 띠 하나에 추론 강도, 컨텍스트, 캐시 타이머, 마지막 요청에 실제로 답한 모델과 캐시
253
+ 적중률이 보입니다. 작은 판정 모델(Haiku 5.5 또는 Jev)이 프롬프트마다 최근 대화와 함께 읽고 low부터 max까지 추론
254
+ 강도를 정합니다. 맡긴 일은 `ripple:auto`로 가고, 판정 모델이 난이도에 따라 워커를 고릅니다. 가벼운 일은 DeepSeek·GLM,
255
+ 어려운 일은 GPT·Opus로. 캐시가 식었을 때, 컨텍스트가 무거워졌을 때, 요금제 한도가 80%를 넘었을 때 카드로 알려 주고,
256
+ 압축이나 같은 폴더 새 세션으로의 인수인계를 제안합니다. `Log`(또는 `/ripple-log`)로 요청 로그를 옆 패널에 엽니다.
257
+ 클라이언트 화면의 스위치 하나, 또는 `clauderipple mod on`.
244
258
  - **ChatGPT 구독으로 이미지 생성.** `clauderipple image "<프롬프트>"`. 참고 이미지와 투명 배경도 됩니다. 서브에이전트에도
245
259
  방법이 적혀 있어, GPT나 DeepSeek 워커가 이미지 도구 없이 이미지를 만들고 직접 확인합니다.
246
260
  - **원하면 가벼운 워커.** 스위치 하나로, 생성된 서브에이전트에 세션의 MCP·플러그인 도구 전부 대신 워커가 쓰는 도구만
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  <p align="center">
2
- <img src="docs/media/icon.png" width="128" alt="ClaudeRipple">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="brand/mark-dark.svg">
4
+ <source media="(prefers-color-scheme: light)" srcset="brand/mark.svg">
5
+ <img src="brand/mark.svg" width="120" height="120" alt="The ClaudeRipple mascot: a hollow ripple ring with a curling wave crest">
6
+ </picture>
3
7
  </p>
4
8
 
5
9
  <h1 align="center">ClaudeRipple</h1>
@@ -26,16 +30,24 @@
26
30
  </p>
27
31
 
28
32
  <p align="center">
29
- <img src="docs/media/tour.png" width="880" alt="ClaudeRipple settings tour: status, model mapping, providers, clients, request log">
33
+ <a href="https://github.com/PBJ-2/clauderipple/releases/download/v0.9.0/clauderipple-demo.mp4"><img src="docs/media/demo.webp" width="880" alt="A one-minute tour: other models in Claude Desktop's own model menu, effort set for every prompt, and each subagent sent to the model that fits. Click for the full video."></a><br>
34
+ <sub>A one-minute tour: other models in Claude Desktop's own model menu, effort set for every prompt, and each subagent sent to the model that fits. Click for the full video.</sub>
30
35
  </p>
31
36
 
32
37
  <table align="center">
33
38
  <tr>
34
- <td align="center" width="34%"><img src="docs/media/picker-zoom.png" width="300" alt="Real names in the Claude Desktop picker"><br><sub>GPT models under their real names in the Claude Desktop picker</sub></td>
35
- <td align="center" width="66%"><img src="docs/media/luna-answer.png" alt="GPT-5.6 Luna answering in the Claude Desktop Code tab"><br><sub>GPT-5.6 Luna answering in the Code tab, at the effort you chose</sub></td>
39
+ <td align="center" width="34%"><img src="docs/media/picker.png" width="300" alt="GPT, DeepSeek, GLM and Gemini in Claude Desktop's own model menu"><br><sub>GPT, DeepSeek, GLM and Gemini in Claude Desktop's own model menu</sub></td>
40
+ <td align="center" width="66%"><img src="docs/media/answer.png" alt="GPT-6 Astra working in the Code tab, every request logged on the right"><br><sub>GPT-6 Astra working in the Code tab, every request logged on the right</sub></td>
36
41
  </tr>
37
42
  <tr>
38
- <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="Subagents on GPT-5.6 Terra and Sol, named in the background-task panel"><br><sub>Subagents on GPT-5.6 Terra and Sol, named in the background-task panel</sub></td>
43
+ <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="Subagents on DeepSeek and GLM, named in the background-task panel"><br><sub>Subagents on DeepSeek and GLM, named in the background-task panel</sub></td>
44
+ </tr>
45
+ <tr>
46
+ <td colspan="2" align="center"><img src="docs/media/mod-band.png" alt="The ripple mod: effort, context, cache timer, and which model answered with its cache hit"><br><sub>The ripple mod: effort, context, cache timer, and which model answered with its cache hit</sub></td>
47
+ </tr>
48
+ <tr>
49
+ <td align="center" width="50%"><img src="docs/media/mod-alerts.png" alt="Warnings when the cache goes cold or a limit is near, and a handoff to a fresh chat"><br><sub>Warnings when the cache goes cold or a limit is near, and a handoff to a fresh chat</sub></td>
50
+ <td align="center" width="50%"><img src="docs/media/mod-settings.png" alt="Quick settings: automatic effort, the judge, worker modes"><br><sub>Quick settings: automatic effort, the judge, worker modes</sub></td>
39
51
  </tr>
40
52
  </table>
41
53
 
@@ -286,12 +298,15 @@ you map go to your provider, everything else goes to Anthropic byte for byte.
286
298
  latency, status, per request, with a one-hour summary.
287
299
  - **Subagent name tags.** The background-task panel shows `Terra·high · Review`
288
300
  instead of a generic "Agent".
289
- - **The route, where you type.** A Claude Code mod puts one line above the prompt:
290
- where your last request went, its effort, cache hit and time. `Log` (or `/ripple-log`)
291
- opens the request log in a side pane, color-coded by provider and result; `×` (or
292
- `/ripple-bar`) hides the line. The same mod keeps a worker on its own model when the
293
- Agent call names another, and reads its `[[ripple: name@level]]` marker wherever it sits
294
- in the prompt. One switch on the Clients screen, or `clauderipple mod on`.
301
+ - **The ripple mod, above the prompt.** A band shows the reasoning effort, context, cache
302
+ timer, and which model answered your last request with its cache hit. A small judge
303
+ model (Haiku 5.5 or Jev) reads each prompt with the recent turns and sets the effort,
304
+ low through max. Delegated work goes to `ripple:auto`, and the judge sends each task to
305
+ a worker by difficulty: light work to DeepSeek or GLM, hard work to GPT or Opus. Cards
306
+ warn when the cache has gone cold, the context gets heavy or a plan window passes 80%,
307
+ and offer compact or a handoff to a fresh session in the same folder. `Log` (or
308
+ `/ripple-log`) opens the request log in a side pane. One switch on the Clients screen,
309
+ or `clauderipple mod on`.
295
310
  - **Images from your ChatGPT subscription.** `clauderipple image "<prompt>"`, with
296
311
  reference images and transparent backgrounds. Subagents are told how, so a GPT or
297
312
  DeepSeek worker can make an image and look at it without an image tool.
package/README.pt-BR.md CHANGED
@@ -1,7 +1,3 @@
1
- <p align="center">
2
- <img src="docs/media/icon.png" width="128" alt="ClaudeRipple">
3
- </p>
4
-
5
1
  <h1 align="center">ClaudeRipple</h1>
6
2
 
7
3
  <p align="center"><a href="README.md">English</a> · <a href="README.ko.md">한국어</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.es.md">Español</a> · <b>Português (BR)</b></p>
@@ -26,16 +22,24 @@
26
22
  </p>
27
23
 
28
24
  <p align="center">
29
- <img src="docs/media/tour.png" width="880" alt="Tour pelas configurações do ClaudeRipple: status, mapeamento de modelos, provedores, clientes, log de requisições">
25
+ <a href="https://github.com/PBJ-2/clauderipple/releases/download/v0.9.0/clauderipple-demo.mp4"><img src="docs/media/demo.webp" width="880" alt="Tour de um minuto: outros modelos no próprio menu de modelos do Claude Desktop, o esforço ajustado a cada prompt e cada subagente enviado ao modelo certo. Clique para ver o vídeo completo."></a><br>
26
+ <sub>Tour de um minuto: outros modelos no próprio menu de modelos do Claude Desktop, o esforço ajustado a cada prompt e cada subagente enviado ao modelo certo. Clique para ver o vídeo completo.</sub>
30
27
  </p>
31
28
 
32
29
  <table align="center">
33
30
  <tr>
34
- <td align="center" width="34%"><img src="docs/media/picker-zoom.png" width="300" alt="Nomes reais no seletor do Claude Desktop"><br><sub>Modelos GPT com os nomes reais no seletor do Claude Desktop</sub></td>
35
- <td align="center" width="66%"><img src="docs/media/luna-answer.png" alt="GPT-5.6 Luna respondendo na aba Code do Claude Desktop"><br><sub>GPT-5.6 Luna respondendo na aba Code, com o esforço que você escolheu</sub></td>
31
+ <td align="center" width="34%"><img src="docs/media/picker.png" width="300" alt="GPT, DeepSeek, GLM e Gemini no próprio menu de modelos do Claude Desktop"><br><sub>GPT, DeepSeek, GLM e Gemini no próprio menu de modelos do Claude Desktop</sub></td>
32
+ <td align="center" width="66%"><img src="docs/media/answer.png" alt="GPT-6 Astra trabalhando na aba Code, com cada requisição registrada à direita"><br><sub>GPT-6 Astra trabalhando na aba Code, com cada requisição registrada à direita</sub></td>
33
+ </tr>
34
+ <tr>
35
+ <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="Subagentes no DeepSeek e no GLM, identificados no painel de tarefas"><br><sub>Subagentes no DeepSeek e no GLM, identificados no painel de tarefas</sub></td>
36
+ </tr>
37
+ <tr>
38
+ <td colspan="2" align="center"><img src="docs/media/mod-band.png" alt="O mod ripple: esforço, contexto, timer do cache e qual modelo respondeu, com o acerto de cache"><br><sub>O mod ripple: esforço, contexto, timer do cache e qual modelo respondeu, com o acerto de cache</sub></td>
36
39
  </tr>
37
40
  <tr>
38
- <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="Subagentes no GPT-5.6 Terra e no Sol, identificados no painel de tarefas em segundo plano"><br><sub>Subagentes no GPT-5.6 Terra e no Sol, identificados no painel de tarefas em segundo plano</sub></td>
41
+ <td align="center" width="50%"><img src="docs/media/mod-alerts.png" alt="Avisos quando o cache esfria ou um limite está perto, e passagem para um chat novo"><br><sub>Avisos quando o cache esfria ou um limite está perto, e passagem para um chat novo</sub></td>
42
+ <td align="center" width="50%"><img src="docs/media/mod-settings.png" alt="Ajustes rápidos: esforço automático, o juiz, modos de workers"><br><sub>Ajustes rápidos: esforço automático, o juiz, modos de workers</sub></td>
39
43
  </tr>
40
44
  </table>
41
45
 
@@ -299,13 +303,15 @@ que você mapeia vão para o seu provedor, e todo o resto vai para a Anthropic b
299
303
  última hora.
300
304
  - **Identificação dos subagentes.** O painel de tarefas em segundo plano mostra
301
305
  `Terra·high · Review` em vez de um "Agent" genérico.
302
- - **A rota, onde você digita.** Um mod do Claude Code coloca uma linha acima do prompt:
303
- para onde foi sua última requisição, o esforço, o acerto de cache e o tempo. `Log` (ou
304
- `/ripple-log`) abre o log de requisições em um painel lateral, com cores por provedor e
305
- por resultado; `×` (ou `/ripple-bar`) oculta a linha. O mesmo mod mantém um worker no
306
- próprio modelo quando a chamada do Agent indica outro, e lê o marcador
307
- `[[ripple: name@level]]` dele onde quer que esteja no prompt. Basta um botão na tela
308
- **Clientes**, ou `clauderipple mod on`.
306
+ - **O mod ripple, acima do prompt.** Uma faixa mostra o esforço de raciocínio, o contexto, o
307
+ timer do cache e qual modelo respondeu sua última requisição, com o acerto de cache. Um
308
+ pequeno modelo juiz (Haiku 5.5 ou Jev) lê cada prompt junto com os turnos recentes e define
309
+ o esforço, de low a max. O trabalho delegado vai para `ripple:auto`, e o juiz manda cada
310
+ tarefa para um worker conforme a dificuldade: o leve para DeepSeek ou GLM, o difícil para
311
+ GPT ou Opus. Cartões avisam quando o cache esfriou, o contexto ficou pesado ou uma janela do
312
+ plano passou de 80%, e oferecem compactar ou passar para uma sessão nova na mesma pasta.
313
+ `Log` (ou `/ripple-log`) abre o log de requisições em um painel lateral. Basta um botão na
314
+ tela **Clientes**, ou `clauderipple mod on`.
309
315
  - **Imagens pela sua assinatura do ChatGPT.** `clauderipple image "<prompt>"`, com imagens
310
316
  de referência e fundos transparentes. Os subagentes recebem instruções de como fazer,
311
317
  então um worker GPT ou DeepSeek consegue criar uma imagem e olhar para ela sem uma
package/README.zh-CN.md CHANGED
@@ -1,7 +1,3 @@
1
- <p align="center">
2
- <img src="docs/media/icon.png" width="128" alt="ClaudeRipple">
3
- </p>
4
-
5
1
  <h1 align="center">ClaudeRipple</h1>
6
2
 
7
3
  <p align="center"><a href="README.md">English</a> · <a href="README.ko.md">한국어</a> · <b>简体中文</b> · <a href="README.ja.md">日本語</a> · <a href="README.es.md">Español</a> · <a href="README.pt-BR.md">Português (BR)</a></p>
@@ -26,16 +22,24 @@
26
22
  </p>
27
23
 
28
24
  <p align="center">
29
- <img src="docs/media/tour.png" width="880" alt="ClaudeRipple 设置界面一览:状态、模型映射、供应商、客户端、请求日志">
25
+ <a href="https://github.com/PBJ-2/clauderipple/releases/download/v0.9.0/clauderipple-demo.mp4"><img src="docs/media/demo.webp" width="880" alt="一分钟概览:其他模型出现在 Claude Desktop 自带的模型菜单里,每条提示设定推理强度,子代理分派给合适的模型。点击观看完整视频。"></a><br>
26
+ <sub>一分钟概览:其他模型出现在 Claude Desktop 自带的模型菜单里,每条提示设定推理强度,子代理分派给合适的模型。点击观看完整视频。</sub>
30
27
  </p>
31
28
 
32
29
  <table align="center">
33
30
  <tr>
34
- <td align="center" width="34%"><img src="docs/media/picker-zoom.png" width="300" alt="Claude Desktop 模型选择器中的真实模型名称"><br><sub>GPT 模型以真实名称出现在 Claude Desktop 的模型选择器中</sub></td>
35
- <td align="center" width="66%"><img src="docs/media/luna-answer.png" alt="GPT-5.6 Luna 在 Claude Desktop 的 Code 标签页中作答"><br><sub>GPT-5.6 Luna 在 Code 标签页中按你选择的推理强度作答</sub></td>
31
+ <td align="center" width="34%"><img src="docs/media/picker.png" width="300" alt="Claude Desktop 自带的模型菜单里出现 GPT、DeepSeek、GLM、Gemini"><br><sub>Claude Desktop 自带的模型菜单里出现 GPT、DeepSeek、GLM、Gemini</sub></td>
32
+ <td align="center" width="66%"><img src="docs/media/answer.png" alt="GPT-6 Astra 在 Code 标签页中工作,右侧记录每一个请求"><br><sub>GPT-6 Astra 在 Code 标签页中工作,右侧记录每一个请求</sub></td>
33
+ </tr>
34
+ <tr>
35
+ <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="运行在 DeepSeek 和 GLM 上的子代理,在任务面板中显示真实名称"><br><sub>运行在 DeepSeek 和 GLM 上的子代理,在任务面板中显示真实名称</sub></td>
36
+ </tr>
37
+ <tr>
38
+ <td colspan="2" align="center"><img src="docs/media/mod-band.png" alt="ripple 模组:推理强度、上下文、缓存计时,以及实际作答的模型和缓存命中率"><br><sub>ripple 模组:推理强度、上下文、缓存计时,以及实际作答的模型和缓存命中率</sub></td>
36
39
  </tr>
37
40
  <tr>
38
- <td colspan="2" align="center"><img src="docs/media/subagents.png" alt="运行在 GPT-5.6 Terra 和 Sol 上的子代理,在后台任务面板中显示模型名称"><br><sub>运行在 GPT-5.6 Terra 和 Sol 上的子代理,在后台任务面板中显示模型名称</sub></td>
41
+ <td align="center" width="50%"><img src="docs/media/mod-alerts.png" alt="缓存变冷或额度将满时提醒,并可交接到新的对话"><br><sub>缓存变冷或额度将满时提醒,并可交接到新的对话</sub></td>
42
+ <td align="center" width="50%"><img src="docs/media/mod-settings.png" alt="快速设置:自动推理强度、判定模型、工作者模式"><br><sub>快速设置:自动推理强度、判定模型、工作者模式</sub></td>
39
43
  </tr>
40
44
  </table>
41
45
 
@@ -168,7 +172,7 @@ Claude Code 的系统提示词和工具描述是为 Claude 编写的,所以其
168
172
  - **从设计上保证正确。** 保留提示缓存(Anthropic 缓存断点和稳定的 OpenAI 前缀),处理 Claude Code 的服务端线程,完整保留双向传递的工具调用和图片,将推理强度限定在各模型接受的范围内,并为兼容厂商去除 Anthropic 专有的请求字段。
169
173
  - **真正的请求日志。** 逐条记录谁发起了请求、哪个模型作答、输入 / 缓存 / 输出 token、延迟和状态,并附最近一小时的汇总。
170
174
  - **子代理名称标签。** 后台任务面板显示 `Terra·high · Review`,而不是笼统的“Agent”。
171
- - **在输入处看到路由。** 一个 Claude Code mod 会在输入框上方显示一行信息:上一个请求发往何处、推理强度、缓存命中率和耗时。`Log`(或 `/ripple-log`)会在侧边窗格中打开请求日志,按供应商和结果着色;`×`(或 `/ripple-bar`)可隐藏这一行。当 Agent 调用指定了其他模型时,同一个 mod 还会让 worker 留在自己的模型上,并读取它的 `[[ripple: name@level]]` 标记,无论标记位于提示词何处。在“客户端”页面上打开一个开关即可启用,或运行 `clauderipple mod on`。
175
+ - **输入框上方的 ripple 模组。** 一条横栏显示推理强度、上下文、缓存计时,以及上一个请求实际由哪个模型作答和缓存命中率。一个小型判定模型(Haiku 5.5 或 Jev)会结合最近的对话阅读每条提示词,在 low 到 max 之间设定推理强度。委派的工作交给 `ripple:auto`,由判定模型按难度挑选 worker:轻活交给 DeepSeek 或 GLM,难活交给 GPT 或 Opus。缓存变冷、上下文变重或套餐额度超过 80% 时会弹出卡片提醒,并提供压缩或交接到同一文件夹的新会话。`Log`(或 `/ripple-log`)会在侧边窗格中打开请求日志。在“客户端”页面上打开一个开关即可启用,或运行 `clauderipple mod on`。
172
176
  - **用 ChatGPT 订阅生成图片。** `clauderipple image "<prompt>"`,支持参考图和透明背景。子代理会被告知用法,因此 GPT 或 DeepSeek worker 无需图像工具也能生成图片并查看结果。
173
177
  - **按需精简 worker。** 打开一个开关,生成的子代理就只获得 worker 会用到的工具,而不是会话中的所有 MCP 服务器和插件:某个 worker 的首个请求因此从 33k token 降到了 9k token。
174
178
  - **为不想碰终端的人而设计。** 供应商预设支持一键连接测试和模型发现,下拉式模型映射,自动保存,韩语和英语界面。菜单栏应用自带运行时,首次启动时自动完成设置。经过签名和公证。
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "private": true,
3
- "version": "0.8.10",
3
+ "version": "0.9.1",
4
4
  "type": "commonjs"
5
5
  }
@@ -4,6 +4,7 @@
4
4
  import fs from "node:fs";
5
5
  import os from "node:os";
6
6
  import path from "node:path";
7
+ import { isJudgeOnlyModel } from "../../router/src/model-policy.js";
7
8
  const START = "# >>> ClaudeRipple Codex provider >>>";
8
9
  const END = "# <<< ClaudeRipple Codex provider <<<";
9
10
  const PROFILE_START = "# >>> ClaudeRipple Codex profile >>>";
@@ -76,7 +77,8 @@ export function writeCodexCatalog(models, home = codexHome()) {
76
77
  catch {
77
78
  return undefined;
78
79
  }
79
- const entries = (cached.models ?? []).filter((m) => typeof m.slug === "string");
80
+ models = models.filter(m => !isJudgeOnlyModel(m.id));
81
+ const entries = (cached.models ?? []).filter((m) => typeof m.slug === "string" && !isJudgeOnlyModel(m.slug));
80
82
  const template = entries.find((m) => m.slug === "gpt-5.5" && m.model_messages) ?? entries.find((m) => m.model_messages);
81
83
  if (!template)
82
84
  return undefined;
@@ -216,11 +216,14 @@ export function agentTitleHookEnabled() {
216
216
  }
217
217
  // ---- Status mod (packages/mod) ------------------------------------------------------------
218
218
  /** The `name` in packages/mod/.claude-plugin/plugin.json: how our entry is told from anyone else's. */
219
- export const STATUS_MOD_NAME = "clauderipple-status";
219
+ export const STATUS_MOD_NAME = "ripple";
220
+ /** Its name until 0.8.10: an entry an older install added is still ours to replace or remove. */
221
+ const OLD_STATUS_MOD_NAMES = ["clauderipple-status"];
220
222
  const PLUGIN_DIRS = "CLAUDE_CODE_PLUGIN_DIRS";
221
223
  function isStatusMod(dir) {
222
224
  try {
223
- return JSON.parse(fs.readFileSync(path.join(dir, ".claude-plugin", "plugin.json"), "utf8")).name === STATUS_MOD_NAME;
225
+ const name = JSON.parse(fs.readFileSync(path.join(dir, ".claude-plugin", "plugin.json"), "utf8")).name;
226
+ return name === STATUS_MOD_NAME || OLD_STATUS_MOD_NAMES.includes(name);
224
227
  }
225
228
  catch {
226
229
  return false;
@@ -1 +1,9 @@
1
- { "name": "clauderipple-status", "version": "0.1.0", "description": "Shows where ClaudeRipple sent each request and its request log, and keeps ClaudeRipple workers on their own model and effort.", "types": "./types/index.d.ts" }
1
+ {
2
+ "name": "ripple",
3
+ "displayName": "ClaudeRipple",
4
+ "version": "0.7.0",
5
+ "description": "Picks the reasoning effort for every prompt and the worker for every delegated task, can keep the prompt cache warm, and shows where ClaudeRipple sent each request.",
6
+ "author": { "name": "ClaudeRipple" },
7
+ "license": "GPL-3.0-only",
8
+ "types": "./types/index.d.ts"
9
+ }
@@ -0,0 +1,60 @@
1
+ import type { ModelForkResult } from 'claude-code'
2
+ import type { CacheMemo, Settings, Usage, WarmState } from '../types'
3
+ import { weighted } from './stats'
4
+ import { t } from './i18n.ts'
5
+ import type { Lang } from './i18n.ts'
6
+
7
+ const HOUR = 3600000
8
+ const FIVE_MINUTES = 300000
9
+
10
+ export function ttlFromUsage(usage: Usage): number {
11
+ if ((usage.cache_creation?.ephemeral_1h_input_tokens ?? 0) > 0) return HOUR
12
+ if ((usage.cache_creation?.ephemeral_5m_input_tokens ?? 0) > 0) return FIVE_MINUTES
13
+ return HOUR
14
+ }
15
+
16
+ /** A five-minute tail must not shorten a mostly-read hour-long prefix. */
17
+ export function nextMemo(prev: CacheMemo | null, usage: Usage, now: number): CacheMemo {
18
+ const total = (usage.input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0)
19
+ const mostlyRead = (usage.cache_read_input_tokens ?? 0) > total / 2
20
+ const explicit = (usage.cache_creation?.ephemeral_1h_input_tokens ?? 0) > 0 || (usage.cache_creation?.ephemeral_5m_input_tokens ?? 0) > 0
21
+ let ttlMs = explicit ? ttlFromUsage(usage) : prev?.ttlMs ?? HOUR
22
+ if (prev?.ttlMs === HOUR && mostlyRead) ttlMs = HOUR
23
+ if (!explicit && prev && now - prev.lastReplyAt > FIVE_MINUTES && mostlyRead) ttlMs = HOUR
24
+ return { ttlMs, lastReplyAt: now, expiresAt: now + ttlMs }
25
+ }
26
+
27
+ export function secondsLeft(memo: CacheMemo | null, now: number): number | null {
28
+ return memo ? Math.max(0, Math.ceil((memo.expiresAt - now) / 1000)) : null
29
+ }
30
+
31
+ /** Never pay to revive an expired cache or extend the last-real-reply bound with our own pings. */
32
+ export function shouldPing(input: {
33
+ settings: Settings; memo: CacheMemo | null; warm: WarmState; now: number; idle: boolean
34
+ contextTokens: number; lastRealReplyAt: number | null
35
+ }): { ping: true } | { ping: false; reason?: string } {
36
+ const { settings, memo, warm, now } = input
37
+ if (!settings.keepWarm) return { ping: false, reason: 'keep warm is off' }
38
+ if (warm.stopped) return { ping: false, reason: warm.stopped }
39
+ if (!input.idle) return { ping: false, reason: 'chat is busy' }
40
+ if (!memo || memo.expiresAt <= now) return { ping: false, reason: 'cache is not warm' }
41
+ if (input.lastRealReplyAt === null || now >= input.lastRealReplyAt + settings.keepWarmHours * HOUR) return { ping: false, reason: 'keep warm time bound reached' }
42
+ if (input.contextTokens < settings.keepWarmMinTokens) return { ping: false, reason: 'chat is too small' }
43
+ const lead = memo.ttlMs === FIVE_MINUTES ? 60000 : 240000
44
+ return memo.expiresAt - now <= lead ? { ping: true } : { ping: false }
45
+ }
46
+
47
+ /** Failed forks stop once; answered cache misses still count the real tokens they spent. */
48
+ export function afterPing(warm: WarmState, forkResult: ModelForkResult | null, now: number, lang: Lang = 'en'): WarmState {
49
+ if (!forkResult?.isAnswered) return { ...warm, stopped: t(lang, 'toasts.warmNoReply') }
50
+ const next: WarmState = { pings: warm.pings + 1, cost: warm.cost + weighted(forkResult.usage), lastPingAt: now }
51
+ if (forkResult.usage.cache_read_input_tokens <= 0) next.stopped = t(lang, 'toasts.warmNoCache')
52
+ return next
53
+ }
54
+
55
+ export function restoreFromResume(secondsSinceLastResponse: number | undefined, likelyExpired: boolean | undefined, ttlMs: number, now: number): CacheMemo | null {
56
+ if (secondsSinceLastResponse === undefined || !Number.isFinite(secondsSinceLastResponse) || secondsSinceLastResponse < 0) return null
57
+ const lastReplyAt = now - secondsSinceLastResponse * 1000
58
+ const expiresAt = lastReplyAt + ttlMs
59
+ return { ttlMs, lastReplyAt, expiresAt: likelyExpired || expiresAt <= now ? now - 1 : expiresAt }
60
+ }