@fgv/ts-extras 5.1.0-4 → 5.1.0-40
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/dist/index.browser.js +4 -2
- package/dist/index.browser.js.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/packlets/ai-assist/apiClient.js +886 -158
- package/dist/packlets/ai-assist/apiClient.js.map +1 -0
- package/dist/packlets/ai-assist/chatRequestBuilders.js +282 -0
- package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
- package/dist/packlets/ai-assist/converters.js +47 -3
- package/dist/packlets/ai-assist/converters.js.map +1 -0
- package/dist/packlets/ai-assist/embeddingClient.js +345 -0
- package/dist/packlets/ai-assist/embeddingClient.js.map +1 -0
- package/dist/packlets/ai-assist/endpoint.js +78 -0
- package/dist/packlets/ai-assist/endpoint.js.map +1 -0
- package/dist/packlets/ai-assist/http.js +75 -0
- package/dist/packlets/ai-assist/http.js.map +1 -0
- package/dist/packlets/ai-assist/imageOptionsResolver.js +193 -0
- package/dist/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
- package/dist/packlets/ai-assist/index.js +10 -4
- package/dist/packlets/ai-assist/index.js.map +1 -0
- package/dist/packlets/ai-assist/jsonCompletion.js +93 -0
- package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -0
- package/dist/packlets/ai-assist/jsonResponse.js +149 -0
- package/dist/packlets/ai-assist/jsonResponse.js.map +1 -0
- package/dist/packlets/ai-assist/model.js +193 -9
- package/dist/packlets/ai-assist/model.js.map +1 -0
- package/dist/packlets/ai-assist/registry.js +314 -12
- package/dist/packlets/ai-assist/registry.js.map +1 -0
- package/dist/packlets/ai-assist/sseParser.js +123 -0
- package/dist/packlets/ai-assist/sseParser.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +368 -0
- package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +687 -0
- package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/common.js +187 -0
- package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/gemini.js +204 -0
- package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +170 -0
- package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +386 -0
- package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/proxy.js +173 -0
- package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
- package/dist/packlets/ai-assist/streamingClient.js +140 -0
- package/dist/packlets/ai-assist/streamingClient.js.map +1 -0
- package/dist/packlets/ai-assist/thinkingOptionsResolver.js +288 -0
- package/dist/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
- package/dist/packlets/ai-assist/toolFormats.js +106 -10
- package/dist/packlets/ai-assist/toolFormats.js.map +1 -0
- package/dist/packlets/conversion/converters.js +35 -1
- package/dist/packlets/conversion/converters.js.map +1 -0
- package/dist/packlets/conversion/index.js.map +1 -0
- package/dist/packlets/crypto-utils/constants.js.map +1 -0
- package/dist/packlets/crypto-utils/converters.js +42 -4
- package/dist/packlets/crypto-utils/converters.js.map +1 -0
- package/dist/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
- package/dist/packlets/crypto-utils/encryptedFile.js.map +1 -0
- package/dist/packlets/crypto-utils/hpkeProvider.js +333 -0
- package/dist/packlets/crypto-utils/hpkeProvider.js.map +1 -0
- package/dist/packlets/crypto-utils/index.browser.js +10 -2
- package/dist/packlets/crypto-utils/index.browser.js.map +1 -0
- package/dist/packlets/crypto-utils/index.js +6 -0
- package/dist/packlets/crypto-utils/index.js.map +1 -0
- package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js +71 -0
- package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
- package/dist/packlets/crypto-utils/keystore/converters.js +103 -11
- package/dist/packlets/crypto-utils/keystore/converters.js.map +1 -0
- package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +287 -0
- package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
- package/dist/packlets/crypto-utils/keystore/index.browser.js +36 -0
- package/dist/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
- package/dist/packlets/crypto-utils/keystore/index.js +3 -0
- package/dist/packlets/crypto-utils/keystore/index.js.map +1 -0
- package/dist/packlets/crypto-utils/keystore/keyStore.js +633 -118
- package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
- package/dist/packlets/crypto-utils/keystore/model.js +22 -1
- package/dist/packlets/crypto-utils/keystore/model.js.map +1 -0
- package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js +21 -0
- package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
- package/dist/packlets/crypto-utils/model.js +32 -0
- package/dist/packlets/crypto-utils/model.js.map +1 -0
- package/dist/packlets/crypto-utils/nodeCryptoProvider.js +270 -1
- package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
- package/dist/packlets/crypto-utils/spkiHelpers.js +209 -0
- package/dist/packlets/crypto-utils/spkiHelpers.js.map +1 -0
- package/dist/packlets/csv/csvFileHelpers.js +0 -14
- package/dist/packlets/csv/csvFileHelpers.js.map +1 -0
- package/dist/packlets/csv/csvHelpers.js +14 -0
- package/dist/packlets/csv/csvHelpers.js.map +1 -0
- package/dist/packlets/csv/index.browser.js +1 -3
- package/dist/packlets/csv/index.browser.js.map +1 -0
- package/dist/packlets/csv/index.js.map +1 -0
- package/dist/packlets/experimental/extendedArray.js.map +1 -0
- package/dist/packlets/experimental/formatter.js.map +1 -0
- package/dist/packlets/experimental/index.js.map +1 -0
- package/dist/packlets/experimental/rangeOf.js.map +1 -0
- package/dist/packlets/hash/index.browser.js.map +1 -0
- package/dist/packlets/hash/index.js.map +1 -0
- package/dist/packlets/hash/index.node.js.map +1 -0
- package/dist/packlets/hash/md5Normalizer.browser.js.map +1 -0
- package/dist/packlets/hash/md5Normalizer.js.map +1 -0
- package/dist/packlets/mustache/index.js.map +1 -0
- package/dist/packlets/mustache/interfaces.js.map +1 -0
- package/dist/packlets/mustache/mustacheTemplate.js +42 -4
- package/dist/packlets/mustache/mustacheTemplate.js.map +1 -0
- package/dist/packlets/record-jar/index.browser.js +1 -3
- package/dist/packlets/record-jar/index.browser.js.map +1 -0
- package/dist/packlets/record-jar/index.js.map +1 -0
- package/dist/packlets/record-jar/recordJarFileHelpers.js +0 -18
- package/dist/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
- package/dist/packlets/record-jar/recordJarHelpers.js +18 -0
- package/dist/packlets/record-jar/recordJarHelpers.js.map +1 -0
- package/dist/packlets/yaml/converters.js.map +1 -0
- package/dist/packlets/yaml/index.js +1 -0
- package/dist/packlets/yaml/index.js.map +1 -0
- package/dist/packlets/yaml/serializers.js +48 -0
- package/dist/packlets/yaml/serializers.js.map +1 -0
- package/dist/packlets/zip-file-tree/index.js.map +1 -0
- package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js +2 -2
- package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
- package/dist/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
- package/dist/ts-extras.d.ts +3880 -105
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/index.browser.d.ts +4 -2
- package/lib/index.browser.d.ts.map +1 -0
- package/lib/index.browser.js +8 -3
- package/lib/index.browser.js.map +1 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js.map +1 -0
- package/lib/packlets/ai-assist/apiClient.d.ts +115 -32
- package/lib/packlets/ai-assist/apiClient.d.ts.map +1 -0
- package/lib/packlets/ai-assist/apiClient.js +888 -156
- package/lib/packlets/ai-assist/apiClient.js.map +1 -0
- package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +149 -0
- package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -0
- package/lib/packlets/ai-assist/chatRequestBuilders.js +293 -0
- package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
- package/lib/packlets/ai-assist/converters.d.ts +15 -1
- package/lib/packlets/ai-assist/converters.d.ts.map +1 -0
- package/lib/packlets/ai-assist/converters.js +47 -3
- package/lib/packlets/ai-assist/converters.js.map +1 -0
- package/lib/packlets/ai-assist/embeddingClient.d.ts +69 -0
- package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -0
- package/lib/packlets/ai-assist/embeddingClient.js +349 -0
- package/lib/packlets/ai-assist/embeddingClient.js.map +1 -0
- package/lib/packlets/ai-assist/endpoint.d.ts +28 -0
- package/lib/packlets/ai-assist/endpoint.d.ts.map +1 -0
- package/lib/packlets/ai-assist/endpoint.js +82 -0
- package/lib/packlets/ai-assist/endpoint.js.map +1 -0
- package/lib/packlets/ai-assist/http.d.ts +24 -0
- package/lib/packlets/ai-assist/http.d.ts.map +1 -0
- package/lib/packlets/ai-assist/http.js +78 -0
- package/lib/packlets/ai-assist/http.js.map +1 -0
- package/lib/packlets/ai-assist/imageOptionsResolver.d.ts +66 -0
- package/lib/packlets/ai-assist/imageOptionsResolver.d.ts.map +1 -0
- package/lib/packlets/ai-assist/imageOptionsResolver.js +197 -0
- package/lib/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
- package/lib/packlets/ai-assist/index.d.ts +10 -4
- package/lib/packlets/ai-assist/index.d.ts.map +1 -0
- package/lib/packlets/ai-assist/index.js +36 -1
- package/lib/packlets/ai-assist/index.js.map +1 -0
- package/lib/packlets/ai-assist/jsonCompletion.d.ts +93 -0
- package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -0
- package/lib/packlets/ai-assist/jsonCompletion.js +97 -0
- package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -0
- package/lib/packlets/ai-assist/jsonResponse.d.ts +91 -0
- package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -0
- package/lib/packlets/ai-assist/jsonResponse.js +154 -0
- package/lib/packlets/ai-assist/jsonResponse.js.map +1 -0
- package/lib/packlets/ai-assist/model.d.ts +1202 -12
- package/lib/packlets/ai-assist/model.d.ts.map +1 -0
- package/lib/packlets/ai-assist/model.js +198 -10
- package/lib/packlets/ai-assist/model.js.map +1 -0
- package/lib/packlets/ai-assist/registry.d.ts +56 -1
- package/lib/packlets/ai-assist/registry.d.ts.map +1 -0
- package/lib/packlets/ai-assist/registry.js +319 -13
- package/lib/packlets/ai-assist/registry.js.map +1 -0
- package/lib/packlets/ai-assist/sseParser.d.ts +45 -0
- package/lib/packlets/ai-assist/sseParser.d.ts.map +1 -0
- package/lib/packlets/ai-assist/sseParser.js +128 -0
- package/lib/packlets/ai-assist/sseParser.js.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +72 -0
- package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +371 -0
- package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +260 -0
- package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +694 -0
- package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +154 -0
- package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/common.js +193 -0
- package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts +43 -0
- package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/gemini.js +207 -0
- package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts +19 -0
- package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js +173 -0
- package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +33 -0
- package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +389 -0
- package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts +34 -0
- package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/proxy.js +176 -0
- package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
- package/lib/packlets/ai-assist/streamingClient.d.ts +50 -0
- package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -0
- package/lib/packlets/ai-assist/streamingClient.js +146 -0
- package/lib/packlets/ai-assist/streamingClient.js.map +1 -0
- package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts +87 -0
- package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts.map +1 -0
- package/lib/packlets/ai-assist/thinkingOptionsResolver.js +294 -0
- package/lib/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
- package/lib/packlets/ai-assist/toolFormats.d.ts +40 -9
- package/lib/packlets/ai-assist/toolFormats.d.ts.map +1 -0
- package/lib/packlets/ai-assist/toolFormats.js +107 -10
- package/lib/packlets/ai-assist/toolFormats.js.map +1 -0
- package/lib/packlets/conversion/converters.d.ts +8 -1
- package/lib/packlets/conversion/converters.d.ts.map +1 -0
- package/lib/packlets/conversion/converters.js +36 -2
- package/lib/packlets/conversion/converters.js.map +1 -0
- package/lib/packlets/conversion/index.d.ts.map +1 -0
- package/lib/packlets/conversion/index.js.map +1 -0
- package/lib/packlets/crypto-utils/constants.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/constants.js.map +1 -0
- package/lib/packlets/crypto-utils/converters.d.ts +20 -1
- package/lib/packlets/crypto-utils/converters.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/converters.js +43 -5
- package/lib/packlets/crypto-utils/converters.js.map +1 -0
- package/lib/packlets/crypto-utils/directEncryptionProvider.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
- package/lib/packlets/crypto-utils/encryptedFile.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/encryptedFile.js.map +1 -0
- package/lib/packlets/crypto-utils/hpkeProvider.d.ts +142 -0
- package/lib/packlets/crypto-utils/hpkeProvider.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/hpkeProvider.js +337 -0
- package/lib/packlets/crypto-utils/hpkeProvider.js.map +1 -0
- package/lib/packlets/crypto-utils/index.browser.d.ts +4 -1
- package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/index.browser.js +21 -3
- package/lib/packlets/crypto-utils/index.browser.js.map +1 -0
- package/lib/packlets/crypto-utils/index.d.ts +3 -0
- package/lib/packlets/crypto-utils/index.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/index.js +17 -1
- package/lib/packlets/crypto-utils/index.js.map +1 -0
- package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts +54 -0
- package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js +74 -0
- package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
- package/lib/packlets/crypto-utils/keystore/converters.d.ts +68 -6
- package/lib/packlets/crypto-utils/keystore/converters.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keystore/converters.js +101 -9
- package/lib/packlets/crypto-utils/keystore/converters.js.map +1 -0
- package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts +148 -0
- package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +324 -0
- package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
- package/lib/packlets/crypto-utils/keystore/index.browser.d.ts +10 -0
- package/lib/packlets/crypto-utils/keystore/index.browser.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keystore/index.browser.js +76 -0
- package/lib/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
- package/lib/packlets/crypto-utils/keystore/index.d.ts +2 -0
- package/lib/packlets/crypto-utils/keystore/index.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keystore/index.js +5 -1
- package/lib/packlets/crypto-utils/keystore/index.js.map +1 -0
- package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +205 -13
- package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keystore/keyStore.js +639 -124
- package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
- package/lib/packlets/crypto-utils/keystore/model.d.ts +275 -19
- package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keystore/model.js +24 -2
- package/lib/packlets/crypto-utils/keystore/model.js.map +1 -0
- package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts +53 -0
- package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js +22 -0
- package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
- package/lib/packlets/crypto-utils/model.d.ts +348 -10
- package/lib/packlets/crypto-utils/model.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/model.js +33 -1
- package/lib/packlets/crypto-utils/model.js.map +1 -0
- package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts +110 -2
- package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/nodeCryptoProvider.js +269 -0
- package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
- package/lib/packlets/crypto-utils/spkiHelpers.d.ts +110 -0
- package/lib/packlets/crypto-utils/spkiHelpers.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/spkiHelpers.js +219 -0
- package/lib/packlets/crypto-utils/spkiHelpers.js.map +1 -0
- package/lib/packlets/csv/csvFileHelpers.d.ts +0 -10
- package/lib/packlets/csv/csvFileHelpers.d.ts.map +1 -0
- package/lib/packlets/csv/csvFileHelpers.js +0 -15
- package/lib/packlets/csv/csvFileHelpers.js.map +1 -0
- package/lib/packlets/csv/csvHelpers.d.ts +10 -0
- package/lib/packlets/csv/csvHelpers.d.ts.map +1 -0
- package/lib/packlets/csv/csvHelpers.js +15 -0
- package/lib/packlets/csv/csvHelpers.js.map +1 -0
- package/lib/packlets/csv/index.browser.d.ts +0 -1
- package/lib/packlets/csv/index.browser.d.ts.map +1 -0
- package/lib/packlets/csv/index.browser.js +1 -5
- package/lib/packlets/csv/index.browser.js.map +1 -0
- package/lib/packlets/csv/index.d.ts.map +1 -0
- package/lib/packlets/csv/index.js.map +1 -0
- package/lib/packlets/experimental/extendedArray.d.ts.map +1 -0
- package/lib/packlets/experimental/extendedArray.js.map +1 -0
- package/lib/packlets/experimental/formatter.d.ts.map +1 -0
- package/lib/packlets/experimental/formatter.js.map +1 -0
- package/lib/packlets/experimental/index.d.ts.map +1 -0
- package/lib/packlets/experimental/index.js.map +1 -0
- package/lib/packlets/experimental/rangeOf.d.ts.map +1 -0
- package/lib/packlets/experimental/rangeOf.js.map +1 -0
- package/lib/packlets/hash/index.browser.d.ts.map +1 -0
- package/lib/packlets/hash/index.browser.js.map +1 -0
- package/lib/packlets/hash/index.d.ts.map +1 -0
- package/lib/packlets/hash/index.js.map +1 -0
- package/lib/packlets/hash/index.node.d.ts.map +1 -0
- package/lib/packlets/hash/index.node.js.map +1 -0
- package/lib/packlets/hash/md5Normalizer.browser.d.ts.map +1 -0
- package/lib/packlets/hash/md5Normalizer.browser.js.map +1 -0
- package/lib/packlets/hash/md5Normalizer.d.ts.map +1 -0
- package/lib/packlets/hash/md5Normalizer.js.map +1 -0
- package/lib/packlets/mustache/index.d.ts +1 -1
- package/lib/packlets/mustache/index.d.ts.map +1 -0
- package/lib/packlets/mustache/index.js.map +1 -0
- package/lib/packlets/mustache/interfaces.d.ts +34 -0
- package/lib/packlets/mustache/interfaces.d.ts.map +1 -0
- package/lib/packlets/mustache/interfaces.js.map +1 -0
- package/lib/packlets/mustache/mustacheTemplate.d.ts +2 -0
- package/lib/packlets/mustache/mustacheTemplate.d.ts.map +1 -0
- package/lib/packlets/mustache/mustacheTemplate.js +42 -4
- package/lib/packlets/mustache/mustacheTemplate.js.map +1 -0
- package/lib/packlets/record-jar/index.browser.d.ts +0 -1
- package/lib/packlets/record-jar/index.browser.d.ts.map +1 -0
- package/lib/packlets/record-jar/index.browser.js +1 -5
- package/lib/packlets/record-jar/index.browser.js.map +1 -0
- package/lib/packlets/record-jar/index.d.ts.map +1 -0
- package/lib/packlets/record-jar/index.js.map +1 -0
- package/lib/packlets/record-jar/recordJarFileHelpers.d.ts +0 -11
- package/lib/packlets/record-jar/recordJarFileHelpers.d.ts.map +1 -0
- package/lib/packlets/record-jar/recordJarFileHelpers.js +0 -19
- package/lib/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
- package/lib/packlets/record-jar/recordJarHelpers.d.ts +11 -0
- package/lib/packlets/record-jar/recordJarHelpers.d.ts.map +1 -0
- package/lib/packlets/record-jar/recordJarHelpers.js +19 -0
- package/lib/packlets/record-jar/recordJarHelpers.js.map +1 -0
- package/lib/packlets/yaml/converters.d.ts.map +1 -0
- package/lib/packlets/yaml/converters.js.map +1 -0
- package/lib/packlets/yaml/index.d.ts +1 -0
- package/lib/packlets/yaml/index.d.ts.map +1 -0
- package/lib/packlets/yaml/index.js +1 -0
- package/lib/packlets/yaml/index.js.map +1 -0
- package/lib/packlets/yaml/serializers.d.ts +45 -0
- package/lib/packlets/yaml/serializers.d.ts.map +1 -0
- package/lib/packlets/yaml/serializers.js +84 -0
- package/lib/packlets/yaml/serializers.js.map +1 -0
- package/lib/packlets/zip-file-tree/index.d.ts.map +1 -0
- package/lib/packlets/zip-file-tree/index.js.map +1 -0
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts +2 -2
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts.map +1 -0
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js +2 -2
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts.map +1 -0
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
- package/package.json +20 -15
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// Copyright (c) 2026 Erik Fortune
|
|
2
|
+
//
|
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
// in the Software without restriction, including without limitation the rights
|
|
6
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
// furnished to do so, subject to the following conditions:
|
|
9
|
+
//
|
|
10
|
+
// The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
// copies or substantial portions of the Software.
|
|
12
|
+
//
|
|
13
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
// SOFTWARE.
|
|
20
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
21
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
22
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
23
|
+
var m = o[Symbol.asyncIterator], i;
|
|
24
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
25
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
26
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
27
|
+
};
|
|
28
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
29
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
30
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
31
|
+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
32
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
33
|
+
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
34
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
35
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
36
|
+
function fulfill(value) { resume("next", value); }
|
|
37
|
+
function reject(value) { resume("throw", value); }
|
|
38
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Streaming adapter for OpenAI Chat Completions (also used for Groq, Mistral,
|
|
42
|
+
* and other Chat-Completions-compatible providers when no tools are
|
|
43
|
+
* requested).
|
|
44
|
+
*
|
|
45
|
+
* @packageDocumentation
|
|
46
|
+
*/
|
|
47
|
+
import { succeed, Validators } from '@fgv/ts-utils';
|
|
48
|
+
import { buildMessages, buildOpenAiChatUserContent } from '../chatRequestBuilders';
|
|
49
|
+
import { bearerAuthHeader } from '../endpoint';
|
|
50
|
+
import { parseSseEventJson, readSseEvents } from '../sseParser';
|
|
51
|
+
import { openSseConnection, validateEventPayload } from './common';
|
|
52
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
53
|
+
const stringOrNull = Validators.isA('string-or-null',
|
|
54
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
55
|
+
(v) => typeof v === 'string' || v === null);
|
|
56
|
+
const openAiChatStreamChoice = Validators.object({
|
|
57
|
+
delta: Validators.object({ content: Validators.string }, { options: { optionalFields: ['content'] } }).optional(),
|
|
58
|
+
finish_reason: stringOrNull.optional()
|
|
59
|
+
}, { options: { optionalFields: ['delta', 'finish_reason'] } });
|
|
60
|
+
const openAiChatStreamChunk = Validators.object({
|
|
61
|
+
choices: Validators.arrayOf(openAiChatStreamChoice)
|
|
62
|
+
});
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Stream translator
|
|
65
|
+
// ============================================================================
|
|
66
|
+
/**
|
|
67
|
+
* Translates an OpenAI Chat Completions SSE stream into unified events.
|
|
68
|
+
*
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
function translateOpenAiChatStream(response) {
|
|
72
|
+
return __asyncGenerator(this, arguments, function* translateOpenAiChatStream_1() {
|
|
73
|
+
var _a, e_1, _b, _c;
|
|
74
|
+
var _d;
|
|
75
|
+
let fullText = '';
|
|
76
|
+
let truncated = false;
|
|
77
|
+
let receivedDone = false;
|
|
78
|
+
try {
|
|
79
|
+
/* c8 ignore next - body is non-null at this point per openSseConnection */
|
|
80
|
+
if (!response.body)
|
|
81
|
+
return yield __await(void 0);
|
|
82
|
+
try {
|
|
83
|
+
for (var _e = true, _f = __asyncValues(readSseEvents(response.body)), _g; _g = yield __await(_f.next()), _a = _g.done, !_a; _e = true) {
|
|
84
|
+
_c = _g.value;
|
|
85
|
+
_e = false;
|
|
86
|
+
const message = _c;
|
|
87
|
+
const json = parseSseEventJson(message.data);
|
|
88
|
+
if (json === undefined) {
|
|
89
|
+
// [DONE] sentinel or unparseable; skip
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const chunk = validateEventPayload(json, openAiChatStreamChunk);
|
|
93
|
+
/* c8 ignore next 1 - defensive: chunk?.choices optional chain unreachable after validation */
|
|
94
|
+
const choice = chunk === null || chunk === void 0 ? void 0 : chunk.choices[0];
|
|
95
|
+
/* c8 ignore next 3 - defensive: SSE events without choices are skipped */
|
|
96
|
+
if (!choice) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
/* c8 ignore next 1 - defensive: choice.delta?.content optional chain unreachable after validation */
|
|
100
|
+
const delta = (_d = choice.delta) === null || _d === void 0 ? void 0 : _d.content;
|
|
101
|
+
if (typeof delta === 'string' && delta.length > 0) {
|
|
102
|
+
fullText += delta;
|
|
103
|
+
yield yield __await({ type: 'text-delta', delta });
|
|
104
|
+
}
|
|
105
|
+
const finish = choice.finish_reason;
|
|
106
|
+
if (typeof finish === 'string' && finish.length > 0) {
|
|
107
|
+
truncated = finish === 'length';
|
|
108
|
+
receivedDone = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
113
|
+
finally {
|
|
114
|
+
try {
|
|
115
|
+
if (!_e && !_a && (_b = _f.return)) yield __await(_b.call(_f));
|
|
116
|
+
}
|
|
117
|
+
finally { if (e_1) throw e_1.error; }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (err) /* c8 ignore start - defensive: stream errors are always Error instances */ {
|
|
121
|
+
yield yield __await({ type: 'error', message: err instanceof Error ? err.message : String(err) });
|
|
122
|
+
return yield __await(void 0);
|
|
123
|
+
} /* c8 ignore stop */
|
|
124
|
+
if (receivedDone) {
|
|
125
|
+
yield yield __await({ type: 'done', truncated, fullText });
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
yield yield __await({ type: 'error', message: 'OpenAI stream ended without a finish_reason' });
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// Per-format request caller
|
|
134
|
+
// ============================================================================
|
|
135
|
+
/**
|
|
136
|
+
* Issues a streaming Chat Completions request and returns the unified-event
|
|
137
|
+
* iterable on success.
|
|
138
|
+
*
|
|
139
|
+
* @internal
|
|
140
|
+
*/
|
|
141
|
+
export async function callOpenAiChatStream(config, prompt, messagesBefore, temperature, logger, signal, resolvedThinking) {
|
|
142
|
+
var _a;
|
|
143
|
+
const url = `${config.baseUrl}/chat/completions`;
|
|
144
|
+
const messages = buildMessages(prompt.system, buildOpenAiChatUserContent(prompt), {
|
|
145
|
+
head: messagesBefore
|
|
146
|
+
});
|
|
147
|
+
const effort = (_a = resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.openAiEffort) !== null && _a !== void 0 ? _a : resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.xaiEffort;
|
|
148
|
+
const supportsReasoning = config.model !== 'grok-4';
|
|
149
|
+
const body = { model: config.model, messages, stream: true };
|
|
150
|
+
if (effort !== undefined && supportsReasoning) {
|
|
151
|
+
body.reasoning_effort = effort;
|
|
152
|
+
}
|
|
153
|
+
// Temperature is sent only when the caller explicitly provided one; omitting it lets the
|
|
154
|
+
// provider apply its own default (current-gen models reject a caller-supplied default). This
|
|
155
|
+
// adapter is reached only via the conflict-guarded streaming entry point — the client-tool path
|
|
156
|
+
// routes OpenAI through the Responses adapter, not chat — so, like callOpenAiCompletion, no
|
|
157
|
+
// effort gate is needed: temperature is present here only when the effort is undefined/'none'.
|
|
158
|
+
if (temperature !== undefined) {
|
|
159
|
+
body.temperature = temperature;
|
|
160
|
+
}
|
|
161
|
+
if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
|
|
162
|
+
Object.assign(body, resolvedThinking.otherParams);
|
|
163
|
+
}
|
|
164
|
+
const headers = bearerAuthHeader(config.apiKey);
|
|
165
|
+
/* c8 ignore next 1 - optional logger */
|
|
166
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`OpenAI streaming completion: model=${config.model}`);
|
|
167
|
+
const conn = await openSseConnection(url, headers, body, logger, signal);
|
|
168
|
+
return conn.onSuccess((response) => succeed(translateOpenAiChatStream(response)));
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=openaiChat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openaiChat.js","sourceRoot":"","sources":["../../../../src/packlets/ai-assist/streamingAdapters/openaiChat.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Streaming adapter for OpenAI Chat Completions (also used for Groq, Mistral,\n * and other Chat-Completions-compatible providers when no tools are\n * requested).\n *\n * @packageDocumentation\n */\n\nimport { type Logging, Result, succeed, type Validator, Validators } from '@fgv/ts-utils';\n\nimport { buildMessages, buildOpenAiChatUserContent } from '../chatRequestBuilders';\nimport { bearerAuthHeader } from '../endpoint';\nimport { AiPrompt, type IAiStreamEvent, type IChatMessage } from '../model';\nimport { parseSseEventJson, readSseEvents } from '../sseParser';\nimport { type IResolvedThinkingConfig } from '../thinkingOptionsResolver';\nimport { IStreamApiConfig, openSseConnection, validateEventPayload } from './common';\n\n// ============================================================================\n// Event payload shapes\n// ============================================================================\n\n/**\n * The shape of `choices[0]` in an OpenAI Chat Completions streaming chunk.\n * Both `delta.content` and `finish_reason` are optional — content arrives in\n * intermediate chunks, finish_reason in the terminal chunk. The wire sends\n * `finish_reason: null` (literal null, not absent) on intermediate chunks,\n * so the validator must accept null alongside string.\n *\n * @internal\n */\ninterface IOpenAiChatStreamChoice {\n readonly delta?: { readonly content?: string };\n // eslint-disable-next-line @rushstack/no-new-null\n readonly finish_reason?: string | null;\n}\n\n/**\n * One streaming chunk from the OpenAI Chat Completions endpoint. Always has\n * a `choices` array with one element in the streaming mode.\n *\n * @internal\n */\ninterface IOpenAiChatStreamChunk {\n readonly choices: ReadonlyArray<IOpenAiChatStreamChoice>;\n}\n\n// eslint-disable-next-line @rushstack/no-new-null\nconst stringOrNull: Validator<string | null> = Validators.isA<string | null>(\n 'string-or-null',\n // eslint-disable-next-line @rushstack/no-new-null\n (v: unknown): v is string | null => typeof v === 'string' || v === null\n);\n\nconst openAiChatStreamChoice: Validator<IOpenAiChatStreamChoice> = Validators.object<IOpenAiChatStreamChoice>(\n {\n delta: Validators.object<{ content?: string }>(\n { content: Validators.string },\n { options: { optionalFields: ['content'] } }\n ).optional(),\n finish_reason: stringOrNull.optional()\n },\n { options: { optionalFields: ['delta', 'finish_reason'] } }\n);\n\nconst openAiChatStreamChunk: Validator<IOpenAiChatStreamChunk> = Validators.object<IOpenAiChatStreamChunk>({\n choices: Validators.arrayOf(openAiChatStreamChoice)\n});\n\n// ============================================================================\n// Stream translator\n// ============================================================================\n\n/**\n * Translates an OpenAI Chat Completions SSE stream into unified events.\n *\n * @internal\n */\nasync function* translateOpenAiChatStream(response: Response): AsyncGenerator<IAiStreamEvent> {\n let fullText = '';\n let truncated = false;\n let receivedDone = false;\n\n try {\n /* c8 ignore next - body is non-null at this point per openSseConnection */\n if (!response.body) return;\n for await (const message of readSseEvents(response.body)) {\n const json = parseSseEventJson(message.data);\n if (json === undefined) {\n // [DONE] sentinel or unparseable; skip\n continue;\n }\n const chunk = validateEventPayload(json, openAiChatStreamChunk);\n /* c8 ignore next 1 - defensive: chunk?.choices optional chain unreachable after validation */\n const choice = chunk?.choices[0];\n /* c8 ignore next 3 - defensive: SSE events without choices are skipped */\n if (!choice) {\n continue;\n }\n /* c8 ignore next 1 - defensive: choice.delta?.content optional chain unreachable after validation */\n const delta = choice.delta?.content;\n if (typeof delta === 'string' && delta.length > 0) {\n fullText += delta;\n yield { type: 'text-delta', delta };\n }\n const finish = choice.finish_reason;\n if (typeof finish === 'string' && finish.length > 0) {\n truncated = finish === 'length';\n receivedDone = true;\n }\n }\n } catch (err: unknown) /* c8 ignore start - defensive: stream errors are always Error instances */ {\n yield { type: 'error', message: err instanceof Error ? err.message : String(err) };\n return;\n } /* c8 ignore stop */\n\n if (receivedDone) {\n yield { type: 'done', truncated, fullText };\n } else {\n yield { type: 'error', message: 'OpenAI stream ended without a finish_reason' };\n }\n}\n\n// ============================================================================\n// Per-format request caller\n// ============================================================================\n\n/**\n * Issues a streaming Chat Completions request and returns the unified-event\n * iterable on success.\n *\n * @internal\n */\nexport async function callOpenAiChatStream(\n config: IStreamApiConfig,\n prompt: AiPrompt,\n messagesBefore: ReadonlyArray<IChatMessage> | undefined,\n temperature: number | undefined,\n logger?: Logging.ILogger,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig\n): Promise<Result<AsyncIterable<IAiStreamEvent>>> {\n const url = `${config.baseUrl}/chat/completions`;\n const messages = buildMessages(prompt.system, buildOpenAiChatUserContent(prompt), {\n head: messagesBefore\n });\n const effort = resolvedThinking?.openAiEffort ?? resolvedThinking?.xaiEffort;\n const supportsReasoning = config.model !== 'grok-4';\n const body: Record<string, unknown> = { model: config.model, messages, stream: true };\n if (effort !== undefined && supportsReasoning) {\n body.reasoning_effort = effort;\n }\n // Temperature is sent only when the caller explicitly provided one; omitting it lets the\n // provider apply its own default (current-gen models reject a caller-supplied default). This\n // adapter is reached only via the conflict-guarded streaming entry point — the client-tool path\n // routes OpenAI through the Responses adapter, not chat — so, like callOpenAiCompletion, no\n // effort gate is needed: temperature is present here only when the effort is undefined/'none'.\n if (temperature !== undefined) {\n body.temperature = temperature;\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n const headers: Record<string, string> = bearerAuthHeader(config.apiKey);\n /* c8 ignore next 1 - optional logger */\n logger?.info(`OpenAI streaming completion: model=${config.model}`);\n const conn = await openSseConnection(url, headers, body, logger, signal);\n return conn.onSuccess((response) => succeed(translateOpenAiChatStream(response)));\n}\n"]}
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
// Copyright (c) 2026 Erik Fortune
|
|
2
|
+
//
|
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
// in the Software without restriction, including without limitation the rights
|
|
6
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
// furnished to do so, subject to the following conditions:
|
|
9
|
+
//
|
|
10
|
+
// The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
// copies or substantial portions of the Software.
|
|
12
|
+
//
|
|
13
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
// SOFTWARE.
|
|
20
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
21
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
22
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
23
|
+
var m = o[Symbol.asyncIterator], i;
|
|
24
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
25
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
26
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
27
|
+
};
|
|
28
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
29
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
30
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
31
|
+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
32
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
33
|
+
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
34
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
35
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
36
|
+
function fulfill(value) { resume("next", value); }
|
|
37
|
+
function reject(value) { resume("throw", value); }
|
|
38
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Streaming adapter for the OpenAI / xAI Responses API. This is the format
|
|
42
|
+
* used when server-side tools (e.g. web_search) are requested — Chat
|
|
43
|
+
* Completions doesn't support tool progress events, but the Responses API
|
|
44
|
+
* does.
|
|
45
|
+
*
|
|
46
|
+
* Client-defined tools (`function_call` type) are accumulated per call ID
|
|
47
|
+
* and emitted as `client-tool-call-done` events when complete.
|
|
48
|
+
*
|
|
49
|
+
* @packageDocumentation
|
|
50
|
+
*/
|
|
51
|
+
import { succeed, Validators } from '@fgv/ts-utils';
|
|
52
|
+
import { buildMessages, buildOpenAiResponsesUserContent } from '../chatRequestBuilders';
|
|
53
|
+
import { bearerAuthHeader } from '../endpoint';
|
|
54
|
+
import { parseSseEventJson, readSseEvents } from '../sseParser';
|
|
55
|
+
import { toResponsesApiTools } from '../toolFormats';
|
|
56
|
+
import { UNRECOGNIZED_EVENT_WARN_TAG, formatUnrecognizedEventPayloadPreview, openSseConnection, validateEventPayload } from './common';
|
|
57
|
+
const responsesDeltaPayload = Validators.object({
|
|
58
|
+
delta: Validators.string
|
|
59
|
+
});
|
|
60
|
+
const responsesOutputItemInner = Validators.object({
|
|
61
|
+
type: Validators.string.optional(),
|
|
62
|
+
id: Validators.string.optional(),
|
|
63
|
+
name: Validators.string.optional(),
|
|
64
|
+
call_id: Validators.string.optional()
|
|
65
|
+
}, { options: { optionalFields: ['type', 'id', 'name', 'call_id'] } });
|
|
66
|
+
const responsesOutputItemAddedPayload = Validators.object({ item: responsesOutputItemInner });
|
|
67
|
+
const responsesFunctionCallArgsDeltaPayload = Validators.object({
|
|
68
|
+
item_id: Validators.string,
|
|
69
|
+
delta: Validators.string
|
|
70
|
+
});
|
|
71
|
+
const responsesFunctionCallArgsDonePayload = Validators.object({
|
|
72
|
+
item_id: Validators.string,
|
|
73
|
+
arguments: Validators.string
|
|
74
|
+
});
|
|
75
|
+
const responsesIncompleteDetails = Validators.object({ reason: Validators.string.optional() }, { options: { optionalFields: ['reason'] } });
|
|
76
|
+
const responsesCompletedPayload = Validators.object({
|
|
77
|
+
response: Validators.object({
|
|
78
|
+
status: Validators.string.optional(),
|
|
79
|
+
incomplete_details: responsesIncompleteDetails.optional()
|
|
80
|
+
}, { options: { optionalFields: ['status', 'incomplete_details'] } })
|
|
81
|
+
});
|
|
82
|
+
const responsesErrorInner = Validators.object({ message: Validators.string.optional() }, { options: { optionalFields: ['message'] } });
|
|
83
|
+
const responsesErrorPayload = Validators.object({
|
|
84
|
+
error: responsesErrorInner.optional(),
|
|
85
|
+
message: Validators.string.optional()
|
|
86
|
+
}, { options: { optionalFields: ['error', 'message'] } });
|
|
87
|
+
// ============================================================================
|
|
88
|
+
// Stream translator
|
|
89
|
+
// ============================================================================
|
|
90
|
+
/**
|
|
91
|
+
* Recognized OpenAI / xAI Responses API SSE event names. An event in this set is either
|
|
92
|
+
* handled below or intentionally ignored (lifecycle / reasoning content discarded by design /
|
|
93
|
+
* server-tool channels not yet surfaced). Any event whose name is NOT in this set surfaces
|
|
94
|
+
* a one-time `logger.warn` per stream — making provider drift (new event types from a model
|
|
95
|
+
* update) visible empirically instead of silently no-op'd.
|
|
96
|
+
*
|
|
97
|
+
* Source: official `openai-node` SDK source (`src/resources/responses/responses.ts`)
|
|
98
|
+
* event-type literal-string sweep, plus the xAI Responses superset. Add to this set when a
|
|
99
|
+
* new event type is observed and confirmed safe to ignore.
|
|
100
|
+
*
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
const RECOGNIZED_OPENAI_RESPONSES_EVENTS = new Set([
|
|
104
|
+
// ---- handled by the translator ----
|
|
105
|
+
'response.output_text.delta',
|
|
106
|
+
'response.web_search_call.in_progress',
|
|
107
|
+
'response.web_search_call.completed',
|
|
108
|
+
'response.output_item.added',
|
|
109
|
+
'response.function_call_arguments.delta',
|
|
110
|
+
'response.function_call_arguments.done',
|
|
111
|
+
'response.completed',
|
|
112
|
+
'response.failed',
|
|
113
|
+
'error',
|
|
114
|
+
// ---- lifecycle events: intentionally silent ----
|
|
115
|
+
'response.created',
|
|
116
|
+
'response.in_progress',
|
|
117
|
+
'response.queued',
|
|
118
|
+
'response.incomplete',
|
|
119
|
+
// ---- text content lifecycle: handled implicitly via delta accumulation ----
|
|
120
|
+
'response.output_text.done',
|
|
121
|
+
'response.output_text.annotation.added',
|
|
122
|
+
'response.content_part.added',
|
|
123
|
+
'response.content_part.done',
|
|
124
|
+
'response.output_item.done',
|
|
125
|
+
// ---- reasoning content: discarded by design (see ai-assist-thinking-events follow-on) ----
|
|
126
|
+
'response.reasoning_summary_part.added',
|
|
127
|
+
'response.reasoning_summary_part.done',
|
|
128
|
+
'response.reasoning_summary_text.delta',
|
|
129
|
+
'response.reasoning_summary_text.done',
|
|
130
|
+
'response.reasoning_text.delta',
|
|
131
|
+
'response.reasoning_text.done',
|
|
132
|
+
// ---- refusals: caller currently sees these via the model's final text ----
|
|
133
|
+
'response.refusal.delta',
|
|
134
|
+
'response.refusal.done',
|
|
135
|
+
// ---- server-tool channels not surfaced as tool-event yet ----
|
|
136
|
+
'response.web_search_call.searching',
|
|
137
|
+
'response.file_search_call.in_progress',
|
|
138
|
+
'response.file_search_call.searching',
|
|
139
|
+
'response.file_search_call.completed',
|
|
140
|
+
'response.code_interpreter_call.in_progress',
|
|
141
|
+
'response.code_interpreter_call.interpreting',
|
|
142
|
+
'response.code_interpreter_call.completed',
|
|
143
|
+
'response.code_interpreter_call_code.delta',
|
|
144
|
+
'response.code_interpreter_call_code.done',
|
|
145
|
+
'response.image_generation_call.in_progress',
|
|
146
|
+
'response.image_generation_call.generating',
|
|
147
|
+
'response.image_generation_call.completed',
|
|
148
|
+
'response.image_generation_call.partial_image',
|
|
149
|
+
'response.mcp_call.in_progress',
|
|
150
|
+
'response.mcp_call.completed',
|
|
151
|
+
'response.mcp_call.failed',
|
|
152
|
+
'response.mcp_call_arguments.delta',
|
|
153
|
+
'response.mcp_call_arguments.done',
|
|
154
|
+
'response.mcp_list_tools.in_progress',
|
|
155
|
+
'response.mcp_list_tools.completed',
|
|
156
|
+
'response.mcp_list_tools.failed',
|
|
157
|
+
'response.custom_tool_call_input.delta',
|
|
158
|
+
'response.custom_tool_call_input.done',
|
|
159
|
+
// ---- audio (not used in chat/tool flows here) ----
|
|
160
|
+
'response.audio.delta',
|
|
161
|
+
'response.audio.done',
|
|
162
|
+
'response.audio.transcript.delta',
|
|
163
|
+
'response.audio.transcript.done'
|
|
164
|
+
]);
|
|
165
|
+
/**
|
|
166
|
+
* Translates an OpenAI Responses API SSE stream into unified events.
|
|
167
|
+
*
|
|
168
|
+
* Maintains a per-call-ID accumulation map for client-defined function calls.
|
|
169
|
+
* The map is exposed via the passed-in `functionCallMap` parameter for the
|
|
170
|
+
* C3 continuation builder to read after the stream completes.
|
|
171
|
+
*
|
|
172
|
+
* Unrecognized event names are reported once per stream via `logger?.warn` —
|
|
173
|
+
* see {@link RECOGNIZED_OPENAI_RESPONSES_EVENTS}.
|
|
174
|
+
*
|
|
175
|
+
* @internal
|
|
176
|
+
*/
|
|
177
|
+
function translateOpenAiResponsesStream(response, functionCallMap, logger) {
|
|
178
|
+
return __asyncGenerator(this, arguments, function* translateOpenAiResponsesStream_1() {
|
|
179
|
+
var _a, e_1, _b, _c;
|
|
180
|
+
var _d, _e, _f, _g, _h;
|
|
181
|
+
let fullText = '';
|
|
182
|
+
let truncated = false;
|
|
183
|
+
let completed = false;
|
|
184
|
+
let incompleteReason;
|
|
185
|
+
// OpenAI / xAI Responses API emits function_call_arguments.{delta,done} events keyed by
|
|
186
|
+
// `item_id` (the fc_* output-item id). The harness and continuation builder key by
|
|
187
|
+
// `call_id` (the call_* id). This map correlates the two — populated when the
|
|
188
|
+
// function_call item is announced in `response.output_item.added`.
|
|
189
|
+
const itemIdToCallId = new Map();
|
|
190
|
+
// Track unrecognized event names we have already warned about, so a hot stream of
|
|
191
|
+
// an unknown event type produces exactly one log line per name per stream.
|
|
192
|
+
const warnedEvents = new Set();
|
|
193
|
+
try {
|
|
194
|
+
/* c8 ignore next - body is non-null at this point per openSseConnection */
|
|
195
|
+
if (!response.body)
|
|
196
|
+
return yield __await(void 0);
|
|
197
|
+
try {
|
|
198
|
+
for (var _j = true, _k = __asyncValues(readSseEvents(response.body)), _l; _l = yield __await(_k.next()), _a = _l.done, !_a; _j = true) {
|
|
199
|
+
_c = _l.value;
|
|
200
|
+
_j = false;
|
|
201
|
+
const message = _c;
|
|
202
|
+
const eventName = message.event;
|
|
203
|
+
if (eventName === 'response.output_text.delta') {
|
|
204
|
+
const payload = validateEventPayload(parseSseEventJson(message.data), responsesDeltaPayload);
|
|
205
|
+
/* c8 ignore next 1 - defensive: payload?.delta null branch unreachable after validation */
|
|
206
|
+
const delta = payload === null || payload === void 0 ? void 0 : payload.delta;
|
|
207
|
+
if (typeof delta === 'string' && delta.length > 0) {
|
|
208
|
+
fullText += delta;
|
|
209
|
+
yield yield __await({ type: 'text-delta', delta });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else if (eventName === 'response.web_search_call.in_progress') {
|
|
213
|
+
yield yield __await({ type: 'tool-event', toolType: 'web_search', phase: 'started' });
|
|
214
|
+
}
|
|
215
|
+
else if (eventName === 'response.web_search_call.completed') {
|
|
216
|
+
yield yield __await({ type: 'tool-event', toolType: 'web_search', phase: 'completed' });
|
|
217
|
+
}
|
|
218
|
+
else if (eventName === 'response.output_item.added') {
|
|
219
|
+
const payload = validateEventPayload(parseSseEventJson(message.data), responsesOutputItemAddedPayload);
|
|
220
|
+
/* c8 ignore next 1 - defensive: payload null branch unreachable after validation */
|
|
221
|
+
const item = payload === null || payload === void 0 ? void 0 : payload.item;
|
|
222
|
+
/* c8 ignore next 1 - defensive: falsy call_id/name branches are protocol violations */
|
|
223
|
+
if ((item === null || item === void 0 ? void 0 : item.type) === 'function_call' && item.call_id && item.name) {
|
|
224
|
+
functionCallMap.set(item.call_id, { id: item.call_id, name: item.name, argsBuffer: '' });
|
|
225
|
+
// Reasoning models (and the standard flow) reference this function_call in subsequent
|
|
226
|
+
// arguments.{delta,done} events by `item_id`, never by `call_id`. Record the mapping
|
|
227
|
+
// so the arg-accumulation handlers can resolve the call.
|
|
228
|
+
if (item.id) {
|
|
229
|
+
itemIdToCallId.set(item.id, item.call_id);
|
|
230
|
+
}
|
|
231
|
+
yield yield __await({ type: 'client-tool-call-start', toolName: item.name, callId: item.call_id });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else if (eventName === 'response.function_call_arguments.delta') {
|
|
235
|
+
const payload = validateEventPayload(parseSseEventJson(message.data), responsesFunctionCallArgsDeltaPayload);
|
|
236
|
+
/* c8 ignore next 1 - defensive: payload null branch unreachable after validation */
|
|
237
|
+
const itemId = payload === null || payload === void 0 ? void 0 : payload.item_id;
|
|
238
|
+
if (itemId !== undefined) {
|
|
239
|
+
const callId = itemIdToCallId.get(itemId);
|
|
240
|
+
/* c8 ignore next 1 - defensive: orphan delta (no preceding output_item.added) is a protocol violation */
|
|
241
|
+
const call = callId !== undefined ? functionCallMap.get(callId) : undefined;
|
|
242
|
+
/* c8 ignore next 1 - defensive: call always present and delta always string in valid stream */
|
|
243
|
+
if (call && typeof (payload === null || payload === void 0 ? void 0 : payload.delta) === 'string') {
|
|
244
|
+
call.argsBuffer += payload.delta;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else if (eventName === 'response.function_call_arguments.done') {
|
|
249
|
+
const payload = validateEventPayload(parseSseEventJson(message.data), responsesFunctionCallArgsDonePayload);
|
|
250
|
+
/* c8 ignore next 1 - defensive: payload null branch unreachable after validation */
|
|
251
|
+
const itemId = payload === null || payload === void 0 ? void 0 : payload.item_id;
|
|
252
|
+
if (itemId !== undefined) {
|
|
253
|
+
const callId = itemIdToCallId.get(itemId);
|
|
254
|
+
/* c8 ignore next 1 - defensive: orphan done (no preceding output_item.added) is a protocol violation */
|
|
255
|
+
const call = callId !== undefined ? functionCallMap.get(callId) : undefined;
|
|
256
|
+
if (call && callId !== undefined) {
|
|
257
|
+
/* c8 ignore next 1 - defensive: payload?.arguments null branch unreachable after validation */
|
|
258
|
+
const canonicalArgs = (_d = payload === null || payload === void 0 ? void 0 : payload.arguments) !== null && _d !== void 0 ? _d : '{}';
|
|
259
|
+
// Sync the accumulation entry with the canonical arguments from the .done event.
|
|
260
|
+
// Delta events may carry partial/empty payloads; the .done event carries the
|
|
261
|
+
// authoritative final arguments string used by the continuation builder.
|
|
262
|
+
call.argsBuffer = canonicalArgs;
|
|
263
|
+
let args;
|
|
264
|
+
try {
|
|
265
|
+
const parsed = JSON.parse(canonicalArgs);
|
|
266
|
+
/* c8 ignore start - defensive: non-object/malformed parse defaults to empty object */
|
|
267
|
+
args =
|
|
268
|
+
parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
269
|
+
? parsed
|
|
270
|
+
: {};
|
|
271
|
+
}
|
|
272
|
+
catch (_m) {
|
|
273
|
+
args = {};
|
|
274
|
+
}
|
|
275
|
+
/* c8 ignore stop */
|
|
276
|
+
yield yield __await({ type: 'client-tool-call-done', toolName: call.name, callId, args });
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
else if (eventName === 'response.completed') {
|
|
281
|
+
const payload = validateEventPayload(parseSseEventJson(message.data), responsesCompletedPayload);
|
|
282
|
+
/* c8 ignore next 1 - defensive: payload null branch unreachable after validation */
|
|
283
|
+
if (payload) {
|
|
284
|
+
truncated = payload.response.status === 'incomplete';
|
|
285
|
+
// Per IAiStreamDone.incompleteReason's contract, the reason is meaningful only
|
|
286
|
+
// when the response was truncated. Move both fields together on every completed
|
|
287
|
+
// event so a stray incomplete_details on a non-incomplete payload never leaks
|
|
288
|
+
// through, and a later (defensive) completed event can't leave a stale reason.
|
|
289
|
+
incompleteReason = truncated ? (_e = payload.response.incomplete_details) === null || _e === void 0 ? void 0 : _e.reason : undefined;
|
|
290
|
+
}
|
|
291
|
+
completed = true;
|
|
292
|
+
/* c8 ignore next 1 - defensive: eventName === 'error' alternative not exercised in tests */
|
|
293
|
+
}
|
|
294
|
+
else if (eventName === 'response.failed' || eventName === 'error') {
|
|
295
|
+
const payload = validateEventPayload(parseSseEventJson(message.data), responsesErrorPayload);
|
|
296
|
+
/* c8 ignore next 1 - defensive: payload?.error and payload?.message null branches unreachable */
|
|
297
|
+
const errMsg = (_h = (_g = (_f = payload === null || payload === void 0 ? void 0 : payload.error) === null || _f === void 0 ? void 0 : _f.message) !== null && _g !== void 0 ? _g : payload === null || payload === void 0 ? void 0 : payload.message) !== null && _h !== void 0 ? _h : 'Responses API stream failed';
|
|
298
|
+
yield yield __await({ type: 'error', message: errMsg });
|
|
299
|
+
return yield __await(void 0);
|
|
300
|
+
}
|
|
301
|
+
else if (typeof eventName === 'string' &&
|
|
302
|
+
!RECOGNIZED_OPENAI_RESPONSES_EVENTS.has(eventName) &&
|
|
303
|
+
!warnedEvents.has(eventName)) {
|
|
304
|
+
// Empirical drift instrument: an unrecognized SSE event from the Responses API
|
|
305
|
+
// surfaces as a one-time warning per stream. If a provider adds a new event type
|
|
306
|
+
// (or changes an existing event's name), the warning fires the first time the
|
|
307
|
+
// event arrives. Update RECOGNIZED_OPENAI_RESPONSES_EVENTS once the new event is
|
|
308
|
+
// either handled or confirmed safe to ignore.
|
|
309
|
+
warnedEvents.add(eventName);
|
|
310
|
+
logger === null || logger === void 0 ? void 0 : logger.warn(`${UNRECOGNIZED_EVENT_WARN_TAG} OpenAI Responses adapter: unrecognized SSE event ` +
|
|
311
|
+
`'${eventName}'. ` +
|
|
312
|
+
`payload preview: ${formatUnrecognizedEventPayloadPreview(message.data)}. ` +
|
|
313
|
+
`This may indicate provider drift — if the new event carries data the adapter ` +
|
|
314
|
+
`should surface, add a handler; otherwise add the name to ` +
|
|
315
|
+
`RECOGNIZED_OPENAI_RESPONSES_EVENTS.`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
320
|
+
finally {
|
|
321
|
+
try {
|
|
322
|
+
if (!_j && !_a && (_b = _k.return)) yield __await(_b.call(_k));
|
|
323
|
+
}
|
|
324
|
+
finally { if (e_1) throw e_1.error; }
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
catch (err) /* c8 ignore start - defensive: stream errors are always Error instances */ {
|
|
328
|
+
yield yield __await({ type: 'error', message: err instanceof Error ? err.message : String(err) });
|
|
329
|
+
return yield __await(void 0);
|
|
330
|
+
} /* c8 ignore stop */
|
|
331
|
+
if (completed) {
|
|
332
|
+
yield yield __await({ type: 'done', truncated, fullText, incompleteReason });
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
yield yield __await({ type: 'error', message: 'Responses API stream ended without a completed event' });
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
// ============================================================================
|
|
340
|
+
// Per-format request caller
|
|
341
|
+
// ============================================================================
|
|
342
|
+
/**
|
|
343
|
+
* Issues a streaming Responses API request (with tools) and returns the
|
|
344
|
+
* unified-event iterable on success.
|
|
345
|
+
*
|
|
346
|
+
* @internal
|
|
347
|
+
*/
|
|
348
|
+
export async function callOpenAiResponsesStream(config, prompt, tools = [], messagesBefore, temperature, logger, signal, resolvedThinking, functionCallMap, continuationMessages) {
|
|
349
|
+
var _a;
|
|
350
|
+
const url = `${config.baseUrl}/responses`;
|
|
351
|
+
const input = buildMessages(prompt.system, buildOpenAiResponsesUserContent(prompt), {
|
|
352
|
+
head: messagesBefore,
|
|
353
|
+
rawTail: continuationMessages
|
|
354
|
+
});
|
|
355
|
+
const effort = (_a = resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.openAiEffort) !== null && _a !== void 0 ? _a : resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.xaiEffort;
|
|
356
|
+
const supportsReasoning = config.model !== 'grok-4';
|
|
357
|
+
const body = {
|
|
358
|
+
model: config.model,
|
|
359
|
+
input,
|
|
360
|
+
stream: true
|
|
361
|
+
};
|
|
362
|
+
// `tools` is omitted entirely when none are requested — a Responses-only model routed
|
|
363
|
+
// here for tier/model reasons (not tools) must not send an empty tools array.
|
|
364
|
+
if (tools.length > 0) {
|
|
365
|
+
body.tools = toResponsesApiTools(tools);
|
|
366
|
+
}
|
|
367
|
+
if (effort !== undefined && supportsReasoning) {
|
|
368
|
+
body.reasoning = { effort };
|
|
369
|
+
}
|
|
370
|
+
// Temperature is sent only when the caller explicitly provided one (see callOpenAiChatStream).
|
|
371
|
+
if (effort === undefined || effort === 'none') {
|
|
372
|
+
if (temperature !== undefined) {
|
|
373
|
+
body.temperature = temperature;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
|
|
377
|
+
Object.assign(body, resolvedThinking.otherParams);
|
|
378
|
+
}
|
|
379
|
+
const headers = bearerAuthHeader(config.apiKey);
|
|
380
|
+
/* c8 ignore next 3 - optional logger */
|
|
381
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`OpenAI Responses streaming: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);
|
|
382
|
+
const callMap = functionCallMap !== null && functionCallMap !== void 0 ? functionCallMap : new Map();
|
|
383
|
+
const conn = await openSseConnection(url, headers, body, logger, signal);
|
|
384
|
+
return conn.onSuccess((response) => succeed(translateOpenAiResponsesStream(response, callMap, logger)));
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=openaiResponses.js.map
|