@qvac/sdk 0.4.1 → 0.5.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 +328 -200
- package/dist/client/api/completion-stream.d.ts +15 -5
- package/dist/client/api/completion-stream.js +50 -14
- package/dist/client/api/embed.d.ts +17 -3
- package/dist/client/api/embed.js +0 -8
- package/dist/client/api/get-model-info.d.ts +1 -1
- package/dist/client/api/index.d.ts +0 -1
- package/dist/client/api/index.js +0 -1
- package/dist/client/api/load-model.d.ts +37 -11
- package/dist/client/api/load-model.js +29 -117
- package/dist/client/api/logging-stream.d.ts +6 -3
- package/dist/client/api/logging-stream.js +6 -3
- package/dist/client/api/unload-model.js +5 -2
- package/dist/client/config-loader/config-utils.d.ts +5 -0
- package/dist/client/config-loader/config-utils.js +20 -0
- package/dist/client/config-loader/resolve-config.bare.d.ts +9 -0
- package/dist/client/config-loader/resolve-config.bare.js +87 -0
- package/dist/client/config-loader/resolve-config.expo.d.ts +11 -0
- package/dist/client/config-loader/resolve-config.expo.js +62 -0
- package/dist/client/config-loader/resolve-config.node.d.ts +9 -0
- package/dist/client/config-loader/resolve-config.node.js +118 -0
- package/dist/client/init-hooks.d.ts +17 -3
- package/dist/client/init-hooks.js +37 -18
- package/dist/client/logging-stream-registry.d.ts +1 -1
- package/dist/client/logging-stream-registry.js +14 -13
- package/dist/client/rpc/bare-client.d.ts +10 -14
- package/dist/client/rpc/bare-client.js +28 -2
- package/dist/client/rpc/bare-rpc-client.d.ts +1 -1
- package/dist/client/rpc/bare-rpc-client.js +16 -13
- package/dist/client/rpc/expo-rpc-client.d.ts +2 -2
- package/dist/client/rpc/expo-rpc-client.js +15 -12
- package/dist/client/rpc/node-rpc-client.d.ts +1 -1
- package/dist/client/rpc/node-rpc-client.js +10 -7
- package/dist/client/rpc/rpc-client.js +16 -15
- package/dist/examples/config/config-path.d.ts +8 -0
- package/dist/examples/config/config-path.js +13 -0
- package/dist/examples/config-reload.d.ts +2 -0
- package/dist/examples/config-reload.js +49 -0
- package/dist/examples/download-with-blind-relays.js +20 -20
- package/dist/examples/embed-hyperdrive.js +35 -3
- package/dist/examples/kv-cache-cleanup.js +1 -1
- package/dist/examples/kv-cache-custom-key.js +1 -1
- package/dist/examples/kv-cache-example.js +1 -1
- package/dist/examples/llamacpp-hyperdrive.js +1 -1
- package/dist/examples/llamacpp-sharded.js +1 -1
- package/dist/examples/logging-file-transport.d.ts +2 -0
- package/dist/examples/{llamacpp-file-logging.js → logging-file-transport.js} +3 -7
- package/dist/examples/logging-streaming.d.ts +2 -0
- package/dist/examples/logging-streaming.js +75 -0
- package/dist/examples/mcp-websearch.d.ts +13 -0
- package/dist/examples/mcp-websearch.js +176 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/logging/addon.d.ts +6 -0
- package/dist/logging/addon.js +59 -0
- package/dist/logging/base-logger.js +24 -14
- package/dist/logging/client-logger.d.ts +3 -0
- package/dist/logging/client-logger.js +13 -0
- package/dist/logging/index.d.ts +6 -1
- package/dist/logging/index.js +6 -1
- package/dist/logging/logger.d.ts +0 -2
- package/dist/logging/logger.js +0 -3
- package/dist/logging/namespaces.d.ts +11 -0
- package/dist/logging/namespaces.js +11 -0
- package/dist/logging/registry.d.ts +26 -0
- package/dist/logging/registry.js +36 -0
- package/dist/logging/server-logger.d.ts +3 -0
- package/dist/logging/server-logger.js +16 -0
- package/dist/logging/stream-logger.d.ts +1 -1
- package/dist/logging/stream-logger.js +6 -3
- package/dist/logging/types.d.ts +2 -0
- package/dist/models/hyperdrive/models.d.ts +789 -51
- package/dist/models/hyperdrive/models.js +979 -200
- package/dist/schemas/common.d.ts +86 -23
- package/dist/schemas/common.js +0 -3
- package/dist/schemas/download-asset.d.ts +5 -5
- package/dist/schemas/embed.d.ts +3 -3
- package/dist/schemas/embed.js +9 -2
- package/dist/schemas/get-model-info.d.ts +2 -2
- package/dist/schemas/index.d.ts +5 -1
- package/dist/schemas/index.js +5 -1
- package/dist/schemas/json-schema.d.ts +16 -0
- package/dist/schemas/json-schema.js +2 -0
- package/dist/schemas/llamacpp-config.d.ts +5 -4
- package/dist/schemas/llamacpp-config.js +7 -5
- package/dist/schemas/load-model.d.ts +931 -211
- package/dist/schemas/load-model.js +7 -1
- package/dist/schemas/logging-stream.d.ts +10 -3
- package/dist/schemas/logging-stream.js +4 -3
- package/dist/schemas/mcp-adapter.d.ts +47 -0
- package/dist/schemas/mcp-adapter.js +1 -0
- package/dist/schemas/model-src-utils.d.ts +8 -6
- package/dist/schemas/model-src-utils.js +8 -3
- package/dist/schemas/reload-config.d.ts +344 -0
- package/dist/schemas/reload-config.js +42 -0
- package/dist/schemas/sdk-config.d.ts +22 -0
- package/dist/schemas/sdk-config.js +33 -0
- package/dist/schemas/sdk-errors-client.d.ts +4 -0
- package/dist/schemas/sdk-errors-client.js +20 -0
- package/dist/schemas/sdk-errors-server.d.ts +3 -0
- package/dist/schemas/sdk-errors-server.js +15 -0
- package/dist/schemas/tools.d.ts +3 -0
- package/dist/schemas/translation-config.d.ts +81 -0
- package/dist/schemas/translation-config.js +3 -4
- package/dist/schemas/whispercpp-config.d.ts +9 -1
- package/dist/schemas/whispercpp-config.js +2 -1
- package/dist/server/bare/addons/llamacpp/create-model.js +13 -4
- package/dist/server/bare/addons/llamacpp/handlers/embed.d.ts +9 -1
- package/dist/server/bare/addons/llamacpp/handlers/embed.js +18 -4
- package/dist/server/bare/addons/llamacpp/kv-cache-utils.js +6 -4
- package/dist/server/bare/addons/load-model.js +10 -4
- package/dist/server/bare/addons/unload-model.js +6 -3
- package/dist/server/bare/addons/whispercpp/handlers/transcribe-stream.js +56 -37
- package/dist/server/bare/delegate-rpc-client.js +12 -10
- package/dist/server/bare/hyperswarm.js +7 -5
- package/dist/server/bare/rag-hyperdb/rag-manager.js +3 -1
- package/dist/server/bare/registry/config-registry.d.ts +13 -4
- package/dist/server/bare/registry/config-registry.js +42 -10
- package/dist/server/bare/registry/logging-stream-registry.d.ts +24 -7
- package/dist/server/bare/registry/logging-stream-registry.js +99 -20
- package/dist/server/bare/registry/model-registry.d.ts +3 -0
- package/dist/server/bare/registry/model-registry.js +9 -6
- package/dist/server/rpc/create-server.js +5 -3
- package/dist/server/rpc/handle-request.js +30 -16
- package/dist/server/rpc/handlers/cancelHandler.js +3 -1
- package/dist/server/rpc/handlers/completion-stream-delegated.js +4 -2
- package/dist/server/rpc/handlers/delete-cache.js +3 -1
- package/dist/server/rpc/handlers/download-asset.js +3 -1
- package/dist/server/rpc/handlers/embed.js +3 -1
- package/dist/server/rpc/handlers/index.d.ts +0 -1
- package/dist/server/rpc/handlers/index.js +0 -2
- package/dist/server/rpc/handlers/load-model/download-manager.js +4 -2
- package/dist/server/rpc/handlers/load-model/http.js +20 -18
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +21 -19
- package/dist/server/rpc/handlers/load-model/resolve.js +7 -5
- package/dist/server/rpc/handlers/load-model-delegated.d.ts +2 -2
- package/dist/server/rpc/handlers/load-model-delegated.js +10 -8
- package/dist/server/rpc/handlers/load-model.js +55 -3
- package/dist/server/rpc/handlers/logging-stream.js +4 -4
- package/dist/server/rpc/handlers/provideHandler/connection.js +12 -10
- package/dist/server/rpc/handlers/provideHandler/handler.js +18 -16
- package/dist/server/rpc/handlers/provideHandler/proxy.js +8 -6
- package/dist/server/rpc/handlers/rag.js +3 -1
- package/dist/server/rpc/handlers/stopProvideHandler.js +3 -1
- package/dist/server/rpc/handlers/transcribe-stream.js +3 -1
- package/dist/server/rpc/handlers/translate.js +3 -1
- package/dist/server/rpc/handlers/unload-model.js +4 -2
- package/dist/server/utils/audio/decoder.d.ts +2 -1
- package/dist/server/utils/audio/decoder.js +48 -11
- package/dist/server/utils/cache.js +7 -5
- package/dist/server/utils/config-transform.d.ts +3 -0
- package/dist/server/utils/config-transform.js +21 -0
- package/dist/server/utils/index.d.ts +1 -0
- package/dist/server/utils/index.js +1 -0
- package/dist/server/worker.js +41 -16
- package/dist/utils/errors-client.d.ts +12 -0
- package/dist/utils/errors-client.js +20 -0
- package/dist/utils/errors-server.d.ts +9 -0
- package/dist/utils/errors-server.js +16 -0
- package/dist/utils/getProcessSafe.d.ts +7 -0
- package/dist/utils/getProcessSafe.js +17 -0
- package/dist/utils/mcp-adapter.d.ts +12 -0
- package/dist/utils/mcp-adapter.js +103 -0
- package/dist/utils/object.d.ts +2 -0
- package/dist/utils/object.js +3 -0
- package/dist/utils/runtime.d.ts +30 -0
- package/dist/utils/runtime.js +48 -0
- package/dist/utils/tool-helpers.d.ts +10 -2
- package/dist/utils/tool-helpers.js +24 -11
- package/package.json +46 -33
- package/dist/client/api/set-config.d.ts +0 -7
- package/dist/client/api/set-config.js +0 -20
- package/dist/client/config-manager.d.ts +0 -4
- package/dist/client/config-manager.js +0 -8
- package/dist/examples/llamacpp-file-logging.d.ts +0 -2
- package/dist/schemas/set-config.d.ts +0 -21
- package/dist/schemas/set-config.js +0 -14
- package/dist/server/rpc/handlers/set-config.d.ts +0 -3
- package/dist/server/rpc/handlers/set-config.js +0 -18
|
@@ -3,13 +3,15 @@ import Hyperswarm from "hyperswarm";
|
|
|
3
3
|
import crypto from "bare-crypto";
|
|
4
4
|
import { envSchema } from "../../schemas/provide.js";
|
|
5
5
|
import { getSDKConfig } from "./registry/config-registry.js";
|
|
6
|
+
import { getServerLogger } from "../../logging/index.js";
|
|
7
|
+
const logger = getServerLogger();
|
|
6
8
|
function getHyperswarmSeedBuffer() {
|
|
7
9
|
const parsedEnv = envSchema.safeParse(process.env);
|
|
8
10
|
if (parsedEnv.success) {
|
|
9
11
|
return Buffer.from(parsedEnv.data.QVAC_HYPERSWARM_SEED, "hex");
|
|
10
12
|
}
|
|
11
13
|
else {
|
|
12
|
-
|
|
14
|
+
logger.info(`🎲 No seed provided, generating random seed (provider will have random identity)`);
|
|
13
15
|
return crypto.randomBytes(32);
|
|
14
16
|
}
|
|
15
17
|
}
|
|
@@ -24,20 +26,20 @@ function createFirewallFunction(config) {
|
|
|
24
26
|
if (mode === "allow") {
|
|
25
27
|
const allowed = publicKeySet.has(remoteKeyHex);
|
|
26
28
|
if (!allowed) {
|
|
27
|
-
|
|
29
|
+
logger.debug(`🚫 Firewall: Denied connection from ${remoteKeyHex.substring(0, 16)}... (not in allowlist)`);
|
|
28
30
|
}
|
|
29
31
|
else {
|
|
30
|
-
|
|
32
|
+
logger.debug(`✅ Firewall: Allowed connection from ${remoteKeyHex.substring(0, 16)}... (in allowlist)`);
|
|
31
33
|
}
|
|
32
34
|
return !allowed;
|
|
33
35
|
}
|
|
34
36
|
else {
|
|
35
37
|
const denied = publicKeySet.has(remoteKeyHex);
|
|
36
38
|
if (denied) {
|
|
37
|
-
|
|
39
|
+
logger.debug(`🚫 Firewall: Denied connection from ${remoteKeyHex.substring(0, 16)}... (in denylist)`);
|
|
38
40
|
}
|
|
39
41
|
else {
|
|
40
|
-
|
|
42
|
+
logger.debug(`✅ Firewall: Allowed connection from ${remoteKeyHex.substring(0, 16)}... (not in denylist)`);
|
|
41
43
|
}
|
|
42
44
|
return denied;
|
|
43
45
|
}
|
|
@@ -3,6 +3,8 @@ import Corestore from "corestore";
|
|
|
3
3
|
import path from "bare-path";
|
|
4
4
|
import { getEnv } from "../../worker.js";
|
|
5
5
|
import { RAGWorkspaceModelMismatchError } from "../../../utils/errors-server.js";
|
|
6
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
7
|
+
const logger = getServerLogger();
|
|
6
8
|
const ragInstances = new Map();
|
|
7
9
|
const defaultWorkspace = "default";
|
|
8
10
|
const getStorePath = (workspace) => {
|
|
@@ -59,6 +61,6 @@ export const closeAllRagInstances = async () => {
|
|
|
59
61
|
await Promise.all(closures);
|
|
60
62
|
}
|
|
61
63
|
catch (error) {
|
|
62
|
-
|
|
64
|
+
logger.error("❌ Error during RAG cleanup:", error);
|
|
63
65
|
}
|
|
64
66
|
};
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import type { QvacConfig } from "../../../schemas/index";
|
|
2
|
+
/**
|
|
3
|
+
* Sets the SDK configuration. This can only be called ONCE during initialization.
|
|
4
|
+
* After the first call, the config becomes immutable and any subsequent calls will throw.
|
|
5
|
+
*
|
|
6
|
+
* @param config - The configuration to set
|
|
7
|
+
* @throws {ConfigAlreadySetError} If config has already been set
|
|
8
|
+
* @throws {CacheDirNotAbsoluteError} If cacheDirectory is not an absolute path
|
|
9
|
+
* @throws {CacheDirNotWritableError} If cacheDirectory is not writable
|
|
10
|
+
*/
|
|
11
|
+
export declare function setSDKConfig(config: QvacConfig): void;
|
|
12
|
+
export declare function getSDKConfig(): QvacConfig;
|
|
13
|
+
export declare function getConfiguredCacheDir(): string;
|
|
5
14
|
//# sourceMappingURL=config-registry.d.ts.map
|
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
import fs from "bare-fs";
|
|
2
2
|
import path from "bare-path";
|
|
3
3
|
import { getEnv } from "../../worker.js";
|
|
4
|
-
import { CacheDirNotAbsoluteError, CacheDirNotWritableError, } from "../../../utils/errors-server.js";
|
|
4
|
+
import { CacheDirNotAbsoluteError, CacheDirNotWritableError, ConfigAlreadySetError, } from "../../../utils/errors-server.js";
|
|
5
|
+
import { getServerLogger, setGlobalConsoleOutput, setGlobalLogLevel, } from "../../../logging/index.js";
|
|
6
|
+
const logger = getServerLogger();
|
|
5
7
|
const configRegistry = {
|
|
6
8
|
cacheDirectory: undefined,
|
|
7
9
|
swarmRelays: undefined,
|
|
10
|
+
loggerLevel: undefined,
|
|
11
|
+
loggerConsoleOutput: undefined,
|
|
8
12
|
};
|
|
9
|
-
|
|
13
|
+
let configIsSet = false;
|
|
14
|
+
/**
|
|
15
|
+
* Sets the SDK configuration. This can only be called ONCE during initialization.
|
|
16
|
+
* After the first call, the config becomes immutable and any subsequent calls will throw.
|
|
17
|
+
*
|
|
18
|
+
* @param config - The configuration to set
|
|
19
|
+
* @throws {ConfigAlreadySetError} If config has already been set
|
|
20
|
+
* @throws {CacheDirNotAbsoluteError} If cacheDirectory is not an absolute path
|
|
21
|
+
* @throws {CacheDirNotWritableError} If cacheDirectory is not writable
|
|
22
|
+
*/
|
|
23
|
+
export function setSDKConfig(config) {
|
|
24
|
+
// Enforce immutability - config can only be set once
|
|
25
|
+
if (configIsSet) {
|
|
26
|
+
throw new ConfigAlreadySetError();
|
|
27
|
+
}
|
|
10
28
|
if (config.cacheDirectory !== undefined && config.cacheDirectory !== null) {
|
|
11
29
|
if (!path.isAbsolute(config.cacheDirectory)) {
|
|
12
30
|
throw new CacheDirNotAbsoluteError();
|
|
@@ -21,19 +39,33 @@ export const setSDKConfig = (config) => {
|
|
|
21
39
|
throw new CacheDirNotWritableError(config.cacheDirectory, error instanceof Error ? error.message : String(error), error);
|
|
22
40
|
}
|
|
23
41
|
configRegistry.cacheDirectory = config.cacheDirectory;
|
|
24
|
-
|
|
42
|
+
logger.info(`✅ Cache directory set to: ${config.cacheDirectory}`);
|
|
25
43
|
}
|
|
26
44
|
if (config.swarmRelays !== undefined && config.swarmRelays !== null) {
|
|
27
45
|
configRegistry.swarmRelays = config.swarmRelays;
|
|
46
|
+
logger.info(`✅ Swarm relays configured: ${config.swarmRelays.length} relay(s)`);
|
|
28
47
|
}
|
|
29
|
-
|
|
30
|
-
|
|
48
|
+
if (config.loggerLevel !== undefined && config.loggerLevel !== null) {
|
|
49
|
+
configRegistry.loggerLevel = config.loggerLevel;
|
|
50
|
+
setGlobalLogLevel(config.loggerLevel);
|
|
51
|
+
logger.info(`Log level set to: ${config.loggerLevel}`);
|
|
52
|
+
}
|
|
53
|
+
if (config.loggerConsoleOutput !== undefined &&
|
|
54
|
+
config.loggerConsoleOutput !== null) {
|
|
55
|
+
configRegistry.loggerConsoleOutput = config.loggerConsoleOutput;
|
|
56
|
+
setGlobalConsoleOutput(config.loggerConsoleOutput);
|
|
57
|
+
logger.info(`Console output ${config.loggerConsoleOutput ? "enabled" : "disabled"}`);
|
|
58
|
+
}
|
|
59
|
+
// Mark config as set - now it's immutable
|
|
60
|
+
configIsSet = true;
|
|
61
|
+
}
|
|
62
|
+
export function getSDKConfig() {
|
|
31
63
|
return { ...configRegistry };
|
|
32
|
-
}
|
|
33
|
-
|
|
64
|
+
}
|
|
65
|
+
function getDefaultCacheDir() {
|
|
34
66
|
const homeDir = getEnv().HOME_DIR;
|
|
35
67
|
return path.join(homeDir, ".qvac", "models");
|
|
36
|
-
}
|
|
37
|
-
export
|
|
68
|
+
}
|
|
69
|
+
export function getConfiguredCacheDir() {
|
|
38
70
|
return configRegistry.cacheDirectory || getDefaultCacheDir();
|
|
39
|
-
}
|
|
71
|
+
}
|
|
@@ -1,13 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging Stream Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages RPC subscriptions for streaming logs from server to connected clients.
|
|
5
|
+
*
|
|
6
|
+
* Purpose:
|
|
7
|
+
* - Registers client subscriptions to model/SDK log streams
|
|
8
|
+
* - Routes log messages to subscribed clients via RPC
|
|
9
|
+
* - Buffers logs during model loading (before client subscribes)
|
|
10
|
+
* - Manages stream lifecycle (subscribe/unsubscribe)
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
1
13
|
import type { LogLevel } from "@qvac/logging";
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
14
|
+
export declare function startLogBuffering(id: string): void;
|
|
15
|
+
export declare function stopLogBufferingWithTimeout(id: string): void;
|
|
16
|
+
export declare function registerLoggingStream(id: string, streamHandler: (level: LogLevel, namespace: string, message: string) => void): void;
|
|
17
|
+
export declare function unregisterLoggingStream(id: string, streamHandler: (level: LogLevel, namespace: string, message: string) => void): void;
|
|
18
|
+
export declare function unregisterAllLoggingStreams(id: string): void;
|
|
19
|
+
export declare function sendLogToStreams(id: string, level: LogLevel, namespace: string, message: string): void;
|
|
20
|
+
export declare function hasLoggingStreams(id: string): boolean | undefined;
|
|
7
21
|
export declare function getLoggingStreamStats(): {
|
|
8
|
-
|
|
9
|
-
|
|
22
|
+
totalIds: number;
|
|
23
|
+
ids: string[];
|
|
10
24
|
totalStreams: number;
|
|
25
|
+
bufferedIds: number;
|
|
26
|
+
idsWithBuffering: number;
|
|
27
|
+
activeTimeouts: number;
|
|
11
28
|
};
|
|
12
29
|
export declare function clearAllLoggingStreams(): void;
|
|
13
30
|
//# sourceMappingURL=logging-stream-registry.d.ts.map
|
|
@@ -1,53 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging Stream Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages RPC subscriptions for streaming logs from server to connected clients.
|
|
5
|
+
*
|
|
6
|
+
* Purpose:
|
|
7
|
+
* - Registers client subscriptions to model/SDK log streams
|
|
8
|
+
* - Routes log messages to subscribed clients via RPC
|
|
9
|
+
* - Buffers logs during model loading (before client subscribes)
|
|
10
|
+
* - Manages stream lifecycle (subscribe/unsubscribe)
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
1
13
|
const loggingStreams = new Map();
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
14
|
+
// Buffering for logs emitted during model loading (before client subscribes)
|
|
15
|
+
const MAX_BUFFERED_LOGS_PER_MODEL = 100;
|
|
16
|
+
const BUFFER_EXPIRY_MS = 30_000;
|
|
17
|
+
const BUFFERING_TIMEOUT_MS = 5_000;
|
|
18
|
+
const logBuffer = new Map();
|
|
19
|
+
const modelsWithBuffering = new Set();
|
|
20
|
+
const bufferingTimeouts = new Map();
|
|
21
|
+
function clearBufferingTimeout(id) {
|
|
22
|
+
const timeout = bufferingTimeouts.get(id);
|
|
23
|
+
if (timeout) {
|
|
24
|
+
clearTimeout(timeout);
|
|
25
|
+
bufferingTimeouts.delete(id);
|
|
5
26
|
}
|
|
6
|
-
loggingStreams.get(modelId).add(streamHandler);
|
|
7
27
|
}
|
|
8
|
-
export function
|
|
9
|
-
|
|
28
|
+
export function startLogBuffering(id) {
|
|
29
|
+
modelsWithBuffering.add(id);
|
|
30
|
+
}
|
|
31
|
+
export function stopLogBufferingWithTimeout(id) {
|
|
32
|
+
clearBufferingTimeout(id);
|
|
33
|
+
const timeout = setTimeout(() => {
|
|
34
|
+
if (modelsWithBuffering.has(id)) {
|
|
35
|
+
modelsWithBuffering.delete(id);
|
|
36
|
+
logBuffer.delete(id);
|
|
37
|
+
}
|
|
38
|
+
bufferingTimeouts.delete(id);
|
|
39
|
+
}, BUFFERING_TIMEOUT_MS);
|
|
40
|
+
bufferingTimeouts.set(id, timeout);
|
|
41
|
+
}
|
|
42
|
+
export function registerLoggingStream(id, streamHandler) {
|
|
43
|
+
if (!loggingStreams.has(id)) {
|
|
44
|
+
loggingStreams.set(id, new Set());
|
|
45
|
+
}
|
|
46
|
+
loggingStreams.get(id).add(streamHandler);
|
|
47
|
+
const buffered = logBuffer.get(id);
|
|
48
|
+
if (buffered && buffered.length > 0) {
|
|
49
|
+
for (const log of buffered) {
|
|
50
|
+
try {
|
|
51
|
+
streamHandler(log.level, log.namespace, log.message);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error(`Error flushing buffered log for ID ${id}:`, error);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
logBuffer.delete(id);
|
|
58
|
+
}
|
|
59
|
+
modelsWithBuffering.delete(id);
|
|
60
|
+
clearBufferingTimeout(id);
|
|
61
|
+
}
|
|
62
|
+
export function unregisterLoggingStream(id, streamHandler) {
|
|
63
|
+
const streams = loggingStreams.get(id);
|
|
10
64
|
if (streams) {
|
|
11
65
|
streams.delete(streamHandler);
|
|
12
66
|
if (streams.size === 0) {
|
|
13
|
-
loggingStreams.delete(
|
|
67
|
+
loggingStreams.delete(id);
|
|
14
68
|
}
|
|
15
69
|
}
|
|
16
70
|
}
|
|
17
|
-
export function unregisterAllLoggingStreams(
|
|
18
|
-
// Simply remove all logging handlers
|
|
71
|
+
export function unregisterAllLoggingStreams(id) {
|
|
72
|
+
// Simply remove all logging handlers
|
|
19
73
|
// Active streams will naturally terminate when no more logs flow
|
|
20
|
-
loggingStreams.delete(
|
|
21
|
-
|
|
74
|
+
loggingStreams.delete(id);
|
|
75
|
+
logBuffer.delete(id);
|
|
76
|
+
modelsWithBuffering.delete(id);
|
|
77
|
+
clearBufferingTimeout(id);
|
|
22
78
|
}
|
|
23
|
-
export function sendLogToStreams(
|
|
24
|
-
const streams = loggingStreams.get(
|
|
25
|
-
|
|
79
|
+
export function sendLogToStreams(id, level, namespace, message) {
|
|
80
|
+
const streams = loggingStreams.get(id);
|
|
81
|
+
const isBuffering = modelsWithBuffering.has(id);
|
|
82
|
+
if (streams && streams.size > 0) {
|
|
26
83
|
for (const streamHandler of streams) {
|
|
27
84
|
try {
|
|
28
85
|
streamHandler(level, namespace, message);
|
|
29
86
|
}
|
|
30
87
|
catch (error) {
|
|
31
|
-
console.error(`Error sending log to stream for
|
|
88
|
+
console.error(`Error sending log to stream for ID ${id}:`, error);
|
|
32
89
|
}
|
|
33
90
|
}
|
|
34
91
|
}
|
|
92
|
+
else if (isBuffering) {
|
|
93
|
+
if (!logBuffer.has(id)) {
|
|
94
|
+
logBuffer.set(id, []);
|
|
95
|
+
}
|
|
96
|
+
const buffer = logBuffer.get(id);
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
const validLogs = buffer.filter((log) => now - log.timestamp < BUFFER_EXPIRY_MS);
|
|
99
|
+
if (validLogs.length >= MAX_BUFFERED_LOGS_PER_MODEL) {
|
|
100
|
+
validLogs.shift();
|
|
101
|
+
}
|
|
102
|
+
validLogs.push({ level, namespace, message, timestamp: now });
|
|
103
|
+
logBuffer.set(id, validLogs);
|
|
104
|
+
}
|
|
35
105
|
}
|
|
36
|
-
export function hasLoggingStreams(
|
|
37
|
-
const streams = loggingStreams.get(
|
|
106
|
+
export function hasLoggingStreams(id) {
|
|
107
|
+
const streams = loggingStreams.get(id);
|
|
38
108
|
return streams && streams.size > 0;
|
|
39
109
|
}
|
|
40
110
|
export function getLoggingStreamStats() {
|
|
41
111
|
return {
|
|
42
|
-
|
|
43
|
-
|
|
112
|
+
totalIds: loggingStreams.size,
|
|
113
|
+
ids: Array.from(loggingStreams.keys()),
|
|
44
114
|
totalStreams: Array.from(loggingStreams.values()).reduce((sum, streams) => sum + streams.size, 0),
|
|
115
|
+
bufferedIds: logBuffer.size,
|
|
116
|
+
idsWithBuffering: modelsWithBuffering.size,
|
|
117
|
+
activeTimeouts: bufferingTimeouts.size,
|
|
45
118
|
};
|
|
46
119
|
}
|
|
47
120
|
export function clearAllLoggingStreams() {
|
|
48
121
|
const count = loggingStreams.size;
|
|
122
|
+
for (const timeout of bufferingTimeouts.values()) {
|
|
123
|
+
clearTimeout(timeout);
|
|
124
|
+
}
|
|
49
125
|
loggingStreams.clear();
|
|
126
|
+
logBuffer.clear();
|
|
127
|
+
modelsWithBuffering.clear();
|
|
128
|
+
bufferingTimeouts.clear();
|
|
50
129
|
if (count > 0) {
|
|
51
|
-
console.log(`🧹 Cleared logging streams for ${count}
|
|
130
|
+
console.log(`🧹 Cleared logging streams for ${count} ID(s)`);
|
|
52
131
|
}
|
|
53
132
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type EventEmitter from "events";
|
|
2
2
|
import type FilesystemDL from "@qvac/dl-filesystem";
|
|
3
|
+
import type { ModelType } from "../../../schemas/index";
|
|
3
4
|
interface AddonInterface {
|
|
4
5
|
cancel(jobId?: string): Promise<void>;
|
|
5
6
|
}
|
|
@@ -40,6 +41,7 @@ interface LocalOptions {
|
|
|
40
41
|
path: string;
|
|
41
42
|
loadedAt: Date;
|
|
42
43
|
config: unknown;
|
|
44
|
+
modelType: ModelType;
|
|
43
45
|
name?: string | undefined;
|
|
44
46
|
loader: FilesystemDL;
|
|
45
47
|
}
|
|
@@ -53,6 +55,7 @@ export declare function registerModel(id: string, options: {
|
|
|
53
55
|
model: AnyModel;
|
|
54
56
|
path: string;
|
|
55
57
|
config: unknown;
|
|
58
|
+
modelType: ModelType;
|
|
56
59
|
loader: FilesystemDL;
|
|
57
60
|
name?: string | undefined;
|
|
58
61
|
} | {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { ModelAlreadyRegisteredError, ModelNotFoundError, ModelIsDelegatedError, } from "../../../utils/errors-server.js";
|
|
2
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
3
|
+
const logger = getServerLogger();
|
|
2
4
|
// Global registry state - using stateless functions to manage it
|
|
3
5
|
const modelRegistry = new Map();
|
|
4
6
|
export function registerModel(id, options) {
|
|
@@ -17,7 +19,7 @@ export function registerModel(id, options) {
|
|
|
17
19
|
timeout,
|
|
18
20
|
},
|
|
19
21
|
});
|
|
20
|
-
|
|
22
|
+
logger.info(`Delegated model registered: ${id} -> topic: ${topic}, provider: ${providerPublicKey}, timeout: ${timeout}ms`);
|
|
21
23
|
}
|
|
22
24
|
else {
|
|
23
25
|
modelRegistry.set(id, {
|
|
@@ -28,12 +30,13 @@ export function registerModel(id, options) {
|
|
|
28
30
|
path: options.path,
|
|
29
31
|
loadedAt: new Date(),
|
|
30
32
|
config: options.config,
|
|
33
|
+
modelType: options.modelType,
|
|
31
34
|
loader: options.loader,
|
|
32
35
|
name: options.name,
|
|
33
36
|
},
|
|
34
37
|
});
|
|
35
38
|
const nameStr = options.name ? ` (${options.name})` : "";
|
|
36
|
-
|
|
39
|
+
logger.info(`Local model registered: ${id}${nameStr} -> ${options.path}`);
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
export function getModelEntry(id) {
|
|
@@ -56,7 +59,7 @@ export function unregisterModel(id) {
|
|
|
56
59
|
const entry = modelRegistry.get(id);
|
|
57
60
|
if (entry) {
|
|
58
61
|
modelRegistry.delete(id);
|
|
59
|
-
|
|
62
|
+
logger.debug(`Model unregistered: ${id}`);
|
|
60
63
|
return entry;
|
|
61
64
|
}
|
|
62
65
|
return null;
|
|
@@ -99,7 +102,7 @@ export function updateModelConfig(id, config) {
|
|
|
99
102
|
}
|
|
100
103
|
export function clearRegistry() {
|
|
101
104
|
modelRegistry.clear();
|
|
102
|
-
|
|
105
|
+
logger.info("Model registry cleared");
|
|
103
106
|
}
|
|
104
107
|
export function getRegistryStats() {
|
|
105
108
|
return {
|
|
@@ -113,9 +116,9 @@ export async function unloadAllModels() {
|
|
|
113
116
|
const entry = modelRegistry.get(modelId);
|
|
114
117
|
if (entry?.local?.model && entry.local.model.unload) {
|
|
115
118
|
await entry.local.model.unload();
|
|
116
|
-
|
|
119
|
+
logger.debug(`Model unloaded: ${modelId}`);
|
|
117
120
|
}
|
|
118
121
|
modelRegistry.delete(modelId);
|
|
119
122
|
}
|
|
120
|
-
|
|
123
|
+
logger.info(`Unloaded ${modelIds.length} models`);
|
|
121
124
|
}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import RPC from "bare-rpc";
|
|
2
2
|
import { connect } from "bare-net";
|
|
3
3
|
import { handleRequest } from "./handle-request.js";
|
|
4
|
+
import { getServerLogger } from "../../logging/index.js";
|
|
5
|
+
const logger = getServerLogger();
|
|
4
6
|
export function createBareKitRPCServer() {
|
|
5
7
|
const { IPC } = globalThis
|
|
6
8
|
.BareKit;
|
|
7
9
|
return new RPC(IPC, handleRequest);
|
|
8
10
|
}
|
|
9
11
|
export function createIPCClient(socketPath) {
|
|
10
|
-
|
|
12
|
+
logger.info(`Connecting to IPC socket at ${socketPath}`);
|
|
11
13
|
const socket = connect(socketPath);
|
|
12
14
|
socket.on("connect", () => {
|
|
13
|
-
|
|
15
|
+
logger.info("Connected to IPC server");
|
|
14
16
|
});
|
|
15
17
|
socket.on("error", (err) => {
|
|
16
|
-
|
|
18
|
+
logger.error("IPC client connection error:", err);
|
|
17
19
|
});
|
|
18
20
|
return new RPC(socket, handleRequest);
|
|
19
21
|
}
|
|
@@ -5,6 +5,7 @@ import { handleLoadModel } from "./handlers/load-model.js";
|
|
|
5
5
|
import { handleLoadModelDelegated } from "./handlers/load-model-delegated.js";
|
|
6
6
|
import { handleCompletionStreamDelegated } from "./handlers/completion-stream-delegated.js";
|
|
7
7
|
import { getModelEntry } from "../bare/registry/model-registry.js";
|
|
8
|
+
import { setSDKConfig } from "../bare/registry/config-registry.js";
|
|
8
9
|
import { handleUnloadModel } from "./handlers/unload-model.js";
|
|
9
10
|
import { handleTranscribeStream } from "./handlers/transcribe-stream.js";
|
|
10
11
|
import { handleEmbed } from "./handlers/embed.js";
|
|
@@ -16,7 +17,6 @@ import { stopProvideHandler } from "./handlers/stopProvideHandler.js";
|
|
|
16
17
|
import { handleRag } from "./handlers/rag.js";
|
|
17
18
|
import { handleDeleteCache } from "./handlers/delete-cache.js";
|
|
18
19
|
import { handleTextToSpeech } from "./handlers/text-to-speech.js";
|
|
19
|
-
import { handleSetConfig } from "./handlers/set-config.js";
|
|
20
20
|
import { handleGetModelInfo } from "./handlers/get-model-info.js";
|
|
21
21
|
import { sendErrorResponse, sendStreamErrorResponse, } from "../error-handlers.js";
|
|
22
22
|
import { NoDataReceivedError, UnknownRequestTypeError, } from "../../utils/errors-client.js";
|
|
@@ -27,6 +27,24 @@ export async function handleRequest(req) {
|
|
|
27
27
|
throw new NoDataReceivedError();
|
|
28
28
|
}
|
|
29
29
|
const jsonData = JSON.parse(rawData);
|
|
30
|
+
// Handle special internal config initialization message
|
|
31
|
+
if (jsonData &&
|
|
32
|
+
typeof jsonData === "object" &&
|
|
33
|
+
"type" in jsonData &&
|
|
34
|
+
jsonData.type === "__init_config") {
|
|
35
|
+
try {
|
|
36
|
+
const configData = jsonData;
|
|
37
|
+
setSDKConfig(configData.config);
|
|
38
|
+
req.reply(JSON.stringify({ success: true }), "utf-8");
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
req.reply(JSON.stringify({
|
|
42
|
+
success: false,
|
|
43
|
+
error: error instanceof Error ? error.message : String(error),
|
|
44
|
+
}), "utf-8");
|
|
45
|
+
}
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
30
48
|
const request = requestSchema.parse(jsonData);
|
|
31
49
|
switch (request.type) {
|
|
32
50
|
case "downloadAsset": {
|
|
@@ -84,13 +102,19 @@ export async function handleRequest(req) {
|
|
|
84
102
|
sendStreamErrorResponse(stream, error);
|
|
85
103
|
}
|
|
86
104
|
}
|
|
105
|
+
else if (request.delegate) {
|
|
106
|
+
try {
|
|
107
|
+
const response = await handleLoadModelDelegated(request);
|
|
108
|
+
req.reply(JSON.stringify(responseSchema.parse(response)), "utf-8");
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
sendErrorResponse(req, error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
87
114
|
else {
|
|
88
|
-
//
|
|
115
|
+
// Load without progress/delegate, or reload config
|
|
89
116
|
try {
|
|
90
|
-
const
|
|
91
|
-
? handleLoadModelDelegated
|
|
92
|
-
: handleLoadModel;
|
|
93
|
-
const response = await handler(request);
|
|
117
|
+
const response = await handleLoadModel(request);
|
|
94
118
|
req.reply(JSON.stringify(responseSchema.parse(response)), "utf-8");
|
|
95
119
|
}
|
|
96
120
|
catch (error) {
|
|
@@ -245,16 +269,6 @@ export async function handleRequest(req) {
|
|
|
245
269
|
}
|
|
246
270
|
break;
|
|
247
271
|
}
|
|
248
|
-
case "setConfig": {
|
|
249
|
-
try {
|
|
250
|
-
const response = handleSetConfig(request);
|
|
251
|
-
req.reply(JSON.stringify(responseSchema.parse(response)), "utf-8");
|
|
252
|
-
}
|
|
253
|
-
catch (error) {
|
|
254
|
-
sendErrorResponse(req, error);
|
|
255
|
-
}
|
|
256
|
-
break;
|
|
257
|
-
}
|
|
258
272
|
case "getModelInfo": {
|
|
259
273
|
try {
|
|
260
274
|
const response = await handleGetModelInfo(request);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { cancel } from "../../bare/addons/index.js";
|
|
2
2
|
import { createCancelFunction } from "./load-model/download-manager.js";
|
|
3
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
4
|
+
const logger = getServerLogger();
|
|
3
5
|
export async function cancelHandler(request) {
|
|
4
6
|
try {
|
|
5
7
|
switch (request.operation) {
|
|
@@ -17,7 +19,7 @@ export async function cancelHandler(request) {
|
|
|
17
19
|
};
|
|
18
20
|
}
|
|
19
21
|
catch (error) {
|
|
20
|
-
|
|
22
|
+
logger.error("Error during cancellation:", error);
|
|
21
23
|
return {
|
|
22
24
|
type: "cancel",
|
|
23
25
|
success: false,
|
|
@@ -2,6 +2,8 @@ import { getModelEntry } from "../../bare/registry/model-registry.js";
|
|
|
2
2
|
import { getRPC } from "../../bare/delegate-rpc-client.js";
|
|
3
3
|
import { stream } from "../../../client/rpc/rpc-client.js";
|
|
4
4
|
import { ModelIsDelegatedError } from "../../../utils/errors-server.js";
|
|
5
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
6
|
+
const logger = getServerLogger();
|
|
5
7
|
export async function* handleCompletionStreamDelegated(request) {
|
|
6
8
|
// Get delegation info from model registry
|
|
7
9
|
const entry = getModelEntry(request.modelId);
|
|
@@ -10,7 +12,7 @@ export async function* handleCompletionStreamDelegated(request) {
|
|
|
10
12
|
}
|
|
11
13
|
const { topic, providerPublicKey, timeout } = entry.delegated;
|
|
12
14
|
try {
|
|
13
|
-
|
|
15
|
+
logger.debug(`📤 Sending delegated completionStream request to provider: ${providerPublicKey}${timeout ? `, timeout: ${timeout}ms` : ""}`);
|
|
14
16
|
// Create RPC instance for this HyperSwarm peer
|
|
15
17
|
const rpc = await getRPC(topic, providerPublicKey, { timeout });
|
|
16
18
|
// Use the regular stream function with the HyperSwarm RPC instance
|
|
@@ -21,7 +23,7 @@ export async function* handleCompletionStreamDelegated(request) {
|
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
catch (error) {
|
|
24
|
-
|
|
26
|
+
logger.error("Error in delegated completion stream:", error);
|
|
25
27
|
yield {
|
|
26
28
|
type: "completionStream",
|
|
27
29
|
token: `Error communicating with provider: ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { deleteCache as deleteCacheUtil } from "../../bare/addons/llamacpp/kv-cache-utils.js";
|
|
2
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
3
|
+
const logger = getServerLogger();
|
|
2
4
|
export async function handleDeleteCache(request) {
|
|
3
5
|
try {
|
|
4
6
|
if ("all" in request && request.all) {
|
|
@@ -19,7 +21,7 @@ export async function handleDeleteCache(request) {
|
|
|
19
21
|
};
|
|
20
22
|
}
|
|
21
23
|
catch (error) {
|
|
22
|
-
|
|
24
|
+
logger.error("Error deleting cache:", error);
|
|
23
25
|
return {
|
|
24
26
|
type: "deleteCache",
|
|
25
27
|
success: false,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { resolveModelPath } from "./load-model/resolve.js";
|
|
2
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
3
|
+
const logger = getServerLogger();
|
|
2
4
|
export async function handleDownloadAsset(request, progressCallback) {
|
|
3
5
|
const { assetSrc, seed } = request;
|
|
4
6
|
try {
|
|
@@ -10,7 +12,7 @@ export async function handleDownloadAsset(request, progressCallback) {
|
|
|
10
12
|
};
|
|
11
13
|
}
|
|
12
14
|
catch (error) {
|
|
13
|
-
|
|
15
|
+
logger.error("Error downloading asset:", error);
|
|
14
16
|
return {
|
|
15
17
|
type: "downloadAsset",
|
|
16
18
|
success: false,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { embed } from "../../bare/addons/llamacpp/index.js";
|
|
2
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
3
|
+
const logger = getServerLogger();
|
|
2
4
|
export async function handleEmbed(request) {
|
|
3
5
|
const { modelId, text } = request;
|
|
4
6
|
try {
|
|
@@ -10,7 +12,7 @@ export async function handleEmbed(request) {
|
|
|
10
12
|
};
|
|
11
13
|
}
|
|
12
14
|
catch (error) {
|
|
13
|
-
|
|
15
|
+
logger.error("Error during embedding:", error);
|
|
14
16
|
return {
|
|
15
17
|
type: "embed",
|
|
16
18
|
success: false,
|
|
@@ -27,7 +27,6 @@ export declare const handlers: {
|
|
|
27
27
|
rag: typeof handleRag;
|
|
28
28
|
cancel: typeof cancelHandler;
|
|
29
29
|
textToSpeech: typeof handleTextToSpeech;
|
|
30
|
-
setConfig: (request: import("../../../schemas").SetConfigRequest) => import("../../../schemas").SetConfigResponse;
|
|
31
30
|
getModelInfo: (request: import("../../../schemas").GetModelInfoRequest) => Promise<import("../../../schemas").GetModelInfoResponse>;
|
|
32
31
|
};
|
|
33
32
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -12,7 +12,6 @@ import { handleRag } from "./rag.js";
|
|
|
12
12
|
import { cancelHandler } from "./cancelHandler.js";
|
|
13
13
|
import { handleDeleteCache } from "./delete-cache.js";
|
|
14
14
|
import { handleTextToSpeech } from "./text-to-speech.js";
|
|
15
|
-
import { handleSetConfig } from "./set-config.js";
|
|
16
15
|
import { handleGetModelInfo } from "./get-model-info.js";
|
|
17
16
|
export const handlers = {
|
|
18
17
|
completionStream: handleCompletionStream,
|
|
@@ -29,6 +28,5 @@ export const handlers = {
|
|
|
29
28
|
rag: handleRag,
|
|
30
29
|
cancel: cancelHandler,
|
|
31
30
|
textToSpeech: handleTextToSpeech,
|
|
32
|
-
setConfig: handleSetConfig,
|
|
33
31
|
getModelInfo: handleGetModelInfo,
|
|
34
32
|
};
|