@halo-sdk/adapters 1.0.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,5 @@
1
+ # @halo-sdk/adapters
2
+
3
+ Model adapters for Halo AI SDK.
4
+
5
+ - `DeepSeekAdapter` — DeepSeek API adapter with prefix cache support
@@ -0,0 +1,23 @@
1
+ import type { ChatMessage, ToolCall, ToolSpec, Usage, TurnChunk } from "@halo-sdk/core";
2
+ import type { ModelAdapter, ModelCapabilities, PricingInfo } from "@halo-sdk/core";
3
+ export declare class DeepSeekAdapter implements ModelAdapter {
4
+ readonly modelId: string;
5
+ readonly contextWindow = 128000;
6
+ readonly capabilities: ModelCapabilities;
7
+ /** DeepSeek pricing (USD per 1K tokens). */
8
+ readonly pricing: PricingInfo;
9
+ private _apiKey;
10
+ private _baseUrl;
11
+ constructor(opts: {
12
+ apiKey: string;
13
+ model?: string;
14
+ baseUrl?: string;
15
+ });
16
+ chat(prefix: ChatMessage[], history: ChatMessage[], tools?: ToolSpec[]): Promise<{
17
+ content: string;
18
+ toolCalls: ToolCall[];
19
+ usage: Usage;
20
+ }>;
21
+ stream(prefix: ChatMessage[], history: ChatMessage[], tools?: ToolSpec[]): AsyncGenerator<TurnChunk>;
22
+ }
23
+ //# sourceMappingURL=deepseek.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepseek.d.ts","sourceRoot":"","sources":["../src/deepseek.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACxF,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEnF,qBAAa,eAAgB,YAAW,YAAY;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,UAAW;IACjC,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAGtC;IAEF,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,WAAW,CAG3B;IAEF,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAMhE,IAAI,CACR,MAAM,EAAE,WAAW,EAAE,EACrB,OAAO,EAAE,WAAW,EAAE,EACtB,KAAK,CAAC,EAAE,QAAQ,EAAE,GACjB,OAAO,CAAC;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,QAAQ,EAAE,CAAC;QACtB,KAAK,EAAE,KAAK,CAAC;KACd,CAAC;IAiDK,MAAM,CACX,MAAM,EAAE,WAAW,EAAE,EACrB,OAAO,EAAE,WAAW,EAAE,EACtB,KAAK,CAAC,EAAE,QAAQ,EAAE,GACjB,cAAc,CAAC,SAAS,CAAC;CA4F7B"}
@@ -0,0 +1,153 @@
1
+ export class DeepSeekAdapter {
2
+ modelId;
3
+ contextWindow = 128_000;
4
+ capabilities = {
5
+ toolUse: true,
6
+ streaming: true,
7
+ };
8
+ /** DeepSeek pricing (USD per 1K tokens). */
9
+ pricing = {
10
+ inputPricePer1k: 0.00027,
11
+ cachedInputPricePer1k: 0.00007,
12
+ };
13
+ _apiKey;
14
+ _baseUrl;
15
+ constructor(opts) {
16
+ this._apiKey = opts.apiKey;
17
+ this.modelId = opts.model ?? "deepseek-v4-flash";
18
+ this._baseUrl = (opts.baseUrl ?? "https://api.deepseek.com").replace(/\/+$/, "");
19
+ }
20
+ async chat(prefix, history, tools) {
21
+ const messages = [...prefix, ...history];
22
+ const body = {
23
+ model: this.modelId,
24
+ messages,
25
+ stream: false,
26
+ };
27
+ if (tools?.length)
28
+ body.tools = tools;
29
+ const resp = await fetch(`${this._baseUrl}/chat/completions`, {
30
+ method: "POST",
31
+ headers: {
32
+ Authorization: `Bearer ${this._apiKey}`,
33
+ "Content-Type": "application/json",
34
+ },
35
+ body: JSON.stringify(body),
36
+ });
37
+ if (!resp.ok) {
38
+ throw new Error(`DeepSeek ${resp.status}: ${await resp.text()}`);
39
+ }
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ const data = await resp.json();
42
+ const choice = data.choices?.[0]?.message;
43
+ const usageRaw = data.usage;
44
+ const content = choice?.content ?? "";
45
+ const toolCalls = choice?.tool_calls ?? [];
46
+ const promptTokens = usageRaw?.prompt_tokens ?? 0;
47
+ const completionTokens = usageRaw?.completion_tokens ?? 0;
48
+ const cacheHit = usageRaw?.prompt_cache_hit_tokens ?? 0;
49
+ const cacheMiss = usageRaw?.prompt_cache_miss_tokens ?? Math.max(0, promptTokens - cacheHit);
50
+ const usage = {
51
+ promptTokens,
52
+ completionTokens,
53
+ caching: {
54
+ hitTokens: cacheHit,
55
+ missTokens: cacheMiss,
56
+ hitRate: cacheHit + cacheMiss > 0 ? cacheHit / (cacheHit + cacheMiss) : 0,
57
+ },
58
+ };
59
+ return { content, toolCalls, usage };
60
+ }
61
+ async *stream(prefix, history, tools) {
62
+ const messages = [...prefix, ...history];
63
+ const body = {
64
+ model: this.modelId,
65
+ messages,
66
+ stream: true,
67
+ stream_options: { include_usage: true },
68
+ };
69
+ if (tools?.length)
70
+ body.tools = tools;
71
+ const resp = await fetch(`${this._baseUrl}/chat/completions`, {
72
+ method: "POST",
73
+ headers: {
74
+ Authorization: `Bearer ${this._apiKey}`,
75
+ "Content-Type": "application/json",
76
+ Accept: "text/event-stream",
77
+ },
78
+ body: JSON.stringify(body),
79
+ });
80
+ if (!resp.ok || !resp.body) {
81
+ throw new Error(`DeepSeek ${resp.status}: ${await resp.text().catch(() => "")}`);
82
+ }
83
+ const reader = resp.body.getReader();
84
+ const decoder = new TextDecoder();
85
+ let buffer = "";
86
+ try {
87
+ while (true) {
88
+ const { value, done } = await reader.read();
89
+ if (done)
90
+ break;
91
+ buffer += decoder.decode(value, { stream: true });
92
+ const lines = buffer.split("\n");
93
+ buffer = lines.pop() ?? "";
94
+ for (const line of lines) {
95
+ const trimmed = line.trim();
96
+ if (!trimmed || !trimmed.startsWith("data: "))
97
+ continue;
98
+ const data = trimmed.slice(6);
99
+ if (data === "[DONE]") {
100
+ yield { type: "done", usage: { promptTokens: 0, completionTokens: 0 } };
101
+ return;
102
+ }
103
+ try {
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ const json = JSON.parse(data);
106
+ const delta = json.choices?.[0]?.delta;
107
+ if (delta?.content) {
108
+ yield { type: "text-delta", delta: String(delta.content) };
109
+ }
110
+ const toolCalls = delta?.tool_calls;
111
+ if (toolCalls) {
112
+ for (let i = 0; i < toolCalls.length; i++) {
113
+ const tc = toolCalls[i];
114
+ yield {
115
+ type: "tool-call-delta",
116
+ index: typeof tc.index === "number" ? tc.index : i,
117
+ name: tc.function ? String(tc.function.name ?? "") : undefined,
118
+ argumentsDelta: tc.function ? String(tc.function.arguments ?? "") : undefined,
119
+ };
120
+ }
121
+ }
122
+ const usageRaw = json.usage;
123
+ if (usageRaw) {
124
+ const promptTokens = usageRaw.prompt_tokens ?? 0;
125
+ const completionTokens = usageRaw.completion_tokens ?? 0;
126
+ const cacheHit = usageRaw.prompt_cache_hit_tokens ?? 0;
127
+ const cacheMiss = usageRaw.prompt_cache_miss_tokens ?? Math.max(0, promptTokens - cacheHit);
128
+ yield {
129
+ type: "done",
130
+ usage: {
131
+ promptTokens,
132
+ completionTokens,
133
+ caching: {
134
+ hitTokens: cacheHit,
135
+ missTokens: cacheMiss,
136
+ hitRate: cacheHit + cacheMiss > 0 ? cacheHit / (cacheHit + cacheMiss) : 0,
137
+ },
138
+ },
139
+ };
140
+ }
141
+ }
142
+ catch {
143
+ /* skip malformed SSE frame */
144
+ }
145
+ }
146
+ }
147
+ }
148
+ finally {
149
+ reader.releaseLock();
150
+ }
151
+ }
152
+ }
153
+ //# sourceMappingURL=deepseek.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepseek.js","sourceRoot":"","sources":["../src/deepseek.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { DeepSeekAdapter } from "./deepseek.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { DeepSeekAdapter } from "./deepseek.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@halo-sdk/adapters",
3
+ "version": "1.0.0",
4
+ "description": "Model adapters for Halo AI SDK — DeepSeek API with prefix cache support",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "ai",
8
+ "llm",
9
+ "deepseek",
10
+ "adapter",
11
+ "prefix-cache"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/halo-sdk/halo-ai",
16
+ "directory": "packages/adapters"
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "type": "module",
22
+ "main": "./dist/index.js",
23
+ "types": "./dist/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.js"
28
+ }
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "peerDependencies": {
34
+ "@halo-sdk/core": ">=1.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "typescript": "^5.8.0",
38
+ "vitest": "^3.0.0",
39
+ "@halo-sdk/core": "1.0.0"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "dev": "tsc --watch",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest"
46
+ }
47
+ }