Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions devlog/_plan/260907_lane_d/040_price_editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,24 @@ A fold-back: add GET/PUT entries in src/server/management/route-registry.ts.
Reuse providerModelCostsConfigError. GET returns sanitized per-provider modelCosts map;
Models owns a typed map loaded with catalog or dedicated GET, so manual badges survive
reload. CLI omitted cache-read/cache-write rates default to zero, explicitly documented.

P revalidation/API contract: GET /api/providers/{provider}/model-costs returns
{provider,modelCosts}; PUT accepts {modelId,cost:Cost4|null}, returns
{ok:true,provider,modelId,cost}. Null deletes only that model key. Models API adds
manualPricing boolean on applicable rows so badges survive reload, while the dialog
GET owns editable rates. CLI models price reads; models set-price writes/resets.
Same C2 phase splits disjoint workers: backend API/CLI/model-row/tests; frontend dialog/
Models/types/i18n/tests; main owns explicit-zero cost semantics, docs and manifests.
No worker commits/pushes/runs local checks. Main integrates once both return.
Main granted D exactly the zero sentence in all seven translated providers config
reference pages; leave all other sections to E/M. New i18n keys are append-only.

Implementation checkpoint: GET/PUT editor and two CLI verbs share the four-rate store;
manualPricing is emitted only for exact stored overrides. All-zero user prices are
known-zero estimates while catalog zero fallbacks remain unchanged. API/CLI and dialog
regressions cover persistence, reset, sibling isolation, invalid input and unknown receipts.
All 9 locale catalogs gained matching append-only keys. Seven existing configuration
rows (English plus six translations) had only the zero sentence updated; zh-tw has no
modelCosts row on this baseline and was left untouched. CLI surface regenerated by its
own generator, not a build or test. New backend test names appended to both manifests.
Local suites/typecheck/build/install NOT RUN; final top CI and screenshot remain open.
19 changes: 19 additions & 0 deletions devlog/_plan/260907_lane_d/050_usage_ranges.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,22 @@ integer epoch milliseconds or full ISO-8601 with timezone only; require both bou
reject negative/unsafe/date-invalid/reversed, never normalize overflow dates.
MODIFY src/cli/usage-report.ts heading prints since/until for customWindow responses.
GUI datetime values become epoch ms locally; end selected minute includes 59.999s.

P revalidation: custom windows always filter rows before aggregation. Introduce exported
UsageTimeWindow {since:number,until:number} and immutable optional accumulator window;
snapshot timestamps update first, clone retains the window, summary returns customWindow:true
and exact since/until while actual generatedAt stays now. Partition/day filtering must not
drop the partial first day. Grid uses local calendar day boundaries and caps at 366 days.
getFilteredUsageAggregate accepts window, keys both bounds, passes window to factory and
reuses existing revision/timezone/overlay guards. Only-window queries preserve account rows.
GUI skips held/session report caching for custom windows (arbitrary keys must not grow the
preset cache); useDataSurface key still includes bounds and unsubscribed stores already evict.
Workers split backend/API/CLI/tests and GUI/i18n/tests; main owns docs/manifests/generated map.

Implementation checkpoint: shared strict ISO/epoch-ms parser, immutable per-entry window,
window-keyed filtered cache, API and CLI inclusive bounds, exact interval heading, and
localized Usage date/time controls are implemented. Custom GUI reports bypass held caches;
calendar grid stays within the server's bounded days. Tests cover partial/inclusive bounds,
filters/accounts, cache invalidation, clone/snapshot behavior, empty/error responses and UI
apply/clear/stale-response paths. New parser test registered in both manifests. ISO fractions
beyond millisecond precision reject instead of truncating. Product execution NOT RUN locally.
24 changes: 24 additions & 0 deletions devlog/_plan/260907_lane_d/060_delivery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 060 Remote verification and delivery

Consume D5's implementation checkpoint. Resolve remaining independent review feedback on
its owning layer, cascade all dependent refs, and preserve contributor trailers. Detailed
unpublished security-review notes stay in scratch. Reconcile A's added reasoning-envelope
budget arguments with D1 ordering when A reaches dev; preserve both changes.

Fetch fresh dev before final dispatch. Run only the top branch's ci.yml workflow with
lane=all; require successful actual platform jobs including Windows on the exact head.
Download its dashboard-preview artifact and verify build-commit/build-gui-tree markers.
Capture the changed dialogs and custom Usage range with synthetic data through the existing
browser capability; publish proof images separately so evidence does not change tested code.

Create D2-D5 PRs with the required template, screenshot, manual chain table and native
stack:null proof. Attach independent implementation/security verdicts and top CI URL to
each PR. Leave all merges and original issue/PR closure actions to the main task.
Local product tests/typecheck/build/install remain NOT RUN. D closes only when exact-head
remote evidence and the requested handoff table are complete.

Calendar audit fold-back: custom heatmaps iterate the server's returned civil dates,
using UTC only for weekday/month layout; they do not step a local midnight cursor.
The server's backward calendar walk resets midnight after decrement and explicitly
advances to the prior existing local day if a whole-day timezone jump prevented progress.
Regressions pin America/Santiago (2026-09-05..07) and Pacific/Apia (2011-12-29..31).
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ sauvegarde dont le contenu diffère, puis réécrit en identifiants sans préfix
| `modelAutoCompactTokenLimits?` | `Record<string, number>` | Budgets souples de compactage automatique par modèle, sous forme d'entiers sûrs positifs. Ils peuvent uniquement abaisser l'enveloppe effective de 90 % du contexte ou de l'entrée maximale et sont omis lorsqu'aucune fenêtre de contexte faisant autorité n'est connue. Pour le fournisseur canonique `openai`, les clés doivent être les identifiants exacts de modèles natifs pris en charge, sans préfixe de fournisseur ni de sélecteur de compte. PATCH fusionne les entrées ; `null` supprime une clé, tandis que `null` pour le champ entier efface la table. Ces marqueurs `null` sont réservés à PATCH. |
| `defaultMaxOutputTokens?` | `number` | Solution de secours `openai-chat` à l’échelle du fournisseur lorsque le client omet `max_output_tokens`. |
| `modelMaxOutputTokens?` | `Record<string, number>` | Budgets de repli `openai-chat` positifs par modèle ; les correspondances exactes ou par motif priment sur la valeur par défaut du fournisseur. |
| `modelCosts?` | `Record<string, Cost4>` | Prix affichés par modèle (USD par 1M de jetons), indexés par l'identifiant exact du modèle en amont de ce fournisseur — et non par un identifiant de fournisseur ni par une étiquette routée `provider/model`, par exemple `{ "deepseek-v4-flash": { "input": 0.14, "output": 0.28, "cacheRead": 0.0028, "cacheWrite": 0 } }`. Tout identifiant de modèle constitue une clé valide : les fournisseurs personnalisés peuvent cibler n'importe quel point de terminaison compatible avec OpenAI au moyen de l'adaptateur `openai-chat`, et les identifiants de fournisseur locaux ou internes fonctionnent même s'ils sont absents des catalogues intégrés. Les prix configurés par l'utilisateur priment sur les catalogues intégrés dans les estimations des pages Journaux (`~$`) et Utilisation. Les entrées historiques sont recalculées à partir de la surcharge actuelle ; modifier un prix peut donc changer les totaux antérieurs. L'ordre de repli est le suivant : `modelCosts` défini par l'utilisateur → catalogue jawcode → surcharge des prix attendus → repli propre au fournisseur au niveau du modèle. Une entrée entièrement nulle passe à la source suivante. Chaque tarif doit être un nombre fini positif ou nul, inférieur ou égal à 1 000 000 (USD par 1M de jetons) ; les lignes hors plage sont rejetées par l'interface de gestion et ignorées au chargement. Ces valeurs servent uniquement à l'estimation lors de l'affichage : les surcharges n'affectent jamais le routage, la sélection des comptes, les quotas ni la facturation. |
| `modelCosts?` | `Record<string, Cost4>` | Prix affichés par modèle (USD par 1M de jetons), indexés par l'identifiant exact du modèle en amont de ce fournisseur — et non par un identifiant de fournisseur ni par une étiquette routée `provider/model`, par exemple `{ "deepseek-v4-flash": { "input": 0.14, "output": 0.28, "cacheRead": 0.0028, "cacheWrite": 0 } }`. Tout identifiant de modèle constitue une clé valide : les fournisseurs personnalisés peuvent cibler n'importe quel point de terminaison compatible avec OpenAI au moyen de l'adaptateur `openai-chat`, et les identifiants de fournisseur locaux ou internes fonctionnent même s'ils sont absents des catalogues intégrés. Les prix configurés par l'utilisateur priment sur les catalogues intégrés dans les estimations des pages Journaux (`~$`) et Utilisation. Les entrées historiques sont recalculées à partir de la surcharge actuelle ; modifier un prix peut donc changer les totaux antérieurs. L'ordre de repli est le suivant : `modelCosts` défini par l'utilisateur → catalogue jawcode → surcharge des prix attendus → repli propre au fournisseur au niveau du modèle. Une surcharge utilisateur explicitement définie à zéro produit une estimation nulle connue ; supprimez cette entrée pour rétablir la tarification automatique. Les prix de catalogue entièrement nuls restent soumis au repli. Chaque tarif doit être un nombre fini positif ou nul, inférieur ou égal à 1 000 000 (USD par 1M de jetons) ; les lignes hors plage sont rejetées par l'interface de gestion et ignorées au chargement. Ces valeurs servent uniquement à l'estimation lors de l'affichage : les surcharges n'affectent jamais le routage, la sélection des comptes, les quotas ni la facturation. |
| `headers?` | `Record<string, string>` | En-têtes supplémentaires en amont. L'autorisation, les cookies, les en-têtes de clé API, les nouvelles lignes intégrées et les noms invalides sont rejetés. |
| `openRouterRouting?` | `OpenRouterProviderRouting` | Préférences OpenRouter `order`, `only` et `allowFallbacks` par défaut ; valable uniquement pour les OpenRouter canoniques avec `openai-chat`. |
| `modelOpenRouterRouting?` | `Record<string, OpenRouterProviderRouting>` | Remplacements exacts de l'ID de modèle qui remplacent la préférence OpenRouter à l'échelle du fournisseur. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ account を削除しても mapping は保持され、同じ id を再追加す
| `modelAutoCompactTokenLimits?` | `Record<string, number>` | モデルごとの正の安全な整数によるソフト自動圧縮予算。実効値であるコンテキストまたは最大入力の 90% の上限を下げることだけができ、信頼できるコンテキストウィンドウが不明な場合は出力されません。canonical `openai` では、キーは provider や account-selector の接頭辞を含まない、サポート対象の正確なネイティブモデル ID でなければなりません。provider PATCH はエントリをマージし、キーを `null` にするとそのキーを削除し、フィールド全体を `null` にするとマップを消去します。これらの `null` tombstone は PATCH 専用です。 |
| `defaultMaxOutputTokens?` | `number` |クライアントが `max_output_tokens` を省略した場合の、プロバイダー全体の `openai-chat` フォールバック。 |
| `modelMaxOutputTokens?` | `Record<string, number>` |モデルごとの `openai-chat` フォールバック バジェットがプラスになります。正確な/パターン一致はプロバイダーのデフォルトを上回ります。 |
| `modelCosts?` | `Record<string, Cost4>` | モデルごとの表示価格(100万トークンあたりの米ドル)。そのプロバイダーの正確なアップストリーム モデル ID をキーにします(プロバイダー識別子やルーティングされた `provider/model` ラベルではありません)。値は `input`, `output`, `cacheRead`, `cacheWrite` の 4 フィールドです(例: `{ "deepseek-v4-flash": { "input": 0.14, "output": 0.28, "cacheRead": 0.0028, "cacheWrite": 0 } }`)。組み込みカタログにないモデル ID も、任意の OpenAI 互換エンドポイントを対象とするカスタムプロバイダーや、ローカル・内部プロバイダーで有効です。ユーザー設定の価格は Logs の `~$` と Usage の見積もりで組み込みカタログより優先されます。過去のエントリも現在のオーバーレイで再計算されるため、価格を編集すると過去の合計が変わることがあります(フォールバック順: ユーザー設定 → jawcode カタログ → expected-price オーバーレイ → モデル別ベンダー価格)。全ゼロのエントリは次のソースにフォールバックします。各レートは 0 以上の有限数で、最大 1,000,000(100万トークンあたりの米ドル)です。範囲外の行は管理境界で拒否され、読み込み時に破棄されます。表示専用の見積もりであり、ルーティング・アカウント選択・クォータ・請求には影響しません。 |
| `modelCosts?` | `Record<string, Cost4>` | モデルごとの表示価格(100万トークンあたりの米ドル)。そのプロバイダーの正確なアップストリーム モデル ID をキーにします(プロバイダー識別子やルーティングされた `provider/model` ラベルではありません)。値は `input`, `output`, `cacheRead`, `cacheWrite` の 4 フィールドです(例: `{ "deepseek-v4-flash": { "input": 0.14, "output": 0.28, "cacheRead": 0.0028, "cacheWrite": 0 } }`)。組み込みカタログにないモデル ID も、任意の OpenAI 互換エンドポイントを対象とするカスタムプロバイダーや、ローカル・内部プロバイダーで有効です。ユーザー設定の価格は Logs の `~$` と Usage の見積もりで組み込みカタログより優先されます。過去のエントリも現在のオーバーレイで再計算されるため、価格を編集すると過去の合計が変わることがあります(フォールバック順: ユーザー設定 → jawcode カタログ → expected-price オーバーレイ → モデル別ベンダー価格)。ユーザーが明示的に全レートを 0 にした場合は、既知のゼロ料金として見積もります。自動料金に戻すにはそのモデルの設定を削除してください。カタログの全ゼロ料金は引き続きフォールバックします。各レートは 0 以上の有限数で、最大 1,000,000(100万トークンあたりの米ドル)です。範囲外の行は管理境界で拒否され、読み込み時に破棄されます。表示専用の見積もりであり、ルーティング・アカウント選択・クォータ・請求には影響しません。 |
| `headers?` | `Record<string, string>` |追加の上流ヘッダー。認証、Cookie、API キー ヘッダー、埋め込まれた改行、および無効な名前は拒否されます。 |
| `openRouterRouting?` | `OpenRouterProviderRouting` |デフォルトの OpenRouter `order`、`only`、および `allowFallbacks` 設定。 `openai-chat` を持つ正規 OpenRouter に対してのみ有効です。 |
| `modelOpenRouterRouting?` | `Record<string, OpenRouterProviderRouting>` |プロバイダー全体の OpenRouter 設定を置き換える正確なモデル ID のオーバーライド。 |
Expand Down
Loading
Loading