@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
|
@@ -1,51 +1,53 @@
|
|
|
1
1
|
import { getSwarm, registerProviderTopic } from "../../../bare/hyperswarm.js";
|
|
2
2
|
import { setupConnectionHandlers } from "./connection.js";
|
|
3
|
+
import { getServerLogger } from "../../../../logging/index.js";
|
|
4
|
+
const logger = getServerLogger();
|
|
3
5
|
export async function provideHandler(request) {
|
|
4
6
|
const swarm = getSwarm({
|
|
5
7
|
firewallConfig: request.firewall,
|
|
6
8
|
});
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
logger.debug("🚀 Provide request received:", request);
|
|
10
|
+
logger.debug("🔍 Swarm keyPair exists:", !!swarm.keyPair);
|
|
11
|
+
logger.debug("🔍 Swarm publicKey:", swarm.keyPair?.publicKey?.toString("hex")?.substring(0, 16));
|
|
10
12
|
try {
|
|
11
|
-
|
|
13
|
+
logger.debug("⚡ Starting provide handler execution");
|
|
12
14
|
const pubKey = swarm.keyPair.publicKey;
|
|
13
|
-
|
|
15
|
+
logger.debug("🔑 Got public key:", pubKey.toString("hex"));
|
|
14
16
|
// Use provided topic from hex string
|
|
15
17
|
const topic = Buffer.from(request.topic, "hex");
|
|
16
18
|
// Join topic as server (provider)
|
|
17
|
-
|
|
19
|
+
logger.info("🌐 Joining topic as server...");
|
|
18
20
|
const discovery = swarm.join(topic, { server: true, client: false });
|
|
19
|
-
|
|
21
|
+
logger.debug("📡 Discovery object created:", !!discovery);
|
|
20
22
|
// Wait for the topic to be fully announced on the DHT
|
|
21
|
-
|
|
23
|
+
logger.debug("⏳ Waiting for topic announcement...");
|
|
22
24
|
await discovery.flushed();
|
|
23
|
-
|
|
25
|
+
logger.info(`✅ Topic announced: ${topic.toString("hex")}`);
|
|
24
26
|
// Wait for connections
|
|
25
|
-
|
|
27
|
+
logger.debug("⏳ Waiting for swarm flush...");
|
|
26
28
|
await swarm.flush();
|
|
27
|
-
|
|
29
|
+
logger.info(`🎯 Ready to accept connections on topic: ${topic.toString("hex").substring(0, 16)}...`);
|
|
28
30
|
// Handle incoming connections
|
|
29
31
|
setupConnectionHandlers(swarm);
|
|
30
32
|
registerProviderTopic(topic.toString("hex"));
|
|
31
|
-
|
|
33
|
+
logger.debug("🏁 About to return success response...");
|
|
32
34
|
const response = {
|
|
33
35
|
type: "provide",
|
|
34
36
|
success: true,
|
|
35
37
|
publicKey: pubKey.toString("hex"),
|
|
36
38
|
};
|
|
37
|
-
|
|
39
|
+
logger.debug("📤 Returning response:", response);
|
|
38
40
|
return response;
|
|
39
41
|
}
|
|
40
42
|
catch (error) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
logger.error("❌ Error in provide handler:", error);
|
|
44
|
+
logger.error("❌ Error stack:", error instanceof Error ? error.stack : "No stack trace");
|
|
43
45
|
const errorResponse = {
|
|
44
46
|
type: "provide",
|
|
45
47
|
success: false,
|
|
46
48
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
47
49
|
};
|
|
48
|
-
|
|
50
|
+
logger.debug("📤 Returning error response:", errorResponse);
|
|
49
51
|
return errorResponse;
|
|
50
52
|
}
|
|
51
53
|
}
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { handleRequest } from "../../handle-request.js";
|
|
2
|
+
import { getServerLogger } from "../../../../logging/index.js";
|
|
3
|
+
const logger = getServerLogger();
|
|
2
4
|
// Proxies RPC requests to the main handler: handleRequest
|
|
3
5
|
export function createRpcProxy() {
|
|
4
6
|
return async (rpcRequest) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
logger.debug("📬 RPC request callback triggered!");
|
|
8
|
+
logger.debug("📦 Raw RPC request data:", rpcRequest.data?.toString());
|
|
7
9
|
try {
|
|
8
|
-
|
|
10
|
+
logger.debug("🚀 Calling handleRequest...");
|
|
9
11
|
await handleRequest(rpcRequest);
|
|
10
|
-
|
|
12
|
+
logger.debug("✅ handleRequest completed successfully");
|
|
11
13
|
}
|
|
12
14
|
catch (error) {
|
|
13
|
-
|
|
15
|
+
logger.error("❌ Error:", error instanceof Error ? error.message : error);
|
|
14
16
|
const errorResponse = JSON.stringify({
|
|
15
17
|
type: "error",
|
|
16
18
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
17
19
|
});
|
|
18
|
-
|
|
20
|
+
logger.debug("📤 Sending error response:", errorResponse);
|
|
19
21
|
rpcRequest.reply(errorResponse, "utf-8");
|
|
20
22
|
}
|
|
21
23
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { saveEmbeddings, search, deleteEmbeddings, } from "../../bare/rag-hyperdb/index.js";
|
|
2
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
3
|
+
const logger = getServerLogger();
|
|
2
4
|
export async function handleRag(request) {
|
|
3
5
|
try {
|
|
4
6
|
switch (request.operation) {
|
|
@@ -32,7 +34,7 @@ export async function handleRag(request) {
|
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
catch (error) {
|
|
35
|
-
|
|
37
|
+
logger.error("Error in RAG handler:", error);
|
|
36
38
|
const baseError = {
|
|
37
39
|
type: "rag",
|
|
38
40
|
success: false,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { getSwarm, unregisterProviderTopic } from "../../bare/hyperswarm.js";
|
|
2
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
3
|
+
const logger = getServerLogger();
|
|
2
4
|
export function stopProvideHandler(request) {
|
|
3
5
|
const swarm = getSwarm();
|
|
4
6
|
try {
|
|
@@ -12,7 +14,7 @@ export function stopProvideHandler(request) {
|
|
|
12
14
|
};
|
|
13
15
|
}
|
|
14
16
|
catch (error) {
|
|
15
|
-
|
|
17
|
+
logger.error("❌ Error in stop provide handler:", error);
|
|
16
18
|
return {
|
|
17
19
|
type: "stopProvide",
|
|
18
20
|
success: false,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { transcribeStream } from "../../bare/addons/whispercpp/index.js";
|
|
2
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
3
|
+
const logger = getServerLogger();
|
|
2
4
|
export async function* handleTranscribeStream(request) {
|
|
3
5
|
const { modelId, audioChunk, prompt } = request;
|
|
4
6
|
try {
|
|
@@ -20,7 +22,7 @@ export async function* handleTranscribeStream(request) {
|
|
|
20
22
|
};
|
|
21
23
|
}
|
|
22
24
|
catch (error) {
|
|
23
|
-
|
|
25
|
+
logger.error("Error during transcription:", error);
|
|
24
26
|
yield {
|
|
25
27
|
type: "transcribeStream",
|
|
26
28
|
text: "",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { translate } from "../../bare/addons/translation/index.js";
|
|
2
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
3
|
+
const logger = getServerLogger();
|
|
2
4
|
export async function* handleTranslate(request) {
|
|
3
5
|
const { modelId, text, stream, modelType } = request;
|
|
4
6
|
const from = request.modelType === "llm" ? request.from : undefined;
|
|
@@ -41,7 +43,7 @@ export async function* handleTranslate(request) {
|
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
45
|
catch (error) {
|
|
44
|
-
|
|
46
|
+
logger.error("Error during translation:", error);
|
|
45
47
|
yield {
|
|
46
48
|
type: "translate",
|
|
47
49
|
token: "",
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { unloadModel } from "../../bare/addons/index.js";
|
|
2
2
|
import { getRegistryStats } from "../../bare/registry/model-registry.js";
|
|
3
3
|
import { hasActiveProviders } from "../../bare/hyperswarm.js";
|
|
4
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
5
|
+
const logger = getServerLogger();
|
|
4
6
|
export async function handleUnloadModel(request) {
|
|
5
7
|
const { modelId, clearStorage } = request;
|
|
6
8
|
try {
|
|
7
|
-
|
|
9
|
+
logger.debug("Unloading model", modelId);
|
|
8
10
|
await unloadModel({ modelId, clearStorage });
|
|
9
11
|
const stats = getRegistryStats();
|
|
10
12
|
const modelsActive = stats.totalModels > 0;
|
|
@@ -17,7 +19,7 @@ export async function handleUnloadModel(request) {
|
|
|
17
19
|
};
|
|
18
20
|
}
|
|
19
21
|
catch (error) {
|
|
20
|
-
|
|
22
|
+
logger.error("Error during model unload:", error);
|
|
21
23
|
return {
|
|
22
24
|
type: "unloadModel",
|
|
23
25
|
success: false,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Readable } from "bare-stream";
|
|
2
|
+
import { type AudioFormat } from "../../../schemas/index";
|
|
2
3
|
export declare function needsDecoding(filePath: string): boolean;
|
|
3
|
-
export declare function decodeAudioToStream(inputPath: string): Promise<Readable>;
|
|
4
|
+
export declare function decodeAudioToStream(inputPath: string, audioFormat?: AudioFormat): Promise<Readable>;
|
|
4
5
|
//# sourceMappingURL=decoder.d.ts.map
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import fs from "bare-fs";
|
|
2
2
|
import path from "bare-path";
|
|
3
|
-
import
|
|
3
|
+
import { FFmpegDecoder } from "@qvac/decoder-audio";
|
|
4
4
|
import { FORMATS_NEEDING_DECODE } from "@qvac/decoder-audio/constants.js";
|
|
5
5
|
import { Readable } from "bare-stream";
|
|
6
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
7
|
+
import {} from "../../../schemas/index.js";
|
|
8
|
+
const logger = getServerLogger();
|
|
6
9
|
export function needsDecoding(filePath) {
|
|
7
10
|
const ext = path.extname(filePath).toLowerCase();
|
|
8
11
|
return FORMATS_NEEDING_DECODE.includes(ext);
|
|
9
12
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const DECODER_TIMEOUT_MS = 10000;
|
|
14
|
+
export async function decodeAudioToStream(inputPath, audioFormat = "s16le") {
|
|
15
|
+
const decoder = new FFmpegDecoder({
|
|
16
|
+
config: { audioFormat },
|
|
17
|
+
logger,
|
|
15
18
|
});
|
|
16
19
|
try {
|
|
17
20
|
await decoder.load();
|
|
@@ -20,22 +23,56 @@ export async function decodeAudioToStream(inputPath) {
|
|
|
20
23
|
const outputStream = new Readable({
|
|
21
24
|
read() { },
|
|
22
25
|
});
|
|
26
|
+
let hasReceivedData = false;
|
|
27
|
+
let hasEnded = false;
|
|
28
|
+
// Fallback timeout in case the decoder hangs without emitting any events
|
|
29
|
+
const timeoutId = setTimeout(() => {
|
|
30
|
+
if (!hasEnded) {
|
|
31
|
+
hasEnded = true;
|
|
32
|
+
const timeoutError = new Error(`Audio decoding timed out after ${DECODER_TIMEOUT_MS}ms for file: ${inputPath}`);
|
|
33
|
+
outputStream.destroy(timeoutError);
|
|
34
|
+
}
|
|
35
|
+
}, DECODER_TIMEOUT_MS);
|
|
23
36
|
response
|
|
24
37
|
.onUpdate((output) => {
|
|
38
|
+
hasReceivedData = true;
|
|
25
39
|
const bytes = new Uint8Array(output.outputArray);
|
|
26
40
|
outputStream.push(Buffer.from(bytes));
|
|
27
41
|
})
|
|
28
42
|
.onFinish(() => {
|
|
29
|
-
|
|
43
|
+
if (!hasEnded) {
|
|
44
|
+
hasEnded = true;
|
|
45
|
+
clearTimeout(timeoutId);
|
|
46
|
+
setImmediate(() => void decoder.unload());
|
|
47
|
+
if (!hasReceivedData) {
|
|
48
|
+
outputStream.destroy(new Error(`No audio data decoded from file: ${inputPath}`));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
outputStream.push(null);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
30
54
|
})
|
|
31
|
-
.
|
|
32
|
-
|
|
33
|
-
|
|
55
|
+
.onError((errorMessage) => {
|
|
56
|
+
if (!hasEnded) {
|
|
57
|
+
hasEnded = true;
|
|
58
|
+
clearTimeout(timeoutId);
|
|
59
|
+
setImmediate(() => void decoder.unload());
|
|
60
|
+
outputStream.destroy(new Error(errorMessage));
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
response.await().catch((error) => {
|
|
64
|
+
if (!hasEnded) {
|
|
65
|
+
hasEnded = true;
|
|
66
|
+
clearTimeout(timeoutId);
|
|
67
|
+
setImmediate(() => void decoder.unload());
|
|
68
|
+
outputStream.destroy(error instanceof Error ? error : new Error(String(error)));
|
|
69
|
+
}
|
|
34
70
|
});
|
|
35
71
|
return outputStream;
|
|
36
72
|
}
|
|
37
73
|
catch (error) {
|
|
38
|
-
|
|
74
|
+
await decoder.unload();
|
|
75
|
+
logger.error("Decoding failed:", error instanceof Error ? error.message : String(error));
|
|
39
76
|
throw error;
|
|
40
77
|
}
|
|
41
78
|
}
|
|
@@ -3,6 +3,8 @@ import path from "bare-path";
|
|
|
3
3
|
import { getEnv } from "../worker.js";
|
|
4
4
|
import { getConfiguredCacheDir } from "../bare/registry/config-registry.js";
|
|
5
5
|
import { calculateFileChecksum } from "./checksum.js";
|
|
6
|
+
import { getServerLogger } from "../../logging/index.js";
|
|
7
|
+
const logger = getServerLogger();
|
|
6
8
|
export const getCacheDir = (subDir) => {
|
|
7
9
|
const homeDir = getEnv().HOME_DIR;
|
|
8
10
|
const cacheDir = path.join(homeDir, ".qvac", subDir);
|
|
@@ -10,7 +12,7 @@ export const getCacheDir = (subDir) => {
|
|
|
10
12
|
fs.mkdirSync(cacheDir, { recursive: true });
|
|
11
13
|
}
|
|
12
14
|
catch (error) {
|
|
13
|
-
|
|
15
|
+
logger.error(`Error creating cache directory (${subDir}):`, error instanceof Error ? error.message : String(error));
|
|
14
16
|
}
|
|
15
17
|
return cacheDir;
|
|
16
18
|
};
|
|
@@ -20,7 +22,7 @@ export const getModelsCacheDir = () => {
|
|
|
20
22
|
fs.mkdirSync(configuredDir, { recursive: true });
|
|
21
23
|
}
|
|
22
24
|
catch (error) {
|
|
23
|
-
|
|
25
|
+
logger.error(`Error creating models cache directory:`, error instanceof Error ? error.message : String(error));
|
|
24
26
|
}
|
|
25
27
|
return configuredDir;
|
|
26
28
|
};
|
|
@@ -38,7 +40,7 @@ export function getShardedModelCacheDir(hyperdriveKey) {
|
|
|
38
40
|
fs.mkdirSync(shardDir, { recursive: true });
|
|
39
41
|
}
|
|
40
42
|
catch (error) {
|
|
41
|
-
|
|
43
|
+
logger.error(`Error creating sharded model cache directory:`, error instanceof Error ? error.message : String(error));
|
|
42
44
|
}
|
|
43
45
|
return shardDir;
|
|
44
46
|
}
|
|
@@ -66,14 +68,14 @@ export async function checkShardCompleteness(hyperdriveKey, shardFilenames, shar
|
|
|
66
68
|
try {
|
|
67
69
|
const stats = await fsPromises.stat(shardPath);
|
|
68
70
|
if (stats.size !== fileMeta.expectedSize) {
|
|
69
|
-
|
|
71
|
+
logger.warn(`File ${i + 1} size mismatch: expected ${fileMeta.expectedSize}, got ${stats.size}`);
|
|
70
72
|
invalidIndices.push(i);
|
|
71
73
|
continue;
|
|
72
74
|
}
|
|
73
75
|
if (fileMeta.sha256Checksum) {
|
|
74
76
|
const actualChecksum = await calculateFileChecksum(shardPath);
|
|
75
77
|
if (actualChecksum !== fileMeta.sha256Checksum) {
|
|
76
|
-
|
|
78
|
+
logger.warn(`File ${i + 1} checksum mismatch for ${fileMeta.filename}. Expected: ${fileMeta.sha256Checksum}. Actual: ${actualChecksum}. Will re-download.`);
|
|
77
79
|
invalidIndices.push(i);
|
|
78
80
|
}
|
|
79
81
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function transformConfigForReload(modelType, config) {
|
|
2
|
+
switch (modelType) {
|
|
3
|
+
case "whisper": {
|
|
4
|
+
const whisperConfig = config;
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
6
|
+
const { contextParams, miscConfig, ...whisperParams } = whisperConfig;
|
|
7
|
+
return {
|
|
8
|
+
whisperConfig: whisperParams,
|
|
9
|
+
...(miscConfig && { miscConfig }),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
case "llm":
|
|
13
|
+
case "embeddings":
|
|
14
|
+
case "nmt":
|
|
15
|
+
case "tts":
|
|
16
|
+
// Return as-is for now
|
|
17
|
+
return config;
|
|
18
|
+
default:
|
|
19
|
+
return config;
|
|
20
|
+
}
|
|
21
|
+
}
|
package/dist/server/worker.js
CHANGED
|
@@ -5,9 +5,24 @@ import { destroySwarm } from "./bare/hyperswarm.js";
|
|
|
5
5
|
import { closeAllRagInstances } from "./bare/rag-hyperdb/rag-manager.js";
|
|
6
6
|
import { cleanupDownloads } from "./rpc/handlers/load-model/download-manager.js";
|
|
7
7
|
import { unloadAllModels } from "./bare/registry/model-registry.js";
|
|
8
|
-
import { clearAllLoggingStreams } from "./bare/registry/logging-stream-registry.js";
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import { clearAllLoggingStreams, startLogBuffering, } from "./bare/registry/logging-stream-registry.js";
|
|
9
|
+
import { ADDON_NAMESPACES, createAddonLoggerCallback, clearAllAddonLoggers, getServerLogger, SDK_LOG_ID, } from "../logging/index.js";
|
|
10
|
+
import llmAddonLogging from "@qvac/llm-llamacpp/addonLogging.js";
|
|
11
|
+
import embedAddonLogging from "@qvac/embed-llamacpp/addonLogging.js";
|
|
12
|
+
import ttsAddonLogging from "@qvac/tts-onnx/addonLogging.js";
|
|
13
|
+
import whisperAddonLogging from "@qvac/transcription-whispercpp/addonLogging.js";
|
|
14
|
+
import nmtAddonLogging from "@qvac/translation-nmtcpp/addonLogging.js";
|
|
15
|
+
// Buffer SDK logs from startup so clients can receive them when they subscribe
|
|
16
|
+
startLogBuffering(SDK_LOG_ID);
|
|
17
|
+
const logger = getServerLogger();
|
|
18
|
+
logger.info("🐻 Hello from Bare");
|
|
19
|
+
logger.debug("Arguments to worker:", process.argv);
|
|
20
|
+
// Initialize addon logger callbacks
|
|
21
|
+
llmAddonLogging.setLogger(createAddonLoggerCallback(ADDON_NAMESPACES.LLAMACPP_LLM));
|
|
22
|
+
embedAddonLogging.setLogger(createAddonLoggerCallback(ADDON_NAMESPACES.LLAMACPP_EMBED));
|
|
23
|
+
ttsAddonLogging.setLogger(createAddonLoggerCallback(ADDON_NAMESPACES.TTS));
|
|
24
|
+
whisperAddonLogging.setLogger(createAddonLoggerCallback(ADDON_NAMESPACES.WHISPERCPP));
|
|
25
|
+
nmtAddonLogging.setLogger(createAddonLoggerCallback(ADDON_NAMESPACES.NMTCPP));
|
|
11
26
|
const defaultHomeDir = process.env["HOME"] || process.env["USERPROFILE"] || "/tmp";
|
|
12
27
|
let envConfig = { HOME_DIR: defaultHomeDir };
|
|
13
28
|
let hasRPCConfig = false;
|
|
@@ -17,11 +32,11 @@ if (process.argv[2]) {
|
|
|
17
32
|
const rpcArgs = JSON.parse(process.argv[2]);
|
|
18
33
|
envConfig = { ...envConfig, ...rpcArgs };
|
|
19
34
|
hasRPCConfig = true;
|
|
20
|
-
|
|
35
|
+
logger.info("Parsed RPC configuration from arguments");
|
|
21
36
|
}
|
|
22
37
|
catch {
|
|
23
38
|
// Not JSON or invalid - use defaults (direct mode)
|
|
24
|
-
|
|
39
|
+
logger.info("Using default configuration (direct mode)");
|
|
25
40
|
}
|
|
26
41
|
}
|
|
27
42
|
const validatedEnv = z
|
|
@@ -43,22 +58,22 @@ export function ensureRPCSetup() {
|
|
|
43
58
|
try {
|
|
44
59
|
const ipcSocketPath = validatedEnv.QVAC_IPC_SOCKET_PATH;
|
|
45
60
|
if (ipcSocketPath) {
|
|
46
|
-
|
|
61
|
+
logger.info(`Running in desktop mode, connecting to IPC socket: ${ipcSocketPath}`);
|
|
47
62
|
// Connect to the IPC server (Named Pipe or Unix Socket)
|
|
48
63
|
const rpc = createIPCClient(ipcSocketPath);
|
|
49
|
-
|
|
64
|
+
logger.debug("Desktop IPC client created?", !!rpc);
|
|
50
65
|
}
|
|
51
66
|
else {
|
|
52
|
-
|
|
67
|
+
logger.info("Running in BareKit IPC mode");
|
|
53
68
|
// Start the standard RPC server with BareKit IPC for mobile
|
|
54
69
|
createBareKitRPCServer();
|
|
55
70
|
}
|
|
56
|
-
|
|
57
|
-
|
|
71
|
+
logger.info("Bare worker started and listening for RPC requests");
|
|
72
|
+
logger.debug("Working directory:", process.cwd());
|
|
58
73
|
rpcInitialized = true;
|
|
59
74
|
}
|
|
60
75
|
catch (error) {
|
|
61
|
-
|
|
76
|
+
logger.error("Worker error:", error);
|
|
62
77
|
process.exit(1);
|
|
63
78
|
}
|
|
64
79
|
}
|
|
@@ -67,7 +82,17 @@ if (hasRPCConfig) {
|
|
|
67
82
|
ensureRPCSetup();
|
|
68
83
|
}
|
|
69
84
|
else {
|
|
70
|
-
|
|
85
|
+
logger.info("Running in direct mode - RPC setup will be lazy");
|
|
86
|
+
}
|
|
87
|
+
// Centralized logger cleanup
|
|
88
|
+
function clearLoggers() {
|
|
89
|
+
clearAllLoggingStreams();
|
|
90
|
+
clearAllAddonLoggers();
|
|
91
|
+
llmAddonLogging.releaseLogger();
|
|
92
|
+
embedAddonLogging.releaseLogger();
|
|
93
|
+
ttsAddonLogging.releaseLogger();
|
|
94
|
+
whisperAddonLogging.releaseLogger();
|
|
95
|
+
nmtAddonLogging.releaseLogger();
|
|
71
96
|
}
|
|
72
97
|
// Centralized cleanup for graceful shutdown
|
|
73
98
|
let isShuttingDown = false;
|
|
@@ -75,19 +100,19 @@ const shutdownHandler = async () => {
|
|
|
75
100
|
if (isShuttingDown)
|
|
76
101
|
return;
|
|
77
102
|
isShuttingDown = true;
|
|
78
|
-
|
|
103
|
+
logger.info("🐻 Bare worker shutdown signal received, cleaning up...");
|
|
79
104
|
try {
|
|
80
|
-
|
|
105
|
+
clearLoggers();
|
|
81
106
|
await Promise.allSettled([
|
|
82
107
|
destroySwarm(),
|
|
83
108
|
closeAllRagInstances(),
|
|
84
109
|
cleanupDownloads(),
|
|
85
110
|
unloadAllModels(),
|
|
86
111
|
]);
|
|
87
|
-
|
|
112
|
+
logger.info("✅ Cleanup completed successfully");
|
|
88
113
|
}
|
|
89
114
|
catch (error) {
|
|
90
|
-
|
|
115
|
+
logger.error("❌ Error during shutdown cleanup:", error);
|
|
91
116
|
}
|
|
92
117
|
process.exit(0);
|
|
93
118
|
};
|
|
@@ -56,6 +56,18 @@ export declare class SDKNotFoundInNodeModulesError extends QvacErrorBase {
|
|
|
56
56
|
export declare class WorkerFileNotFoundError extends QvacErrorBase {
|
|
57
57
|
constructor(workerPath: string, cause?: unknown);
|
|
58
58
|
}
|
|
59
|
+
export declare class ConfigFileNotFoundError extends QvacErrorBase {
|
|
60
|
+
constructor(searchPaths: string, cause?: unknown);
|
|
61
|
+
}
|
|
62
|
+
export declare class ConfigFileInvalidError extends QvacErrorBase {
|
|
63
|
+
constructor(filePath: string, reason: string, cause?: unknown);
|
|
64
|
+
}
|
|
65
|
+
export declare class ConfigFileParseFailedError extends QvacErrorBase {
|
|
66
|
+
constructor(filePath: string, error: string, cause?: unknown);
|
|
67
|
+
}
|
|
68
|
+
export declare class ConfigValidationFailedError extends QvacErrorBase {
|
|
69
|
+
constructor(errors: string, cause?: unknown);
|
|
70
|
+
}
|
|
59
71
|
export declare class ModelUnloadFailedError extends QvacErrorBase {
|
|
60
72
|
constructor(modelId?: string, cause?: unknown);
|
|
61
73
|
}
|
|
@@ -100,6 +100,26 @@ export class WorkerFileNotFoundError extends QvacErrorBase {
|
|
|
100
100
|
super(createErrorOptions(SDK_CLIENT_ERROR_CODES.WORKER_FILE_NOT_FOUND, [workerPath], cause));
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
+
export class ConfigFileNotFoundError extends QvacErrorBase {
|
|
104
|
+
constructor(searchPaths, cause) {
|
|
105
|
+
super(createErrorOptions(SDK_CLIENT_ERROR_CODES.CONFIG_FILE_NOT_FOUND, [searchPaths], cause));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export class ConfigFileInvalidError extends QvacErrorBase {
|
|
109
|
+
constructor(filePath, reason, cause) {
|
|
110
|
+
super(createErrorOptions(SDK_CLIENT_ERROR_CODES.CONFIG_FILE_INVALID, [filePath, reason], cause));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export class ConfigFileParseFailedError extends QvacErrorBase {
|
|
114
|
+
constructor(filePath, error, cause) {
|
|
115
|
+
super(createErrorOptions(SDK_CLIENT_ERROR_CODES.CONFIG_FILE_PARSE_FAILED, [filePath, error], cause));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export class ConfigValidationFailedError extends QvacErrorBase {
|
|
119
|
+
constructor(errors, cause) {
|
|
120
|
+
super(createErrorOptions(SDK_CLIENT_ERROR_CODES.CONFIG_VALIDATION_FAILED, [errors], cause));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
103
123
|
// ============== Operation Errors (Client-side wrappers for server operations) ==============
|
|
104
124
|
// These are used by client API to throw errors based on server responses
|
|
105
125
|
// They reference server error codes but are thrown on client side
|
|
@@ -68,6 +68,12 @@ export declare class CancelFailedError extends QvacErrorBase {
|
|
|
68
68
|
export declare class TextToSpeechFailedError extends QvacErrorBase {
|
|
69
69
|
constructor(details?: string, cause?: unknown);
|
|
70
70
|
}
|
|
71
|
+
export declare class ConfigReloadNotSupportedError extends QvacErrorBase {
|
|
72
|
+
constructor(modelId: string, cause?: unknown);
|
|
73
|
+
}
|
|
74
|
+
export declare class ModelTypeMismatchError extends QvacErrorBase {
|
|
75
|
+
constructor(expectedType: string, providedType: string, cause?: unknown);
|
|
76
|
+
}
|
|
71
77
|
export declare class RAGSaveFailedError extends QvacErrorBase {
|
|
72
78
|
constructor(details?: string, cause?: unknown);
|
|
73
79
|
}
|
|
@@ -125,6 +131,9 @@ export declare class CacheDirNotAbsoluteError extends QvacErrorBase {
|
|
|
125
131
|
export declare class CacheDirNotWritableError extends QvacErrorBase {
|
|
126
132
|
constructor(cacheDir: string, details?: string, cause?: unknown);
|
|
127
133
|
}
|
|
134
|
+
export declare class ConfigAlreadySetError extends QvacErrorBase {
|
|
135
|
+
constructor(cause?: unknown);
|
|
136
|
+
}
|
|
128
137
|
export declare class FFmpegNotAvailableError extends QvacErrorBase {
|
|
129
138
|
constructor(cause?: unknown);
|
|
130
139
|
}
|
|
@@ -120,6 +120,16 @@ export class TextToSpeechFailedError extends QvacErrorBase {
|
|
|
120
120
|
super(createErrorOptions(SDK_SERVER_ERROR_CODES.TEXT_TO_SPEECH_FAILED, details ? [details] : undefined, cause));
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
+
export class ConfigReloadNotSupportedError extends QvacErrorBase {
|
|
124
|
+
constructor(modelId, cause) {
|
|
125
|
+
super(createErrorOptions(SDK_SERVER_ERROR_CODES.CONFIG_RELOAD_NOT_SUPPORTED, [modelId], cause));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export class ModelTypeMismatchError extends QvacErrorBase {
|
|
129
|
+
constructor(expectedType, providedType, cause) {
|
|
130
|
+
super(createErrorOptions(SDK_SERVER_ERROR_CODES.MODEL_TYPE_MISMATCH, [expectedType, providedType], cause));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
123
133
|
// ============== RAG Operation Errors ==============
|
|
124
134
|
export class RAGSaveFailedError extends QvacErrorBase {
|
|
125
135
|
constructor(details, cause) {
|
|
@@ -218,6 +228,12 @@ export class CacheDirNotWritableError extends QvacErrorBase {
|
|
|
218
228
|
super(createErrorOptions(SDK_SERVER_ERROR_CODES.CACHE_DIR_NOT_WRITABLE, details ? [cacheDir, details] : [cacheDir], cause));
|
|
219
229
|
}
|
|
220
230
|
}
|
|
231
|
+
// ============== Config Operations Errors ==============
|
|
232
|
+
export class ConfigAlreadySetError extends QvacErrorBase {
|
|
233
|
+
constructor(cause) {
|
|
234
|
+
super(createErrorOptions(SDK_SERVER_ERROR_CODES.CONFIG_ALREADY_SET, undefined, cause));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
221
237
|
// ============== System/Runtime Errors ==============
|
|
222
238
|
export class FFmpegNotAvailableError extends QvacErrorBase {
|
|
223
239
|
constructor(cause) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { detectRuntime } from "./runtime.js";
|
|
2
|
+
export async function getProcessSafe() {
|
|
3
|
+
const runtime = detectRuntime();
|
|
4
|
+
if (runtime === "bare") {
|
|
5
|
+
try {
|
|
6
|
+
const bareProcess = await import("bare-process");
|
|
7
|
+
return bareProcess.default;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
if (typeof process !== "undefined") {
|
|
14
|
+
return process;
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Tool } from "../schemas/tools";
|
|
2
|
+
import type { McpClientInput } from "../schemas/mcp-adapter";
|
|
3
|
+
import type { ToolHandler } from "./tool-helpers";
|
|
4
|
+
export type { McpClient, McpClientInput } from "../schemas/mcp-adapter";
|
|
5
|
+
export type ToolHandlerMap = Map<string, ToolHandler>;
|
|
6
|
+
export type McpToolsResult = {
|
|
7
|
+
tools: Tool[];
|
|
8
|
+
handlers: ToolHandlerMap;
|
|
9
|
+
};
|
|
10
|
+
export declare function getMcpToolsWithHandlers(clients: McpClientInput[]): Promise<McpToolsResult>;
|
|
11
|
+
export declare function getMcpTools(clients: McpClientInput[]): Promise<Tool[]>;
|
|
12
|
+
//# sourceMappingURL=mcp-adapter.d.ts.map
|