promptimizer 0.1.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.
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # promptimizer
2
+
3
+ OpenAI-compatible TypeScript SDK for [Promptimizer](https://hackathon-omega-liart.vercel.app). Route each request to the cheapest adequate model, cache repeated prefixes, and keep a quality gate so savings do not silently degrade hard answers.
4
+
5
+ ```bash
6
+ npm install promptimizer
7
+ ```
8
+
9
+ ## Account + BYOK
10
+
11
+ Create a `pmz_live_` key at `/account`, connect a provider in the console or CLI, then:
12
+
13
+ ```ts
14
+ import { Promptimizer } from "promptimizer";
15
+
16
+ const client = new Promptimizer({
17
+ apiKey: process.env.PROMPTIMIZER_API_KEY,
18
+ });
19
+
20
+ const completion = await client.chat.completions.create({
21
+ messages: [{ role: "user", content: "What is 17 * 24?" }],
22
+ });
23
+
24
+ console.log(completion.choices[0].message.content);
25
+ console.log(completion.promptimizer);
26
+ console.log(completion.usage.cost);
27
+ ```
28
+
29
+ The default gateway is the hosted app. Override with `gatewayURL` or `PROMPTIMIZER_URL`.
30
+
31
+ Connect a provider from code if it is not already saved on the account:
32
+
33
+ ```ts
34
+ await client.connect({
35
+ provider: "baseten",
36
+ apiKey: process.env.BASETEN_API_KEY,
37
+ });
38
+ ```
39
+
40
+ ## Drop-in with the official OpenAI SDK
41
+
42
+ ```ts
43
+ import OpenAI from "openai";
44
+
45
+ const openai = new OpenAI({
46
+ apiKey: process.env.PROMPTIMIZER_API_KEY,
47
+ baseURL: "https://hackathon-omega-liart.vercel.app/api/v1",
48
+ });
49
+
50
+ await openai.chat.completions.create({
51
+ model: "auto",
52
+ messages: [{ role: "user", content: "Explain REST in two sentences." }],
53
+ });
54
+ ```
55
+
56
+ ## Local classification (no network)
57
+
58
+ ```ts
59
+ import { classifyText } from "promptimizer";
60
+
61
+ classifyText("Design a rate limiter for 1 million QPS");
62
+ // recommended_tier: "frontier"
63
+ ```
@@ -0,0 +1,4 @@
1
+ import type { ChatMessage, Classification, Tier } from "./types";
2
+ export declare function classifyMessages(messages: ChatMessage[]): Classification;
3
+ export declare function classifyText(text: string): Classification;
4
+ export declare function difficultyTier(complexity: number): Tier;
@@ -0,0 +1,54 @@
1
+ import type { ChatCompletion, ChatCompletionRequest, ConnectOptions, PromptimizerOptions, SavingsSummary, Session } from "./types";
2
+ export declare class PromptimizerError extends Error {
3
+ readonly status: number;
4
+ readonly body?: unknown | undefined;
5
+ constructor(message: string, status: number, body?: unknown | undefined);
6
+ }
7
+ export declare const DEFAULT_GATEWAY: string;
8
+ export declare class Promptimizer {
9
+ readonly gatewayURL: string;
10
+ sessionId?: string;
11
+ apiKey?: string;
12
+ private readonly fetcher;
13
+ constructor(options?: PromptimizerOptions);
14
+ static connect(options: ConnectOptions & {
15
+ gatewayURL?: string;
16
+ }): Promise<{
17
+ client: Promptimizer;
18
+ session: Session;
19
+ }>;
20
+ connect(options: ConnectOptions): Promise<Session>;
21
+ providers(): Promise<{
22
+ object: string;
23
+ data: Array<{
24
+ id: string;
25
+ label: string;
26
+ base_url: string;
27
+ env: string;
28
+ }>;
29
+ }>;
30
+ savings(): Promise<SavingsSummary>;
31
+ session(): Promise<Session>;
32
+ models(): Promise<{
33
+ object: string;
34
+ data: Session["models"];
35
+ baseline_model: string | null;
36
+ }>;
37
+ updateFleet(body: {
38
+ overrides?: Record<string, string>;
39
+ selected?: Record<string, boolean>;
40
+ baseline_model?: string;
41
+ }): Promise<Session>;
42
+ classify(input: {
43
+ messages?: ChatCompletionRequest["messages"];
44
+ prompt?: string;
45
+ }): Promise<unknown>;
46
+ benchmark(compareAlwaysFrontier?: boolean): Promise<unknown>;
47
+ readonly chat: {
48
+ completions: {
49
+ create: (request: ChatCompletionRequest) => Promise<ChatCompletion>;
50
+ };
51
+ };
52
+ createChatCompletion(request: ChatCompletionRequest): Promise<ChatCompletion>;
53
+ private request;
54
+ }
package/dist/index.cjs ADDED
@@ -0,0 +1,315 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_GATEWAY: () => DEFAULT_GATEWAY,
24
+ PROVIDERS: () => PROVIDERS,
25
+ Promptimizer: () => Promptimizer,
26
+ PromptimizerError: () => PromptimizerError,
27
+ classifyMessages: () => classifyMessages,
28
+ classifyText: () => classifyText,
29
+ difficultyTier: () => difficultyTier,
30
+ findProvider: () => findProvider,
31
+ publicCatalog: () => publicCatalog,
32
+ resolveBaseURL: () => resolveBaseURL
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+
36
+ // src/client.ts
37
+ var PromptimizerError = class extends Error {
38
+ constructor(message, status, body) {
39
+ super(message);
40
+ this.status = status;
41
+ this.body = body;
42
+ this.name = "PromptimizerError";
43
+ }
44
+ };
45
+ var DEFAULT_GATEWAY = (process.env.PROMPTIMIZER_URL || "https://hackathon-omega-liart.vercel.app/api").replace(/\/$/, "");
46
+ var Promptimizer = class _Promptimizer {
47
+ gatewayURL;
48
+ sessionId;
49
+ apiKey;
50
+ fetcher;
51
+ constructor(options = {}) {
52
+ this.gatewayURL = (options.gatewayURL ?? options.baseURL ?? DEFAULT_GATEWAY).replace(/\/$/, "");
53
+ this.sessionId = options.sessionId;
54
+ this.apiKey = options.apiKey;
55
+ this.fetcher = options.fetch ?? fetch;
56
+ }
57
+ static async connect(options) {
58
+ const client = new _Promptimizer({
59
+ gatewayURL: options.gatewayURL,
60
+ apiKey: options.accountKey
61
+ });
62
+ const session = await client.connect(options);
63
+ return { client, session };
64
+ }
65
+ async connect(options) {
66
+ const session = await this.request("/v1/providers/connect", {
67
+ method: "POST",
68
+ body: JSON.stringify({
69
+ mode: options.mode ?? "byok",
70
+ label: options.label,
71
+ provider: options.provider,
72
+ base_url: options.baseURL,
73
+ api_key: options.apiKey
74
+ })
75
+ });
76
+ this.sessionId = session.session_id;
77
+ return session;
78
+ }
79
+ async providers() {
80
+ return this.request(
81
+ "/v1/providers"
82
+ );
83
+ }
84
+ async savings() {
85
+ return this.request("/v1/savings");
86
+ }
87
+ async session() {
88
+ return this.request("/v1/session");
89
+ }
90
+ async models() {
91
+ return this.request(
92
+ "/v1/models"
93
+ );
94
+ }
95
+ async updateFleet(body) {
96
+ return this.request("/v1/models", { method: "PATCH", body: JSON.stringify(body) });
97
+ }
98
+ async classify(input) {
99
+ return this.request("/v1/classify", { method: "POST", body: JSON.stringify(input) });
100
+ }
101
+ async benchmark(compareAlwaysFrontier = true) {
102
+ return this.request("/v1/benchmark/run", {
103
+ method: "POST",
104
+ body: JSON.stringify({ compare_always_frontier: compareAlwaysFrontier })
105
+ });
106
+ }
107
+ chat = {
108
+ completions: {
109
+ create: (request) => this.createChatCompletion(request)
110
+ }
111
+ };
112
+ async createChatCompletion(request) {
113
+ return this.request("/v1/chat/completions", {
114
+ method: "POST",
115
+ body: JSON.stringify(request)
116
+ });
117
+ }
118
+ async request(path, init = {}) {
119
+ const headers = new Headers(init.headers);
120
+ headers.set("Content-Type", "application/json");
121
+ if (this.apiKey) {
122
+ headers.set("Authorization", `Bearer ${this.apiKey}`);
123
+ } else if (this.sessionId) {
124
+ headers.set("X-Promptimizer-Session", this.sessionId);
125
+ headers.set("Authorization", `Bearer ${this.sessionId}`);
126
+ }
127
+ const response = await this.fetcher(`${this.gatewayURL}${path}`, { ...init, headers });
128
+ const data = await response.json().catch(() => ({}));
129
+ if (!response.ok) {
130
+ const detail = typeof data === "object" && data && "detail" in data ? String(data.detail) : response.statusText;
131
+ throw new PromptimizerError(detail, response.status, data);
132
+ }
133
+ return data;
134
+ }
135
+ };
136
+
137
+ // src/classify.ts
138
+ var HIGH_RISK = /* @__PURE__ */ new Set(["system_design", "safety_sensitive", "code_debug", "reasoning"]);
139
+ function textFrom(messages) {
140
+ return messages.map((m) => {
141
+ if (typeof m.content === "string") return m.content;
142
+ return m.content.map((b) => b.text ?? "").join("\n");
143
+ }).join("\n").trim();
144
+ }
145
+ function classifyMessages(messages) {
146
+ return classifyText(textFrom(messages));
147
+ }
148
+ function classifyText(text) {
149
+ const words = text.split(/\s+/).filter(Boolean).length;
150
+ const lines = text.split("\n").length;
151
+ const features = {
152
+ code_fence: /```/.test(text),
153
+ code_kw: /\b(def |class |function |import |fn |pub |async |SELECT |goroutine|mutex|traceback)\b/i.test(
154
+ text
155
+ ),
156
+ math: /(\$\$|\\frac|prove that|expected value|O\([nN]\)|\d+\s*[\*\^]\s*\d+)/i.test(text),
157
+ design: /\b(design|architect|rate limiter|distributed|consistency|shard|1 million QPS)\b/i.test(
158
+ text
159
+ ),
160
+ reason: /\b(prove|why does|walk through|step by step|derive|contradiction|p-value)\b/i.test(
161
+ text
162
+ ),
163
+ debug: /\b(bug|race|panic|fails on|diagnose|deadlock)\b/i.test(text),
164
+ summarize: /\b(summarize|tl;dr|in two sentences|eli5)\b/i.test(text),
165
+ translate: /\b(translate|traduce)\b/i.test(text),
166
+ creative: /\b(write a (poem|story|song)|haiku)\b/i.test(text),
167
+ safety: /\b(refund|legal|medical|hipaa|lawsuit|diagnosis)\b/i.test(text),
168
+ analysis: /\b(compare|trade-?off|versus|analyse|analyze|evaluate|should we)\b/i.test(text),
169
+ constraints: (text.match(/\b(must|include|constraints?|requirements?)\b/gi) ?? []).length,
170
+ words,
171
+ lines,
172
+ question_marks: (text.match(/\?/g) ?? []).length
173
+ };
174
+ const category = categoryOf(features);
175
+ const complexity = complexityOf(features, category);
176
+ const p_small_quality = pSmallQuality(features, category, complexity);
177
+ const quality_risk = riskOf(category, complexity, p_small_quality);
178
+ const recommended_tier = tierFromP(p_small_quality);
179
+ const signals = [
180
+ features.code_fence,
181
+ features.code_kw,
182
+ features.math,
183
+ features.design,
184
+ features.reason,
185
+ features.debug,
186
+ features.safety
187
+ ].filter(Boolean).length;
188
+ const confidence = category === "factual_recall" && words < 16 ? 0.9 : Math.min(0.95, 0.55 + 0.12 * signals);
189
+ return {
190
+ complexity,
191
+ category,
192
+ confidence: Number(confidence.toFixed(3)),
193
+ recommended_tier,
194
+ quality_risk,
195
+ p_small_quality,
196
+ uncertainty: Number((1 - p_small_quality).toFixed(3)),
197
+ structured_output: Boolean(features.code_fence || features.constraints >= 1),
198
+ context_tokens_est: Math.max(1, Math.round(text.length / 4)),
199
+ rationale: `${category.replaceAll("_", " ")} L${complexity}. P(quality|small)=${p_small_quality}. Route to ${recommended_tier}.`,
200
+ features
201
+ };
202
+ }
203
+ function categoryOf(h) {
204
+ if (h.safety) return "safety_sensitive";
205
+ if (h.design) return "system_design";
206
+ if (h.debug && (h.code_fence || h.code_kw)) return "code_debug";
207
+ if (h.code_fence || h.code_kw) return "code_generation";
208
+ if (h.math && h.reason) return "reasoning";
209
+ if (h.math) return "math";
210
+ if (h.reason) return "reasoning";
211
+ if (h.translate) return "translation";
212
+ if (h.summarize) return "summarization";
213
+ if (h.creative) return "creative";
214
+ if (h.analysis) return "analysis";
215
+ if (h.words < 24 && h.question_marks >= 1) return "factual_recall";
216
+ return h.words > 80 ? "analysis" : "factual_recall";
217
+ }
218
+ function complexityOf(h, category) {
219
+ let score = 1;
220
+ if (h.words > 40) score += 1;
221
+ if (h.words > 120) score += 1;
222
+ if (h.lines > 12 || h.code_fence) score += 1;
223
+ if (h.constraints >= 2) score += 1;
224
+ if (h.design || h.reason) score += 1;
225
+ if (h.debug) score += 1;
226
+ if (["system_design", "reasoning", "safety_sensitive"].includes(category)) score = Math.max(score + 1, 4);
227
+ if (category === "code_generation") score = Math.max(score, 3);
228
+ if (category === "code_debug") score = Math.max(score, 4);
229
+ if (category === "factual_recall" && h.words < 20) score = Math.min(score, 2);
230
+ return Math.max(1, Math.min(5, score));
231
+ }
232
+ function pSmallQuality(h, category, complexity) {
233
+ let p = 0.96;
234
+ if (h.design || category === "system_design") p -= 0.28;
235
+ if (h.safety || category === "safety_sensitive") p -= 0.3;
236
+ if (h.debug || category === "code_debug") p -= 0.22;
237
+ if (h.reason || category === "reasoning") p -= 0.18;
238
+ if (complexity >= 5) p -= 0.22;
239
+ else if (complexity >= 4) p -= 0.14;
240
+ else if (complexity === 3) p -= 0.06;
241
+ if (h.words > 120) p -= 0.07;
242
+ if (h.constraints >= 2) p -= 0.07;
243
+ if (category === "code_generation") p -= 0.05;
244
+ if (category === "factual_recall" && h.words < 24) p = Math.max(p, 0.94);
245
+ return Number(Math.min(0.99, Math.max(0.05, p)).toFixed(3));
246
+ }
247
+ function riskOf(category, complexity, p) {
248
+ if (HIGH_RISK.has(category) || complexity >= 5 || p < 0.72) return "high";
249
+ if (complexity >= 3 || p < 0.9) return "medium";
250
+ return "low";
251
+ }
252
+ function tierFromP(p) {
253
+ if (p >= 0.9) return "economy";
254
+ if (p >= 0.72) return "standard";
255
+ return "frontier";
256
+ }
257
+ function difficultyTier(complexity) {
258
+ if (complexity <= 2) return "economy";
259
+ if (complexity === 3) return "standard";
260
+ return "frontier";
261
+ }
262
+
263
+ // src/providers.ts
264
+ var PROVIDERS = [
265
+ { id: "openai", label: "OpenAI", baseURL: "https://api.openai.com/v1", env: "OPENAI_API_KEY", hint: "sk-..." },
266
+ { id: "groq", label: "Groq", baseURL: "https://api.groq.com/openai/v1", env: "GROQ_API_KEY", hint: "gsk_..." },
267
+ { id: "baseten", label: "Baseten", baseURL: "https://inference.baseten.co/v1", env: "BASETEN_API_KEY", hint: "baseten key" },
268
+ { id: "openrouter", label: "OpenRouter", baseURL: "https://openrouter.ai/api/v1", env: "OPENROUTER_API_KEY", hint: "sk-or-..." },
269
+ { id: "together", label: "Together", baseURL: "https://api.together.xyz/v1", env: "TOGETHER_API_KEY", hint: "together key" },
270
+ { id: "fireworks", label: "Fireworks", baseURL: "https://api.fireworks.ai/inference/v1", env: "FIREWORKS_API_KEY", hint: "fw_..." },
271
+ { id: "deepseek", label: "DeepSeek", baseURL: "https://api.deepseek.com/v1", env: "DEEPSEEK_API_KEY", hint: "sk-..." },
272
+ { id: "mistral", label: "Mistral", baseURL: "https://api.mistral.ai/v1", env: "MISTRAL_API_KEY", hint: "mistral key" },
273
+ { id: "cerebras", label: "Cerebras", baseURL: "https://api.cerebras.ai/v1", env: "CEREBRAS_API_KEY", hint: "csk-..." },
274
+ { id: "xai", label: "xAI", baseURL: "https://api.x.ai/v1", env: "XAI_API_KEY", hint: "xai-..." },
275
+ { id: "google", label: "Google", baseURL: "https://generativelanguage.googleapis.com/v1beta/openai", env: "GOOGLE_API_KEY", hint: "AIza..." },
276
+ { id: "perplexity", label: "Perplexity", baseURL: "https://api.perplexity.ai", env: "PERPLEXITY_API_KEY", hint: "pplx-..." },
277
+ { id: "nvidia", label: "NVIDIA NIM", baseURL: "https://integrate.api.nvidia.com/v1", env: "NVIDIA_API_KEY", hint: "nvapi-..." },
278
+ { id: "sambanova", label: "SambaNova", baseURL: "https://api.sambanova.ai/v1", env: "SAMBANOVA_API_KEY", hint: "samba key" },
279
+ { id: "hyperbolic", label: "Hyperbolic", baseURL: "https://api.hyperbolic.xyz/v1", env: "HYPERBOLIC_API_KEY", hint: "hyperbolic key" },
280
+ { id: "moonshot", label: "Moonshot", baseURL: "https://api.moonshot.ai/v1", env: "MOONSHOT_API_KEY", hint: "sk-..." },
281
+ { id: "ollama", label: "Ollama", baseURL: "http://localhost:11434/v1", env: "OLLAMA_API_KEY", hint: "optional" }
282
+ ];
283
+ function findProvider(input) {
284
+ const needle = input.trim().toLowerCase();
285
+ return PROVIDERS.find((p) => p.id === needle || p.label.toLowerCase() === needle) ?? null;
286
+ }
287
+ function publicCatalog() {
288
+ return PROVIDERS.map(({ id, label, baseURL, env }) => ({
289
+ id,
290
+ label,
291
+ base_url: baseURL,
292
+ env
293
+ }));
294
+ }
295
+ function resolveBaseURL(input) {
296
+ if (input.baseURL?.trim()) return { baseURL: input.baseURL.trim().replace(/\/$/, ""), provider: findProvider(input.provider ?? "") };
297
+ if (input.provider) {
298
+ const provider = findProvider(input.provider);
299
+ if (provider) return { baseURL: provider.baseURL, provider };
300
+ }
301
+ return { baseURL: null, provider: null };
302
+ }
303
+ // Annotate the CommonJS export names for ESM import in node:
304
+ 0 && (module.exports = {
305
+ DEFAULT_GATEWAY,
306
+ PROVIDERS,
307
+ Promptimizer,
308
+ PromptimizerError,
309
+ classifyMessages,
310
+ classifyText,
311
+ difficultyTier,
312
+ findProvider,
313
+ publicCatalog,
314
+ resolveBaseURL
315
+ });
@@ -0,0 +1,5 @@
1
+ export { DEFAULT_GATEWAY, Promptimizer, PromptimizerError } from "./client";
2
+ export { classifyMessages, classifyText, difficultyTier } from "./classify";
3
+ export { PROVIDERS, findProvider, publicCatalog, resolveBaseURL } from "./providers";
4
+ export type { ProviderPreset } from "./providers";
5
+ export type { ChatCompletion, ChatCompletionRequest, ChatMessage, Classification, ConnectOptions, CostBreakdown, ModelInfo, PromptimizerOptions, SavingsSummary, Session, Tier, } from "./types.js";
package/dist/index.js ADDED
@@ -0,0 +1,279 @@
1
+ // src/client.ts
2
+ var PromptimizerError = class extends Error {
3
+ constructor(message, status, body) {
4
+ super(message);
5
+ this.status = status;
6
+ this.body = body;
7
+ this.name = "PromptimizerError";
8
+ }
9
+ };
10
+ var DEFAULT_GATEWAY = (process.env.PROMPTIMIZER_URL || "https://hackathon-omega-liart.vercel.app/api").replace(/\/$/, "");
11
+ var Promptimizer = class _Promptimizer {
12
+ gatewayURL;
13
+ sessionId;
14
+ apiKey;
15
+ fetcher;
16
+ constructor(options = {}) {
17
+ this.gatewayURL = (options.gatewayURL ?? options.baseURL ?? DEFAULT_GATEWAY).replace(/\/$/, "");
18
+ this.sessionId = options.sessionId;
19
+ this.apiKey = options.apiKey;
20
+ this.fetcher = options.fetch ?? fetch;
21
+ }
22
+ static async connect(options) {
23
+ const client = new _Promptimizer({
24
+ gatewayURL: options.gatewayURL,
25
+ apiKey: options.accountKey
26
+ });
27
+ const session = await client.connect(options);
28
+ return { client, session };
29
+ }
30
+ async connect(options) {
31
+ const session = await this.request("/v1/providers/connect", {
32
+ method: "POST",
33
+ body: JSON.stringify({
34
+ mode: options.mode ?? "byok",
35
+ label: options.label,
36
+ provider: options.provider,
37
+ base_url: options.baseURL,
38
+ api_key: options.apiKey
39
+ })
40
+ });
41
+ this.sessionId = session.session_id;
42
+ return session;
43
+ }
44
+ async providers() {
45
+ return this.request(
46
+ "/v1/providers"
47
+ );
48
+ }
49
+ async savings() {
50
+ return this.request("/v1/savings");
51
+ }
52
+ async session() {
53
+ return this.request("/v1/session");
54
+ }
55
+ async models() {
56
+ return this.request(
57
+ "/v1/models"
58
+ );
59
+ }
60
+ async updateFleet(body) {
61
+ return this.request("/v1/models", { method: "PATCH", body: JSON.stringify(body) });
62
+ }
63
+ async classify(input) {
64
+ return this.request("/v1/classify", { method: "POST", body: JSON.stringify(input) });
65
+ }
66
+ async benchmark(compareAlwaysFrontier = true) {
67
+ return this.request("/v1/benchmark/run", {
68
+ method: "POST",
69
+ body: JSON.stringify({ compare_always_frontier: compareAlwaysFrontier })
70
+ });
71
+ }
72
+ chat = {
73
+ completions: {
74
+ create: (request) => this.createChatCompletion(request)
75
+ }
76
+ };
77
+ async createChatCompletion(request) {
78
+ return this.request("/v1/chat/completions", {
79
+ method: "POST",
80
+ body: JSON.stringify(request)
81
+ });
82
+ }
83
+ async request(path, init = {}) {
84
+ const headers = new Headers(init.headers);
85
+ headers.set("Content-Type", "application/json");
86
+ if (this.apiKey) {
87
+ headers.set("Authorization", `Bearer ${this.apiKey}`);
88
+ } else if (this.sessionId) {
89
+ headers.set("X-Promptimizer-Session", this.sessionId);
90
+ headers.set("Authorization", `Bearer ${this.sessionId}`);
91
+ }
92
+ const response = await this.fetcher(`${this.gatewayURL}${path}`, { ...init, headers });
93
+ const data = await response.json().catch(() => ({}));
94
+ if (!response.ok) {
95
+ const detail = typeof data === "object" && data && "detail" in data ? String(data.detail) : response.statusText;
96
+ throw new PromptimizerError(detail, response.status, data);
97
+ }
98
+ return data;
99
+ }
100
+ };
101
+
102
+ // src/classify.ts
103
+ var HIGH_RISK = /* @__PURE__ */ new Set(["system_design", "safety_sensitive", "code_debug", "reasoning"]);
104
+ function textFrom(messages) {
105
+ return messages.map((m) => {
106
+ if (typeof m.content === "string") return m.content;
107
+ return m.content.map((b) => b.text ?? "").join("\n");
108
+ }).join("\n").trim();
109
+ }
110
+ function classifyMessages(messages) {
111
+ return classifyText(textFrom(messages));
112
+ }
113
+ function classifyText(text) {
114
+ const words = text.split(/\s+/).filter(Boolean).length;
115
+ const lines = text.split("\n").length;
116
+ const features = {
117
+ code_fence: /```/.test(text),
118
+ code_kw: /\b(def |class |function |import |fn |pub |async |SELECT |goroutine|mutex|traceback)\b/i.test(
119
+ text
120
+ ),
121
+ math: /(\$\$|\\frac|prove that|expected value|O\([nN]\)|\d+\s*[\*\^]\s*\d+)/i.test(text),
122
+ design: /\b(design|architect|rate limiter|distributed|consistency|shard|1 million QPS)\b/i.test(
123
+ text
124
+ ),
125
+ reason: /\b(prove|why does|walk through|step by step|derive|contradiction|p-value)\b/i.test(
126
+ text
127
+ ),
128
+ debug: /\b(bug|race|panic|fails on|diagnose|deadlock)\b/i.test(text),
129
+ summarize: /\b(summarize|tl;dr|in two sentences|eli5)\b/i.test(text),
130
+ translate: /\b(translate|traduce)\b/i.test(text),
131
+ creative: /\b(write a (poem|story|song)|haiku)\b/i.test(text),
132
+ safety: /\b(refund|legal|medical|hipaa|lawsuit|diagnosis)\b/i.test(text),
133
+ analysis: /\b(compare|trade-?off|versus|analyse|analyze|evaluate|should we)\b/i.test(text),
134
+ constraints: (text.match(/\b(must|include|constraints?|requirements?)\b/gi) ?? []).length,
135
+ words,
136
+ lines,
137
+ question_marks: (text.match(/\?/g) ?? []).length
138
+ };
139
+ const category = categoryOf(features);
140
+ const complexity = complexityOf(features, category);
141
+ const p_small_quality = pSmallQuality(features, category, complexity);
142
+ const quality_risk = riskOf(category, complexity, p_small_quality);
143
+ const recommended_tier = tierFromP(p_small_quality);
144
+ const signals = [
145
+ features.code_fence,
146
+ features.code_kw,
147
+ features.math,
148
+ features.design,
149
+ features.reason,
150
+ features.debug,
151
+ features.safety
152
+ ].filter(Boolean).length;
153
+ const confidence = category === "factual_recall" && words < 16 ? 0.9 : Math.min(0.95, 0.55 + 0.12 * signals);
154
+ return {
155
+ complexity,
156
+ category,
157
+ confidence: Number(confidence.toFixed(3)),
158
+ recommended_tier,
159
+ quality_risk,
160
+ p_small_quality,
161
+ uncertainty: Number((1 - p_small_quality).toFixed(3)),
162
+ structured_output: Boolean(features.code_fence || features.constraints >= 1),
163
+ context_tokens_est: Math.max(1, Math.round(text.length / 4)),
164
+ rationale: `${category.replaceAll("_", " ")} L${complexity}. P(quality|small)=${p_small_quality}. Route to ${recommended_tier}.`,
165
+ features
166
+ };
167
+ }
168
+ function categoryOf(h) {
169
+ if (h.safety) return "safety_sensitive";
170
+ if (h.design) return "system_design";
171
+ if (h.debug && (h.code_fence || h.code_kw)) return "code_debug";
172
+ if (h.code_fence || h.code_kw) return "code_generation";
173
+ if (h.math && h.reason) return "reasoning";
174
+ if (h.math) return "math";
175
+ if (h.reason) return "reasoning";
176
+ if (h.translate) return "translation";
177
+ if (h.summarize) return "summarization";
178
+ if (h.creative) return "creative";
179
+ if (h.analysis) return "analysis";
180
+ if (h.words < 24 && h.question_marks >= 1) return "factual_recall";
181
+ return h.words > 80 ? "analysis" : "factual_recall";
182
+ }
183
+ function complexityOf(h, category) {
184
+ let score = 1;
185
+ if (h.words > 40) score += 1;
186
+ if (h.words > 120) score += 1;
187
+ if (h.lines > 12 || h.code_fence) score += 1;
188
+ if (h.constraints >= 2) score += 1;
189
+ if (h.design || h.reason) score += 1;
190
+ if (h.debug) score += 1;
191
+ if (["system_design", "reasoning", "safety_sensitive"].includes(category)) score = Math.max(score + 1, 4);
192
+ if (category === "code_generation") score = Math.max(score, 3);
193
+ if (category === "code_debug") score = Math.max(score, 4);
194
+ if (category === "factual_recall" && h.words < 20) score = Math.min(score, 2);
195
+ return Math.max(1, Math.min(5, score));
196
+ }
197
+ function pSmallQuality(h, category, complexity) {
198
+ let p = 0.96;
199
+ if (h.design || category === "system_design") p -= 0.28;
200
+ if (h.safety || category === "safety_sensitive") p -= 0.3;
201
+ if (h.debug || category === "code_debug") p -= 0.22;
202
+ if (h.reason || category === "reasoning") p -= 0.18;
203
+ if (complexity >= 5) p -= 0.22;
204
+ else if (complexity >= 4) p -= 0.14;
205
+ else if (complexity === 3) p -= 0.06;
206
+ if (h.words > 120) p -= 0.07;
207
+ if (h.constraints >= 2) p -= 0.07;
208
+ if (category === "code_generation") p -= 0.05;
209
+ if (category === "factual_recall" && h.words < 24) p = Math.max(p, 0.94);
210
+ return Number(Math.min(0.99, Math.max(0.05, p)).toFixed(3));
211
+ }
212
+ function riskOf(category, complexity, p) {
213
+ if (HIGH_RISK.has(category) || complexity >= 5 || p < 0.72) return "high";
214
+ if (complexity >= 3 || p < 0.9) return "medium";
215
+ return "low";
216
+ }
217
+ function tierFromP(p) {
218
+ if (p >= 0.9) return "economy";
219
+ if (p >= 0.72) return "standard";
220
+ return "frontier";
221
+ }
222
+ function difficultyTier(complexity) {
223
+ if (complexity <= 2) return "economy";
224
+ if (complexity === 3) return "standard";
225
+ return "frontier";
226
+ }
227
+
228
+ // src/providers.ts
229
+ var PROVIDERS = [
230
+ { id: "openai", label: "OpenAI", baseURL: "https://api.openai.com/v1", env: "OPENAI_API_KEY", hint: "sk-..." },
231
+ { id: "groq", label: "Groq", baseURL: "https://api.groq.com/openai/v1", env: "GROQ_API_KEY", hint: "gsk_..." },
232
+ { id: "baseten", label: "Baseten", baseURL: "https://inference.baseten.co/v1", env: "BASETEN_API_KEY", hint: "baseten key" },
233
+ { id: "openrouter", label: "OpenRouter", baseURL: "https://openrouter.ai/api/v1", env: "OPENROUTER_API_KEY", hint: "sk-or-..." },
234
+ { id: "together", label: "Together", baseURL: "https://api.together.xyz/v1", env: "TOGETHER_API_KEY", hint: "together key" },
235
+ { id: "fireworks", label: "Fireworks", baseURL: "https://api.fireworks.ai/inference/v1", env: "FIREWORKS_API_KEY", hint: "fw_..." },
236
+ { id: "deepseek", label: "DeepSeek", baseURL: "https://api.deepseek.com/v1", env: "DEEPSEEK_API_KEY", hint: "sk-..." },
237
+ { id: "mistral", label: "Mistral", baseURL: "https://api.mistral.ai/v1", env: "MISTRAL_API_KEY", hint: "mistral key" },
238
+ { id: "cerebras", label: "Cerebras", baseURL: "https://api.cerebras.ai/v1", env: "CEREBRAS_API_KEY", hint: "csk-..." },
239
+ { id: "xai", label: "xAI", baseURL: "https://api.x.ai/v1", env: "XAI_API_KEY", hint: "xai-..." },
240
+ { id: "google", label: "Google", baseURL: "https://generativelanguage.googleapis.com/v1beta/openai", env: "GOOGLE_API_KEY", hint: "AIza..." },
241
+ { id: "perplexity", label: "Perplexity", baseURL: "https://api.perplexity.ai", env: "PERPLEXITY_API_KEY", hint: "pplx-..." },
242
+ { id: "nvidia", label: "NVIDIA NIM", baseURL: "https://integrate.api.nvidia.com/v1", env: "NVIDIA_API_KEY", hint: "nvapi-..." },
243
+ { id: "sambanova", label: "SambaNova", baseURL: "https://api.sambanova.ai/v1", env: "SAMBANOVA_API_KEY", hint: "samba key" },
244
+ { id: "hyperbolic", label: "Hyperbolic", baseURL: "https://api.hyperbolic.xyz/v1", env: "HYPERBOLIC_API_KEY", hint: "hyperbolic key" },
245
+ { id: "moonshot", label: "Moonshot", baseURL: "https://api.moonshot.ai/v1", env: "MOONSHOT_API_KEY", hint: "sk-..." },
246
+ { id: "ollama", label: "Ollama", baseURL: "http://localhost:11434/v1", env: "OLLAMA_API_KEY", hint: "optional" }
247
+ ];
248
+ function findProvider(input) {
249
+ const needle = input.trim().toLowerCase();
250
+ return PROVIDERS.find((p) => p.id === needle || p.label.toLowerCase() === needle) ?? null;
251
+ }
252
+ function publicCatalog() {
253
+ return PROVIDERS.map(({ id, label, baseURL, env }) => ({
254
+ id,
255
+ label,
256
+ base_url: baseURL,
257
+ env
258
+ }));
259
+ }
260
+ function resolveBaseURL(input) {
261
+ if (input.baseURL?.trim()) return { baseURL: input.baseURL.trim().replace(/\/$/, ""), provider: findProvider(input.provider ?? "") };
262
+ if (input.provider) {
263
+ const provider = findProvider(input.provider);
264
+ if (provider) return { baseURL: provider.baseURL, provider };
265
+ }
266
+ return { baseURL: null, provider: null };
267
+ }
268
+ export {
269
+ DEFAULT_GATEWAY,
270
+ PROVIDERS,
271
+ Promptimizer,
272
+ PromptimizerError,
273
+ classifyMessages,
274
+ classifyText,
275
+ difficultyTier,
276
+ findProvider,
277
+ publicCatalog,
278
+ resolveBaseURL
279
+ };
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/providers.ts
21
+ var providers_exports = {};
22
+ __export(providers_exports, {
23
+ PROVIDERS: () => PROVIDERS,
24
+ findProvider: () => findProvider,
25
+ publicCatalog: () => publicCatalog,
26
+ resolveBaseURL: () => resolveBaseURL
27
+ });
28
+ module.exports = __toCommonJS(providers_exports);
29
+ var PROVIDERS = [
30
+ { id: "openai", label: "OpenAI", baseURL: "https://api.openai.com/v1", env: "OPENAI_API_KEY", hint: "sk-..." },
31
+ { id: "groq", label: "Groq", baseURL: "https://api.groq.com/openai/v1", env: "GROQ_API_KEY", hint: "gsk_..." },
32
+ { id: "baseten", label: "Baseten", baseURL: "https://inference.baseten.co/v1", env: "BASETEN_API_KEY", hint: "baseten key" },
33
+ { id: "openrouter", label: "OpenRouter", baseURL: "https://openrouter.ai/api/v1", env: "OPENROUTER_API_KEY", hint: "sk-or-..." },
34
+ { id: "together", label: "Together", baseURL: "https://api.together.xyz/v1", env: "TOGETHER_API_KEY", hint: "together key" },
35
+ { id: "fireworks", label: "Fireworks", baseURL: "https://api.fireworks.ai/inference/v1", env: "FIREWORKS_API_KEY", hint: "fw_..." },
36
+ { id: "deepseek", label: "DeepSeek", baseURL: "https://api.deepseek.com/v1", env: "DEEPSEEK_API_KEY", hint: "sk-..." },
37
+ { id: "mistral", label: "Mistral", baseURL: "https://api.mistral.ai/v1", env: "MISTRAL_API_KEY", hint: "mistral key" },
38
+ { id: "cerebras", label: "Cerebras", baseURL: "https://api.cerebras.ai/v1", env: "CEREBRAS_API_KEY", hint: "csk-..." },
39
+ { id: "xai", label: "xAI", baseURL: "https://api.x.ai/v1", env: "XAI_API_KEY", hint: "xai-..." },
40
+ { id: "google", label: "Google", baseURL: "https://generativelanguage.googleapis.com/v1beta/openai", env: "GOOGLE_API_KEY", hint: "AIza..." },
41
+ { id: "perplexity", label: "Perplexity", baseURL: "https://api.perplexity.ai", env: "PERPLEXITY_API_KEY", hint: "pplx-..." },
42
+ { id: "nvidia", label: "NVIDIA NIM", baseURL: "https://integrate.api.nvidia.com/v1", env: "NVIDIA_API_KEY", hint: "nvapi-..." },
43
+ { id: "sambanova", label: "SambaNova", baseURL: "https://api.sambanova.ai/v1", env: "SAMBANOVA_API_KEY", hint: "samba key" },
44
+ { id: "hyperbolic", label: "Hyperbolic", baseURL: "https://api.hyperbolic.xyz/v1", env: "HYPERBOLIC_API_KEY", hint: "hyperbolic key" },
45
+ { id: "moonshot", label: "Moonshot", baseURL: "https://api.moonshot.ai/v1", env: "MOONSHOT_API_KEY", hint: "sk-..." },
46
+ { id: "ollama", label: "Ollama", baseURL: "http://localhost:11434/v1", env: "OLLAMA_API_KEY", hint: "optional" }
47
+ ];
48
+ function findProvider(input) {
49
+ const needle = input.trim().toLowerCase();
50
+ return PROVIDERS.find((p) => p.id === needle || p.label.toLowerCase() === needle) ?? null;
51
+ }
52
+ function publicCatalog() {
53
+ return PROVIDERS.map(({ id, label, baseURL, env }) => ({
54
+ id,
55
+ label,
56
+ base_url: baseURL,
57
+ env
58
+ }));
59
+ }
60
+ function resolveBaseURL(input) {
61
+ if (input.baseURL?.trim()) return { baseURL: input.baseURL.trim().replace(/\/$/, ""), provider: findProvider(input.provider ?? "") };
62
+ if (input.provider) {
63
+ const provider = findProvider(input.provider);
64
+ if (provider) return { baseURL: provider.baseURL, provider };
65
+ }
66
+ return { baseURL: null, provider: null };
67
+ }
68
+ // Annotate the CommonJS export names for ESM import in node:
69
+ 0 && (module.exports = {
70
+ PROVIDERS,
71
+ findProvider,
72
+ publicCatalog,
73
+ resolveBaseURL
74
+ });
@@ -0,0 +1,25 @@
1
+ export type ProviderPreset = {
2
+ id: string;
3
+ label: string;
4
+ baseURL: string;
5
+ env: string;
6
+ hint: string;
7
+ };
8
+ export declare const PROVIDERS: ProviderPreset[];
9
+ export declare function findProvider(input: string): ProviderPreset | null;
10
+ export declare function publicCatalog(): {
11
+ id: string;
12
+ label: string;
13
+ base_url: string;
14
+ env: string;
15
+ }[];
16
+ export declare function resolveBaseURL(input: {
17
+ provider?: string;
18
+ baseURL?: string;
19
+ }): {
20
+ baseURL: string;
21
+ provider: ProviderPreset | null;
22
+ } | {
23
+ baseURL: null;
24
+ provider: null;
25
+ };
@@ -0,0 +1,46 @@
1
+ // src/providers.ts
2
+ var PROVIDERS = [
3
+ { id: "openai", label: "OpenAI", baseURL: "https://api.openai.com/v1", env: "OPENAI_API_KEY", hint: "sk-..." },
4
+ { id: "groq", label: "Groq", baseURL: "https://api.groq.com/openai/v1", env: "GROQ_API_KEY", hint: "gsk_..." },
5
+ { id: "baseten", label: "Baseten", baseURL: "https://inference.baseten.co/v1", env: "BASETEN_API_KEY", hint: "baseten key" },
6
+ { id: "openrouter", label: "OpenRouter", baseURL: "https://openrouter.ai/api/v1", env: "OPENROUTER_API_KEY", hint: "sk-or-..." },
7
+ { id: "together", label: "Together", baseURL: "https://api.together.xyz/v1", env: "TOGETHER_API_KEY", hint: "together key" },
8
+ { id: "fireworks", label: "Fireworks", baseURL: "https://api.fireworks.ai/inference/v1", env: "FIREWORKS_API_KEY", hint: "fw_..." },
9
+ { id: "deepseek", label: "DeepSeek", baseURL: "https://api.deepseek.com/v1", env: "DEEPSEEK_API_KEY", hint: "sk-..." },
10
+ { id: "mistral", label: "Mistral", baseURL: "https://api.mistral.ai/v1", env: "MISTRAL_API_KEY", hint: "mistral key" },
11
+ { id: "cerebras", label: "Cerebras", baseURL: "https://api.cerebras.ai/v1", env: "CEREBRAS_API_KEY", hint: "csk-..." },
12
+ { id: "xai", label: "xAI", baseURL: "https://api.x.ai/v1", env: "XAI_API_KEY", hint: "xai-..." },
13
+ { id: "google", label: "Google", baseURL: "https://generativelanguage.googleapis.com/v1beta/openai", env: "GOOGLE_API_KEY", hint: "AIza..." },
14
+ { id: "perplexity", label: "Perplexity", baseURL: "https://api.perplexity.ai", env: "PERPLEXITY_API_KEY", hint: "pplx-..." },
15
+ { id: "nvidia", label: "NVIDIA NIM", baseURL: "https://integrate.api.nvidia.com/v1", env: "NVIDIA_API_KEY", hint: "nvapi-..." },
16
+ { id: "sambanova", label: "SambaNova", baseURL: "https://api.sambanova.ai/v1", env: "SAMBANOVA_API_KEY", hint: "samba key" },
17
+ { id: "hyperbolic", label: "Hyperbolic", baseURL: "https://api.hyperbolic.xyz/v1", env: "HYPERBOLIC_API_KEY", hint: "hyperbolic key" },
18
+ { id: "moonshot", label: "Moonshot", baseURL: "https://api.moonshot.ai/v1", env: "MOONSHOT_API_KEY", hint: "sk-..." },
19
+ { id: "ollama", label: "Ollama", baseURL: "http://localhost:11434/v1", env: "OLLAMA_API_KEY", hint: "optional" }
20
+ ];
21
+ function findProvider(input) {
22
+ const needle = input.trim().toLowerCase();
23
+ return PROVIDERS.find((p) => p.id === needle || p.label.toLowerCase() === needle) ?? null;
24
+ }
25
+ function publicCatalog() {
26
+ return PROVIDERS.map(({ id, label, baseURL, env }) => ({
27
+ id,
28
+ label,
29
+ base_url: baseURL,
30
+ env
31
+ }));
32
+ }
33
+ function resolveBaseURL(input) {
34
+ if (input.baseURL?.trim()) return { baseURL: input.baseURL.trim().replace(/\/$/, ""), provider: findProvider(input.provider ?? "") };
35
+ if (input.provider) {
36
+ const provider = findProvider(input.provider);
37
+ if (provider) return { baseURL: provider.baseURL, provider };
38
+ }
39
+ return { baseURL: null, provider: null };
40
+ }
41
+ export {
42
+ PROVIDERS,
43
+ findProvider,
44
+ publicCatalog,
45
+ resolveBaseURL
46
+ };
@@ -0,0 +1,123 @@
1
+ export type Tier = "economy" | "standard" | "frontier";
2
+ export type ChatMessage = {
3
+ role: "system" | "user" | "assistant" | "tool" | string;
4
+ content: string | Array<{
5
+ type: string;
6
+ text?: string;
7
+ }>;
8
+ name?: string;
9
+ };
10
+ export type Classification = {
11
+ complexity: number;
12
+ category: string;
13
+ confidence: number;
14
+ recommended_tier: Tier;
15
+ quality_risk: "low" | "medium" | "high";
16
+ p_small_quality: number;
17
+ uncertainty: number;
18
+ structured_output: boolean;
19
+ context_tokens_est: number;
20
+ rationale: string;
21
+ features: Record<string, unknown>;
22
+ };
23
+ export type ModelInfo = {
24
+ id: string;
25
+ owned_by?: string;
26
+ input_per_1m?: number | null;
27
+ output_per_1m?: number | null;
28
+ tier: Tier;
29
+ source?: string;
30
+ selected?: boolean;
31
+ };
32
+ export type ConnectOptions = {
33
+ mode?: "mock" | "byok";
34
+ label?: string;
35
+ provider?: string;
36
+ baseURL?: string;
37
+ apiKey?: string;
38
+ accountKey?: string;
39
+ gatewayURL?: string;
40
+ };
41
+ export type SavingsSummary = {
42
+ requests: number;
43
+ actual_usd: number;
44
+ baseline_usd: number;
45
+ saved_usd: number;
46
+ saved_pct: number;
47
+ routing_saved_usd: number;
48
+ cache_saved_usd: number;
49
+ cache_hits: number;
50
+ escalations: number;
51
+ avg_quality: number | null;
52
+ recent: Array<{
53
+ id: string;
54
+ model: string;
55
+ tier: string;
56
+ actual_usd: number;
57
+ baseline_usd: number;
58
+ saved_usd: number;
59
+ routing_saved_usd: number;
60
+ cache_saved_usd: number;
61
+ cache_hit: boolean;
62
+ escalated: boolean;
63
+ quality: number | null;
64
+ created_at: string;
65
+ }>;
66
+ };
67
+ export type PromptimizerOptions = {
68
+ gatewayURL?: string;
69
+ sessionId?: string;
70
+ apiKey?: string;
71
+ baseURL?: string;
72
+ fetch?: typeof fetch;
73
+ };
74
+ export type ChatCompletionRequest = {
75
+ messages: ChatMessage[];
76
+ model?: string;
77
+ stream?: boolean;
78
+ level_override?: number;
79
+ temperature?: number;
80
+ max_tokens?: number;
81
+ };
82
+ export type CostBreakdown = {
83
+ actual_usd: number;
84
+ baseline_usd: number;
85
+ saved_usd: number;
86
+ saved_pct: number;
87
+ routing_saved_usd: number;
88
+ cache_discount_usd: number;
89
+ prompt_tokens: number;
90
+ completion_tokens: number;
91
+ cached_tokens: number;
92
+ };
93
+ export type ChatCompletion = {
94
+ id: string;
95
+ object: string;
96
+ created: number;
97
+ model: string;
98
+ choices: Array<{
99
+ index: number;
100
+ message: {
101
+ role: string;
102
+ content: string;
103
+ };
104
+ finish_reason: string;
105
+ }>;
106
+ usage: {
107
+ prompt_tokens: number;
108
+ completion_tokens: number;
109
+ total_tokens: number;
110
+ cost?: CostBreakdown;
111
+ };
112
+ promptimizer?: Record<string, unknown>;
113
+ };
114
+ export type Session = {
115
+ session_id: string;
116
+ mode: string;
117
+ label: string;
118
+ base_url: string;
119
+ models: ModelInfo[];
120
+ baseline_model: string | null;
121
+ stats: Record<string, number>;
122
+ created_at: number;
123
+ };
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "promptimizer",
3
+ "version": "0.1.0",
4
+ "description": "OpenAI-compatible SDK for Promptimizer — BYOK model routing, classification, and prompt caching.",
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "module": "./src/index.ts",
8
+ "types": "./src/index.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./src/index.ts",
12
+ "import": "./src/index.ts",
13
+ "default": "./src/index.ts"
14
+ },
15
+ "./providers": {
16
+ "types": "./src/providers.ts",
17
+ "import": "./src/providers.ts",
18
+ "default": "./src/providers.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md"
24
+ ],
25
+ "scripts": {
26
+ "build": "node scripts/build.mjs",
27
+ "dev": "node scripts/build.mjs",
28
+ "prepublishOnly": "npm run build",
29
+ "typecheck": "tsc --noEmit",
30
+ "test": "node --experimental-strip-types --test src/classify.test.ts src/providers.test.ts",
31
+ "publish:npm": "npm publish --access public"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public",
35
+ "main": "./dist/index.cjs",
36
+ "module": "./dist/index.js",
37
+ "types": "./dist/index.d.ts",
38
+ "exports": {
39
+ ".": {
40
+ "types": "./dist/index.d.ts",
41
+ "import": "./dist/index.js",
42
+ "require": "./dist/index.cjs"
43
+ },
44
+ "./providers": {
45
+ "types": "./dist/providers.d.ts",
46
+ "import": "./dist/providers.js",
47
+ "require": "./dist/providers.cjs"
48
+ }
49
+ }
50
+ },
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "git+https://github.com/sreecharan-desu/promptimizer.git",
54
+ "directory": "packages/sdk"
55
+ },
56
+ "homepage": "https://hackathon-omega-liart.vercel.app",
57
+ "bugs": {
58
+ "url": "https://github.com/sreecharan-desu/promptimizer/issues"
59
+ },
60
+ "keywords": [
61
+ "llm",
62
+ "openai",
63
+ "router",
64
+ "prompt-cache",
65
+ "byok",
66
+ "cost-optimization"
67
+ ],
68
+ "license": "MIT",
69
+ "devDependencies": {
70
+ "@types/node": "^22.15.0",
71
+ "esbuild": "^0.25.9",
72
+ "typescript": "^5.8.0"
73
+ }
74
+ }