@marinoscar/platform-api 0.1.0-next.5 → 0.1.0-next.6
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/CHANGELOG.md +12 -0
- package/dist/ai/core/ai-error.d.ts +15 -158
- package/dist/ai/core/ai-error.d.ts.map +1 -1
- package/dist/ai/core/ai-error.js +58 -221
- package/dist/ai/core/ai-error.js.map +1 -1
- package/dist/ai/core/capabilities.d.ts +3 -126
- package/dist/ai/core/capabilities.d.ts.map +1 -1
- package/dist/ai/core/capabilities.js +13 -109
- package/dist/ai/core/capabilities.js.map +1 -1
- package/dist/ai/core/conversation.d.ts +2 -15
- package/dist/ai/core/conversation.d.ts.map +1 -1
- package/dist/ai/core/conversation.js +9 -54
- package/dist/ai/core/conversation.js.map +1 -1
- package/dist/ai/core/hosted-tools.d.ts +3 -172
- package/dist/ai/core/hosted-tools.d.ts.map +1 -1
- package/dist/ai/core/hosted-tools.js +20 -286
- package/dist/ai/core/hosted-tools.js.map +1 -1
- package/dist/ai/core/provider-adapter.interface.d.ts +3 -260
- package/dist/ai/core/provider-adapter.interface.d.ts.map +1 -1
- package/dist/ai/core/provider-adapter.interface.js +7 -29
- package/dist/ai/core/provider-adapter.interface.js.map +1 -1
- package/dist/ai/core/structured-output.d.ts +3 -49
- package/dist/ai/core/structured-output.d.ts.map +1 -1
- package/dist/ai/core/structured-output.js +9 -80
- package/dist/ai/core/structured-output.js.map +1 -1
- package/dist/ai/core/tools.d.ts +3 -93
- package/dist/ai/core/tools.d.ts.map +1 -1
- package/dist/ai/core/tools.js +9 -73
- package/dist/ai/core/tools.js.map +1 -1
- package/dist/ai/core/types/file-inputs.types.d.ts +3 -102
- package/dist/ai/core/types/file-inputs.types.d.ts.map +1 -1
- package/dist/ai/core/types/file-inputs.types.js +14 -78
- package/dist/ai/core/types/file-inputs.types.js.map +1 -1
- package/dist/ai/core/types/media.types.d.ts +3 -616
- package/dist/ai/core/types/media.types.d.ts.map +1 -1
- package/dist/ai/core/types/media.types.js +33 -203
- package/dist/ai/core/types/media.types.js.map +1 -1
- package/dist/ai/core/types/responses.types.d.ts +3 -619
- package/dist/ai/core/types/responses.types.d.ts.map +1 -1
- package/dist/ai/core/types/responses.types.js +9 -57
- package/dist/ai/core/types/responses.types.js.map +1 -1
- package/dist/ai/http/dto/ai-images.dto.d.ts +4 -4
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +3 -3
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/providers/anthropic/anthropic-client.factory.d.ts +13 -15
- package/dist/ai/providers/anthropic/anthropic-client.factory.d.ts.map +1 -1
- package/dist/ai/providers/anthropic/anthropic-client.factory.js +23 -52
- package/dist/ai/providers/anthropic/anthropic-client.factory.js.map +1 -1
- package/dist/ai/providers/anthropic/anthropic.adapter.d.ts +15 -51
- package/dist/ai/providers/anthropic/anthropic.adapter.d.ts.map +1 -1
- package/dist/ai/providers/anthropic/anthropic.adapter.js +29 -293
- package/dist/ai/providers/anthropic/anthropic.adapter.js.map +1 -1
- package/dist/ai/providers/azure-openai/azure-openai-client.factory.d.ts +10 -14
- package/dist/ai/providers/azure-openai/azure-openai-client.factory.d.ts.map +1 -1
- package/dist/ai/providers/azure-openai/azure-openai-client.factory.js +20 -53
- package/dist/ai/providers/azure-openai/azure-openai-client.factory.js.map +1 -1
- package/dist/ai/providers/azure-openai/azure-openai.adapter.d.ts +14 -31
- package/dist/ai/providers/azure-openai/azure-openai.adapter.d.ts.map +1 -1
- package/dist/ai/providers/azure-openai/azure-openai.adapter.js +25 -170
- package/dist/ai/providers/azure-openai/azure-openai.adapter.js.map +1 -1
- package/dist/ai/providers/gemini/gemini-client.factory.d.ts +13 -18
- package/dist/ai/providers/gemini/gemini-client.factory.d.ts.map +1 -1
- package/dist/ai/providers/gemini/gemini-client.factory.js +24 -68
- package/dist/ai/providers/gemini/gemini-client.factory.js.map +1 -1
- package/dist/ai/providers/gemini/gemini.adapter.d.ts +15 -58
- package/dist/ai/providers/gemini/gemini.adapter.d.ts.map +1 -1
- package/dist/ai/providers/gemini/gemini.adapter.js +29 -348
- package/dist/ai/providers/gemini/gemini.adapter.js.map +1 -1
- package/dist/ai/providers/openai/openai-client.factory.d.ts +13 -35
- package/dist/ai/providers/openai/openai-client.factory.d.ts.map +1 -1
- package/dist/ai/providers/openai/openai-client.factory.js +25 -64
- package/dist/ai/providers/openai/openai-client.factory.js.map +1 -1
- package/dist/ai/providers/openai/openai.adapter.d.ts +15 -48
- package/dist/ai/providers/openai/openai.adapter.d.ts.map +1 -1
- package/dist/ai/providers/openai/openai.adapter.js +27 -206
- package/dist/ai/providers/openai/openai.adapter.js.map +1 -1
- package/dist/ai/providers/openai-compatible/openai-compatible-client.factory.d.ts +11 -11
- package/dist/ai/providers/openai-compatible/openai-compatible-client.factory.d.ts.map +1 -1
- package/dist/ai/providers/openai-compatible/openai-compatible-client.factory.js +18 -41
- package/dist/ai/providers/openai-compatible/openai-compatible-client.factory.js.map +1 -1
- package/dist/ai/providers/openai-compatible/openai-compatible.adapter.d.ts +14 -32
- package/dist/ai/providers/openai-compatible/openai-compatible.adapter.d.ts.map +1 -1
- package/dist/ai/providers/openai-compatible/openai-compatible.adapter.js +25 -149
- package/dist/ai/providers/openai-compatible/openai-compatible.adapter.js.map +1 -1
- package/dist/ai/providers/platform-ai-tracer.d.ts +4 -0
- package/dist/ai/providers/platform-ai-tracer.d.ts.map +1 -0
- package/dist/ai/providers/platform-ai-tracer.js +20 -0
- package/dist/ai/providers/platform-ai-tracer.js.map +1 -0
- package/dist/ai/runtime/ai-image-run-request.d.ts +1 -1
- package/dist/ai/testing/conformance/ai-no-sdk-leak.suite.d.ts +28 -5
- package/dist/ai/testing/conformance/ai-no-sdk-leak.suite.d.ts.map +1 -1
- package/dist/ai/testing/conformance/ai-no-sdk-leak.suite.js +54 -9
- package/dist/ai/testing/conformance/ai-no-sdk-leak.suite.js.map +1 -1
- package/dist/ai/testing/index.d.ts +1 -1
- package/dist/ai/testing/index.d.ts.map +1 -1
- package/dist/ai/testing/index.js +2 -1
- package/dist/ai/testing/index.js.map +1 -1
- package/dist/jobs/rate-limit.error.d.ts +2 -26
- package/dist/jobs/rate-limit.error.d.ts.map +1 -1
- package/dist/jobs/rate-limit.error.js +4 -52
- package/dist/jobs/rate-limit.error.js.map +1 -1
- package/dist/storage/config/storage-config.controller.d.ts +1 -1
- package/package.json +3 -2
- package/dist/ai/providers/anthropic/anthropic-errors.d.ts +0 -16
- package/dist/ai/providers/anthropic/anthropic-errors.d.ts.map +0 -1
- package/dist/ai/providers/anthropic/anthropic-errors.js +0 -156
- package/dist/ai/providers/anthropic/anthropic-errors.js.map +0 -1
- package/dist/ai/providers/anthropic/anthropic-messages.mapper.d.ts +0 -80
- package/dist/ai/providers/anthropic/anthropic-messages.mapper.d.ts.map +0 -1
- package/dist/ai/providers/anthropic/anthropic-messages.mapper.js +0 -536
- package/dist/ai/providers/anthropic/anthropic-messages.mapper.js.map +0 -1
- package/dist/ai/providers/anthropic/anthropic-model-catalog.d.ts +0 -49
- package/dist/ai/providers/anthropic/anthropic-model-catalog.d.ts.map +0 -1
- package/dist/ai/providers/anthropic/anthropic-model-catalog.js +0 -198
- package/dist/ai/providers/anthropic/anthropic-model-catalog.js.map +0 -1
- package/dist/ai/providers/anthropic/anthropic-stream.mapper.d.ts +0 -35
- package/dist/ai/providers/anthropic/anthropic-stream.mapper.d.ts.map +0 -1
- package/dist/ai/providers/anthropic/anthropic-stream.mapper.js +0 -203
- package/dist/ai/providers/anthropic/anthropic-stream.mapper.js.map +0 -1
- package/dist/ai/providers/anthropic/testing/anthropic-fixtures.d.ts +0 -18
- package/dist/ai/providers/anthropic/testing/anthropic-fixtures.d.ts.map +0 -1
- package/dist/ai/providers/anthropic/testing/anthropic-fixtures.js +0 -120
- package/dist/ai/providers/anthropic/testing/anthropic-fixtures.js.map +0 -1
- package/dist/ai/providers/anthropic/testing/anthropic-mock-transport.d.ts +0 -59
- package/dist/ai/providers/anthropic/testing/anthropic-mock-transport.d.ts.map +0 -1
- package/dist/ai/providers/anthropic/testing/anthropic-mock-transport.js +0 -206
- package/dist/ai/providers/anthropic/testing/anthropic-mock-transport.js.map +0 -1
- package/dist/ai/providers/azure-openai/azure-openai-settings.d.ts +0 -23
- package/dist/ai/providers/azure-openai/azure-openai-settings.d.ts.map +0 -1
- package/dist/ai/providers/azure-openai/azure-openai-settings.js +0 -54
- package/dist/ai/providers/azure-openai/azure-openai-settings.js.map +0 -1
- package/dist/ai/providers/gemini/gemini-content.mapper.d.ts +0 -98
- package/dist/ai/providers/gemini/gemini-content.mapper.d.ts.map +0 -1
- package/dist/ai/providers/gemini/gemini-content.mapper.js +0 -665
- package/dist/ai/providers/gemini/gemini-content.mapper.js.map +0 -1
- package/dist/ai/providers/gemini/gemini-embeddings.mapper.d.ts +0 -13
- package/dist/ai/providers/gemini/gemini-embeddings.mapper.d.ts.map +0 -1
- package/dist/ai/providers/gemini/gemini-embeddings.mapper.js +0 -78
- package/dist/ai/providers/gemini/gemini-embeddings.mapper.js.map +0 -1
- package/dist/ai/providers/gemini/gemini-errors.d.ts +0 -32
- package/dist/ai/providers/gemini/gemini-errors.d.ts.map +0 -1
- package/dist/ai/providers/gemini/gemini-errors.js +0 -191
- package/dist/ai/providers/gemini/gemini-errors.js.map +0 -1
- package/dist/ai/providers/gemini/gemini-model-catalog.d.ts +0 -45
- package/dist/ai/providers/gemini/gemini-model-catalog.d.ts.map +0 -1
- package/dist/ai/providers/gemini/gemini-model-catalog.js +0 -264
- package/dist/ai/providers/gemini/gemini-model-catalog.js.map +0 -1
- package/dist/ai/providers/gemini/gemini-stream.mapper.d.ts +0 -31
- package/dist/ai/providers/gemini/gemini-stream.mapper.d.ts.map +0 -1
- package/dist/ai/providers/gemini/gemini-stream.mapper.js +0 -118
- package/dist/ai/providers/gemini/gemini-stream.mapper.js.map +0 -1
- package/dist/ai/providers/gemini/testing/gemini-fixtures.d.ts +0 -80
- package/dist/ai/providers/gemini/testing/gemini-fixtures.d.ts.map +0 -1
- package/dist/ai/providers/gemini/testing/gemini-fixtures.js +0 -118
- package/dist/ai/providers/gemini/testing/gemini-fixtures.js.map +0 -1
- package/dist/ai/providers/gemini/testing/gemini-mock-transport.d.ts +0 -82
- package/dist/ai/providers/gemini/testing/gemini-mock-transport.d.ts.map +0 -1
- package/dist/ai/providers/gemini/testing/gemini-mock-transport.js +0 -342
- package/dist/ai/providers/gemini/testing/gemini-mock-transport.js.map +0 -1
- package/dist/ai/providers/openai/openai-audio.mapper.d.ts +0 -42
- package/dist/ai/providers/openai/openai-audio.mapper.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-audio.mapper.js +0 -266
- package/dist/ai/providers/openai/openai-audio.mapper.js.map +0 -1
- package/dist/ai/providers/openai/openai-call-telemetry.d.ts +0 -25
- package/dist/ai/providers/openai/openai-call-telemetry.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-call-telemetry.js +0 -93
- package/dist/ai/providers/openai/openai-call-telemetry.js.map +0 -1
- package/dist/ai/providers/openai/openai-chat-completions-stream.mapper.d.ts +0 -41
- package/dist/ai/providers/openai/openai-chat-completions-stream.mapper.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-chat-completions-stream.mapper.js +0 -173
- package/dist/ai/providers/openai/openai-chat-completions-stream.mapper.js.map +0 -1
- package/dist/ai/providers/openai/openai-chat-completions.engine.d.ts +0 -33
- package/dist/ai/providers/openai/openai-chat-completions.engine.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-chat-completions.engine.js +0 -165
- package/dist/ai/providers/openai/openai-chat-completions.engine.js.map +0 -1
- package/dist/ai/providers/openai/openai-chat-completions.mapper.d.ts +0 -42
- package/dist/ai/providers/openai/openai-chat-completions.mapper.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-chat-completions.mapper.js +0 -304
- package/dist/ai/providers/openai/openai-chat-completions.mapper.js.map +0 -1
- package/dist/ai/providers/openai/openai-embeddings.mapper.d.ts +0 -25
- package/dist/ai/providers/openai/openai-embeddings.mapper.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-embeddings.mapper.js +0 -81
- package/dist/ai/providers/openai/openai-embeddings.mapper.js.map +0 -1
- package/dist/ai/providers/openai/openai-errors.d.ts +0 -45
- package/dist/ai/providers/openai/openai-errors.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-errors.js +0 -247
- package/dist/ai/providers/openai/openai-errors.js.map +0 -1
- package/dist/ai/providers/openai/openai-family-guards.d.ts +0 -4
- package/dist/ai/providers/openai/openai-family-guards.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-family-guards.js +0 -19
- package/dist/ai/providers/openai/openai-family-guards.js.map +0 -1
- package/dist/ai/providers/openai/openai-images.mapper.d.ts +0 -23
- package/dist/ai/providers/openai/openai-images.mapper.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-images.mapper.js +0 -164
- package/dist/ai/providers/openai/openai-images.mapper.js.map +0 -1
- package/dist/ai/providers/openai/openai-model-catalog.d.ts +0 -36
- package/dist/ai/providers/openai/openai-model-catalog.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-model-catalog.js +0 -209
- package/dist/ai/providers/openai/openai-model-catalog.js.map +0 -1
- package/dist/ai/providers/openai/openai-realtime.mapper.d.ts +0 -18
- package/dist/ai/providers/openai/openai-realtime.mapper.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-realtime.mapper.js +0 -159
- package/dist/ai/providers/openai/openai-realtime.mapper.js.map +0 -1
- package/dist/ai/providers/openai/openai-redirect-guard.d.ts +0 -9
- package/dist/ai/providers/openai/openai-redirect-guard.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-redirect-guard.js +0 -61
- package/dist/ai/providers/openai/openai-redirect-guard.js.map +0 -1
- package/dist/ai/providers/openai/openai-responses.engine.d.ts +0 -50
- package/dist/ai/providers/openai/openai-responses.engine.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-responses.engine.js +0 -206
- package/dist/ai/providers/openai/openai-responses.engine.js.map +0 -1
- package/dist/ai/providers/openai/openai-responses.mapper.d.ts +0 -64
- package/dist/ai/providers/openai/openai-responses.mapper.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-responses.mapper.js +0 -580
- package/dist/ai/providers/openai/openai-responses.mapper.js.map +0 -1
- package/dist/ai/providers/openai/openai-stream.mapper.d.ts +0 -28
- package/dist/ai/providers/openai/openai-stream.mapper.d.ts.map +0 -1
- package/dist/ai/providers/openai/openai-stream.mapper.js +0 -139
- package/dist/ai/providers/openai/openai-stream.mapper.js.map +0 -1
- package/dist/ai/providers/openai/testing/chat-completions-fixtures.d.ts +0 -24
- package/dist/ai/providers/openai/testing/chat-completions-fixtures.d.ts.map +0 -1
- package/dist/ai/providers/openai/testing/chat-completions-fixtures.js +0 -72
- package/dist/ai/providers/openai/testing/chat-completions-fixtures.js.map +0 -1
- package/dist/ai/providers/openai/testing/conformance-responders.d.ts +0 -7
- package/dist/ai/providers/openai/testing/conformance-responders.d.ts.map +0 -1
- package/dist/ai/providers/openai/testing/conformance-responders.js +0 -64
- package/dist/ai/providers/openai/testing/conformance-responders.js.map +0 -1
- package/dist/ai/providers/openai/testing/openai-fixtures.d.ts +0 -52
- package/dist/ai/providers/openai/testing/openai-fixtures.d.ts.map +0 -1
- package/dist/ai/providers/openai/testing/openai-fixtures.js +0 -208
- package/dist/ai/providers/openai/testing/openai-fixtures.js.map +0 -1
- package/dist/ai/providers/openai/testing/openai-mock-transport.d.ts +0 -242
- package/dist/ai/providers/openai/testing/openai-mock-transport.d.ts.map +0 -1
- package/dist/ai/providers/openai/testing/openai-mock-transport.js +0 -523
- package/dist/ai/providers/openai/testing/openai-mock-transport.js.map +0 -1
- package/dist/ai/providers/openai-compatible/openai-compatible-settings.d.ts +0 -13
- package/dist/ai/providers/openai-compatible/openai-compatible-settings.d.ts.map +0 -1
- package/dist/ai/providers/openai-compatible/openai-compatible-settings.js +0 -29
- package/dist/ai/providers/openai-compatible/openai-compatible-settings.js.map +0 -1
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// =============================================================================
|
|
3
|
-
// OpenAI audio mapper (issue #438, epic #420)
|
|
4
|
-
// =============================================================================
|
|
5
|
-
//
|
|
6
|
-
// AiTranscriptionRequest <-> `POST /v1/audio/transcriptions`, and (#439)
|
|
7
|
-
// AiSpeechRequest <-> `POST /v1/audio/speech`. Pure functions
|
|
8
|
-
// (plus the SDK's `toFile`/`toStreamingFile`, which only wrap bytes); every
|
|
9
|
-
// failure is an `AiError`, never an SDK error.
|
|
10
|
-
//
|
|
11
|
-
// STREAMED, NOT BUFFERED. A streamed input (`AiStreamedPayload`) becomes the
|
|
12
|
-
// SDK's `toStreamingFile`: the multipart body is encoded lazily as the
|
|
13
|
-
// request is sent, so the recording is read from storage once and never held
|
|
14
|
-
// in memory whole. Bytes already in hand go through `toFile`.
|
|
15
|
-
//
|
|
16
|
-
// 25 MiB. OpenAI refuses a larger upload; `OPENAI_TRANSCRIPTION_MAX_BYTES` is
|
|
17
|
-
// declared on the port so the runtime refuses it FIRST (`AI_INVALID_REQUEST`,
|
|
18
|
-
// no provider call), and this mapper refuses one whose size it can see too.
|
|
19
|
-
//
|
|
20
|
-
// THE FILE NAME CARRIES THE FORMAT. OpenAI decides how to decode an upload
|
|
21
|
-
// from its file extension, so a storage object named `memo` (no extension)
|
|
22
|
-
// is sent as `memo.m4a` when its MIME type is `audio/mp4`.
|
|
23
|
-
//
|
|
24
|
-
// TWO FAMILIES. `whisper-1` answers `verbose_json` (language, duration,
|
|
25
|
-
// segments, word timestamps) and is asked for it by default; the GPT-4o
|
|
26
|
-
// transcribe family answers `json`/`text` only and does not take
|
|
27
|
-
// `timestamp_granularities`, so for it that field is left out rather than
|
|
28
|
-
// sent to a 400 — the same "what the family cannot honour is dropped" rule
|
|
29
|
-
// the images mapper follows.
|
|
30
|
-
// =============================================================================
|
|
31
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.OPENAI_TRANSCRIPTION_MAX_BYTES = void 0;
|
|
33
|
-
exports.isOpenAiWhisper = isOpenAiWhisper;
|
|
34
|
-
exports.openAiAudioFileName = openAiAudioFileName;
|
|
35
|
-
exports.toOpenAiTranscriptionRequest = toOpenAiTranscriptionRequest;
|
|
36
|
-
exports.fromOpenAiTranscriptionResponse = fromOpenAiTranscriptionResponse;
|
|
37
|
-
exports.isOpenAiTts1 = isOpenAiTts1;
|
|
38
|
-
exports.toOpenAiSpeechRequest = toOpenAiSpeechRequest;
|
|
39
|
-
exports.fromOpenAiSpeechResponse = fromOpenAiSpeechResponse;
|
|
40
|
-
const openai_1 = require("openai");
|
|
41
|
-
const ai_error_1 = require("../../core/ai-error");
|
|
42
|
-
const media_types_1 = require("../../core/types/media.types");
|
|
43
|
-
const openai_errors_1 = require("./openai-errors");
|
|
44
|
-
/** OpenAI's upload limit for `/v1/audio/transcriptions` (25 MiB). */
|
|
45
|
-
exports.OPENAI_TRANSCRIPTION_MAX_BYTES = 25 * 1024 * 1024;
|
|
46
|
-
const WHISPER = /^whisper-/;
|
|
47
|
-
/** The extension OpenAI needs to see for each MIME type it can decode. */
|
|
48
|
-
const AUDIO_EXTENSIONS = {
|
|
49
|
-
'audio/mpeg': 'mp3',
|
|
50
|
-
'audio/mp3': 'mp3',
|
|
51
|
-
'audio/mpga': 'mpga',
|
|
52
|
-
'audio/mp4': 'm4a',
|
|
53
|
-
'audio/m4a': 'm4a',
|
|
54
|
-
'audio/x-m4a': 'm4a',
|
|
55
|
-
'audio/aac': 'm4a',
|
|
56
|
-
'audio/wav': 'wav',
|
|
57
|
-
'audio/wave': 'wav',
|
|
58
|
-
'audio/x-wav': 'wav',
|
|
59
|
-
'audio/vnd.wave': 'wav',
|
|
60
|
-
'audio/webm': 'webm',
|
|
61
|
-
'audio/ogg': 'ogg',
|
|
62
|
-
'audio/opus': 'ogg',
|
|
63
|
-
'audio/flac': 'flac',
|
|
64
|
-
'audio/x-flac': 'flac',
|
|
65
|
-
'video/mp4': 'mp4',
|
|
66
|
-
'video/webm': 'webm',
|
|
67
|
-
};
|
|
68
|
-
const KNOWN_EXTENSIONS = new Set(['flac', 'mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'ogg', 'oga', 'wav', 'webm']);
|
|
69
|
-
/** Whether OpenAI model `modelId` is a Whisper model (verbose_json, timestamps). */
|
|
70
|
-
function isOpenAiWhisper(modelId) {
|
|
71
|
-
return WHISPER.test(modelId.trim().toLowerCase());
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* The name the upload is sent under: the caller's own base name (no path),
|
|
75
|
-
* with an extension OpenAI can decode — appended from the MIME type when the
|
|
76
|
-
* name has none it recognises.
|
|
77
|
-
*/
|
|
78
|
-
function openAiAudioFileName(input) {
|
|
79
|
-
const base = (input.filename ?? '').split(/[\\/]/).pop()?.trim() || 'audio';
|
|
80
|
-
const dot = base.lastIndexOf('.');
|
|
81
|
-
const ext = dot > 0 ? base.slice(dot + 1).toLowerCase() : '';
|
|
82
|
-
if (KNOWN_EXTENSIONS.has(ext))
|
|
83
|
-
return base;
|
|
84
|
-
const mime = input.mimeType.split(';')[0].trim().toLowerCase();
|
|
85
|
-
return `${base}.${AUDIO_EXTENSIONS[mime] ?? 'mp3'}`;
|
|
86
|
-
}
|
|
87
|
-
function tooLarge(size) {
|
|
88
|
-
return new ai_error_1.AiError('AI_INVALID_REQUEST', `The audio is larger than ${exports.OPENAI_TRANSCRIPTION_MAX_BYTES} bytes.`, {
|
|
89
|
-
details: { provider: openai_errors_1.OPENAI_PROVIDER_ID, size, maxBytes: exports.OPENAI_TRANSCRIPTION_MAX_BYTES },
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* The `/v1/audio/transcriptions` multipart body. A streamed input stays a
|
|
94
|
-
* stream (`toStreamingFile`); bytes become a `File`.
|
|
95
|
-
*/
|
|
96
|
-
async function toOpenAiTranscriptionRequest(req) {
|
|
97
|
-
const { audio } = req;
|
|
98
|
-
const name = openAiAudioFileName(audio);
|
|
99
|
-
const type = audio.mimeType;
|
|
100
|
-
let file;
|
|
101
|
-
if ((0, media_types_1.isStreamedPayload)(audio)) {
|
|
102
|
-
if (audio.size !== undefined && audio.size > exports.OPENAI_TRANSCRIPTION_MAX_BYTES)
|
|
103
|
-
throw tooLarge(audio.size);
|
|
104
|
-
file = (0, openai_1.toStreamingFile)(audio.stream, name, { type });
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
if (audio.data.byteLength === 0) {
|
|
108
|
-
throw new ai_error_1.AiError('AI_INVALID_REQUEST', 'The audio is empty.', { details: { provider: openai_errors_1.OPENAI_PROVIDER_ID } });
|
|
109
|
-
}
|
|
110
|
-
if (audio.data.byteLength > exports.OPENAI_TRANSCRIPTION_MAX_BYTES)
|
|
111
|
-
throw tooLarge(audio.data.byteLength);
|
|
112
|
-
file = await (0, openai_1.toFile)(audio.data, name, { type });
|
|
113
|
-
}
|
|
114
|
-
const whisper = isOpenAiWhisper(req.model);
|
|
115
|
-
const format = req.responseFormat ?? (whisper ? 'verbose_json' : 'json');
|
|
116
|
-
const escapeHatch = (req.providerOptions?.[openai_errors_1.OPENAI_PROVIDER_ID] ?? {});
|
|
117
|
-
const body = {
|
|
118
|
-
...escapeHatch,
|
|
119
|
-
file,
|
|
120
|
-
model: req.model,
|
|
121
|
-
response_format: format,
|
|
122
|
-
stream: false,
|
|
123
|
-
};
|
|
124
|
-
if (req.language !== undefined)
|
|
125
|
-
body.language = req.language;
|
|
126
|
-
if (req.prompt !== undefined)
|
|
127
|
-
body.prompt = req.prompt;
|
|
128
|
-
if (whisper && format === 'verbose_json' && req.timestampGranularities?.length) {
|
|
129
|
-
body.timestamp_granularities = [...new Set(req.timestampGranularities)];
|
|
130
|
-
}
|
|
131
|
-
return body;
|
|
132
|
-
}
|
|
133
|
-
function malformed(reason, opts) {
|
|
134
|
-
return new ai_error_1.AiError('AI_PROVIDER_UNAVAILABLE', 'OpenAI returned a malformed transcription response.', {
|
|
135
|
-
details: {
|
|
136
|
-
provider: openai_errors_1.OPENAI_PROVIDER_ID,
|
|
137
|
-
// Not `reason`: the error body's `details.reason` is always the AiErrorCode.
|
|
138
|
-
problem: reason,
|
|
139
|
-
...(opts.providerRequestId ? { providerRequestId: opts.providerRequestId } : {}),
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
function finite(value) {
|
|
144
|
-
return typeof value === 'number' && Number.isFinite(value) && value >= 0;
|
|
145
|
-
}
|
|
146
|
-
/** Token usage (the GPT-4o family) and, separately, a billed duration (Whisper). */
|
|
147
|
-
function transcriptionUsage(usage) {
|
|
148
|
-
if (!usage)
|
|
149
|
-
return { usage: {} };
|
|
150
|
-
if (usage.type === 'duration') {
|
|
151
|
-
return { usage: {}, ...(finite(usage.seconds) ? { seconds: usage.seconds } : {}) };
|
|
152
|
-
}
|
|
153
|
-
const out = {};
|
|
154
|
-
if (finite(usage.input_tokens))
|
|
155
|
-
out.inputTokens = usage.input_tokens;
|
|
156
|
-
if (finite(usage.output_tokens))
|
|
157
|
-
out.outputTokens = usage.output_tokens;
|
|
158
|
-
return { usage: out };
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* The neutral result, from whichever shape the requested `response_format`
|
|
162
|
-
* produced: a bare string (`text`), `{ text, usage? }` (`json`), or the
|
|
163
|
-
* verbose object with language, duration, segments and words.
|
|
164
|
-
*/
|
|
165
|
-
function fromOpenAiTranscriptionResponse(data, opts) {
|
|
166
|
-
const base = {
|
|
167
|
-
provider: openai_errors_1.OPENAI_PROVIDER_ID,
|
|
168
|
-
model: opts.request.model,
|
|
169
|
-
...(opts.providerRequestId ? { providerRequestId: opts.providerRequestId } : {}),
|
|
170
|
-
};
|
|
171
|
-
if (typeof data === 'string') {
|
|
172
|
-
return { ...base, text: data.trim(), usage: {} };
|
|
173
|
-
}
|
|
174
|
-
if (!data || typeof data !== 'object' || typeof data.text !== 'string') {
|
|
175
|
-
throw malformed('missing_text', opts);
|
|
176
|
-
}
|
|
177
|
-
const body = data;
|
|
178
|
-
const { usage, seconds } = transcriptionUsage(body.usage);
|
|
179
|
-
const result = { ...base, text: body.text, usage };
|
|
180
|
-
const language = typeof body.language === 'string' && body.language ? body.language : body.languages?.[0]?.code;
|
|
181
|
-
if (language)
|
|
182
|
-
result.language = language;
|
|
183
|
-
const duration = finite(body.duration) ? body.duration : seconds;
|
|
184
|
-
if (duration !== undefined)
|
|
185
|
-
result.durationSeconds = duration;
|
|
186
|
-
if (Array.isArray(body.segments)) {
|
|
187
|
-
result.segments = body.segments
|
|
188
|
-
.filter((s) => finite(s.start) && finite(s.end) && typeof s.text === 'string')
|
|
189
|
-
.map((s) => ({ startSeconds: s.start, endSeconds: s.end, text: s.text.trim() }));
|
|
190
|
-
}
|
|
191
|
-
if (Array.isArray(body.words)) {
|
|
192
|
-
result.words = body.words
|
|
193
|
-
.filter((w) => finite(w.start) && finite(w.end) && typeof w.word === 'string')
|
|
194
|
-
.map((w) => ({ startSeconds: w.start, endSeconds: w.end, word: w.word }));
|
|
195
|
-
}
|
|
196
|
-
return result;
|
|
197
|
-
}
|
|
198
|
-
// ---- Speech (#439) ------------------------------------------------------------
|
|
199
|
-
//
|
|
200
|
-
// The answer is the audio itself (a binary body), never a URL. `tts-1` and
|
|
201
|
-
// `tts-1-hd` do not take `instructions`; it is left out for them rather than
|
|
202
|
-
// sent to a 400. `stream_format` is never sent: the endpoint's default for a
|
|
203
|
-
// non-streamed call is the whole file.
|
|
204
|
-
const TTS1 = /^tts-1(?:-|$)/;
|
|
205
|
-
/** Whether OpenAI model `modelId` is `tts-1`/`tts-1-hd` (no `instructions`). */
|
|
206
|
-
function isOpenAiTts1(modelId) {
|
|
207
|
-
return TTS1.test(modelId.trim().toLowerCase());
|
|
208
|
-
}
|
|
209
|
-
function invalidSpeech(message, details = {}) {
|
|
210
|
-
return new ai_error_1.AiError('AI_INVALID_REQUEST', message, { details: { provider: openai_errors_1.OPENAI_PROVIDER_ID, ...details } });
|
|
211
|
-
}
|
|
212
|
-
/** The `/v1/audio/speech` JSON body. Refuses what OpenAI would refuse, before calling. */
|
|
213
|
-
function toOpenAiSpeechRequest(req) {
|
|
214
|
-
if (typeof req.input !== 'string' || req.input.trim().length === 0) {
|
|
215
|
-
throw invalidSpeech('Speech needs non-empty input text.');
|
|
216
|
-
}
|
|
217
|
-
if (req.input.length > media_types_1.AI_SPEECH_INPUT_MAX_CHARS) {
|
|
218
|
-
throw invalidSpeech(`Speech input is longer than ${media_types_1.AI_SPEECH_INPUT_MAX_CHARS} characters.`, {
|
|
219
|
-
length: req.input.length,
|
|
220
|
-
max: media_types_1.AI_SPEECH_INPUT_MAX_CHARS,
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
if (typeof req.voice !== 'string' || req.voice.trim().length === 0) {
|
|
224
|
-
throw invalidSpeech('Speech needs a voice.');
|
|
225
|
-
}
|
|
226
|
-
if (req.speed !== undefined && !(req.speed >= media_types_1.AI_SPEECH_SPEED_MIN && req.speed <= media_types_1.AI_SPEECH_SPEED_MAX)) {
|
|
227
|
-
throw invalidSpeech(`speed must be from ${media_types_1.AI_SPEECH_SPEED_MIN} to ${media_types_1.AI_SPEECH_SPEED_MAX}.`, { speed: req.speed });
|
|
228
|
-
}
|
|
229
|
-
const escapeHatch = (req.providerOptions?.[openai_errors_1.OPENAI_PROVIDER_ID] ?? {});
|
|
230
|
-
const body = {
|
|
231
|
-
...escapeHatch,
|
|
232
|
-
model: req.model,
|
|
233
|
-
input: req.input,
|
|
234
|
-
voice: req.voice,
|
|
235
|
-
response_format: req.format ?? 'mp3',
|
|
236
|
-
};
|
|
237
|
-
if (req.speed !== undefined)
|
|
238
|
-
body.speed = req.speed;
|
|
239
|
-
if (req.instructions !== undefined && !isOpenAiTts1(req.model))
|
|
240
|
-
body.instructions = req.instructions;
|
|
241
|
-
return body;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* The neutral result: the bytes, typed by the format that was asked for
|
|
245
|
-
* (the one OpenAI produces). No bytes is a provider fault.
|
|
246
|
-
*/
|
|
247
|
-
function fromOpenAiSpeechResponse(bytes, opts) {
|
|
248
|
-
if (bytes.byteLength === 0) {
|
|
249
|
-
throw new ai_error_1.AiError('AI_PROVIDER_UNAVAILABLE', 'OpenAI returned an empty speech response.', {
|
|
250
|
-
details: {
|
|
251
|
-
provider: openai_errors_1.OPENAI_PROVIDER_ID,
|
|
252
|
-
problem: 'empty_audio',
|
|
253
|
-
...(opts.providerRequestId ? { providerRequestId: opts.providerRequestId } : {}),
|
|
254
|
-
},
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
const format = opts.request.format ?? 'mp3';
|
|
258
|
-
return {
|
|
259
|
-
provider: openai_errors_1.OPENAI_PROVIDER_ID,
|
|
260
|
-
model: opts.request.model,
|
|
261
|
-
audio: { data: bytes, mimeType: media_types_1.AI_SPEECH_FORMAT_MIME[format] },
|
|
262
|
-
usage: {},
|
|
263
|
-
...(opts.providerRequestId ? { providerRequestId: opts.providerRequestId } : {}),
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
//# sourceMappingURL=openai-audio.mapper.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-audio.mapper.js","sourceRoot":"","sources":["../../../../src/ai/providers/openai/openai-audio.mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { Logger } from '@nestjs/common';
|
|
2
|
-
import { Span } from '@opentelemetry/api';
|
|
3
|
-
import type { AiError } from '../../core/ai-error';
|
|
4
|
-
import type { AiCallContext } from '../../core/provider-adapter.interface';
|
|
5
|
-
import { type OpenAiFamily } from './openai-errors';
|
|
6
|
-
export declare const AI_PROVIDER_CALL_SPAN = "ai.provider.call";
|
|
7
|
-
export declare class OpenAiCallTelemetry {
|
|
8
|
-
private readonly family;
|
|
9
|
-
private readonly logger;
|
|
10
|
-
/** Maps a thrown error; the family's own `mapOpenAiError` by default. */
|
|
11
|
-
private readonly mapError;
|
|
12
|
-
constructor(family: OpenAiFamily, logger: Logger,
|
|
13
|
-
/** Maps a thrown error; the family's own `mapOpenAiError` by default. */
|
|
14
|
-
mapError?: (err: unknown) => AiError);
|
|
15
|
-
startSpan(operation: string, model: string | undefined): Span;
|
|
16
|
-
endSpan(span: Span, status: string): void;
|
|
17
|
-
/**
|
|
18
|
-
* ⚠ Only ids, the model, the operation, the outcome and a duration. Never
|
|
19
|
-
* `ctx.apiKey`, never the request or response body.
|
|
20
|
-
*/
|
|
21
|
-
logCall(operation: string, model: string | undefined, ctx: AiCallContext, status: string, started: number, providerRequestId?: string | null): void;
|
|
22
|
-
/** Runs `fn` inside an `ai.provider.call` span, mapping any failure to `AiError`. */
|
|
23
|
-
call<T>(operation: string, model: string | undefined, ctx: AiCallContext, fn: () => Promise<T>): Promise<T>;
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=openai-call-telemetry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-call-telemetry.d.ts","sourceRoot":"","sources":["../../../../src/ai/providers/openai/openai-call-telemetry.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAmC,MAAM,oBAAoB,CAAC;AAE3E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAE3E,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpE,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAIxD,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAHR,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM;IAC/B,yEAAyE;IACxD,QAAQ,GAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAA8C;IAG7F,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAW7D,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAMzC;;;OAGG;IACH,OAAO,CACL,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,GAChC,IAAI;IAaP,qFAAqF;IAC/E,IAAI,CAAC,CAAC,EACV,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC;CA0Bd"}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// =============================================================================
|
|
3
|
-
// Provider-call telemetry for the OpenAI wire family (issue #426, extracted #448)
|
|
4
|
-
// =============================================================================
|
|
5
|
-
//
|
|
6
|
-
// Every provider call an OpenAI-family adapter (OpenAI, Azure OpenAI, a
|
|
7
|
-
// generic OpenAI-compatible server) makes runs inside one `ai.provider.call`
|
|
8
|
-
// span carrying `ai.provider`, `ai.model`, `ai.operation` and `ai.status`
|
|
9
|
-
// (`ok` or the AiErrorCode) — never prompt text, output text or the key. The
|
|
10
|
-
// debug log line carries the same four facts plus the request ids and a
|
|
11
|
-
// duration. No exception is recorded on the span: an SDK error's message can
|
|
12
|
-
// echo a masked key.
|
|
13
|
-
//
|
|
14
|
-
// Extracted from `openai.adapter.ts` unchanged so the two #448 adapters share
|
|
15
|
-
// it rather than copy it; the OpenAI adapter's spans and log lines are
|
|
16
|
-
// byte-for-byte what they were.
|
|
17
|
-
// =============================================================================
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.OpenAiCallTelemetry = exports.AI_PROVIDER_CALL_SPAN = void 0;
|
|
20
|
-
const api_1 = require("@opentelemetry/api");
|
|
21
|
-
const index_1 = require("../../../otel-core/index");
|
|
22
|
-
const openai_errors_1 = require("./openai-errors");
|
|
23
|
-
exports.AI_PROVIDER_CALL_SPAN = 'ai.provider.call';
|
|
24
|
-
const tracer = api_1.trace.getTracer((0, index_1.resolveServiceName)());
|
|
25
|
-
class OpenAiCallTelemetry {
|
|
26
|
-
family;
|
|
27
|
-
logger;
|
|
28
|
-
mapError;
|
|
29
|
-
constructor(family, logger,
|
|
30
|
-
/** Maps a thrown error; the family's own `mapOpenAiError` by default. */
|
|
31
|
-
mapError = (err) => (0, openai_errors_1.mapOpenAiError)(err, family)) {
|
|
32
|
-
this.family = family;
|
|
33
|
-
this.logger = logger;
|
|
34
|
-
this.mapError = mapError;
|
|
35
|
-
}
|
|
36
|
-
startSpan(operation, model) {
|
|
37
|
-
return tracer.startSpan(exports.AI_PROVIDER_CALL_SPAN, {
|
|
38
|
-
kind: api_1.SpanKind.CLIENT,
|
|
39
|
-
attributes: {
|
|
40
|
-
'ai.provider': this.family.providerId,
|
|
41
|
-
'ai.operation': operation,
|
|
42
|
-
...(model ? { 'ai.model': model } : {}),
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
endSpan(span, status) {
|
|
47
|
-
span.setAttribute('ai.status', status);
|
|
48
|
-
span.setStatus(status === 'ok' ? { code: api_1.SpanStatusCode.OK } : { code: api_1.SpanStatusCode.ERROR, message: status });
|
|
49
|
-
span.end();
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* ⚠ Only ids, the model, the operation, the outcome and a duration. Never
|
|
53
|
-
* `ctx.apiKey`, never the request or response body.
|
|
54
|
-
*/
|
|
55
|
-
logCall(operation, model, ctx, status, started, providerRequestId) {
|
|
56
|
-
this.logger.debug({
|
|
57
|
-
msg: 'AI provider call',
|
|
58
|
-
provider: this.family.providerId,
|
|
59
|
-
operation,
|
|
60
|
-
model,
|
|
61
|
-
status,
|
|
62
|
-
requestId: ctx.requestId,
|
|
63
|
-
providerRequestId: providerRequestId ?? undefined,
|
|
64
|
-
durationMs: Date.now() - started,
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
/** Runs `fn` inside an `ai.provider.call` span, mapping any failure to `AiError`. */
|
|
68
|
-
async call(operation, model, ctx, fn) {
|
|
69
|
-
const started = Date.now();
|
|
70
|
-
const span = this.startSpan(operation, model);
|
|
71
|
-
let status = 'ok';
|
|
72
|
-
let providerRequestId;
|
|
73
|
-
try {
|
|
74
|
-
const result = await fn();
|
|
75
|
-
if (result && typeof result === 'object' && 'providerRequestId' in result) {
|
|
76
|
-
providerRequestId = result.providerRequestId;
|
|
77
|
-
}
|
|
78
|
-
return result;
|
|
79
|
-
}
|
|
80
|
-
catch (err) {
|
|
81
|
-
const mapped = this.mapError(err);
|
|
82
|
-
status = mapped.code;
|
|
83
|
-
providerRequestId = mapped.toJSON().details.providerRequestId;
|
|
84
|
-
throw mapped;
|
|
85
|
-
}
|
|
86
|
-
finally {
|
|
87
|
-
this.endSpan(span, status);
|
|
88
|
-
this.logCall(operation, model, ctx, status, started, providerRequestId);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
exports.OpenAiCallTelemetry = OpenAiCallTelemetry;
|
|
93
|
-
//# sourceMappingURL=openai-call-telemetry.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-call-telemetry.js","sourceRoot":"","sources":["../../../../src/ai/providers/openai/openai-call-telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { ChatCompletionChunk } from 'openai/resources/chat/completions/completions';
|
|
2
|
-
import { AiError } from '../../core/ai-error';
|
|
3
|
-
import type { AiResponseRequest, AiStreamEvent } from '../../core/types/responses.types';
|
|
4
|
-
import { type OpenAiFamily } from './openai-errors';
|
|
5
|
-
export interface ChatCompletionsStreamMapperOptions {
|
|
6
|
-
request: AiResponseRequest;
|
|
7
|
-
providerRequestId?: string | null;
|
|
8
|
-
family?: OpenAiFamily;
|
|
9
|
-
}
|
|
10
|
-
export declare class ChatCompletionsStreamMapper {
|
|
11
|
-
private readonly opts;
|
|
12
|
-
private id;
|
|
13
|
-
private model;
|
|
14
|
-
private created;
|
|
15
|
-
private text;
|
|
16
|
-
private refusal;
|
|
17
|
-
private readonly calls;
|
|
18
|
-
private finishReason;
|
|
19
|
-
private usage;
|
|
20
|
-
private startedFlag;
|
|
21
|
-
private terminalFlag;
|
|
22
|
-
constructor(opts: ChatCompletionsStreamMapperOptions);
|
|
23
|
-
private get family();
|
|
24
|
-
/** Whether `response.created` has been emitted. */
|
|
25
|
-
get started(): boolean;
|
|
26
|
-
/** Whether a terminal event (`response.completed` or `error`) has been emitted. */
|
|
27
|
-
get terminated(): boolean;
|
|
28
|
-
/** Whether the server has said why the turn ended — i.e. whether `finish()` can complete. */
|
|
29
|
-
get finished(): boolean;
|
|
30
|
-
/** Maps one SDK chunk to zero or more of ours. Nothing is emitted after a terminal event. */
|
|
31
|
-
map(chunk: ChatCompletionChunk): AiStreamEvent[];
|
|
32
|
-
/**
|
|
33
|
-
* The closing events, once the SDK stream is exhausted: each output item's
|
|
34
|
-
* `output_item.done`, then `response.completed` — or nothing when the
|
|
35
|
-
* server never gave a finish reason (see the file header).
|
|
36
|
-
*/
|
|
37
|
-
finish(): AiStreamEvent[];
|
|
38
|
-
/** Ends the stream with an `error` event for `err` (idempotent). */
|
|
39
|
-
fail(err: AiError): AiStreamEvent[];
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=openai-chat-completions-stream.mapper.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-chat-completions-stream.mapper.d.ts","sourceRoot":"","sources":["../../../../src/ai/providers/openai/openai-chat-completions-stream.mapper.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAkB,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AAEzG,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnE,MAAM,WAAW,kCAAkC;IACjD,OAAO,EAAE,iBAAiB,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAQD,qBAAa,2BAA2B;IAY1B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAXjC,OAAO,CAAC,EAAE,CAAuB;IACjC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,YAAY,CAAuD;IAC3E,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;gBAEA,IAAI,EAAE,kCAAkC;IAErE,OAAO,KAAK,MAAM,GAEjB;IAED,mDAAmD;IACnD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,mFAAmF;IACnF,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,6FAA6F;IAC7F,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,6FAA6F;IAC7F,GAAG,CAAC,KAAK,EAAE,mBAAmB,GAAG,aAAa,EAAE;IAoDhD;;;;OAIG;IACH,MAAM,IAAI,aAAa,EAAE;IAsDzB,oEAAoE;IACpE,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,EAAE;CAMpC"}
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// =============================================================================
|
|
3
|
-
// Chat Completions stream chunks -> AiStreamEvent (issue #448, epic #421)
|
|
4
|
-
// =============================================================================
|
|
5
|
-
//
|
|
6
|
-
// One mapper per stream. Chat Completions streams DELTAS only — there is no
|
|
7
|
-
// `response.created`, no per-item `done`, and no final object — so this
|
|
8
|
-
// mapper accumulates what the Responses API would have announced:
|
|
9
|
-
//
|
|
10
|
-
// first chunk -> response.created (the chunk's id)
|
|
11
|
-
// choices[0].delta.content -> output_text.delta
|
|
12
|
-
// choices[0].delta.tool_calls[i] -> function_call.arguments.delta, keyed by
|
|
13
|
-
// the call id the i-th call announced in
|
|
14
|
-
// its first fragment
|
|
15
|
-
// choices[0].finish_reason -> remembered
|
|
16
|
-
// a usage-only chunk (no choices) -> remembered (stream_options.include_usage)
|
|
17
|
-
//
|
|
18
|
-
// `finish()`, called once the SDK stream is exhausted, emits the
|
|
19
|
-
// `output_item.done` events (the message, then each function call) and the
|
|
20
|
-
// terminal `response.completed`, built by handing a synthetic `ChatCompletion`
|
|
21
|
-
// to `fromChatCompletion` — the same function `create` uses, so structured
|
|
22
|
-
// output is validated identically; if that fails the stream ends with an
|
|
23
|
-
// `error` event instead. A stream that ends WITHOUT a finish reason was cut
|
|
24
|
-
// short: `finish()` returns nothing and the engine fails it as truncated.
|
|
25
|
-
//
|
|
26
|
-
// Error events carry OUR generic message for the code, never the server's.
|
|
27
|
-
// =============================================================================
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.ChatCompletionsStreamMapper = void 0;
|
|
30
|
-
const node_crypto_1 = require("node:crypto");
|
|
31
|
-
const ai_error_1 = require("../../core/ai-error");
|
|
32
|
-
const openai_chat_completions_mapper_1 = require("./openai-chat-completions.mapper");
|
|
33
|
-
const openai_errors_1 = require("./openai-errors");
|
|
34
|
-
class ChatCompletionsStreamMapper {
|
|
35
|
-
opts;
|
|
36
|
-
id = null;
|
|
37
|
-
model = null;
|
|
38
|
-
created = 0;
|
|
39
|
-
text = '';
|
|
40
|
-
refusal = '';
|
|
41
|
-
calls = new Map();
|
|
42
|
-
finishReason = null;
|
|
43
|
-
usage;
|
|
44
|
-
startedFlag = false;
|
|
45
|
-
terminalFlag = false;
|
|
46
|
-
constructor(opts) {
|
|
47
|
-
this.opts = opts;
|
|
48
|
-
}
|
|
49
|
-
get family() {
|
|
50
|
-
return this.opts.family ?? openai_errors_1.OPENAI_FAMILY;
|
|
51
|
-
}
|
|
52
|
-
/** Whether `response.created` has been emitted. */
|
|
53
|
-
get started() {
|
|
54
|
-
return this.startedFlag;
|
|
55
|
-
}
|
|
56
|
-
/** Whether a terminal event (`response.completed` or `error`) has been emitted. */
|
|
57
|
-
get terminated() {
|
|
58
|
-
return this.terminalFlag;
|
|
59
|
-
}
|
|
60
|
-
/** Whether the server has said why the turn ended — i.e. whether `finish()` can complete. */
|
|
61
|
-
get finished() {
|
|
62
|
-
return this.finishReason !== null;
|
|
63
|
-
}
|
|
64
|
-
/** Maps one SDK chunk to zero or more of ours. Nothing is emitted after a terminal event. */
|
|
65
|
-
map(chunk) {
|
|
66
|
-
if (this.terminalFlag)
|
|
67
|
-
return [];
|
|
68
|
-
const events = [];
|
|
69
|
-
if (!this.startedFlag) {
|
|
70
|
-
this.startedFlag = true;
|
|
71
|
-
// Some compatible servers omit the id; the neutral contract needs one.
|
|
72
|
-
this.id = chunk.id || `chatcmpl-${(0, node_crypto_1.randomUUID)()}`;
|
|
73
|
-
events.push({ type: 'response.created', id: this.id });
|
|
74
|
-
}
|
|
75
|
-
if (chunk.model)
|
|
76
|
-
this.model = chunk.model;
|
|
77
|
-
if (typeof chunk.created === 'number')
|
|
78
|
-
this.created = chunk.created;
|
|
79
|
-
if (chunk.usage)
|
|
80
|
-
this.usage = chunk.usage;
|
|
81
|
-
const choice = chunk.choices?.[0];
|
|
82
|
-
if (!choice)
|
|
83
|
-
return events;
|
|
84
|
-
const delta = choice.delta ?? {};
|
|
85
|
-
if (typeof delta.content === 'string' && delta.content.length > 0) {
|
|
86
|
-
this.text += delta.content;
|
|
87
|
-
events.push({ type: 'output_text.delta', delta: delta.content });
|
|
88
|
-
}
|
|
89
|
-
if (typeof delta.refusal === 'string')
|
|
90
|
-
this.refusal += delta.refusal;
|
|
91
|
-
for (const fragment of delta.tool_calls ?? []) {
|
|
92
|
-
let call = this.calls.get(fragment.index);
|
|
93
|
-
if (!call) {
|
|
94
|
-
call = { id: fragment.id || `call_${(0, node_crypto_1.randomUUID)()}`, name: '', arguments: '' };
|
|
95
|
-
this.calls.set(fragment.index, call);
|
|
96
|
-
}
|
|
97
|
-
if (fragment.function?.name)
|
|
98
|
-
call.name += fragment.function.name;
|
|
99
|
-
const args = fragment.function?.arguments;
|
|
100
|
-
if (args) {
|
|
101
|
-
call.arguments += args;
|
|
102
|
-
events.push({ type: 'function_call.arguments.delta', callId: call.id, delta: args });
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
if (choice.finish_reason)
|
|
106
|
-
this.finishReason = choice.finish_reason;
|
|
107
|
-
return events;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* The closing events, once the SDK stream is exhausted: each output item's
|
|
111
|
-
* `output_item.done`, then `response.completed` — or nothing when the
|
|
112
|
-
* server never gave a finish reason (see the file header).
|
|
113
|
-
*/
|
|
114
|
-
finish() {
|
|
115
|
-
if (this.terminalFlag || !this.startedFlag || this.finishReason === null)
|
|
116
|
-
return [];
|
|
117
|
-
const completion = {
|
|
118
|
-
id: this.id ?? '',
|
|
119
|
-
object: 'chat.completion',
|
|
120
|
-
created: this.created,
|
|
121
|
-
model: this.model ?? this.opts.request.model,
|
|
122
|
-
choices: [
|
|
123
|
-
{
|
|
124
|
-
index: 0,
|
|
125
|
-
finish_reason: this.finishReason,
|
|
126
|
-
logprobs: null,
|
|
127
|
-
message: {
|
|
128
|
-
role: 'assistant',
|
|
129
|
-
content: this.text.length > 0 ? this.text : null,
|
|
130
|
-
refusal: this.refusal.length > 0 ? this.refusal : null,
|
|
131
|
-
...(this.calls.size > 0
|
|
132
|
-
? {
|
|
133
|
-
tool_calls: [...this.calls.entries()]
|
|
134
|
-
.sort(([a], [b]) => a - b)
|
|
135
|
-
.map(([, call]) => ({
|
|
136
|
-
id: call.id,
|
|
137
|
-
type: 'function',
|
|
138
|
-
function: { name: call.name, arguments: call.arguments },
|
|
139
|
-
})),
|
|
140
|
-
}
|
|
141
|
-
: {}),
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
],
|
|
145
|
-
...(this.usage ? { usage: this.usage } : {}),
|
|
146
|
-
};
|
|
147
|
-
let response;
|
|
148
|
-
try {
|
|
149
|
-
response = (0, openai_chat_completions_mapper_1.fromChatCompletion)(completion, {
|
|
150
|
-
request: this.opts.request,
|
|
151
|
-
providerRequestId: this.opts.providerRequestId,
|
|
152
|
-
family: this.family,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
catch (err) {
|
|
156
|
-
return this.fail(ai_error_1.AiError.wrap(err));
|
|
157
|
-
}
|
|
158
|
-
this.terminalFlag = true;
|
|
159
|
-
return [
|
|
160
|
-
...response.output.map((item) => ({ type: 'output_item.done', item })),
|
|
161
|
-
{ type: 'response.completed', response },
|
|
162
|
-
];
|
|
163
|
-
}
|
|
164
|
-
/** Ends the stream with an `error` event for `err` (idempotent). */
|
|
165
|
-
fail(err) {
|
|
166
|
-
if (this.terminalFlag)
|
|
167
|
-
return [];
|
|
168
|
-
this.terminalFlag = true;
|
|
169
|
-
return [{ type: 'error', code: err.code, message: err.message }];
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
exports.ChatCompletionsStreamMapper = ChatCompletionsStreamMapper;
|
|
173
|
-
//# sourceMappingURL=openai-chat-completions-stream.mapper.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-chat-completions-stream.mapper.js","sourceRoot":"","sources":["../../../../src/ai/providers/openai/openai-chat-completions-stream.mapper.ts"],"names":[],"mappings":"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"}
|