@seanyao/roll 2.603.1 → 2.604.2
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.
- package/CHANGELOG.md +50 -11
- package/bin/roll +113 -800
- package/lib/__pycache__/changelog_audit.cpython-314.pyc +0 -0
- package/lib/__pycache__/changelog_generate.cpython-314.pyc +0 -0
- package/lib/__pycache__/loop-fmt.cpython-314.pyc +0 -0
- package/lib/__pycache__/prices_fetcher.cpython-314.pyc +0 -0
- package/lib/__pycache__/roll-loop-status.cpython-314.pyc +0 -0
- package/lib/changelog_audit.py +149 -0
- package/lib/changelog_generate.py +41 -23
- package/lib/consistency_check.py +409 -0
- package/lib/i18n/consistency.sh +8 -0
- package/lib/i18n/loop.sh +0 -4
- package/lib/prices/snapshot-2026-05-22.json +1 -7
- package/lib/prices/snapshot-2026-05-23-deepseek.json +0 -2
- package/lib/prices/snapshot-2026-06-02-kimi.json +0 -1
- package/lib/prices_fetcher.py +1 -20
- package/lib/roll-loop-status.py +15 -7
- package/package.json +1 -1
|
@@ -9,14 +9,8 @@
|
|
|
9
9
|
"prices": {
|
|
10
10
|
"claude-opus-4-7": {"in": 5.00, "out": 25.00, "cache_create": 6.25, "cache_read": 0.50},
|
|
11
11
|
"claude-opus-4-6": {"in": 5.00, "out": 25.00, "cache_create": 6.25, "cache_read": 0.50},
|
|
12
|
-
"claude-opus-4-5": {"in": 5.00, "out": 25.00, "cache_create": 6.25, "cache_read": 0.50},
|
|
13
|
-
"claude-opus-4-1": {"in": 15.00, "out": 75.00, "cache_create": 18.75, "cache_read": 1.50},
|
|
14
|
-
"claude-opus-4": {"in": 15.00, "out": 75.00, "cache_create": 18.75, "cache_read": 1.50},
|
|
15
12
|
"claude-sonnet-4-6": {"in": 3.00, "out": 15.00, "cache_create": 3.75, "cache_read": 0.30},
|
|
16
13
|
"claude-sonnet-4-5": {"in": 3.00, "out": 15.00, "cache_create": 3.75, "cache_read": 0.30},
|
|
17
|
-
"claude-
|
|
18
|
-
"claude-haiku-4-5": {"in": 1.00, "out": 5.00, "cache_create": 1.25, "cache_read": 0.10},
|
|
19
|
-
"claude-haiku-3-5": {"in": 0.80, "out": 4.00, "cache_create": 1.00, "cache_read": 0.08},
|
|
20
|
-
"claude-3-5-sonnet": {"in": 3.00, "out": 15.00, "cache_create": 3.75, "cache_read": 0.30}
|
|
14
|
+
"claude-haiku-4-5": {"in": 1.00, "out": 5.00, "cache_create": 1.25, "cache_read": 0.10}
|
|
21
15
|
}
|
|
22
16
|
}
|
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
"default_model": "deepseek-chat",
|
|
8
8
|
"notes": "Rates per million tokens in CNY (¥) — DeepSeek's native billing currency; we never convert to USD (the dashboard already shows the currency symbol). deepseek-chat and deepseek-reasoner are both deepseek-v4-flash with different thinking modes — same pricing. deepseek-v4-pro is priced at in 3 / out 6 — the earlier 2.5折 launch promo became permanent (confirmed 2026-06-02 against the official page), so these are the standing rates, not a temporary discount. cache_read is the official cache-hit input price (reduced to 1/10 of launch price since 2026-04-26). cache_create = cache-miss input rate: DeepSeek levies no separate cache-write surcharge, and pi reports cacheWrite cost as 0, so this rate only ever applies to (near-zero) cacheWrite tokens. pi's own per-message cost.total is computed in USD and is kept as cost_reported_usd for audit, NOT used for the authoritative cost.",
|
|
9
9
|
"prices": {
|
|
10
|
-
"deepseek-chat": {"in": 1, "out": 2, "cache_create": 1, "cache_read": 0.02},
|
|
11
|
-
"deepseek-reasoner": {"in": 1, "out": 2, "cache_create": 1, "cache_read": 0.02},
|
|
12
10
|
"deepseek-v4-flash": {"in": 1, "out": 2, "cache_create": 1, "cache_read": 0.02},
|
|
13
11
|
"deepseek-v4-pro": {"in": 3, "out": 6, "cache_create": 3, "cache_read": 0.025}
|
|
14
12
|
}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
"default_model": "kimi-k2.6",
|
|
8
8
|
"notes": "Rates per million tokens (CNY), verified 2026-06-02 against the official Kimi platform pricing pages (pricing/chat-k25 + pricing/chat-k26). Corrects the 2026-05-23 snapshot, which had copied the original-K2 rate (1/4) onto EVERY kimi model — real K2.5 is 4/21, K2.6 is 6.5/27, so the current models' cost was under-reported ~5-7x on output. Field convention: `in` = standard (cache-miss) input price; `cache_read` = cache-hit input price; `cache_create` = cache-miss input rate (Kimi documents no separate cache-write surcharge, mirroring DeepSeek). kimi-for-coding is the kimi-code CLI's model id; the CLI config pins it to K2.6 (display_name Kimi-k2.6, default_thinking=true, base_url api.kimi.com/coding/v1), so it is priced at K2.6 rates. NOTE: kimi-code is a coding *subscription*; these per-token rates are the published K2.6 API rates used as a usage-cost estimate, not the flat subscription fee. kimi-k2 is the prior-gen original K2, retained at its launch rate (1/4) for currency resolution of legacy name variants; it is no longer on the public pricing page and is not actually billed — only kimi-for-coding (K2.6) is.",
|
|
9
9
|
"prices": {
|
|
10
|
-
"kimi-k2": {"in": 1.00, "out": 4.00, "cache_create": 1.00, "cache_read": 0.25},
|
|
11
10
|
"kimi-k2.5": {"in": 4.00, "out": 21.00, "cache_create": 4.00, "cache_read": 0.70},
|
|
12
11
|
"kimi-k2.6": {"in": 6.50, "out": 27.00, "cache_create": 6.50, "cache_read": 1.10},
|
|
13
12
|
"kimi-for-coding": {"in": 6.50, "out": 27.00, "cache_create": 6.50, "cache_read": 1.10}
|
package/lib/prices_fetcher.py
CHANGED
|
@@ -162,12 +162,6 @@ def _parse_deepseek_html(html: str) -> Dict[str, Dict[str, float]]:
|
|
|
162
162
|
if not prices:
|
|
163
163
|
raise ParseError('no price rows found in HTML; page layout may have changed')
|
|
164
164
|
|
|
165
|
-
# Aliases: deepseek-chat and deepseek-reasoner both map to v4-flash.
|
|
166
|
-
if 'deepseek-v4-flash' in prices:
|
|
167
|
-
flash = prices['deepseek-v4-flash']
|
|
168
|
-
prices['deepseek-chat'] = dict(flash)
|
|
169
|
-
prices['deepseek-reasoner'] = dict(flash)
|
|
170
|
-
|
|
171
165
|
return prices
|
|
172
166
|
|
|
173
167
|
|
|
@@ -212,13 +206,6 @@ def _parse_kimi_html(html: str) -> Dict[str, Dict[str, float]]:
|
|
|
212
206
|
if prices:
|
|
213
207
|
if "kimi-k2.6" in prices:
|
|
214
208
|
prices["kimi-for-coding"] = dict(prices["kimi-k2.6"])
|
|
215
|
-
if "kimi-k2" not in prices:
|
|
216
|
-
prices["kimi-k2"] = {
|
|
217
|
-
"in": 1.00,
|
|
218
|
-
"out": 4.00,
|
|
219
|
-
"cache_create": 1.00,
|
|
220
|
-
"cache_read": 0.25,
|
|
221
|
-
}
|
|
222
209
|
return prices
|
|
223
210
|
|
|
224
211
|
sub_urls = [
|
|
@@ -238,13 +225,7 @@ def _parse_kimi_html(html: str) -> Dict[str, Dict[str, float]]:
|
|
|
238
225
|
|
|
239
226
|
if "kimi-k2.6" in prices:
|
|
240
227
|
prices["kimi-for-coding"] = dict(prices["kimi-k2.6"])
|
|
241
|
-
|
|
242
|
-
prices["kimi-k2"] = {
|
|
243
|
-
"in": 1.00,
|
|
244
|
-
"out": 4.00,
|
|
245
|
-
"cache_create": 1.00,
|
|
246
|
-
"cache_read": 0.25,
|
|
247
|
-
}
|
|
228
|
+
|
|
248
229
|
return prices
|
|
249
230
|
|
|
250
231
|
|
package/lib/roll-loop-status.py
CHANGED
|
@@ -668,6 +668,12 @@ def load_runs(slug: str) -> Dict[str, Dict[str, Any]]:
|
|
|
668
668
|
r = json.loads(line)
|
|
669
669
|
except Exception:
|
|
670
670
|
continue
|
|
671
|
+
# FIX-193: a stray line can parse as a bare JSON scalar (e.g. an
|
|
672
|
+
# agent pretty-printed a record across lines and `"FIX-181"` parses
|
|
673
|
+
# as a str) — r.get() then crashes the whole dashboard. Records
|
|
674
|
+
# must be objects; skip anything else.
|
|
675
|
+
if not isinstance(r, dict):
|
|
676
|
+
continue
|
|
671
677
|
p = r.get("project", "")
|
|
672
678
|
if p != slug and p != base and not p.startswith(f"{slug}-cycle-"):
|
|
673
679
|
# String match failed — try path match for old-slug salvage.
|
|
@@ -737,7 +743,7 @@ def merge_runs_into_cycles(cycles: List[Dict[str, Any]], runs: Dict[str, Dict[st
|
|
|
737
743
|
# Outcome: runs.jsonl wins when events stream was vacuous or
|
|
738
744
|
# misleading (idle/failed emitted by _loop_event even though the
|
|
739
745
|
# agent completed work and _runs_append recorded built).
|
|
740
|
-
if cy.get("outcome") in ("unknown", "running", "idle", "failed") and r.get("status"):
|
|
746
|
+
if cy.get("outcome") in ("unknown", "running", "idle", "failed", "orphan") and r.get("status"):
|
|
741
747
|
cy["outcome"] = {"built": "done", "interrupted": "fail"}.get(r["status"], r["status"])
|
|
742
748
|
if not cy.get("story") and r["built"]:
|
|
743
749
|
cy["story"] = r["built"][0]
|
|
@@ -1186,15 +1192,17 @@ def render(events, cron, state, backlog, *, days=3, lang="both", now=None,
|
|
|
1186
1192
|
# would duplicate signal without adding info.
|
|
1187
1193
|
print(eb_zh)
|
|
1188
1194
|
|
|
1189
|
-
# US-LOOP-036: daily service (dream
|
|
1190
|
-
#
|
|
1191
|
-
#
|
|
1192
|
-
|
|
1195
|
+
# US-LOOP-036: daily service (dream) next-fire line, read straight from the
|
|
1196
|
+
# launchd plist so it reflects the latest `roll config dream-time` reload
|
|
1197
|
+
# rather than a stale yaml-derived guess.
|
|
1198
|
+
# FIX-194/FIX-195: brief loop retired — dream is the only daily service.
|
|
1199
|
+
for _svc in ("dream",):
|
|
1193
1200
|
_sl = _daily_schedule_line(_svc, now=now)
|
|
1194
1201
|
if _sl:
|
|
1195
1202
|
print(" " + c("dim", _sl))
|
|
1196
|
-
# FIX-151: dedicated loop
|
|
1197
|
-
|
|
1203
|
+
# FIX-151: dedicated loop last-tick age.
|
|
1204
|
+
# FIX-194: ci/alert loops retired — pr is the only dedicated loop tick.
|
|
1205
|
+
for _loop in ("pr",):
|
|
1198
1206
|
_tl = _tick_age_line(_loop, now=now)
|
|
1199
1207
|
if _tl:
|
|
1200
1208
|
print(" " + c("dim", _tl))
|