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;
|
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:
|
default:
|
||||||
// Generic fallback for unknown providers
|
// Generic fallback for unknown providers
|
||||||
if (data.quotas) {
|
if (data.quotas) {
|
||||||
|
|||||||
@@ -11,7 +11,16 @@ import { openaiToKiroRequest } from "../../open-sse/translator/request/openai-to
|
|||||||
|
|
||||||
const contentOf = (result) =>
|
const contentOf = (result) =>
|
||||||
result.conversationState.currentMessage.userInputMessage.content;
|
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("openaiToKiroRequest", () => {
|
||||||
describe("basic message conversion", () => {
|
describe("basic message conversion", () => {
|
||||||
@@ -568,23 +577,36 @@ describe("openaiToKiroRequest", () => {
|
|||||||
expect(systemPromptOf(result)).toContain("<max_thinking_length>16000</max_thinking_length>");
|
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(
|
const first = openaiToKiroRequest(
|
||||||
"claude-sonnet-4.6-thinking",
|
"claude-sonnet-4.6-thinking",
|
||||||
{ messages: [{ role: "user", content: "first" }] },
|
{ messages: [{ role: "user", content: "first" }] },
|
||||||
true,
|
true,
|
||||||
{}
|
credentials
|
||||||
);
|
);
|
||||||
const second = openaiToKiroRequest(
|
const second = openaiToKiroRequest(
|
||||||
"claude-sonnet-4.6-thinking",
|
"claude-sonnet-4.6-thinking",
|
||||||
{ messages: [{ role: "user", content: "second" }] },
|
{ messages: [{ role: "user", content: "second" }] },
|
||||||
true,
|
true,
|
||||||
{}
|
credentials
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(first.systemPrompt).toBe(second.systemPrompt);
|
const msg0 = second.conversationState.history[0].userInputMessage.content;
|
||||||
expect(first.systemPrompt).not.toContain("Current time");
|
// msg0 carries the thinking directive and is replayed byte-identical on
|
||||||
expect(first.conversationState.currentMessage.userInputMessage.content).toContain("Current time");
|
// 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", () => {
|
it("replays frozen msg0 for explicit Kiro sessions while keeping current time fresh", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user