threadwire 0.1.28 → 0.1.30
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 +8 -0
- package/docs/capacity-admission.md +7 -5
- package/package.json +2 -2
- package/src/provider-capacity.js +19 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Fix `threadwire capacity --provider kimi` for the current Kimi usages API:
|
|
6
|
+
quota objects may provide either `used` or `remaining` alongside `limit` and
|
|
7
|
+
`resetTime`. Threadwire derives the omitted value while retaining strict
|
|
8
|
+
decimal, bounds, and consistency validation.
|
|
9
|
+
|
|
10
|
+
- Upgrade `release-patch` from 1.0.3 to 1.0.5 so npm registry visibility is
|
|
11
|
+
checked for up to 10 attempts over 150 seconds without repeating the publish.
|
|
12
|
+
|
|
5
13
|
- Add an optional loopback-only TensorBuzz-to-Telegram queue bridge. It verifies
|
|
6
14
|
bounded raw-body HMAC-SHA-256 requests before JSON parsing, admits a closed
|
|
7
15
|
`build_group.completed` schema, builds a bounded canonical `/queue` prompt,
|
|
@@ -80,11 +80,13 @@ pin before relying on it.
|
|
|
80
80
|
to `short`; every returned window is validated (`window.duration` in
|
|
81
81
|
`TIME_UNIT_MINUTE`s, `detail` quota) but intermediate windows are ignored,
|
|
82
82
|
and normalization fails closed if the long duration would not exceed the
|
|
83
|
-
short. Quota fields are strict non-negative decimal strings
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
short. Quota fields are strict non-negative decimal strings with a positive
|
|
84
|
+
limit. Kimi may provide either `used` or `remaining` (or both); Threadwire
|
|
85
|
+
derives the omitted side from `limit` and, when both are present, requires
|
|
86
|
+
`used + remaining === limit`. Reset times must be bounded ISO-8601, and
|
|
87
|
+
remaining percent is floored so normalization never overstates capacity.
|
|
88
|
+
Unrelated top-level response fields are neither read nor propagated into
|
|
89
|
+
output or errors.
|
|
88
90
|
|
|
89
91
|
Both probes are bounded (capped lines/bytes, single absolute timeout) and fail
|
|
90
92
|
closed on any shape drift: exact keys within the parsed projection, forced
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "threadwire",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "Stream Codex, Claude, Kimi Code, and OpenCode worker progress to an explicit Telegram destination",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agent",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"eslint-plugin-jsdoc": "63.0.0",
|
|
69
69
|
"fallow": "3.2.0",
|
|
70
70
|
"globals": "17.0.0",
|
|
71
|
-
"release-patch": "1.0.
|
|
71
|
+
"release-patch": "1.0.5",
|
|
72
72
|
"typescript": "6.0.2"
|
|
73
73
|
},
|
|
74
74
|
"license": "AGPL-3.0-only",
|
package/src/provider-capacity.js
CHANGED
|
@@ -199,21 +199,25 @@ function kimiLimitsWindow(value) {
|
|
|
199
199
|
|
|
200
200
|
/**
|
|
201
201
|
* Validate one quota object (`usage` or `detail`): exact keys, strict
|
|
202
|
-
* non-negative decimal-string integers with `used
|
|
203
|
-
* positive limit, and a bounded ISO-8601 reset time.
|
|
202
|
+
* non-negative decimal-string integers with either `used` or `remaining` (or
|
|
203
|
+
* both), a positive limit, and a bounded ISO-8601 reset time. Derive the
|
|
204
|
+
* omitted side from the limit and require equality when both are present.
|
|
204
205
|
* @param {unknown} value
|
|
205
206
|
* @param {number} windowDurationSeconds
|
|
206
207
|
* @returns {CapacityWindow}
|
|
207
208
|
*/
|
|
208
209
|
function kimiQuotaWindow(value, windowDurationSeconds) {
|
|
209
|
-
if (!isRecord(value) || !
|
|
210
|
+
if (!isRecord(value) || !kimiQuotaKeys(value)) {
|
|
210
211
|
throw kimiProtocolError()
|
|
211
212
|
}
|
|
212
213
|
const limit = quotaValue(value.limit)
|
|
213
|
-
const used = quotaValue(value.used)
|
|
214
|
-
const remaining = quotaValue(value.remaining)
|
|
215
|
-
if (limit < 1 || used
|
|
216
|
-
|
|
214
|
+
const used = value.used === undefined ? null : quotaValue(value.used)
|
|
215
|
+
const remaining = value.remaining === undefined ? null : quotaValue(value.remaining)
|
|
216
|
+
if (limit < 1 || (used !== null && used > limit) || (remaining !== null && remaining > limit)
|
|
217
|
+
|| (used !== null && remaining !== null && used + remaining !== limit)) throw kimiProtocolError()
|
|
218
|
+
if (used === null && remaining === null) throw kimiProtocolError()
|
|
219
|
+
const normalizedRemaining = remaining === null ? limit - /** @type {number} */ (used) : remaining
|
|
220
|
+
const remainingPercent = Number((BigInt(normalizedRemaining) * 100n) / BigInt(limit))
|
|
217
221
|
return {
|
|
218
222
|
usedPercent: 100 - remainingPercent,
|
|
219
223
|
remainingPercent,
|
|
@@ -222,6 +226,14 @@ function kimiQuotaWindow(value, windowDurationSeconds) {
|
|
|
222
226
|
}
|
|
223
227
|
}
|
|
224
228
|
|
|
229
|
+
/** @param {Record<string, unknown>} value @returns {boolean} */
|
|
230
|
+
function kimiQuotaKeys(value) {
|
|
231
|
+
const keys = Object.keys(value).sort()
|
|
232
|
+
return exactKeys(value, ["limit", "used", "remaining", "resetTime"])
|
|
233
|
+
|| (keys.length === 3 && keys.includes("limit") && keys.includes("resetTime")
|
|
234
|
+
&& (keys.includes("used") || keys.includes("remaining")))
|
|
235
|
+
}
|
|
236
|
+
|
|
225
237
|
/**
|
|
226
238
|
* A strict non-negative decimal-string integer, digit-bounded so the sum of
|
|
227
239
|
* two values always stays a safe integer.
|