@degreesign/chat 0.0.0-stage → 0.1.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.
@@ -0,0 +1 @@
1
+ /*! MIT License. DegreeSign Chat SDK */
@@ -0,0 +1,4 @@
1
+ import type { Runtime, RuntimeDeps } from './types';
2
+ declare const createRuntime: (deps?: RuntimeDeps) => Runtime;
3
+ declare const runtime: Runtime;
4
+ export { createRuntime, runtime };
@@ -0,0 +1,270 @@
1
+ import type { ChatModelId, ChatStatus, LlmBackend, LlmPhase, LlmRole, LlmStatus } from './enums';
2
+ /** One chat message, owned by the host */
3
+ interface ChatMessage {
4
+ role: LlmRole;
5
+ content: string;
6
+ /** Image data URLs or URLs attached to the turn */
7
+ images?: string[];
8
+ }
9
+ /** One on-device model */
10
+ interface ChatModel {
11
+ /** Stable catalog id, passed by the host */
12
+ id: ChatModelId;
13
+ /** Whether the model supports chain-of-thought reasoning */
14
+ reasoning: boolean;
15
+ /** wllama (CPU) artifact */
16
+ cpu: {
17
+ repo: string;
18
+ file: string;
19
+ /** Vision projector, present when the CPU build accepts images */
20
+ mmproj?: {
21
+ file: string;
22
+ };
23
+ };
24
+ }
25
+ /** Token, prompt and thread budgets of an on-device generation */
26
+ interface LlmLimits {
27
+ /** Max answer tokens */
28
+ maxReplyTokens: number;
29
+ /** Max chain-of-thought tokens, used by the CPU engine when it loads */
30
+ maxThinkingTokens: number;
31
+ /** Total output budget when reasoning is on, thinking plus answer */
32
+ maxReasoningTokens: number;
33
+ /** Max images sent in one prompt */
34
+ maxImages: number;
35
+ /** Max characters kept per message */
36
+ maxContentLength: number;
37
+ /** Max characters of the whole prompt */
38
+ promptCharBudget: number;
39
+ /** Max CPU threads, applied after the hardware maximum */
40
+ maxThreads: number;
41
+ }
42
+ /** Current model and request state reported to the host */
43
+ interface ChatStatusSnapshot {
44
+ /** Availability derived from the engine status */
45
+ availability: ChatStatus;
46
+ status: LlmStatus;
47
+ backend: LlmBackend;
48
+ /** Whether the requested model accepts images on this backend */
49
+ supportsImages: boolean;
50
+ ready: boolean;
51
+ loading: boolean;
52
+ /** Whether a reply is streaming right now */
53
+ requesting: boolean;
54
+ phase: LlmPhase;
55
+ /** Download or load progress, 0..100 */
56
+ percent: number;
57
+ /** Last request error, cleared when a reply starts */
58
+ error?: string;
59
+ }
60
+ /** One chat request, invoked for every response */
61
+ interface ChatInput {
62
+ /** On-device model that answers this request */
63
+ model: ChatModelId;
64
+ /** Complete prompt, including the system and user turns */
65
+ messages: ChatMessage[];
66
+ /** Override any token, prompt or thread budget */
67
+ limits?: Partial<LlmLimits>;
68
+ /** Whether the model may use chain-of-thought reasoning, defaults to off */
69
+ reasoning?: boolean;
70
+ /** Whether package and engine logs reach the console, defaults to off */
71
+ logging?: boolean;
72
+ /** Accumulated reasoning text, streamed while the model thinks */
73
+ onThinking?: (text: string) => void;
74
+ /** Accumulated reply text, streamed while the model answers */
75
+ onResponse: (text: string) => void;
76
+ /** Model and request state, reported on every change */
77
+ onStatus?: (snapshot: ChatStatusSnapshot) => void;
78
+ }
79
+ /** Stop the current request, its model load, or free the loaded model */
80
+ type CancelChat = () => void;
81
+ /** wllama wasm assets used by the CPU engine */
82
+ interface WllamaAssets {
83
+ /** URL of the wllama wasm binary */
84
+ wasm: string;
85
+ /** URL of the wllama compat wasm binary */
86
+ compatWasm: string;
87
+ /** URL of the wllama compat worker script */
88
+ compatWorker: string;
89
+ }
90
+ /** One live chat request */
91
+ interface ActiveCall {
92
+ token: number;
93
+ input: ChatInput;
94
+ controller: AbortController;
95
+ percent: number;
96
+ phase: LlmPhase;
97
+ requesting: boolean;
98
+ cancelled: boolean;
99
+ error?: string;
100
+ }
101
+ /** Engine and backend overrides used by tests */
102
+ interface RuntimeDeps {
103
+ engines?: {
104
+ cpu?: LlmEngine;
105
+ };
106
+ backend?: LlmBackend;
107
+ }
108
+ /** One model load request */
109
+ interface RuntimeLoadParams {
110
+ model: ChatModel;
111
+ limits: LlmLimits;
112
+ assets?: Partial<WllamaAssets>;
113
+ /** Whether engine logs reach the console */
114
+ logging?: boolean;
115
+ onProgress: (progress: number, phase: LlmPhase) => void;
116
+ }
117
+ /** One generation request */
118
+ interface RuntimeChatParams {
119
+ messages: ChatMessage[];
120
+ limits: LlmLimits;
121
+ reasoning: boolean;
122
+ /** Whether engine logs reach the console */
123
+ logging?: boolean;
124
+ onReason: (text: string) => void;
125
+ onText: (text: string) => void;
126
+ signal?: AbortSignal;
127
+ }
128
+ /** On-device runtime shared by every request */
129
+ interface Runtime {
130
+ load: (params: RuntimeLoadParams) => Promise<boolean>;
131
+ chat: (params: RuntimeChatParams) => Promise<string | undefined>;
132
+ unload: () => Promise<void>;
133
+ cancelLoad: () => void;
134
+ ready: () => boolean;
135
+ loading: () => boolean;
136
+ status: () => LlmStatus;
137
+ backend: () => LlmBackend;
138
+ /** Model currently loaded on this runtime */
139
+ model: () => ChatModel | undefined;
140
+ }
141
+ /** Params for a single on-device chat generation */
142
+ interface EngineChatParams {
143
+ messages: ChatMessage[];
144
+ limits: LlmLimits;
145
+ /** User preference, off unless explicitly turned on */
146
+ reasoning: boolean;
147
+ /** Whether engine logs reach the console */
148
+ logging?: boolean;
149
+ /** Streamed reasoning delta */
150
+ onReason: (text: string) => void;
151
+ /** Streamed reply delta */
152
+ onText: (text: string) => void;
153
+ signal?: AbortSignal;
154
+ }
155
+ /** Params of the engine startLLM */
156
+ interface StartLlmParams {
157
+ model: ChatModel;
158
+ /** Engine-level budgets, read when the model loads */
159
+ limits: LlmLimits;
160
+ /** Report download and load progress 0..1 */
161
+ onProgress: (progress: number, phase?: LlmPhase) => void;
162
+ /** Stop a download or load that is no longer wanted */
163
+ signal?: AbortSignal;
164
+ /** Whether engine logs reach the console */
165
+ logging?: boolean;
166
+ /** CPU engine asset override */
167
+ assets?: Partial<WllamaAssets>;
168
+ }
169
+ /** Unified object returned by the engine startLLM */
170
+ interface LlmRuntime {
171
+ /** Model this runtime serves */
172
+ model: ChatModel;
173
+ /** Backend that accepted the model */
174
+ backend: LlmBackend;
175
+ /** Context window requested from the engine */
176
+ contextSize: number;
177
+ /** Stream one reply, returning the final text or undefined when stopped */
178
+ chat: (params: EngineChatParams) => Promise<string | undefined>;
179
+ /** Release the model from memory, keeping its cache */
180
+ unload: () => Promise<void>;
181
+ }
182
+ /** A model runner backed by one inference engine */
183
+ interface LlmEngine {
184
+ backend: LlmBackend;
185
+ /** Download (if needed) and load a model, returning its runtime */
186
+ startLLM: (params: StartLlmParams) => Promise<LlmRuntime>;
187
+ /** Whether the model files are already fully stored on this device */
188
+ cached: (model: ChatModel) => Promise<boolean>;
189
+ /** Whether this engine holds any cache, checked before loading the engine */
190
+ hasCache: () => Promise<boolean>;
191
+ /** Delete the model's on-device cache */
192
+ remove: (model: ChatModel) => Promise<void>;
193
+ /** Delete every on-device artifact this engine keeps, including orphans */
194
+ purge: () => Promise<void>;
195
+ }
196
+ /** One text or image segment of a user turn */
197
+ type EngineContentPart = {
198
+ type: `text`;
199
+ text: string;
200
+ } | {
201
+ type: `image`;
202
+ url: string;
203
+ };
204
+ /** One wllama content segment */
205
+ type WllamaContentPart = {
206
+ type: `text`;
207
+ text: string;
208
+ } | {
209
+ type: `image`;
210
+ data: ArrayBuffer;
211
+ };
212
+ /** One wllama chat turn */
213
+ type WllamaMessage = {
214
+ role: `system`;
215
+ content: string;
216
+ } | {
217
+ role: `user`;
218
+ content: string | WllamaContentPart[];
219
+ } | {
220
+ role: `assistant`;
221
+ content: string;
222
+ };
223
+ /** One OpenAI-style message */
224
+ type EngineMessage = {
225
+ role: `system`;
226
+ content: string;
227
+ } | {
228
+ role: `user`;
229
+ content: string | EngineContentPart[];
230
+ } | {
231
+ role: `assistant`;
232
+ content: string;
233
+ };
234
+ /** Streamed delta, reasoning may be inline or structured */
235
+ interface EngineDelta {
236
+ content?: string;
237
+ reasoning?: string;
238
+ reasoning_content?: string;
239
+ }
240
+ /** Streamed chunk as the engine shapes it */
241
+ interface EngineChunk {
242
+ choices?: Array<{
243
+ finish_reason?: string;
244
+ delta?: EngineDelta;
245
+ }>;
246
+ }
247
+ /** Params of one streamed reply */
248
+ interface StreamReplyParams {
249
+ model: ChatModel;
250
+ /** Streamed reasoning delta */
251
+ onReason: (text: string) => void;
252
+ /** Streamed reply delta */
253
+ onText: (text: string) => void;
254
+ /** Open the engine stream for the prepared messages */
255
+ start: () => Promise<AsyncIterable<unknown>>;
256
+ /** Whether the caller stopped the generation */
257
+ stopped: () => boolean;
258
+ /** Whether engine logs reach the console */
259
+ logging?: boolean;
260
+ }
261
+ /** Params of one engine chat call */
262
+ interface EngineRunParams {
263
+ model: ChatModel;
264
+ params: EngineChatParams;
265
+ /** Open the engine stream for the prepared messages */
266
+ start: (messages: EngineMessage[]) => Promise<AsyncIterable<unknown>>;
267
+ /** Whether the caller stopped the generation */
268
+ stopped: () => boolean;
269
+ }
270
+ export type { ChatMessage, ChatModel, LlmLimits, ChatStatusSnapshot, ChatInput, CancelChat, WllamaAssets, ActiveCall, RuntimeDeps, RuntimeLoadParams, RuntimeChatParams, Runtime, EngineChatParams, StartLlmParams, LlmRuntime, LlmEngine, EngineMessage, EngineContentPart, WllamaContentPart, WllamaMessage, EngineDelta, EngineChunk, StreamReplyParams, EngineRunParams, };
package/package.json CHANGED
@@ -1,6 +1,73 @@
1
1
  {
2
- "name": "@degreesign/chat",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
2
+ "name": "@degreesign/chat",
3
+ "version": "0.1.1",
4
+ "description": "Headless on-device AI chat for browsers, workers and Node with a wllama CPU engine",
5
+ "main": "dist/node/chat.node.min.js",
6
+ "module": "dist/browser/chat.min.mjs",
7
+ "browser": "dist/browser/chat.min.mjs",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "browser": "./dist/browser/chat.min.mjs",
13
+ "node": {
14
+ "import": "./dist/node/chat.node.min.mjs",
15
+ "require": "./dist/node/chat.node.min.js"
16
+ },
17
+ "default": "./dist/node/chat.node.min.mjs"
18
+ },
19
+ "./dist/*": "./dist/*",
20
+ "./package.json": "./package.json"
21
+ },
22
+ "sideEffects": false,
23
+ "scripts": {
24
+ "build": "tsc --emitDeclarationOnly && webpack && node scripts/banner-wllama.cjs",
25
+ "typecheck": "tsc --noEmit",
26
+ "verify:node": "node test/node.cjs"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/DegreeSign/ds_chat.git"
31
+ },
32
+ "keywords": [
33
+ "ai chat",
34
+ "chat",
35
+ "llm",
36
+ "on-device",
37
+ "local inference",
38
+ "wllama",
39
+ "typescript",
40
+ "browser",
41
+ "node",
42
+ "react",
43
+ "degreesign"
44
+ ],
45
+ "author": "DegreeSign",
46
+ "license": "MIT",
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "bugs": {
51
+ "url": "https://github.com/DegreeSign/ds_chat/issues"
52
+ },
53
+ "homepage": "https://github.com/DegreeSign/ds_chat#readme",
54
+ "engines": {
55
+ "node": ">=24"
56
+ },
57
+ "files": [
58
+ "dist/"
59
+ ],
60
+ "dependencies": {
61
+ "@wllama/wllama": "^3.8.1",
62
+ "@wllama/wllama-compat": "^3.8.1"
63
+ },
64
+ "devDependencies": {
65
+ "@types/node": "^24.0.0",
66
+ "terser-webpack-plugin": "^5.3.11",
67
+ "ts-loader": "^9.5.1",
68
+ "ts-node": "^10.9.2",
69
+ "typescript": "^5.9.0",
70
+ "webpack": "^5.97.1",
71
+ "webpack-cli": "^6.0.1"
72
+ }
6
73
  }