@f3d1/llmkit-sdk 0.0.1
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/dist/client.d.ts +30 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +124 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/tracker.d.ts +64 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +121 -0
- package/dist/tracker.js.map +1 -0
- package/package.json +25 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CostBreakdown, LLMKitConfig, LLMRequest, LLMResponse, TokenUsage } from '@f3d1/llmkit-shared';
|
|
2
|
+
type ChatRequest = Omit<LLMRequest, 'provider'> & {
|
|
3
|
+
provider?: string;
|
|
4
|
+
};
|
|
5
|
+
export declare class LLMKit {
|
|
6
|
+
private config;
|
|
7
|
+
private sessionId?;
|
|
8
|
+
constructor(config: LLMKitConfig);
|
|
9
|
+
session(id?: string): LLMKit;
|
|
10
|
+
chat(req: ChatRequest): Promise<LLMResponse>;
|
|
11
|
+
chatStream(req: ChatRequest): Promise<ChatStream>;
|
|
12
|
+
private fetch;
|
|
13
|
+
}
|
|
14
|
+
export declare class ChatStream {
|
|
15
|
+
private response;
|
|
16
|
+
private _usage?;
|
|
17
|
+
private _cost?;
|
|
18
|
+
private _model?;
|
|
19
|
+
private _provider?;
|
|
20
|
+
private _id?;
|
|
21
|
+
constructor(response: Response);
|
|
22
|
+
get usage(): TokenUsage | undefined;
|
|
23
|
+
get cost(): CostBreakdown | undefined;
|
|
24
|
+
get model(): string | undefined;
|
|
25
|
+
get provider(): string | undefined;
|
|
26
|
+
get id(): string | undefined;
|
|
27
|
+
[Symbol.asyncIterator](): AsyncGenerator<string>;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAI5G,KAAK,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAqD;IACnE,OAAO,CAAC,SAAS,CAAC,CAAS;gBAEf,MAAM,EAAE,YAAY;IAQhC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IAQtB,IAAI,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAY5C,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAYvD,OAAO,CAAC,KAAK;CAoBd;AAGD,qBAAa,UAAU;IAOT,OAAO,CAAC,QAAQ;IAN5B,OAAO,CAAC,MAAM,CAAC,CAAa;IAC5B,OAAO,CAAC,KAAK,CAAC,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,GAAG,CAAC,CAAS;gBAED,QAAQ,EAAE,QAAQ;IAEtC,IAAI,KAAK,2BAA0B;IACnC,IAAI,IAAI,8BAAyB;IACjC,IAAI,KAAK,uBAA0B;IACnC,IAAI,QAAQ,uBAA6B;IACzC,IAAI,EAAE,uBAAuB;IAEtB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,MAAM,CAAC;CAsDxD"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const DEFAULT_BASE_URL = 'https://api.llmkit.dev';
|
|
2
|
+
export class LLMKit {
|
|
3
|
+
config;
|
|
4
|
+
sessionId;
|
|
5
|
+
constructor(config) {
|
|
6
|
+
this.config = {
|
|
7
|
+
apiKey: config.apiKey,
|
|
8
|
+
baseUrl: config.baseUrl || DEFAULT_BASE_URL,
|
|
9
|
+
};
|
|
10
|
+
this.sessionId = config.sessionId;
|
|
11
|
+
}
|
|
12
|
+
session(id) {
|
|
13
|
+
const clone = new LLMKit({
|
|
14
|
+
...this.config,
|
|
15
|
+
sessionId: id || crypto.randomUUID(),
|
|
16
|
+
});
|
|
17
|
+
return clone;
|
|
18
|
+
}
|
|
19
|
+
async chat(req) {
|
|
20
|
+
const res = await this.fetch(req);
|
|
21
|
+
if (!res.ok) {
|
|
22
|
+
const body = await res.json().catch(() => null);
|
|
23
|
+
const msg = body?.error?.message || body?.message || res.statusText;
|
|
24
|
+
throw new Error(msg);
|
|
25
|
+
}
|
|
26
|
+
return res.json();
|
|
27
|
+
}
|
|
28
|
+
async chatStream(req) {
|
|
29
|
+
const res = await this.fetch({ ...req, stream: true });
|
|
30
|
+
if (!res.ok) {
|
|
31
|
+
const body = await res.json().catch(() => null);
|
|
32
|
+
const msg = body?.error?.message || body?.message || res.statusText;
|
|
33
|
+
throw new Error(msg);
|
|
34
|
+
}
|
|
35
|
+
return new ChatStream(res);
|
|
36
|
+
}
|
|
37
|
+
fetch(req) {
|
|
38
|
+
const headers = {
|
|
39
|
+
'Authorization': `Bearer ${this.config.apiKey}`,
|
|
40
|
+
'Content-Type': 'application/json',
|
|
41
|
+
'x-llmkit-format': 'llmkit',
|
|
42
|
+
};
|
|
43
|
+
if (this.sessionId) {
|
|
44
|
+
headers['x-llmkit-session-id'] = this.sessionId;
|
|
45
|
+
}
|
|
46
|
+
if (req.provider) {
|
|
47
|
+
headers['x-llmkit-provider'] = req.provider;
|
|
48
|
+
}
|
|
49
|
+
return fetch(`${this.config.baseUrl}/v1/chat/completions`, {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
headers,
|
|
52
|
+
body: JSON.stringify(req),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// async iterable that yields text chunks and exposes metadata after completion
|
|
57
|
+
export class ChatStream {
|
|
58
|
+
response;
|
|
59
|
+
_usage;
|
|
60
|
+
_cost;
|
|
61
|
+
_model;
|
|
62
|
+
_provider;
|
|
63
|
+
_id;
|
|
64
|
+
constructor(response) {
|
|
65
|
+
this.response = response;
|
|
66
|
+
}
|
|
67
|
+
get usage() { return this._usage; }
|
|
68
|
+
get cost() { return this._cost; }
|
|
69
|
+
get model() { return this._model; }
|
|
70
|
+
get provider() { return this._provider; }
|
|
71
|
+
get id() { return this._id; }
|
|
72
|
+
async *[Symbol.asyncIterator]() {
|
|
73
|
+
if (!this.response.body)
|
|
74
|
+
throw new Error('No response body');
|
|
75
|
+
const reader = this.response.body.getReader();
|
|
76
|
+
const decoder = new TextDecoder();
|
|
77
|
+
let buffer = '';
|
|
78
|
+
let currentEvent = '';
|
|
79
|
+
try {
|
|
80
|
+
while (true) {
|
|
81
|
+
const { done, value } = await reader.read();
|
|
82
|
+
if (done)
|
|
83
|
+
break;
|
|
84
|
+
buffer += decoder.decode(value, { stream: true });
|
|
85
|
+
const lines = buffer.split('\n');
|
|
86
|
+
buffer = lines.pop();
|
|
87
|
+
for (const line of lines) {
|
|
88
|
+
if (line.startsWith('event: ')) {
|
|
89
|
+
currentEvent = line.slice(7).trim();
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (!line.startsWith('data: ')) {
|
|
93
|
+
if (line === '')
|
|
94
|
+
currentEvent = '';
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const raw = line.slice(6).trim();
|
|
98
|
+
if (!raw)
|
|
99
|
+
continue;
|
|
100
|
+
try {
|
|
101
|
+
const data = JSON.parse(raw);
|
|
102
|
+
if (currentEvent === 'delta' && data.text !== undefined) {
|
|
103
|
+
yield data.text;
|
|
104
|
+
}
|
|
105
|
+
if (currentEvent === 'done') {
|
|
106
|
+
this._usage = data.usage;
|
|
107
|
+
this._cost = data.cost;
|
|
108
|
+
this._model = data.model;
|
|
109
|
+
this._provider = data.provider;
|
|
110
|
+
this._id = data.id;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// partial JSON, will be completed in next chunk
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
reader.releaseLock();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { CostBreakdown, LLMKitConfig, LLMRequest, LLMResponse, ProviderName, SessionSummary, TokenUsage, } from '@f3d1/llmkit-shared';
|
|
2
|
+
export { ChatStream, LLMKit } from './client';
|
|
3
|
+
export type { CostEntry } from './tracker';
|
|
4
|
+
export { CostTracker } from './tracker';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,cAAc,EACd,UAAU,GACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAC9C,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type ProviderName } from '@f3d1/llmkit-shared';
|
|
2
|
+
interface UsageInput {
|
|
3
|
+
inputTokens: number;
|
|
4
|
+
outputTokens: number;
|
|
5
|
+
cacheReadTokens?: number;
|
|
6
|
+
cacheWriteTokens?: number;
|
|
7
|
+
sessionId?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CostEntry {
|
|
10
|
+
provider: ProviderName;
|
|
11
|
+
model: string;
|
|
12
|
+
inputTokens: number;
|
|
13
|
+
outputTokens: number;
|
|
14
|
+
cacheReadTokens: number;
|
|
15
|
+
cacheWriteTokens: number;
|
|
16
|
+
costCents: number;
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
timestamp: Date;
|
|
19
|
+
}
|
|
20
|
+
interface OpenAILikeUsage {
|
|
21
|
+
prompt_tokens: number;
|
|
22
|
+
completion_tokens: number;
|
|
23
|
+
}
|
|
24
|
+
interface AnthropicLikeUsage {
|
|
25
|
+
input_tokens: number;
|
|
26
|
+
output_tokens: number;
|
|
27
|
+
cache_read_input_tokens?: number;
|
|
28
|
+
cache_creation_input_tokens?: number;
|
|
29
|
+
}
|
|
30
|
+
type CostListener = (entry: CostEntry) => void;
|
|
31
|
+
interface TrackerConfig {
|
|
32
|
+
log?: boolean;
|
|
33
|
+
onTrack?: CostListener;
|
|
34
|
+
}
|
|
35
|
+
interface Bucket {
|
|
36
|
+
cents: number;
|
|
37
|
+
requests: number;
|
|
38
|
+
inputTokens: number;
|
|
39
|
+
outputTokens: number;
|
|
40
|
+
}
|
|
41
|
+
export declare class CostTracker {
|
|
42
|
+
private entries;
|
|
43
|
+
private listeners;
|
|
44
|
+
private shouldLog;
|
|
45
|
+
constructor(config?: TrackerConfig);
|
|
46
|
+
track(provider: ProviderName, model: string, usage: UsageInput): CostEntry;
|
|
47
|
+
trackResponse(provider: ProviderName, response: {
|
|
48
|
+
model: string;
|
|
49
|
+
usage: OpenAILikeUsage | AnthropicLikeUsage;
|
|
50
|
+
}): CostEntry;
|
|
51
|
+
on(listener: CostListener): () => void;
|
|
52
|
+
get totalCents(): number;
|
|
53
|
+
get totalDollars(): string;
|
|
54
|
+
get requestCount(): number;
|
|
55
|
+
byProvider(): Record<string, Bucket>;
|
|
56
|
+
byModel(): Record<string, Bucket>;
|
|
57
|
+
bySession(): Record<string, Bucket>;
|
|
58
|
+
summary(): string;
|
|
59
|
+
reset(): void;
|
|
60
|
+
private emit;
|
|
61
|
+
private groupBy;
|
|
62
|
+
}
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../src/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEvE,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;CACjB;AAGD,UAAU,eAAe;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,kBAAkB;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,KAAK,YAAY,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;AAE/C,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED,UAAU,MAAM;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,SAAS,CAAU;gBAEf,MAAM,GAAE,aAAkB;IAKtC,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS;IAyB1E,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,eAAe,GAAG,kBAAkB,CAAA;KAAE,GAAG,SAAS;IAkB1H,EAAE,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,IAAI;IAQtC,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAIpC,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAIjC,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAInC,OAAO,IAAI,MAAM;IA0BjB,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,IAAI;IAWZ,OAAO,CAAC,OAAO;CAahB"}
|
package/dist/tracker.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { calculateCost } from '@f3d1/llmkit-shared';
|
|
2
|
+
export class CostTracker {
|
|
3
|
+
entries = [];
|
|
4
|
+
listeners = [];
|
|
5
|
+
shouldLog;
|
|
6
|
+
constructor(config = {}) {
|
|
7
|
+
this.shouldLog = config.log ?? false;
|
|
8
|
+
if (config.onTrack)
|
|
9
|
+
this.listeners.push(config.onTrack);
|
|
10
|
+
}
|
|
11
|
+
track(provider, model, usage) {
|
|
12
|
+
const costDollars = calculateCost(provider, model, usage.inputTokens, usage.outputTokens, usage.cacheReadTokens ?? 0, usage.cacheWriteTokens ?? 0);
|
|
13
|
+
const entry = {
|
|
14
|
+
provider,
|
|
15
|
+
model,
|
|
16
|
+
inputTokens: usage.inputTokens,
|
|
17
|
+
outputTokens: usage.outputTokens,
|
|
18
|
+
cacheReadTokens: usage.cacheReadTokens ?? 0,
|
|
19
|
+
cacheWriteTokens: usage.cacheWriteTokens ?? 0,
|
|
20
|
+
costCents: +(costDollars * 100).toFixed(4),
|
|
21
|
+
sessionId: usage.sessionId,
|
|
22
|
+
timestamp: new Date(),
|
|
23
|
+
};
|
|
24
|
+
this.entries.push(entry);
|
|
25
|
+
this.emit(entry);
|
|
26
|
+
return entry;
|
|
27
|
+
}
|
|
28
|
+
// accepts a raw response from OpenAI SDK (prompt_tokens) or Anthropic SDK (input_tokens)
|
|
29
|
+
trackResponse(provider, response) {
|
|
30
|
+
const { model, usage } = response;
|
|
31
|
+
if ('prompt_tokens' in usage) {
|
|
32
|
+
return this.track(provider, model, {
|
|
33
|
+
inputTokens: usage.prompt_tokens,
|
|
34
|
+
outputTokens: usage.completion_tokens,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return this.track(provider, model, {
|
|
38
|
+
inputTokens: usage.input_tokens,
|
|
39
|
+
outputTokens: usage.output_tokens,
|
|
40
|
+
cacheReadTokens: usage.cache_read_input_tokens,
|
|
41
|
+
cacheWriteTokens: usage.cache_creation_input_tokens,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
on(listener) {
|
|
45
|
+
this.listeners.push(listener);
|
|
46
|
+
return () => {
|
|
47
|
+
const idx = this.listeners.indexOf(listener);
|
|
48
|
+
if (idx >= 0)
|
|
49
|
+
this.listeners.splice(idx, 1);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
get totalCents() {
|
|
53
|
+
return this.entries.reduce((sum, e) => sum + e.costCents, 0);
|
|
54
|
+
}
|
|
55
|
+
get totalDollars() {
|
|
56
|
+
return (this.totalCents / 100).toFixed(4);
|
|
57
|
+
}
|
|
58
|
+
get requestCount() {
|
|
59
|
+
return this.entries.length;
|
|
60
|
+
}
|
|
61
|
+
byProvider() {
|
|
62
|
+
return this.groupBy((e) => e.provider);
|
|
63
|
+
}
|
|
64
|
+
byModel() {
|
|
65
|
+
return this.groupBy((e) => e.model);
|
|
66
|
+
}
|
|
67
|
+
bySession() {
|
|
68
|
+
return this.groupBy((e) => e.sessionId || 'default');
|
|
69
|
+
}
|
|
70
|
+
summary() {
|
|
71
|
+
const lines = [
|
|
72
|
+
`LLMKit Cost Summary`,
|
|
73
|
+
`---`,
|
|
74
|
+
`Total: $${this.totalDollars} (${this.requestCount} requests)`,
|
|
75
|
+
'',
|
|
76
|
+
];
|
|
77
|
+
const providers = this.byProvider();
|
|
78
|
+
if (Object.keys(providers).length > 1) {
|
|
79
|
+
lines.push('By provider:');
|
|
80
|
+
for (const [name, b] of Object.entries(providers)) {
|
|
81
|
+
lines.push(` ${name}: $${fmtCents(b.cents)} (${b.requests} reqs)`);
|
|
82
|
+
}
|
|
83
|
+
lines.push('');
|
|
84
|
+
}
|
|
85
|
+
const models = this.byModel();
|
|
86
|
+
lines.push('By model:');
|
|
87
|
+
for (const [name, b] of Object.entries(models)) {
|
|
88
|
+
lines.push(` ${name}: $${fmtCents(b.cents)} (${b.requests} reqs)`);
|
|
89
|
+
}
|
|
90
|
+
return lines.join('\n');
|
|
91
|
+
}
|
|
92
|
+
reset() {
|
|
93
|
+
this.entries = [];
|
|
94
|
+
}
|
|
95
|
+
emit(entry) {
|
|
96
|
+
if (this.shouldLog) {
|
|
97
|
+
const cache = entry.cacheReadTokens > 0 ? `, ${entry.cacheReadTokens} cached` : '';
|
|
98
|
+
console.log(`[llmkit] ${entry.provider}/${entry.model}: $${fmtCents(entry.costCents)} ` +
|
|
99
|
+
`(${entry.inputTokens} in, ${entry.outputTokens} out${cache})`);
|
|
100
|
+
}
|
|
101
|
+
for (const fn of this.listeners)
|
|
102
|
+
fn(entry);
|
|
103
|
+
}
|
|
104
|
+
groupBy(keyFn) {
|
|
105
|
+
const out = {};
|
|
106
|
+
for (const e of this.entries) {
|
|
107
|
+
const key = keyFn(e);
|
|
108
|
+
const b = out[key] || { cents: 0, requests: 0, inputTokens: 0, outputTokens: 0 };
|
|
109
|
+
b.cents += e.costCents;
|
|
110
|
+
b.requests++;
|
|
111
|
+
b.inputTokens += e.inputTokens;
|
|
112
|
+
b.outputTokens += e.outputTokens;
|
|
113
|
+
out[key] = b;
|
|
114
|
+
}
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function fmtCents(cents) {
|
|
119
|
+
return (cents / 100).toFixed(4);
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../src/tracker.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@f3d1/llmkit-sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "TypeScript SDK for LLMKit - cost tracking, provider routing, budget enforcement",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": ["dist"],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsc --watch",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"clean": "rm -rf dist"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@f3d1/llmkit-shared": "workspace:*"
|
|
24
|
+
}
|
|
25
|
+
}
|