@motebit/sdk 0.6.11 → 0.8.0

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.
Files changed (74) hide show
  1. package/README.md +15 -110
  2. package/dist/__tests__/appearance-config.test.d.ts +2 -0
  3. package/dist/__tests__/appearance-config.test.d.ts.map +1 -0
  4. package/dist/__tests__/appearance-config.test.js +104 -0
  5. package/dist/__tests__/appearance-config.test.js.map +1 -0
  6. package/dist/__tests__/branded-ids.test.d.ts +2 -0
  7. package/dist/__tests__/branded-ids.test.d.ts.map +1 -0
  8. package/dist/__tests__/branded-ids.test.js +70 -0
  9. package/dist/__tests__/branded-ids.test.js.map +1 -0
  10. package/dist/__tests__/index.test.d.ts +2 -0
  11. package/dist/__tests__/index.test.d.ts.map +1 -0
  12. package/dist/__tests__/index.test.js +194 -0
  13. package/dist/__tests__/index.test.js.map +1 -0
  14. package/dist/__tests__/provider-mode.test.d.ts +2 -0
  15. package/dist/__tests__/provider-mode.test.d.ts.map +1 -0
  16. package/dist/__tests__/provider-mode.test.js +180 -0
  17. package/dist/__tests__/provider-mode.test.js.map +1 -0
  18. package/dist/__tests__/provider-resolver.test.d.ts +2 -0
  19. package/dist/__tests__/provider-resolver.test.d.ts.map +1 -0
  20. package/dist/__tests__/provider-resolver.test.js +353 -0
  21. package/dist/__tests__/provider-resolver.test.js.map +1 -0
  22. package/dist/__tests__/voice-config.test.d.ts +2 -0
  23. package/dist/__tests__/voice-config.test.d.ts.map +1 -0
  24. package/dist/__tests__/voice-config.test.js +98 -0
  25. package/dist/__tests__/voice-config.test.js.map +1 -0
  26. package/dist/appearance-config.d.ts +55 -0
  27. package/dist/appearance-config.d.ts.map +1 -0
  28. package/dist/appearance-config.js +79 -0
  29. package/dist/appearance-config.js.map +1 -0
  30. package/dist/approval-presets.d.ts +16 -0
  31. package/dist/approval-presets.d.ts.map +1 -0
  32. package/dist/approval-presets.js +30 -0
  33. package/dist/approval-presets.js.map +1 -0
  34. package/dist/color-presets.d.ts +14 -0
  35. package/dist/color-presets.d.ts.map +1 -0
  36. package/dist/color-presets.js +17 -0
  37. package/dist/color-presets.js.map +1 -0
  38. package/dist/credential-types-doc.d.ts +73 -0
  39. package/dist/credential-types-doc.d.ts.map +1 -0
  40. package/dist/credential-types-doc.js +2 -0
  41. package/dist/credential-types-doc.js.map +1 -0
  42. package/dist/governance-config.d.ts +19 -0
  43. package/dist/governance-config.d.ts.map +1 -0
  44. package/dist/governance-config.js +15 -0
  45. package/dist/governance-config.js.map +1 -0
  46. package/dist/index.d.ts +97 -1045
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +12 -346
  49. package/dist/index.js.map +1 -1
  50. package/dist/models.d.ts +56 -0
  51. package/dist/models.d.ts.map +1 -0
  52. package/dist/models.js +85 -0
  53. package/dist/models.js.map +1 -0
  54. package/dist/provider-mode.d.ts +109 -0
  55. package/dist/provider-mode.d.ts.map +1 -0
  56. package/dist/provider-mode.js +179 -0
  57. package/dist/provider-mode.js.map +1 -0
  58. package/dist/provider-resolver.d.ts +179 -0
  59. package/dist/provider-resolver.d.ts.map +1 -0
  60. package/dist/provider-resolver.js +224 -0
  61. package/dist/provider-resolver.js.map +1 -0
  62. package/dist/risk-labels.d.ts +22 -0
  63. package/dist/risk-labels.d.ts.map +1 -0
  64. package/dist/risk-labels.js +28 -0
  65. package/dist/risk-labels.js.map +1 -0
  66. package/dist/surface-options.d.ts +34 -0
  67. package/dist/surface-options.d.ts.map +1 -0
  68. package/dist/surface-options.js +36 -0
  69. package/dist/surface-options.js.map +1 -0
  70. package/dist/voice-config.d.ts +52 -0
  71. package/dist/voice-config.d.ts.map +1 -0
  72. package/dist/voice-config.js +61 -0
  73. package/dist/voice-config.js.map +1 -0
  74. package/package.json +9 -6
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Top-level provider mode — the user's intent, not the concrete vendor.
3
+ *
4
+ * - `on-device`: the user wants inference to run locally (privacy, offline, latency).
5
+ * - `motebit-cloud`: the user wants the default product experience (subscription, auto-routing).
6
+ * - `byok`: the user brings their own API key to a named vendor.
7
+ */
8
+ export type ProviderMode = "on-device" | "motebit-cloud" | "byok";
9
+ /**
10
+ * On-device backend kinds. Not every backend is available on every platform:
11
+ *
12
+ * - `apple-fm`: Apple Foundation Models (iOS/macOS 26+ only).
13
+ * - `mlx`: MLX runtime (Apple Silicon, iOS 16+ / macOS).
14
+ * - `webllm`: MLC WebLLM in-browser (web surface + WebGPU only).
15
+ * - `local-server`: auto-detected local OpenAI-compatible server
16
+ * (Ollama, LM Studio, llama.cpp, Jan, vLLM, …). Vendor-agnostic.
17
+ */
18
+ export type OnDeviceBackend = "apple-fm" | "mlx" | "webllm" | "local-server";
19
+ /** BYOK vendors — the only ones where the user holds the API key directly. */
20
+ export type ByokVendor = "anthropic" | "openai" | "google";
21
+ /** On-device mode config. */
22
+ export interface OnDeviceProviderConfig {
23
+ mode: "on-device";
24
+ backend: OnDeviceBackend;
25
+ /** Model identifier. Meaning depends on backend (MLX name, WebLLM id, server tag, …). */
26
+ model?: string;
27
+ /** For `local-server`: endpoint URL (e.g., http://localhost:11434). Auto-detected otherwise. */
28
+ endpoint?: string;
29
+ /** Optional temperature override. */
30
+ temperature?: number;
31
+ /** Optional max_tokens override. */
32
+ maxTokens?: number;
33
+ }
34
+ /** Motebit Cloud mode config — the subscription-backed product. */
35
+ export interface MotebitCloudProviderConfig {
36
+ mode: "motebit-cloud";
37
+ /** Optional preferred model. When omitted, the relay picks. */
38
+ model?: string;
39
+ /** Signed proxy token — included as x-proxy-token for authenticated requests. */
40
+ proxyToken?: string;
41
+ /** Override proxy base URL (dev/staging). */
42
+ baseUrl?: string;
43
+ temperature?: number;
44
+ maxTokens?: number;
45
+ }
46
+ /** BYOK mode config — user supplies the API key. */
47
+ export interface ByokProviderConfig {
48
+ mode: "byok";
49
+ vendor: ByokVendor;
50
+ apiKey: string;
51
+ model?: string;
52
+ /**
53
+ * Optional custom base URL. Used e.g. for Google via the OpenAI-compatible
54
+ * endpoint (`https://generativelanguage.googleapis.com/v1beta/openai`).
55
+ */
56
+ baseUrl?: string;
57
+ temperature?: number;
58
+ maxTokens?: number;
59
+ }
60
+ /** Union of all three modes. Surfaces persist this shape. */
61
+ export type UnifiedProviderConfig = OnDeviceProviderConfig | MotebitCloudProviderConfig | ByokProviderConfig;
62
+ /**
63
+ * Heuristic: is this URL pointing at a local inference server?
64
+ * Shared across all surfaces so the migration behaves identically everywhere.
65
+ */
66
+ export declare function isLocalServerUrl(url: string | undefined | null): boolean;
67
+ /**
68
+ * Legacy provider config shape — a superset of every surface's historical fields.
69
+ * Used only as the input to `migrateLegacyProvider`.
70
+ */
71
+ export interface LegacyProviderConfig {
72
+ type?: string;
73
+ provider?: string;
74
+ apiKey?: string;
75
+ api_key?: string;
76
+ model?: string;
77
+ baseUrl?: string;
78
+ base_url?: string;
79
+ proxyToken?: string;
80
+ proxy_token?: string;
81
+ maxTokens?: number;
82
+ max_tokens?: number;
83
+ temperature?: number;
84
+ localBackend?: string;
85
+ ollamaEndpoint?: string;
86
+ default_provider?: string;
87
+ default_model?: string;
88
+ mode?: string;
89
+ backend?: string;
90
+ vendor?: string;
91
+ endpoint?: string;
92
+ }
93
+ /**
94
+ * Migrate any legacy provider config shape to `UnifiedProviderConfig`.
95
+ *
96
+ * Rules:
97
+ * - `hybrid` and `proxy` map to `motebit-cloud` (the product).
98
+ * - `ollama` with a localhost URL maps to `on-device/local-server`.
99
+ * - `ollama` with a remote URL maps to `on-device/local-server` with that endpoint preserved.
100
+ * - `anthropic` / `openai` / `google` map to `byok` with that vendor.
101
+ * - Mobile `local` with `localBackend` maps to `on-device` with that backend.
102
+ * - If input is already a `UnifiedProviderConfig` (has `mode`), it passes through.
103
+ *
104
+ * Returns `null` only if the input is entirely unrecognizable.
105
+ */
106
+ export declare function migrateLegacyProvider(legacy: LegacyProviderConfig | null | undefined): UnifiedProviderConfig | null;
107
+ /** Sensible default when no config has ever been persisted. */
108
+ export declare function defaultProviderConfig(): MotebitCloudProviderConfig;
109
+ //# sourceMappingURL=provider-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-mode.d.ts","sourceRoot":"","sources":["../src/provider-mode.ts"],"names":[],"mappings":"AAYA;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,eAAe,GAAG,MAAM,CAAC;AAElE;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,cAAc,CAAC;AAE7E,8EAA8E;AAC9E,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3D,6BAA6B;AAC7B,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,eAAe,CAAC;IACzB,yFAAyF;IACzF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gGAAgG;IAChG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,mEAAmE;AACnE,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,eAAe,CAAC;IACtB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,6DAA6D;AAC7D,MAAM,MAAM,qBAAqB,GAC7B,sBAAsB,GACtB,0BAA0B,GAC1B,kBAAkB,CAAC;AAuBvB;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAkBxE;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IAEnC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,GAC9C,qBAAqB,GAAG,IAAI,CAmH9B;AAID,+DAA+D;AAC/D,wBAAgB,qBAAqB,IAAI,0BAA0B,CAElE"}
@@ -0,0 +1,179 @@
1
+ // === Provider Mode (Three-Mode Architecture) ===
2
+ //
3
+ // User-intent-based provider config — matches the pattern of settlement rails:
4
+ // user picks the capability class, the system resolves the concrete vendor.
5
+ //
6
+ // Flat unions like "ollama" | "anthropic" | "openai" | "hybrid" mix implementation
7
+ // details with user intent. "Hybrid" is an implementation detail, not a user choice.
8
+ // "Ollama" is a vendor name, not a capability class.
9
+ //
10
+ // All surfaces (web, mobile, desktop, cli) persist and exchange this shape.
11
+ // Platform-specific sub-options live inside each mode's discriminated variant.
12
+ // === Migration ===
13
+ //
14
+ // Legacy shapes, in order of historical appearance:
15
+ //
16
+ // Web (apps/web/src/storage.ts):
17
+ // { type: "anthropic" | "openai" | "ollama" | "webllm" | "proxy",
18
+ // apiKey?, model, baseUrl?, proxyToken?, maxTokens?, temperature? }
19
+ //
20
+ // Mobile (apps/mobile/src/mobile-app.ts):
21
+ // { provider: "ollama" | "anthropic" | "openai" | "hybrid" | "proxy" | "local",
22
+ // localBackend?: "apple-fm" | "mlx",
23
+ // model?, apiKey?, ollamaEndpoint?, maxTokens? }
24
+ //
25
+ // Desktop (apps/desktop/src/index.ts):
26
+ // { provider: "anthropic" | "ollama" | "openai" | "proxy" | "hybrid",
27
+ // model?, apiKey?, maxTokens? }
28
+ //
29
+ // CLI (apps/cli/src/config.ts):
30
+ // { default_provider?: "anthropic" | "openai" | "ollama",
31
+ // default_model?, api_key? (in keyring) }
32
+ /**
33
+ * Heuristic: is this URL pointing at a local inference server?
34
+ * Shared across all surfaces so the migration behaves identically everywhere.
35
+ */
36
+ export function isLocalServerUrl(url) {
37
+ if (!url)
38
+ return false;
39
+ try {
40
+ const u = new URL(url);
41
+ const host = u.hostname.toLowerCase();
42
+ return (host === "localhost" ||
43
+ host === "127.0.0.1" ||
44
+ host === "::1" ||
45
+ host === "0.0.0.0" ||
46
+ host.endsWith(".local") ||
47
+ /^10\./.test(host) ||
48
+ /^192\.168\./.test(host) ||
49
+ /^172\.(1[6-9]|2\d|3[01])\./.test(host));
50
+ }
51
+ catch {
52
+ return false;
53
+ }
54
+ }
55
+ /**
56
+ * Migrate any legacy provider config shape to `UnifiedProviderConfig`.
57
+ *
58
+ * Rules:
59
+ * - `hybrid` and `proxy` map to `motebit-cloud` (the product).
60
+ * - `ollama` with a localhost URL maps to `on-device/local-server`.
61
+ * - `ollama` with a remote URL maps to `on-device/local-server` with that endpoint preserved.
62
+ * - `anthropic` / `openai` / `google` map to `byok` with that vendor.
63
+ * - Mobile `local` with `localBackend` maps to `on-device` with that backend.
64
+ * - If input is already a `UnifiedProviderConfig` (has `mode`), it passes through.
65
+ *
66
+ * Returns `null` only if the input is entirely unrecognizable.
67
+ */
68
+ export function migrateLegacyProvider(legacy) {
69
+ if (!legacy)
70
+ return null;
71
+ // Already-new shape — passthrough with light validation.
72
+ if (legacy.mode === "on-device" || legacy.mode === "motebit-cloud" || legacy.mode === "byok") {
73
+ return legacy;
74
+ }
75
+ const apiKey = legacy.apiKey ?? legacy.api_key;
76
+ const baseUrl = legacy.baseUrl ?? legacy.base_url;
77
+ const proxyToken = legacy.proxyToken ?? legacy.proxy_token;
78
+ const maxTokens = legacy.maxTokens ?? legacy.max_tokens;
79
+ const temperature = legacy.temperature;
80
+ const model = legacy.model ?? legacy.default_model;
81
+ // Normalize the discriminator across shapes.
82
+ const kind = legacy.type ?? legacy.provider ?? legacy.default_provider;
83
+ if (!kind)
84
+ return null;
85
+ switch (kind) {
86
+ case "proxy":
87
+ case "hybrid":
88
+ case "motebit-cloud":
89
+ return {
90
+ mode: "motebit-cloud",
91
+ model,
92
+ proxyToken,
93
+ baseUrl,
94
+ maxTokens,
95
+ temperature,
96
+ };
97
+ case "anthropic":
98
+ return {
99
+ mode: "byok",
100
+ vendor: "anthropic",
101
+ apiKey: apiKey ?? "",
102
+ model,
103
+ baseUrl,
104
+ maxTokens,
105
+ temperature,
106
+ };
107
+ case "openai":
108
+ return {
109
+ mode: "byok",
110
+ vendor: "openai",
111
+ apiKey: apiKey ?? "",
112
+ model,
113
+ baseUrl,
114
+ maxTokens,
115
+ temperature,
116
+ };
117
+ case "google":
118
+ return {
119
+ mode: "byok",
120
+ vendor: "google",
121
+ apiKey: apiKey ?? "",
122
+ model,
123
+ baseUrl,
124
+ maxTokens,
125
+ temperature,
126
+ };
127
+ case "ollama": {
128
+ // Ollama is always a local server — endpoint may or may not be localhost.
129
+ const endpoint = baseUrl ?? legacy.ollamaEndpoint ?? legacy.endpoint;
130
+ return {
131
+ mode: "on-device",
132
+ backend: "local-server",
133
+ model,
134
+ endpoint,
135
+ maxTokens,
136
+ temperature,
137
+ };
138
+ }
139
+ case "webllm":
140
+ return {
141
+ mode: "on-device",
142
+ backend: "webllm",
143
+ model,
144
+ maxTokens,
145
+ temperature,
146
+ };
147
+ case "local": {
148
+ // Mobile legacy: `local` with `localBackend` sub-option.
149
+ const backend = (() => {
150
+ switch (legacy.localBackend) {
151
+ case "apple-fm":
152
+ return "apple-fm";
153
+ case "mlx":
154
+ return "mlx";
155
+ case "local-server":
156
+ return "local-server";
157
+ default:
158
+ return "mlx";
159
+ }
160
+ })();
161
+ return {
162
+ mode: "on-device",
163
+ backend,
164
+ model,
165
+ endpoint: legacy.ollamaEndpoint ?? legacy.endpoint,
166
+ maxTokens,
167
+ temperature,
168
+ };
169
+ }
170
+ default:
171
+ return null;
172
+ }
173
+ }
174
+ // === Defaults ===
175
+ /** Sensible default when no config has ever been persisted. */
176
+ export function defaultProviderConfig() {
177
+ return { mode: "motebit-cloud" };
178
+ }
179
+ //# sourceMappingURL=provider-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-mode.js","sourceRoot":"","sources":["../src/provider-mode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,179 @@
1
+ import type { UnifiedProviderConfig, ByokVendor, OnDeviceBackend } from "./provider-mode.js";
2
+ /**
3
+ * Google's OpenAI-compatible chat completions endpoint. Used when the user
4
+ * picks Google as a BYOK vendor — Google is dispatched as OpenAI-compat
5
+ * because every cloud client (web, mobile, desktop, cli) already understands
6
+ * the OpenAI wire protocol. Single source of truth.
7
+ */
8
+ export declare const GOOGLE_OPENAI_COMPAT_URL = "https://generativelanguage.googleapis.com/v1beta/openai";
9
+ /** Canonical Anthropic API base URL. */
10
+ export declare const ANTHROPIC_CANONICAL_URL = "https://api.anthropic.com";
11
+ /** Canonical OpenAI API base URL. */
12
+ export declare const OPENAI_CANONICAL_URL = "https://api.openai.com/v1";
13
+ /** Default Motebit Cloud relay URL. Surfaces may override via env. */
14
+ export declare const DEFAULT_MOTEBIT_CLOUD_URL = "https://api.motebit.com";
15
+ /** Default WebLLM model when none specified — small enough to fit on most devices. */
16
+ export declare const DEFAULT_WEBLLM_MODEL = "Llama-3.2-3B-Instruct-q4f16_1-MLC";
17
+ /**
18
+ * Normalize a local-inference server URL so that it points at the
19
+ * OpenAI-compatible chat completions base path. Auto-appends `/v1` if
20
+ * the URL doesn't already contain it. Idempotent.
21
+ *
22
+ * Every supported local server (Ollama via its OpenAI shim, LM Studio,
23
+ * llama.cpp, Jan, vLLM, text-generation-webui) exposes
24
+ * `{base}/v1/chat/completions`. Users typically type just the host
25
+ * (`http://localhost:11434`) — this helper completes the path so the
26
+ * client can call `{normalized}/chat/completions` directly.
27
+ *
28
+ * Examples:
29
+ * "http://localhost:11434" → "http://localhost:11434/v1"
30
+ * "http://localhost:11434/v1" → "http://localhost:11434/v1"
31
+ * "http://localhost:1234/" → "http://localhost:1234/v1"
32
+ * "http://192.168.1.42:11434" → "http://192.168.1.42:11434/v1"
33
+ * "/api/ollama" → "/api/ollama/v1" (dev proxy path)
34
+ */
35
+ export declare function normalizeLocalServerEndpoint(url: string): string;
36
+ /** Default chat model for a BYOK vendor. */
37
+ export declare function defaultModelForVendor(vendor: ByokVendor): string;
38
+ /**
39
+ * Canonical (vendor-published) base URL for a BYOK vendor. Surfaces that
40
+ * need to substitute a CORS proxy or dev-mode path receive this canonical
41
+ * URL via the resolver and may rewrite it.
42
+ */
43
+ export declare function canonicalVendorBaseUrl(vendor: ByokVendor): string;
44
+ /**
45
+ * Discriminated union describing what concrete provider class the surface
46
+ * should instantiate, with all decision logic already resolved. The surface's
47
+ * job is reduced to a transport switch + class construction.
48
+ */
49
+ export type ProviderSpec = CloudProviderSpec | WebLLMProviderSpec | AppleFoundationModelsSpec | MlxProviderSpec;
50
+ /**
51
+ * Cloud HTTP provider — used for Anthropic, OpenAI, Google (via OpenAI-compat),
52
+ * Motebit Cloud (anthropic protocol via relay), and OpenAI-compat local
53
+ * servers (LM Studio, llama.cpp, etc.).
54
+ *
55
+ * The `wireProtocol` discriminates between Anthropic's messages API and
56
+ * OpenAI's chat completions API. The surface uses this to pick the right
57
+ * concrete class (`AnthropicProvider` or `OpenAIProvider`) to instantiate.
58
+ */
59
+ export interface CloudProviderSpec {
60
+ kind: "cloud";
61
+ /** Wire protocol family this client speaks. */
62
+ wireProtocol: "anthropic" | "openai";
63
+ /** API key to use. Empty string for motebit-cloud (server injects). */
64
+ apiKey: string;
65
+ model: string;
66
+ /** Already-resolved base URL — env.cloudBaseUrl has been applied. */
67
+ baseUrl: string;
68
+ maxTokens?: number;
69
+ temperature?: number;
70
+ /** Extra HTTP headers (e.g., x-proxy-token for motebit-cloud). */
71
+ extraHeaders?: Record<string, string>;
72
+ }
73
+ /** Browser-only WebLLM provider — runs in-browser via WebGPU. */
74
+ export interface WebLLMProviderSpec {
75
+ kind: "webllm";
76
+ model: string;
77
+ maxTokens?: number;
78
+ temperature?: number;
79
+ }
80
+ /** Apple Foundation Models — iOS 26+ / macOS 26+ only. */
81
+ export interface AppleFoundationModelsSpec {
82
+ kind: "apple-fm";
83
+ model?: string;
84
+ maxTokens?: number;
85
+ }
86
+ /** MLX runtime — Apple Silicon only. */
87
+ export interface MlxProviderSpec {
88
+ kind: "mlx";
89
+ model?: string;
90
+ maxTokens?: number;
91
+ }
92
+ /**
93
+ * Per-surface environment that captures the only things the resolver can't
94
+ * decide on its own: platform-specific URL routing, which on-device backends
95
+ * are physically supported, and motebit-cloud session state.
96
+ *
97
+ * Each surface constructs one of these once (or per call if the session
98
+ * state changes) and passes it to `resolveProviderSpec`. The interface is
99
+ * intentionally narrow — anything that can be computed from a
100
+ * `UnifiedProviderConfig` alone stays inside the resolver.
101
+ */
102
+ export interface ResolverEnv {
103
+ /**
104
+ * Resolve the actual base URL for a cloud provider given its canonical
105
+ * vendor URL. Most surfaces return `canonical` unchanged. Browser surfaces
106
+ * substitute a CORS proxy for vendors that block direct browser calls.
107
+ * Tauri dev mode substitutes a Vite proxy path.
108
+ *
109
+ * The function form (rather than a static map) lets surfaces compute the
110
+ * substitution lazily based on runtime state (e.g., `isTauri`).
111
+ */
112
+ cloudBaseUrl(wireProtocol: "anthropic" | "openai", canonical: string): string;
113
+ /**
114
+ * Default URL for the on-device local-server backend when the user
115
+ * hasn't supplied an endpoint. The resolver auto-appends `/v1` via
116
+ * `normalizeLocalServerEndpoint`, so this can be a bare host. Use
117
+ * `localServerBaseUrl` to translate the user-supplied URL into a
118
+ * surface-specific transport URL (e.g., a Vite dev proxy path).
119
+ */
120
+ defaultLocalServerUrl: string;
121
+ /**
122
+ * Optional translator from a logical local-server URL into the actual URL
123
+ * the provider should call. Most surfaces return the input unchanged.
124
+ * Desktop dev mode substitutes the Vite proxy path `/api/ollama` for any
125
+ * Ollama-shaped logical URL — but the dispatch decision (Ollama-native vs
126
+ * OpenAI-compat) is made BEFORE this substitution, on the logical URL.
127
+ *
128
+ * This separation lets surfaces use proxy/rewrite paths without losing
129
+ * the resolver's ability to dispatch on the user's intent.
130
+ */
131
+ localServerBaseUrl?(logical: string): string;
132
+ /**
133
+ * Which on-device backends this surface can physically run.
134
+ * - web: webllm, local-server
135
+ * - mobile: apple-fm, mlx, local-server
136
+ * - desktop: local-server (today; could grow)
137
+ * - cli: local-server
138
+ */
139
+ supportedBackends: ReadonlySet<OnDeviceBackend>;
140
+ /**
141
+ * Base URL for motebit-cloud requests. Each surface resolves this from
142
+ * its own session state / env (proxy session, VITE_PROXY_URL, etc.).
143
+ * Falls back to `DEFAULT_MOTEBIT_CLOUD_URL` if absent.
144
+ */
145
+ motebitCloudBaseUrl?: string;
146
+ /**
147
+ * Extra HTTP headers to attach to motebit-cloud requests. Typically
148
+ * `{ "x-proxy-token": "..." }` from the surface's proxy session state.
149
+ */
150
+ motebitCloudHeaders?: Record<string, string>;
151
+ /**
152
+ * Default model for motebit-cloud when the config doesn't specify.
153
+ * Most surfaces leave this undefined (resolver falls back to
154
+ * `DEFAULT_PROXY_MODEL`); the relay session may override based on tier.
155
+ */
156
+ motebitCloudDefaultModel?: string;
157
+ }
158
+ /**
159
+ * Thrown when the user picks an on-device backend that the current surface
160
+ * doesn't physically support (e.g., apple-fm on web). Surfaces should
161
+ * present a graceful error rather than letting it propagate.
162
+ */
163
+ export declare class UnsupportedBackendError extends Error {
164
+ backend: OnDeviceBackend;
165
+ constructor(backend: OnDeviceBackend);
166
+ }
167
+ /**
168
+ * Resolve a `UnifiedProviderConfig` (the user's choice) against a surface's
169
+ * `ResolverEnv` (its physical capabilities) to produce a normalized
170
+ * `ProviderSpec` (what the surface should instantiate).
171
+ *
172
+ * Pure function. No I/O. No side effects. Tested once, used everywhere.
173
+ *
174
+ * @throws {UnsupportedBackendError} if the chosen on-device backend isn't
175
+ * in `env.supportedBackends`. Surfaces should catch and present a
176
+ * user-facing message.
177
+ */
178
+ export declare function resolveProviderSpec(config: UnifiedProviderConfig, env: ResolverEnv): ProviderSpec;
179
+ //# sourceMappingURL=provider-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-resolver.d.ts","sourceRoot":"","sources":["../src/provider-resolver.ts"],"names":[],"mappings":"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"}