@qvac/sdk 0.1.0-dev.1760648187.328e967
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/LICENSE +202 -0
- package/README.md +301 -0
- package/dist/client/api/cancel.d.ts +25 -0
- package/dist/client/api/cancel.js +37 -0
- package/dist/client/api/completion-stream.d.ts +50 -0
- package/dist/client/api/completion-stream.js +103 -0
- package/dist/client/api/download-asset.d.ts +39 -0
- package/dist/client/api/download-asset.js +72 -0
- package/dist/client/api/embed.d.ts +11 -0
- package/dist/client/api/embed.js +24 -0
- package/dist/client/api/index.d.ts +13 -0
- package/dist/client/api/index.js +12 -0
- package/dist/client/api/load-model.d.ts +98 -0
- package/dist/client/api/load-model.js +154 -0
- package/dist/client/api/logging-stream.d.ts +21 -0
- package/dist/client/api/logging-stream.js +32 -0
- package/dist/client/api/ping.d.ts +11 -0
- package/dist/client/api/ping.js +18 -0
- package/dist/client/api/provide.d.ts +18 -0
- package/dist/client/api/provide.js +27 -0
- package/dist/client/api/rag.d.ts +42 -0
- package/dist/client/api/rag.js +97 -0
- package/dist/client/api/transcribe.d.ts +24 -0
- package/dist/client/api/transcribe.js +52 -0
- package/dist/client/api/translate.d.ts +47 -0
- package/dist/client/api/translate.js +114 -0
- package/dist/client/api/unload-model.d.ts +11 -0
- package/dist/client/api/unload-model.js +26 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +1 -0
- package/dist/client/logging-stream-registry.d.ts +5 -0
- package/dist/client/logging-stream-registry.js +60 -0
- package/dist/client/rpc/bare-client.d.ts +112 -0
- package/dist/client/rpc/bare-client.js +82 -0
- package/dist/client/rpc/bare-rpc-client.d.ts +4 -0
- package/dist/client/rpc/bare-rpc-client.js +87 -0
- package/dist/client/rpc/expo-rpc-client.d.ts +3 -0
- package/dist/client/rpc/expo-rpc-client.js +57 -0
- package/dist/client/rpc/node-rpc-client.d.ts +9 -0
- package/dist/client/rpc/node-rpc-client.js +99 -0
- package/dist/client/rpc/rpc-client.d.ts +5 -0
- package/dist/client/rpc/rpc-client.js +91 -0
- package/dist/client/rpc/rpc-error.d.ts +19 -0
- package/dist/client/rpc/rpc-error.js +39 -0
- package/dist/constants/audio.d.ts +3 -0
- package/dist/constants/audio.js +17 -0
- package/dist/constants/index.d.ts +2 -0
- package/dist/constants/index.js +1 -0
- package/dist/examples/delegated-inference/consumer.d.ts +2 -0
- package/dist/examples/delegated-inference/consumer.js +56 -0
- package/dist/examples/delegated-inference/provider.d.ts +2 -0
- package/dist/examples/delegated-inference/provider.js +57 -0
- package/dist/examples/download-with-cancel.d.ts +2 -0
- package/dist/examples/download-with-cancel.js +46 -0
- package/dist/examples/embed-hyperdrive.d.ts +2 -0
- package/dist/examples/embed-hyperdrive.js +19 -0
- package/dist/examples/kv-cache-example.d.ts +2 -0
- package/dist/examples/kv-cache-example.js +74 -0
- package/dist/examples/llamacpp-file-logging.d.ts +2 -0
- package/dist/examples/llamacpp-file-logging.js +62 -0
- package/dist/examples/llamacpp-filesystem.d.ts +2 -0
- package/dist/examples/llamacpp-filesystem.js +40 -0
- package/dist/examples/llamacpp-http.d.ts +2 -0
- package/dist/examples/llamacpp-http.js +41 -0
- package/dist/examples/llamacpp-hyperdrive.d.ts +2 -0
- package/dist/examples/llamacpp-hyperdrive.js +39 -0
- package/dist/examples/llamacpp-multimodal.d.ts +2 -0
- package/dist/examples/llamacpp-multimodal.js +62 -0
- package/dist/examples/llamacpp-native-tools.d.ts +2 -0
- package/dist/examples/llamacpp-native-tools.js +64 -0
- package/dist/examples/llamacpp-tools-routing.d.ts +2 -0
- package/dist/examples/llamacpp-tools-routing.js +364 -0
- package/dist/examples/llamacpp-tools.d.ts +2 -0
- package/dist/examples/llamacpp-tools.js +81 -0
- package/dist/examples/multi-model-demo.d.ts +2 -0
- package/dist/examples/multi-model-demo.js +75 -0
- package/dist/examples/parallel-download.d.ts +2 -0
- package/dist/examples/parallel-download.js +21 -0
- package/dist/examples/rag/rag-chromadb.d.ts +2 -0
- package/dist/examples/rag/rag-chromadb.js +130 -0
- package/dist/examples/rag/rag-hyperdb-workspaces.d.ts +2 -0
- package/dist/examples/rag/rag-hyperdb-workspaces.js +106 -0
- package/dist/examples/rag/rag-hyperdb.d.ts +2 -0
- package/dist/examples/rag/rag-hyperdb.js +50 -0
- package/dist/examples/rag/rag-lancedb.d.ts +2 -0
- package/dist/examples/rag/rag-lancedb.js +95 -0
- package/dist/examples/rag/rag-sqlite.d.ts +2 -0
- package/dist/examples/rag/rag-sqlite.js +107 -0
- package/dist/examples/seed-hyperdrive.d.ts +2 -0
- package/dist/examples/seed-hyperdrive.js +21 -0
- package/dist/examples/translation/translation-indic.d.ts +2 -0
- package/dist/examples/translation/translation-indic.js +30 -0
- package/dist/examples/translation/translation-llm-context.d.ts +2 -0
- package/dist/examples/translation/translation-llm-context.js +30 -0
- package/dist/examples/translation/translation-llm.d.ts +2 -0
- package/dist/examples/translation/translation-llm.js +38 -0
- package/dist/examples/translation/translation-opus.d.ts +2 -0
- package/dist/examples/translation/translation-opus.js +30 -0
- package/dist/examples/translation/translation-stream.d.ts +2 -0
- package/dist/examples/translation/translation-stream.js +35 -0
- package/dist/examples/whispercpp-filesystem.d.ts +2 -0
- package/dist/examples/whispercpp-filesystem.js +43 -0
- package/dist/examples/whispercpp-microphone-record.d.ts +2 -0
- package/dist/examples/whispercpp-microphone-record.js +311 -0
- package/dist/expo/plugins/index.d.ts +5 -0
- package/dist/expo/plugins/index.js +5 -0
- package/dist/expo/plugins/withMobileBundle.d.ts +8 -0
- package/dist/expo/plugins/withMobileBundle.js +60 -0
- package/dist/expo/plugins/withOpenCL.d.ts +9 -0
- package/dist/expo/plugins/withOpenCL.js +118 -0
- package/dist/expo/plugins/withQvacSDK.d.ts +9 -0
- package/dist/expo/plugins/withQvacSDK.js +13 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/logging/base-logger.d.ts +7 -0
- package/dist/logging/base-logger.js +55 -0
- package/dist/logging/index.d.ts +4 -0
- package/dist/logging/index.js +2 -0
- package/dist/logging/logger.d.ts +5 -0
- package/dist/logging/logger.js +28 -0
- package/dist/logging/stream-logger.d.ts +3 -0
- package/dist/logging/stream-logger.js +9 -0
- package/dist/logging/transport.d.ts +3 -0
- package/dist/logging/transport.js +15 -0
- package/dist/logging/types.d.ts +18 -0
- package/dist/logging/types.js +1 -0
- package/dist/logging/utils.d.ts +4 -0
- package/dist/logging/utils.js +47 -0
- package/dist/models/hyperdrive/index.d.ts +2 -0
- package/dist/models/hyperdrive/index.js +2 -0
- package/dist/models/hyperdrive/models.d.ts +475 -0
- package/dist/models/hyperdrive/models.js +534 -0
- package/dist/schemas/cancel.d.ts +33 -0
- package/dist/schemas/cancel.js +25 -0
- package/dist/schemas/common.d.ts +626 -0
- package/dist/schemas/common.js +47 -0
- package/dist/schemas/completion-stream.d.ts +125 -0
- package/dist/schemas/completion-stream.js +53 -0
- package/dist/schemas/delegate.d.ts +9 -0
- package/dist/schemas/delegate.js +9 -0
- package/dist/schemas/download-asset.d.ts +75 -0
- package/dist/schemas/download-asset.js +43 -0
- package/dist/schemas/embed.d.ts +20 -0
- package/dist/schemas/embed.js +14 -0
- package/dist/schemas/error.d.ts +13 -0
- package/dist/schemas/error.js +35 -0
- package/dist/schemas/index.d.ts +19 -0
- package/dist/schemas/index.js +19 -0
- package/dist/schemas/llamacpp-config.d.ts +30 -0
- package/dist/schemas/llamacpp-config.js +39 -0
- package/dist/schemas/load-model.d.ts +1259 -0
- package/dist/schemas/load-model.js +108 -0
- package/dist/schemas/logging-stream.d.ts +27 -0
- package/dist/schemas/logging-stream.js +16 -0
- package/dist/schemas/ping.d.ts +11 -0
- package/dist/schemas/ping.js +8 -0
- package/dist/schemas/provide.d.ts +43 -0
- package/dist/schemas/provide.js +25 -0
- package/dist/schemas/rag.d.ts +159 -0
- package/dist/schemas/rag.js +78 -0
- package/dist/schemas/transcription.d.ts +24 -0
- package/dist/schemas/transcription.js +15 -0
- package/dist/schemas/translate.d.ts +82 -0
- package/dist/schemas/translate.js +42 -0
- package/dist/schemas/translation-config.d.ts +83 -0
- package/dist/schemas/translation-config.js +46 -0
- package/dist/schemas/unload-model.d.ts +19 -0
- package/dist/schemas/unload-model.js +13 -0
- package/dist/schemas/whispercpp-config.d.ts +25 -0
- package/dist/schemas/whispercpp-config.js +18 -0
- package/dist/server/bare/addons/cancel.d.ts +3 -0
- package/dist/server/bare/addons/cancel.js +12 -0
- package/dist/server/bare/addons/index.d.ts +4 -0
- package/dist/server/bare/addons/index.js +3 -0
- package/dist/server/bare/addons/llamacpp/create-model.d.ts +5 -0
- package/dist/server/bare/addons/llamacpp/create-model.js +57 -0
- package/dist/server/bare/addons/llamacpp/handlers/completion-stream.d.ts +3 -0
- package/dist/server/bare/addons/llamacpp/handlers/completion-stream.js +65 -0
- package/dist/server/bare/addons/llamacpp/handlers/embed.d.ts +4 -0
- package/dist/server/bare/addons/llamacpp/handlers/embed.js +40 -0
- package/dist/server/bare/addons/llamacpp/index.d.ts +4 -0
- package/dist/server/bare/addons/llamacpp/index.js +3 -0
- package/dist/server/bare/addons/llamacpp/kv-cache-utils.d.ts +19 -0
- package/dist/server/bare/addons/llamacpp/kv-cache-utils.js +46 -0
- package/dist/server/bare/addons/load-model.d.ts +3 -0
- package/dist/server/bare/addons/load-model.js +55 -0
- package/dist/server/bare/addons/translation/create-model.d.ts +4 -0
- package/dist/server/bare/addons/translation/create-model.js +45 -0
- package/dist/server/bare/addons/translation/handlers/translate.d.ts +3 -0
- package/dist/server/bare/addons/translation/handlers/translate.js +86 -0
- package/dist/server/bare/addons/translation/index.d.ts +3 -0
- package/dist/server/bare/addons/translation/index.js +2 -0
- package/dist/server/bare/addons/unload-model.d.ts +3 -0
- package/dist/server/bare/addons/unload-model.js +20 -0
- package/dist/server/bare/addons/whispercpp/create-model.d.ts +6 -0
- package/dist/server/bare/addons/whispercpp/create-model.js +55 -0
- package/dist/server/bare/addons/whispercpp/handlers/transcribe-stream.d.ts +3 -0
- package/dist/server/bare/addons/whispercpp/handlers/transcribe-stream.js +42 -0
- package/dist/server/bare/addons/whispercpp/index.d.ts +3 -0
- package/dist/server/bare/addons/whispercpp/index.js +2 -0
- package/dist/server/bare/delegate-rpc-client.d.ts +4 -0
- package/dist/server/bare/delegate-rpc-client.js +70 -0
- package/dist/server/bare/hyperswarm.d.ts +7 -0
- package/dist/server/bare/hyperswarm.js +62 -0
- package/dist/server/bare/rag-hyperdb/handlers/delete-embeddings.d.ts +3 -0
- package/dist/server/bare/rag-hyperdb/handlers/delete-embeddings.js +12 -0
- package/dist/server/bare/rag-hyperdb/handlers/save-embeddings.d.ts +6 -0
- package/dist/server/bare/rag-hyperdb/handlers/save-embeddings.js +16 -0
- package/dist/server/bare/rag-hyperdb/handlers/search.d.ts +3 -0
- package/dist/server/bare/rag-hyperdb/handlers/search.js +15 -0
- package/dist/server/bare/rag-hyperdb/index.d.ts +5 -0
- package/dist/server/bare/rag-hyperdb/index.js +4 -0
- package/dist/server/bare/rag-hyperdb/rag-manager.d.ts +5 -0
- package/dist/server/bare/rag-hyperdb/rag-manager.js +61 -0
- package/dist/server/bare/registry/logging-stream-registry.d.ts +12 -0
- package/dist/server/bare/registry/logging-stream-registry.js +46 -0
- package/dist/server/bare/registry/model-registry.d.ts +64 -0
- package/dist/server/bare/registry/model-registry.js +95 -0
- package/dist/server/error-handlers.d.ts +4 -0
- package/dist/server/error-handlers.js +27 -0
- package/dist/server/http-server.d.ts +2 -0
- package/dist/server/http-server.js +189 -0
- package/dist/server/rpc/create-server.d.ts +4 -0
- package/dist/server/rpc/create-server.js +19 -0
- package/dist/server/rpc/handle-request.d.ts +12 -0
- package/dist/server/rpc/handle-request.js +220 -0
- package/dist/server/rpc/handlers/cancelHandler.d.ts +3 -0
- package/dist/server/rpc/handlers/cancelHandler.js +27 -0
- package/dist/server/rpc/handlers/completion-stream-delegated.d.ts +3 -0
- package/dist/server/rpc/handlers/completion-stream-delegated.js +30 -0
- package/dist/server/rpc/handlers/completion-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/completion-stream.js +52 -0
- package/dist/server/rpc/handlers/download-asset.d.ts +3 -0
- package/dist/server/rpc/handlers/download-asset.js +21 -0
- package/dist/server/rpc/handlers/embed.d.ts +3 -0
- package/dist/server/rpc/handlers/embed.js +21 -0
- package/dist/server/rpc/handlers/index.d.ts +23 -0
- package/dist/server/rpc/handlers/index.js +22 -0
- package/dist/server/rpc/handlers/load-model/download-manager.d.ts +31 -0
- package/dist/server/rpc/handlers/load-model/download-manager.js +88 -0
- package/dist/server/rpc/handlers/load-model/http.d.ts +3 -0
- package/dist/server/rpc/handlers/load-model/http.js +337 -0
- package/dist/server/rpc/handlers/load-model/hyperdrive.d.ts +4 -0
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +332 -0
- package/dist/server/rpc/handlers/load-model/index.d.ts +4 -0
- package/dist/server/rpc/handlers/load-model/index.js +3 -0
- package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -0
- package/dist/server/rpc/handlers/load-model/resolve.js +121 -0
- package/dist/server/rpc/handlers/load-model-delegated.d.ts +3 -0
- package/dist/server/rpc/handlers/load-model-delegated.js +93 -0
- package/dist/server/rpc/handlers/load-model.d.ts +3 -0
- package/dist/server/rpc/handlers/load-model.js +41 -0
- package/dist/server/rpc/handlers/logging-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/logging-stream.js +37 -0
- package/dist/server/rpc/handlers/provideHandler/connection.d.ts +3 -0
- package/dist/server/rpc/handlers/provideHandler/connection.js +25 -0
- package/dist/server/rpc/handlers/provideHandler/handler.d.ts +3 -0
- package/dist/server/rpc/handlers/provideHandler/handler.js +50 -0
- package/dist/server/rpc/handlers/provideHandler/proxy.d.ts +3 -0
- package/dist/server/rpc/handlers/provideHandler/proxy.js +22 -0
- package/dist/server/rpc/handlers/provideHandler.d.ts +2 -0
- package/dist/server/rpc/handlers/provideHandler.js +2 -0
- package/dist/server/rpc/handlers/rag.d.ts +3 -0
- package/dist/server/rpc/handlers/rag.js +67 -0
- package/dist/server/rpc/handlers/transcribe-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/transcribe-stream.js +26 -0
- package/dist/server/rpc/handlers/translate.d.ts +3 -0
- package/dist/server/rpc/handlers/translate.js +51 -0
- package/dist/server/rpc/handlers/unload-model.d.ts +3 -0
- package/dist/server/rpc/handlers/unload-model.js +20 -0
- package/dist/server/rpc/index.d.ts +3 -0
- package/dist/server/rpc/index.js +2 -0
- package/dist/server/utils/audio/decoder.d.ts +4 -0
- package/dist/server/utils/audio/decoder.js +41 -0
- package/dist/server/utils/cache.d.ts +15 -0
- package/dist/server/utils/cache.js +32 -0
- package/dist/server/utils/hash.d.ts +5 -0
- package/dist/server/utils/hash.js +11 -0
- package/dist/server/utils/index.d.ts +5 -0
- package/dist/server/utils/index.js +4 -0
- package/dist/server/utils/model-path.d.ts +5 -0
- package/dist/server/utils/model-path.js +7 -0
- package/dist/server/worker.d.ts +6 -0
- package/dist/server/worker.js +77 -0
- package/dist/utils/withTimeout.d.ts +11 -0
- package/dist/utils/withTimeout.js +37 -0
- package/package.json +129 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { getModel } from "../../../registry/model-registry.js";
|
|
2
|
+
import { translateServerParamsSchema, } from "../../../../../schemas/index.js";
|
|
3
|
+
export async function* translate(params) {
|
|
4
|
+
const { modelId, text, modelType } = params;
|
|
5
|
+
const from = params.modelType === "llm" ? params.from : undefined;
|
|
6
|
+
const to = params.modelType === "llm" ? params.to : undefined;
|
|
7
|
+
const context = params.modelType === "llm" ? params.context : undefined;
|
|
8
|
+
translateServerParamsSchema.parse(params);
|
|
9
|
+
const model = getModel(modelId);
|
|
10
|
+
// Prepare input based on model type
|
|
11
|
+
const input = modelType === "nmt"
|
|
12
|
+
? text
|
|
13
|
+
: [
|
|
14
|
+
{
|
|
15
|
+
role: "system",
|
|
16
|
+
content: `${context ? `${context}. ` : ""}Translate the following text from ${from?.toUpperCase()} into ${to?.toUpperCase()}.Only output the translation, nothing else.\n\n${from?.toUpperCase()}: ${text}\n${to?.toUpperCase()}:`,
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
const startTime = Date.now();
|
|
20
|
+
let processedTokens = 0;
|
|
21
|
+
const response = await model.run(input);
|
|
22
|
+
// Check if the response has an iterate method (like LLM models)
|
|
23
|
+
if (modelType === "llm" && typeof response.iterate === "function") {
|
|
24
|
+
for await (const token of response.iterate()) {
|
|
25
|
+
processedTokens++;
|
|
26
|
+
yield token;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// For models that don't support iterate, create an async iterator using onUpdate
|
|
31
|
+
const tokenQueue = [];
|
|
32
|
+
let isComplete = false;
|
|
33
|
+
let resolveNext = null;
|
|
34
|
+
// Start the response processing
|
|
35
|
+
const responsePromise = response
|
|
36
|
+
.onUpdate((data) => {
|
|
37
|
+
processedTokens++;
|
|
38
|
+
if (resolveNext) {
|
|
39
|
+
// If there's a pending read, resolve it immediately
|
|
40
|
+
resolveNext({ value: data, done: false });
|
|
41
|
+
resolveNext = null;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// Otherwise, queue the token
|
|
45
|
+
tokenQueue.push(data);
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.await()
|
|
49
|
+
.then(() => {
|
|
50
|
+
isComplete = true;
|
|
51
|
+
if (resolveNext) {
|
|
52
|
+
resolveNext({ value: undefined, done: true });
|
|
53
|
+
resolveNext = null;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// Create an async iterator
|
|
57
|
+
const asyncIterator = {
|
|
58
|
+
async next() {
|
|
59
|
+
if (tokenQueue.length > 0) {
|
|
60
|
+
return { value: tokenQueue.shift(), done: false };
|
|
61
|
+
}
|
|
62
|
+
if (isComplete) {
|
|
63
|
+
return { value: undefined, done: true };
|
|
64
|
+
}
|
|
65
|
+
// Wait for the next token
|
|
66
|
+
return new Promise((resolve) => {
|
|
67
|
+
resolveNext = resolve;
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
[Symbol.asyncIterator]() {
|
|
71
|
+
return this;
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
// Yield tokens as they come
|
|
75
|
+
for await (const token of asyncIterator) {
|
|
76
|
+
yield token;
|
|
77
|
+
}
|
|
78
|
+
// Ensure the response is fully processed
|
|
79
|
+
await responsePromise;
|
|
80
|
+
}
|
|
81
|
+
const endTime = Date.now();
|
|
82
|
+
return {
|
|
83
|
+
processedTokens,
|
|
84
|
+
processingTime: endTime - startTime,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { promises as fsPromises } from "bare-fs";
|
|
2
|
+
import { unregisterModel } from "../registry/model-registry.js";
|
|
3
|
+
import { unregisterAllLoggingStreams } from "../registry/logging-stream-registry.js";
|
|
4
|
+
import { unloadModelParamsSchema } from "../../../schemas/index.js";
|
|
5
|
+
export async function unloadModel(params) {
|
|
6
|
+
const { modelId, clearStorage } = unloadModelParamsSchema.parse(params);
|
|
7
|
+
const entry = unregisterModel(modelId);
|
|
8
|
+
if (!entry) {
|
|
9
|
+
throw new Error(`Model with ID "${modelId}" is not loaded`);
|
|
10
|
+
}
|
|
11
|
+
if (entry.local?.model && entry.local.model.unload) {
|
|
12
|
+
await entry.local.model.unload();
|
|
13
|
+
}
|
|
14
|
+
if (clearStorage && entry.local?.path) {
|
|
15
|
+
await fsPromises.rm(entry.local.path, { recursive: true, force: true });
|
|
16
|
+
console.log(`Model storage cleared: ${entry.local.path}`);
|
|
17
|
+
}
|
|
18
|
+
unregisterAllLoggingStreams(modelId);
|
|
19
|
+
console.log(`Model ${modelId} unloaded`);
|
|
20
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import TranscriptionWhispercpp from "@qvac/transcription-whispercpp";
|
|
2
|
+
import { type AnyModel } from "../../registry/model-registry";
|
|
3
|
+
import { type WhisperConfig } from "../../../../schemas/index";
|
|
4
|
+
export type WhispercppModel = TranscriptionWhispercpp;
|
|
5
|
+
export declare function createWhisperModel(modelId: string, modelPath: string, whisperConfig: WhisperConfig, vadModelPath?: string): AnyModel;
|
|
6
|
+
//# sourceMappingURL=create-model.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import TranscriptionWhispercpp from "@qvac/transcription-whispercpp";
|
|
2
|
+
import { Readable } from "bare-stream";
|
|
3
|
+
import {} from "../../registry/model-registry.js";
|
|
4
|
+
import {} from "../../../../schemas/index.js";
|
|
5
|
+
import { createStreamLogger } from "../../../../logging/index.js";
|
|
6
|
+
import { parseModelPath } from "../../../utils/index.js";
|
|
7
|
+
// Mimic qvac-lib-dl-filesystem functionality
|
|
8
|
+
function createFilesystemDLMimic(options) {
|
|
9
|
+
return {
|
|
10
|
+
dirPath: options.dirPath,
|
|
11
|
+
getStream: () => {
|
|
12
|
+
return Readable.from([]);
|
|
13
|
+
},
|
|
14
|
+
ready: () => Promise.resolve(),
|
|
15
|
+
close: () => Promise.resolve(),
|
|
16
|
+
destroy: () => Promise.resolve(),
|
|
17
|
+
getFileSize: () => Promise.resolve(0),
|
|
18
|
+
download: () => Promise.resolve({
|
|
19
|
+
await: () => Promise.resolve(),
|
|
20
|
+
}),
|
|
21
|
+
downloadFiles: () => Promise.resolve([]),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function createWhisperModel(modelId, modelPath, whisperConfig, vadModelPath) {
|
|
25
|
+
const { dirPath, basePath } = parseModelPath(modelPath);
|
|
26
|
+
// Handle VAD model path - now uses vadModelPath parameter for consistency
|
|
27
|
+
let vadModelName = "";
|
|
28
|
+
let vadDirPath = "./";
|
|
29
|
+
if (vadModelPath) {
|
|
30
|
+
const vadParsed = parseModelPath(vadModelPath);
|
|
31
|
+
vadDirPath = vadParsed.dirPath;
|
|
32
|
+
vadModelName = vadParsed.basePath;
|
|
33
|
+
}
|
|
34
|
+
const dl = createFilesystemDLMimic({
|
|
35
|
+
dirPath: vadDirPath,
|
|
36
|
+
});
|
|
37
|
+
const logger = createStreamLogger(modelId, "whispercpp");
|
|
38
|
+
const args = {
|
|
39
|
+
loader: dl,
|
|
40
|
+
logger,
|
|
41
|
+
modelName: basePath,
|
|
42
|
+
diskPath: dirPath,
|
|
43
|
+
vadModelName,
|
|
44
|
+
opts: {
|
|
45
|
+
stats: false,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
const config = {
|
|
49
|
+
whisperConfig: {
|
|
50
|
+
...whisperConfig,
|
|
51
|
+
vad_model: vadModelPath || "",
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
return new TranscriptionWhispercpp(args, config);
|
|
55
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getModel } from "../../../registry/model-registry.js";
|
|
2
|
+
import { Readable } from "bare-stream";
|
|
3
|
+
import fs from "bare-fs";
|
|
4
|
+
import { needsDecoding, decodeAudioToStream } from "../../../../utils/index.js";
|
|
5
|
+
import path from "bare-path";
|
|
6
|
+
import { transcribeParamsSchema } from "../../../../../schemas/index.js";
|
|
7
|
+
export async function* transcribe(params) {
|
|
8
|
+
const { audioChunk: audioInput, modelId } = transcribeParamsSchema.parse(params);
|
|
9
|
+
const model = getModel(modelId);
|
|
10
|
+
let audioStream;
|
|
11
|
+
// Check if it's a file path or base64 buffer
|
|
12
|
+
if (typeof audioInput === "string" &&
|
|
13
|
+
(audioInput.startsWith("/") || audioInput.includes("."))) {
|
|
14
|
+
// It's a file path - check if it needs decoding
|
|
15
|
+
if (needsDecoding(audioInput)) {
|
|
16
|
+
console.log(`Detected encoded format: ${path.extname(audioInput).toLowerCase()}, decoding before transcription...`);
|
|
17
|
+
audioStream = await decodeAudioToStream(audioInput);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
// File doesn't need decoding (e.g., RAW), create stream directly
|
|
21
|
+
audioStream = fs.createReadStream(audioInput);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// It's base64 encoded buffer - decode and create stream
|
|
26
|
+
const audioBuffer = Buffer.from(audioInput, "base64");
|
|
27
|
+
audioStream = Readable.from([audioBuffer]);
|
|
28
|
+
}
|
|
29
|
+
// Run transcription with streaming enabled
|
|
30
|
+
const response = await model.run(audioStream);
|
|
31
|
+
for await (const output of response.iterate()) {
|
|
32
|
+
console.log("Streaming Transcription Update:", output);
|
|
33
|
+
// Filter out blank audio chunks and process the text
|
|
34
|
+
const text = output
|
|
35
|
+
.filter((chunk) => !chunk.text.includes("[BLANK_AUDIO]"))
|
|
36
|
+
.map((chunk) => chunk.text)
|
|
37
|
+
.join("");
|
|
38
|
+
if (text.trim()) {
|
|
39
|
+
yield text;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { getSwarm } from "./hyperswarm.js";
|
|
2
|
+
import RPC from "bare-rpc";
|
|
3
|
+
import { withTimeout } from "../../utils/withTimeout.js";
|
|
4
|
+
// Map of active RPC instances by public key
|
|
5
|
+
const activeRPCs = new Map();
|
|
6
|
+
// Establish RPC connection to a peer if not already connected
|
|
7
|
+
async function ensureRPCConnection(topic, publicKey, timeout) {
|
|
8
|
+
// Check if we already have an RPC instance for this peer
|
|
9
|
+
let rpc = activeRPCs.get(publicKey);
|
|
10
|
+
const swarm = getSwarm();
|
|
11
|
+
if (!rpc) {
|
|
12
|
+
// Need to establish connection first
|
|
13
|
+
try {
|
|
14
|
+
console.log(`🔗 Establishing RPC connection to topic: ${topic}, peer: ${publicKey}, timeout: ${timeout}ms`);
|
|
15
|
+
const connectionPromise = (async () => {
|
|
16
|
+
const topicBuffer = Buffer.from(topic, "hex");
|
|
17
|
+
// const discovery =
|
|
18
|
+
swarm.join(topicBuffer, {
|
|
19
|
+
server: false,
|
|
20
|
+
client: true,
|
|
21
|
+
});
|
|
22
|
+
await swarm.flush();
|
|
23
|
+
console.log(`✅ Connected to topic: ${topic}`);
|
|
24
|
+
console.log(`📊 Active RPC connections: ${activeRPCs.size}`);
|
|
25
|
+
// Check again if we now have an RPC instance for the target peer
|
|
26
|
+
rpc = activeRPCs.get(publicKey);
|
|
27
|
+
if (!rpc) {
|
|
28
|
+
console.error(`❌ No RPC instance found for peer ${publicKey}`);
|
|
29
|
+
console.log(`📊 Available RPC connections:`, Array.from(activeRPCs.keys()));
|
|
30
|
+
throw new Error(`Could not establish RPC connection to peer ${publicKey} on topic ${topic}`);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.log(`✅ RPC instance found for peer ${publicKey}`);
|
|
34
|
+
}
|
|
35
|
+
})();
|
|
36
|
+
await withTimeout(connectionPromise, timeout);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error("Failed to establish RPC connection:", error);
|
|
40
|
+
throw new Error(`RPC connection failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return rpc;
|
|
44
|
+
}
|
|
45
|
+
// Create an RPC instance for a specific HyperSwarm peer
|
|
46
|
+
export async function getRPC(topic, publicKey, options = {}) {
|
|
47
|
+
const swarm = getSwarm();
|
|
48
|
+
// Set up connection tracking
|
|
49
|
+
swarm.on("connection", (conn) => {
|
|
50
|
+
const peerPubkey = conn.remotePublicKey?.toString("hex");
|
|
51
|
+
if (!peerPubkey)
|
|
52
|
+
return;
|
|
53
|
+
console.log(`🍺 New peer connection established: ${peerPubkey}`);
|
|
54
|
+
// Create RPC instance for this connection (as client)
|
|
55
|
+
const rpc = new RPC(conn, () => {
|
|
56
|
+
// No-op handler since we're only sending requests, not receiving them
|
|
57
|
+
});
|
|
58
|
+
// Store RPC instance by peer ID for lookup
|
|
59
|
+
activeRPCs.set(peerPubkey, rpc);
|
|
60
|
+
conn.on("close", () => {
|
|
61
|
+
console.log(`Connection closed for peer: ${peerPubkey}`);
|
|
62
|
+
activeRPCs.delete(peerPubkey);
|
|
63
|
+
});
|
|
64
|
+
conn.on("error", (err) => {
|
|
65
|
+
console.error(`Connection error for peer ${peerPubkey}:`, err);
|
|
66
|
+
activeRPCs.delete(peerPubkey);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
return await ensureRPCConnection(topic, publicKey, options.timeout);
|
|
70
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import Hyperswarm from "hyperswarm";
|
|
2
|
+
import { type FirewallConfig } from "../../schemas/provide";
|
|
3
|
+
export declare function getSwarm({ firewallConfig, }?: {
|
|
4
|
+
firewallConfig?: FirewallConfig | undefined;
|
|
5
|
+
}): Hyperswarm;
|
|
6
|
+
export declare function destroySwarm(): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=hyperswarm.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import process from "bare-process";
|
|
2
|
+
import Hyperswarm from "hyperswarm";
|
|
3
|
+
import crypto from "bare-crypto";
|
|
4
|
+
import { envSchema } from "../../schemas/provide.js";
|
|
5
|
+
function getHyperswarmSeedBuffer() {
|
|
6
|
+
const parsedEnv = envSchema.safeParse(process.env);
|
|
7
|
+
if (parsedEnv.success) {
|
|
8
|
+
return Buffer.from(parsedEnv.data.QVAC_HYPERSWARM_SEED, "hex");
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
console.log(`🎲 No seed provided, generating random seed (provider will have random identity)`);
|
|
12
|
+
return crypto.randomBytes(32);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function createFirewallFunction(config) {
|
|
16
|
+
if (!config || config.publicKeys.length === 0) {
|
|
17
|
+
return () => false;
|
|
18
|
+
}
|
|
19
|
+
const { mode, publicKeys } = config;
|
|
20
|
+
const publicKeySet = new Set(publicKeys);
|
|
21
|
+
return (remotePublicKey) => {
|
|
22
|
+
const remoteKeyHex = remotePublicKey.toString("hex");
|
|
23
|
+
if (mode === "allow") {
|
|
24
|
+
const allowed = publicKeySet.has(remoteKeyHex);
|
|
25
|
+
if (!allowed) {
|
|
26
|
+
console.log(`🚫 Firewall: Denied connection from ${remoteKeyHex.substring(0, 16)}... (not in allowlist)`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
console.log(`✅ Firewall: Allowed connection from ${remoteKeyHex.substring(0, 16)}... (in allowlist)`);
|
|
30
|
+
}
|
|
31
|
+
return !allowed;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const denied = publicKeySet.has(remoteKeyHex);
|
|
35
|
+
if (denied) {
|
|
36
|
+
console.log(`🚫 Firewall: Denied connection from ${remoteKeyHex.substring(0, 16)}... (in denylist)`);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.log(`✅ Firewall: Allowed connection from ${remoteKeyHex.substring(0, 16)}... (not in denylist)`);
|
|
40
|
+
}
|
|
41
|
+
return denied;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function createSwarm(firewallConfig) {
|
|
46
|
+
const seed = getHyperswarmSeedBuffer();
|
|
47
|
+
const firewall = createFirewallFunction(firewallConfig);
|
|
48
|
+
return new Hyperswarm({ seed, firewall });
|
|
49
|
+
}
|
|
50
|
+
let swarm;
|
|
51
|
+
export function getSwarm({ firewallConfig, } = {}) {
|
|
52
|
+
if (swarm) {
|
|
53
|
+
return swarm;
|
|
54
|
+
}
|
|
55
|
+
swarm = createSwarm(firewallConfig);
|
|
56
|
+
return swarm;
|
|
57
|
+
}
|
|
58
|
+
export async function destroySwarm() {
|
|
59
|
+
if (swarm) {
|
|
60
|
+
return swarm.destroy();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getRagInstance } from "../rag-manager.js";
|
|
2
|
+
import { embed } from "../../addons/llamacpp/index.js";
|
|
3
|
+
import { ragDeleteEmbeddingsOperationSchema, } from "../../../../schemas/index.js";
|
|
4
|
+
export async function deleteEmbeddings(params) {
|
|
5
|
+
const { modelId, ids, workspace } = ragDeleteEmbeddingsOperationSchema.parse(params);
|
|
6
|
+
const embeddingFunction = async (text) => {
|
|
7
|
+
return await embed({ modelId, text });
|
|
8
|
+
};
|
|
9
|
+
const rag = await getRagInstance(modelId, embeddingFunction, workspace);
|
|
10
|
+
const success = await rag.deleteEmbeddings(ids);
|
|
11
|
+
return success;
|
|
12
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type RagSaveEmbeddingsParams } from "../../../../schemas/index";
|
|
2
|
+
export declare function saveEmbeddings(params: RagSaveEmbeddingsParams): Promise<{
|
|
3
|
+
processed: import("@qvac/rag").SaveEmbeddingsResult[];
|
|
4
|
+
droppedIndices: number[];
|
|
5
|
+
}>;
|
|
6
|
+
//# sourceMappingURL=save-embeddings.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getRagInstance } from "../rag-manager.js";
|
|
2
|
+
import { embed } from "../../addons/llamacpp/index.js";
|
|
3
|
+
import { ragSaveEmbeddingsOperationSchema, } from "../../../../schemas/index.js";
|
|
4
|
+
export async function saveEmbeddings(params) {
|
|
5
|
+
const { modelId, documents, chunk, chunkOpts, workspace } = ragSaveEmbeddingsOperationSchema.parse(params);
|
|
6
|
+
const embeddingFunction = async (text) => {
|
|
7
|
+
return await embed({ modelId, text });
|
|
8
|
+
};
|
|
9
|
+
const rag = await getRagInstance(modelId, embeddingFunction, workspace);
|
|
10
|
+
const saveOpts = { chunk };
|
|
11
|
+
if (chunkOpts) {
|
|
12
|
+
saveOpts.chunkOpts = chunkOpts;
|
|
13
|
+
}
|
|
14
|
+
const result = await rag.saveEmbeddings(documents, saveOpts);
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getRagInstance } from "../rag-manager.js";
|
|
2
|
+
import { embed } from "../../addons/llamacpp/index.js";
|
|
3
|
+
import { ragSearchOperationSchema } from "../../../../schemas/index.js";
|
|
4
|
+
export async function search(params) {
|
|
5
|
+
const { modelId, query, topK, n, workspace } = ragSearchOperationSchema.parse(params);
|
|
6
|
+
const embeddingFunction = async (text) => {
|
|
7
|
+
return await embed({ modelId, text });
|
|
8
|
+
};
|
|
9
|
+
const rag = await getRagInstance(modelId, embeddingFunction, workspace);
|
|
10
|
+
const results = await rag.search(query, {
|
|
11
|
+
topK,
|
|
12
|
+
n,
|
|
13
|
+
});
|
|
14
|
+
return results;
|
|
15
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { saveEmbeddings } from "./handlers/save-embeddings";
|
|
2
|
+
export { search } from "./handlers/search";
|
|
3
|
+
export { deleteEmbeddings } from "./handlers/delete-embeddings";
|
|
4
|
+
export { closeRagInstance, closeAllRagInstances, } from "./rag-manager";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { RAG, type EmbeddingFunction } from "@qvac/rag";
|
|
2
|
+
export declare const getRagInstance: (modelId: string, embeddingFunction: EmbeddingFunction, workspace?: string) => Promise<RAG>;
|
|
3
|
+
export declare const closeRagInstance: (workspace?: string) => Promise<void>;
|
|
4
|
+
export declare const closeAllRagInstances: () => Promise<void>;
|
|
5
|
+
//# sourceMappingURL=rag-manager.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { RAG, HyperDBAdapter } from "@qvac/rag";
|
|
2
|
+
import Corestore from "corestore";
|
|
3
|
+
import path from "bare-path";
|
|
4
|
+
import process from "bare-process";
|
|
5
|
+
import { getEnv } from "../../worker.js";
|
|
6
|
+
const ragInstances = new Map();
|
|
7
|
+
const defaultWorkspace = "default";
|
|
8
|
+
const getStorePath = (workspace) => {
|
|
9
|
+
const homeDir = getEnv().HOME_DIR;
|
|
10
|
+
return path.join(homeDir, ".qvac", "rag-hyperdb", workspace);
|
|
11
|
+
};
|
|
12
|
+
export const getRagInstance = async (modelId, embeddingFunction, workspace) => {
|
|
13
|
+
const key = workspace ?? defaultWorkspace;
|
|
14
|
+
const existingEntry = ragInstances.get(key);
|
|
15
|
+
if (existingEntry) {
|
|
16
|
+
// Validate model consistency
|
|
17
|
+
if (existingEntry.modelId !== modelId) {
|
|
18
|
+
throw new Error(`Workspace "${key}" is configured for model "${existingEntry.modelId}", ` +
|
|
19
|
+
`but you're trying to use model "${modelId}". ` +
|
|
20
|
+
`Use a different workspace or the same model.`);
|
|
21
|
+
}
|
|
22
|
+
return existingEntry.rag;
|
|
23
|
+
}
|
|
24
|
+
// Create new instance for this workspace
|
|
25
|
+
const storePath = getStorePath(key);
|
|
26
|
+
const corestore = new Corestore(storePath);
|
|
27
|
+
// Create HyperDB adapter
|
|
28
|
+
const hyperdbAdapter = new HyperDBAdapter({
|
|
29
|
+
store: corestore,
|
|
30
|
+
});
|
|
31
|
+
const rag = new RAG({
|
|
32
|
+
dbAdapter: hyperdbAdapter,
|
|
33
|
+
embeddingFunction,
|
|
34
|
+
});
|
|
35
|
+
await rag.ready();
|
|
36
|
+
ragInstances.set(key, {
|
|
37
|
+
rag,
|
|
38
|
+
corestore,
|
|
39
|
+
modelId,
|
|
40
|
+
});
|
|
41
|
+
return rag;
|
|
42
|
+
};
|
|
43
|
+
export const closeRagInstance = async (workspace) => {
|
|
44
|
+
const key = workspace ?? defaultWorkspace;
|
|
45
|
+
const entry = ragInstances.get(key);
|
|
46
|
+
if (entry) {
|
|
47
|
+
await entry.rag.close();
|
|
48
|
+
ragInstances.delete(key);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export const closeAllRagInstances = async () => {
|
|
52
|
+
const closures = Array.from(ragInstances.entries()).map(async ([key, entry]) => {
|
|
53
|
+
await entry.rag.close();
|
|
54
|
+
ragInstances.delete(key);
|
|
55
|
+
});
|
|
56
|
+
await Promise.all(closures);
|
|
57
|
+
};
|
|
58
|
+
// Ensure cleanup on process exit
|
|
59
|
+
process.on("SIGINT", () => {
|
|
60
|
+
void closeAllRagInstances();
|
|
61
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LogLevel } from "@qvac/logging";
|
|
2
|
+
export declare function registerLoggingStream(modelId: string, streamHandler: (level: LogLevel, namespace: string, message: string) => void): void;
|
|
3
|
+
export declare function unregisterLoggingStream(modelId: string, streamHandler: (level: LogLevel, namespace: string, message: string) => void): void;
|
|
4
|
+
export declare function unregisterAllLoggingStreams(modelId: string): void;
|
|
5
|
+
export declare function sendLogToStreams(modelId: string, level: LogLevel, namespace: string, message: string): void;
|
|
6
|
+
export declare function hasLoggingStreams(modelId: string): boolean | undefined;
|
|
7
|
+
export declare function getLoggingStreamStats(): {
|
|
8
|
+
totalModels: number;
|
|
9
|
+
modelIds: string[];
|
|
10
|
+
totalStreams: number;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=logging-stream-registry.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const loggingStreams = new Map();
|
|
2
|
+
export function registerLoggingStream(modelId, streamHandler) {
|
|
3
|
+
if (!loggingStreams.has(modelId)) {
|
|
4
|
+
loggingStreams.set(modelId, new Set());
|
|
5
|
+
}
|
|
6
|
+
loggingStreams.get(modelId).add(streamHandler);
|
|
7
|
+
}
|
|
8
|
+
export function unregisterLoggingStream(modelId, streamHandler) {
|
|
9
|
+
const streams = loggingStreams.get(modelId);
|
|
10
|
+
if (streams) {
|
|
11
|
+
streams.delete(streamHandler);
|
|
12
|
+
if (streams.size === 0) {
|
|
13
|
+
loggingStreams.delete(modelId);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function unregisterAllLoggingStreams(modelId) {
|
|
18
|
+
// Simply remove all logging handlers for this model
|
|
19
|
+
// Active streams will naturally terminate when no more logs flow
|
|
20
|
+
loggingStreams.delete(modelId);
|
|
21
|
+
console.debug(`Unregistered all logging streams for model ${modelId}`);
|
|
22
|
+
}
|
|
23
|
+
export function sendLogToStreams(modelId, level, namespace, message) {
|
|
24
|
+
const streams = loggingStreams.get(modelId);
|
|
25
|
+
if (streams) {
|
|
26
|
+
for (const streamHandler of streams) {
|
|
27
|
+
try {
|
|
28
|
+
streamHandler(level, namespace, message);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
console.error(`Error sending log to stream for model ${modelId}:`, error);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function hasLoggingStreams(modelId) {
|
|
37
|
+
const streams = loggingStreams.get(modelId);
|
|
38
|
+
return streams && streams.size > 0;
|
|
39
|
+
}
|
|
40
|
+
export function getLoggingStreamStats() {
|
|
41
|
+
return {
|
|
42
|
+
totalModels: loggingStreams.size,
|
|
43
|
+
modelIds: Array.from(loggingStreams.keys()),
|
|
44
|
+
totalStreams: Array.from(loggingStreams.values()).reduce((sum, streams) => sum + streams.size, 0),
|
|
45
|
+
};
|
|
46
|
+
}
|