fix(studio): a hand-written provider at a declared address takes that preset's vendor mark; the setup cards show vendor marks

The mark for a model came only from the preset a provider was installed from, so an entry pointing at api.deepseek.com by hand drew a letter tile. The address is now read through the curated preset serving it, as vision models already are. Setup service cards draw the mark their vendor declares.
This commit is contained in:
yhh committed 2026-11-05 17:17:45 -08:00
1 parent 1b8b56aa65
commit ca80fec2fc
6 files changed
+53 -12

No files matched your search

@@ -27,7 +27,7 @@
}
.onb-service:hover:not(:disabled) { background: var(--overlay); }
.onb-service[aria-checked="true"] { border-color: var(--accent); background: var(--raised); box-shadow: inset 0 0 0 .5px var(--accent); }
.onb-service b { font: var(--w-semi) var(--fs-ui) var(--ui); }
.onb-service b { display: flex; align-items: center; gap: 6px; font: var(--w-semi) var(--fs-ui) var(--ui); }
.onb-service small { color: var(--faint); font: var(--w-med) var(--fs-micro) var(--ui); }
.onb-models { display: flex; flex-direction: column; gap: 6px; }
@@ -9,7 +9,7 @@ import { describe, expect, it } from "vitest";
// The judgement is structural, never a look at the words: a class is monospaced
// if a rule in app.css gives it var(--mono), and an element renders prose if its
// own children call t(). Nothing here reads what a string says.
const CSS = import.meta.glob("./app.css", { query: "?raw", import: "default", eager: true }) as Record<string, string>;
const CSS = import.meta.glob(["./app.css", "./find.css"], { query: "?raw", import: "default", eager: true }) as Record<string, string>;
const SOURCES = import.meta.glob(["../**/*.tsx", "!../**/*.test.*"], {
query: "?raw",
import: "default",
@@ -132,7 +132,7 @@ function landings(mono: Set<string>): Landing[] {
}
describe("monospace is for machine facts", () => {
const mono = monoClasses(Object.values(CSS)[0]);
const mono = monoClasses(Object.values(CSS).join("\n"));
const all = landings(mono);
const byClass = new Map<string, Landing[]>();
for (const l of all) byClass.set(l.cls, [...(byClass.get(l.cls) ?? []), l]);
+8 -6
View File
@@ -5,6 +5,7 @@ import logoWordmark from "../assets/logo-wordmark.svg";
import { HttpError } from "../port/port";
import type { AgentPort, Protocol, ProviderProbe, ProviderSetup } from "../port/port";
import { KIND_LABEL, nameFrom } from "./vendors";
import { hasVendorMark, VendorMark } from "./vendormarks";
import { Picker } from "./Menu";
import { WindowControls, zoomOnTitleBar } from "./WindowControls";
@@ -25,9 +26,10 @@ interface Props {
// cannot name links to its platform root instead: sending someone to a 404 is
// worse than sending them to a front door. These are addresses on someone
// else's site and will rot; a dead one is a bug report, not a silent failure.
const SHORTCUTS: { label: string; hint: string; url: string; console?: string; protocolUrls?: Record<string, string> }[] = [
const SHORTCUTS: { label: string; hint: string; url: string; mark?: string; console?: string; protocolUrls?: Record<string, string> }[] = [
{
label: "DeepSeek",
mark: "deepseek",
hint: "onboarding.deepseek_hint",
url: "https://api.deepseek.com",
console: "https://platform.deepseek.com/api_keys",
@@ -38,10 +40,10 @@ const SHORTCUTS: { label: string; hint: string; url: string; console?: string; p
},
},
{ label: "onboarding.siliconflow", hint: "onboarding.siliconflow_hint", url: "https://api.siliconflow.cn/v1", console: "https://cloud.siliconflow.cn" },
{ label: "onboarding.moonshot", hint: "onboarding.moonshot_hint", url: "https://api.moonshot.cn/v1", console: "https://platform.moonshot.cn" },
{ label: "onboarding.zhipu", hint: "onboarding.zhipu_hint", url: "https://open.bigmodel.cn/api/paas/v4", console: "https://bigmodel.cn/usercenter/proj-mgmt/apikeys" },
{ label: "MiMo", hint: "onboarding.mimo_hint", url: "https://api.xiaomimimo.com/v1", console: "https://platform.xiaomimimo.com" },
{ label: "LongCat", hint: "onboarding.longcat_hint", url: "https://api.longcat.chat/openai", console: "https://longcat.chat/platform" },
{ mark: "kimi", label: "onboarding.moonshot", hint: "onboarding.moonshot_hint", url: "https://api.moonshot.cn/v1", console: "https://platform.moonshot.cn" },
{ mark: "zhipu", label: "onboarding.zhipu", hint: "onboarding.zhipu_hint", url: "https://open.bigmodel.cn/api/paas/v4", console: "https://bigmodel.cn/usercenter/proj-mgmt/apikeys" },
{ mark: "mimo", label: "MiMo", hint: "onboarding.mimo_hint", url: "https://api.xiaomimimo.com/v1", console: "https://platform.xiaomimimo.com" },
{ mark: "longcat", label: "LongCat", hint: "onboarding.longcat_hint", url: "https://api.longcat.chat/openai", console: "https://longcat.chat/platform" },
{ label: "onboarding.relay_self_hosted", hint: "onboarding.relay_hint", url: "" },
];
@@ -233,7 +235,7 @@ export function Onboarding({ port, setup, onDone, onSkip }: Props) {
{SHORTCUTS.map((s) => (
<button key={s.label} type="button" role="radio" className="onb-service" data-action="onboarding.service" data-value={s.label}
aria-checked={pick === s.label} disabled={busy} onClick={() => choose(s.label, s.url)}>
<b>{t(s.label)}</b><small>{t(s.hint)}</small>
<b>{hasVendorMark(s.mark) && <VendorMark slug={s.mark} size={16} />}{t(s.label)}</b><small>{t(s.hint)}</small>
</button>
))}
</div>
@@ -0,0 +1,21 @@
package config
import "strings"
// CuratedProviderPresetForAddress returns the curated preset one of whose
// entries serves this address, so a hand-written entry pointing at a declared
// service is read through that declaration rather than through its name.
func CuratedProviderPresetForAddress(baseURL string) (ProviderPreset, bool) {
want := strings.TrimRight(strings.TrimSpace(baseURL), "/")
if want == "" {
return ProviderPreset{}, false
}
for _, p := range curatedProviderPresets {
for _, e := range p.Entries {
if strings.TrimRight(strings.TrimSpace(e.BaseURL), "/") == want {
return cloneProviderPreset(p), true
}
}
}
return ProviderPreset{}, false
}
@@ -44,3 +44,18 @@ func TestRelaysAreDeclaredNotInferred(t *testing.T) {
}
}
}
// A hand-written entry pointing at a declared service is read through that
// declaration; an address no preset serves stays unmarked.
func TestAnAddressIsReadThroughThePresetServingIt(t *testing.T) {
preset, ok := CuratedProviderPresetForAddress(" https://api.deepseek.com/ ")
if !ok || preset.Vendor != "deepseek" {
t.Fatalf("api.deepseek.com vendor = %q (found %v), want deepseek", preset.Vendor, ok)
}
if _, ok := CuratedProviderPresetForAddress("https://yyds.yy2hd.com/v1"); ok {
t.Fatal("an address no preset serves must stay unmarked")
}
if _, ok := CuratedProviderPresetForAddress(""); ok {
t.Fatal("an empty address names nothing")
}
}
+6 -3
View File
@@ -407,15 +407,18 @@ func tariffBody(t pricing.Tariff) map[string]any {
}
// presetVendor is the declared vendor of the curated preset a provider came
// from, read through the provenance the entry already records, and whether the
// preset is a relay of other makers' models.
// from or, for a hand-written entry, of the one serving its address, and whether
// the preset is a relay of other makers' models.
func presetVendor(p *config.ProviderEntry) (vendor string, relay bool) {
if p == nil || p.PresetID == "" {
if p == nil {
return "", false
}
if preset, ok := config.CuratedProviderPreset(p.PresetID); ok {
return preset.Vendor, preset.Relay
}
if preset, ok := config.CuratedProviderPresetForAddress(p.BaseURL); ok {
return preset.Vendor, preset.Relay
}
return "", false
}