@burtson-labs/bandit-engine 2.0.25 → 2.0.26

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 (134) hide show
  1. package/README.md +3 -2
  2. package/dist/cli/cli.js +2 -2
  3. package/dist/cli/cli.js.map +1 -1
  4. package/dist/index.mjs +3 -3
  5. package/docs/05_cli_quickstart.md +1 -1
  6. package/docs/api_reference/assets/bandit-docs.js +402 -217
  7. package/docs/api_reference/assets/highlight.css +15 -8
  8. package/docs/api_reference/assets/main.js +1 -9
  9. package/docs/api_reference/classes/DebugLogger.html +11 -11
  10. package/docs/api_reference/classes/FeatureFlagService.html +13 -13
  11. package/docs/api_reference/classes/NotificationService.html +10 -10
  12. package/docs/api_reference/classes/StreamingTTSClient.html +9 -9
  13. package/docs/api_reference/classes/VectorDatabaseService.html +24 -24
  14. package/docs/api_reference/classes/VectorMigrationService.html +8 -8
  15. package/docs/api_reference/classes/VoiceService.html +2 -2
  16. package/docs/api_reference/enums/TTSState.html +2 -2
  17. package/docs/api_reference/functions/Chat.html +1 -1
  18. package/docs/api_reference/functions/ChatModal.html +3 -3
  19. package/docs/api_reference/functions/ChatProvider.html +3 -3
  20. package/docs/api_reference/functions/FeatureFlagProvider.html +3 -3
  21. package/docs/api_reference/functions/FeedbackButton.html +3 -3
  22. package/docs/api_reference/functions/FeedbackModal.html +3 -3
  23. package/docs/api_reference/functions/Management.html +1 -1
  24. package/docs/api_reference/functions/NotificationProvider.html +3 -3
  25. package/docs/api_reference/functions/SubscriptionExpiredGuard.html +3 -3
  26. package/docs/api_reference/functions/SubscriptionExpiredModal.html +3 -3
  27. package/docs/api_reference/functions/defineCustomElement.html +1 -1
  28. package/docs/api_reference/functions/getCriticalConfig.html +1 -1
  29. package/docs/api_reference/functions/getFeatureMatrix.html +1 -1
  30. package/docs/api_reference/functions/getStreamingTTSClient.html +1 -1
  31. package/docs/api_reference/functions/getSystemConstants.html +1 -1
  32. package/docs/api_reference/functions/getTTSState.html +1 -1
  33. package/docs/api_reference/functions/handleHttpError.html +1 -1
  34. package/docs/api_reference/functions/handleSubscriptionUpgrade.html +1 -1
  35. package/docs/api_reference/functions/handleValidationError.html +1 -1
  36. package/docs/api_reference/functions/initializeCoreSystem.html +1 -1
  37. package/docs/api_reference/functions/pauseTTS.html +1 -1
  38. package/docs/api_reference/functions/previewTierUpgrade.html +1 -1
  39. package/docs/api_reference/functions/resumeTTS.html +1 -1
  40. package/docs/api_reference/functions/showInfoNotification.html +1 -1
  41. package/docs/api_reference/functions/showSuccessNotification.html +1 -1
  42. package/docs/api_reference/functions/speakWithStreaming.html +1 -1
  43. package/docs/api_reference/functions/stopTTS.html +1 -1
  44. package/docs/api_reference/functions/syncSubscriptionWithAPI.html +1 -1
  45. package/docs/api_reference/functions/updateSubscriptionTier.html +1 -1
  46. package/docs/api_reference/functions/useFeatureFlag.html +1 -1
  47. package/docs/api_reference/functions/useFeatureVisibility.html +1 -1
  48. package/docs/api_reference/functions/useFeatures.html +1 -1
  49. package/docs/api_reference/functions/useGatewayHealth.html +1 -1
  50. package/docs/api_reference/functions/useGatewayMemory.html +1 -1
  51. package/docs/api_reference/functions/useGatewayModels.html +1 -1
  52. package/docs/api_reference/functions/useGlobalTTS.html +1 -1
  53. package/docs/api_reference/functions/useNotification.html +1 -1
  54. package/docs/api_reference/functions/useNotificationService.html +1 -1
  55. package/docs/api_reference/functions/useTTS.html +1 -1
  56. package/docs/api_reference/functions/useVectorStore.html +1 -1
  57. package/docs/api_reference/functions/useVoiceStore.html +2 -2
  58. package/docs/api_reference/functions/useVoices.html +1 -1
  59. package/docs/api_reference/functions/validateEnvironment.html +1 -1
  60. package/docs/api_reference/functions/validateSystemIntegrity.html +1 -1
  61. package/docs/api_reference/index.html +15 -63
  62. package/docs/api_reference/interfaces/AIChatRequest.html +2 -2
  63. package/docs/api_reference/interfaces/AIChatResponse.html +2 -2
  64. package/docs/api_reference/interfaces/AIGenerateRequest.html +2 -2
  65. package/docs/api_reference/interfaces/AIGenerateResponse.html +2 -2
  66. package/docs/api_reference/interfaces/AIMessage.html +2 -2
  67. package/docs/api_reference/interfaces/AIModel.html +2 -2
  68. package/docs/api_reference/interfaces/AIProviderConfig.html +2 -2
  69. package/docs/api_reference/interfaces/ChatConfig.html +3 -3
  70. package/docs/api_reference/interfaces/ChatModalProps.html +3 -3
  71. package/docs/api_reference/interfaces/CreateMemoryOptions.html +2 -2
  72. package/docs/api_reference/interfaces/FeatureEvaluation.html +7 -7
  73. package/docs/api_reference/interfaces/FeatureFlagConfig.html +9 -9
  74. package/docs/api_reference/interfaces/FeatureFlagContextValue.html +8 -8
  75. package/docs/api_reference/interfaces/FeatureFlagProviderProps.html +2 -2
  76. package/docs/api_reference/interfaces/FeedbackButtonProps.html +10 -10
  77. package/docs/api_reference/interfaces/FeedbackCategories.html +2 -2
  78. package/docs/api_reference/interfaces/FeedbackModalProps.html +2 -2
  79. package/docs/api_reference/interfaces/FeedbackPriorities.html +2 -2
  80. package/docs/api_reference/interfaces/FeedbackRequest.html +2 -2
  81. package/docs/api_reference/interfaces/FeedbackResponse.html +2 -2
  82. package/docs/api_reference/interfaces/FileUploadResult.html +2 -2
  83. package/docs/api_reference/interfaces/GatewayChatRequest.html +2 -2
  84. package/docs/api_reference/interfaces/GatewayChatResponse.html +2 -2
  85. package/docs/api_reference/interfaces/GatewayContract.html +2 -2
  86. package/docs/api_reference/interfaces/GatewayGenerateRequest.html +2 -2
  87. package/docs/api_reference/interfaces/GatewayGenerateResponse.html +2 -2
  88. package/docs/api_reference/interfaces/GatewayHealthResponse.html +2 -2
  89. package/docs/api_reference/interfaces/GatewayMemoryRecord.html +2 -2
  90. package/docs/api_reference/interfaces/GatewayMemoryResponse.html +2 -2
  91. package/docs/api_reference/interfaces/GatewayMessage.html +2 -2
  92. package/docs/api_reference/interfaces/GatewayMessageContent.html +2 -2
  93. package/docs/api_reference/interfaces/GatewayModel.html +2 -2
  94. package/docs/api_reference/interfaces/GatewayModelsResponse.html +2 -2
  95. package/docs/api_reference/interfaces/MemorySearchFilters.html +2 -2
  96. package/docs/api_reference/interfaces/MigrationProgress.html +2 -2
  97. package/docs/api_reference/interfaces/MigrationStatus.html +2 -2
  98. package/docs/api_reference/interfaces/NotificationConfig.html +2 -2
  99. package/docs/api_reference/interfaces/NotificationContextType.html +2 -2
  100. package/docs/api_reference/interfaces/NotificationProviderProps.html +2 -2
  101. package/docs/api_reference/interfaces/PackageSettings.html +2 -2
  102. package/docs/api_reference/interfaces/SearchOptions.html +2 -2
  103. package/docs/api_reference/interfaces/SearchResult.html +2 -2
  104. package/docs/api_reference/interfaces/SubscriptionExpiredGuardProps.html +2 -2
  105. package/docs/api_reference/interfaces/SubscriptionExpiredModalProps.html +2 -2
  106. package/docs/api_reference/interfaces/TTSOptions.html +2 -2
  107. package/docs/api_reference/interfaces/TTSProgress.html +2 -2
  108. package/docs/api_reference/interfaces/TrialUsage.html +2 -2
  109. package/docs/api_reference/interfaces/UploadRequest.html +3 -3
  110. package/docs/api_reference/interfaces/UseTTSReturn.html +2 -2
  111. package/docs/api_reference/interfaces/VectorDocument.html +2 -2
  112. package/docs/api_reference/interfaces/VectorMemory.html +2 -2
  113. package/docs/api_reference/interfaces/VectorMemoryMetadata.html +2 -2
  114. package/docs/api_reference/interfaces/VectorStoreStatus.html +2 -2
  115. package/docs/api_reference/interfaces/VoiceModelsResponse.html +2 -2
  116. package/docs/api_reference/interfaces/VoiceState.html +2 -2
  117. package/docs/api_reference/media/05_cli_quickstart.md +1 -1
  118. package/docs/api_reference/types/FeatureKey.html +1 -1
  119. package/docs/api_reference/types/FeatureMatrix.html +1 -1
  120. package/docs/api_reference/types/GatewayQueryOptions.html +1 -1
  121. package/docs/api_reference/types/LogContext.html +1 -1
  122. package/docs/api_reference/types/SubscriptionTier.html +1 -1
  123. package/docs/api_reference/variables/DEFAULT_TIER_FEATURES.html +1 -1
  124. package/docs/api_reference/variables/FeatureFlagContext.html +1 -1
  125. package/docs/api_reference/variables/OSS_DEFAULT_FEATURES.html +1 -1
  126. package/docs/api_reference/variables/SYSTEM_FLAGS.html +1 -1
  127. package/docs/api_reference/variables/authenticationService.html +1 -1
  128. package/docs/api_reference/variables/debugLogger-1.html +1 -1
  129. package/docs/api_reference/variables/featureFlagService-1.html +1 -1
  130. package/docs/api_reference/variables/notificationService-1.html +1 -1
  131. package/docs/api_reference/variables/vectorDatabaseService-1.html +1 -1
  132. package/docs/api_reference/variables/vectorMigrationService-1.html +1 -1
  133. package/docs/api_reference/variables/voiceService-1.html +1 -1
  134. package/package.json +2 -2
@@ -1,271 +1,456 @@
1
1
  (() => {
2
- const STORAGE_KEY = "bandit-doc-view:target-id";
3
- const MAX_LOOKUPS = 360;
4
- const RESCROLL_DELAYS = [100, 300, 600, 1200, 2400, 3600];
5
-
6
- const decodeHash = (hash) => {
7
- if (!hash) {
8
- return null;
9
- }
2
+ const STYLE_ID = "bandit-typedoc-mobile-tweaks";
3
+ const BACK_BUTTON_ID = "bandit-docs-back-button";
4
+ const FALLBACK_URL = "/npm-package";
5
+ const GATEWAY_MARKER = "VITE_DEFAULT_MODEL";
6
+ const MAX_GATEWAY_ATTEMPTS = 40;
7
+ const EMBEDDED_CLASS = "bandit-docs-embedded";
8
+ const STANDALONE_CLASS = "bandit-docs-standalone";
9
+
10
+ const isEmbedded = (() => {
10
11
  try {
11
- return decodeURIComponent(hash.replace(/^#/, ""));
12
+ return window.top !== window;
12
13
  } catch {
13
- return hash.replace(/^#/, "");
14
+ return true;
14
15
  }
15
- };
16
+ })();
16
17
 
17
- const sanitizeId = (id) => {
18
- if (!id) {
19
- return null;
20
- }
21
- return id
22
- .normalize("NFKD")
23
- .replace(/[\u{1F300}-\u{1FAFF}]/gu, "")
24
- .replace(/[\u{1F600}-\u{1F64F}]/gu, "")
25
- .replace(/[\u{1F680}-\u{1F6FF}]/gu, "")
26
- .replace(/[\u2600-\u27BF]/g, "")
27
- .replace(/[:]/g, "-")
28
- .replace(/-+/g, "-")
29
- .replace(/^-|-$/g, "");
30
- };
18
+ const addStyles = () => {
19
+ if (document.getElementById(STYLE_ID)) return;
31
20
 
32
- const ensureAliasAnchors = () => {
33
- const processed = new Set();
34
- document.querySelectorAll("[id]").forEach((node) => {
35
- const aliasId = sanitizeId(node.id);
36
- if (!aliasId || aliasId === node.id || processed.has(aliasId)) {
37
- return;
21
+ const style = document.createElement("style");
22
+ style.id = STYLE_ID;
23
+ style.textContent = `
24
+ :root {
25
+ --bandit-docs-footer-height: 56px;
26
+ --bandit-docs-header-height: 68px;
38
27
  }
39
- if (document.getElementById(aliasId)) {
40
- processed.add(aliasId);
41
- return;
28
+
29
+ html,
30
+ body {
31
+ overflow: hidden;
42
32
  }
43
33
 
44
- const alias = document.createElement("span");
45
- alias.id = aliasId;
46
- alias.setAttribute("data-bandit-alias", node.id);
47
- alias.style.position = "relative";
48
- alias.style.display = "block";
49
- alias.style.height = "0";
50
- alias.style.margin = "0";
51
- alias.style.padding = "0";
52
- alias.style.visibility = "hidden";
34
+ body.bandit-docs-ready {
35
+ display: block !important;
36
+ }
53
37
 
54
- if (node.parentNode) {
55
- node.parentNode.insertBefore(alias, node);
38
+ .tsd-panel table {
39
+ width: 100%;
40
+ border-collapse: collapse;
56
41
  }
57
- processed.add(aliasId);
58
- });
59
- };
60
42
 
61
- const resolveTarget = (id) => {
62
- if (!id) {
63
- return null;
64
- }
43
+ .tsd-panel table:not(.tsd-comment-table) {
44
+ display: block;
45
+ overflow-x: auto;
46
+ }
65
47
 
66
- if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
67
- const escaped = CSS.escape(id);
68
- const viaSelector = document.querySelector(`#${escaped}`);
69
- if (viaSelector) {
70
- return viaSelector;
48
+ .tsd-panel table::-webkit-scrollbar {
49
+ height: 6px;
71
50
  }
72
- }
73
51
 
74
- const direct = document.getElementById(id);
75
- if (direct) {
76
- return direct;
77
- }
52
+ .gateway-doc {
53
+ display: grid;
54
+ gap: clamp(12px, 2.5vw, 20px);
55
+ line-height: 1.65;
56
+ }
78
57
 
79
- const sanitized = sanitizeId(id);
80
- if (sanitized && sanitized !== id) {
81
- const fallback = document.getElementById(sanitized);
82
- if (fallback) {
83
- return fallback;
58
+ .gateway-doc ul {
59
+ margin: 0;
60
+ padding-left: clamp(20px, 4vw, 32px);
84
61
  }
85
- }
86
62
 
87
- const slug = id.includes(":") ? id.split(":").pop() : id;
88
- if (slug) {
89
- const nodes = document.querySelectorAll("[id]");
90
- for (const node of nodes) {
91
- if (typeof node.id === "string" && node.id.endsWith(slug)) {
92
- return node;
63
+ .gateway-doc blockquote {
64
+ margin: 0;
65
+ padding-left: clamp(16px, 3vw, 24px);
66
+ border-left: 3px solid rgba(148, 163, 184, 0.35);
67
+ opacity: 0.9;
68
+ }
69
+
70
+ .container {
71
+ width: 100%;
72
+ max-width: none;
73
+ margin: 0 auto;
74
+ padding-left: clamp(18px, 2.8vw, 64px);
75
+ padding-right: clamp(18px, 2.8vw, 64px);
76
+ box-sizing: border-box;
77
+ }
78
+
79
+ .container-main {
80
+ box-sizing: border-box;
81
+ margin: 0 auto;
82
+ padding-top: clamp(4px, 0.6vh, 10px);
83
+ padding-bottom: 0;
84
+ gap: clamp(12px, 1.4vw, 24px);
85
+ height: calc(100vh - var(--bandit-docs-header-height));
86
+ display: grid;
87
+ grid-template-rows: max-content 1fr;
88
+ align-content: start;
89
+ }
90
+
91
+ .container-main .col-content,
92
+ .container-main .col-navigation,
93
+ .container-main .col-sidebar {
94
+ padding-bottom: clamp(12px, 1.4vw, 20px);
95
+ }
96
+
97
+ @media (min-width: 1280px) {
98
+ .container-main {
99
+ display: grid;
100
+ grid-template-columns:
101
+ minmax(200px, clamp(236px, 15.5vw, 284px))
102
+ minmax(0, 1fr)
103
+ minmax(200px, clamp(236px, 15.5vw, 284px));
104
+ align-items: stretch;
105
+ grid-template-rows: max-content 1fr;
106
+ }
107
+
108
+ .container-main .col-navigation,
109
+ .container-main .col-sidebar {
110
+ position: sticky;
111
+ top: var(--bandit-docs-header-height);
112
+ max-height: calc(100vh - var(--bandit-docs-header-height) - var(--bandit-docs-footer-height) - clamp(12px, 1.5vh, 24px));
113
+ overflow-y: auto;
114
+ padding-right: clamp(6px, 0.9vw, 16px);
115
+ padding-bottom: calc(var(--bandit-docs-footer-height) + clamp(12px, 1.5vh, 24px));
116
+ scrollbar-gutter: stable;
117
+ overscroll-behavior: contain;
118
+ -webkit-overflow-scrolling: touch;
119
+ min-width: 0;
120
+ }
121
+
122
+ .container-main .col-content {
123
+ min-width: 0;
124
+ max-height: calc(100vh - var(--bandit-docs-header-height) - var(--bandit-docs-footer-height) - clamp(12px, 1.5vh, 24px));
125
+ overflow-y: auto;
126
+ padding-right: clamp(8px, 1vw, 20px);
127
+ padding-bottom: calc(var(--bandit-docs-footer-height) + clamp(16px, 2vh, 28px));
128
+ scrollbar-gutter: stable;
129
+ overscroll-behavior: contain;
130
+ -webkit-overflow-scrolling: touch;
131
+ }
132
+
133
+ .container-main .col-navigation .tsd-navigation a,
134
+ .container-main .col-sidebar .tsd-navigation a {
135
+ white-space: normal;
93
136
  }
94
137
  }
95
- }
96
138
 
97
- return null;
98
- };
139
+ footer {
140
+ position: fixed;
141
+ left: 0;
142
+ right: 0;
143
+ bottom: 0;
144
+ margin: 0;
145
+ padding: 0 clamp(18px, 2.8vw, 54px);
146
+ height: var(--bandit-docs-footer-height);
147
+ display: flex;
148
+ align-items: center;
149
+ background: rgba(5, 11, 25, 0.94);
150
+ backdrop-filter: blur(14px);
151
+ border-top: 1px solid rgba(148, 163, 184, 0.2);
152
+ z-index: 200;
153
+ }
99
154
 
100
- const performScroll = (target) => {
101
- if (!target) {
102
- return;
103
- }
104
- try {
105
- target.scrollIntoView({ block: "start", inline: "nearest" });
106
- } catch {
107
- target.scrollIntoView();
108
- }
109
- };
155
+ footer > * {
156
+ max-width: min(100%, calc(100vw - clamp(32px, 6vw, 120px)));
157
+ margin: 0 auto;
158
+ }
110
159
 
111
- const scrollToId = (id, attempt = 0) => {
112
- if (!id || attempt > MAX_LOOKUPS) {
113
- return;
114
- }
160
+ .${EMBEDDED_CLASS} footer {
161
+ padding-left: clamp(18px, 2.4vw, 54px);
162
+ padding-right: clamp(18px, 2.4vw, 54px);
163
+ }
115
164
 
116
- ensureAliasAnchors();
165
+ body {
166
+ margin: 0;
167
+ padding-bottom: 0;
168
+ }
117
169
 
118
- const target = resolveTarget(id);
119
- if (!target) {
120
- requestAnimationFrame(() => scrollToId(id, attempt + 1));
121
- return;
122
- }
170
+ @media (min-width: 1280px) {
171
+ body {
172
+ overflow-y: hidden;
173
+ }
174
+ }
123
175
 
124
- performScroll(target);
125
- RESCROLL_DELAYS.forEach((delay) => setTimeout(() => performScroll(target), delay));
126
- };
176
+ @media (min-width: 1200px) {
177
+ .page-menu,
178
+ .site-menu {
179
+ max-height: calc(100vh - 2rem - 114px) !important;
180
+ }
181
+ }
127
182
 
128
- const consumeStoredTarget = () => {
129
- try {
130
- const stored = window.sessionStorage.getItem(STORAGE_KEY);
131
- if (stored) {
132
- window.sessionStorage.removeItem(STORAGE_KEY);
133
- try {
134
- const parsed = JSON.parse(stored);
135
- if (parsed && (parsed.rawId || parsed.aliasId)) {
136
- return {
137
- rawId: parsed.rawId ?? null,
138
- aliasId: parsed.aliasId ?? sanitizeId(parsed.rawId ?? null),
139
- };
140
- }
141
- } catch {
142
- // fall back to treating it as a plain ID
143
- return {
144
- rawId: stored,
145
- aliasId: sanitizeId(stored),
146
- };
183
+ @media (min-width: 770px) and (max-width: 1199px) {
184
+ .site-menu {
185
+ max-height: calc(100vh - 2rem - 114px) !important;
147
186
  }
148
187
  }
149
- } catch {
150
- // ignore storage access failures
151
- }
152
- return { rawId: null, aliasId: null };
153
- };
154
188
 
155
- const createTarget = (rawId) => ({
156
- rawId: rawId ?? null,
157
- aliasId: rawId ? sanitizeId(rawId) : null,
158
- });
189
+ @media (max-width: 1024px) {
190
+ html,
191
+ body {
192
+ overflow: auto;
193
+ }
159
194
 
160
- const latestTarget = (() => {
161
- const stored = consumeStoredTarget();
162
- if (stored && (stored.rawId || stored.aliasId)) {
163
- return stored;
164
- }
165
- const initial = decodeHash(window.location.hash);
166
- return createTarget(initial);
167
- })();
195
+ .container {
196
+ padding-left: clamp(16px, 4.5vw, 28px);
197
+ padding-right: clamp(16px, 4.5vw, 28px);
198
+ }
168
199
 
169
- const isTargetEmpty = (target) => !target || (!target.rawId && !target.aliasId);
200
+ .container-main {
201
+ display: block;
202
+ max-width: min(100%, 780px);
203
+ margin-left: auto;
204
+ margin-right: auto;
205
+ min-height: auto;
206
+ height: auto;
207
+ padding-top: clamp(18px, 6vw, 28px);
208
+ padding-bottom: clamp(18px, 6vw, 32px);
209
+ }
170
210
 
171
- const applyScrollForTarget = (target) => {
172
- if (isTargetEmpty(target)) {
173
- return;
174
- }
175
- const tried = new Set();
176
- const candidates = [];
177
- if (target.rawId) {
178
- candidates.push(target.rawId);
179
- }
180
- if (target.aliasId && target.aliasId !== target.rawId) {
181
- candidates.push(target.aliasId);
182
- }
183
- candidates.forEach((candidate) => {
184
- if (candidate && !tried.has(candidate)) {
185
- scrollToId(candidate);
186
- tried.add(candidate);
211
+ .container-main .col-navigation,
212
+ .container-main .col-sidebar {
213
+ position: relative;
214
+ top: auto;
215
+ max-height: none;
216
+ overflow: visible;
217
+ padding-right: 0;
218
+ padding-bottom: clamp(24px, 6vw, 48px);
219
+ }
220
+
221
+ .container-main .col-content {
222
+ max-height: none;
223
+ overflow: visible;
224
+ padding-right: 0;
225
+ padding-bottom: clamp(72px, 10vw, 120px);
226
+ }
227
+
228
+ footer {
229
+ position: static;
230
+ padding: clamp(18px, 6vw, 28px) 0 clamp(24px, 6vw, 36px);
231
+ background: transparent;
232
+ backdrop-filter: none;
233
+ border-top: 1px solid rgba(148, 163, 184, 0.24);
234
+ height: auto;
235
+ }
236
+
237
+ footer > * {
238
+ max-width: none;
239
+ padding-left: clamp(16px, 4.5vw, 28px);
240
+ padding-right: clamp(16px, 4.5vw, 28px);
241
+ }
242
+
243
+ body {
244
+ overflow-y: auto;
245
+ padding-bottom: clamp(48px, 12vw, 88px);
246
+ }
247
+
248
+ #${BACK_BUTTON_ID} {
249
+ display: flex;
250
+ }
187
251
  }
188
- });
189
- };
190
252
 
191
- const ensureBodyVisibleThenScroll = (target) => {
192
- if (isTargetEmpty(target)) {
193
- return;
194
- }
253
+ .${EMBEDDED_CLASS} .container {
254
+ padding-left: clamp(18px, 2.4vw, 54px);
255
+ padding-right: clamp(18px, 2.4vw, 54px);
256
+ }
257
+
258
+ .${EMBEDDED_CLASS} .container-main {
259
+ margin-left: auto;
260
+ margin-right: auto;
261
+ width: min(100%, calc(100vw - clamp(32px, 6vw, 120px)));
262
+ }
263
+
264
+ .${EMBEDDED_CLASS} .tsd-page-toolbar {
265
+ position: sticky;
266
+ top: 0;
267
+ z-index: 90;
268
+ min-height: 56px;
269
+ padding: 0;
270
+ box-shadow: inset 0 -1px 0 rgba(148, 163, 184, 0.18);
271
+ backdrop-filter: blur(18px);
272
+ }
195
273
 
196
- const checkVisibility = () => {
197
- ensureAliasAnchors();
198
- if (!document.body) {
199
- requestAnimationFrame(checkVisibility);
200
- return;
274
+ .${EMBEDDED_CLASS} .tsd-page-toolbar .tsd-toolbar-contents {
275
+ margin: 0 auto;
276
+ padding: 0 clamp(18px, 2.4vw, 54px);
277
+ width: min(100%, calc(100vw - clamp(32px, 6vw, 120px)));
278
+ display: flex;
279
+ align-items: center;
201
280
  }
202
281
 
203
- const visible = window.getComputedStyle(document.body).display !== "none";
204
- if (visible) {
205
- applyScrollForTarget(target);
206
- } else {
207
- requestAnimationFrame(checkVisibility);
282
+ #${BACK_BUTTON_ID} {
283
+ position: fixed;
284
+ left: 50%;
285
+ transform: translateX(-50%);
286
+ bottom: calc(env(safe-area-inset-bottom, 0px) + clamp(18px, 6vw, 32px));
287
+ z-index: 2147483647;
288
+ border: 1px solid rgba(148, 163, 184, 0.18);
289
+ border-radius: clamp(32px, 10vw, 999px);
290
+ padding: clamp(12px, 4vw, 18px) clamp(18px, 7vw, 22px);
291
+ min-height: 46px;
292
+ width: min(480px, calc(100vw - clamp(28px, 10vw, 64px)));
293
+ background: linear-gradient(135deg, rgba(63, 133, 245, 0.95), rgba(14, 165, 233, 0.95));
294
+ color: #f8fafc;
295
+ font-size: clamp(14px, 4vw, 16px);
296
+ font-weight: 700;
297
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
298
+ box-shadow: 0 20px 36px rgba(8, 15, 32, 0.35);
299
+ display: none;
300
+ align-items: center;
301
+ justify-content: center;
302
+ gap: clamp(4px, 2vw, 10px);
303
+ cursor: pointer;
304
+ backdrop-filter: blur(18px);
305
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
208
306
  }
209
- };
210
307
 
211
- checkVisibility();
308
+ #${BACK_BUTTON_ID}:hover {
309
+ transform: translate(-50%, -2px);
310
+ box-shadow: 0 26px 45px rgba(8, 15, 32, 0.4);
311
+ }
312
+
313
+ #${BACK_BUTTON_ID}:active {
314
+ transform: translate(-50%, 0) scale(0.97);
315
+ box-shadow: 0 16px 30px rgba(8, 15, 32, 0.4);
316
+ }
317
+
318
+ #${BACK_BUTTON_ID} svg {
319
+ width: clamp(16px, 4vw, 18px);
320
+ height: clamp(16px, 4vw, 18px);
321
+ fill: currentColor;
322
+ }
323
+
324
+ #${BACK_BUTTON_ID} span {
325
+ white-space: nowrap;
326
+ letter-spacing: 0.01em;
327
+ }
328
+
329
+ @media (max-width: 1024px) {
330
+ .container {
331
+ width: 100%;
332
+ max-width: calc(100vw - clamp(8px, 4vw, 28px));
333
+ margin: 0 auto;
334
+ padding: clamp(14px, 4.5vw, 24px);
335
+ }
336
+
337
+ #${BACK_BUTTON_ID} {
338
+ display: flex;
339
+ }
340
+ }
341
+ `;
342
+
343
+ document.head.appendChild(style);
212
344
  };
213
345
 
214
- const hookTypeDocApp = () => {
215
- if (!window.app || typeof window.app.showPage !== "function" || window.app.__banditHooked) {
216
- if (!window.app) {
217
- setTimeout(hookTypeDocApp, 40);
346
+ const revealBody = () => {
347
+ if (document.body) {
348
+ document.body.classList.add("bandit-docs-ready");
349
+ document.body.style.removeProperty("display");
350
+ }
351
+ };
352
+
353
+ const ensureBackButton = () => {
354
+ if (isEmbedded) return;
355
+
356
+ let button = document.getElementById(BACK_BUTTON_ID);
357
+ if (!button) {
358
+ button = document.createElement("button");
359
+ button.id = BACK_BUTTON_ID;
360
+ button.type = "button";
361
+ button.setAttribute("aria-label", "Return to npm package page");
362
+ button.innerHTML =
363
+ '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg><span>Back to overview</span>';
364
+ button.addEventListener("click", () => {
365
+ const fallback = () => {
366
+ window.location.href = FALLBACK_URL;
367
+ };
368
+ const timeout = setTimeout(fallback, 180);
369
+ window.addEventListener(
370
+ "popstate",
371
+ () => {
372
+ clearTimeout(timeout);
373
+ },
374
+ { once: true },
375
+ );
376
+ window.history.back();
377
+ });
378
+ document.body.appendChild(button);
379
+ }
380
+ };
381
+
382
+ const replaceGatewaySnippet = (attempt = 0) => {
383
+ const codeBlocks = Array.from(document.querySelectorAll("pre code"));
384
+ const targetBlock = codeBlocks.find((block) => {
385
+ const text = block.textContent || "";
386
+ return text.includes(GATEWAY_MARKER) && text.includes("Voice Services (TTS/STT)");
387
+ });
388
+
389
+ if (!targetBlock) {
390
+ if (attempt < MAX_GATEWAY_ATTEMPTS) {
391
+ setTimeout(() => replaceGatewaySnippet(attempt + 1), 200);
218
392
  }
219
393
  return;
220
394
  }
221
395
 
222
- const originalShowPage = window.app.showPage.bind(window.app);
223
- window.app.showPage = (...args) => {
224
- const result = originalShowPage(...args);
225
- setTimeout(() => {
226
- ensureAliasAnchors();
227
- ensureBodyVisibleThenScroll(latestTarget);
228
- }, 16);
229
- return result;
230
- };
231
-
232
- window.app.__banditHooked = true;
396
+ const pre = targetBlock.closest("pre");
397
+ if (!pre) return;
398
+
399
+ const copyButton = pre.nextElementSibling;
400
+ if (copyButton?.tagName === "BUTTON") {
401
+ copyButton.remove();
402
+ }
403
+
404
+ const wrapper = document.createElement("div");
405
+ wrapper.className = "gateway-doc";
406
+ wrapper.innerHTML = `
407
+ <p>Set <code>VITE_DEFAULT_MODEL</code> / <code>VITE_FALLBACK_MODEL</code> to the exact Ollama model tags you have available (<code>gemma</code>, <code>llava</code>, <code>moondream</code>, or your own custom builds). Bandit automatically detects multimodal Ollama models, so setting <code>llava</code>, <code>moondream</code>, or other vision-capable variants enables image understanding with no extra code.</p>
408
+ <h3>🎤 Voice Services (TTS/STT)</h3>
409
+ <p>The Bandit Engine supports Text-to-Speech (TTS) and Speech-to-Text (STT) through your gateway API. These services are <strong>technology-agnostic</strong> — you can implement them using any backend technology:</p>
410
+ <ul>
411
+ <li>
412
+ <strong>TTS Endpoint (<code>POST /api/tts</code>)</strong>
413
+ <ul>
414
+ <li><strong>Input</strong>: <code>{ text: string, voice?: string, speed?: number }</code></li>
415
+ <li><strong>Output</strong>: Audio file (MP3, WAV, etc.) or streaming audio</li>
416
+ <li><strong>Compatible with</strong>: OpenAI TTS, Azure Speech, Google Cloud TTS, AWS Polly, local TTS servers, or custom implementations</li>
417
+ </ul>
418
+ </li>
419
+ <li>
420
+ <strong>STT Endpoint (<code>POST /api/stt/transcribe</code>)</strong>
421
+ <ul>
422
+ <li><strong>Input</strong>: Audio file upload (multipart/form-data)</li>
423
+ <li><strong>Output</strong>: <code>{ text: string }</code> or <code>{ transcription: string }</code></li>
424
+ <li><strong>Compatible with</strong>: OpenAI Whisper, Azure Speech, Google Speech, AWS Transcribe, local Whisper servers, or custom implementations</li>
425
+ </ul>
426
+ </li>
427
+ <li>
428
+ <strong>Service Discovery (<code>GET /api/tts/available-models</code>)</strong>
429
+ <ul>
430
+ <li><strong>Output</strong>: <code>{ models: string[], defaultModel: string, fallbackModel: string }</code></li>
431
+ <li>Used for automatic service availability detection and voice model selection</li>
432
+ </ul>
433
+ </li>
434
+ </ul>
435
+ <blockquote>Quickstart note: the generated Express gateway ships these TTS/STT routes as <code>501</code> placeholders so you can connect your own provider. Voice features remain disabled until you implement them server-side.</blockquote>
436
+ <p>See the <a href="media/02_gateway_api.md">Gateway API Contract</a> for complete implementation examples in multiple languages.</p>
437
+ <p>Use the Management interface to switch providers anytime or migrate from direct to gateway setup.</p>
438
+ `;
439
+
440
+ pre.replaceWith(wrapper);
233
441
  };
234
442
 
235
- const handleInitialScroll = () => {
236
- ensureAliasAnchors();
237
- ensureBodyVisibleThenScroll(latestTarget);
443
+ const init = () => {
444
+ document.documentElement.classList.add(isEmbedded ? EMBEDDED_CLASS : STANDALONE_CLASS);
445
+ addStyles();
446
+ revealBody();
447
+ ensureBackButton();
448
+ replaceGatewaySnippet();
238
449
  };
239
450
 
240
451
  if (document.readyState === "complete" || document.readyState === "interactive") {
241
- handleInitialScroll();
452
+ init();
242
453
  } else {
243
- window.addEventListener("DOMContentLoaded", handleInitialScroll, { once: true });
454
+ document.addEventListener("DOMContentLoaded", init, { once: true });
244
455
  }
245
-
246
- window.addEventListener("load", () => {
247
- ensureAliasAnchors();
248
- ensureBodyVisibleThenScroll(latestTarget);
249
- });
250
-
251
- window.addEventListener("hashchange", () => {
252
- const nextTarget = decodeHash(window.location.hash);
253
- if (nextTarget) {
254
- latestTarget.rawId = nextTarget;
255
- latestTarget.aliasId = sanitizeId(nextTarget);
256
- }
257
- ensureBodyVisibleThenScroll(latestTarget);
258
- });
259
-
260
- const observer = new MutationObserver(() => {
261
- ensureAliasAnchors();
262
- ensureBodyVisibleThenScroll(latestTarget);
263
- });
264
- observer.observe(document.body ?? document.documentElement, {
265
- attributes: true,
266
- childList: true,
267
- subtree: true,
268
- });
269
-
270
- hookTypeDocApp();
271
456
  })();