squad-kit 0.7.2 → 0.8.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.
- package/CHANGELOG.md +18 -0
- package/dist/cli.js +33 -6
- package/dist/cli.js.map +1 -1
- package/dist/console-ui/assets/index-C5I4cnED.css +1 -0
- package/dist/console-ui/assets/{index-gaFPpGMN.js → index-DGzIogF0.js} +166 -166
- package/dist/console-ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/console-ui/assets/index-BDlxrwaG.css +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.0] — 2026-05-03
|
|
11
|
+
|
|
12
|
+
### What's new
|
|
13
|
+
|
|
14
|
+
- Generate page shows provider rate limits: countdown, auto-retry banner,
|
|
15
|
+
and rerun when the planner aborts over the wait cap.
|
|
16
|
+
- Planner emits richer `rate_limit` stream events (`retrying` vs `aborted`,
|
|
17
|
+
cap seconds, provider, short error snippet). CLI `new-plan` only shows the
|
|
18
|
+
“waiting to retry” spinner for the retrying phase.
|
|
19
|
+
- Run SSE ends a rate-limit abort with `done` (partial) only — no extra
|
|
20
|
+
`error` line repeating the same message.
|
|
21
|
+
|
|
22
|
+
### Bug fixes
|
|
23
|
+
|
|
24
|
+
- Jira issue search called deprecated `/rest/api/3/search` (Atlassian returns
|
|
25
|
+
HTTP 410). Search now uses `/rest/api/3/search/jql` with clearer 410 errors
|
|
26
|
+
if an old client hits removed endpoints.
|
|
27
|
+
|
|
10
28
|
## [0.7.2] — 2026-04-28
|
|
11
29
|
|
|
12
30
|
### Bug fixes
|
package/dist/cli.js
CHANGED
|
@@ -1685,7 +1685,7 @@ var JiraClient = class {
|
|
|
1685
1685
|
const esc = q.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
1686
1686
|
jql = `text ~ "${esc}" order by updated DESC`;
|
|
1687
1687
|
}
|
|
1688
|
-
const url = `${this.baseUrl}/rest/api/3/search?jql=${encodeURIComponent(jql)}&fields=summary,status,issuetype&maxResults=${limit}`;
|
|
1688
|
+
const url = `${this.baseUrl}/rest/api/3/search/jql?jql=${encodeURIComponent(jql)}&fields=summary,status,issuetype&maxResults=${limit}`;
|
|
1689
1689
|
let res;
|
|
1690
1690
|
try {
|
|
1691
1691
|
res = await fetch(url, { headers: this.headers() });
|
|
@@ -1734,6 +1734,13 @@ var JiraClient = class {
|
|
|
1734
1734
|
if (status === 429) {
|
|
1735
1735
|
return new TrackerError(`Jira rate limit hit (HTTP 429). Wait a minute and retry.`, "rate-limited", status);
|
|
1736
1736
|
}
|
|
1737
|
+
if (status === 410) {
|
|
1738
|
+
return new TrackerError(
|
|
1739
|
+
id === "search" ? `Jira search endpoint has been removed by Atlassian (HTTP 410). squad-kit must call /rest/api/3/search/jql instead \u2014 upgrade squad-kit to a version that includes this fix.` : `Jira endpoint has been removed by Atlassian (HTTP 410). Upgrade squad-kit to a version that calls the current Jira Cloud REST API.`,
|
|
1740
|
+
"other",
|
|
1741
|
+
status
|
|
1742
|
+
);
|
|
1743
|
+
}
|
|
1737
1744
|
return new TrackerError(
|
|
1738
1745
|
id === "search" ? `Jira search failed (HTTP ${status}).` : `Jira request failed (HTTP ${status}).`,
|
|
1739
1746
|
"other",
|
|
@@ -4103,12 +4110,26 @@ async function runPlanner(input5) {
|
|
|
4103
4110
|
let retrySkippedReason;
|
|
4104
4111
|
if (response.stopReason === "error" && response.errorKind === "rate_limit") {
|
|
4105
4112
|
const asked = response.retryAfterSec;
|
|
4113
|
+
const emitRateLimit = (phase, waitSec) => {
|
|
4114
|
+
bus.emit({
|
|
4115
|
+
kind: "rate_limit",
|
|
4116
|
+
runId,
|
|
4117
|
+
turn: iterations,
|
|
4118
|
+
retryAfterSec: response.retryAfterSec,
|
|
4119
|
+
waitSec,
|
|
4120
|
+
capSec: MAX_RATE_LIMIT_RETRY_SEC,
|
|
4121
|
+
phase,
|
|
4122
|
+
provider: input5.provider.name,
|
|
4123
|
+
rawBody: (response.rawError ?? "").slice(0, 200)
|
|
4124
|
+
});
|
|
4125
|
+
};
|
|
4106
4126
|
if (asked !== void 0 && asked > MAX_RATE_LIMIT_RETRY_SEC) {
|
|
4127
|
+
emitRateLimit("aborted", asked);
|
|
4107
4128
|
retrySkippedReason = "retry_after_too_long";
|
|
4108
4129
|
} else {
|
|
4109
4130
|
const waitSec = Math.min(asked ?? 10, MAX_RATE_LIMIT_RETRY_SEC);
|
|
4131
|
+
emitRateLimit("retrying", waitSec);
|
|
4110
4132
|
input5.onRateLimit?.(waitSec);
|
|
4111
|
-
bus.emit({ kind: "rate_limit", runId, turn: iterations, waitSec });
|
|
4112
4133
|
try {
|
|
4113
4134
|
await sleepWithAbort(waitSec * 1e3, sleepFn, input5.abort);
|
|
4114
4135
|
} catch (e) {
|
|
@@ -4888,9 +4909,11 @@ async function emitViaApi(story, paths, config2, opts) {
|
|
|
4888
4909
|
sessionSpinner.current = spinner("thinking\u2026");
|
|
4889
4910
|
break;
|
|
4890
4911
|
case "rate_limit":
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4912
|
+
if (e.phase === "retrying") {
|
|
4913
|
+
sessionSpinner.current?.stop();
|
|
4914
|
+
warning(`${e.provider} rate limit hit \u2014 retrying in ${e.waitSec}s`);
|
|
4915
|
+
sessionSpinner.current = spinner("waiting for rate limit to reset\u2026");
|
|
4916
|
+
}
|
|
4894
4917
|
break;
|
|
4895
4918
|
case "usage":
|
|
4896
4919
|
break;
|
|
@@ -6566,7 +6589,11 @@ function mountRunsApi(app, opts) {
|
|
|
6566
6589
|
});
|
|
6567
6590
|
} catch (err) {
|
|
6568
6591
|
const durationMs = Date.now() - startedAt;
|
|
6569
|
-
|
|
6592
|
+
const last = eventBuffer[eventBuffer.length - 1];
|
|
6593
|
+
const isRateLimitAbort = last?.kind === "rate_limit" && last.phase === "aborted";
|
|
6594
|
+
if (!isRateLimitAbort) {
|
|
6595
|
+
bus.emit({ kind: "error", runId, message: err.message });
|
|
6596
|
+
}
|
|
6570
6597
|
bus.emit({
|
|
6571
6598
|
kind: "done",
|
|
6572
6599
|
runId,
|