fix(usage): restore xai quota label case; update stale kiro tests
3-way unit-suite comparison (branch-pre-merge vs origin/master vs HEAD) with git worktrees: * ProviderLimits/utils.js: parseQuotaData 'xai' case (ab9a3c1dweekly/api_usage label mapping) was dropped by an EARLIER merge (already failing at the pre-merge branch tip) — its companion test xai-usage.test.js has been red since. Restored verbatim from ab9a3c1d; the xai usage handler + dispatch entry survived, only the UI label mapping was lost. * openai-to-kiro.test.js: 19 failures were stale upstream tests —1fc2a81dintentionally removed the redundant top-level systemPrompt field (Kiro rejects it) without updating them. The thinking/agentic directives now ride the frozen session-start msg0 via contentPrefix. systemPromptOf reads msg0 (or the current message when there is no replayed session); the cross-turn stability test asserts the actual cacheability contract. Suite now: 83 failing vs 103 on origin/master baseline; zero files fail in HEAD that did not fail pre-merge. next build passes.
This commit is contained in:
@@ -666,6 +666,48 @@ export function parseQuotaData(provider, data) {
|
||||
}
|
||||
break;
|
||||
|
||||
case "xai":
|
||||
// xAI mixes:
|
||||
// - weekly: percentage window (used/total 0-100) from GetGrokCreditsConfig
|
||||
// - api_usage: absolute monthly credits from /v1/billing
|
||||
// For absolute rows, do not forward remainingCredits as `remaining`
|
||||
// (QuotaTable treats remaining as a 0-100 percentage; same pitfall as Qoder).
|
||||
if (data.quotas) {
|
||||
Object.entries(data.quotas).forEach(([quotaType, quota]) => {
|
||||
const name =
|
||||
quotaType === "weekly"
|
||||
? "Weekly limit"
|
||||
: quotaType === "api_usage"
|
||||
? "Api usage"
|
||||
: quotaType === "monthly"
|
||||
? "Api usage"
|
||||
: quotaType === "on_demand"
|
||||
? "On-demand"
|
||||
: quotaType;
|
||||
|
||||
if (quotaType === "weekly") {
|
||||
normalizedQuotas.push({
|
||||
name,
|
||||
used: quota.used || 0,
|
||||
total: quota.total || 100,
|
||||
remaining: quota.remaining,
|
||||
remainingPercentage: quota.remainingPercentage ?? quota.remaining,
|
||||
resetAt: quota.resetAt || null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
normalizedQuotas.push({
|
||||
name,
|
||||
used: quota.used || 0,
|
||||
total: quota.total || 0,
|
||||
unit: quota.unit,
|
||||
resetAt: quota.resetAt || null,
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Generic fallback for unknown providers
|
||||
if (data.quotas) {
|
||||
|
||||
@@ -11,7 +11,16 @@ import { openaiToKiroRequest } from "../../open-sse/translator/request/openai-to
|
||||
|
||||
const contentOf = (result) =>
|
||||
result.conversationState.currentMessage.userInputMessage.content;
|
||||
const systemPromptOf = (result) => result.systemPrompt || "";
|
||||
// 1fc2a81d dropped the redundant top-level systemPrompt field (Kiro rejects
|
||||
// it): thinking/agentic directives ride into the frozen session-start message
|
||||
// (msg0) via contentPrefix, or into the current message when there is no
|
||||
// session to replay. Read whichever carries them.
|
||||
const systemPromptOf = (result) => {
|
||||
const cs = result.conversationState || {};
|
||||
const msg0 = cs.history?.[0]?.userInputMessage?.content;
|
||||
if (typeof msg0 === "string" && msg0) return msg0;
|
||||
return cs.currentMessage?.userInputMessage?.content || "";
|
||||
};
|
||||
|
||||
describe("openaiToKiroRequest", () => {
|
||||
describe("basic message conversion", () => {
|
||||
@@ -568,23 +577,36 @@ describe("openaiToKiroRequest", () => {
|
||||
expect(systemPromptOf(result)).toContain("<max_thinking_length>16000</max_thinking_length>");
|
||||
});
|
||||
|
||||
it("keeps top-level systemPrompt stable across turns", () => {
|
||||
it("keeps the frozen session-start directive stable across turns", () => {
|
||||
// Upstream dropped the redundant top-level systemPrompt; cacheability
|
||||
// now lives in the replayed msg0. Assert the directive rides msg0 and
|
||||
// the volatile clock only enters the current turn.
|
||||
const credentials = {
|
||||
connectionId: "kiro-account-openai-stable",
|
||||
rawHeaders: { "x-session-id": "hermes-session-openai-stable" },
|
||||
};
|
||||
const first = openaiToKiroRequest(
|
||||
"claude-sonnet-4.6-thinking",
|
||||
{ messages: [{ role: "user", content: "first" }] },
|
||||
true,
|
||||
{}
|
||||
credentials
|
||||
);
|
||||
const second = openaiToKiroRequest(
|
||||
"claude-sonnet-4.6-thinking",
|
||||
{ messages: [{ role: "user", content: "second" }] },
|
||||
true,
|
||||
{}
|
||||
credentials
|
||||
);
|
||||
|
||||
expect(first.systemPrompt).toBe(second.systemPrompt);
|
||||
expect(first.systemPrompt).not.toContain("Current time");
|
||||
expect(first.conversationState.currentMessage.userInputMessage.content).toContain("Current time");
|
||||
const msg0 = second.conversationState.history[0].userInputMessage.content;
|
||||
// msg0 carries the thinking directive and is replayed byte-identical on
|
||||
// later turns (upstream prefix includes the session-start timestamp;
|
||||
// the cacheability contract is that it does NOT change per turn).
|
||||
expect(msg0).toBe(first.conversationState.currentMessage.userInputMessage.content);
|
||||
expect(msg0).toContain("<max_thinking_length>");
|
||||
const cur = second.conversationState.currentMessage.userInputMessage.content;
|
||||
expect(cur).toContain("second");
|
||||
expect(cur).toContain("Current time");
|
||||
});
|
||||
|
||||
it("replays frozen msg0 for explicit Kiro sessions while keeping current time fresh", () => {
|
||||
|
||||
Reference in New Issue
Block a user