@fgv/ts-extras 5.1.0-5 → 5.1.0-50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +90 -0
- package/dist/index.browser.js +6 -2
- package/dist/index.browser.js.map +1 -0
- package/dist/index.js +2 -1
- package/dist/index.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/{apiClient.js → completionClient.js} +165 -214
- package/dist/packlets/ai-assist/completionClient.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 +107 -0
- package/dist/packlets/ai-assist/endpoint.js.map +1 -0
- package/dist/packlets/ai-assist/http.js +104 -0
- package/dist/packlets/ai-assist/http.js.map +1 -0
- package/dist/packlets/ai-assist/imageGenerationClient.js +454 -0
- package/dist/packlets/ai-assist/imageGenerationClient.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 +12 -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 +423 -0
- package/dist/packlets/ai-assist/jsonResponse.js.map +1 -0
- package/dist/packlets/ai-assist/listModelsClient.js +294 -0
- package/dist/packlets/ai-assist/listModelsClient.js.map +1 -0
- package/dist/packlets/ai-assist/model.js +301 -9
- package/dist/packlets/ai-assist/model.js.map +1 -0
- package/dist/packlets/ai-assist/registry.js +376 -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 +376 -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 +208 -0
- package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +175 -0
- package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +390 -0
- package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/proxy.js +178 -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 +37 -0
- package/dist/packlets/crypto-utils/encryptedFile.js.map +1 -0
- package/dist/packlets/crypto-utils/hpkeProvider.js +355 -0
- package/dist/packlets/crypto-utils/hpkeProvider.js.map +1 -0
- package/dist/packlets/crypto-utils/index.browser.js +13 -2
- package/dist/packlets/crypto-utils/index.browser.js.map +1 -0
- package/dist/packlets/crypto-utils/index.js +9 -1
- 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 +111 -16
- 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 +872 -119
- package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
- package/dist/packlets/crypto-utils/keystore/model.js +35 -4
- 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 +347 -1
- package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
- package/dist/packlets/crypto-utils/seedDerivedKeyPair.js +120 -0
- package/dist/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -0
- package/dist/packlets/crypto-utils/spkiHelpers.js +284 -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/safer-fetch/addressClassification.js +438 -0
- package/dist/packlets/safer-fetch/addressClassification.js.map +1 -0
- package/dist/packlets/safer-fetch/addressPolicy.js +119 -0
- package/dist/packlets/safer-fetch/addressPolicy.js.map +1 -0
- package/dist/packlets/safer-fetch/contentType.js +120 -0
- package/dist/packlets/safer-fetch/contentType.js.map +1 -0
- package/dist/packlets/safer-fetch/deadline.js +254 -0
- package/dist/packlets/safer-fetch/deadline.js.map +1 -0
- package/dist/packlets/safer-fetch/defaults.js +131 -0
- package/dist/packlets/safer-fetch/defaults.js.map +1 -0
- package/dist/packlets/safer-fetch/failureReason.js +21 -0
- package/dist/packlets/safer-fetch/failureReason.js.map +1 -0
- package/dist/packlets/safer-fetch/guards.js +148 -0
- package/dist/packlets/safer-fetch/guards.js.map +1 -0
- package/dist/packlets/safer-fetch/index.browser.js +58 -0
- package/dist/packlets/safer-fetch/index.browser.js.map +1 -0
- package/dist/packlets/safer-fetch/index.js +52 -0
- package/dist/packlets/safer-fetch/index.js.map +1 -0
- package/dist/packlets/safer-fetch/model.js +21 -0
- package/dist/packlets/safer-fetch/model.js.map +1 -0
- package/dist/packlets/safer-fetch/nodeAddressGuard.js +191 -0
- package/dist/packlets/safer-fetch/nodeAddressGuard.js.map +1 -0
- package/dist/packlets/safer-fetch/redirect.js +93 -0
- package/dist/packlets/safer-fetch/redirect.js.map +1 -0
- package/dist/packlets/safer-fetch/retry.js +188 -0
- package/dist/packlets/safer-fetch/retry.js.map +1 -0
- package/dist/packlets/safer-fetch/saferFetch.js +755 -0
- package/dist/packlets/safer-fetch/saferFetch.js.map +1 -0
- package/dist/packlets/safer-fetch/transport.js +50 -0
- package/dist/packlets/safer-fetch/transport.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 +99 -9
- package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
- package/dist/packlets/zip-file-tree/zipFileTreeWriter.js +16 -1
- package/dist/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
- package/dist/ts-extras.d.ts +6648 -553
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/index.browser.d.ts +5 -2
- package/lib/index.browser.d.ts.map +1 -0
- package/lib/index.browser.js +11 -3
- package/lib/index.browser.js.map +1 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +3 -1
- package/lib/index.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/completionClient.d.ts +74 -0
- package/lib/packlets/ai-assist/completionClient.d.ts.map +1 -0
- package/lib/packlets/ai-assist/{apiClient.js → completionClient.js} +164 -213
- package/lib/packlets/ai-assist/completionClient.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 +49 -0
- package/lib/packlets/ai-assist/endpoint.d.ts.map +1 -0
- package/lib/packlets/ai-assist/endpoint.js +113 -0
- package/lib/packlets/ai-assist/endpoint.js.map +1 -0
- package/lib/packlets/ai-assist/http.d.ts +34 -0
- package/lib/packlets/ai-assist/http.d.ts.map +1 -0
- package/lib/packlets/ai-assist/http.js +109 -0
- package/lib/packlets/ai-assist/http.js.map +1 -0
- package/lib/packlets/ai-assist/imageGenerationClient.d.ts +46 -0
- package/lib/packlets/ai-assist/imageGenerationClient.d.ts.map +1 -0
- package/lib/packlets/ai-assist/imageGenerationClient.js +458 -0
- package/lib/packlets/ai-assist/imageGenerationClient.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 +12 -4
- package/lib/packlets/ai-assist/index.d.ts.map +1 -0
- package/lib/packlets/ai-assist/index.js +47 -4
- 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 +194 -0
- package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -0
- package/lib/packlets/ai-assist/jsonResponse.js +429 -0
- package/lib/packlets/ai-assist/jsonResponse.js.map +1 -0
- package/lib/packlets/ai-assist/listModelsClient.d.ts +46 -0
- package/lib/packlets/ai-assist/listModelsClient.d.ts.map +1 -0
- package/lib/packlets/ai-assist/listModelsClient.js +298 -0
- package/lib/packlets/ai-assist/listModelsClient.js.map +1 -0
- package/lib/packlets/ai-assist/model.d.ts +1346 -12
- package/lib/packlets/ai-assist/model.d.ts.map +1 -0
- package/lib/packlets/ai-assist/model.js +309 -10
- package/lib/packlets/ai-assist/model.js.map +1 -0
- package/lib/packlets/ai-assist/registry.d.ts +76 -1
- package/lib/packlets/ai-assist/registry.d.ts.map +1 -0
- package/lib/packlets/ai-assist/registry.js +381 -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 +379 -0
- package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +269 -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 +163 -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 +211 -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 +178 -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 +393 -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 +181 -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 +25 -0
- package/lib/packlets/crypto-utils/encryptedFile.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/encryptedFile.js +38 -0
- package/lib/packlets/crypto-utils/encryptedFile.js.map +1 -0
- package/lib/packlets/crypto-utils/hpkeProvider.d.ts +150 -0
- package/lib/packlets/crypto-utils/hpkeProvider.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/hpkeProvider.js +359 -0
- package/lib/packlets/crypto-utils/hpkeProvider.js.map +1 -0
- package/lib/packlets/crypto-utils/index.browser.d.ts +5 -1
- package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/index.browser.js +28 -3
- package/lib/packlets/crypto-utils/index.browser.js.map +1 -0
- package/lib/packlets/crypto-utils/index.d.ts +5 -1
- package/lib/packlets/crypto-utils/index.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/index.js +24 -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 +109 -14
- 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 +314 -13
- package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keystore/keyStore.js +877 -124
- package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
- package/lib/packlets/crypto-utils/keystore/model.d.ts +404 -21
- package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/keystore/model.js +37 -5
- 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 +518 -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 +142 -2
- package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/nodeCryptoProvider.js +346 -0
- package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
- package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts +42 -0
- package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/seedDerivedKeyPair.js +123 -0
- package/lib/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -0
- package/lib/packlets/crypto-utils/spkiHelpers.d.ts +151 -0
- package/lib/packlets/crypto-utils/spkiHelpers.d.ts.map +1 -0
- package/lib/packlets/crypto-utils/spkiHelpers.js +297 -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/safer-fetch/addressClassification.d.ts +144 -0
- package/lib/packlets/safer-fetch/addressClassification.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/addressClassification.js +441 -0
- package/lib/packlets/safer-fetch/addressClassification.js.map +1 -0
- package/lib/packlets/safer-fetch/addressPolicy.d.ts +113 -0
- package/lib/packlets/safer-fetch/addressPolicy.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/addressPolicy.js +123 -0
- package/lib/packlets/safer-fetch/addressPolicy.js.map +1 -0
- package/lib/packlets/safer-fetch/contentType.d.ts +51 -0
- package/lib/packlets/safer-fetch/contentType.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/contentType.js +127 -0
- package/lib/packlets/safer-fetch/contentType.js.map +1 -0
- package/lib/packlets/safer-fetch/deadline.d.ts +138 -0
- package/lib/packlets/safer-fetch/deadline.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/deadline.js +258 -0
- package/lib/packlets/safer-fetch/deadline.js.map +1 -0
- package/lib/packlets/safer-fetch/defaults.d.ts +108 -0
- package/lib/packlets/safer-fetch/defaults.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/defaults.js +134 -0
- package/lib/packlets/safer-fetch/defaults.js.map +1 -0
- package/lib/packlets/safer-fetch/failureReason.d.ts +148 -0
- package/lib/packlets/safer-fetch/failureReason.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/failureReason.js +22 -0
- package/lib/packlets/safer-fetch/failureReason.js.map +1 -0
- package/lib/packlets/safer-fetch/guards.d.ts +62 -0
- package/lib/packlets/safer-fetch/guards.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/guards.js +153 -0
- package/lib/packlets/safer-fetch/guards.js.map +1 -0
- package/lib/packlets/safer-fetch/index.browser.d.ts +33 -0
- package/lib/packlets/safer-fetch/index.browser.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/index.browser.js +82 -0
- package/lib/packlets/safer-fetch/index.browser.js.map +1 -0
- package/lib/packlets/safer-fetch/index.d.ts +27 -0
- package/lib/packlets/safer-fetch/index.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/index.js +78 -0
- package/lib/packlets/safer-fetch/index.js.map +1 -0
- package/lib/packlets/safer-fetch/model.d.ts +373 -0
- package/lib/packlets/safer-fetch/model.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/model.js +22 -0
- package/lib/packlets/safer-fetch/model.js.map +1 -0
- package/lib/packlets/safer-fetch/nodeAddressGuard.d.ts +129 -0
- package/lib/packlets/safer-fetch/nodeAddressGuard.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/nodeAddressGuard.js +196 -0
- package/lib/packlets/safer-fetch/nodeAddressGuard.js.map +1 -0
- package/lib/packlets/safer-fetch/redirect.d.ts +62 -0
- package/lib/packlets/safer-fetch/redirect.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/redirect.js +98 -0
- package/lib/packlets/safer-fetch/redirect.js.map +1 -0
- package/lib/packlets/safer-fetch/retry.d.ts +162 -0
- package/lib/packlets/safer-fetch/retry.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/retry.js +197 -0
- package/lib/packlets/safer-fetch/retry.js.map +1 -0
- package/lib/packlets/safer-fetch/saferFetch.d.ts +108 -0
- package/lib/packlets/safer-fetch/saferFetch.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/saferFetch.js +760 -0
- package/lib/packlets/safer-fetch/saferFetch.js.map +1 -0
- package/lib/packlets/safer-fetch/transport.d.ts +18 -0
- package/lib/packlets/safer-fetch/transport.d.ts.map +1 -0
- package/lib/packlets/safer-fetch/transport.js +53 -0
- package/lib/packlets/safer-fetch/transport.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 +84 -8
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts.map +1 -0
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js +99 -9
- package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts +26 -1
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts.map +1 -0
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.js +17 -1
- package/lib/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
- package/package.json +30 -15
- package/lib/packlets/ai-assist/apiClient.d.ts +0 -60
|
@@ -0,0 +1,109 @@
|
|
|
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.fetchJson = fetchJson;
|
|
23
|
+
exports.fetchGetJson = fetchGetJson;
|
|
24
|
+
exports.fetchMultipart = fetchMultipart;
|
|
25
|
+
/**
|
|
26
|
+
* Shared low-level HTTP helpers for the AI-assist provider clients (completion,
|
|
27
|
+
* image generation, embedding). Internal to the packlet.
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
*/
|
|
30
|
+
const ts_json_base_1 = require("@fgv/ts-json-base");
|
|
31
|
+
const ts_utils_1 = require("@fgv/ts-utils");
|
|
32
|
+
/**
|
|
33
|
+
* Issue one request and parse a JSON object body, or fail.
|
|
34
|
+
*
|
|
35
|
+
* @remarks
|
|
36
|
+
* The single implementation behind {@link fetchJson}, {@link fetchGetJson} and
|
|
37
|
+
* {@link fetchMultipart} — the three differed *only* in how they built their
|
|
38
|
+
* `RequestInit` and what they logged, and carried byte-identical copies of
|
|
39
|
+
* everything after the `fetch` call. Non-2xx responses, network errors, invalid
|
|
40
|
+
* JSON and non-object JSON bodies are all surfaced as `Result.fail`.
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
async function _fetchAndParseJson(url, init, requestLabel, logger) {
|
|
44
|
+
/* c8 ignore next 1 - optional logger */
|
|
45
|
+
logger === null || logger === void 0 ? void 0 : logger.detail(`AI API request: ${requestLabel}`);
|
|
46
|
+
// `captureAsyncResult` normalizes both a synchronous throw and a rejected
|
|
47
|
+
// promise, and its `_errorMessage` is the same `instanceof Error` shaping this
|
|
48
|
+
// used to spell out by hand — so the failure text is unchanged and the
|
|
49
|
+
// defensive `c8 ignore` on the non-Error branch is no longer needed here.
|
|
50
|
+
const fetched = await (0, ts_utils_1.captureAsyncResult)(() => fetch(url, init)).withErrorFormat((msg) => `AI API request failed: ${msg}`);
|
|
51
|
+
if (fetched.isFailure()) {
|
|
52
|
+
/* c8 ignore next 1 - optional logger */
|
|
53
|
+
logger === null || logger === void 0 ? void 0 : logger.error(fetched.message);
|
|
54
|
+
return (0, ts_utils_1.fail)(fetched.message);
|
|
55
|
+
}
|
|
56
|
+
const response = fetched.value;
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const errorText = await response.text().catch(() => 'unknown error');
|
|
59
|
+
/* c8 ignore next 1 - optional logger */
|
|
60
|
+
logger === null || logger === void 0 ? void 0 : logger.error(`AI API returned ${response.status}: ${errorText}`);
|
|
61
|
+
return (0, ts_utils_1.fail)(`AI API returned ${response.status}: ${errorText}`);
|
|
62
|
+
}
|
|
63
|
+
/* c8 ignore next 1 - optional logger */
|
|
64
|
+
logger === null || logger === void 0 ? void 0 : logger.detail(`AI API response: ${response.status}`);
|
|
65
|
+
let json;
|
|
66
|
+
try {
|
|
67
|
+
json = await response.json();
|
|
68
|
+
}
|
|
69
|
+
catch (_a) {
|
|
70
|
+
/* c8 ignore next 1 - optional logger */
|
|
71
|
+
logger === null || logger === void 0 ? void 0 : logger.error('AI API returned invalid JSON response');
|
|
72
|
+
return (0, ts_utils_1.fail)('AI API returned invalid JSON response');
|
|
73
|
+
}
|
|
74
|
+
if (!(0, ts_json_base_1.isJsonObject)(json)) {
|
|
75
|
+
/* c8 ignore next 1 - optional logger */
|
|
76
|
+
logger === null || logger === void 0 ? void 0 : logger.error('AI API returned non-object JSON response');
|
|
77
|
+
return (0, ts_utils_1.fail)('AI API returned non-object JSON response');
|
|
78
|
+
}
|
|
79
|
+
return (0, ts_utils_1.succeed)(json);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Makes a JSON POST request and returns the parsed object body, or a failure.
|
|
83
|
+
* @internal
|
|
84
|
+
*/
|
|
85
|
+
async function fetchJson(url, headers, body, logger, signal) {
|
|
86
|
+
return _fetchAndParseJson(url, {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
headers: Object.assign({ 'Content-Type': 'application/json' }, headers),
|
|
89
|
+
body: JSON.stringify(body),
|
|
90
|
+
signal
|
|
91
|
+
}, `POST ${url}`, logger);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Makes an HTTP GET request and returns the parsed JSON, or a failure.
|
|
95
|
+
* @internal
|
|
96
|
+
*/
|
|
97
|
+
async function fetchGetJson(url, headers, logger, signal) {
|
|
98
|
+
return _fetchAndParseJson(url, { method: 'GET', headers, signal }, `GET ${url}`, logger);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Makes a multipart/form-data POST request and returns the parsed JSON, or a
|
|
102
|
+
* failure. The Content-Type header (with boundary) is set automatically by
|
|
103
|
+
* `fetch` from the `FormData` body — callers must NOT pass it explicitly.
|
|
104
|
+
* @internal
|
|
105
|
+
*/
|
|
106
|
+
async function fetchMultipart(url, headers, body, logger, signal) {
|
|
107
|
+
return _fetchAndParseJson(url, { method: 'POST', headers, body, signal }, `POST ${url} (multipart)`, logger);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/http.ts"],"names":[],"mappings":";AAAA,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AACxE,2DAA2D;AAC3D,EAAE;AACF,iFAAiF;AACjF,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,gFAAgF;AAChF,YAAY;;AAsFZ,8BAkBC;AAMD,oCAOC;AAQD,wCAaC;AAxID;;;;GAIG;AAEH,oDAAkE;AAClE,4CAAwF;AAYxF;;;;;;;;;;GAUG;AACH,KAAK,UAAU,kBAAkB,CAC/B,GAAW,EACX,IAAiB,EACjB,YAAoB,EACpB,MAAwB;IAExB,wCAAwC;IACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,mBAAmB,YAAY,EAAE,CAAC,CAAC;IAElD,0EAA0E;IAC1E,+EAA+E;IAC/E,uEAAuE;IACvE,0EAA0E;IAC1E,MAAM,OAAO,GAAqB,MAAM,IAAA,6BAAkB,EAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,eAAe,CAChG,CAAC,GAAG,EAAE,EAAE,CAAC,0BAA0B,GAAG,EAAE,CACzC,CAAC;IACF,IAAI,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;QACxB,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/B,OAAO,IAAA,eAAI,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,QAAQ,GAAa,OAAO,CAAC,KAAK,CAAC;IAEzC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;QACrE,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;QAClE,OAAO,IAAA,eAAI,EAAC,mBAAmB,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,wCAAwC;IACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAC,oBAAoB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtD,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,WAAM,CAAC;QACP,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACvD,OAAO,IAAA,eAAI,EAAC,uCAAuC,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,IAAA,2BAAY,EAAC,IAAI,CAAC,EAAE,CAAC;QACxB,wCAAwC;QACxC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,IAAA,eAAI,EAAC,0CAA0C,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,IAAA,kBAAO,EAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,OAA+B,EAC/B,IAAa,EACb,MAAwB,EACxB,MAAoB;IAEpB,OAAO,kBAAkB,CACvB,GAAG,EACH;QACE,MAAM,EAAE,MAAM;QACd,OAAO,kBAAI,cAAc,EAAE,kBAAkB,IAAK,OAAO,CAAE;QAC3D,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC1B,MAAM;KACP,EACD,QAAQ,GAAG,EAAE,EACb,MAAM,CACP,CAAC;AACJ,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,OAA+B,EAC/B,MAAwB,EACxB,MAAoB;IAEpB,OAAO,kBAAkB,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;AAC3F,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,OAA+B,EAC/B,IAAc,EACd,MAAwB,EACxB,MAAoB;IAEpB,OAAO,kBAAkB,CACvB,GAAG,EACH,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EACzC,QAAQ,GAAG,cAAc,EACzB,MAAM,CACP,CAAC;AACJ,CAAC","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 * Shared low-level HTTP helpers for the AI-assist provider clients (completion,\n * image generation, embedding). Internal to the packlet.\n * @packageDocumentation\n */\n\nimport { isJsonObject, type JsonObject } from '@fgv/ts-json-base';\nimport { captureAsyncResult, fail, type Logging, Result, succeed } from '@fgv/ts-utils';\n\n/**\n * Internal API configuration built from a provider descriptor.\n * @internal\n */\nexport interface IAiApiConfig {\n readonly baseUrl: string;\n readonly apiKey: string;\n readonly model: string;\n}\n\n/**\n * Issue one request and parse a JSON object body, or fail.\n *\n * @remarks\n * The single implementation behind {@link fetchJson}, {@link fetchGetJson} and\n * {@link fetchMultipart} — the three differed *only* in how they built their\n * `RequestInit` and what they logged, and carried byte-identical copies of\n * everything after the `fetch` call. Non-2xx responses, network errors, invalid\n * JSON and non-object JSON bodies are all surfaced as `Result.fail`.\n * @internal\n */\nasync function _fetchAndParseJson(\n url: string,\n init: RequestInit,\n requestLabel: string,\n logger?: Logging.ILogger\n): Promise<Result<JsonObject>> {\n /* c8 ignore next 1 - optional logger */\n logger?.detail(`AI API request: ${requestLabel}`);\n\n // `captureAsyncResult` normalizes both a synchronous throw and a rejected\n // promise, and its `_errorMessage` is the same `instanceof Error` shaping this\n // used to spell out by hand — so the failure text is unchanged and the\n // defensive `c8 ignore` on the non-Error branch is no longer needed here.\n const fetched: Result<Response> = await captureAsyncResult(() => fetch(url, init)).withErrorFormat(\n (msg) => `AI API request failed: ${msg}`\n );\n if (fetched.isFailure()) {\n /* c8 ignore next 1 - optional logger */\n logger?.error(fetched.message);\n return fail(fetched.message);\n }\n const response: Response = fetched.value;\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'unknown error');\n /* c8 ignore next 1 - optional logger */\n logger?.error(`AI API returned ${response.status}: ${errorText}`);\n return fail(`AI API returned ${response.status}: ${errorText}`);\n }\n\n /* c8 ignore next 1 - optional logger */\n logger?.detail(`AI API response: ${response.status}`);\n\n let json: unknown;\n try {\n json = await response.json();\n } catch {\n /* c8 ignore next 1 - optional logger */\n logger?.error('AI API returned invalid JSON response');\n return fail('AI API returned invalid JSON response');\n }\n\n if (!isJsonObject(json)) {\n /* c8 ignore next 1 - optional logger */\n logger?.error('AI API returned non-object JSON response');\n return fail('AI API returned non-object JSON response');\n }\n return succeed(json);\n}\n\n/**\n * Makes a JSON POST request and returns the parsed object body, or a failure.\n * @internal\n */\nexport async function fetchJson(\n url: string,\n headers: Record<string, string>,\n body: unknown,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<JsonObject>> {\n return _fetchAndParseJson(\n url,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify(body),\n signal\n },\n `POST ${url}`,\n logger\n );\n}\n\n/**\n * Makes an HTTP GET request and returns the parsed JSON, or a failure.\n * @internal\n */\nexport async function fetchGetJson(\n url: string,\n headers: Record<string, string>,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<JsonObject>> {\n return _fetchAndParseJson(url, { method: 'GET', headers, signal }, `GET ${url}`, logger);\n}\n\n/**\n * Makes a multipart/form-data POST request and returns the parsed JSON, or a\n * failure. The Content-Type header (with boundary) is set automatically by\n * `fetch` from the `FormData` body — callers must NOT pass it explicitly.\n * @internal\n */\nexport async function fetchMultipart(\n url: string,\n headers: Record<string, string>,\n body: FormData,\n logger?: Logging.ILogger,\n signal?: AbortSignal\n): Promise<Result<JsonObject>> {\n return _fetchAndParseJson(\n url,\n { method: 'POST', headers, body, signal },\n `POST ${url} (multipart)`,\n logger\n );\n}\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Logging, Result } from '@fgv/ts-utils';
|
|
2
|
+
import { type IAiImageGenerationParams, type IAiImageGenerationResponse, type IAiProviderDescriptor, type ModelSpec } from './model';
|
|
3
|
+
/**
|
|
4
|
+
* Parameters for an image-generation request.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface IProviderImageGenerationParams {
|
|
8
|
+
/** The provider descriptor */
|
|
9
|
+
readonly descriptor: IAiProviderDescriptor;
|
|
10
|
+
/** API key for authentication */
|
|
11
|
+
readonly apiKey: string;
|
|
12
|
+
/** The image-generation request */
|
|
13
|
+
readonly params: IAiImageGenerationParams;
|
|
14
|
+
/** Optional model override — string or context-aware map (uses descriptor.defaultModel.image otherwise) */
|
|
15
|
+
readonly modelOverride?: ModelSpec;
|
|
16
|
+
/** Optional logger for request/response observability. */
|
|
17
|
+
readonly logger?: Logging.ILogger;
|
|
18
|
+
/** Optional abort signal for cancelling the in-flight request. */
|
|
19
|
+
readonly signal?: AbortSignal;
|
|
20
|
+
/** Optional override of the descriptor's base URL; per-route suffix is appended unchanged. */
|
|
21
|
+
readonly endpoint?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Calls the appropriate image-generation API for a given provider. Routes by the
|
|
25
|
+
* `format` field of the resolved {@link IAiImageModelCapability}:
|
|
26
|
+
* `'openai-images'`, `'xai-images'`, `'xai-images-edits'`, or
|
|
27
|
+
* `'gemini-image-out'`. Rejects up front if `referenceImages` is set but the
|
|
28
|
+
* capability does not declare `acceptsImageReferenceInput`.
|
|
29
|
+
* @param params - Request parameters including descriptor, API key, and prompt
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export declare function callProviderImageGeneration(params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
|
|
33
|
+
/**
|
|
34
|
+
* Calls the image-generation endpoint on a proxy server instead of calling
|
|
35
|
+
* the provider API directly from the browser.
|
|
36
|
+
* Endpoint: `POST ${proxyUrl}/api/ai/image-generation`. Request body:
|
|
37
|
+
* `{providerId, apiKey, params, modelOverride?}`. The proxy handles descriptor
|
|
38
|
+
* lookup, model resolution, provider dispatch, and response normalization
|
|
39
|
+
* (including repackaging `referenceImages` for the upstream wire format).
|
|
40
|
+
* Error body `{error: string}` is surfaced as `proxy: ${error}`.
|
|
41
|
+
* @param proxyUrl - Base URL of the proxy server
|
|
42
|
+
* @param params - Same parameters as {@link callProviderImageGeneration}
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export declare function callProxiedImageGeneration(proxyUrl: string, params: IProviderImageGenerationParams): Promise<Result<IAiImageGenerationResponse>>;
|
|
46
|
+
//# sourceMappingURL=imageGenerationClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageGenerationClient.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/imageGenerationClient.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAQ,KAAK,OAAO,EAAc,MAAM,EAAuC,MAAM,eAAe,CAAC;AAE5G,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAE/B,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EAEf,MAAM,SAAS,CAAC;AAmEjB;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,8BAA8B;IAC9B,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAC3C,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAC1C,2GAA2G;IAC3G,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AA6YD;;;;;;;;GAQG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,8BAA8B,GACrC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CA+D7C;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,8BAA8B,GACrC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CA6B7C"}
|
|
@@ -0,0 +1,458 @@
|
|
|
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.callProviderImageGeneration = callProviderImageGeneration;
|
|
23
|
+
exports.callProxiedImageGeneration = callProxiedImageGeneration;
|
|
24
|
+
const ts_utils_1 = require("@fgv/ts-utils");
|
|
25
|
+
const model_1 = require("./model");
|
|
26
|
+
const endpoint_1 = require("./endpoint");
|
|
27
|
+
const http_1 = require("./http");
|
|
28
|
+
const registry_1 = require("./registry");
|
|
29
|
+
const imageOptionsResolver_1 = require("./imageOptionsResolver");
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// Image attachment helpers
|
|
32
|
+
// ============================================================================
|
|
33
|
+
/**
|
|
34
|
+
* Decodes a base64-encoded image attachment into a `Blob` suitable for use as
|
|
35
|
+
* a multipart file field. On Node hands the `Buffer` straight to `Blob`
|
|
36
|
+
* (Buffer extends Uint8Array) to skip an intermediate copy; falls back to
|
|
37
|
+
* `atob` in browsers. Inputs come from `FileReader` or prior provider
|
|
38
|
+
* responses, which are trusted to be valid. Note that Node's
|
|
39
|
+
* `Buffer.from(..., 'base64')` silently strips invalid characters rather
|
|
40
|
+
* than throwing, so failures are only observable in the browser path.
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
function attachmentToBlob(attachment) {
|
|
44
|
+
if (typeof Buffer !== 'undefined') {
|
|
45
|
+
return (0, ts_utils_1.succeed)(new Blob([Buffer.from(attachment.base64, 'base64')], { type: attachment.mimeType }));
|
|
46
|
+
}
|
|
47
|
+
/* c8 ignore start - Browser-only fallback cannot be tested in Node.js environment */
|
|
48
|
+
try {
|
|
49
|
+
const binary = atob(attachment.base64);
|
|
50
|
+
const bytes = new Uint8Array(binary.length);
|
|
51
|
+
for (let i = 0; i < binary.length; i++) {
|
|
52
|
+
bytes[i] = binary.charCodeAt(i);
|
|
53
|
+
}
|
|
54
|
+
return (0, ts_utils_1.succeed)(new Blob([bytes], { type: attachment.mimeType }));
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
58
|
+
return (0, ts_utils_1.fail)(`Invalid base64: ${message}`);
|
|
59
|
+
}
|
|
60
|
+
/* c8 ignore stop */
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Maps a MIME type to a sensible file extension for multipart filenames.
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
function extensionForMimeType(mimeType) {
|
|
67
|
+
switch (mimeType) {
|
|
68
|
+
case 'image/png':
|
|
69
|
+
return 'png';
|
|
70
|
+
case 'image/jpeg':
|
|
71
|
+
case 'image/jpg':
|
|
72
|
+
return 'jpg';
|
|
73
|
+
case 'image/webp':
|
|
74
|
+
return 'webp';
|
|
75
|
+
case 'image/gif':
|
|
76
|
+
return 'gif';
|
|
77
|
+
default:
|
|
78
|
+
return 'bin';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const openAiImageItem = ts_utils_1.Validators.object({
|
|
82
|
+
b64_json: ts_utils_1.Validators.string,
|
|
83
|
+
revised_prompt: ts_utils_1.Validators.string.optional()
|
|
84
|
+
});
|
|
85
|
+
const openAiImageResponse = ts_utils_1.Validators.object({
|
|
86
|
+
data: ts_utils_1.Validators.arrayOf(openAiImageItem).withConstraint((arr) => arr.length > 0)
|
|
87
|
+
});
|
|
88
|
+
const geminiImageInlineData = ts_utils_1.Validators.object({
|
|
89
|
+
mimeType: ts_utils_1.Validators.string,
|
|
90
|
+
data: ts_utils_1.Validators.string
|
|
91
|
+
});
|
|
92
|
+
const geminiImageOutPart = ts_utils_1.Validators.object({
|
|
93
|
+
text: ts_utils_1.Validators.string.optional(),
|
|
94
|
+
inlineData: geminiImageInlineData.optional()
|
|
95
|
+
});
|
|
96
|
+
const geminiImageOutContent = ts_utils_1.Validators.object({
|
|
97
|
+
parts: ts_utils_1.Validators.arrayOf(geminiImageOutPart)
|
|
98
|
+
});
|
|
99
|
+
const geminiImageOutCandidate = ts_utils_1.Validators.object({
|
|
100
|
+
content: geminiImageOutContent.optional(),
|
|
101
|
+
finishReason: ts_utils_1.Validators.string.optional(),
|
|
102
|
+
finishMessage: ts_utils_1.Validators.string.optional()
|
|
103
|
+
});
|
|
104
|
+
const geminiImageOutResponse = ts_utils_1.Validators.object({
|
|
105
|
+
candidates: ts_utils_1.Validators.arrayOf(geminiImageOutCandidate).withConstraint((arr) => arr.length > 0)
|
|
106
|
+
});
|
|
107
|
+
// ---- Proxied image generation response ----
|
|
108
|
+
const proxiedGeneratedImage = ts_utils_1.Validators.object({
|
|
109
|
+
mimeType: ts_utils_1.Validators.string,
|
|
110
|
+
base64: ts_utils_1.Validators.string,
|
|
111
|
+
revisedPrompt: ts_utils_1.Validators.string.optional()
|
|
112
|
+
});
|
|
113
|
+
const proxiedImageGenerationResponse = ts_utils_1.Validators.object({
|
|
114
|
+
images: ts_utils_1.Validators.arrayOf(proxiedGeneratedImage).withConstraint((arr) => arr.length > 0)
|
|
115
|
+
});
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// Image generation — adapters
|
|
118
|
+
// ============================================================================
|
|
119
|
+
/** Routes to /images/generations or /images/edits; handles outputParamStyle. @internal */
|
|
120
|
+
async function callOpenAiImageGeneration(config, request, capability, resolved, logger, signal) {
|
|
121
|
+
var _a, _b;
|
|
122
|
+
const refs = (_a = request.referenceImages) !== null && _a !== void 0 ? _a : [];
|
|
123
|
+
const headers = (0, endpoint_1.bearerAuthHeader)(config.apiKey);
|
|
124
|
+
const effectiveMimeType = resolved.outputFormat !== undefined
|
|
125
|
+
? `image/${resolved.outputFormat}`
|
|
126
|
+
: (_b = capability.defaultOutputMimeType) !== null && _b !== void 0 ? _b : 'image/png';
|
|
127
|
+
const fetched = refs.length > 0
|
|
128
|
+
? await callOpenAiImagesEdits(config, capability, request, headers, resolved, logger, signal)
|
|
129
|
+
: await callOpenAiImagesGenerations(config, request, headers, resolved, capability, logger, signal);
|
|
130
|
+
return fetched.onSuccess((json) => openAiImageResponse
|
|
131
|
+
.validate(json)
|
|
132
|
+
.withErrorFormat((msg) => `OpenAI images API response: ${msg}`)
|
|
133
|
+
.onSuccess((response) => (0, ts_utils_1.succeed)({
|
|
134
|
+
images: response.data.map((item) => (Object.assign({ mimeType: effectiveMimeType, base64: item.b64_json }, (item.revised_prompt !== undefined ? { revisedPrompt: item.revised_prompt } : {}))))
|
|
135
|
+
})));
|
|
136
|
+
}
|
|
137
|
+
/** Builds the JSON /images/generations request; handles outputParamStyle. @internal */
|
|
138
|
+
function callOpenAiImagesGenerations(config, request, headers, resolved, capability, logger, signal) {
|
|
139
|
+
var _a;
|
|
140
|
+
const body = {
|
|
141
|
+
model: config.model,
|
|
142
|
+
prompt: request.prompt,
|
|
143
|
+
n: resolved.n
|
|
144
|
+
};
|
|
145
|
+
// Output format param — conditional on model capability
|
|
146
|
+
if (capability.outputParamStyle === 'response-format') {
|
|
147
|
+
body.response_format = 'b64_json';
|
|
148
|
+
}
|
|
149
|
+
else if (capability.outputParamStyle === 'output-format') {
|
|
150
|
+
body.output_format = (_a = resolved.outputFormat) !== null && _a !== void 0 ? _a : 'png';
|
|
151
|
+
}
|
|
152
|
+
if (resolved.size !== undefined) {
|
|
153
|
+
body.size = resolved.size;
|
|
154
|
+
}
|
|
155
|
+
if (capability.supportsQualityParam && resolved.quality !== undefined) {
|
|
156
|
+
body.quality = resolved.quality;
|
|
157
|
+
}
|
|
158
|
+
if (resolved.seed !== undefined) {
|
|
159
|
+
body.seed = resolved.seed;
|
|
160
|
+
}
|
|
161
|
+
if (resolved.background !== undefined) {
|
|
162
|
+
body.background = resolved.background;
|
|
163
|
+
}
|
|
164
|
+
if (resolved.moderation !== undefined) {
|
|
165
|
+
body.moderation = resolved.moderation;
|
|
166
|
+
}
|
|
167
|
+
if (resolved.outputCompression !== undefined) {
|
|
168
|
+
body.output_compression = resolved.outputCompression;
|
|
169
|
+
}
|
|
170
|
+
if (resolved.otherParams !== undefined) {
|
|
171
|
+
Object.assign(body, resolved.otherParams);
|
|
172
|
+
}
|
|
173
|
+
/* c8 ignore next 1 - optional logger */
|
|
174
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`Image generation: model=${config.model}, n=${resolved.n}`);
|
|
175
|
+
return (0, http_1.fetchJson)(`${config.baseUrl}/images/generations`, headers, body, logger, signal);
|
|
176
|
+
}
|
|
177
|
+
/** Builds the multipart /images/edits request with ref images. @internal */
|
|
178
|
+
async function callOpenAiImagesEdits(config, capability, request, headers, resolved, logger, signal) {
|
|
179
|
+
const refs = request.referenceImages; // callers verify refs.length > 0 before calling this function
|
|
180
|
+
const blobsResult = (0, ts_utils_1.mapResults)(refs.map((ref, i) => attachmentToBlob(ref).withErrorFormat((msg) => `reference image ${i}: ${msg}`)));
|
|
181
|
+
/* c8 ignore next 3 - decode failure unreachable via Node's Buffer.from (silently strips invalid input) */
|
|
182
|
+
if (blobsResult.isFailure()) {
|
|
183
|
+
return (0, ts_utils_1.fail)(blobsResult.message);
|
|
184
|
+
}
|
|
185
|
+
const form = new FormData();
|
|
186
|
+
form.append('model', config.model);
|
|
187
|
+
form.append('prompt', request.prompt);
|
|
188
|
+
form.append('n', String(resolved.n));
|
|
189
|
+
if (capability.outputParamStyle !== 'output-format') {
|
|
190
|
+
form.append('response_format', 'b64_json');
|
|
191
|
+
}
|
|
192
|
+
if (resolved.size !== undefined) {
|
|
193
|
+
form.append('size', resolved.size);
|
|
194
|
+
}
|
|
195
|
+
blobsResult.value.forEach((blob, i) => {
|
|
196
|
+
form.append('image[]', blob, `ref-${i}.${extensionForMimeType(refs[i].mimeType)}`);
|
|
197
|
+
});
|
|
198
|
+
/* c8 ignore next 1 - optional logger */
|
|
199
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`Image edit: model=${config.model}, n=${resolved.n}, refs=${refs.length}`);
|
|
200
|
+
return (0, http_1.fetchMultipart)(`${config.baseUrl}/images/edits`, headers, form, logger, signal);
|
|
201
|
+
}
|
|
202
|
+
/** Calls xAI /images/edits with JSON body (not multipart); up to 3 source images. @internal */
|
|
203
|
+
async function callXaiImagesEdits(config, request, resolved, logger, signal) {
|
|
204
|
+
var _a;
|
|
205
|
+
/* c8 ignore next 1 - defensive: referenceImages always defined when this function is called */
|
|
206
|
+
const refs = (_a = request.referenceImages) !== null && _a !== void 0 ? _a : [];
|
|
207
|
+
if (refs.length > 3) {
|
|
208
|
+
return (0, ts_utils_1.fail)(`xAI image edits supports at most 3 reference images; got ${refs.length}`);
|
|
209
|
+
}
|
|
210
|
+
const images = refs.map((ref) => ({
|
|
211
|
+
type: 'image_url',
|
|
212
|
+
url: `data:${ref.mimeType};base64,${ref.base64}`
|
|
213
|
+
}));
|
|
214
|
+
const body = {
|
|
215
|
+
model: config.model,
|
|
216
|
+
prompt: request.prompt,
|
|
217
|
+
n: resolved.n,
|
|
218
|
+
response_format: 'b64_json',
|
|
219
|
+
image: images
|
|
220
|
+
};
|
|
221
|
+
if (resolved.aspectRatio !== undefined) {
|
|
222
|
+
body.aspect_ratio = resolved.aspectRatio;
|
|
223
|
+
}
|
|
224
|
+
if (resolved.resolution !== undefined) {
|
|
225
|
+
body.resolution = resolved.resolution;
|
|
226
|
+
}
|
|
227
|
+
if (resolved.otherParams !== undefined) {
|
|
228
|
+
Object.assign(body, resolved.otherParams);
|
|
229
|
+
}
|
|
230
|
+
/* c8 ignore next 1 - optional logger */
|
|
231
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`xAI image edit: model=${config.model}, n=${resolved.n}, refs=${refs.length}`);
|
|
232
|
+
return (0, http_1.fetchJson)(`${config.baseUrl}/images/edits`, (0, endpoint_1.bearerAuthHeader)(config.apiKey), body, logger, signal);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Normalizes an xAI images API response (OpenAI-shaped) into the provider-neutral
|
|
236
|
+
* generated-image result.
|
|
237
|
+
*
|
|
238
|
+
* @remarks
|
|
239
|
+
* Shared by the generations path and the edits path. These were two independent
|
|
240
|
+
* copies 160 lines apart — identical but for the receiver name — so the
|
|
241
|
+
* `defaultOutputMimeType` fallback and the error prefix each existed twice, and a
|
|
242
|
+
* fix to one would silently have missed the other.
|
|
243
|
+
* @internal
|
|
244
|
+
*/
|
|
245
|
+
function normalizeXaiImageResponse(json, capability) {
|
|
246
|
+
return openAiImageResponse
|
|
247
|
+
.validate(json)
|
|
248
|
+
.withErrorFormat((msg) => `xAI images API response: ${msg}`)
|
|
249
|
+
.onSuccess((response) => (0, ts_utils_1.succeed)({
|
|
250
|
+
images: response.data.map((item) => {
|
|
251
|
+
var _a;
|
|
252
|
+
return ({
|
|
253
|
+
mimeType: (_a = capability.defaultOutputMimeType) !== null && _a !== void 0 ? _a : 'image/jpeg',
|
|
254
|
+
base64: item.b64_json
|
|
255
|
+
});
|
|
256
|
+
})
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
259
|
+
/** Calls xAI /images/generations; uses aspect_ratio instead of size. @internal */
|
|
260
|
+
async function callXaiImageGeneration(config, request, capability, resolved, logger, signal) {
|
|
261
|
+
const headers = (0, endpoint_1.bearerAuthHeader)(config.apiKey);
|
|
262
|
+
const body = {
|
|
263
|
+
model: config.model,
|
|
264
|
+
prompt: request.prompt,
|
|
265
|
+
n: resolved.n,
|
|
266
|
+
response_format: 'b64_json'
|
|
267
|
+
};
|
|
268
|
+
if (resolved.aspectRatio !== undefined) {
|
|
269
|
+
body.aspect_ratio = resolved.aspectRatio;
|
|
270
|
+
}
|
|
271
|
+
if (resolved.resolution !== undefined) {
|
|
272
|
+
body.resolution = resolved.resolution;
|
|
273
|
+
}
|
|
274
|
+
if (resolved.otherParams !== undefined) {
|
|
275
|
+
Object.assign(body, resolved.otherParams);
|
|
276
|
+
}
|
|
277
|
+
/* c8 ignore next 1 - optional logger */
|
|
278
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`xAI image generation: model=${config.model}, n=${resolved.n}`);
|
|
279
|
+
const fetched = await (0, http_1.fetchJson)(`${config.baseUrl}/images/generations`, headers, body, logger, signal);
|
|
280
|
+
return fetched.onSuccess((json) => normalizeXaiImageResponse(json, capability));
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Gemini `finishReason` values that indicate a normal terminal completion rather
|
|
284
|
+
* than a refusal. `STOP` is set on every successful generation (and on completions
|
|
285
|
+
* that return a text part instead of an image); `MAX_TOKENS` is a benign truncation.
|
|
286
|
+
* A candidate carrying only one of these is NOT a decline — treating it as one would
|
|
287
|
+
* mislabel an ordinary no-image outcome as a policy refusal. @internal
|
|
288
|
+
*/
|
|
289
|
+
const benignGeminiImageFinishReasons = new Set(['STOP', 'MAX_TOKENS']);
|
|
290
|
+
/** Calls Gemini :generateContent for image output; accepts ref images as inlineData. @internal */
|
|
291
|
+
async function callGeminiImageOutGeneration(config, request, resolved, logger, signal) {
|
|
292
|
+
var _a;
|
|
293
|
+
const url = `${config.baseUrl}/models/${config.model}:generateContent`;
|
|
294
|
+
const refs = (_a = request.referenceImages) !== null && _a !== void 0 ? _a : [];
|
|
295
|
+
const parts = [{ text: request.prompt }];
|
|
296
|
+
for (const ref of refs) {
|
|
297
|
+
parts.push({ inlineData: { mimeType: ref.mimeType, data: ref.base64 } });
|
|
298
|
+
}
|
|
299
|
+
const generationConfig = {};
|
|
300
|
+
if (resolved.geminiAspectRatio !== undefined) {
|
|
301
|
+
generationConfig.imageConfig = { aspectRatio: resolved.geminiAspectRatio };
|
|
302
|
+
}
|
|
303
|
+
if (resolved.otherParams !== undefined) {
|
|
304
|
+
Object.assign(generationConfig, resolved.otherParams);
|
|
305
|
+
}
|
|
306
|
+
const body = { contents: [{ role: 'user', parts }] };
|
|
307
|
+
if (Object.keys(generationConfig).length > 0) {
|
|
308
|
+
body.generationConfig = generationConfig;
|
|
309
|
+
}
|
|
310
|
+
const headers = (0, endpoint_1.geminiAuthHeader)(config.apiKey);
|
|
311
|
+
/* c8 ignore next 1 - optional logger */
|
|
312
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`Gemini image-out: model=${config.model}, refs=${refs.length}`);
|
|
313
|
+
return (await (0, http_1.fetchJson)(url, headers, body, logger, signal)).onSuccess((json) => geminiImageOutResponse
|
|
314
|
+
.validate(json)
|
|
315
|
+
.withErrorFormat((msg) => `Gemini image API response: ${msg}`)
|
|
316
|
+
.onSuccess((response) => {
|
|
317
|
+
var _a, _b;
|
|
318
|
+
const images = [];
|
|
319
|
+
for (const candidate of response.candidates) {
|
|
320
|
+
for (const part of (_b = (_a = candidate.content) === null || _a === void 0 ? void 0 : _a.parts) !== null && _b !== void 0 ? _b : []) {
|
|
321
|
+
if (part.inlineData) {
|
|
322
|
+
images.push({
|
|
323
|
+
mimeType: part.inlineData.mimeType,
|
|
324
|
+
base64: part.inlineData.data
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (images.length === 0) {
|
|
330
|
+
// A candidate with no image parts is a *decline* only when it carries a
|
|
331
|
+
// refusal-shaped finishReason — i.e. present and not a benign terminal reason
|
|
332
|
+
// (`STOP`/`MAX_TOKENS`). A normal completion that emitted text-instead-of-image
|
|
333
|
+
// carries `finishReason: 'STOP'` and must fall through to the no-image message.
|
|
334
|
+
const declined = response.candidates.find((candidate) => candidate.finishReason !== undefined &&
|
|
335
|
+
!benignGeminiImageFinishReasons.has(candidate.finishReason));
|
|
336
|
+
if ((declined === null || declined === void 0 ? void 0 : declined.finishReason) !== undefined) {
|
|
337
|
+
// Truthiness (not `!== undefined`) so an empty-string finishMessage is treated
|
|
338
|
+
// as "no message" and produces no dangling ` — ` separator.
|
|
339
|
+
const suffix = declined.finishMessage ? ` — ${declined.finishMessage}` : '';
|
|
340
|
+
return (0, ts_utils_1.fail)(`Gemini image generation declined: ${declined.finishReason}${suffix}`);
|
|
341
|
+
}
|
|
342
|
+
return (0, ts_utils_1.fail)('Gemini image API response: no image parts in response');
|
|
343
|
+
}
|
|
344
|
+
return (0, ts_utils_1.succeed)({ images });
|
|
345
|
+
}));
|
|
346
|
+
}
|
|
347
|
+
// ============================================================================
|
|
348
|
+
// Image generation — dispatcher
|
|
349
|
+
// ============================================================================
|
|
350
|
+
/**
|
|
351
|
+
* Calls the appropriate image-generation API for a given provider. Routes by the
|
|
352
|
+
* `format` field of the resolved {@link IAiImageModelCapability}:
|
|
353
|
+
* `'openai-images'`, `'xai-images'`, `'xai-images-edits'`, or
|
|
354
|
+
* `'gemini-image-out'`. Rejects up front if `referenceImages` is set but the
|
|
355
|
+
* capability does not declare `acceptsImageReferenceInput`.
|
|
356
|
+
* @param params - Request parameters including descriptor, API key, and prompt
|
|
357
|
+
* @public
|
|
358
|
+
*/
|
|
359
|
+
async function callProviderImageGeneration(params) {
|
|
360
|
+
var _a, _b, _c;
|
|
361
|
+
const { descriptor, apiKey, params: request, modelOverride, logger, signal, endpoint } = params;
|
|
362
|
+
if (!(0, registry_1.supportsImageGeneration)(descriptor)) {
|
|
363
|
+
return (0, ts_utils_1.fail)(`provider "${descriptor.id}" does not support image generation`);
|
|
364
|
+
}
|
|
365
|
+
const baseUrlResult = (0, endpoint_1.resolveEffectiveBaseUrl)(descriptor, endpoint);
|
|
366
|
+
if (baseUrlResult.isFailure()) {
|
|
367
|
+
return (0, ts_utils_1.fail)(baseUrlResult.message);
|
|
368
|
+
}
|
|
369
|
+
const modelResult = (0, model_1.resolveProviderModel)(descriptor, modelOverride, 'image');
|
|
370
|
+
if (modelResult.isFailure()) {
|
|
371
|
+
return (0, ts_utils_1.fail)(modelResult.message);
|
|
372
|
+
}
|
|
373
|
+
const model = modelResult.value;
|
|
374
|
+
const capability = (0, registry_1.resolveImageCapability)(descriptor, model);
|
|
375
|
+
if (capability === undefined) {
|
|
376
|
+
return (0, ts_utils_1.fail)(`provider "${descriptor.id}" does not support image generation for model "${model}"`);
|
|
377
|
+
}
|
|
378
|
+
if (((_b = (_a = request.referenceImages) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 && !capability.acceptsImageReferenceInput) {
|
|
379
|
+
return (0, ts_utils_1.fail)(`model "${model}" does not support reference images`);
|
|
380
|
+
}
|
|
381
|
+
const resolved = (0, imageOptionsResolver_1.resolveImageOptions)(model, capability, request.options);
|
|
382
|
+
const validationResult = (0, imageOptionsResolver_1.validateResolvedOptions)(model, capability, resolved);
|
|
383
|
+
if (validationResult.isFailure()) {
|
|
384
|
+
return (0, ts_utils_1.fail)(validationResult.message);
|
|
385
|
+
}
|
|
386
|
+
const config = {
|
|
387
|
+
baseUrl: baseUrlResult.value,
|
|
388
|
+
apiKey,
|
|
389
|
+
model
|
|
390
|
+
};
|
|
391
|
+
/* c8 ignore next 6 - optional logger diagnostic output */
|
|
392
|
+
if (logger) {
|
|
393
|
+
logger.info(`AI image generation: provider=${descriptor.id}, format=${capability.format}, ` +
|
|
394
|
+
`model=${config.model}`);
|
|
395
|
+
}
|
|
396
|
+
switch (capability.format) {
|
|
397
|
+
case 'openai-images':
|
|
398
|
+
return callOpenAiImageGeneration(config, request, capability, resolved, logger, signal);
|
|
399
|
+
case 'xai-images':
|
|
400
|
+
return callXaiImageGeneration(config, request, capability, resolved, logger, signal);
|
|
401
|
+
case 'xai-images-edits': {
|
|
402
|
+
const refs = (_c = request.referenceImages) !== null && _c !== void 0 ? _c : [];
|
|
403
|
+
if (refs.length > 0) {
|
|
404
|
+
const editsResult = await callXaiImagesEdits(config, request, resolved, logger, signal);
|
|
405
|
+
return editsResult.onSuccess((json) => normalizeXaiImageResponse(json, capability));
|
|
406
|
+
}
|
|
407
|
+
return callXaiImageGeneration(config, request, capability, resolved, logger, signal);
|
|
408
|
+
}
|
|
409
|
+
case 'gemini-image-out':
|
|
410
|
+
return callGeminiImageOutGeneration(config, request, resolved, logger, signal);
|
|
411
|
+
/* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */
|
|
412
|
+
default: {
|
|
413
|
+
const _exhaustive = capability.format;
|
|
414
|
+
return (0, ts_utils_1.fail)(`unsupported image API format: ${String(_exhaustive)}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
// ============================================================================
|
|
419
|
+
// Proxied image generation
|
|
420
|
+
// ============================================================================
|
|
421
|
+
/**
|
|
422
|
+
* Calls the image-generation endpoint on a proxy server instead of calling
|
|
423
|
+
* the provider API directly from the browser.
|
|
424
|
+
* Endpoint: `POST ${proxyUrl}/api/ai/image-generation`. Request body:
|
|
425
|
+
* `{providerId, apiKey, params, modelOverride?}`. The proxy handles descriptor
|
|
426
|
+
* lookup, model resolution, provider dispatch, and response normalization
|
|
427
|
+
* (including repackaging `referenceImages` for the upstream wire format).
|
|
428
|
+
* Error body `{error: string}` is surfaced as `proxy: ${error}`.
|
|
429
|
+
* @param proxyUrl - Base URL of the proxy server
|
|
430
|
+
* @param params - Same parameters as {@link callProviderImageGeneration}
|
|
431
|
+
* @public
|
|
432
|
+
*/
|
|
433
|
+
async function callProxiedImageGeneration(proxyUrl, params) {
|
|
434
|
+
const { descriptor, apiKey, params: request, modelOverride, logger, signal } = params;
|
|
435
|
+
const body = {
|
|
436
|
+
providerId: descriptor.id,
|
|
437
|
+
apiKey,
|
|
438
|
+
params: request
|
|
439
|
+
};
|
|
440
|
+
if (modelOverride !== undefined) {
|
|
441
|
+
body.modelOverride = modelOverride;
|
|
442
|
+
}
|
|
443
|
+
/* c8 ignore next 1 - optional logger */
|
|
444
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`AI image proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);
|
|
445
|
+
const url = `${proxyUrl}/api/ai/image-generation`;
|
|
446
|
+
const jsonResult = await (0, http_1.fetchJson)(url, {}, body, logger, signal);
|
|
447
|
+
if (jsonResult.isFailure()) {
|
|
448
|
+
return (0, ts_utils_1.fail)(jsonResult.message);
|
|
449
|
+
}
|
|
450
|
+
const response = jsonResult.value;
|
|
451
|
+
if (typeof response.error === 'string') {
|
|
452
|
+
return (0, ts_utils_1.fail)(`proxy: ${response.error}`);
|
|
453
|
+
}
|
|
454
|
+
return proxiedImageGenerationResponse
|
|
455
|
+
.validate(response)
|
|
456
|
+
.withErrorFormat((msg) => `proxy returned invalid response: ${msg}`);
|
|
457
|
+
}
|
|
458
|
+
//# sourceMappingURL=imageGenerationClient.js.map
|