@launchdarkly/server-sdk-ai 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +68 -0
  3. package/dist/LDAIClientImpl.d.ts +11 -0
  4. package/dist/LDAIClientImpl.d.ts.map +1 -0
  5. package/dist/LDAIClientImpl.js +35 -0
  6. package/dist/LDAIClientImpl.js.map +1 -0
  7. package/dist/LDAIConfigTrackerImpl.d.ts +40 -0
  8. package/dist/LDAIConfigTrackerImpl.d.ts.map +1 -0
  9. package/dist/LDAIConfigTrackerImpl.js +79 -0
  10. package/dist/LDAIConfigTrackerImpl.js.map +1 -0
  11. package/dist/LDClientMin.d.ts +10 -0
  12. package/dist/LDClientMin.d.ts.map +1 -0
  13. package/dist/LDClientMin.js +3 -0
  14. package/dist/LDClientMin.js.map +1 -0
  15. package/dist/api/LDAIClient.d.ts +62 -0
  16. package/dist/api/LDAIClient.d.ts.map +1 -0
  17. package/dist/api/LDAIClient.js +3 -0
  18. package/dist/api/LDAIClient.js.map +1 -0
  19. package/dist/api/config/LDAIConfig.d.ts +58 -0
  20. package/dist/api/config/LDAIConfig.d.ts.map +1 -0
  21. package/dist/api/config/LDAIConfig.js +3 -0
  22. package/dist/api/config/LDAIConfig.js.map +1 -0
  23. package/dist/api/config/LDAIConfigTracker.d.ts +71 -0
  24. package/dist/api/config/LDAIConfigTracker.d.ts.map +1 -0
  25. package/dist/api/config/LDAIConfigTracker.js +3 -0
  26. package/dist/api/config/LDAIConfigTracker.js.map +1 -0
  27. package/dist/api/config/index.d.ts +3 -0
  28. package/dist/api/config/index.d.ts.map +1 -0
  29. package/dist/api/config/index.js +18 -0
  30. package/dist/api/config/index.js.map +1 -0
  31. package/dist/api/index.d.ts +4 -0
  32. package/dist/api/index.d.ts.map +1 -0
  33. package/dist/api/index.js +20 -0
  34. package/dist/api/index.js.map +1 -0
  35. package/dist/api/metrics/BedrockTokenUsage.d.ts +7 -0
  36. package/dist/api/metrics/BedrockTokenUsage.d.ts.map +1 -0
  37. package/dist/api/metrics/BedrockTokenUsage.js +12 -0
  38. package/dist/api/metrics/BedrockTokenUsage.js.map +1 -0
  39. package/dist/api/metrics/LDFeedbackKind.d.ts +14 -0
  40. package/dist/api/metrics/LDFeedbackKind.d.ts.map +1 -0
  41. package/dist/api/metrics/LDFeedbackKind.js +18 -0
  42. package/dist/api/metrics/LDFeedbackKind.js.map +1 -0
  43. package/dist/api/metrics/LDTokenUsage.d.ts +18 -0
  44. package/dist/api/metrics/LDTokenUsage.d.ts.map +1 -0
  45. package/dist/api/metrics/LDTokenUsage.js +3 -0
  46. package/dist/api/metrics/LDTokenUsage.js.map +1 -0
  47. package/dist/api/metrics/OpenAiUsage.d.ts +7 -0
  48. package/dist/api/metrics/OpenAiUsage.d.ts.map +1 -0
  49. package/dist/api/metrics/OpenAiUsage.js +13 -0
  50. package/dist/api/metrics/OpenAiUsage.js.map +1 -0
  51. package/dist/api/metrics/UnderScoreTokenUsage.d.ts +3 -0
  52. package/dist/api/metrics/UnderScoreTokenUsage.d.ts.map +1 -0
  53. package/dist/api/metrics/UnderScoreTokenUsage.js +12 -0
  54. package/dist/api/metrics/UnderScoreTokenUsage.js.map +1 -0
  55. package/dist/api/metrics/index.d.ts +5 -0
  56. package/dist/api/metrics/index.d.ts.map +1 -0
  57. package/dist/api/metrics/index.js +21 -0
  58. package/dist/api/metrics/index.js.map +1 -0
  59. package/dist/index.d.ts +10 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +29 -0
  62. package/dist/index.js.map +1 -0
  63. package/docs/.nojekyll +1 -0
  64. package/docs/assets/highlight.css +85 -0
  65. package/docs/assets/icons.js +18 -0
  66. package/docs/assets/icons.svg +1 -0
  67. package/docs/assets/main.js +60 -0
  68. package/docs/assets/navigation.js +1 -0
  69. package/docs/assets/search.js +1 -0
  70. package/docs/assets/style.css +1493 -0
  71. package/docs/enums/LDFeedbackKind.html +6 -0
  72. package/docs/functions/createBedrockTokenUsage.html +1 -0
  73. package/docs/functions/createUnderscoreTokenUsage.html +1 -0
  74. package/docs/functions/initAi.html +4 -0
  75. package/docs/index.html +12 -0
  76. package/docs/interfaces/LDAIClient.html +25 -0
  77. package/docs/interfaces/LDAIConfig.html +8 -0
  78. package/docs/interfaces/LDAIConfigTracker.html +26 -0
  79. package/docs/interfaces/LDGenerationConfig.html +6 -0
  80. package/docs/interfaces/LDMessage.html +6 -0
  81. package/docs/interfaces/LDModelConfig.html +5 -0
  82. package/docs/interfaces/LDTokenUsage.html +8 -0
  83. package/package.json +53 -0
  84. package/src/LDAIClientImpl.ts +68 -0
  85. package/src/LDAIConfigTrackerImpl.ts +102 -0
  86. package/src/LDClientMin.ts +16 -0
  87. package/src/api/LDAIClient.ts +70 -0
  88. package/src/api/config/LDAIConfig.ts +64 -0
  89. package/src/api/config/LDAIConfigTracker.ts +79 -0
  90. package/src/api/config/index.ts +2 -0
  91. package/src/api/index.ts +3 -0
  92. package/src/api/metrics/BedrockTokenUsage.ts +13 -0
  93. package/src/api/metrics/LDFeedbackKind.ts +13 -0
  94. package/src/api/metrics/LDTokenUsage.ts +19 -0
  95. package/src/api/metrics/OpenAiUsage.ts +13 -0
  96. package/src/api/metrics/UnderScoreTokenUsage.ts +9 -0
  97. package/src/api/metrics/index.ts +4 -0
  98. package/src/index.ts +14 -0
  99. package/tsconfig.eslint.json +5 -0
  100. package/tsconfig.json +21 -0
  101. package/tsconfig.ref.json +7 -0
  102. package/typedoc.json +5 -0
@@ -0,0 +1,5 @@
1
+ <!DOCTYPE html><html class="default" lang="en"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>LDModelConfig | @launchdarkly/server-sdk-ai - v0.1.0</title><meta name="description" content="Documentation for @launchdarkly/server-sdk-ai"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search" data-base=".."><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">@launchdarkly/server-sdk-ai - v0.1.0</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../index.html">@launchdarkly/server-sdk-ai</a></li><li><a href="LDModelConfig.html">LDModelConfig</a></li></ul><h1>Interface LDModelConfig</h1></div><section class="tsd-panel tsd-comment"><div class="tsd-comment tsd-typography"><p>Configuration related to the model.</p>
2
+ </div><div class="tsd-comment tsd-typography"></div></section><div class="tsd-signature"><span class="tsd-signature-keyword">interface </span><span class="tsd-kind-interface">LDModelConfig</span> <span class="tsd-signature-symbol">{ </span><br/><span>    </span><a class="tsd-kind-property" href="LDModelConfig.html#modelId">modelId</a><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">; </span><br/><span>    </span>[<span class="tsd-kind-index-signature">index</span>: <span class="tsd-signature-type">string</span>]<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">; </span><br/><span class="tsd-signature-symbol">}</span></div><section class="tsd-panel"><h4 class="tsd-before-signature">Indexable</h4><ul class="tsd-signatures"><li class="tsd-index-signature"><div class="tsd-signature"><span class="tsd-signature-symbol">[</span><span class="tsd-kind-parameter">index</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]: </span><span class="tsd-signature-type">unknown</span></div><div class="tsd-comment tsd-typography"><p>And additional model specific information.</p>
3
+ </div><div class="tsd-comment tsd-typography"></div></li></ul></section><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/launchdarkly/js-core/blob/cc35e9ed1c2a3fe9d6cacb7e9654b9160e90879c/packages/sdk/server-ai/src/api/config/LDAIConfig.ts#L6">api/config/LDAIConfig.ts:6</a></li></ul></aside><section class="tsd-panel-group tsd-index-group"><section class="tsd-panel tsd-index-panel"><details class="tsd-index-content tsd-accordion" open><summary class="tsd-accordion-summary tsd-index-summary"><h5 class="tsd-index-heading uppercase" role="button" aria-expanded="false" tabIndex="0"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-chevronSmall"></use></svg> Index</h5></summary><div class="tsd-accordion-details"><section class="tsd-index-section"><h3 class="tsd-index-heading">Properties</h3><div class="tsd-index-list"><a href="LDModelConfig.html#modelId" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>model<wbr/>Id?</span></a>
4
+ </div></section></div></details></section></section><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Properties"><h2><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg> Properties</h2></summary><section><section class="tsd-panel tsd-member"><a id="modelId" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><code class="tsd-tag">Optional</code><span>model<wbr/>Id</span><a href="#modelId" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">model<wbr/>Id</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span></div><div class="tsd-comment tsd-typography"><p>The ID of the model.</p>
5
+ </div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/launchdarkly/js-core/blob/cc35e9ed1c2a3fe9d6cacb7e9654b9160e90879c/packages/sdk/server-ai/src/api/config/LDAIConfig.ts#L10">api/config/LDAIConfig.ts:10</a></li></ul></aside></section></section></details></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="tsd-otp-Properties"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Properties</summary><div><a href="#modelId" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>model<wbr/>Id</span></a></div></details></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="../index.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1"></use></svg><span>@launchdarkly/server-sdk-ai - v0.1.0</span></a><ul class="tsd-small-nested-navigation" id="tsd-nav-container" data-base=".."><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
@@ -0,0 +1,8 @@
1
+ <!DOCTYPE html><html class="default" lang="en"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>LDTokenUsage | @launchdarkly/server-sdk-ai - v0.1.0</title><meta name="description" content="Documentation for @launchdarkly/server-sdk-ai"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search" data-base=".."><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">@launchdarkly/server-sdk-ai - v0.1.0</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../index.html">@launchdarkly/server-sdk-ai</a></li><li><a href="LDTokenUsage.html">LDTokenUsage</a></li></ul><h1>Interface LDTokenUsage</h1></div><section class="tsd-panel tsd-comment"><div class="tsd-comment tsd-typography"><p>Information about token usage.</p>
2
+ </div><div class="tsd-comment tsd-typography"></div></section><div class="tsd-signature"><span class="tsd-signature-keyword">interface </span><span class="tsd-kind-interface">LDTokenUsage</span> <span class="tsd-signature-symbol">{ </span><br/><span>    </span><a class="tsd-kind-property" href="LDTokenUsage.html#input">input</a><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span><br/><span>    </span><a class="tsd-kind-property" href="LDTokenUsage.html#output">output</a><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span><br/><span>    </span><a class="tsd-kind-property" href="LDTokenUsage.html#total">total</a><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">; </span><br/><span class="tsd-signature-symbol">}</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/launchdarkly/js-core/blob/cc35e9ed1c2a3fe9d6cacb7e9654b9160e90879c/packages/sdk/server-ai/src/api/metrics/LDTokenUsage.ts#L4">api/metrics/LDTokenUsage.ts:4</a></li></ul></aside><section class="tsd-panel-group tsd-index-group"><section class="tsd-panel tsd-index-panel"><details class="tsd-index-content tsd-accordion" open><summary class="tsd-accordion-summary tsd-index-summary"><h5 class="tsd-index-heading uppercase" role="button" aria-expanded="false" tabIndex="0"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-chevronSmall"></use></svg> Index</h5></summary><div class="tsd-accordion-details"><section class="tsd-index-section"><h3 class="tsd-index-heading">Properties</h3><div class="tsd-index-list"><a href="LDTokenUsage.html#input" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>input</span></a>
3
+ <a href="LDTokenUsage.html#output" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>output</span></a>
4
+ <a href="LDTokenUsage.html#total" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>total</span></a>
5
+ </div></section></div></details></section></section><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Properties"><h2><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg> Properties</h2></summary><section><section class="tsd-panel tsd-member"><a id="input" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>input</span><a href="#input" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">input</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><div class="tsd-comment tsd-typography"><p>Number of tokens in the input.</p>
6
+ </div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/launchdarkly/js-core/blob/cc35e9ed1c2a3fe9d6cacb7e9654b9160e90879c/packages/sdk/server-ai/src/api/metrics/LDTokenUsage.ts#L13">api/metrics/LDTokenUsage.ts:13</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="output" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>output</span><a href="#output" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">output</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><div class="tsd-comment tsd-typography"><p>Number of tokens in the output.</p>
7
+ </div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/launchdarkly/js-core/blob/cc35e9ed1c2a3fe9d6cacb7e9654b9160e90879c/packages/sdk/server-ai/src/api/metrics/LDTokenUsage.ts#L18">api/metrics/LDTokenUsage.ts:18</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="total" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>total</span><a href="#total" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">total</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><div class="tsd-comment tsd-typography"><p>Combined token usage.</p>
8
+ </div><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/launchdarkly/js-core/blob/cc35e9ed1c2a3fe9d6cacb7e9654b9160e90879c/packages/sdk/server-ai/src/api/metrics/LDTokenUsage.ts#L8">api/metrics/LDTokenUsage.ts:8</a></li></ul></aside></section></section></details></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="tsd-otp-Properties"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Properties</summary><div><a href="#input" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>input</span></a><a href="#output" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>output</span></a><a href="#total" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>total</span></a></div></details></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="../index.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1"></use></svg><span>@launchdarkly/server-sdk-ai - v0.1.0</span></a><ul class="tsd-small-nested-navigation" id="tsd-nav-container" data-base=".."><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@launchdarkly/server-sdk-ai",
3
+ "version": "0.1.0",
4
+ "description": "LaunchDarkly AI SDK for Server-Side JavaScript",
5
+ "homepage": "https://github.com/launchdarkly/js-core/tree/main/packages/sdk/server-ai",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/launchdarkly/js-core.git"
9
+ },
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "type": "commonjs",
13
+ "scripts": {
14
+ "build": "npx tsc",
15
+ "lint": "npx eslint . --ext .ts",
16
+ "prettier": "prettier --write '**/*.@(js|ts|tsx|json|css)' --ignore-path ../../../.prettierignore",
17
+ "lint:fix": "yarn run lint --fix",
18
+ "check": "yarn prettier && yarn lint && yarn build && yarn test",
19
+ "test": "echo No tests added yet."
20
+ },
21
+ "keywords": [
22
+ "launchdarkly",
23
+ "ai",
24
+ "llm"
25
+ ],
26
+ "author": "LaunchDarkly",
27
+ "license": "Apache-2.0",
28
+ "dependencies": {
29
+ "mustache": "^4.2.0"
30
+ },
31
+ "devDependencies": {
32
+ "@launchdarkly/js-server-sdk-common": "2.9.0",
33
+ "@trivago/prettier-plugin-sort-imports": "^4.1.1",
34
+ "@types/jest": "^29.5.3",
35
+ "@types/mustache": "^4.2.5",
36
+ "@typescript-eslint/eslint-plugin": "^6.20.0",
37
+ "@typescript-eslint/parser": "^6.20.0",
38
+ "eslint": "^8.45.0",
39
+ "eslint-config-airbnb-base": "^15.0.0",
40
+ "eslint-config-airbnb-typescript": "^17.1.0",
41
+ "eslint-config-prettier": "^8.8.0",
42
+ "eslint-plugin-import": "^2.27.5",
43
+ "eslint-plugin-jest": "^27.6.3",
44
+ "eslint-plugin-prettier": "^5.0.0",
45
+ "jest": "^29.6.1",
46
+ "prettier": "^3.0.0",
47
+ "ts-jest": "^29.1.1",
48
+ "typescript": "5.1.6"
49
+ },
50
+ "peerDependencies": {
51
+ "@launchdarkly/js-server-sdk-common": "2.x"
52
+ }
53
+ }
@@ -0,0 +1,68 @@
1
+ import * as Mustache from 'mustache';
2
+
3
+ import { LDContext } from '@launchdarkly/js-server-sdk-common';
4
+
5
+ import { LDAIConfig, LDGenerationConfig, LDMessage, LDModelConfig } from './api/config';
6
+ import { LDAIClient } from './api/LDAIClient';
7
+ import { LDAIConfigTrackerImpl } from './LDAIConfigTrackerImpl';
8
+ import { LDClientMin } from './LDClientMin';
9
+
10
+ /**
11
+ * Metadata assorted with a model configuration variation.
12
+ */
13
+ interface LDMeta {
14
+ versionKey: string;
15
+ enabled: boolean;
16
+ }
17
+
18
+ /**
19
+ * Interface for the model configuration variation returned by LaunchDarkly. This is the internal
20
+ * typing and not meant for exposure to the application developer.
21
+ */
22
+ interface VariationContent {
23
+ model?: LDModelConfig;
24
+ prompt?: LDMessage[];
25
+ _ldMeta?: LDMeta;
26
+ }
27
+
28
+ export class LDAIClientImpl implements LDAIClient {
29
+ constructor(private _ldClient: LDClientMin) {}
30
+
31
+ interpolateTemplate(template: string, variables: Record<string, unknown>): string {
32
+ return Mustache.render(template, variables, undefined, { escape: (item: any) => item });
33
+ }
34
+
35
+ async modelConfig<TDefault extends LDGenerationConfig>(
36
+ key: string,
37
+ context: LDContext,
38
+ defaultValue: TDefault,
39
+ variables?: Record<string, unknown>,
40
+ ): Promise<LDAIConfig> {
41
+ const value: VariationContent = await this._ldClient.variation(key, context, defaultValue);
42
+ // We are going to modify the contents before returning them, so we make a copy.
43
+ // This isn't a deep copy and the application developer should not modify the returned content.
44
+ const config: LDGenerationConfig = { ...value };
45
+ const allVariables = { ...variables, ldctx: context };
46
+
47
+ if (value.prompt) {
48
+ config.prompt = value.prompt.map((entry: any) => ({
49
+ ...entry,
50
+ content: this.interpolateTemplate(entry.content, allVariables),
51
+ }));
52
+ }
53
+
54
+ return {
55
+ config,
56
+ // eslint-disable-next-line no-underscore-dangle
57
+ tracker: new LDAIConfigTrackerImpl(
58
+ this._ldClient,
59
+ key,
60
+ // eslint-disable-next-line no-underscore-dangle
61
+ value._ldMeta?.versionKey ?? '',
62
+ context,
63
+ ),
64
+ // eslint-disable-next-line no-underscore-dangle
65
+ enabled: !!value._ldMeta?.enabled,
66
+ };
67
+ }
68
+ }
@@ -0,0 +1,102 @@
1
+ import { LDContext } from '@launchdarkly/js-server-sdk-common';
2
+
3
+ import { LDAIConfigTracker } from './api/config';
4
+ import { createBedrockTokenUsage, LDFeedbackKind, LDTokenUsage } from './api/metrics';
5
+ import { createOpenAiUsage } from './api/metrics/OpenAiUsage';
6
+ import { LDClientMin } from './LDClientMin';
7
+
8
+ export class LDAIConfigTrackerImpl implements LDAIConfigTracker {
9
+ constructor(
10
+ private _ldClient: LDClientMin,
11
+ private _configKey: string,
12
+ private _versionKey: string,
13
+ private _context: LDContext,
14
+ ) {}
15
+
16
+ private _getTrackData(): { versionKey: string; configKey: string } {
17
+ return {
18
+ versionKey: this._versionKey,
19
+ configKey: this._configKey,
20
+ };
21
+ }
22
+
23
+ trackDuration(duration: number): void {
24
+ this._ldClient.track('$ld:ai:duration:total', this._context, this._getTrackData(), duration);
25
+ }
26
+
27
+ async trackDurationOf<TRes>(func: () => Promise<TRes>): Promise<TRes> {
28
+ const startTime = Date.now();
29
+ const result = await func();
30
+ const endTime = Date.now();
31
+ const duration = endTime - startTime; // duration in milliseconds
32
+ this.trackDuration(duration);
33
+ return result;
34
+ }
35
+
36
+ trackFeedback(feedback: { kind: LDFeedbackKind }): void {
37
+ if (feedback.kind === LDFeedbackKind.Positive) {
38
+ this._ldClient.track('$ld:ai:feedback:user:positive', this._context, this._getTrackData(), 1);
39
+ } else if (feedback.kind === LDFeedbackKind.Negative) {
40
+ this._ldClient.track('$ld:ai:feedback:user:negative', this._context, this._getTrackData(), 1);
41
+ }
42
+ }
43
+
44
+ trackSuccess(): void {
45
+ this._ldClient.track('$ld:ai:generation', this._context, this._getTrackData(), 1);
46
+ }
47
+
48
+ async trackOpenAI<
49
+ TRes extends {
50
+ usage?: {
51
+ total_tokens?: number;
52
+ prompt_tokens?: number;
53
+ completion_tokens?: number;
54
+ };
55
+ },
56
+ >(func: () => Promise<TRes>): Promise<TRes> {
57
+ const result = await this.trackDurationOf(func);
58
+ this.trackSuccess();
59
+ if (result.usage) {
60
+ this.trackTokens(createOpenAiUsage(result.usage));
61
+ }
62
+ return result;
63
+ }
64
+
65
+ trackBedrockConverse<
66
+ TRes extends {
67
+ $metadata: { httpStatusCode?: number };
68
+ metrics?: { latencyMs?: number };
69
+ usage?: {
70
+ inputTokens?: number;
71
+ outputTokens?: number;
72
+ totalTokens?: number;
73
+ };
74
+ },
75
+ >(res: TRes): TRes {
76
+ if (res.$metadata?.httpStatusCode === 200) {
77
+ this.trackSuccess();
78
+ } else if (res.$metadata?.httpStatusCode && res.$metadata.httpStatusCode >= 400) {
79
+ // Potentially add error tracking in the future.
80
+ }
81
+ if (res.metrics && res.metrics.latencyMs) {
82
+ this.trackDuration(res.metrics.latencyMs);
83
+ }
84
+ if (res.usage) {
85
+ this.trackTokens(createBedrockTokenUsage(res.usage));
86
+ }
87
+ return res;
88
+ }
89
+
90
+ trackTokens(tokens: LDTokenUsage): void {
91
+ const trackData = this._getTrackData();
92
+ if (tokens.total > 0) {
93
+ this._ldClient.track('$ld:ai:tokens:total', this._context, trackData, tokens.total);
94
+ }
95
+ if (tokens.input > 0) {
96
+ this._ldClient.track('$ld:ai:tokens:input', this._context, trackData, tokens.input);
97
+ }
98
+ if (tokens.output > 0) {
99
+ this._ldClient.track('$ld:ai:tokens:output', this._context, trackData, tokens.output);
100
+ }
101
+ }
102
+ }
@@ -0,0 +1,16 @@
1
+ import { LDContext, LDFlagValue } from '@launchdarkly/js-server-sdk-common';
2
+
3
+ /**
4
+ * Interface which represents the required interface components for a sever SDK
5
+ * to work with the AI SDK.
6
+ */
7
+ export interface LDClientMin {
8
+ variation(
9
+ key: string,
10
+ context: LDContext,
11
+ defaultValue: LDFlagValue,
12
+ callback?: (err: any, res: LDFlagValue) => void,
13
+ ): Promise<LDFlagValue>;
14
+
15
+ track(key: string, context: LDContext, data?: any, metricValue?: number): void;
16
+ }
@@ -0,0 +1,70 @@
1
+ import { LDContext } from '@launchdarkly/js-server-sdk-common';
2
+
3
+ import { LDAIConfig, LDGenerationConfig } from './config/LDAIConfig';
4
+
5
+ /**
6
+ * Interface for performing AI operations using LaunchDarkly.
7
+ */
8
+
9
+ export interface LDAIClient {
10
+ /**
11
+ * Parses and interpolates a template string with the provided variables.
12
+ *
13
+ * @param template - The template string to be parsed and interpolated.
14
+ * @param variables - An object containing the variables to be used for interpolation.
15
+ * @returns The interpolated string.
16
+ */
17
+ interpolateTemplate(template: string, variables: Record<string, unknown>): string;
18
+
19
+ /**
20
+ * Retrieves and processes a prompt template based on the provided key, LaunchDarkly context, and
21
+ * variables.
22
+ *
23
+ * @param key - A unique identifier for the prompt template. This key is used to fetch the correct
24
+ * prompt from storage or configuration.
25
+ * @param context - The LaunchDarkly context object that contains relevant information about the
26
+ * current environment, user, or session. This context may influence how the prompt is processed
27
+ * or personalized.
28
+ * @param variables - A map of key-value pairs representing dynamic variables to be injected into
29
+ * the prompt template. The keys correspond to placeholders within the template, and the values
30
+ * are the corresponding replacements.
31
+ * @param defaultValue - A fallback value to be used if the prompt template associated with the
32
+ * key is not found or if any errors occur during processing.
33
+ *
34
+ * @returns The processed prompt after all variables have been substituted in the stored prompt
35
+ * template. If the prompt cannot be retrieved or processed, the `defaultValue` is returned.
36
+ *
37
+ * @example
38
+ * ```
39
+ * const key = "welcome_prompt";
40
+ * const context = {...};
41
+ * const variables = {username: 'john'};
42
+ * const defaultValue = {};
43
+ *
44
+ * const result = modelConfig(key, context, defaultValue, variables);
45
+ * // Output:
46
+ * {
47
+ * modelId: "gpt-4o",
48
+ * temperature: 0.2,
49
+ * maxTokens: 4096,
50
+ * userDefinedKey: "myValue",
51
+ * prompt: [
52
+ * {
53
+ * role: "system",
54
+ * content: "You are an amazing GPT."
55
+ * },
56
+ * {
57
+ * role: "user",
58
+ * content: "Explain how you're an amazing GPT."
59
+ * }
60
+ * ]
61
+ * }
62
+ * ```
63
+ */
64
+ modelConfig<TDefault extends LDGenerationConfig>(
65
+ key: string,
66
+ context: LDContext,
67
+ defaultValue: TDefault,
68
+ variables?: Record<string, unknown>,
69
+ ): Promise<LDAIConfig>;
70
+ }
@@ -0,0 +1,64 @@
1
+ import { LDAIConfigTracker } from './LDAIConfigTracker';
2
+
3
+ /**
4
+ * Configuration related to the model.
5
+ */
6
+ export interface LDModelConfig {
7
+ /**
8
+ * The ID of the model.
9
+ */
10
+ modelId?: string;
11
+
12
+ /**
13
+ * And additional model specific information.
14
+ */
15
+ [index: string]: unknown;
16
+ }
17
+
18
+ /**
19
+ * Information about prompts.
20
+ */
21
+ export interface LDMessage {
22
+ /**
23
+ * The role of the prompt.
24
+ */
25
+ role: 'user' | 'assistant' | 'system';
26
+ /**
27
+ * Content for the prompt.
28
+ */
29
+ content: string;
30
+ }
31
+
32
+ /**
33
+ * Configuration which affects generation.
34
+ */
35
+ export interface LDGenerationConfig {
36
+ /**
37
+ * Optional model configuration.
38
+ */
39
+ model?: LDModelConfig;
40
+ /**
41
+ * Optional prompt data.
42
+ */
43
+ prompt?: LDMessage[];
44
+ }
45
+
46
+ /**
47
+ * AI Config value and tracker.
48
+ */
49
+ export interface LDAIConfig {
50
+ /**
51
+ * The result of the AI Config customization.
52
+ */
53
+ config: LDGenerationConfig;
54
+
55
+ /**
56
+ * A tracker which can be used to generate analytics.
57
+ */
58
+ tracker: LDAIConfigTracker;
59
+
60
+ /**
61
+ * Whether the configuration is enabled.
62
+ */
63
+ enabled: boolean;
64
+ }
@@ -0,0 +1,79 @@
1
+ import { LDFeedbackKind, LDTokenUsage } from '../metrics';
2
+
3
+ /**
4
+ * The LDAIConfigTracker is used to track various details about AI operations.
5
+ */
6
+ export interface LDAIConfigTracker {
7
+ /**
8
+ * Track the duration of generation.
9
+ *
10
+ * Ideally this would not include overhead time such as network communication.
11
+ *
12
+ * @param durationMs The duration in milliseconds.
13
+ */
14
+ trackDuration(durationMs: number): void;
15
+
16
+ /**
17
+ * Track information about token usage.
18
+ *
19
+ * @param tokens Token usage information.
20
+ */
21
+ trackTokens(tokens: LDTokenUsage): void;
22
+
23
+ /**
24
+ * Generation was successful.
25
+ */
26
+ trackSuccess(): void;
27
+
28
+ /**
29
+ * Track sentiment about the generation.
30
+ *
31
+ * @param feedback Feedback about the generation.
32
+ */
33
+ trackFeedback(feedback: { kind: LDFeedbackKind }): void;
34
+
35
+ /**
36
+ * Track the duration of execution of the provided function.
37
+ * @param func The function to track the duration of.
38
+ * @returns The result of the function.
39
+ */
40
+ trackDurationOf(func: () => Promise<any>): Promise<any>;
41
+
42
+ /**
43
+ * Track an OpenAI operation.
44
+ *
45
+ * @param func Function which executes the operation.
46
+ * @returns The result of the operation.
47
+ */
48
+ trackOpenAI<
49
+ TRes extends {
50
+ usage?: {
51
+ total_tokens?: number;
52
+ prompt_tokens?: number;
53
+ completion_tokens?: number;
54
+ };
55
+ },
56
+ >(
57
+ func: () => Promise<TRes>,
58
+ ): Promise<TRes>;
59
+
60
+ /**
61
+ * Track an operation which uses Bedrock.
62
+ *
63
+ * @param res The result of the Bedrock operation.
64
+ * @returns The input operation.
65
+ */
66
+ trackBedrockConverse<
67
+ TRes extends {
68
+ $metadata: { httpStatusCode?: number };
69
+ metrics?: { latencyMs?: number };
70
+ usage?: {
71
+ inputTokens?: number;
72
+ outputTokens?: number;
73
+ totalTokens?: number;
74
+ };
75
+ },
76
+ >(
77
+ res: TRes,
78
+ ): TRes;
79
+ }
@@ -0,0 +1,2 @@
1
+ export * from './LDAIConfig';
2
+ export { LDAIConfigTracker } from './LDAIConfigTracker';
@@ -0,0 +1,3 @@
1
+ export * from './config';
2
+ export * from './metrics';
3
+ export * from './LDAIClient';
@@ -0,0 +1,13 @@
1
+ import { LDTokenUsage } from './LDTokenUsage';
2
+
3
+ export function createBedrockTokenUsage(data: {
4
+ totalTokens?: number;
5
+ inputTokens?: number;
6
+ outputTokens?: number;
7
+ }): LDTokenUsage {
8
+ return {
9
+ total: data.totalTokens || 0,
10
+ input: data.inputTokens || 0,
11
+ output: data.outputTokens || 0,
12
+ };
13
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Feedback about the generated content.
3
+ */
4
+ export enum LDFeedbackKind {
5
+ /**
6
+ * The sentiment was positive.
7
+ */
8
+ Positive = 'positive',
9
+ /**
10
+ * The sentiment is negative.
11
+ */
12
+ Negative = 'negative',
13
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Information about token usage.
3
+ */
4
+ export interface LDTokenUsage {
5
+ /**
6
+ * Combined token usage.
7
+ */
8
+ total: number;
9
+
10
+ /**
11
+ * Number of tokens in the input.
12
+ */
13
+ input: number;
14
+
15
+ /**
16
+ * Number of tokens in the output.
17
+ */
18
+ output: number;
19
+ }
@@ -0,0 +1,13 @@
1
+ import { LDTokenUsage } from './LDTokenUsage';
2
+
3
+ export function createOpenAiUsage(data: {
4
+ total_tokens?: number;
5
+ prompt_tokens?: number;
6
+ completion_tokens?: number;
7
+ }): LDTokenUsage {
8
+ return {
9
+ total: data.total_tokens ?? 0,
10
+ input: data.prompt_tokens ?? 0,
11
+ output: data.completion_tokens ?? 0,
12
+ };
13
+ }
@@ -0,0 +1,9 @@
1
+ import { LDTokenUsage } from './LDTokenUsage';
2
+
3
+ export function createUnderscoreTokenUsage(data: any): LDTokenUsage {
4
+ return {
5
+ total: data.total_tokens || 0,
6
+ input: data.prompt_tokens || 0,
7
+ output: data.completion_tokens || 0,
8
+ };
9
+ }
@@ -0,0 +1,4 @@
1
+ export * from './BedrockTokenUsage';
2
+ export * from './LDFeedbackKind';
3
+ export * from './LDTokenUsage';
4
+ export * from './UnderScoreTokenUsage';
package/src/index.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { LDAIClient } from './api/LDAIClient';
2
+ import { LDAIClientImpl } from './LDAIClientImpl';
3
+ import { LDClientMin } from './LDClientMin';
4
+
5
+ /**
6
+ * Initialize a new AI client. This client will be used to perform any AI operations.
7
+ * @param ldClient The base LaunchDarkly client.
8
+ * @returns A new AI client.
9
+ */
10
+ export function initAi(ldClient: LDClientMin): LDAIClient {
11
+ return new LDAIClientImpl(ldClient);
12
+ }
13
+
14
+ export * from './api';
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["/**/*.ts"],
4
+ "exclude": ["node_modules"]
5
+ }