@vellumai/assistant 0.10.5-dev.202607022248.91fa053 → 0.10.5-dev.202607022329.d89bf2f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.10.5-dev.202607022248.91fa053",
3
+ "version": "0.10.5-dev.202607022329.d89bf2f",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -0,0 +1,51 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import {
4
+ formatVellumModel,
5
+ MANAGED_ROUTABLE_PROVIDERS,
6
+ parseVellumModel,
7
+ } from "./vellum-model-routing.js";
8
+
9
+ describe("vellum-model-routing", () => {
10
+ test("round-trips a slashy native Fireworks id losslessly", () => {
11
+ const native = "accounts/fireworks/models/minimax-m3";
12
+ const encoded = formatVellumModel("fireworks", native);
13
+ expect(encoded).toBe("fireworks/accounts/fireworks/models/minimax-m3");
14
+ expect(parseVellumModel(encoded)).toEqual({
15
+ provider: "fireworks",
16
+ model: native,
17
+ });
18
+ });
19
+
20
+ test("round-trips a bare Anthropic id", () => {
21
+ const encoded = formatVellumModel("anthropic", "claude-fable-5");
22
+ expect(parseVellumModel(encoded)).toEqual({
23
+ provider: "anthropic",
24
+ model: "claude-fable-5",
25
+ });
26
+ });
27
+
28
+ test("format rejects a non-managed provider", () => {
29
+ expect(() => formatVellumModel("openrouter", "x")).toThrow();
30
+ expect(() => formatVellumModel("fireworks", "")).toThrow();
31
+ });
32
+
33
+ test("parse returns null for non-routed strings", () => {
34
+ expect(parseVellumModel("claude-opus-4-8")).toBeNull(); // no slash
35
+ expect(parseVellumModel("openrouter/whatever")).toBeNull(); // not managed
36
+ expect(parseVellumModel("minimax/minimax-m3")).toBeNull(); // not managed
37
+ expect(parseVellumModel("fireworks/")).toBeNull(); // empty model
38
+ expect(parseVellumModel("/foo")).toBeNull(); // empty provider
39
+ });
40
+
41
+ test("managed set matches the platform proxy table", () => {
42
+ // Guards against drift if PLATFORM_PROVIDER_META changes.
43
+ expect([...MANAGED_ROUTABLE_PROVIDERS].sort()).toEqual([
44
+ "anthropic",
45
+ "fireworks",
46
+ "gemini",
47
+ "openai",
48
+ "together",
49
+ ]);
50
+ });
51
+ });
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Codec for Vellum-managed model routing strings.
3
+ *
4
+ * A single `vellum` provider connection is provider-agnostic: unlike the
5
+ * per-provider `*-managed` connections it does not carry the upstream provider
6
+ * on its DB row. The upstream provider therefore has to travel *with* the
7
+ * model. Where a routing site has the provider as a sibling field it uses that
8
+ * directly; where only a single model string is available (telemetry headers
9
+ * like `X-Vellum-Resolved-Model`, persisted model overrides, display), the
10
+ * provider is encoded as a `<provider>/<model>` prefix, e.g.
11
+ * `fireworks/accounts/fireworks/models/minimax-m3`.
12
+ *
13
+ * This module is the single source of truth for that encoding. It is a pure
14
+ * codec — no I/O, no wiring — so it can be adopted incrementally.
15
+ */
16
+
17
+ import { PLATFORM_PROVIDER_META } from "./platform-proxy/constants.js";
18
+
19
+ /**
20
+ * Provider ids that can front a Vellum-managed (platform-proxied) route.
21
+ * Only these are valid prefixes for a routing string; everything else
22
+ * (openrouter, ollama, openai-compatible, or a raw native model id) is not a
23
+ * Vellum-routed string and `parseVellumModel` returns null for it.
24
+ */
25
+ export const MANAGED_ROUTABLE_PROVIDERS: ReadonlySet<string> = new Set(
26
+ Object.values(PLATFORM_PROVIDER_META)
27
+ .filter((m) => m.managed)
28
+ .map((m) => m.name),
29
+ );
30
+
31
+ export interface VellumModelRoute {
32
+ /** Upstream provider id, e.g. "fireworks". Always a managed-routable id. */
33
+ provider: string;
34
+ /** Native upstream model id, slashes intact, e.g. "accounts/fireworks/models/minimax-m3". */
35
+ model: string;
36
+ }
37
+
38
+ /**
39
+ * Encode a provider + native model id into a Vellum routing string.
40
+ * Throws on a non-routable provider — that is a caller bug, not user input.
41
+ */
42
+ export function formatVellumModel(provider: string, model: string): string {
43
+ if (!MANAGED_ROUTABLE_PROVIDERS.has(provider)) {
44
+ throw new Error(
45
+ `formatVellumModel: "${provider}" is not a Vellum-managed provider ` +
46
+ `(expected one of ${[...MANAGED_ROUTABLE_PROVIDERS].join(", ")})`,
47
+ );
48
+ }
49
+ if (!model) {
50
+ throw new Error("formatVellumModel: model must be non-empty");
51
+ }
52
+ return `${provider}/${model}`;
53
+ }
54
+
55
+ /**
56
+ * Decode a Vellum routing string back into provider + native model id.
57
+ *
58
+ * Splits on the FIRST slash only so native ids that themselves contain
59
+ * slashes (Fireworks `accounts/fireworks/models/...`) round-trip losslessly.
60
+ * Returns null when the string is not a Vellum-routed model — no slash, empty
61
+ * model, or a prefix that is not a managed-routable provider.
62
+ *
63
+ * Note: `anthropic/…` is also OpenRouter's native id shape, so this codec
64
+ * must only be applied in a Vellum-connection context. OpenRouter is
65
+ * `managed:false` and never routes through a vellum connection, so the
66
+ * collision is unreachable in practice; the guard here is belt-and-suspenders.
67
+ */
68
+ export function parseVellumModel(
69
+ routingString: string,
70
+ ): VellumModelRoute | null {
71
+ const slash = routingString.indexOf("/");
72
+ if (slash <= 0) {
73
+ return null;
74
+ }
75
+ const provider = routingString.slice(0, slash);
76
+ const model = routingString.slice(slash + 1);
77
+ if (!model) {
78
+ return null;
79
+ }
80
+ if (!MANAGED_ROUTABLE_PROVIDERS.has(provider)) {
81
+ return null;
82
+ }
83
+ return { provider, model };
84
+ }