clauderipple 0.8.9 → 0.9.0

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 (75) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.es.md +0 -4
  3. package/README.ja.md +0 -4
  4. package/README.ko.md +5 -1
  5. package/README.md +5 -1
  6. package/README.pt-BR.md +0 -4
  7. package/README.zh-CN.md +0 -4
  8. package/dist/app/dist/main.js +23 -3
  9. package/dist/app/package.json +1 -1
  10. package/dist/cli/src/codex.js +3 -1
  11. package/dist/cli/src/index.js +1 -1
  12. package/dist/cli/src/settings.js +5 -2
  13. package/dist/cli/src/tray.js +41 -5
  14. package/dist/mod/.claude-plugin/plugin.json +9 -1
  15. package/dist/mod/hooks/cache.ts +60 -0
  16. package/dist/mod/hooks/compact.ts +40 -0
  17. package/dist/mod/hooks/handoff.ts +43 -0
  18. package/dist/mod/hooks/i18n.ts +2716 -0
  19. package/dist/mod/hooks/judge.ts +226 -0
  20. package/dist/mod/hooks/ladder.js +179 -0
  21. package/dist/mod/hooks/ladder.ts +174 -0
  22. package/dist/mod/hooks/modes.ts +93 -0
  23. package/dist/mod/hooks/register.tsx +1458 -256
  24. package/dist/mod/hooks/session.ts +62 -0
  25. package/dist/mod/hooks/settings.js +342 -0
  26. package/dist/mod/hooks/settings.ts +321 -0
  27. package/dist/mod/hooks/stats.ts +59 -0
  28. package/dist/mod/hooks/ui/agents.tsx +138 -0
  29. package/dist/mod/hooks/ui/alerts.tsx +370 -0
  30. package/dist/mod/hooks/ui/art.ts +628 -0
  31. package/dist/mod/hooks/ui/band.tsx +836 -0
  32. package/dist/mod/hooks/ui/kit.tsx +258 -0
  33. package/dist/mod/hooks/ui/log.tsx +109 -0
  34. package/dist/mod/hooks/ui/parts.tsx +217 -0
  35. package/dist/mod/hooks/ui/ripple.ts +614 -0
  36. package/dist/mod/hooks/ui/settings.tsx +376 -0
  37. package/dist/mod/hooks/ui/setup.tsx +148 -0
  38. package/dist/mod/hooks/ui/theme.ts +217 -0
  39. package/dist/mod/hooks/ui/view.ts +371 -0
  40. package/dist/mod/hooks/worker.ts +1 -1
  41. package/dist/mod/hooks/workers.ts +217 -0
  42. package/dist/mod/tests/register.test.tsx +1730 -0
  43. package/dist/mod/tests/ui.test.tsx +853 -0
  44. package/dist/mod/tsconfig.json +2 -1
  45. package/dist/mod/types/index.d.ts +320 -1
  46. package/dist/router/src/admin.js +195 -53
  47. package/dist/router/src/agents.js +24 -5
  48. package/dist/router/src/bootstrap.js +4 -2
  49. package/dist/router/src/compat.js +10 -2
  50. package/dist/router/src/config.js +3 -0
  51. package/dist/router/src/health.js +33 -0
  52. package/dist/router/src/index.js +1 -0
  53. package/dist/router/src/ingress/models.js +4 -1
  54. package/dist/router/src/mod-settings.js +119 -0
  55. package/dist/router/src/model-policy.js +6 -0
  56. package/dist/router/src/model-scores.js +159 -0
  57. package/dist/router/src/picker.js +7 -0
  58. package/dist/router/src/providers/anthropic-account-pool.js +10 -4
  59. package/dist/router/src/providers/anthropic-accounts.js +26 -1
  60. package/dist/router/src/providers/chatgpt/catalog.js +45 -14
  61. package/dist/router/src/providers/chatgpt/index.js +9 -3
  62. package/dist/router/src/providers/chatgpt/translate.js +9 -5
  63. package/dist/router/src/providers/google/index.js +6 -2
  64. package/dist/router/src/providers/openai/index.js +4 -1
  65. package/dist/router/src/providers/openai/translate.js +1 -1
  66. package/dist/router/src/proxy.js +14 -3
  67. package/dist/router/src/version.js +1 -1
  68. package/dist/ui/app.js +932 -209
  69. package/dist/ui/favicon-32.png +0 -0
  70. package/dist/ui/favicon.svg +12 -0
  71. package/dist/ui/i18n.js +923 -237
  72. package/dist/ui/index.html +159 -87
  73. package/dist/ui/style.css +789 -408
  74. package/docs/ARCHITECTURE.md +134 -2
  75. package/package.json +7 -3
@@ -196,6 +196,15 @@ request went, and a `Pane` holds the request log.
196
196
  browser) are the app's own; the mod API (CLI 2.1.286 types) has no place for
197
197
  a plugin's button there. Its sites are the band, the status line, panes,
198
198
  transcript rows and slash commands.
199
+ - **Pictures on the desktop are images, never frames.** The desktop app draws
200
+ each answer as a new DOM tree; an `Svg` becomes a new `<img>` of a data URL,
201
+ or with `isInteractive` a sandboxed `<iframe srcdoc>` that paints blank until
202
+ loaded. Only the frame blinks on a redraw: a plain `Svg` image does not, and
203
+ CSS `@keyframes` inside the SVG run in it (seen by the owner in the desktop
204
+ app on 2026-10-11 at commit 8d43b97, 리플이 moving in the band and the quick
205
+ settings with no flicker; Effortless animates its band the same way). A
206
+ redraw still starts the motion over, so the mod's loops all open on a rest
207
+ pose (`packages/mod/hooks/ui/ripple.ts`).
199
208
  - **A pane's open state is the engine's.** A module reload drops its pane
200
209
  without a `ui.close` the module hears, while `$.state` survives the reload: a
201
210
  flag kept there stuck the Log button on "Close log" (2026-10-05). The mod asks
@@ -205,9 +214,128 @@ request went, and a `Pane` holds the request log.
205
214
  path list other plugins may share, so only the entry whose manifest is named
206
215
  `clauderipple-status` is added or removed (`clauderipple mod on|off`, the
207
216
  Clients screen switch).
217
+ - **Developing it, sessions load a copy at the last commit.** With
218
+ `CLAUDE_CODE_PLUGIN_DIR_WATCH=1` a session reloads a plugin folder whenever
219
+ it changes, and each reload leaves "ripple reloaded (N hooks: …)" in every
220
+ open transcript: pointed at the checkout, one session editing the mod
221
+ flooded all the others (2026-10-13). On this machine the entry is
222
+ `~/.clauderipple/mod`, which `scripts/sync-mod.mts` keeps at main's
223
+ `packages/mod` from the post-commit, post-merge and post-rewrite hooks
224
+ (`--install` writes them), writing only files that differ. Uncommitted work
225
+ never reaches everyday sessions; `clauderipple mod on` would point the entry
226
+ back at the checkout.
227
+
228
+ ### 3b. Shared mod settings and judge-only models (2026-10-10)
229
+
230
+ The router is the single source of the mod's settings, persisted in
231
+ `<homeDir()>/mod-settings.json`. `GET /api/mod-settings` returns
232
+ `{settings:<full normalized Settings>, revision, stored:boolean}`. Before the first
233
+ write it returns normalized defaults, revision 0 and `stored:false`, without creating
234
+ storage. `PUT` accepts `{settings, revision?}`, normalizes with the mod's own pure
235
+ `hooks/settings.ts:normalizeSettings` (type-only imports, no `claude-code` runtime),
236
+ increments the revision under the account stores' `withFileLock` and `writeJsonAtomic`
237
+ helpers (0600), and returns `{settings, revision, stored:true}`. A stale supplied
238
+ revision returns 409 with the same full current snapshot, including `stored`.
239
+ Existing stored settings are normalized on reads as well; unknown fields are dropped.
240
+ Before normalization, the router refuses nonobjects, settings over 64 KiB of UTF-8
241
+ JSON (413), and credential field names at any depth, including inside arrays (400).
242
+ The final word of a field name decides (`apiKey`, `access_token`, `clientSecret`,
243
+ `password`, etc.); `keepWarmMinTokens` is a count, not a credential, and is accepted.
244
+ Corrupt storage is an error, never an empty store to overwrite.
245
+
246
+ The mod reads this endpoint at `session.start` and every 3-second router poll, even
247
+ when its band is hidden. A changed revision replaces the settings atom and redraws
248
+ readers. Only when `stored:false` does it read legacy plugin-store `settings` and
249
+ `setupDone` and migrate them with a revision-checked PUT; a racing first writer wins
250
+ instead of being overwritten. Afterwards settings are never read from or saved to the
251
+ plugin store; unrelated keys such as picks, band visibility and handoff choices remain.
252
+ Panel/setup saves PUT the last seen revision. On 409 the mod takes the server copy,
253
+ reapplies only the user's changed paths (including sibling rule/provider fields), and
254
+ retries once. A panel keeps its opening baseline so a poll while it is open cannot
255
+ turn an unrelated remote edit into a local overwrite. Offline changes remain active
256
+ locally with the existing router-not-answering notice and retry on the next poll,
257
+ rebased over that poll's server copy. Revision, pending edits and migration state live
258
+ in session atoms and survive module hot reloads; settings HTTP work is serialized.
259
+ Language resolution and the separate Jev key file are unchanged. Verified with
260
+ `test/admin.test.ts`, `test/mod/settings.test.ts` and the mod's 2.1.293 engine tests.
261
+
262
+ `GET /api/mod-options` returns `agents` (owned manifest entries with existing agent
263
+ files), all configured `models` (`model`, `provider`, `name`, `judgeOnly`), `providers`
264
+ (`name`, `type`, `usable`), `zen:{configured,model}`, and `scores`. ChatGPT usability
265
+ shares `/api/status`'s quota refresh and account states, including purchased credits;
266
+ AA scores reuse `model-scores.ts` and retain its attribution. No provider key is exposed.
267
+ Since 2026-10-11 (the worker ladder, docs/specs/2026-10-11-worker-ladder.md) each agent also
268
+ carries `efforts` (its model's ladder from `effortLevels`, mod efforts only) and `billing`
269
+ (`free | payg | subscription`, `hooks/ladder.ts:billingOf`: ChatGPT, Claude login, Antigravity
270
+ and the OpenCode Go preset are subscriptions, Ollama/LM Studio, a hand-entered local URL and
271
+ `:free`/`-free` models are free, every other preset or API is pay-per-token); providers carry
272
+ `billing`; `claudeEfforts` is Anthropic's ladder; `presets` are the four ladder presets computed
273
+ by the mod's own `hooks/ladder.ts` from the usable workers plus Claude's models, so the dashboard
274
+ and the session's quick settings fill rungs alike.
275
+
276
+ The worker ladder replaced Pin as the default rule mode (`{mode:'ladder', rungs:{light, standard,
277
+ hard, plan}}`, each rung `{target, effort, backup?}`). The judge adds `kind: plan|do`; level picks
278
+ Light/Standard/Hard, a plan at standard or deep goes to Plan, and `sure < 0.5` moves Light→Standard
279
+ →Hard (Plan does not move). An unavailable rung tries its backup, then one rung up (its model, then
280
+ its backup), then the session model (`general-purpose` with no model; refused only when Anthropic is
281
+ switched off), never down. Stored pins normalize to ladders on every read (missing levels climb,
282
+ efforts start at the default ladder's for the same model or low/medium/high, calibrated as the pin
283
+ was; Plan is Hard's model one effort up); Auto stays Auto, shown as experimental. `fallback` and
284
+ `preference` are kept; only Auto still reads `preference`. Every pick writes one
285
+ `ClaudeRipple worker pick:` debug line. Tests: `test/mod/ladder.test.ts`, `test/admin.test.ts`.
286
+
287
+ `model-policy.ts:isJudgeOnlyModel` is the single judge-only rule: ids beginning with
288
+ `jev` are not chat models (the OpenCode Zen note in `presets.ts`: `/systemone` only).
289
+ Desktop/CLI picker injection (including aliases/routes targeting Jev), derived worker
290
+ aliases, generated agents, AA auto-worker score candidates, OpenAI model lists and
291
+ Codex catalogs exclude them; the next enabled agent sync removes previously
292
+ owned Jev files, never hand-written ones. Provider configuration and mod options keep
293
+ them available as judge candidates. Tests: `test/admin.test.ts`, `test/model-policy.test.ts`.
208
294
 
209
295
  ## 4. Provider adapters
210
296
 
297
+ ### Artificial Analysis model scores (2026-10-10)
298
+
299
+ `scripts/aa-dataset.mjs` builds `aa-models.json` on the orphan GitHub `data` branch;
300
+ `.github/workflows/aa-data.yml` checks daily at 03:37 UTC, replacing its single commit
301
+ only for substantive changes or after a week. Source: [AA API v2](https://artificialanalysis.ai/api/v2/data/llms/models)
302
+ (`x-api-key`, free limit 1,000 requests/day; `AA_API_KEY` stays in the environment).
303
+ The API supplies slug/name/creator/release date, `evaluations.artificial_analysis_intelligence_index`
304
+ and input/output USD-per-million prices, **not** cost per task. The model page's Next.js
305
+ flight record supplies `intelligenceIndex`, `intelligenceIndexIsEstimated` and
306
+ `intelligenceIndexCostPerTask.cost.total` (USD, already including input/cache/output);
307
+ `intelligenceIndexCost.total` is a different, whole-benchmark total and is never used.
308
+ Measured [GPT-6.1 Sol High](https://artificialanalysis.ai/models/gpt-6-1-sol-high):
309
+ index **50.2378** (≈50.24), **$0.319144 per task** (≈$0.3191), not estimated.
310
+
311
+ Track families with at least one measured release in the last **365 days**, including
312
+ all their older/unmeasured variants. Group by creator and model name with reasoning
313
+ parentheses removed; retain unrelated Preview/Beta/date labels. Strip only recognized
314
+ reasoning endings from slugs. Effort uses the page suffix/name parentheses, then slug:
315
+ `max/xhigh/high/medium/low/minimal/non-reasoning`; Non-reasoning takes precedence over
316
+ an accompanying High/Low label. Generic Reasoning or the unsuffixed default maps to
317
+ max in a multi-variant family; a single-variant model has null effort. Successful
318
+ `checkedAt` values under **7 days** are reused; failed pages retain prior values/time
319
+ (or null cost/time), and embedded defaults are harvested opportunistically by exact
320
+ slug. Page requests are sequential, ≥1.5 seconds apart with one backed-off 429/5xx
321
+ retry. Fewer than half of attempted pages parsing their requested slug aborts publication.
322
+ The extraction marker `canonicalIntelligenceIndexTokenCount` is a private page-format
323
+ anchor, not an output metric: no token counts are stored. `--limit N` caps page fetches
324
+ for a local smoke run; use `--output <path>` and never publish capped output.
325
+
326
+ Auto routing and field rules were removed 2026-10-12 (along with `GET /api/model-scores`);
327
+ routing is the four workers (docs/specs/2026-10-12-worker-tiers.md). `model-scores.ts`
328
+ remains as the admin's internal catalog for the mod's options, with normalized
329
+ AA bases (decimal dots → hyphens, provider namespace/Claude snapshot date removed),
330
+ variant intelligence/cost, attribution and generation time. The picker's five effort
331
+ names are preserved; AA minimal/non-reasoning and single variants return null rather
332
+ than being mislabeled low. Unknown models remain present with `matched:false`.
333
+ Scores are metadata, never routing policy or the user's subscription bill. The public
334
+ raw JSON is fetched with a 5-second timeout, kept 24 hours in memory and
335
+ `<homeDir()>/aa-models.json` (mtime records retrieval), shared by concurrent lookups;
336
+ on failure the last cache is kept and retried after one hour. Displays/republication
337
+ must preserve **Data: Artificial Analysis (artificialanalysis.ai)** attribution.
338
+
211
339
  - **The Claude model list is Anthropic's own (2026-10-08).** The native `anthropic`
212
340
  provider's models came from a constant in admin.ts, so each release after it was cut
213
341
  was missing from the provider form, the mapping table and the declared list until a
@@ -335,8 +463,12 @@ request went, and a `Pane` holds the request log.
335
463
  visibility: "list"|"hide", context_window, supported_reasoning_levels:
336
464
  [{effort}] }] }` — what the Codex CLI's picker shows. **The server filters by
337
465
  `client_version`:** `0.146.0` omitted gpt-6-astra/sol/luna, `0.155.0`
338
- listed them. The adapter (`catalog.ts`) asks with the higher of a floor and
339
- `~/.codex/models_cache.json`'s `client_version`, drops `hide` entries, keeps
466
+ listed them; `0.158.0` omitted gpt-6.1-sol and `0.159.0` listed it
467
+ (2026-10-10, also listed at `0.162.1`, `1.0.0`, `99.0.0`). A floor alone
468
+ trails every release — a Windows user with no Codex CLI never saw 6.1 Sol
469
+ (#50) — so the adapter (`catalog.ts`) asks with the highest of the floor,
470
+ `~/.codex/models_cache.json`'s `client_version` and the newest `@openai/codex`
471
+ on the npm registry (kept a day), drops `hide` entries, keeps
340
472
  the list an hour, and falls back to a measured list in the same file. The
341
473
  GUI's ChatGPT form fetches it on open; new models arrive unticked. Model ids
342
474
  unknown to the backend answer `400 "… model is not supported when using
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clauderipple",
3
- "version": "0.8.9",
3
+ "version": "0.9.0",
4
4
  "description": "Use GPT (any ChatGPT plan with Codex), DeepSeek and 400+ other models in the Claude Desktop Code tab and Claude Code while staying signed in to your Claude subscription — no third-party gateway mode. Several ChatGPT accounts that take over when one runs out, in Codex too.",
5
5
  "license": "GPL-3.0-only",
6
6
  "workspaces": [
@@ -10,11 +10,15 @@
10
10
  "node": ">=24"
11
11
  },
12
12
  "scripts": {
13
- "typecheck": "tsc -p tsconfig.json --noEmit",
13
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p packages/remote/tsconfig.web.json --noEmit && tsc -p packages/remote/relay/tsconfig.json --noEmit",
14
14
  "dist": "npm --workspace @clauderipple/app run dist",
15
15
  "release": "npm --workspace @clauderipple/app run release",
16
16
  "router": "node packages/router/src/index.ts",
17
- "test": "node --test packages/router/test/*.test.ts packages/cli/test/*.test.ts",
17
+ "remote": "node --disable-warning=ExperimentalWarning packages/remote/src/main.ts",
18
+ "relay:build": "node --disable-warning=ExperimentalWarning packages/remote/relay/build-web.ts",
19
+ "relay:dev": "npm run relay:build && wrangler dev -c packages/remote/relay/wrangler.toml --ip 127.0.0.1 --port 8798",
20
+ "relay:deploy": "npm run relay:build && wrangler deploy -c packages/remote/relay/wrangler.toml",
21
+ "test": "node --test packages/router/test/*.test.ts packages/cli/test/*.test.ts test/mod/*.test.ts packages/remote/test/*.test.ts",
18
22
  "cli": "node packages/cli/src/index.ts",
19
23
  "prepack": "node scripts/build-npm.mjs",
20
24
  "build": "node scripts/build-npm.mjs"