Files
OmniRoute/tests/unit/server-owned-tool-loop-flag.test.ts
Diego Rodrigues de Sa e Souza d8be3b1a77 feat(sse): reserve the Antigravity account for the request's stream lifecycle (re-land of #10011) (#13929)
* feat(sse): reserve the Antigravity account for the request's stream lifecycle

Re-land of the account-lease half of #10011 on the current release branch.
Its exact-model-scoping half had already shipped in #8050 and its quota half
lost to the tip's aggregate-family design (selectAntigravityQuotaWindowNames /
antigravityQuotaFamily.ts); none of that is reintroduced here. The lease is a
concurrency reservation only and never reads or writes quota state.

The Antigravity account selected for a request is reserved for the whole
streaming lifecycle of that request, so a concurrent retry — or the credential
handoff inside getProviderCredentialsWithQuotaPreflight — cannot re-pick an
account already committed to an in-flight upstream stream. The reservation is
scoped to (connection, callable upstream model) rather than the whole account,
so one account can still serve two different models at once; catalog ids that
resolve to the same upstream id (the gemini-3.7-flash tiers, all
gemini-3.7-flash-tiered) share one lease. When every eligible account is leased
for that model the request returns a structured 503 antigravity_pool_busy with
a bounded Retry-After instead of piling onto a busy account.

Opt-in behind ANTIGRAVITY_ACCOUNT_LEASE_ENABLED (runtime, default false). With
the flag off no reservation is taken, credentials carry no routing descriptor,
every release/hold is a no-op on an undefined lease id, and account selection
and dispatch behave exactly as before.

#10011's original test suite asserted family semantics for a lease that was
exact-model scoped and failed deterministically on its own head; the model ids
it used (gemini-3.5-flash / gemini-3-flash-agent) no longer exist in the
catalog. The contradiction is resolved in favour of one coherent semantic —
exact callable upstream model — and the tests assert it against the alias
tables as they are on this branch.

Co-authored-by: Ardem2025 <openclaw-auto@example.invalid>

* fix(sse): widen the Antigravity lease reservation result so auth.ts narrows it

The discriminated-union form of reserveAntigravityLeaseForSelection's return type
did not narrow under tsconfig.typecheck-api.json, so reading `reserved.lease`
after the `reserved.busy` early return raised TS2339 in the API Route Typecheck
gate. A single optional-property shape carries the same information and type-checks
everywhere.

Co-authored-by: Ardem2025 <openclaw-auto@example.invalid>

---------

Co-authored-by: Ardem2025 <openclaw-auto@example.invalid>
2026-09-18 12:09:02 -03:00

141 lines
5.2 KiB
TypeScript

import { describe, it, before, after, beforeEach } from "node:test";
import assert from "node:assert/strict";
import os from "node:os";
import path from "node:path";
import fs from "node:fs";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-test-flag-loop-"));
process.env.DATA_DIR = tmpDir;
const { FEATURE_FLAG_DEFINITIONS } =
await import("../../src/shared/constants/featureFlagDefinitions.ts");
const { setFeatureFlagOverride, clearAllFeatureFlagOverrides } =
await import("../../src/lib/db/featureFlags.ts");
const { isServerOwnedToolLoopEnabled } = await import("../../src/shared/utils/featureFlags.ts");
describe("SERVER_OWNED_TOOL_LOOP_ENABLED flag definition", () => {
it("exists in FEATURE_FLAG_DEFINITIONS", () => {
const def = FEATURE_FLAG_DEFINITIONS.find((d) => d.key === "SERVER_OWNED_TOOL_LOOP_ENABLED");
assert.ok(def, "SERVER_OWNED_TOOL_LOOP_ENABLED should exist");
assert.equal(def.category, "runtime");
assert.equal(def.defaultValue, "false");
assert.equal(def.requiresRestart, false);
assert.equal(def.descriptionI18nKey, "featureFlagServerOwnedToolLoopDescription");
});
});
describe("isServerOwnedToolLoopEnabled wrapper", () => {
beforeEach(() => {
clearAllFeatureFlagOverrides();
});
it("returns false when no override is set (default)", () => {
assert.equal(isServerOwnedToolLoopEnabled(), false);
});
it("returns true when DB override is set to true", () => {
setFeatureFlagOverride("SERVER_OWNED_TOOL_LOOP_ENABLED", "true");
assert.equal(isServerOwnedToolLoopEnabled(), true);
});
it("returns false and logs when injected reader throws", () => {
const logs: unknown[] = [];
const origError = console.error;
console.error = (...args: unknown[]) => {
logs.push(args);
};
try {
const throwingReader = () => {
throw new Error("flag read failed");
};
const result = isServerOwnedToolLoopEnabled(throwingReader);
assert.equal(result, false);
assert.ok(logs.length >= 1, "console.error should be called at least once");
assert.ok(
logs.some((args) =>
String(args).includes("Failed to resolve SERVER_OWNED_TOOL_LOOP_ENABLED")
),
"error log should mention the flag key"
);
} finally {
console.error = origError;
}
});
});
describe("feature-flags-settings count update", () => {
it("flag count matches updated expected value", () => {
assert.equal(FEATURE_FLAG_DEFINITIONS.length, 73);
});
});
describe("i18n key parity for SERVER_OWNED_TOOL_LOOP_ENABLED", () => {
let enMessages: Record<string, unknown>;
let ptBrMessages: Record<string, unknown>;
before(async () => {
const enRaw = fs.readFileSync(
path.resolve(__dirname, "../../src/i18n/messages/en.json"),
"utf8"
);
enMessages = JSON.parse(enRaw);
const ptBrRaw = fs.readFileSync(
path.resolve(__dirname, "../../src/i18n/messages/pt-BR.json"),
"utf8"
);
ptBrMessages = JSON.parse(ptBrRaw);
});
it("en.json has nested featureFlags.definitions.SERVER_OWNED_TOOL_LOOP_ENABLED.label", () => {
const defs = enMessages.featureFlags as Record<string, unknown> | undefined;
assert.ok(defs, "en.json should have featureFlags section");
const definitions = (defs as Record<string, unknown>).definitions as
Record<string, unknown> | undefined;
assert.ok(definitions, "en.json featureFlags should have definitions");
const flagDef = definitions.SERVER_OWNED_TOOL_LOOP_ENABLED as
Record<string, unknown> | undefined;
assert.ok(flagDef, "definitions should contain SERVER_OWNED_TOOL_LOOP_ENABLED");
assert.equal(flagDef.label, "Server-Owned Tool Loop");
assert.equal(
flagDef.description,
"Continue non-streaming server-owned tool calls until the model returns a client-usable response."
);
});
it("pt-BR.json has nested featureFlags.definitions.SERVER_OWNED_TOOL_LOOP_ENABLED.label", () => {
const defs = ptBrMessages.featureFlags as Record<string, unknown> | undefined;
assert.ok(defs, "pt-BR.json should have featureFlags section");
const definitions = (defs as Record<string, unknown>).definitions as
Record<string, unknown> | undefined;
assert.ok(definitions, "pt-BR.json featureFlags should have definitions");
const flagDef = definitions.SERVER_OWNED_TOOL_LOOP_ENABLED as
Record<string, unknown> | undefined;
assert.ok(flagDef, "definitions should contain SERVER_OWNED_TOOL_LOOP_ENABLED");
assert.equal(flagDef.label, "Server-Owned Tool Loop");
assert.equal(typeof flagDef.description, "string");
assert.ok(
((flagDef.description as string) || "").length > 0,
"description should be non-empty"
);
});
it("en.json does NOT have stale top-level featureFlagServerOwnedToolLoopDescription", () => {
assert.equal(
(enMessages as Record<string, unknown>).featureFlagServerOwnedToolLoopDescription,
undefined,
"top-level key should be removed"
);
});
});
after(() => {
try {
fs.rmSync(tmpDir, { recursive: true, force: true });
} catch {
// ignore
}
});