@qvac/sdk 0.7.0 → 0.8.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/NOTICE +57 -331
- package/README.md +2 -2
- package/bare-imports.json +9 -0
- package/dist/client/api/completion-stream.d.ts +2 -1
- package/dist/client/api/completion-stream.js +2 -1
- package/dist/client/api/download-asset.d.ts +3 -2
- package/dist/client/api/download-asset.js +4 -3
- package/dist/client/api/embed.d.ts +5 -2
- package/dist/client/api/embed.js +2 -2
- package/dist/client/api/get-model-info.d.ts +1 -1
- package/dist/client/api/invoke-plugin.d.ts +3 -2
- package/dist/client/api/invoke-plugin.js +4 -4
- package/dist/client/api/load-model.d.ts +12 -10
- package/dist/client/api/load-model.js +3 -3
- package/dist/client/api/rag.d.ts +10 -10
- package/dist/client/api/rag.js +21 -21
- package/dist/client/api/text-to-speech.d.ts +2 -2
- package/dist/client/api/text-to-speech.js +3 -3
- package/dist/client/api/transcribe.d.ts +5 -3
- package/dist/client/api/transcribe.js +6 -4
- package/dist/client/api/translate.d.ts +2 -2
- package/dist/client/api/translate.js +3 -3
- package/dist/client/rpc/node-rpc-client.d.ts +2 -7
- package/dist/client/rpc/node-rpc-client.js +2 -39
- package/dist/client/rpc/profiling/index.d.ts +2 -0
- package/dist/client/rpc/profiling/index.js +1 -0
- package/dist/client/rpc/profiling/profiler.d.ts +27 -0
- package/dist/client/rpc/profiling/profiler.js +139 -0
- package/dist/client/rpc/rpc-client.d.ts +2 -2
- package/dist/client/rpc/rpc-client.js +174 -12
- package/dist/examples/delegated-inference/consumer-profiled.d.ts +2 -0
- package/dist/examples/delegated-inference/consumer-profiled.js +67 -0
- package/dist/examples/llamacpp-multimodal.js +1 -1
- package/dist/examples/parallel-download.js +45 -13
- package/dist/examples/profiling/basic.d.ts +2 -0
- package/dist/examples/profiling/basic.js +71 -0
- package/dist/examples/profiling/per-call.d.ts +2 -0
- package/dist/examples/profiling/per-call.js +30 -0
- package/dist/examples/transcription/parakeet-ctc-filesystem.d.ts +2 -0
- package/dist/examples/transcription/parakeet-ctc-filesystem.js +40 -0
- package/dist/examples/transcription/parakeet-microphone-record.d.ts +2 -0
- package/dist/examples/transcription/parakeet-microphone-record.js +95 -0
- package/dist/examples/transcription/parakeet-sortformer.d.ts +2 -0
- package/dist/examples/transcription/parakeet-sortformer.js +115 -0
- package/dist/examples/transcription/parakeet-tdt-filesystem.d.ts +2 -0
- package/dist/examples/transcription/parakeet-tdt-filesystem.js +44 -0
- package/dist/examples/translation/translation-bergamot-pivot.d.ts +2 -0
- package/dist/examples/translation/translation-bergamot-pivot.js +73 -0
- package/dist/examples/translation/translation-llm-afriquegemma.d.ts +2 -0
- package/dist/examples/translation/translation-llm-afriquegemma.js +39 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.js +1 -1
- package/dist/logging/namespaces.d.ts +3 -9
- package/dist/logging/namespaces.js +2 -8
- package/dist/logging/registry.js +15 -1
- package/dist/models/registry/models.d.ts +1606 -245
- package/dist/models/registry/models.js +2127 -721
- package/dist/models/update-models/codegen.js +2 -2
- package/dist/models/update-models/history.d.ts +11 -0
- package/dist/models/update-models/history.js +24 -5
- package/dist/models/update-models/index.js +17 -16
- package/dist/models/update-models/naming.js +56 -0
- package/dist/profiling/aggregator.d.ts +15 -0
- package/dist/profiling/aggregator.js +100 -0
- package/dist/profiling/clock.d.ts +12 -0
- package/dist/profiling/clock.js +51 -0
- package/dist/profiling/controller.d.ts +33 -0
- package/dist/profiling/controller.js +123 -0
- package/dist/profiling/envelope.d.ts +10 -0
- package/dist/profiling/envelope.js +36 -0
- package/dist/profiling/events.d.ts +20 -0
- package/dist/profiling/events.js +37 -0
- package/dist/profiling/exporters.d.ts +10 -0
- package/dist/profiling/exporters.js +236 -0
- package/dist/profiling/index.d.ts +36 -0
- package/dist/profiling/index.js +31 -0
- package/dist/profiling/ring-buffer.d.ts +19 -0
- package/dist/profiling/ring-buffer.js +83 -0
- package/dist/profiling/types.d.ts +47 -0
- package/dist/profiling/types.js +1 -0
- package/dist/schemas/common.d.ts +1888 -133
- package/dist/schemas/common.js +2 -0
- package/dist/schemas/completion-stream.d.ts +31 -0
- package/dist/schemas/completion-stream.js +13 -0
- package/dist/schemas/download-asset.d.ts +14 -3
- package/dist/schemas/download-asset.js +3 -1
- package/dist/schemas/engine-addon-map.js +9 -6
- package/dist/schemas/get-model-info.d.ts +2 -0
- package/dist/schemas/get-model-info.js +1 -0
- package/dist/schemas/index.d.ts +2 -1
- package/dist/schemas/index.js +2 -1
- package/dist/schemas/llamacpp-config.d.ts +140 -14
- package/dist/schemas/llamacpp-config.js +11 -7
- package/dist/schemas/load-model.d.ts +9649 -2515
- package/dist/schemas/load-model.js +142 -182
- package/dist/schemas/model-src-utils.d.ts +10 -2
- package/dist/schemas/model-types.d.ts +19 -1
- package/dist/schemas/model-types.js +11 -0
- package/dist/schemas/ocr.d.ts +37 -0
- package/dist/schemas/ocr.js +5 -0
- package/dist/schemas/plugin.d.ts +51 -5
- package/dist/schemas/plugin.js +26 -0
- package/dist/schemas/profiling.d.ts +105 -0
- package/dist/schemas/profiling.js +66 -0
- package/dist/schemas/registry.d.ts +18 -0
- package/dist/schemas/registry.js +2 -0
- package/dist/schemas/reload-config.d.ts +126 -6
- package/dist/schemas/reload-config.js +1 -1
- package/dist/schemas/sdk-config.d.ts +2280 -24
- package/dist/schemas/sdk-config.js +6 -1
- package/dist/schemas/sdk-errors-client.d.ts +1 -0
- package/dist/schemas/sdk-errors-client.js +7 -0
- package/dist/schemas/sdk-errors-server.d.ts +3 -0
- package/dist/schemas/sdk-errors-server.js +15 -0
- package/dist/schemas/text-to-speech.d.ts +90 -68
- package/dist/schemas/text-to-speech.js +16 -33
- package/dist/schemas/transcription-config.d.ts +383 -0
- package/dist/schemas/{whispercpp-config.js → transcription-config.js} +29 -1
- package/dist/schemas/translation-config.d.ts +463 -8
- package/dist/schemas/translation-config.js +35 -2
- package/dist/server/bare/delegate-rpc-client.js +11 -1
- package/dist/server/bare/ops/load-model.d.ts +7 -1
- package/dist/server/bare/ops/load-model.js +41 -42
- package/dist/server/bare/ops/transcribe.d.ts +3 -0
- package/dist/server/bare/ops/transcribe.js +75 -0
- package/dist/server/bare/ops/translate.d.ts +2 -0
- package/dist/server/bare/ops/translate.js +12 -4
- package/dist/server/bare/plugins/index.d.ts +1 -0
- package/dist/server/bare/plugins/index.js +1 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +2 -1
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +8 -6
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +108 -3
- package/dist/server/bare/plugins/llamacpp-completion/plugin.js +19 -6
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +32 -2
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +31 -17
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +325 -3
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +117 -10
- package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +50 -2
- package/dist/server/bare/plugins/onnx-ocr/plugin.js +46 -5
- package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +351 -4
- package/dist/server/bare/plugins/onnx-tts/plugin.js +81 -61
- package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +317 -0
- package/dist/server/bare/plugins/parakeet-transcription/plugin.js +154 -0
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +209 -3
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +21 -9
- package/dist/server/bare/rag-hyperdb/rag-workspace-manager.js +2 -2
- package/dist/server/bare/registry/model-config-utils.js +3 -1
- package/dist/server/bare/utils/audio-input.d.ts +10 -0
- package/dist/server/bare/utils/audio-input.js +33 -0
- package/dist/server/error-handlers.d.ts +3 -2
- package/dist/server/error-handlers.js +11 -8
- package/dist/server/plugins/registry.js +5 -1
- package/dist/server/rpc/delegate-transport.d.ts +11 -3
- package/dist/server/rpc/delegate-transport.js +158 -3
- package/dist/server/rpc/handle-request.js +43 -4
- package/dist/server/rpc/handler-registry.js +7 -1
- package/dist/server/rpc/handler-utils.d.ts +5 -4
- package/dist/server/rpc/handler-utils.js +72 -31
- package/dist/server/rpc/handlers/completion-stream-delegated.d.ts +3 -1
- package/dist/server/rpc/handlers/completion-stream-delegated.js +11 -2
- package/dist/server/rpc/handlers/download-asset.js +55 -3
- package/dist/server/rpc/handlers/load-model/download-stats.d.ts +6 -0
- package/dist/server/rpc/handlers/load-model/download-stats.js +87 -0
- package/dist/server/rpc/handlers/load-model/handler.js +108 -123
- package/dist/server/rpc/handlers/load-model/http.d.ts +2 -1
- package/dist/server/rpc/handlers/load-model/http.js +21 -5
- package/dist/server/rpc/handlers/load-model/hyperdrive.d.ts +2 -1
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +19 -14
- package/dist/server/rpc/handlers/load-model/registry.d.ts +2 -1
- package/dist/server/rpc/handlers/load-model/registry.js +123 -130
- package/dist/server/rpc/handlers/load-model/resolve.d.ts +2 -0
- package/dist/server/rpc/handlers/load-model/resolve.js +55 -22
- package/dist/server/rpc/handlers/load-model/types.d.ts +29 -0
- package/dist/server/rpc/handlers/load-model/types.js +1 -0
- package/dist/server/rpc/handlers/load-model-delegated.d.ts +5 -1
- package/dist/server/rpc/handlers/load-model-delegated.js +35 -7
- package/dist/server/rpc/handlers/plugin-dispatch.js +15 -10
- package/dist/server/rpc/handlers/plugin-invoke.js +56 -51
- package/dist/server/rpc/handlers/rag.js +24 -0
- package/dist/server/rpc/handlers/unload-model-delegated.d.ts +3 -0
- package/dist/server/rpc/handlers/unload-model-delegated.js +32 -0
- package/dist/server/rpc/profiling/context.d.ts +18 -0
- package/dist/server/rpc/profiling/context.js +38 -0
- package/dist/server/rpc/profiling/delegation-profiler.d.ts +32 -0
- package/dist/server/rpc/profiling/delegation-profiler.js +154 -0
- package/dist/server/rpc/profiling/index.d.ts +5 -0
- package/dist/server/rpc/profiling/index.js +4 -0
- package/dist/server/rpc/profiling/operation-metrics.d.ts +25 -0
- package/dist/server/rpc/profiling/operation-metrics.js +199 -0
- package/dist/server/rpc/profiling/operation-wrappers.d.ts +18 -0
- package/dist/server/rpc/profiling/operation-wrappers.js +124 -0
- package/dist/server/rpc/profiling/profiler.d.ts +13 -0
- package/dist/server/rpc/profiling/profiler.js +97 -0
- package/dist/server/utils/cache.d.ts +2 -1
- package/dist/server/utils/cache.js +5 -1
- package/dist/server/utils/checksum.d.ts +2 -0
- package/dist/server/utils/checksum.js +7 -0
- package/dist/server/utils/formatting.d.ts +6 -0
- package/dist/server/utils/formatting.js +35 -0
- package/dist/server/worker.js +2 -1
- package/dist/utils/errors-client.d.ts +3 -0
- package/dist/utils/errors-client.js +6 -0
- package/dist/utils/errors-server.d.ts +9 -0
- package/dist/utils/errors-server.js +15 -0
- package/dist/utils/global-singleton.d.ts +2 -0
- package/dist/utils/global-singleton.js +10 -0
- package/package.json +14 -17
- package/dist/schemas/whispercpp-config.d.ts +0 -70
- package/dist/server/bare/plugins/whispercpp-transcription/ops/transcribe-stream.d.ts +0 -3
- package/dist/server/bare/plugins/whispercpp-transcription/ops/transcribe-stream.js +0 -81
- /package/dist/examples/{whispercpp-filesystem.d.ts → transcription/whispercpp-filesystem.d.ts} +0 -0
- /package/dist/examples/{whispercpp-filesystem.js → transcription/whispercpp-filesystem.js} +0 -0
- /package/dist/examples/{whispercpp-microphone-record.d.ts → transcription/whispercpp-microphone-record.d.ts} +0 -0
- /package/dist/examples/{whispercpp-microphone-record.js → transcription/whispercpp-microphone-record.js} +0 -0
- /package/dist/examples/{whispercpp-prompt.d.ts → transcription/whispercpp-prompt.d.ts} +0 -0
- /package/dist/examples/{whispercpp-prompt.js → transcription/whispercpp-prompt.js} +0 -0
|
@@ -1,32 +1,71 @@
|
|
|
1
|
-
import { requestSchema, normalizeModelType, } from "../../schemas/index.js";
|
|
1
|
+
import { requestSchema, normalizeModelType, PROFILING_KEY, } from "../../schemas/index.js";
|
|
2
|
+
import { nowMs } from "../../profiling/index.js";
|
|
2
3
|
import { resolveModelConfig } from "../bare/registry/model-config-registry.js";
|
|
3
4
|
import { sendErrorResponse } from "../error-handlers.js";
|
|
4
5
|
import { RPCNoDataReceivedError, RPCUnknownRequestTypeError, } from "../../utils/errors-server.js";
|
|
5
6
|
import { registry } from "./handler-registry.js";
|
|
6
7
|
import { executeHandler, handleInitConfig, isInitConfigMessage, } from "./handler-utils.js";
|
|
8
|
+
import { createServerProfiler } from "./profiling/index.js";
|
|
7
9
|
export async function handleRequest(req) {
|
|
10
|
+
let profiler;
|
|
11
|
+
let validationStart = 0;
|
|
8
12
|
try {
|
|
9
13
|
const rawData = req.data?.toString();
|
|
10
14
|
if (!rawData) {
|
|
11
15
|
throw new RPCNoDataReceivedError();
|
|
12
16
|
}
|
|
17
|
+
// Timing runs unconditionally since we can't know if client
|
|
18
|
+
// requested profiling until after parsing.
|
|
19
|
+
const parseStart = nowMs();
|
|
13
20
|
const jsonData = JSON.parse(rawData);
|
|
21
|
+
const jsonParseMs = nowMs() - parseStart;
|
|
14
22
|
// Handle internal config initialization (bypasses schema)
|
|
15
23
|
if (isInitConfigMessage(jsonData)) {
|
|
16
24
|
handleInitConfig(req, jsonData);
|
|
17
25
|
return;
|
|
18
26
|
}
|
|
19
|
-
const
|
|
27
|
+
const { data: cleanData, profilingMeta } = extractProfilingMeta(jsonData);
|
|
28
|
+
profiler = createServerProfiler(profilingMeta);
|
|
29
|
+
profiler.markRequestParsed(jsonParseMs);
|
|
30
|
+
validationStart = nowMs();
|
|
31
|
+
const processedData = applyDeviceDefaultsToRequest(cleanData);
|
|
20
32
|
const request = requestSchema.parse(processedData);
|
|
33
|
+
attachProfilingMetaToRequest(request, profilingMeta);
|
|
34
|
+
profiler.markRequestValidated(nowMs() - validationStart);
|
|
35
|
+
validationStart = 0;
|
|
21
36
|
const entry = registry[request.type];
|
|
22
37
|
if (!entry) {
|
|
23
38
|
throw new RPCUnknownRequestTypeError(request.type);
|
|
24
39
|
}
|
|
25
|
-
await executeHandler(req, request, entry);
|
|
40
|
+
await executeHandler(req, request, entry, profiler);
|
|
26
41
|
}
|
|
27
42
|
catch (error) {
|
|
28
|
-
|
|
43
|
+
if (profiler && validationStart > 0) {
|
|
44
|
+
profiler.markRequestValidated(nowMs() - validationStart);
|
|
45
|
+
}
|
|
46
|
+
sendErrorResponse(req, error, profiler);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function attachProfilingMetaToRequest(request, profilingMeta) {
|
|
50
|
+
if (!profilingMeta)
|
|
51
|
+
return;
|
|
52
|
+
Object.defineProperty(request, PROFILING_KEY, {
|
|
53
|
+
value: profilingMeta,
|
|
54
|
+
enumerable: false,
|
|
55
|
+
configurable: true,
|
|
56
|
+
writable: false,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function extractProfilingMeta(data) {
|
|
60
|
+
if (!data || typeof data !== "object" || !(PROFILING_KEY in data)) {
|
|
61
|
+
return { data, profilingMeta: undefined };
|
|
29
62
|
}
|
|
63
|
+
const obj = data;
|
|
64
|
+
const { [PROFILING_KEY]: meta, ...rest } = obj;
|
|
65
|
+
return {
|
|
66
|
+
data: rest,
|
|
67
|
+
profilingMeta: meta,
|
|
68
|
+
};
|
|
30
69
|
}
|
|
31
70
|
/**
|
|
32
71
|
* Apply device-specific config defaults to loadModel requests before schema parsing.
|
|
@@ -6,6 +6,7 @@ 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
8
|
import { handleUnloadModel } from "./handlers/unload-model.js";
|
|
9
|
+
import { handleUnloadModelDelegated } from "./handlers/unload-model-delegated.js";
|
|
9
10
|
import { handleTranscribeStream } from "./handlers/transcribe-stream.js";
|
|
10
11
|
import { handleEmbed } from "./handlers/embed.js";
|
|
11
12
|
import { handleTranslate } from "./handlers/translate.js";
|
|
@@ -35,7 +36,12 @@ function isModelDelegated(request) {
|
|
|
35
36
|
export const registry = {
|
|
36
37
|
// Simple Reply handlers
|
|
37
38
|
ping: { type: "reply", handler: handlePing },
|
|
38
|
-
unloadModel: {
|
|
39
|
+
unloadModel: {
|
|
40
|
+
type: "reply",
|
|
41
|
+
handler: handleUnloadModel,
|
|
42
|
+
delegatedHandler: handleUnloadModelDelegated,
|
|
43
|
+
isDelegated: isModelDelegated,
|
|
44
|
+
},
|
|
39
45
|
embed: { type: "reply", handler: handleEmbed },
|
|
40
46
|
cancel: { type: "reply", handler: cancelHandler },
|
|
41
47
|
provide: { type: "reply", handler: provideHandler },
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type QvacConfig, type Request, type Response, type RuntimeContext } from "../../schemas/index";
|
|
2
2
|
import type RPC from "bare-rpc";
|
|
3
|
-
|
|
4
|
-
type
|
|
5
|
-
type
|
|
3
|
+
import { type ServerProfiler } from "./profiling/index";
|
|
4
|
+
type ReplyHandler = (request: any, ...args: any[]) => Promise<Response> | Response;
|
|
5
|
+
type StreamHandler = (request: any, ...args: any[]) => AsyncGenerator<Response>;
|
|
6
|
+
type ProgressHandler = (request: any, ...args: any[]) => Promise<Response>;
|
|
6
7
|
export type HandlerEntry = {
|
|
7
8
|
type: "reply" | "stream";
|
|
8
9
|
handler: ReplyHandler | StreamHandler | ProgressHandler;
|
|
@@ -10,7 +11,7 @@ export type HandlerEntry = {
|
|
|
10
11
|
isDelegated?: (request: Request) => boolean;
|
|
11
12
|
supportsProgress?: boolean | ((request: Request) => boolean);
|
|
12
13
|
};
|
|
13
|
-
export declare function executeHandler(req: RPC.IncomingRequest, request: Request, entry: HandlerEntry): Promise<void>;
|
|
14
|
+
export declare function executeHandler(req: RPC.IncomingRequest, request: Request, entry: HandlerEntry, profiler: ServerProfiler): Promise<void>;
|
|
14
15
|
type InitConfigMessage = {
|
|
15
16
|
type: "__init_config";
|
|
16
17
|
config: QvacConfig;
|
|
@@ -1,65 +1,106 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PROFILING_KEY, } from "../../schemas/index.js";
|
|
2
2
|
import { sendErrorResponse, sendStreamErrorResponse, } from "../error-handlers.js";
|
|
3
3
|
import { setSDKConfig } from "../bare/registry/config-registry.js";
|
|
4
4
|
import { setRuntimeContext } from "../bare/registry/runtime-context-registry.js";
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import {} from "./profiling/index.js";
|
|
6
|
+
function getProfilingMetaFromRequest(request) {
|
|
7
|
+
if (PROFILING_KEY in request) {
|
|
8
|
+
return request[PROFILING_KEY];
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
7
11
|
}
|
|
8
|
-
async function executeReplyHandler(req, request, handler) {
|
|
12
|
+
async function executeReplyHandler(req, request, handler, profiler, isDelegated) {
|
|
13
|
+
profiler.startHandler();
|
|
9
14
|
try {
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
let response;
|
|
16
|
+
if (isDelegated) {
|
|
17
|
+
const profilingMeta = getProfilingMetaFromRequest(request);
|
|
18
|
+
response = await handler(request, profilingMeta ? { profilingMeta } : undefined);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
response = await handler(request);
|
|
22
|
+
}
|
|
23
|
+
profiler.endHandler();
|
|
24
|
+
req.reply(profiler.serialize(response, true), "utf-8");
|
|
12
25
|
}
|
|
13
26
|
catch (error) {
|
|
14
|
-
|
|
27
|
+
profiler.endHandler();
|
|
28
|
+
sendErrorResponse(req, error, profiler);
|
|
15
29
|
}
|
|
16
30
|
}
|
|
17
|
-
async function executeStreamHandler(req, request, handler) {
|
|
31
|
+
async function executeStreamHandler(req, request, handler, profiler, isDelegated) {
|
|
18
32
|
const stream = req.createResponseStream();
|
|
33
|
+
profiler.startHandler();
|
|
19
34
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
let generator;
|
|
37
|
+
if (isDelegated) {
|
|
38
|
+
const profilingMeta = getProfilingMetaFromRequest(request);
|
|
39
|
+
generator = handler(request, profilingMeta ? { profilingMeta } : undefined);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
generator = handler(request);
|
|
43
|
+
}
|
|
44
|
+
for await (const response of generator) {
|
|
45
|
+
stream.write(profiler.serialize(response, false) + "\n", "utf-8");
|
|
46
|
+
}
|
|
47
|
+
profiler.endHandler();
|
|
48
|
+
const trailer = profiler.serialize();
|
|
49
|
+
if (trailer) {
|
|
50
|
+
stream.write(trailer + "\n", "utf-8");
|
|
22
51
|
}
|
|
23
52
|
stream.end();
|
|
24
53
|
}
|
|
25
54
|
catch (error) {
|
|
26
|
-
|
|
55
|
+
profiler.endHandler();
|
|
56
|
+
sendStreamErrorResponse(stream, error, profiler);
|
|
27
57
|
}
|
|
28
58
|
}
|
|
29
|
-
async function executeProgressHandler(req, request, handler) {
|
|
59
|
+
async function executeProgressHandler(req, request, handler, profiler, isDelegated) {
|
|
30
60
|
const stream = req.createResponseStream();
|
|
61
|
+
profiler.startHandler();
|
|
62
|
+
const progressCallback = (update) => {
|
|
63
|
+
stream.write(profiler.serialize(update, false) + "\n", "utf-8");
|
|
64
|
+
};
|
|
31
65
|
try {
|
|
32
|
-
|
|
33
|
-
|
|
66
|
+
let response;
|
|
67
|
+
if (isDelegated) {
|
|
68
|
+
const profilingMeta = getProfilingMetaFromRequest(request);
|
|
69
|
+
const options = { progressCallback };
|
|
70
|
+
if (profilingMeta) {
|
|
71
|
+
options.profilingMeta = profilingMeta;
|
|
72
|
+
}
|
|
73
|
+
response = await handler(request, options);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
response = await handler(request, progressCallback);
|
|
77
|
+
}
|
|
78
|
+
profiler.endHandler();
|
|
79
|
+
stream.write(profiler.serialize(response, true) + "\n", "utf-8");
|
|
34
80
|
stream.end();
|
|
35
81
|
}
|
|
36
82
|
catch (error) {
|
|
37
|
-
|
|
83
|
+
profiler.endHandler();
|
|
84
|
+
sendStreamErrorResponse(stream, error, profiler);
|
|
38
85
|
}
|
|
39
86
|
}
|
|
40
87
|
// Unified handler executor with delegation and progress support
|
|
41
|
-
export async function executeHandler(req, request, entry) {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
: entry.handler;
|
|
88
|
+
export async function executeHandler(req, request, entry, profiler) {
|
|
89
|
+
const isDelegated = !!(entry.delegatedHandler && entry.isDelegated?.(request));
|
|
90
|
+
const handler = isDelegated ? entry.delegatedHandler : entry.handler;
|
|
45
91
|
const wantsProgress = "withProgress" in request &&
|
|
46
92
|
request.withProgress &&
|
|
47
93
|
(typeof entry.supportsProgress === "function"
|
|
48
94
|
? entry.supportsProgress(request)
|
|
49
95
|
: entry.supportsProgress);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
await executeStreamHandler(req, request, handler);
|
|
53
|
-
}
|
|
54
|
-
else if (wantsProgress) {
|
|
55
|
-
await executeProgressHandler(req, request, handler);
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
await executeReplyHandler(req, request, handler);
|
|
59
|
-
}
|
|
96
|
+
if (entry.type === "stream") {
|
|
97
|
+
await executeStreamHandler(req, request, handler, profiler, isDelegated);
|
|
60
98
|
}
|
|
61
|
-
|
|
62
|
-
|
|
99
|
+
else if (wantsProgress) {
|
|
100
|
+
await executeProgressHandler(req, request, handler, profiler, isDelegated);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
await executeReplyHandler(req, request, handler, profiler, isDelegated);
|
|
63
104
|
}
|
|
64
105
|
}
|
|
65
106
|
export function isInitConfigMessage(data) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { CompletionStreamRequest, CompletionStreamResponse } from "../../../schemas/index";
|
|
2
|
-
|
|
2
|
+
import type { DelegatedHandlerOptions } from "../profiling/index";
|
|
3
|
+
export type HandleCompletionStreamDelegatedOptions = DelegatedHandlerOptions;
|
|
4
|
+
export declare function handleCompletionStreamDelegated(request: CompletionStreamRequest, options?: HandleCompletionStreamDelegatedOptions): AsyncGenerator<CompletionStreamResponse>;
|
|
3
5
|
//# sourceMappingURL=completion-stream-delegated.d.ts.map
|
|
@@ -4,7 +4,8 @@ import { stream } from "../delegate-transport.js";
|
|
|
4
4
|
import { ModelIsDelegatedError } from "../../../utils/errors-server.js";
|
|
5
5
|
import { getServerLogger } from "../../../logging/index.js";
|
|
6
6
|
const logger = getServerLogger();
|
|
7
|
-
export async function* handleCompletionStreamDelegated(request) {
|
|
7
|
+
export async function* handleCompletionStreamDelegated(request, options) {
|
|
8
|
+
const { profilingMeta } = options ?? {};
|
|
8
9
|
// Get delegation info from model registry
|
|
9
10
|
const entry = getModelEntry(request.modelId);
|
|
10
11
|
if (!entry?.isDelegated || !entry.delegated) {
|
|
@@ -15,8 +16,16 @@ export async function* handleCompletionStreamDelegated(request) {
|
|
|
15
16
|
logger.debug(`📤 Sending delegated completionStream request to provider: ${providerPublicKey}${timeout ? `, timeout: ${timeout}ms` : ""}`);
|
|
16
17
|
// Create RPC instance for this HyperSwarm peer
|
|
17
18
|
const rpc = await getRPC(topic, providerPublicKey, { timeout });
|
|
19
|
+
// Build delegate options with profiling metadata
|
|
20
|
+
const delegateOpts = { peerKey: providerPublicKey };
|
|
21
|
+
if (profilingMeta) {
|
|
22
|
+
delegateOpts.profilingMeta = profilingMeta;
|
|
23
|
+
}
|
|
24
|
+
if (timeout) {
|
|
25
|
+
delegateOpts.timeout = timeout;
|
|
26
|
+
}
|
|
18
27
|
// Use the regular stream function with the HyperSwarm RPC instance
|
|
19
|
-
const responseStream = stream(request, rpc,
|
|
28
|
+
const responseStream = stream(request, rpc, delegateOpts);
|
|
20
29
|
// Yield each response from the stream
|
|
21
30
|
for await (const response of responseStream) {
|
|
22
31
|
yield response;
|
|
@@ -1,15 +1,67 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PROFILING_KEY, OPERATION_EVENT_KEY, } from "../../../schemas/index.js";
|
|
2
|
+
import { resolveModelPath, resolveModelPathWithStats, } from "./load-model/resolve.js";
|
|
3
|
+
import { nowMs, generateProfileId } from "../../../profiling/clock.js";
|
|
2
4
|
import { getServerLogger } from "../../../logging/index.js";
|
|
3
5
|
const logger = getServerLogger();
|
|
4
6
|
export async function handleDownloadAsset(request, progressCallback) {
|
|
5
7
|
const { assetSrc, seed } = request;
|
|
8
|
+
const profilingMeta = request[PROFILING_KEY];
|
|
9
|
+
const profilingEnabled = profilingMeta?.enabled !== false && !!profilingMeta;
|
|
6
10
|
try {
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
const totalDownloadStart = profilingEnabled ? nowMs() : 0;
|
|
12
|
+
let sourceType;
|
|
13
|
+
let downloadStats;
|
|
14
|
+
if (profilingEnabled) {
|
|
15
|
+
const result = await resolveModelPathWithStats(assetSrc, progressCallback, seed);
|
|
16
|
+
sourceType = result.sourceType;
|
|
17
|
+
downloadStats = result.downloadStats;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
await resolveModelPath(assetSrc, progressCallback, seed);
|
|
21
|
+
}
|
|
22
|
+
const response = {
|
|
9
23
|
type: "downloadAsset",
|
|
10
24
|
success: true,
|
|
11
25
|
assetId: assetSrc,
|
|
12
26
|
};
|
|
27
|
+
if (profilingEnabled) {
|
|
28
|
+
const totalDownloadTimeMs = nowMs() - totalDownloadStart;
|
|
29
|
+
const profileId = profilingMeta?.id ?? generateProfileId();
|
|
30
|
+
const gauges = {
|
|
31
|
+
totalDownloadTime: totalDownloadTimeMs,
|
|
32
|
+
};
|
|
33
|
+
if (downloadStats) {
|
|
34
|
+
if (downloadStats.downloadTimeMs !== undefined) {
|
|
35
|
+
gauges["downloadTime"] = downloadStats.downloadTimeMs;
|
|
36
|
+
}
|
|
37
|
+
if (downloadStats.totalBytesDownloaded !== undefined) {
|
|
38
|
+
gauges["totalBytesDownloaded"] = downloadStats.totalBytesDownloaded;
|
|
39
|
+
}
|
|
40
|
+
if (downloadStats.downloadSpeedBps !== undefined) {
|
|
41
|
+
gauges["downloadSpeedBps"] = downloadStats.downloadSpeedBps;
|
|
42
|
+
}
|
|
43
|
+
if (downloadStats.checksumValidationTimeMs !== undefined) {
|
|
44
|
+
gauges["checksumValidationTime"] = downloadStats.checksumValidationTimeMs;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const tags = {};
|
|
48
|
+
if (sourceType) {
|
|
49
|
+
tags["sourceType"] = sourceType;
|
|
50
|
+
}
|
|
51
|
+
if (downloadStats?.cacheHit !== undefined) {
|
|
52
|
+
tags["cacheHit"] = downloadStats.cacheHit ? "true" : "false";
|
|
53
|
+
}
|
|
54
|
+
const operationEvent = {
|
|
55
|
+
op: "downloadAsset",
|
|
56
|
+
kind: "handler",
|
|
57
|
+
ms: totalDownloadTimeMs,
|
|
58
|
+
profileId,
|
|
59
|
+
gauges: Object.keys(gauges).length > 0 ? gauges : undefined,
|
|
60
|
+
tags: Object.keys(tags).length > 0 ? tags : undefined,
|
|
61
|
+
};
|
|
62
|
+
response[OPERATION_EVENT_KEY] = operationEvent;
|
|
63
|
+
}
|
|
64
|
+
return response;
|
|
13
65
|
}
|
|
14
66
|
catch (error) {
|
|
15
67
|
logger.error("Error downloading asset:", error);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ModelProgressUpdate } from "../../../../schemas/index";
|
|
2
|
+
import type { DownloadResult } from "./types";
|
|
3
|
+
export declare function downloadModelFromHttpWithStats(url: string, progressCallback?: (progress: ModelProgressUpdate) => void): Promise<DownloadResult>;
|
|
4
|
+
export declare function downloadModelFromRegistryWithStats(registryPath: string, registrySource: string, progressCallback?: (progress: ModelProgressUpdate) => void, expectedChecksum?: string): Promise<DownloadResult>;
|
|
5
|
+
export declare function downloadModelFromHyperdriveWithStats(hyperdriveKey: string, modelFileName: string, seed?: boolean, progressCallback?: (progress: ModelProgressUpdate) => void): Promise<DownloadResult>;
|
|
6
|
+
//# sourceMappingURL=download-stats.d.ts.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { downloadModelFromHttp } from "./http.js";
|
|
2
|
+
import { downloadModelFromRegistry } from "./registry.js";
|
|
3
|
+
import { downloadModelFromHyperdrive } from "./hyperdrive.js";
|
|
4
|
+
import { nowMs } from "../../../../profiling/index.js";
|
|
5
|
+
function createStatsCollector() {
|
|
6
|
+
return {
|
|
7
|
+
maxBytesDownloaded: 0,
|
|
8
|
+
startTimeMs: nowMs(),
|
|
9
|
+
cacheHit: undefined,
|
|
10
|
+
checksumValidationTimeMsTotal: 0,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function createHooks(collector) {
|
|
14
|
+
return {
|
|
15
|
+
markCacheHit: () => {
|
|
16
|
+
if (collector.cacheHit === undefined) {
|
|
17
|
+
collector.cacheHit = true;
|
|
18
|
+
collector.maxBytesDownloaded = 0;
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
markCacheMiss: () => {
|
|
22
|
+
collector.cacheHit = false;
|
|
23
|
+
},
|
|
24
|
+
addChecksumValidationTimeMs: (durationMs) => {
|
|
25
|
+
collector.checksumValidationTimeMsTotal += durationMs;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function wrapProgressCallback(collector, originalCallback) {
|
|
30
|
+
return (progress) => {
|
|
31
|
+
// Don't track bytes for cache hits (they're not real network transfer)
|
|
32
|
+
if (collector.cacheHit !== true) {
|
|
33
|
+
const downloaded = progress.onnxInfo?.overallDownloaded ??
|
|
34
|
+
progress.shardInfo?.overallDownloaded ??
|
|
35
|
+
progress.downloaded ??
|
|
36
|
+
0;
|
|
37
|
+
collector.maxBytesDownloaded = Math.max(collector.maxBytesDownloaded, downloaded);
|
|
38
|
+
}
|
|
39
|
+
originalCallback?.(progress);
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function computeStats(collector) {
|
|
43
|
+
const downloadTimeMs = nowMs() - collector.startTimeMs;
|
|
44
|
+
const totalBytesDownloaded = collector.maxBytesDownloaded;
|
|
45
|
+
const stats = {};
|
|
46
|
+
if (collector.cacheHit !== undefined) {
|
|
47
|
+
stats.cacheHit = collector.cacheHit;
|
|
48
|
+
}
|
|
49
|
+
if (collector.checksumValidationTimeMsTotal > 0) {
|
|
50
|
+
stats.checksumValidationTimeMs = collector.checksumValidationTimeMsTotal;
|
|
51
|
+
}
|
|
52
|
+
if (collector.cacheHit === true) {
|
|
53
|
+
return Object.keys(stats).length > 0 ? stats : undefined;
|
|
54
|
+
}
|
|
55
|
+
if (totalBytesDownloaded > 0) {
|
|
56
|
+
stats.downloadTimeMs = downloadTimeMs;
|
|
57
|
+
stats.totalBytesDownloaded = totalBytesDownloaded;
|
|
58
|
+
if (downloadTimeMs > 0) {
|
|
59
|
+
stats.downloadSpeedBps = (totalBytesDownloaded * 1000) / downloadTimeMs;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return Object.keys(stats).length > 0 ? stats : undefined;
|
|
63
|
+
}
|
|
64
|
+
export async function downloadModelFromHttpWithStats(url, progressCallback) {
|
|
65
|
+
const collector = createStatsCollector();
|
|
66
|
+
const hooks = createHooks(collector);
|
|
67
|
+
const wrappedCallback = wrapProgressCallback(collector, progressCallback);
|
|
68
|
+
const path = await downloadModelFromHttp(url, wrappedCallback, hooks);
|
|
69
|
+
const stats = computeStats(collector);
|
|
70
|
+
return stats ? { path, stats } : { path };
|
|
71
|
+
}
|
|
72
|
+
export async function downloadModelFromRegistryWithStats(registryPath, registrySource, progressCallback, expectedChecksum) {
|
|
73
|
+
const collector = createStatsCollector();
|
|
74
|
+
const hooks = createHooks(collector);
|
|
75
|
+
const wrappedCallback = wrapProgressCallback(collector, progressCallback);
|
|
76
|
+
const path = await downloadModelFromRegistry(registryPath, registrySource, wrappedCallback, expectedChecksum, hooks);
|
|
77
|
+
const stats = computeStats(collector);
|
|
78
|
+
return stats ? { path, stats } : { path };
|
|
79
|
+
}
|
|
80
|
+
export async function downloadModelFromHyperdriveWithStats(hyperdriveKey, modelFileName, seed, progressCallback) {
|
|
81
|
+
const collector = createStatsCollector();
|
|
82
|
+
const hooks = createHooks(collector);
|
|
83
|
+
const wrappedCallback = wrapProgressCallback(collector, progressCallback);
|
|
84
|
+
const path = await downloadModelFromHyperdrive(hyperdriveKey, modelFileName, seed, wrappedCallback, hooks);
|
|
85
|
+
const stats = computeStats(collector);
|
|
86
|
+
return stats ? { path, stats } : { path };
|
|
87
|
+
}
|