@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,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2026 Erik Fortune
|
|
3
|
+
//
|
|
4
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
// in the Software without restriction, including without limitation the rights
|
|
7
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
// furnished to do so, subject to the following conditions:
|
|
10
|
+
//
|
|
11
|
+
// The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
// copies or substantial portions of the Software.
|
|
13
|
+
//
|
|
14
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
// SOFTWARE.
|
|
21
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
22
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
23
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
24
|
+
var m = o[Symbol.asyncIterator], i;
|
|
25
|
+
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);
|
|
26
|
+
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); }); }; }
|
|
27
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
28
|
+
};
|
|
29
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
30
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
31
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
32
|
+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
33
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
34
|
+
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]); } }
|
|
35
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
36
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
37
|
+
function fulfill(value) { resume("next", value); }
|
|
38
|
+
function reject(value) { resume("throw", value); }
|
|
39
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.callProxiedCompletionStream = callProxiedCompletionStream;
|
|
43
|
+
/**
|
|
44
|
+
* Streaming adapter for a caller-provided proxy server. Unlike the
|
|
45
|
+
* provider-specific adapters, the proxy speaks our own unified vocabulary
|
|
46
|
+
* directly: each `data:` line is a JSON-serialized {@link AiAssist.IAiStreamEvent},
|
|
47
|
+
* so this adapter only validates the event-type discriminator and forwards.
|
|
48
|
+
*
|
|
49
|
+
* @packageDocumentation
|
|
50
|
+
*/
|
|
51
|
+
const ts_utils_1 = require("@fgv/ts-utils");
|
|
52
|
+
const chatRequestBuilders_1 = require("../chatRequestBuilders");
|
|
53
|
+
const sseParser_1 = require("../sseParser");
|
|
54
|
+
const common_1 = require("./common");
|
|
55
|
+
const proxyEventTypes = ['text-delta', 'tool-event', 'done', 'error'];
|
|
56
|
+
const proxyEventEnvelope = ts_utils_1.Validators.object({
|
|
57
|
+
type: ts_utils_1.Validators.enumeratedValue(proxyEventTypes)
|
|
58
|
+
});
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// Stream translator
|
|
61
|
+
// ============================================================================
|
|
62
|
+
/**
|
|
63
|
+
* Translates a proxied SSE stream back into {@link AiAssist.IAiStreamEvent} objects.
|
|
64
|
+
* Validation is limited to the type discriminator; the proxy is contractually
|
|
65
|
+
* required to emit shape-correct unified events.
|
|
66
|
+
*
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
function translateProxyStream(response) {
|
|
70
|
+
return __asyncGenerator(this, arguments, function* translateProxyStream_1() {
|
|
71
|
+
var _a, e_1, _b, _c;
|
|
72
|
+
try {
|
|
73
|
+
/* c8 ignore next - body is non-null at this point per openSseConnection */
|
|
74
|
+
if (!response.body)
|
|
75
|
+
return yield __await(void 0);
|
|
76
|
+
try {
|
|
77
|
+
for (var _d = true, _e = __asyncValues((0, sseParser_1.readSseEvents)(response.body)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
|
|
78
|
+
_c = _f.value;
|
|
79
|
+
_d = false;
|
|
80
|
+
const message = _c;
|
|
81
|
+
const json = (0, sseParser_1.parseSseEventJson)(message.data);
|
|
82
|
+
/* c8 ignore next 3 - defensive: malformed SSE events skipped */
|
|
83
|
+
if (json === undefined) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const envelope = (0, common_1.validateEventPayload)(json, proxyEventEnvelope);
|
|
87
|
+
/* c8 ignore next 3 - defensive: SSE events without valid envelope skipped */
|
|
88
|
+
if (!envelope) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const event = json;
|
|
92
|
+
yield yield __await(event);
|
|
93
|
+
if (envelope.type === 'done' || envelope.type === 'error') {
|
|
94
|
+
return yield __await(void 0);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
99
|
+
finally {
|
|
100
|
+
try {
|
|
101
|
+
if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
|
|
102
|
+
}
|
|
103
|
+
finally { if (e_1) throw e_1.error; }
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (err) /* c8 ignore start - defensive: stream errors are always Error instances */ {
|
|
107
|
+
yield yield __await({ type: 'error', message: err instanceof Error ? err.message : String(err) });
|
|
108
|
+
} /* c8 ignore stop */
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// Public entry point
|
|
113
|
+
// ============================================================================
|
|
114
|
+
/**
|
|
115
|
+
* Calls the streaming chat endpoint on a proxy server instead of calling
|
|
116
|
+
* the provider directly from the browser.
|
|
117
|
+
*
|
|
118
|
+
* @remarks
|
|
119
|
+
* Proxy contract:
|
|
120
|
+
* - Endpoint: `POST ${proxyUrl}/api/ai/completion-stream`
|
|
121
|
+
* - Request body: same JSON as `/api/ai/completion` plus `"stream": true`
|
|
122
|
+
* - Response: `Content-Type: text/event-stream`; body is the unified
|
|
123
|
+
* {@link AiAssist.IAiStreamEvent} JSON-serialized one event per SSE `data:` line
|
|
124
|
+
* (no `event:` line needed since the type discriminator is in the JSON).
|
|
125
|
+
* - Error response (when the proxy can't even start): JSON `{error: string}`
|
|
126
|
+
* with a non-2xx status, surfaced as `proxy: ${error}`.
|
|
127
|
+
*
|
|
128
|
+
* The proxy server is responsible for opening the upstream SSE connection,
|
|
129
|
+
* translating provider-native events to the unified vocabulary, and
|
|
130
|
+
* forwarding events as they arrive (no buffering). The library does not
|
|
131
|
+
* ship a proxy implementation.
|
|
132
|
+
*
|
|
133
|
+
* @public
|
|
134
|
+
*/
|
|
135
|
+
async function callProxiedCompletionStream(proxyUrl, params) {
|
|
136
|
+
const { descriptor, apiKey, system, messages, temperature, modelOverride, logger, tools, signal, thinking } = params;
|
|
137
|
+
// Enforce the same unified-request invariants the direct entry points apply
|
|
138
|
+
// (non-empty messages, trailing user turn) so an invalid request fails fast
|
|
139
|
+
// here rather than diverging at the proxy.
|
|
140
|
+
const splitResult = (0, chatRequestBuilders_1.splitChatRequest)(system, messages);
|
|
141
|
+
if (splitResult.isFailure()) {
|
|
142
|
+
return (0, ts_utils_1.fail)(splitResult.message);
|
|
143
|
+
}
|
|
144
|
+
if (splitResult.value.prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {
|
|
145
|
+
return (0, ts_utils_1.fail)(`provider "${descriptor.id}" does not accept image input`);
|
|
146
|
+
}
|
|
147
|
+
const body = {
|
|
148
|
+
providerId: descriptor.id,
|
|
149
|
+
apiKey,
|
|
150
|
+
messages: (0, chatRequestBuilders_1.normalizeOutboundMessages)(splitResult.value),
|
|
151
|
+
stream: true
|
|
152
|
+
};
|
|
153
|
+
// Temperature is forwarded only when explicitly provided, matching the direct path — the proxy
|
|
154
|
+
// omits it from the upstream request so the provider default applies.
|
|
155
|
+
if (temperature !== undefined) {
|
|
156
|
+
body.temperature = temperature;
|
|
157
|
+
}
|
|
158
|
+
if (system !== undefined) {
|
|
159
|
+
body.system = system;
|
|
160
|
+
}
|
|
161
|
+
if (modelOverride !== undefined) {
|
|
162
|
+
body.modelOverride = modelOverride;
|
|
163
|
+
}
|
|
164
|
+
if (tools && tools.length > 0) {
|
|
165
|
+
body.tools = tools;
|
|
166
|
+
}
|
|
167
|
+
if (thinking !== undefined) {
|
|
168
|
+
body.thinking = thinking;
|
|
169
|
+
}
|
|
170
|
+
/* c8 ignore next 1 - optional logger */
|
|
171
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`AI streaming proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);
|
|
172
|
+
const url = `${proxyUrl}/api/ai/completion-stream`;
|
|
173
|
+
const conn = await (0, common_1.openSseConnection)(url, {}, body, logger, signal);
|
|
174
|
+
return conn.onSuccess((response) => (0, ts_utils_1.succeed)(translateProxyStream(response)));
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../../../src/packlets/ai-assist/streamingAdapters/proxy.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 a caller-provided proxy server. Unlike the\n * provider-specific adapters, the proxy speaks our own unified vocabulary\n * directly: each `data:` line is a JSON-serialized {@link AiAssist.IAiStreamEvent},\n * so this adapter only validates the event-type discriminator and forwards.\n *\n * @packageDocumentation\n */\n\nimport { fail, Result, succeed, type Validator, Validators } from '@fgv/ts-utils';\n\nimport { normalizeOutboundMessages, splitChatRequest } from '../chatRequestBuilders';\nimport { type IAiStreamEvent } from '../model';\nimport { parseSseEventJson, readSseEvents } from '../sseParser';\nimport { IProviderCompletionStreamParams, openSseConnection, validateEventPayload } from './common';\n\n// ============================================================================\n// Event payload shape — a tagged-event envelope\n// ============================================================================\n\ntype ProxyEventType = 'text-delta' | 'tool-event' | 'done' | 'error';\n\n/**\n * Minimal envelope used to identify and discriminate proxy events. Once the\n * `type` is recognized, the event is forwarded as-is — the unified shape is\n * the proxy contract, so there's no further per-type validation here.\n *\n * @internal\n */\ninterface IProxyEventEnvelope {\n readonly type: ProxyEventType;\n}\n\nconst proxyEventTypes: ReadonlyArray<ProxyEventType> = ['text-delta', 'tool-event', 'done', 'error'];\n\nconst proxyEventEnvelope: Validator<IProxyEventEnvelope> = Validators.object<IProxyEventEnvelope>({\n type: Validators.enumeratedValue<ProxyEventType>(proxyEventTypes)\n});\n\n// ============================================================================\n// Stream translator\n// ============================================================================\n\n/**\n * Translates a proxied SSE stream back into {@link AiAssist.IAiStreamEvent} objects.\n * Validation is limited to the type discriminator; the proxy is contractually\n * required to emit shape-correct unified events.\n *\n * @internal\n */\nasync function* translateProxyStream(response: Response): AsyncGenerator<IAiStreamEvent> {\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 /* c8 ignore next 3 - defensive: malformed SSE events skipped */\n if (json === undefined) {\n continue;\n }\n const envelope = validateEventPayload(json, proxyEventEnvelope);\n /* c8 ignore next 3 - defensive: SSE events without valid envelope skipped */\n if (!envelope) {\n continue;\n }\n const event = json as IAiStreamEvent;\n yield event;\n if (envelope.type === 'done' || envelope.type === 'error') {\n return;\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 } /* c8 ignore stop */\n}\n\n// ============================================================================\n// Public entry point\n// ============================================================================\n\n/**\n * Calls the streaming chat endpoint on a proxy server instead of calling\n * the provider directly from the browser.\n *\n * @remarks\n * Proxy contract:\n * - Endpoint: `POST ${proxyUrl}/api/ai/completion-stream`\n * - Request body: same JSON as `/api/ai/completion` plus `\"stream\": true`\n * - Response: `Content-Type: text/event-stream`; body is the unified\n * {@link AiAssist.IAiStreamEvent} JSON-serialized one event per SSE `data:` line\n * (no `event:` line needed since the type discriminator is in the JSON).\n * - Error response (when the proxy can't even start): JSON `{error: string}`\n * with a non-2xx status, surfaced as `proxy: ${error}`.\n *\n * The proxy server is responsible for opening the upstream SSE connection,\n * translating provider-native events to the unified vocabulary, and\n * forwarding events as they arrive (no buffering). The library does not\n * ship a proxy implementation.\n *\n * @public\n */\nexport async function callProxiedCompletionStream(\n proxyUrl: string,\n params: IProviderCompletionStreamParams\n): Promise<Result<AsyncIterable<IAiStreamEvent>>> {\n const {\n descriptor,\n apiKey,\n system,\n messages,\n temperature,\n modelOverride,\n logger,\n tools,\n signal,\n thinking\n } = params;\n\n // Enforce the same unified-request invariants the direct entry points apply\n // (non-empty messages, trailing user turn) so an invalid request fails fast\n // here rather than diverging at the proxy.\n const splitResult = splitChatRequest(system, messages);\n if (splitResult.isFailure()) {\n return fail(splitResult.message);\n }\n if (splitResult.value.prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {\n return fail(`provider \"${descriptor.id}\" does not accept image input`);\n }\n\n const body: Record<string, unknown> = {\n providerId: descriptor.id,\n apiKey,\n messages: normalizeOutboundMessages(splitResult.value),\n stream: true\n };\n // Temperature is forwarded only when explicitly provided, matching the direct path — the proxy\n // omits it from the upstream request so the provider default applies.\n if (temperature !== undefined) {\n body.temperature = temperature;\n }\n if (system !== undefined) {\n body.system = system;\n }\n if (modelOverride !== undefined) {\n body.modelOverride = modelOverride;\n }\n if (tools && tools.length > 0) {\n body.tools = tools;\n }\n if (thinking !== undefined) {\n body.thinking = thinking;\n }\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`AI streaming proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);\n\n const url = `${proxyUrl}/api/ai/completion-stream`;\n const conn = await openSseConnection(url, {}, body, logger, signal);\n return conn.onSuccess((response) => succeed(translateProxyStream(response)));\n}\n"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming chat completion client. Public façade over the per-format
|
|
3
|
+
* adapters under `streamingAdapters/`: provider dispatch and pre-flight
|
|
4
|
+
* validation live here; format-specific request/translation logic and the
|
|
5
|
+
* typed event-payload validators live with each adapter.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import { Result } from '@fgv/ts-utils';
|
|
10
|
+
import { type IAiStreamEvent } from './model';
|
|
11
|
+
import { type IProviderCompletionStreamParams } from './streamingAdapters/common';
|
|
12
|
+
export { callProxiedCompletionStream } from './streamingAdapters/proxy';
|
|
13
|
+
export type { IProviderCompletionStreamParams } from './streamingAdapters/common';
|
|
14
|
+
/**
|
|
15
|
+
* Re-export `executeClientToolTurn` from the continuation builder so callers
|
|
16
|
+
* can import it directly from the streaming-client surface.
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* **Why `clientTools` does not flow through `callProviderCompletionStream`:**
|
|
20
|
+
* Client tools require a stateful per-stream accumulation buffer (for thinking
|
|
21
|
+
* blocks, tool-use args, Gemini functionCall accumulation) that is owned by the
|
|
22
|
+
* continuation builder's execution context. Passing `clientTools` through the
|
|
23
|
+
* generic `callProviderCompletionStream` entry would require the caller to manage
|
|
24
|
+
* the accumulation buffer externally. `executeClientToolTurn` is therefore the
|
|
25
|
+
* canonical (and only) call path for client tools in Phase C. Callers that need
|
|
26
|
+
* both server tools and client tools in the same request should use
|
|
27
|
+
* `executeClientToolTurn` with both `tools` (server) and `clientTools` present;
|
|
28
|
+
* `callProviderCompletionStream` is for server-tools-only or no-tools requests.
|
|
29
|
+
*/
|
|
30
|
+
export { executeClientToolTurn, type IExecuteClientToolTurnParams, type IExecuteClientToolTurnResult, type IToolExecutionDecision } from './streamingAdapters/clientToolContinuationBuilder';
|
|
31
|
+
/**
|
|
32
|
+
* Calls the appropriate streaming chat completion API for a given provider.
|
|
33
|
+
*
|
|
34
|
+
* @remarks
|
|
35
|
+
* Pre-flight rejection: when `descriptor.streamingCorsRestricted === true`
|
|
36
|
+
* and the call isn't being routed through a proxy, this returns
|
|
37
|
+
* `Result.fail` before fetch is invoked. Callers should route through
|
|
38
|
+
* {@link AiAssist.callProxiedCompletionStream} or surface the failure to the user.
|
|
39
|
+
*
|
|
40
|
+
* Connection-time failures (auth, network, non-2xx) surface as the outer
|
|
41
|
+
* `Result.fail`. Once iteration begins, errors mid-stream surface as a
|
|
42
|
+
* terminal error event ({@link AiAssist.IAiStreamError}) followed by the iterable
|
|
43
|
+
* ending. The final successful event is {@link AiAssist.IAiStreamDone}.
|
|
44
|
+
*
|
|
45
|
+
* @param params - Request parameters including descriptor, API key, prompt, and optional tools
|
|
46
|
+
* @returns A streaming iterable of unified events, or a Result.fail
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
export declare function callProviderCompletionStream(params: IProviderCompletionStreamParams): Promise<Result<AsyncIterable<IAiStreamEvent>>>;
|
|
50
|
+
//# sourceMappingURL=streamingClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamingClient.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/streamingClient.ts"],"names":[],"mappings":"AAoBA;;;;;;;GAOG;AAEH,OAAO,EAAQ,MAAM,EAAE,MAAM,eAAe,CAAC;AAI7C,OAAO,EAAE,KAAK,cAAc,EAAiE,MAAM,SAAS,CAAC;AAE7G,OAAO,EAAE,KAAK,+BAA+B,EAAyB,MAAM,4BAA4B,CAAC;AAWzG,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,YAAY,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAElF;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,sBAAsB,EAC5B,MAAM,mDAAmD,CAAC;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CA8FhD"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2026 Erik Fortune
|
|
3
|
+
//
|
|
4
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
// in the Software without restriction, including without limitation the rights
|
|
7
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
// furnished to do so, subject to the following conditions:
|
|
10
|
+
//
|
|
11
|
+
// The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
// copies or substantial portions of the Software.
|
|
13
|
+
//
|
|
14
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
// SOFTWARE.
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.executeClientToolTurn = exports.callProxiedCompletionStream = void 0;
|
|
23
|
+
exports.callProviderCompletionStream = callProviderCompletionStream;
|
|
24
|
+
/**
|
|
25
|
+
* Streaming chat completion client. Public façade over the per-format
|
|
26
|
+
* adapters under `streamingAdapters/`: provider dispatch and pre-flight
|
|
27
|
+
* validation live here; format-specific request/translation logic and the
|
|
28
|
+
* typed event-payload validators live with each adapter.
|
|
29
|
+
*
|
|
30
|
+
* @packageDocumentation
|
|
31
|
+
*/
|
|
32
|
+
const ts_utils_1 = require("@fgv/ts-utils");
|
|
33
|
+
const chatRequestBuilders_1 = require("./chatRequestBuilders");
|
|
34
|
+
const endpoint_1 = require("./endpoint");
|
|
35
|
+
const model_1 = require("./model");
|
|
36
|
+
const anthropic_1 = require("./streamingAdapters/anthropic");
|
|
37
|
+
const gemini_1 = require("./streamingAdapters/gemini");
|
|
38
|
+
const openaiChat_1 = require("./streamingAdapters/openaiChat");
|
|
39
|
+
const openaiResponses_1 = require("./streamingAdapters/openaiResponses");
|
|
40
|
+
const thinkingOptionsResolver_1 = require("./thinkingOptionsResolver");
|
|
41
|
+
var proxy_1 = require("./streamingAdapters/proxy");
|
|
42
|
+
Object.defineProperty(exports, "callProxiedCompletionStream", { enumerable: true, get: function () { return proxy_1.callProxiedCompletionStream; } });
|
|
43
|
+
/**
|
|
44
|
+
* Re-export `executeClientToolTurn` from the continuation builder so callers
|
|
45
|
+
* can import it directly from the streaming-client surface.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* **Why `clientTools` does not flow through `callProviderCompletionStream`:**
|
|
49
|
+
* Client tools require a stateful per-stream accumulation buffer (for thinking
|
|
50
|
+
* blocks, tool-use args, Gemini functionCall accumulation) that is owned by the
|
|
51
|
+
* continuation builder's execution context. Passing `clientTools` through the
|
|
52
|
+
* generic `callProviderCompletionStream` entry would require the caller to manage
|
|
53
|
+
* the accumulation buffer externally. `executeClientToolTurn` is therefore the
|
|
54
|
+
* canonical (and only) call path for client tools in Phase C. Callers that need
|
|
55
|
+
* both server tools and client tools in the same request should use
|
|
56
|
+
* `executeClientToolTurn` with both `tools` (server) and `clientTools` present;
|
|
57
|
+
* `callProviderCompletionStream` is for server-tools-only or no-tools requests.
|
|
58
|
+
*/
|
|
59
|
+
/* c8 ignore next 5 - barrel re-export; function is covered by clientToolContinuationBuilder tests */
|
|
60
|
+
var clientToolContinuationBuilder_1 = require("./streamingAdapters/clientToolContinuationBuilder");
|
|
61
|
+
Object.defineProperty(exports, "executeClientToolTurn", { enumerable: true, get: function () { return clientToolContinuationBuilder_1.executeClientToolTurn; } });
|
|
62
|
+
/**
|
|
63
|
+
* Calls the appropriate streaming chat completion API for a given provider.
|
|
64
|
+
*
|
|
65
|
+
* @remarks
|
|
66
|
+
* Pre-flight rejection: when `descriptor.streamingCorsRestricted === true`
|
|
67
|
+
* and the call isn't being routed through a proxy, this returns
|
|
68
|
+
* `Result.fail` before fetch is invoked. Callers should route through
|
|
69
|
+
* {@link AiAssist.callProxiedCompletionStream} or surface the failure to the user.
|
|
70
|
+
*
|
|
71
|
+
* Connection-time failures (auth, network, non-2xx) surface as the outer
|
|
72
|
+
* `Result.fail`. Once iteration begins, errors mid-stream surface as a
|
|
73
|
+
* terminal error event ({@link AiAssist.IAiStreamError}) followed by the iterable
|
|
74
|
+
* ending. The final successful event is {@link AiAssist.IAiStreamDone}.
|
|
75
|
+
*
|
|
76
|
+
* @param params - Request parameters including descriptor, API key, prompt, and optional tools
|
|
77
|
+
* @returns A streaming iterable of unified events, or a Result.fail
|
|
78
|
+
* @public
|
|
79
|
+
*/
|
|
80
|
+
async function callProviderCompletionStream(params) {
|
|
81
|
+
const { descriptor, apiKey, system, messages, temperature, modelOverride, tier, logger, tools, signal, endpoint, thinking } = params;
|
|
82
|
+
const splitResult = (0, chatRequestBuilders_1.splitChatRequest)(system, messages);
|
|
83
|
+
if (splitResult.isFailure()) {
|
|
84
|
+
return (0, ts_utils_1.fail)(splitResult.message);
|
|
85
|
+
}
|
|
86
|
+
const { prompt, head } = splitResult.value;
|
|
87
|
+
const baseUrlResult = (0, endpoint_1.resolveEffectiveBaseUrl)(descriptor, endpoint);
|
|
88
|
+
if (baseUrlResult.isFailure()) {
|
|
89
|
+
return (0, ts_utils_1.fail)(baseUrlResult.message);
|
|
90
|
+
}
|
|
91
|
+
if (descriptor.streamingCorsRestricted) {
|
|
92
|
+
return (0, ts_utils_1.fail)(`provider "${descriptor.id}" requires a proxy for streaming; none is configured`);
|
|
93
|
+
}
|
|
94
|
+
if (prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {
|
|
95
|
+
return (0, ts_utils_1.fail)(`provider "${descriptor.id}" does not accept image input`);
|
|
96
|
+
}
|
|
97
|
+
const hasTools = tools !== undefined && tools.length > 0;
|
|
98
|
+
const discriminator = (0, thinkingOptionsResolver_1.providerDiscriminatorForId)(descriptor.id);
|
|
99
|
+
// The quality tier is the only completion-model selector; thinking and tools
|
|
100
|
+
// are orthogonal request params/capabilities and never pick a model.
|
|
101
|
+
const modelContext = tier;
|
|
102
|
+
const modelResult = (0, model_1.resolveProviderModel)(descriptor, modelOverride, modelContext);
|
|
103
|
+
if (modelResult.isFailure()) {
|
|
104
|
+
return (0, ts_utils_1.fail)(modelResult.message);
|
|
105
|
+
}
|
|
106
|
+
const model = modelResult.value;
|
|
107
|
+
let resolvedThinking;
|
|
108
|
+
if (thinking !== undefined) {
|
|
109
|
+
if (discriminator !== undefined) {
|
|
110
|
+
const mergeResult = (0, thinkingOptionsResolver_1.mergeThinkingConfig)(thinking, model, discriminator);
|
|
111
|
+
/* c8 ignore next 3 - mergeThinkingConfig always succeeds; defensive guard */
|
|
112
|
+
if (mergeResult.isFailure()) {
|
|
113
|
+
return (0, ts_utils_1.fail)(mergeResult.message);
|
|
114
|
+
}
|
|
115
|
+
resolvedThinking = mergeResult.value;
|
|
116
|
+
const conflictResult = (0, thinkingOptionsResolver_1.checkTemperatureConflict)(resolvedThinking, discriminator, temperature);
|
|
117
|
+
if (conflictResult.isFailure()) {
|
|
118
|
+
return (0, ts_utils_1.fail)(conflictResult.message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const config = {
|
|
123
|
+
baseUrl: baseUrlResult.value,
|
|
124
|
+
apiKey,
|
|
125
|
+
model
|
|
126
|
+
};
|
|
127
|
+
switch (descriptor.apiFormat) {
|
|
128
|
+
case 'openai':
|
|
129
|
+
// Responses-API-only models (e.g. gpt-5.5-pro) 400 on /chat/completions, so they route
|
|
130
|
+
// to the Responses stream even with no tools requested — same path the tools case uses.
|
|
131
|
+
if (hasTools || (0, model_1.isResponsesOnlyModel)(descriptor, config.model)) {
|
|
132
|
+
return (0, openaiResponses_1.callOpenAiResponsesStream)(config, prompt, tools, head, temperature, logger, signal, resolvedThinking);
|
|
133
|
+
}
|
|
134
|
+
return (0, openaiChat_1.callOpenAiChatStream)(config, prompt, head, temperature, logger, signal, resolvedThinking);
|
|
135
|
+
case 'anthropic':
|
|
136
|
+
return (0, anthropic_1.callAnthropicStream)(config, prompt, head, temperature, tools, logger, signal, resolvedThinking);
|
|
137
|
+
case 'gemini':
|
|
138
|
+
return (0, gemini_1.callGeminiStream)(config, prompt, head, temperature, tools, logger, signal, resolvedThinking);
|
|
139
|
+
/* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */
|
|
140
|
+
default: {
|
|
141
|
+
const _exhaustive = descriptor.apiFormat;
|
|
142
|
+
return (0, ts_utils_1.fail)(`unsupported API format: ${String(_exhaustive)}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=streamingClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamingClient.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/streamingClient.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 chat completion client. Public façade over the per-format\n * adapters under `streamingAdapters/`: provider dispatch and pre-flight\n * validation live here; format-specific request/translation logic and the\n * typed event-payload validators live with each adapter.\n *\n * @packageDocumentation\n */\n\nimport { fail, Result } from '@fgv/ts-utils';\n\nimport { splitChatRequest } from './chatRequestBuilders';\nimport { resolveEffectiveBaseUrl } from './endpoint';\nimport { type IAiStreamEvent, type ModelSpecKey, isResponsesOnlyModel, resolveProviderModel } from './model';\nimport { callAnthropicStream } from './streamingAdapters/anthropic';\nimport { type IProviderCompletionStreamParams, type IStreamApiConfig } from './streamingAdapters/common';\nimport { callGeminiStream } from './streamingAdapters/gemini';\nimport { callOpenAiChatStream } from './streamingAdapters/openaiChat';\nimport { callOpenAiResponsesStream } from './streamingAdapters/openaiResponses';\nimport {\n checkTemperatureConflict,\n mergeThinkingConfig,\n providerDiscriminatorForId,\n type IResolvedThinkingConfig\n} from './thinkingOptionsResolver';\n\nexport { callProxiedCompletionStream } from './streamingAdapters/proxy';\nexport type { IProviderCompletionStreamParams } from './streamingAdapters/common';\n\n/**\n * Re-export `executeClientToolTurn` from the continuation builder so callers\n * can import it directly from the streaming-client surface.\n *\n * @remarks\n * **Why `clientTools` does not flow through `callProviderCompletionStream`:**\n * Client tools require a stateful per-stream accumulation buffer (for thinking\n * blocks, tool-use args, Gemini functionCall accumulation) that is owned by the\n * continuation builder's execution context. Passing `clientTools` through the\n * generic `callProviderCompletionStream` entry would require the caller to manage\n * the accumulation buffer externally. `executeClientToolTurn` is therefore the\n * canonical (and only) call path for client tools in Phase C. Callers that need\n * both server tools and client tools in the same request should use\n * `executeClientToolTurn` with both `tools` (server) and `clientTools` present;\n * `callProviderCompletionStream` is for server-tools-only or no-tools requests.\n */\n/* c8 ignore next 5 - barrel re-export; function is covered by clientToolContinuationBuilder tests */\nexport {\n executeClientToolTurn,\n type IExecuteClientToolTurnParams,\n type IExecuteClientToolTurnResult,\n type IToolExecutionDecision\n} from './streamingAdapters/clientToolContinuationBuilder';\n\n/**\n * Calls the appropriate streaming chat completion API for a given provider.\n *\n * @remarks\n * Pre-flight rejection: when `descriptor.streamingCorsRestricted === true`\n * and the call isn't being routed through a proxy, this returns\n * `Result.fail` before fetch is invoked. Callers should route through\n * {@link AiAssist.callProxiedCompletionStream} or surface the failure to the user.\n *\n * Connection-time failures (auth, network, non-2xx) surface as the outer\n * `Result.fail`. Once iteration begins, errors mid-stream surface as a\n * terminal error event ({@link AiAssist.IAiStreamError}) followed by the iterable\n * ending. The final successful event is {@link AiAssist.IAiStreamDone}.\n *\n * @param params - Request parameters including descriptor, API key, prompt, and optional tools\n * @returns A streaming iterable of unified events, or a Result.fail\n * @public\n */\nexport async function callProviderCompletionStream(\n params: IProviderCompletionStreamParams\n): Promise<Result<AsyncIterable<IAiStreamEvent>>> {\n const {\n descriptor,\n apiKey,\n system,\n messages,\n temperature,\n modelOverride,\n tier,\n logger,\n tools,\n signal,\n endpoint,\n thinking\n } = params;\n\n const splitResult = splitChatRequest(system, messages);\n if (splitResult.isFailure()) {\n return fail(splitResult.message);\n }\n const { prompt, head } = splitResult.value;\n\n const baseUrlResult = resolveEffectiveBaseUrl(descriptor, endpoint);\n if (baseUrlResult.isFailure()) {\n return fail(baseUrlResult.message);\n }\n if (descriptor.streamingCorsRestricted) {\n return fail(`provider \"${descriptor.id}\" requires a proxy for streaming; none is configured`);\n }\n if (prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {\n return fail(`provider \"${descriptor.id}\" does not accept image input`);\n }\n\n const hasTools = tools !== undefined && tools.length > 0;\n const discriminator = providerDiscriminatorForId(descriptor.id);\n // The quality tier is the only completion-model selector; thinking and tools\n // are orthogonal request params/capabilities and never pick a model.\n const modelContext: ModelSpecKey | undefined = tier;\n\n const modelResult = resolveProviderModel(descriptor, modelOverride, modelContext);\n if (modelResult.isFailure()) {\n return fail(modelResult.message);\n }\n const model = modelResult.value;\n\n let resolvedThinking: IResolvedThinkingConfig | undefined;\n if (thinking !== undefined) {\n if (discriminator !== undefined) {\n const mergeResult = mergeThinkingConfig(thinking, model, discriminator);\n /* c8 ignore next 3 - mergeThinkingConfig always succeeds; defensive guard */\n if (mergeResult.isFailure()) {\n return fail(mergeResult.message);\n }\n resolvedThinking = mergeResult.value;\n const conflictResult = checkTemperatureConflict(resolvedThinking, discriminator, temperature);\n if (conflictResult.isFailure()) {\n return fail(conflictResult.message);\n }\n }\n }\n\n const config: IStreamApiConfig = {\n baseUrl: baseUrlResult.value,\n apiKey,\n model\n };\n\n switch (descriptor.apiFormat) {\n case 'openai':\n // Responses-API-only models (e.g. gpt-5.5-pro) 400 on /chat/completions, so they route\n // to the Responses stream even with no tools requested — same path the tools case uses.\n if (hasTools || isResponsesOnlyModel(descriptor, config.model)) {\n return callOpenAiResponsesStream(\n config,\n prompt,\n tools,\n head,\n temperature,\n logger,\n signal,\n resolvedThinking\n );\n }\n return callOpenAiChatStream(config, prompt, head, temperature, logger, signal, resolvedThinking);\n case 'anthropic':\n return callAnthropicStream(config, prompt, head, temperature, tools, logger, signal, resolvedThinking);\n case 'gemini':\n return callGeminiStream(config, prompt, head, temperature, tools, logger, signal, resolvedThinking);\n /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */\n default: {\n const _exhaustive: never = descriptor.apiFormat;\n return fail(`unsupported API format: ${String(_exhaustive)}`);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge logic and runtime validation for thinking/reasoning options.
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
import { type JsonObject } from '@fgv/ts-json-base';
|
|
6
|
+
import { Result } from '@fgv/ts-utils';
|
|
7
|
+
import type { IThinkingConfig, IAnthropicThinkingConfig, IOpenAiThinkingConfig, IXAiThinkingConfig } from './model';
|
|
8
|
+
/**
|
|
9
|
+
* Coarse provider family used to discriminate thinking config blocks.
|
|
10
|
+
* Maps from AiProviderId to the IThinkingProviderConfig `provider` discriminator.
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export type ThinkingProviderDiscriminator = 'anthropic' | 'openai' | 'google' | 'xai';
|
|
14
|
+
/**
|
|
15
|
+
* Maps an AiProviderId (registry key) to the coarse family discriminator used
|
|
16
|
+
* in IThinkingProviderConfig. Returns undefined for providers without thinking support.
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export declare function providerDiscriminatorForId(providerId: string): ThinkingProviderDiscriminator | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Resolved thinking wire parameters for a specific provider, after merging
|
|
22
|
+
* all applicable config blocks. Ready for provider-specific wire encoding.
|
|
23
|
+
*
|
|
24
|
+
* Callers that pre-resolve thinking config outside of the standard streaming
|
|
25
|
+
* helpers (e.g. `executeClientToolTurn`) accept this type via the
|
|
26
|
+
* `resolvedThinking` parameter and pass it directly to the adapter layer.
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export interface IResolvedThinkingConfig {
|
|
30
|
+
/** Anthropic: effort level; emit-site converts to `thinking.budget_tokens` via `anthropicEffortToBudgetTokens`. */
|
|
31
|
+
readonly anthropicEffort?: IAnthropicThinkingConfig['effort'];
|
|
32
|
+
/** OpenAI Chat: reasoning_effort value; OpenAI Responses: reasoning.effort */
|
|
33
|
+
readonly openAiEffort?: IOpenAiThinkingConfig['effort'];
|
|
34
|
+
/** Gemini: generationConfig.thinkingConfig.thinkingBudget */
|
|
35
|
+
readonly geminiThinkingBudget?: number;
|
|
36
|
+
/** xAI: reasoning_effort value (omit for grok-4) */
|
|
37
|
+
readonly xaiEffort?: IXAiThinkingConfig['effort'];
|
|
38
|
+
/** Other/passthrough: merged verbatim into wire request */
|
|
39
|
+
readonly otherParams?: JsonObject;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Maps Anthropic effort level to the `thinking.budget_tokens` integer that the
|
|
43
|
+
* Anthropic API requires when `thinking.type === 'enabled'`.
|
|
44
|
+
*
|
|
45
|
+
* Policy: low = 2048, medium = 8192, high = 24000, max = 32000. The lower three
|
|
46
|
+
* align with the Anthropic-published minimum-meaningful budget, a mid-range
|
|
47
|
+
* default, and a "deep thinking" allotment respectively. `max` targets Opus 4.6's
|
|
48
|
+
* deepest budget and stays within typical model limits.
|
|
49
|
+
*
|
|
50
|
+
* @public
|
|
51
|
+
*/
|
|
52
|
+
export declare function anthropicEffortToBudgetTokens(effort: NonNullable<IAnthropicThinkingConfig['effort']>): number;
|
|
53
|
+
/**
|
|
54
|
+
* Resolves the effective thinking wire parameters for a specific resolved model
|
|
55
|
+
* by merging all applicable config blocks in precedence order.
|
|
56
|
+
*
|
|
57
|
+
* Precedence (later tier wins; within tier, later declaration wins):
|
|
58
|
+
* 1. Generic effort (top-level IThinkingConfig.effort) → common-subset mapping
|
|
59
|
+
* 2. Provider-generic blocks (matching provider, no models filter)
|
|
60
|
+
* 3. Model-specific blocks (matching provider + models array includes resolved model)
|
|
61
|
+
* 4. Other blocks (provider: 'other', models includes resolved model) — same tier as 3
|
|
62
|
+
*
|
|
63
|
+
* Blocks whose provider does not match are silently skipped.
|
|
64
|
+
*
|
|
65
|
+
* Note: when the resolved OpenAI effort is `'none'`, reasoning is disabled and
|
|
66
|
+
* temperature is accepted; see {@link IOpenAiThinkingConfig.effort} for the full
|
|
67
|
+
* hybrid-mode semantics.
|
|
68
|
+
*
|
|
69
|
+
* @param config - The caller's IThinkingConfig
|
|
70
|
+
* @param resolvedModel - The concrete model string after registry resolution
|
|
71
|
+
* @param discriminator - Coarse provider family
|
|
72
|
+
* @returns Merged effective config for wire encoding
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
export declare function mergeThinkingConfig(config: IThinkingConfig, resolvedModel: string, discriminator: ThinkingProviderDiscriminator): Result<IResolvedThinkingConfig>;
|
|
76
|
+
/**
|
|
77
|
+
* Returns a Result.fail if temperature conflicts with thinking mode for the
|
|
78
|
+
* given provider, otherwise succeed(undefined).
|
|
79
|
+
*
|
|
80
|
+
* Per D4: temperature + thinking = Result.fail for Anthropic, OpenAI (when
|
|
81
|
+
* effective effort is non-null and non-'none'), and xAI (conservative default
|
|
82
|
+
* pending live verification). Gemini accepts temperature alongside thinking.
|
|
83
|
+
*
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
export declare function checkTemperatureConflict(resolved: IResolvedThinkingConfig, discriminator: ThinkingProviderDiscriminator, temperature: number | undefined): Result<undefined>;
|
|
87
|
+
//# sourceMappingURL=thinkingOptionsResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thinkingOptionsResolver.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/thinkingOptionsResolver.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAQ,MAAM,EAAW,MAAM,eAAe,CAAC;AAEtD,OAAO,KAAK,EACV,eAAe,EAEf,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAMjB;;;;GAIG;AACH,MAAM,MAAM,6BAA6B,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEtF;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,6BAA6B,GAAG,SAAS,CAaxG;AAMD;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,mHAAmH;IACnH,QAAQ,CAAC,eAAe,CAAC,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAC9D,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,CAAC,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACxD,6DAA6D;IAC7D,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,oDAAoD;IACpD,QAAQ,CAAC,SAAS,CAAC,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAClD,2DAA2D;IAC3D,QAAQ,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;CACnC;AAaD;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,WAAW,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC,GACtD,MAAM,CAWR;AAuFD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EACvB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,6BAA6B,GAC3C,MAAM,CAAC,uBAAuB,CAAC,CAyCjC;AAyDD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,uBAAuB,EACjC,aAAa,EAAE,6BAA6B,EAC5C,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,MAAM,CAAC,SAAS,CAAC,CAkCnB"}
|