peerllm-host-cli 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.
Files changed (190) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +83 -0
  3. package/dist/cli/commands/agreement.d.ts +3 -0
  4. package/dist/cli/commands/agreement.d.ts.map +1 -0
  5. package/dist/cli/commands/agreement.js +151 -0
  6. package/dist/cli/commands/agreement.js.map +1 -0
  7. package/dist/cli/commands/config.d.ts +3 -0
  8. package/dist/cli/commands/config.d.ts.map +1 -0
  9. package/dist/cli/commands/config.js +163 -0
  10. package/dist/cli/commands/config.js.map +1 -0
  11. package/dist/cli/commands/diagnostics.d.ts +3 -0
  12. package/dist/cli/commands/diagnostics.d.ts.map +1 -0
  13. package/dist/cli/commands/diagnostics.js +131 -0
  14. package/dist/cli/commands/diagnostics.js.map +1 -0
  15. package/dist/cli/commands/doctor.d.ts +3 -0
  16. package/dist/cli/commands/doctor.d.ts.map +1 -0
  17. package/dist/cli/commands/doctor.js +349 -0
  18. package/dist/cli/commands/doctor.js.map +1 -0
  19. package/dist/cli/commands/events.d.ts +3 -0
  20. package/dist/cli/commands/events.d.ts.map +1 -0
  21. package/dist/cli/commands/events.js +51 -0
  22. package/dist/cli/commands/events.js.map +1 -0
  23. package/dist/cli/commands/host.d.ts +3 -0
  24. package/dist/cli/commands/host.d.ts.map +1 -0
  25. package/dist/cli/commands/host.js +252 -0
  26. package/dist/cli/commands/host.js.map +1 -0
  27. package/dist/cli/commands/login.d.ts +3 -0
  28. package/dist/cli/commands/login.d.ts.map +1 -0
  29. package/dist/cli/commands/login.js +51 -0
  30. package/dist/cli/commands/login.js.map +1 -0
  31. package/dist/cli/commands/logout.d.ts +3 -0
  32. package/dist/cli/commands/logout.d.ts.map +1 -0
  33. package/dist/cli/commands/logout.js +28 -0
  34. package/dist/cli/commands/logout.js.map +1 -0
  35. package/dist/cli/commands/logs.d.ts +3 -0
  36. package/dist/cli/commands/logs.d.ts.map +1 -0
  37. package/dist/cli/commands/logs.js +157 -0
  38. package/dist/cli/commands/logs.js.map +1 -0
  39. package/dist/cli/commands/models.d.ts +3 -0
  40. package/dist/cli/commands/models.d.ts.map +1 -0
  41. package/dist/cli/commands/models.js +227 -0
  42. package/dist/cli/commands/models.js.map +1 -0
  43. package/dist/cli/commands/register.d.ts +3 -0
  44. package/dist/cli/commands/register.d.ts.map +1 -0
  45. package/dist/cli/commands/register.js +48 -0
  46. package/dist/cli/commands/register.js.map +1 -0
  47. package/dist/cli/commands/restart.d.ts +3 -0
  48. package/dist/cli/commands/restart.d.ts.map +1 -0
  49. package/dist/cli/commands/restart.js +66 -0
  50. package/dist/cli/commands/restart.js.map +1 -0
  51. package/dist/cli/commands/service.d.ts +3 -0
  52. package/dist/cli/commands/service.d.ts.map +1 -0
  53. package/dist/cli/commands/service.js +194 -0
  54. package/dist/cli/commands/service.js.map +1 -0
  55. package/dist/cli/commands/setup.d.ts +3 -0
  56. package/dist/cli/commands/setup.d.ts.map +1 -0
  57. package/dist/cli/commands/setup.js +242 -0
  58. package/dist/cli/commands/setup.js.map +1 -0
  59. package/dist/cli/commands/start.d.ts +3 -0
  60. package/dist/cli/commands/start.d.ts.map +1 -0
  61. package/dist/cli/commands/start.js +125 -0
  62. package/dist/cli/commands/start.js.map +1 -0
  63. package/dist/cli/commands/status.d.ts +3 -0
  64. package/dist/cli/commands/status.d.ts.map +1 -0
  65. package/dist/cli/commands/status.js +76 -0
  66. package/dist/cli/commands/status.js.map +1 -0
  67. package/dist/cli/commands/stop.d.ts +3 -0
  68. package/dist/cli/commands/stop.d.ts.map +1 -0
  69. package/dist/cli/commands/stop.js +46 -0
  70. package/dist/cli/commands/stop.js.map +1 -0
  71. package/dist/cli/commands/subscription.d.ts +3 -0
  72. package/dist/cli/commands/subscription.d.ts.map +1 -0
  73. package/dist/cli/commands/subscription.js +342 -0
  74. package/dist/cli/commands/subscription.js.map +1 -0
  75. package/dist/cli/exit-codes.d.ts +12 -0
  76. package/dist/cli/exit-codes.d.ts.map +1 -0
  77. package/dist/cli/exit-codes.js +11 -0
  78. package/dist/cli/exit-codes.js.map +1 -0
  79. package/dist/cli/format.d.ts +8 -0
  80. package/dist/cli/format.d.ts.map +1 -0
  81. package/dist/cli/format.js +22 -0
  82. package/dist/cli/format.js.map +1 -0
  83. package/dist/cli/index.d.ts +3 -0
  84. package/dist/cli/index.d.ts.map +1 -0
  85. package/dist/cli/index.js +88 -0
  86. package/dist/cli/index.js.map +1 -0
  87. package/dist/cli/ipc-client.d.ts +20 -0
  88. package/dist/cli/ipc-client.d.ts.map +1 -0
  89. package/dist/cli/ipc-client.js +101 -0
  90. package/dist/cli/ipc-client.js.map +1 -0
  91. package/dist/cli/prompts.d.ts +5 -0
  92. package/dist/cli/prompts.d.ts.map +1 -0
  93. package/dist/cli/prompts.js +68 -0
  94. package/dist/cli/prompts.js.map +1 -0
  95. package/dist/cli/services.d.ts +18 -0
  96. package/dist/cli/services.d.ts.map +1 -0
  97. package/dist/cli/services.js +16 -0
  98. package/dist/cli/services.js.map +1 -0
  99. package/dist/core/auth.d.ts +24 -0
  100. package/dist/core/auth.d.ts.map +1 -0
  101. package/dist/core/auth.js +111 -0
  102. package/dist/core/auth.js.map +1 -0
  103. package/dist/core/backend-client.d.ts +33 -0
  104. package/dist/core/backend-client.d.ts.map +1 -0
  105. package/dist/core/backend-client.js +79 -0
  106. package/dist/core/backend-client.js.map +1 -0
  107. package/dist/core/config.d.ts +21 -0
  108. package/dist/core/config.d.ts.map +1 -0
  109. package/dist/core/config.js +98 -0
  110. package/dist/core/config.js.map +1 -0
  111. package/dist/core/events.d.ts +23 -0
  112. package/dist/core/events.d.ts.map +1 -0
  113. package/dist/core/events.js +15 -0
  114. package/dist/core/events.js.map +1 -0
  115. package/dist/core/fs-lock.d.ts +13 -0
  116. package/dist/core/fs-lock.d.ts.map +1 -0
  117. package/dist/core/fs-lock.js +52 -0
  118. package/dist/core/fs-lock.js.map +1 -0
  119. package/dist/core/jsonrpc.d.ts +55 -0
  120. package/dist/core/jsonrpc.d.ts.map +1 -0
  121. package/dist/core/jsonrpc.js +59 -0
  122. package/dist/core/jsonrpc.js.map +1 -0
  123. package/dist/core/logger.d.ts +28 -0
  124. package/dist/core/logger.d.ts.map +1 -0
  125. package/dist/core/logger.js +80 -0
  126. package/dist/core/logger.js.map +1 -0
  127. package/dist/core/model-info.d.ts +11 -0
  128. package/dist/core/model-info.d.ts.map +1 -0
  129. package/dist/core/model-info.js +137 -0
  130. package/dist/core/model-info.js.map +1 -0
  131. package/dist/core/models-fs.d.ts +6 -0
  132. package/dist/core/models-fs.d.ts.map +1 -0
  133. package/dist/core/models-fs.js +21 -0
  134. package/dist/core/models-fs.js.map +1 -0
  135. package/dist/core/orchestrator.d.ts +42 -0
  136. package/dist/core/orchestrator.d.ts.map +1 -0
  137. package/dist/core/orchestrator.js +304 -0
  138. package/dist/core/orchestrator.js.map +1 -0
  139. package/dist/core/paths.d.ts +17 -0
  140. package/dist/core/paths.d.ts.map +1 -0
  141. package/dist/core/paths.js +51 -0
  142. package/dist/core/paths.js.map +1 -0
  143. package/dist/core/redact.d.ts +3 -0
  144. package/dist/core/redact.d.ts.map +1 -0
  145. package/dist/core/redact.js +27 -0
  146. package/dist/core/redact.js.map +1 -0
  147. package/dist/core/secrets.d.ts +12 -0
  148. package/dist/core/secrets.d.ts.map +1 -0
  149. package/dist/core/secrets.js +66 -0
  150. package/dist/core/secrets.js.map +1 -0
  151. package/dist/core/shared-runner.d.ts +70 -0
  152. package/dist/core/shared-runner.d.ts.map +1 -0
  153. package/dist/core/shared-runner.js +450 -0
  154. package/dist/core/shared-runner.js.map +1 -0
  155. package/dist/core/subscription.d.ts +53 -0
  156. package/dist/core/subscription.d.ts.map +1 -0
  157. package/dist/core/subscription.js +117 -0
  158. package/dist/core/subscription.js.map +1 -0
  159. package/dist/daemon/index.d.ts +3 -0
  160. package/dist/daemon/index.d.ts.map +1 -0
  161. package/dist/daemon/index.js +22 -0
  162. package/dist/daemon/index.js.map +1 -0
  163. package/dist/daemon/ipc-server.d.ts +33 -0
  164. package/dist/daemon/ipc-server.d.ts.map +1 -0
  165. package/dist/daemon/ipc-server.js +202 -0
  166. package/dist/daemon/ipc-server.js.map +1 -0
  167. package/dist/daemon/methods.d.ts +17 -0
  168. package/dist/daemon/methods.d.ts.map +1 -0
  169. package/dist/daemon/methods.js +68 -0
  170. package/dist/daemon/methods.js.map +1 -0
  171. package/dist/daemon/pid-lock.d.ts +10 -0
  172. package/dist/daemon/pid-lock.d.ts.map +1 -0
  173. package/dist/daemon/pid-lock.js +45 -0
  174. package/dist/daemon/pid-lock.js.map +1 -0
  175. package/dist/daemon/run.d.ts +19 -0
  176. package/dist/daemon/run.d.ts.map +1 -0
  177. package/dist/daemon/run.js +182 -0
  178. package/dist/daemon/run.js.map +1 -0
  179. package/dist/shared/config-types.d.ts +27 -0
  180. package/dist/shared/config-types.d.ts.map +1 -0
  181. package/dist/shared/config-types.js +13 -0
  182. package/dist/shared/config-types.js.map +1 -0
  183. package/dist/shared/protocol.d.ts +43 -0
  184. package/dist/shared/protocol.d.ts.map +1 -0
  185. package/dist/shared/protocol.js +11 -0
  186. package/dist/shared/protocol.js.map +1 -0
  187. package/package.json +70 -0
  188. package/templates/launchd/com.peerllm.host.plist +25 -0
  189. package/templates/systemd/peerllm-host.service +17 -0
  190. package/templates/windows/install-service.ps1 +29 -0
@@ -0,0 +1,450 @@
1
+ import { existsSync, promises as fsp } from "node:fs";
2
+ import { arch as osArch, platform as osPlatform } from "node:os";
3
+ import { join } from "node:path";
4
+ import { getLlama, LlamaChatSession } from "node-llama-cpp";
5
+ import si from "systeminformation";
6
+ import { getLogger } from "./logger.js";
7
+ import { calculateGpuLayersFromConfig, parseModelFilename, } from "./model-info.js";
8
+ import { getLLMDirectory } from "./models-fs.js";
9
+ const DEFAULT_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
10
+ const WATCHDOG_INTERVAL_MS = 60 * 1000;
11
+ const STALE_CONTEXT_LIMIT_MS = 5 * 60 * 1000;
12
+ let _cachedGraphics;
13
+ let _graphicsInFlight;
14
+ const GRAPHICS_CACHE_TTL_MS = 5 * 60 * 1000;
15
+ async function getCachedGraphics() {
16
+ const now = Date.now();
17
+ if (_cachedGraphics && now - _cachedGraphics.ts < GRAPHICS_CACHE_TTL_MS) {
18
+ return _cachedGraphics.data;
19
+ }
20
+ if (!_graphicsInFlight) {
21
+ _graphicsInFlight = si.graphics().then((data) => {
22
+ _cachedGraphics = { data, ts: Date.now() };
23
+ _graphicsInFlight = undefined;
24
+ return data;
25
+ });
26
+ }
27
+ return _graphicsInFlight;
28
+ }
29
+ export class SharedGGUFRunner {
30
+ env;
31
+ idleTimeoutMs;
32
+ llama = null;
33
+ model = null;
34
+ modelName = "";
35
+ gpuLayers = 0;
36
+ contexts = new Map();
37
+ maxConcurrentContexts = 10;
38
+ runnerState = "cold";
39
+ modelState = null;
40
+ activeRequestCount = 0;
41
+ loadingPromise = null;
42
+ generation = 0;
43
+ idleTimer = null;
44
+ watchdogTimer = null;
45
+ onIdleDispose = null;
46
+ constructor(env, idleTimeoutMs = DEFAULT_IDLE_TIMEOUT_MS) {
47
+ this.env = env;
48
+ this.idleTimeoutMs = idleTimeoutMs;
49
+ }
50
+ setIdleDisposeCallback(cb) {
51
+ this.onIdleDispose = cb;
52
+ }
53
+ getModelState() {
54
+ return this.modelState;
55
+ }
56
+ getRunnerState() {
57
+ return this.runnerState;
58
+ }
59
+ isModelInUse() {
60
+ return this.activeRequestCount > 0;
61
+ }
62
+ getStats() {
63
+ return {
64
+ activeContexts: this.contexts.size,
65
+ maxContexts: this.maxConcurrentContexts,
66
+ modelName: this.modelName,
67
+ gpuLayers: this.gpuLayers,
68
+ };
69
+ }
70
+ async loadModel(modelName, gpuIndex, loadType = "auto") {
71
+ if (this.runnerState === "disposing") {
72
+ throw new Error(`Cannot load "${modelName}" while disposal is in progress`);
73
+ }
74
+ if (this.model && this.modelName === modelName) {
75
+ if (this.modelState && loadType === "manual" && this.modelState.loadType === "auto") {
76
+ this.modelState.loadType = "manual";
77
+ this.clearIdleTimer();
78
+ }
79
+ if (this.modelState)
80
+ this.modelState.lastUsedAt = Date.now();
81
+ this.scheduleIdleCheck();
82
+ return;
83
+ }
84
+ if (this.loadingPromise) {
85
+ return this.loadingPromise;
86
+ }
87
+ this.loadingPromise = this._doLoadModel(modelName, gpuIndex, loadType).finally(() => {
88
+ this.loadingPromise = null;
89
+ });
90
+ return this.loadingPromise;
91
+ }
92
+ async _doLoadModel(modelName, gpuIndex, loadType) {
93
+ this.generation++;
94
+ const gen = this.generation;
95
+ this.runnerState = "loading";
96
+ this.logTransition("cold", "loading", loadType === "manual" ? "manual-load" : "auto-load", {
97
+ model: modelName,
98
+ });
99
+ try {
100
+ this.llama = await getLlama();
101
+ const llmDir = getLLMDirectory(this.env.paths, this.env.config);
102
+ const modelPath = join(llmDir, `${modelName}.gguf`);
103
+ const graphics = await getCachedGraphics();
104
+ let gpu;
105
+ if (gpuIndex !== undefined && graphics.controllers[gpuIndex]) {
106
+ gpu = graphics.controllers[gpuIndex];
107
+ }
108
+ else if (osPlatform() === "darwin" && osArch() === "arm64") {
109
+ gpu = graphics.controllers[0];
110
+ }
111
+ else {
112
+ gpu =
113
+ graphics.controllers.find((c) => (c.vendor ?? "").toLowerCase().includes("nvidia")) ??
114
+ graphics.controllers.find((c) => (c.vendor ?? "").toLowerCase().includes("amd")) ??
115
+ graphics.controllers[0];
116
+ }
117
+ const vramMB = gpu?.vram ?? 0;
118
+ const modelInfo = parseModelFilename(modelName);
119
+ // On Linux, llama.cpp manages VRAM allocation dynamically. On Apple Silicon,
120
+ // si.graphics() reports vram=0 because Metal uses unified memory. In both
121
+ // cases, ask for all layers (999) and let the runtime sort it out.
122
+ const useAllGpuLayers = osPlatform() === "linux" || (osPlatform() === "darwin" && osArch() === "arm64");
123
+ this.gpuLayers = useAllGpuLayers
124
+ ? 999
125
+ : calculateGpuLayersFromConfig(vramMB, modelInfo, this.env.config.computeMode, this.env.config.gpuLayers);
126
+ getLogger().info(`model load: gpu=${gpu?.model ?? "none"} vram=${vramMB}MB layers=${this.gpuLayers}` +
127
+ (useAllGpuLayers ? ` [all-layers: ${osPlatform()}/${osArch()}]` : ""));
128
+ await this.validateModelFile(modelPath, modelName);
129
+ if (this.generation !== gen) {
130
+ this._cleanupPartialLoad();
131
+ return;
132
+ }
133
+ this.model = await this.llama.loadModel({ modelPath, gpuLayers: this.gpuLayers });
134
+ if (this.generation !== gen) {
135
+ this._cleanupPartialLoad();
136
+ return;
137
+ }
138
+ this.modelName = modelName;
139
+ this.modelState = {
140
+ modelId: modelName,
141
+ isLoaded: true,
142
+ loadType,
143
+ lastUsedAt: Date.now(),
144
+ gpuLayers: this.gpuLayers,
145
+ };
146
+ this.runnerState = "loaded";
147
+ this.startWatchdog();
148
+ this.logTransition("loading", "loaded", loadType === "manual" ? "manual-load" : "auto-load", {
149
+ gpuLayers: this.gpuLayers,
150
+ });
151
+ this.scheduleIdleCheck();
152
+ }
153
+ catch (err) {
154
+ const message = err instanceof Error ? err.message : String(err);
155
+ this.logTransition("loading", "cold", "load-failure", { error: message });
156
+ this._cleanupPartialLoad();
157
+ throw new Error(`Failed to load '${modelName}': ${message}`);
158
+ }
159
+ }
160
+ _cleanupPartialLoad() {
161
+ this.clearIdleTimer();
162
+ this.stopWatchdog();
163
+ this.safeDispose(this.model, "model (partial)");
164
+ this.safeDispose(this.llama, "llama (partial)");
165
+ for (const [id, entry] of this.contexts.entries()) {
166
+ this.safeDispose(entry.context, `context[${id}] (partial)`);
167
+ }
168
+ this.contexts.clear();
169
+ this.model = null;
170
+ this.llama = null;
171
+ this.modelName = "";
172
+ this.modelState = null;
173
+ this.activeRequestCount = 0;
174
+ this.runnerState = "cold";
175
+ }
176
+ async prompt(conversationId, input, onToken, options) {
177
+ if (!this.model)
178
+ throw new Error("Model not loaded.");
179
+ const gen = this.generation;
180
+ this.activeRequestCount++;
181
+ this.clearIdleTimer();
182
+ if (this.modelState)
183
+ this.modelState.lastUsedAt = Date.now();
184
+ const promptTokens = this.model.tokenize(input).length;
185
+ const { session } = await this.getOrCreateContext(conversationId);
186
+ const entry = this.contexts.get(conversationId);
187
+ if (!entry) {
188
+ this.activeRequestCount = Math.max(0, this.activeRequestCount - 1);
189
+ throw new Error(`Context for "${conversationId}" was evicted before prompt could start`);
190
+ }
191
+ entry.abortController = new AbortController();
192
+ entry.inFlight = true;
193
+ let fullText = "";
194
+ try {
195
+ const promptOptions = {
196
+ onTextChunk: (chunk) => {
197
+ if (this.generation !== gen)
198
+ return;
199
+ if (onToken)
200
+ onToken(chunk);
201
+ fullText += chunk;
202
+ },
203
+ signal: entry.abortController.signal,
204
+ };
205
+ if (options?.maxTokens !== undefined)
206
+ promptOptions["maxTokens"] = options.maxTokens;
207
+ if (options?.temperature !== undefined)
208
+ promptOptions["temperature"] = options.temperature;
209
+ if (options?.stop?.length)
210
+ promptOptions["customStopTriggers"] = options.stop;
211
+ await session.prompt(input, promptOptions);
212
+ if (this.generation !== gen) {
213
+ return { text: fullText.trim(), promptTokens, completionTokens: 0 };
214
+ }
215
+ fullText = fullText.trim();
216
+ const completionTokens = this.model.tokenize(fullText).length;
217
+ return { text: fullText, promptTokens, completionTokens };
218
+ }
219
+ catch (err) {
220
+ const e = err;
221
+ if (e?.name === "AbortError") {
222
+ const completionTokens = this.generation === gen && this.model ? this.model.tokenize(fullText).length : 0;
223
+ return { text: fullText, promptTokens, completionTokens };
224
+ }
225
+ throw err;
226
+ }
227
+ finally {
228
+ if (this.generation === gen) {
229
+ if (entry) {
230
+ entry.abortController = null;
231
+ entry.inFlight = false;
232
+ entry.lastUsedAt = Date.now();
233
+ }
234
+ this.activeRequestCount = Math.max(0, this.activeRequestCount - 1);
235
+ this.scheduleIdleCheck();
236
+ }
237
+ }
238
+ }
239
+ cancel(conversationId) {
240
+ const entry = this.contexts.get(conversationId);
241
+ if (entry?.abortController) {
242
+ try {
243
+ entry.abortController.abort();
244
+ }
245
+ catch {
246
+ // ignored
247
+ }
248
+ }
249
+ }
250
+ cancelAll() {
251
+ for (const entry of this.contexts.values()) {
252
+ if (entry.abortController) {
253
+ try {
254
+ entry.abortController.abort();
255
+ }
256
+ catch {
257
+ // ignored
258
+ }
259
+ }
260
+ }
261
+ }
262
+ clearConversation(conversationId) {
263
+ const entry = this.contexts.get(conversationId);
264
+ if (entry) {
265
+ if (entry.inFlight) {
266
+ try {
267
+ entry.abortController?.abort();
268
+ }
269
+ catch {
270
+ // ignored
271
+ }
272
+ }
273
+ this.contexts.delete(conversationId);
274
+ this.safeDispose(entry.context, `context[${conversationId}]`);
275
+ }
276
+ }
277
+ async dispose(reason = "manual-dispose") {
278
+ if (this.runnerState === "disposing")
279
+ return;
280
+ if (this.runnerState === "cold")
281
+ return;
282
+ if (this.runnerState === "loading" && this.loadingPromise) {
283
+ try {
284
+ await this.loadingPromise;
285
+ }
286
+ catch {
287
+ // load failed; we're cold now
288
+ }
289
+ }
290
+ const stateAfter = this.runnerState;
291
+ if (stateAfter === "cold")
292
+ return;
293
+ if (stateAfter === "disposing")
294
+ return;
295
+ const prev = this.runnerState;
296
+ this.runnerState = "disposing";
297
+ this.generation++;
298
+ this.logTransition(prev, "disposing", reason);
299
+ this.clearIdleTimer();
300
+ this.stopWatchdog();
301
+ this.cancelAll();
302
+ await new Promise((resolve) => setTimeout(resolve, 300));
303
+ const entries = Array.from(this.contexts.entries());
304
+ this.contexts.clear();
305
+ for (const [id, entry] of entries) {
306
+ this.safeDispose(entry.context, `context[${id}]`);
307
+ }
308
+ await new Promise((resolve) => setTimeout(resolve, 100));
309
+ this.safeDispose(this.model, `model[${this.modelName}]`);
310
+ this.safeDispose(this.llama, `llama[${this.modelName}]`);
311
+ this.model = null;
312
+ this.llama = null;
313
+ this.modelName = "";
314
+ this.modelState = null;
315
+ this.activeRequestCount = 0;
316
+ this.runnerState = "cold";
317
+ this.logTransition("disposing", "cold", reason);
318
+ }
319
+ scheduleIdleCheck() {
320
+ this.clearIdleTimer();
321
+ if (!this.model)
322
+ return;
323
+ if (this.activeRequestCount > 0)
324
+ return;
325
+ if (this.modelState?.loadType === "manual")
326
+ return;
327
+ const capturedGen = this.generation;
328
+ this.idleTimer = setTimeout(async () => {
329
+ this.idleTimer = null;
330
+ if (this.generation !== capturedGen)
331
+ return;
332
+ if (this.activeRequestCount > 0)
333
+ return;
334
+ if (!this.model)
335
+ return;
336
+ const nameBefore = this.modelName;
337
+ try {
338
+ await this.dispose("idle-timeout");
339
+ }
340
+ finally {
341
+ this.onIdleDispose?.(nameBefore);
342
+ }
343
+ }, this.idleTimeoutMs);
344
+ }
345
+ clearIdleTimer() {
346
+ if (this.idleTimer !== null) {
347
+ clearTimeout(this.idleTimer);
348
+ this.idleTimer = null;
349
+ }
350
+ }
351
+ startWatchdog() {
352
+ if (this.watchdogTimer !== null)
353
+ return;
354
+ this.watchdogTimer = setInterval(() => this.runWatchdogCheck(), WATCHDOG_INTERVAL_MS);
355
+ }
356
+ stopWatchdog() {
357
+ if (this.watchdogTimer !== null) {
358
+ clearInterval(this.watchdogTimer);
359
+ this.watchdogTimer = null;
360
+ }
361
+ }
362
+ runWatchdogCheck() {
363
+ if (!this.model) {
364
+ this.stopWatchdog();
365
+ return;
366
+ }
367
+ const checkGen = this.generation;
368
+ const now = Date.now();
369
+ for (const [id, entry] of this.contexts.entries()) {
370
+ if (this.generation !== checkGen)
371
+ break;
372
+ if (entry.inFlight)
373
+ continue;
374
+ const idleMs = now - entry.lastUsedAt;
375
+ if (idleMs <= STALE_CONTEXT_LIMIT_MS)
376
+ continue;
377
+ this.contexts.delete(id);
378
+ this.logTransition(this.runnerState, this.runnerState, "watchdog-evict", {
379
+ contextId: id,
380
+ idleMin: Math.floor(idleMs / 60000),
381
+ });
382
+ this.safeDispose(entry.context, `watchdog-evict-context[${id}]`);
383
+ }
384
+ }
385
+ async getOrCreateContext(conversationId) {
386
+ const existing = this.contexts.get(conversationId);
387
+ if (existing) {
388
+ existing.lastUsedAt = Date.now();
389
+ return { context: existing.context, session: existing.session };
390
+ }
391
+ if (this.contexts.size >= this.maxConcurrentContexts) {
392
+ const evictable = Array.from(this.contexts.entries())
393
+ .filter(([, e]) => !e.inFlight)
394
+ .sort((a, b) => a[1].lastUsedAt - b[1].lastUsedAt);
395
+ if (evictable.length > 0 && evictable[0]) {
396
+ const [id, entry] = evictable[0];
397
+ this.contexts.delete(id);
398
+ this.safeDispose(entry.context, `lru-context[${id}]`);
399
+ }
400
+ }
401
+ if (!this.model)
402
+ throw new Error("Model not loaded when creating context");
403
+ const context = await this.model.createContext({ contextSize: 4096 });
404
+ const session = new LlamaChatSession({ contextSequence: context.getSequence() });
405
+ this.contexts.set(conversationId, {
406
+ context,
407
+ session,
408
+ lastUsedAt: Date.now(),
409
+ inFlight: false,
410
+ abortController: null,
411
+ });
412
+ return { context, session };
413
+ }
414
+ async validateModelFile(modelPath, modelName) {
415
+ if (!existsSync(modelPath)) {
416
+ throw new Error(`Model '${modelName}' not found at ${modelPath}`);
417
+ }
418
+ try {
419
+ await fsp.access(modelPath);
420
+ }
421
+ catch {
422
+ throw new Error(`Model '${modelName}' cannot be read at ${modelPath}`);
423
+ }
424
+ }
425
+ safeDispose(obj, name) {
426
+ if (!obj)
427
+ return;
428
+ try {
429
+ obj.dispose?.();
430
+ }
431
+ catch (err) {
432
+ getLogger().warn(`failed to dispose ${name}:`, err.message);
433
+ }
434
+ }
435
+ logTransition(from, to, reason, extra) {
436
+ getLogger().info(JSON.stringify({
437
+ event: "runner_state_transition",
438
+ from,
439
+ to,
440
+ model: this.modelName,
441
+ reason,
442
+ generation: this.generation,
443
+ activeRequests: this.activeRequestCount,
444
+ contexts: this.contexts.size,
445
+ timestamp: Date.now(),
446
+ ...extra,
447
+ }));
448
+ }
449
+ }
450
+ //# sourceMappingURL=shared-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-runner.js","sourceRoot":"","sources":["../../src/core/shared-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import type { AuthService } from "./auth.js";
2
+ import type { BackendClient } from "./backend-client.js";
3
+ export interface SubscribedHostRef {
4
+ hostId: string;
5
+ status?: string;
6
+ addedAt?: string;
7
+ }
8
+ export interface SubscriptionCapacity {
9
+ hasActiveSubscription: boolean;
10
+ subscriptionStatus: string | null;
11
+ subscribedHostCount: number;
12
+ availableHostCount: number;
13
+ pendingHostCount?: number;
14
+ totalUserHostCount: number;
15
+ pricePerHost: number;
16
+ subscribedHosts: SubscribedHostRef[];
17
+ pendingHosts?: SubscribedHostRef[];
18
+ availableHosts?: SubscribedHostRef[];
19
+ }
20
+ export interface SubscriptionStatus {
21
+ hasSubscription: boolean;
22
+ subscriptionId?: string;
23
+ status?: string;
24
+ currentPeriodEnd?: string;
25
+ hostCount?: number;
26
+ pricePerHost?: number;
27
+ }
28
+ export interface SubscriptionCreateResult {
29
+ subscriptionId?: string;
30
+ id?: string;
31
+ approvalUrl?: string;
32
+ status?: string;
33
+ }
34
+ export declare class SubscriptionService {
35
+ private readonly backend;
36
+ private readonly auth;
37
+ constructor(backend: BackendClient, auth: AuthService);
38
+ status(): Promise<SubscriptionStatus>;
39
+ capacity(): Promise<SubscriptionCapacity>;
40
+ create(hostIds: string[]): Promise<SubscriptionCreateResult>;
41
+ confirm(subscriptionId: string): Promise<void>;
42
+ addHost(hostId: string): Promise<SubscriptionCreateResult>;
43
+ removeHost(hostId: string): Promise<void>;
44
+ listHosts(): Promise<SubscribedHostRef[]>;
45
+ cancel(): Promise<void>;
46
+ hostIsActive(hostId: string): Promise<{
47
+ subscribed: boolean;
48
+ pending: boolean;
49
+ capacity: SubscriptionCapacity;
50
+ }>;
51
+ private requireToken;
52
+ }
53
+ //# sourceMappingURL=subscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../src/core/subscription.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACnC,cAAc,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,WAAW;IAG9B,MAAM,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAkBrC,QAAQ,IAAI,OAAO,CAAC,oBAAoB,CAAC;IA2BzC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAU5D,OAAO,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9C,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAU1D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASzC,SAAS,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IASzC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IASvB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAC1C,UAAU,EAAE,OAAO,CAAC;QACpB,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,oBAAoB,CAAC;KAChC,CAAC;YAOY,YAAY;CAK3B"}
@@ -0,0 +1,117 @@
1
+ export class SubscriptionService {
2
+ backend;
3
+ auth;
4
+ constructor(backend, auth) {
5
+ this.backend = backend;
6
+ this.auth = auth;
7
+ }
8
+ async status() {
9
+ const token = await this.requireToken();
10
+ try {
11
+ return await this.backend.request({
12
+ method: "GET",
13
+ path: "/subscriptions/hosting",
14
+ bearerToken: token,
15
+ });
16
+ }
17
+ catch (err) {
18
+ // The Electron app treats any non-2xx (including 404) as "no subscription".
19
+ const status = err.status;
20
+ if (status === 404 || status === 400) {
21
+ return { hasSubscription: false };
22
+ }
23
+ throw err;
24
+ }
25
+ }
26
+ async capacity() {
27
+ const token = await this.requireToken();
28
+ try {
29
+ return await this.backend.request({
30
+ method: "GET",
31
+ path: "/subscriptions/hosting/capacity",
32
+ bearerToken: token,
33
+ });
34
+ }
35
+ catch (err) {
36
+ const status = err.status;
37
+ if (status === 404) {
38
+ return {
39
+ hasActiveSubscription: false,
40
+ subscriptionStatus: null,
41
+ subscribedHostCount: 0,
42
+ availableHostCount: 0,
43
+ totalUserHostCount: 0,
44
+ pricePerHost: 5.0,
45
+ subscribedHosts: [],
46
+ availableHosts: [],
47
+ pendingHosts: [],
48
+ };
49
+ }
50
+ throw err;
51
+ }
52
+ }
53
+ async create(hostIds) {
54
+ const token = await this.requireToken();
55
+ return this.backend.request({
56
+ method: "POST",
57
+ path: "/subscriptions/hosting",
58
+ body: { hostIds },
59
+ bearerToken: token,
60
+ });
61
+ }
62
+ async confirm(subscriptionId) {
63
+ const token = await this.requireToken();
64
+ await this.backend.request({
65
+ method: "POST",
66
+ path: "/subscriptions/hosting/confirm",
67
+ body: { subscriptionId },
68
+ bearerToken: token,
69
+ });
70
+ }
71
+ async addHost(hostId) {
72
+ const token = await this.requireToken();
73
+ return this.backend.request({
74
+ method: "POST",
75
+ path: "/subscriptions/hosting/hosts",
76
+ body: { hostId },
77
+ bearerToken: token,
78
+ });
79
+ }
80
+ async removeHost(hostId) {
81
+ const token = await this.requireToken();
82
+ await this.backend.request({
83
+ method: "DELETE",
84
+ path: `/subscriptions/hosting/hosts/${hostId}`,
85
+ bearerToken: token,
86
+ });
87
+ }
88
+ async listHosts() {
89
+ const token = await this.requireToken();
90
+ return this.backend.request({
91
+ method: "GET",
92
+ path: "/subscriptions/hosting/hosts",
93
+ bearerToken: token,
94
+ });
95
+ }
96
+ async cancel() {
97
+ const token = await this.requireToken();
98
+ await this.backend.request({
99
+ method: "DELETE",
100
+ path: "/subscriptions/hosting",
101
+ bearerToken: token,
102
+ });
103
+ }
104
+ async hostIsActive(hostId) {
105
+ const capacity = await this.capacity();
106
+ const subscribed = capacity.subscribedHosts.some((h) => h.hostId === hostId);
107
+ const pending = capacity.pendingHosts?.some((h) => h.hostId === hostId) ?? false;
108
+ return { subscribed, pending, capacity };
109
+ }
110
+ async requireToken() {
111
+ const token = await this.auth.getValidAccessToken();
112
+ if (!token)
113
+ throw new Error("not authenticated");
114
+ return token;
115
+ }
116
+ }
117
+ //# sourceMappingURL=subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../src/core/subscription.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":""}