fix(gsd): apply fast service tier outside auto-mode (#2126)
This commit is contained in:
parent
a9667209ef
commit
b0fc552a2e
3 changed files with 60 additions and 10 deletions
|
|
@ -20,21 +20,27 @@ import { saveActivityLog } from "../activity-log.js";
|
|||
// printed it before the TUI launched. Only re-print on /clear (subsequent sessions).
|
||||
let isFirstSession = true;
|
||||
|
||||
async function syncServiceTierStatus(ctx: ExtensionContext): Promise<void> {
|
||||
const { getEffectiveServiceTier, formatServiceTierFooterStatus } = await import("../service-tier.js");
|
||||
ctx.ui.setStatus("gsd-fast", formatServiceTierFooterStatus(getEffectiveServiceTier(), ctx.model?.id));
|
||||
}
|
||||
|
||||
export function registerHooks(pi: ExtensionAPI): void {
|
||||
pi.on("session_start", async (_event, ctx) => {
|
||||
resetWriteGateState();
|
||||
resetToolCallLoopGuard();
|
||||
await syncServiceTierStatus(ctx);
|
||||
if (isFirstSession) {
|
||||
isFirstSession = false;
|
||||
} else {
|
||||
try {
|
||||
const gsdBinPath = process.env.GSD_BIN_PATH;
|
||||
if (gsdBinPath) {
|
||||
const { dirname } = await import('node:path');
|
||||
const { dirname } = await import("node:path");
|
||||
const { printWelcomeScreen } = await import(
|
||||
join(dirname(gsdBinPath), 'welcome-screen.js')
|
||||
join(dirname(gsdBinPath), "welcome-screen.js")
|
||||
) as { printWelcomeScreen: (opts: { version: string; modelName?: string; provider?: string }) => void };
|
||||
printWelcomeScreen({ version: process.env.GSD_VERSION || '0.0.0' });
|
||||
printWelcomeScreen({ version: process.env.GSD_VERSION || "0.0.0" });
|
||||
}
|
||||
} catch { /* non-fatal */ }
|
||||
}
|
||||
|
|
@ -192,8 +198,11 @@ export function registerHooks(pi: ExtensionAPI): void {
|
|||
markToolEnd(event.toolCallId);
|
||||
});
|
||||
|
||||
pi.on("model_select", async (_event, ctx) => {
|
||||
await syncServiceTierStatus(ctx);
|
||||
});
|
||||
|
||||
pi.on("before_provider_request", async (event) => {
|
||||
if (!isAutoActive()) return;
|
||||
const modelId = event.model?.id;
|
||||
if (!modelId) return;
|
||||
const { getEffectiveServiceTier, supportsServiceTier } = await import("../service-tier.js");
|
||||
|
|
@ -205,4 +214,3 @@ export function registerHooks(pi: ExtensionAPI): void {
|
|||
return payload;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import { ensurePreferencesFile, serializePreferencesToFrontmatter } from "./comm
|
|||
|
||||
export type ServiceTierSetting = "priority" | "flex" | undefined;
|
||||
|
||||
const SERVICE_TIER_SCOPE_NOTE = "Only affects gpt-5.4 models, regardless of provider.";
|
||||
|
||||
// ─── Gating ──────────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
|
|
@ -51,7 +53,7 @@ export function formatServiceTierStatus(tier: ServiceTierSetting): string {
|
|||
" /gsd fast flex Set to flex (0.5x cost, slower)",
|
||||
" /gsd fast off Disable service tier",
|
||||
"",
|
||||
"Only affects gpt-5.4 models.",
|
||||
SERVICE_TIER_SCOPE_NOTE,
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
|
|
@ -64,10 +66,18 @@ export function formatServiceTierStatus(tier: ServiceTierSetting): string {
|
|||
" /gsd fast flex Set to flex (0.5x cost, slower)",
|
||||
" /gsd fast off Disable service tier",
|
||||
"",
|
||||
"Only affects gpt-5.4 models.",
|
||||
SERVICE_TIER_SCOPE_NOTE,
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
export function formatServiceTierFooterStatus(
|
||||
tier: ServiceTierSetting,
|
||||
modelId: string | undefined,
|
||||
): string | undefined {
|
||||
if (!tier || !modelId || !supportsServiceTier(modelId)) return undefined;
|
||||
return tier === "priority" ? "fast: ⚡ priority" : "fast: 💰 flex";
|
||||
}
|
||||
|
||||
// ─── Icon Resolution ─────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
|
|
@ -148,19 +158,22 @@ export async function handleFast(args: string, ctx: ExtensionCommandContext): Pr
|
|||
|
||||
if (trimmed === "on") {
|
||||
await writeGlobalServiceTier(ctx, "priority");
|
||||
ctx.ui.notify("Service tier set to priority (2x cost, faster responses). Only affects gpt-5.4 models.", "info");
|
||||
ctx.ui.setStatus("gsd-fast", formatServiceTierFooterStatus("priority", ctx.model?.id));
|
||||
ctx.ui.notify("Service tier set to priority (2x cost, faster responses). Only affects gpt-5.4 models, regardless of provider.", "info");
|
||||
return;
|
||||
}
|
||||
|
||||
if (trimmed === "off") {
|
||||
await writeGlobalServiceTier(ctx, undefined);
|
||||
ctx.ui.setStatus("gsd-fast", undefined);
|
||||
ctx.ui.notify("Service tier disabled.", "info");
|
||||
return;
|
||||
}
|
||||
|
||||
if (trimmed === "flex") {
|
||||
await writeGlobalServiceTier(ctx, "flex");
|
||||
ctx.ui.notify("Service tier set to flex (0.5x cost, slower responses). Only affects gpt-5.4 models.", "info");
|
||||
ctx.ui.setStatus("gsd-fast", formatServiceTierFooterStatus("flex", ctx.model?.id));
|
||||
ctx.ui.notify("Service tier set to flex (0.5x cost, slower responses). Only affects gpt-5.4 models, regardless of provider.", "info");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import assert from "node:assert/strict";
|
|||
import {
|
||||
supportsServiceTier,
|
||||
formatServiceTierStatus,
|
||||
formatServiceTierFooterStatus,
|
||||
resolveServiceTierIcon,
|
||||
type ServiceTierSetting,
|
||||
} from "../service-tier.ts";
|
||||
|
||||
// ─── supportsServiceTier ─────────────────────────────────────────────────────
|
||||
|
|
@ -27,6 +27,14 @@ describe("supportsServiceTier", () => {
|
|||
assert.equal(supportsServiceTier("openai/gpt-5.4"), true);
|
||||
});
|
||||
|
||||
test("returns true for vibeproxy-openai/gpt-5.4 (proxy provider-prefixed)", () => {
|
||||
assert.equal(supportsServiceTier("vibeproxy-openai/gpt-5.4"), true);
|
||||
});
|
||||
|
||||
test("returns false for provider-only identifier without gpt-5.4 model suffix", () => {
|
||||
assert.equal(supportsServiceTier("vibeproxy-openai"), false);
|
||||
});
|
||||
|
||||
test("returns false for claude-opus-4-6", () => {
|
||||
assert.equal(supportsServiceTier("claude-opus-4-6"), false);
|
||||
});
|
||||
|
|
@ -52,6 +60,11 @@ describe("formatServiceTierStatus", () => {
|
|||
assert.ok(output.includes("disabled"), `Expected 'disabled' in: ${output}`);
|
||||
});
|
||||
|
||||
test("mentions provider-agnostic model gating", () => {
|
||||
const output = formatServiceTierStatus("priority");
|
||||
assert.ok(output.includes("regardless of provider"), `Expected provider note in: ${output}`);
|
||||
});
|
||||
|
||||
test("shows priority when set to priority", () => {
|
||||
const output = formatServiceTierStatus("priority");
|
||||
assert.ok(output.includes("priority"), `Expected 'priority' in: ${output}`);
|
||||
|
|
@ -63,6 +76,22 @@ describe("formatServiceTierStatus", () => {
|
|||
});
|
||||
});
|
||||
|
||||
// ─── formatServiceTierFooterStatus ───────────────────────────────────────────
|
||||
|
||||
describe("formatServiceTierFooterStatus", () => {
|
||||
test("returns priority footer status for supported model", () => {
|
||||
assert.equal(formatServiceTierFooterStatus("priority", "vibeproxy-openai/gpt-5.4"), "fast: ⚡ priority");
|
||||
});
|
||||
|
||||
test("returns undefined for unsupported model", () => {
|
||||
assert.equal(formatServiceTierFooterStatus("priority", "claude-opus-4-6"), undefined);
|
||||
});
|
||||
|
||||
test("returns undefined when tier is disabled", () => {
|
||||
assert.equal(formatServiceTierFooterStatus(undefined, "gpt-5.4"), undefined);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── resolveServiceTierIcon ──────────────────────────────────────────────────
|
||||
|
||||
describe("resolveServiceTierIcon", () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue