mirror of
https://github.com/block/buzz.git
synced 2026-11-08 18:31:56 +00:00
624 lines
22 KiB
JavaScript
624 lines
22 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
BUZZ_AGENT_MAX_CONTEXT_TOKENS,
|
|
BUZZ_AGENT_MAX_OUTPUT_TOKENS,
|
|
BUZZ_AGENT_MAX_ROUNDS,
|
|
BUZZ_AGENT_THINKING_EFFORT,
|
|
BUZZ_AGENT_THINKING_EFFORT_VALUES,
|
|
getProviderEffortConfig,
|
|
isBuzzAgentRuntime,
|
|
} from "./buzzAgentConfig.ts";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Thinking effort values
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("BUZZ_AGENT_THINKING_EFFORT_VALUES contains exactly the 7 accepted values", () => {
|
|
assert.deepEqual(
|
|
[...BUZZ_AGENT_THINKING_EFFORT_VALUES],
|
|
["none", "minimal", "low", "medium", "high", "xhigh", "max"],
|
|
);
|
|
});
|
|
|
|
test("BUZZ_AGENT_THINKING_EFFORT_VALUES has no duplicates", () => {
|
|
const set = new Set(BUZZ_AGENT_THINKING_EFFORT_VALUES);
|
|
assert.equal(set.size, BUZZ_AGENT_THINKING_EFFORT_VALUES.length);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Env var key constants
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("env var key constants match expected BUZZ_AGENT_* names", () => {
|
|
assert.equal(BUZZ_AGENT_THINKING_EFFORT, "BUZZ_AGENT_THINKING_EFFORT");
|
|
assert.equal(BUZZ_AGENT_MAX_OUTPUT_TOKENS, "BUZZ_AGENT_MAX_OUTPUT_TOKENS");
|
|
assert.equal(BUZZ_AGENT_MAX_CONTEXT_TOKENS, "BUZZ_AGENT_MAX_CONTEXT_TOKENS");
|
|
assert.equal(BUZZ_AGENT_MAX_ROUNDS, "BUZZ_AGENT_MAX_ROUNDS");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// isBuzzAgentRuntime
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("isBuzzAgentRuntime returns true only for buzz-agent id", () => {
|
|
assert.equal(isBuzzAgentRuntime("buzz-agent"), true);
|
|
});
|
|
|
|
test("isBuzzAgentRuntime returns false for other runtimes", () => {
|
|
assert.equal(isBuzzAgentRuntime("goose"), false);
|
|
assert.equal(isBuzzAgentRuntime("custom"), false);
|
|
assert.equal(isBuzzAgentRuntime(""), false);
|
|
assert.equal(isBuzzAgentRuntime("buzz-agent-v2"), false);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// handleEnvVarChange logic (the field→envVars mapping)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Mirrors the handleEnvVarChange helper in CreateAgentRuntimeFields.
|
|
* Tests this directly without rendering React.
|
|
*/
|
|
function applyEnvVarChange(envVars, key, value) {
|
|
const next = { ...envVars };
|
|
if (value === "") {
|
|
delete next[key];
|
|
} else {
|
|
next[key] = value;
|
|
}
|
|
return next;
|
|
}
|
|
|
|
test("setting a thinking effort value writes the key into envVars", () => {
|
|
const initial = {};
|
|
const result = applyEnvVarChange(initial, BUZZ_AGENT_THINKING_EFFORT, "high");
|
|
assert.equal(result[BUZZ_AGENT_THINKING_EFFORT], "high");
|
|
});
|
|
|
|
test("clearing thinking effort removes the key so the agent inherits", () => {
|
|
const initial = { [BUZZ_AGENT_THINKING_EFFORT]: "high" };
|
|
const result = applyEnvVarChange(initial, BUZZ_AGENT_THINKING_EFFORT, "");
|
|
assert.equal(Object.hasOwn(result, BUZZ_AGENT_THINKING_EFFORT), false);
|
|
});
|
|
|
|
test("setting max output tokens writes the exact BUZZ_AGENT_MAX_OUTPUT_TOKENS key", () => {
|
|
const initial = {};
|
|
const result = applyEnvVarChange(
|
|
initial,
|
|
BUZZ_AGENT_MAX_OUTPUT_TOKENS,
|
|
"4096",
|
|
);
|
|
assert.equal(result[BUZZ_AGENT_MAX_OUTPUT_TOKENS], "4096");
|
|
// Must not affect other keys
|
|
assert.equal(Object.keys(result).length, 1);
|
|
});
|
|
|
|
test("clearing max output tokens removes the key", () => {
|
|
const initial = { [BUZZ_AGENT_MAX_OUTPUT_TOKENS]: "4096" };
|
|
const result = applyEnvVarChange(initial, BUZZ_AGENT_MAX_OUTPUT_TOKENS, "");
|
|
assert.equal(Object.hasOwn(result, BUZZ_AGENT_MAX_OUTPUT_TOKENS), false);
|
|
});
|
|
|
|
test("setting context limit writes the exact BUZZ_AGENT_MAX_CONTEXT_TOKENS key", () => {
|
|
const initial = {};
|
|
const result = applyEnvVarChange(
|
|
initial,
|
|
BUZZ_AGENT_MAX_CONTEXT_TOKENS,
|
|
"100000",
|
|
);
|
|
assert.equal(result[BUZZ_AGENT_MAX_CONTEXT_TOKENS], "100000");
|
|
});
|
|
|
|
test("clearing context limit removes the key", () => {
|
|
const initial = { [BUZZ_AGENT_MAX_CONTEXT_TOKENS]: "100000" };
|
|
const result = applyEnvVarChange(initial, BUZZ_AGENT_MAX_CONTEXT_TOKENS, "");
|
|
assert.equal(Object.hasOwn(result, BUZZ_AGENT_MAX_CONTEXT_TOKENS), false);
|
|
});
|
|
|
|
test("setting max rounds writes the exact BUZZ_AGENT_MAX_ROUNDS key", () => {
|
|
const initial = {};
|
|
const result = applyEnvVarChange(initial, BUZZ_AGENT_MAX_ROUNDS, "50");
|
|
assert.equal(result[BUZZ_AGENT_MAX_ROUNDS], "50");
|
|
});
|
|
|
|
test("clearing max rounds removes the key", () => {
|
|
const initial = { [BUZZ_AGENT_MAX_ROUNDS]: "50" };
|
|
const result = applyEnvVarChange(initial, BUZZ_AGENT_MAX_ROUNDS, "");
|
|
assert.equal(Object.hasOwn(result, BUZZ_AGENT_MAX_ROUNDS), false);
|
|
});
|
|
|
|
test("changing one field does not disturb other env vars", () => {
|
|
const initial = {
|
|
SOME_OTHER_KEY: "value",
|
|
[BUZZ_AGENT_MAX_OUTPUT_TOKENS]: "2048",
|
|
};
|
|
const result = applyEnvVarChange(initial, BUZZ_AGENT_MAX_ROUNDS, "20");
|
|
assert.equal(result.SOME_OTHER_KEY, "value");
|
|
assert.equal(result[BUZZ_AGENT_MAX_OUTPUT_TOKENS], "2048");
|
|
assert.equal(result[BUZZ_AGENT_MAX_ROUNDS], "20");
|
|
});
|
|
|
|
test("clearing one field does not disturb other env vars", () => {
|
|
const initial = {
|
|
SOME_OTHER_KEY: "value",
|
|
[BUZZ_AGENT_MAX_OUTPUT_TOKENS]: "2048",
|
|
[BUZZ_AGENT_MAX_ROUNDS]: "20",
|
|
};
|
|
const result = applyEnvVarChange(initial, BUZZ_AGENT_MAX_ROUNDS, "");
|
|
assert.equal(Object.hasOwn(result, BUZZ_AGENT_MAX_ROUNDS), false);
|
|
assert.equal(result.SOME_OTHER_KEY, "value");
|
|
assert.equal(result[BUZZ_AGENT_MAX_OUTPUT_TOKENS], "2048");
|
|
});
|
|
|
|
test("thinking effort select is bounded: all 7 accepted values are present in the constant", () => {
|
|
const expected = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
for (const v of expected) {
|
|
assert.ok(
|
|
BUZZ_AGENT_THINKING_EFFORT_VALUES.includes(v),
|
|
`missing value: ${v}`,
|
|
);
|
|
}
|
|
assert.equal(BUZZ_AGENT_THINKING_EFFORT_VALUES.length, expected.length);
|
|
});
|
|
|
|
test("non-numeric string is stored as-is (validation is at the backend)", () => {
|
|
// HTML type=number inputs enforce numeric in the browser; we verify the
|
|
// mapping function itself is not a validator — that's intentional.
|
|
const result = applyEnvVarChange(
|
|
{},
|
|
BUZZ_AGENT_MAX_OUTPUT_TOKENS,
|
|
"not-a-number",
|
|
);
|
|
assert.equal(result[BUZZ_AGENT_MAX_OUTPUT_TOKENS], "not-a-number");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// modelTuningRuntimeId → visibility mapping (regression for Edit dialog path)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Mirrors the `isBuzzAgent` derivation in CreateAgentRuntimeFields.
|
|
// The point of modelTuningRuntimeId is that the Edit dialog can pass
|
|
// prospectiveRuntimeId (the real resolved runtime) while selectedRuntimeId
|
|
// carries the "inherit"/"custom" sentinel — the two must not be conflated.
|
|
|
|
test("isBuzzAgentRuntime(prospectiveRuntimeId) shows fields when Edit resolves buzz-agent even though selectedRuntimeId sentinel is 'inherit'", () => {
|
|
// Simulates Edit dialog state: inheritHarness=true, persona is buzz-agent.
|
|
// selectedRuntimeId would be "inherit" (sentinel for custom-command hiding),
|
|
// but prospectiveRuntimeId correctly resolves to "buzz-agent".
|
|
const selectedRuntimeIdSentinel = "inherit"; // what Edit passes to selectedRuntimeId
|
|
const prospectiveRuntimeId = "buzz-agent"; // what Edit passes to modelTuningRuntimeId
|
|
|
|
assert.equal(
|
|
isBuzzAgentRuntime(selectedRuntimeIdSentinel),
|
|
false,
|
|
"sentinel 'inherit' must NOT trigger model-tuning fields",
|
|
);
|
|
assert.equal(
|
|
isBuzzAgentRuntime(prospectiveRuntimeId),
|
|
true,
|
|
"prospectiveRuntimeId 'buzz-agent' MUST trigger model-tuning fields",
|
|
);
|
|
});
|
|
|
|
test("isBuzzAgentRuntime(prospectiveRuntimeId) shows fields when Edit has a pinned buzz-agent (selectedRuntimeId sentinel is also 'inherit')", () => {
|
|
// Simulates Edit dialog with a pinned non-custom runtime:
|
|
// selectedRuntimeId sentinel = "inherit" (non-custom known runtime),
|
|
// prospectiveRuntimeId = "buzz-agent" (selectedRuntime?.id).
|
|
const selectedRuntimeIdSentinel = "inherit";
|
|
const prospectiveRuntimeId = "buzz-agent";
|
|
|
|
assert.equal(isBuzzAgentRuntime(prospectiveRuntimeId), true);
|
|
assert.equal(isBuzzAgentRuntime(selectedRuntimeIdSentinel), false);
|
|
});
|
|
|
|
test("isBuzzAgentRuntime(prospectiveRuntimeId) hides fields when Edit resolves to non-buzz-agent", () => {
|
|
// E.g. user switches from buzz-agent to goose in Edit — prospectiveRuntimeId = "goose"
|
|
const prospectiveRuntimeId = "goose";
|
|
assert.equal(isBuzzAgentRuntime(prospectiveRuntimeId), false);
|
|
});
|
|
|
|
test("isBuzzAgentRuntime(prospectiveRuntimeId) hides fields when Edit has no resolved runtime (empty string)", () => {
|
|
// prospectiveRuntimeId falls back to "" when catalog hasn't loaded yet
|
|
assert.equal(isBuzzAgentRuntime(""), false);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// getProviderEffortConfig — Anthropic model families
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("anthropic unknown model returns adaptive full set with high default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high", "xhigh", "max"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("anthropic claude-3 model returns manual-budget set with null default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-3-7-sonnet-20250219",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high"]);
|
|
assert.equal(defaultValue, null);
|
|
});
|
|
|
|
test("anthropic claude-opus-4-5 returns manual-budget set with null default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-opus-4-5",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high"]);
|
|
assert.equal(defaultValue, null);
|
|
});
|
|
|
|
test("anthropic claude-opus-4-7 returns xhigh-supporting set with high default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-opus-4-7",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high", "xhigh", "max"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("anthropic claude-opus-4-6 returns non-xhigh adaptive set (no xhigh)", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-opus-4-6",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high", "max"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("anthropic claude-sonnet-5 returns xhigh-supporting set", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-sonnet-5-20260101",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high", "xhigh", "max"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("anthropic claude-sonnet-4-6 returns non-xhigh adaptive set", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-sonnet-4-6",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high", "max"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("anthropic claude-mythos-preview returns non-xhigh adaptive set", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-mythos-preview",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high", "max"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("anthropic claude-mythos-5 returns xhigh-supporting set", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-mythos-5",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high", "xhigh", "max"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// getProviderEffortConfig — OpenAI model families
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("openai gpt-5-pro returns only high with high default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"openai",
|
|
"gpt-5-pro",
|
|
);
|
|
assert.deepEqual([...validValues], ["high"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("openai gpt-5.5 returns none/low/medium/high/xhigh with medium default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"openai",
|
|
"gpt-5.5",
|
|
);
|
|
assert.deepEqual(
|
|
[...validValues],
|
|
["none", "low", "medium", "high", "xhigh"],
|
|
);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
test("openai gpt-5.4 returns same table as gpt-5.5", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"openai",
|
|
"gpt-5.4",
|
|
);
|
|
assert.deepEqual(
|
|
[...validValues],
|
|
["none", "low", "medium", "high", "xhigh"],
|
|
);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
test("openai gpt-5.1 returns none/low/medium/high with none default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"openai",
|
|
"gpt-5.1",
|
|
);
|
|
assert.deepEqual([...validValues], ["none", "low", "medium", "high"]);
|
|
assert.equal(defaultValue, "none");
|
|
});
|
|
|
|
test("openai gpt-5 base returns minimal/low/medium/high with medium default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"openai",
|
|
"gpt-5",
|
|
);
|
|
assert.deepEqual([...validValues], ["minimal", "low", "medium", "high"]);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
test("openai unknown model returns all-except-max with medium default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"openai",
|
|
"gpt-4o",
|
|
);
|
|
assert.deepEqual(
|
|
[...validValues],
|
|
["none", "minimal", "low", "medium", "high", "xhigh"],
|
|
);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
test("openai empty model returns all-except-max with medium default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig("openai", "");
|
|
assert.deepEqual(
|
|
[...validValues],
|
|
["none", "minimal", "low", "medium", "high", "xhigh"],
|
|
);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
// gpt-5-pro must not match the gpt-5 base bucket
|
|
test("openai gpt-5-pro is not matched by gpt-5 base bucket", () => {
|
|
const { validValues } = getProviderEffortConfig("openai", "gpt-5-pro");
|
|
assert.deepEqual(
|
|
[...validValues],
|
|
["high"],
|
|
"gpt-5-pro must use its own table",
|
|
);
|
|
});
|
|
|
|
// gpt-5.10 must NOT match gpt-5.1 (digit boundary)
|
|
test("openai gpt-5.10 is not matched by gpt-5.1 token", () => {
|
|
const { validValues } = getProviderEffortConfig("openai", "gpt-5.10");
|
|
// gpt-5.10 doesn't match any specific family → falls into unknown table
|
|
assert.deepEqual(
|
|
[...validValues],
|
|
["none", "minimal", "low", "medium", "high", "xhigh"],
|
|
);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// getProviderEffortConfig — DatabricksV2 routing
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("databricks_v2 with claude-opus-4-7 routes to anthropic xhigh table", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"claude-opus-4-7",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high", "xhigh", "max"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("databricks_v2 with databricks-prefixed claude model strips prefix and routes correctly", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"databricks-claude-opus-4-7",
|
|
);
|
|
assert.deepEqual([...validValues], ["low", "medium", "high", "xhigh", "max"]);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("databricks_v2 with gpt-5.4 routes to openai gpt-5.5/5.4 table", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"gpt-5.4",
|
|
);
|
|
assert.deepEqual(
|
|
[...validValues],
|
|
["none", "low", "medium", "high", "xhigh"],
|
|
);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
test("databricks_v2 with databricks-gpt-5.1 strips prefix and routes to OpenAI gpt-5.1", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"databricks-gpt-5.1",
|
|
);
|
|
assert.deepEqual([...validValues], ["none", "low", "medium", "high"]);
|
|
assert.equal(defaultValue, "none");
|
|
});
|
|
|
|
test("databricks_v2 with concrete non-claude non-gpt model excludes max (MLflow clamps it)", () => {
|
|
// llama-3 routes through MlflowChatCompletions → normalize_effort_for_openai_route
|
|
// → max is clamped to xhigh. Show all-except-max so the UI is honest.
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"llama-3",
|
|
);
|
|
assert.deepEqual(
|
|
[...validValues],
|
|
["none", "minimal", "low", "medium", "high", "xhigh"],
|
|
);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
test("databricks_v2 with databricks-prefixed llama model strips prefix and excludes max", () => {
|
|
const { validValues } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"databricks-llama-3",
|
|
);
|
|
assert.ok(!validValues.includes("max"));
|
|
});
|
|
|
|
test("databricks_v2 goose-claude-fable-5 strips goose- prefix and routes to anthropic adaptive+xhigh", () => {
|
|
// "goose-claude-fable-5": first claude- occurrence at index 6 → strips "goose-"
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"goose-claude-fable-5",
|
|
);
|
|
assert.ok(
|
|
validValues.includes("max"),
|
|
"max must be valid for goose-claude-fable-5 (adaptive xhigh model)",
|
|
);
|
|
assert.ok(
|
|
validValues.includes("xhigh"),
|
|
"xhigh must be valid for goose-claude-fable-5",
|
|
);
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("databricks_v2 goose-gpt-5.5 strips goose- prefix and routes to openai gpt-5.5 table", () => {
|
|
// "goose-gpt-5.5": first gpt- occurrence at index 6 → strips "goose-"
|
|
const { validValues } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"goose-gpt-5.5",
|
|
);
|
|
assert.ok(!validValues.includes("max"), "max must be excluded for gpt-5.5");
|
|
assert.ok(validValues.includes("xhigh"), "xhigh must be valid for gpt-5.5");
|
|
assert.ok(
|
|
!validValues.includes("minimal"),
|
|
"minimal is not in gpt-5.5 table",
|
|
);
|
|
});
|
|
|
|
test("databricks_v2 arbitrary prefix team-x-claude-opus-4-7 strips to claude-opus-4-7 and routes to anthropic xhigh", () => {
|
|
// "team-x-claude-opus-4-7": first claude- occurrence at index 7 → strips "team-x-"
|
|
// Same routing result as bare "claude-opus-4-7" — verifies prefix allowlist is not required.
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"team-x-claude-opus-4-7",
|
|
);
|
|
assert.ok(
|
|
validValues.includes("max"),
|
|
"max must be valid: claude-opus-4-7 is adaptive xhigh",
|
|
);
|
|
assert.ok(validValues.includes("xhigh"), "xhigh must be valid");
|
|
assert.equal(defaultValue, "high");
|
|
});
|
|
|
|
test("databricks_v2 with empty model returns all-7 (blank = route unknown)", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"databricks_v2",
|
|
"",
|
|
);
|
|
assert.equal(validValues.length, 7);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// getProviderEffortConfig — databricks v1 and other providers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("databricks v1 routes like openai unknown (no gpt-5 model)", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"databricks",
|
|
"",
|
|
);
|
|
assert.deepEqual(
|
|
[...validValues],
|
|
["none", "minimal", "low", "medium", "high", "xhigh"],
|
|
);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
test("openai-compat returns all-7 with medium default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig(
|
|
"openai-compat",
|
|
"",
|
|
);
|
|
assert.equal(validValues.length, 7);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
test("empty provider returns all-7 with medium default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig("", "");
|
|
assert.equal(validValues.length, 7);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
test("unknown provider returns all-7 with medium default", () => {
|
|
const { validValues, defaultValue } = getProviderEffortConfig("goose", "");
|
|
assert.equal(validValues.length, 7);
|
|
assert.equal(defaultValue, "medium");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// getProviderEffortConfig — provider case-insensitivity
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("provider id matching is case-insensitive", () => {
|
|
const lower = getProviderEffortConfig("anthropic", "claude-opus-4-7");
|
|
const upper = getProviderEffortConfig("Anthropic", "claude-opus-4-7");
|
|
assert.deepEqual([...lower.validValues], [...upper.validValues]);
|
|
assert.equal(lower.defaultValue, upper.defaultValue);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// getProviderEffortConfig — auto-clear logic (valid-values membership)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Tests below verify the validValues membership check that the auto-clear
|
|
// useEffect in BuzzAgentModelTuningFields and AgentDefaultsSettingsCard
|
|
// use to decide whether to reset the current effort to Inherit.
|
|
|
|
test("effort max is invalid for OpenAI (should trigger auto-clear)", () => {
|
|
const { validValues } = getProviderEffortConfig("openai", "gpt-5.1");
|
|
assert.ok(!validValues.includes("max"), "max must not be in gpt-5.1 set");
|
|
});
|
|
|
|
test("effort none is invalid for Anthropic adaptive (should trigger auto-clear)", () => {
|
|
const { validValues } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-opus-4-7",
|
|
);
|
|
assert.ok(!validValues.includes("none"), "none must not be in anthropic set");
|
|
});
|
|
|
|
test("effort high is valid for all providers (must not trigger auto-clear)", () => {
|
|
for (const provider of [
|
|
"anthropic",
|
|
"openai",
|
|
"databricks_v2",
|
|
"databricks",
|
|
"openai-compat",
|
|
"",
|
|
]) {
|
|
const { validValues } = getProviderEffortConfig(provider, "");
|
|
assert.ok(
|
|
validValues.includes("high"),
|
|
`high must be valid for provider "${provider}"`,
|
|
);
|
|
}
|
|
});
|
|
|
|
test("effort none is invalid for anthropic manual-budget (should trigger auto-clear)", () => {
|
|
const { validValues } = getProviderEffortConfig(
|
|
"anthropic",
|
|
"claude-3-7-sonnet-20250219",
|
|
);
|
|
assert.ok(
|
|
!validValues.includes("none"),
|
|
"none must not be in manual-budget set",
|
|
);
|
|
});
|