@adminforth/agent 2.0.9 → 2.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 (187) hide show
  1. package/README.md +333 -10
  2. package/dist/application/ports.d.ts +66 -0
  3. package/dist/application/runTurnUseCase.d.ts +68 -0
  4. package/dist/application/runTurnUseCase.js +358 -0
  5. package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +1 -1
  6. package/dist/{agent → domain}/systemPrompt.js +1 -1
  7. package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
  8. package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.js +40 -35
  11. package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
  12. package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
  13. package/dist/llm/agentModels.js +65 -0
  14. package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +11 -2
  15. package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +38 -6
  16. package/dist/llm/langGraphLlm.d.ts +25 -0
  17. package/dist/llm/langGraphLlm.js +54 -0
  18. package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
  19. package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
  20. package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
  21. package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
  22. package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
  23. package/dist/llm/streamAdapter.d.ts +18 -0
  24. package/dist/llm/streamAdapter.js +117 -0
  25. package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +12 -2
  26. package/dist/{sessionStore.js → persistence/sessionStore.js} +33 -0
  27. package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
  28. package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
  29. package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +10 -6
  30. package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
  31. package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
  32. package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
  33. package/dist/{agent/tools → tools}/index.d.ts +1 -1
  34. package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
  35. package/dist/{endpoints → transport/http}/context.d.ts +2 -2
  36. package/dist/transport/http/context.js +1 -0
  37. package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +3 -3
  38. package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +7 -1
  39. package/dist/transport/sse/sseWriter.d.ts +29 -0
  40. package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +15 -0
  41. package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
  42. package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
  43. package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
  44. package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
  45. package/dist/types.d.ts +10 -4
  46. package/package.json +11 -2
  47. package/.woodpecker/buildRelease.sh +0 -13
  48. package/.woodpecker/buildSlackNotify.sh +0 -46
  49. package/.woodpecker/release.yml +0 -57
  50. package/agent/checkpointer.ts +0 -329
  51. package/agent/languageDetect.ts +0 -92
  52. package/agent/middleware/apiBasedTools.ts +0 -174
  53. package/agent/middleware/openAiResponsesContinuation.ts +0 -92
  54. package/agent/middleware/sequenceDebug.ts +0 -429
  55. package/agent/models/AgentModeResolver.ts +0 -9
  56. package/agent/models/AgentModelFactory.ts +0 -28
  57. package/agent/runtime/AgentContext.ts +0 -30
  58. package/agent/runtime/AgentRuntime.ts +0 -89
  59. package/agent/simpleAgent.ts +0 -199
  60. package/agent/skills/registry.ts +0 -162
  61. package/agent/speech/SpeechTurnService.ts +0 -179
  62. package/agent/systemPrompt.ts +0 -133
  63. package/agent/toolCallEvents.ts +0 -135
  64. package/agent/tools/AgentToolProvider.ts +0 -28
  65. package/agent/tools/apiTool.ts +0 -66
  66. package/agent/tools/fetchSkill.ts +0 -68
  67. package/agent/tools/fetchToolSchema.ts +0 -47
  68. package/agent/tools/getUserLocation.ts +0 -45
  69. package/agent/tools/index.ts +0 -31
  70. package/agent/tools/navigateUser.ts +0 -210
  71. package/agent/turn/TurnContextBuilder.ts +0 -36
  72. package/agent/turn/TurnLifecycleService.ts +0 -47
  73. package/agent/turn/TurnPersistenceService.ts +0 -33
  74. package/agent/turn/TurnPromptBuilder.ts +0 -51
  75. package/agent/turn/TurnStreamConsumer.ts +0 -69
  76. package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
  77. package/agent/turn/turnTypes.ts +0 -100
  78. package/agentEvents.ts +0 -75
  79. package/agentTurnService.ts +0 -314
  80. package/apiBasedTools.ts +0 -702
  81. package/build.log +0 -67
  82. package/chatSurfaceService.ts +0 -319
  83. package/custom/ChatFooter.vue +0 -173
  84. package/custom/ChatHeader.vue +0 -78
  85. package/custom/ChatSurface.vue +0 -160
  86. package/custom/CustomAutoScrollContainer.vue +0 -164
  87. package/custom/SessionsHistory.vue +0 -88
  88. package/custom/chat.ts +0 -82
  89. package/custom/composables/agentAudio/utils.ts +0 -220
  90. package/custom/composables/agentStore/constants.ts +0 -19
  91. package/custom/composables/agentStore/pageContext.ts +0 -8
  92. package/custom/composables/agentStore/useAgentChat.ts +0 -241
  93. package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
  94. package/custom/composables/agentStore/useAgentSessions.ts +0 -350
  95. package/custom/composables/useAgentAudio.ts +0 -272
  96. package/custom/composables/useAgentStore.ts +0 -510
  97. package/custom/composables/useAgentTransitions.ts +0 -58
  98. package/custom/conversation_area/ConversationArea.vue +0 -301
  99. package/custom/conversation_area/MessageRenderer.vue +0 -49
  100. package/custom/conversation_area/ProcessingTimeline.vue +0 -286
  101. package/custom/conversation_area/ReasoningRenderer.vue +0 -79
  102. package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
  103. package/custom/conversation_area/TextRenderer.vue +0 -182
  104. package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
  105. package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
  106. package/custom/conversation_area/ToolRenderer.vue +0 -178
  107. package/custom/conversation_area/ToolsGroup.vue +0 -59
  108. package/custom/env.d.ts +0 -7
  109. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
  110. package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
  111. package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
  112. package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
  113. package/custom/package.json +0 -30
  114. package/custom/pnpm-lock.yaml +0 -2394
  115. package/custom/public/agentAudio/agent-processing.mp3 +0 -0
  116. package/custom/skills/analyze_data/SKILL.md +0 -25
  117. package/custom/skills/charts/SKILL.md +0 -193
  118. package/custom/skills/fetch_data/SKILL.md +0 -31
  119. package/custom/skills/mutate_data/SKILL.md +0 -121
  120. package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
  121. package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
  122. package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
  123. package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
  124. package/custom/tsconfig.json +0 -15
  125. package/custom/types.ts +0 -108
  126. package/custom/utils.ts +0 -38
  127. package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
  128. package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
  129. package/dist/agent/models/AgentModeResolver.d.ts +0 -9
  130. package/dist/agent/models/AgentModeResolver.js +0 -9
  131. package/dist/agent/simpleAgent.js +0 -118
  132. package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
  133. package/dist/agent/turn/TurnContextBuilder.js +0 -31
  134. package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
  135. package/dist/agent/turn/TurnLifecycleService.js +0 -47
  136. package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
  137. package/dist/agent/turn/TurnPersistenceService.js +0 -35
  138. package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
  139. package/dist/agent/turn/TurnPromptBuilder.js +0 -43
  140. package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
  141. package/dist/agent/turn/TurnStreamConsumer.js +0 -84
  142. package/dist/agentTurnService.d.ts +0 -24
  143. package/dist/agentTurnService.js +0 -269
  144. package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
  145. package/endpoints/chatSurfaces.ts +0 -66
  146. package/endpoints/context.ts +0 -52
  147. package/endpoints/core.ts +0 -181
  148. package/endpoints/sessions.ts +0 -183
  149. package/errors.ts +0 -10
  150. package/index.ts +0 -192
  151. package/pnpm-workspace.yaml +0 -4
  152. package/sanitizeSpeechText.ts +0 -32
  153. package/sessionStore.ts +0 -105
  154. package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
  155. package/tsconfig.json +0 -14
  156. package/types.ts +0 -127
  157. /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
  158. /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
  159. /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
  160. /package/dist/{agent → domain}/languageDetect.js +0 -0
  161. /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
  162. /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
  163. /package/dist/{agent → domain}/toolCallEvents.js +0 -0
  164. /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
  165. /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
  166. /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
  167. /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
  168. /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
  169. /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
  170. /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
  171. /package/dist/{errors.js → shared/errors.js} +0 -0
  172. /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
  173. /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
  174. /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
  175. /package/dist/{agent/tools → tools}/apiTool.js +0 -0
  176. /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
  177. /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
  178. /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
  179. /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
  180. /package/dist/{agent/tools → tools}/index.js +0 -0
  181. /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
  182. /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
  183. /package/dist/{agent → tools}/skills/registry.js +0 -0
  184. /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
  185. /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
  186. /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
  187. /package/dist/{endpoints/sessions.d.ts → transport/http/sessionEndpoints.d.ts} +0 -0
@@ -1,393 +0,0 @@
1
- <template>
2
- <div
3
- class="incremark-shiki-code"
4
- :data-stream-state="props.blockStatus"
5
- >
6
- <div class="incremark-shiki-toolbar">
7
- <span class="incremark-shiki-language">{{ languageLabel }}</span>
8
- <button
9
- type="button"
10
- class="incremark-shiki-copy"
11
- :class="copied ? 'is-copied' : ''"
12
- :disabled="!sourceCode"
13
- @click="copyCode"
14
- >
15
- {{ copied ? $t('Copied') : $t('Copy') }}
16
- </button>
17
- </div>
18
-
19
- <div class="incremark-shiki-body">
20
- <div
21
- v-if="shouldRenderVega && !renderedHtml"
22
- ref="vegaContainer"
23
- class="incremark-vega"
24
- />
25
-
26
- <div
27
- v-else-if="renderedHtml"
28
- class="incremark-shiki-html"
29
- v-html="renderedHtml"
30
- />
31
-
32
- <pre v-else class="incremark-shiki-fallback"><code>{{ sourceCode }}</code></pre>
33
- </div>
34
- </div>
35
- </template>
36
-
37
- <script setup lang="ts">
38
- import type { Code } from 'mdast';
39
- import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
40
- import embed from 'vega-embed';
41
-
42
- import type { IncremarkCodeTheme } from './incremarkCodeHighlight';
43
-
44
- const props = withDefaults(defineProps<{
45
- node: Code;
46
- lightTheme?: string;
47
- darkTheme?: string;
48
- theme?: string;
49
- fallbackTheme?: string;
50
- disableHighlight?: boolean;
51
- blockStatus?: 'pending' | 'stable' | 'completed';
52
- }>(), {
53
- lightTheme: 'github-light',
54
- darkTheme: 'github-dark',
55
- fallbackTheme: 'github-dark',
56
- disableHighlight: false,
57
- blockStatus: 'completed',
58
- });
59
-
60
- const renderedHtml = ref('');
61
- const copied = ref(false);
62
- const prefersDarkMode = ref(isDarkDocument());
63
- const vegaContainer = ref<HTMLDivElement | null>(null);
64
-
65
- let copyResetTimeout: number | null = null;
66
- let renderRequestId = 0;
67
- let scheduledFrameId: number | null = null;
68
- let themeObserver: MutationObserver | null = null;
69
- let vegaResult: { finalize: () => void } | null = null;
70
- let highlightModulePromise: Promise<typeof import('./incremarkCodeHighlight')> | null = null;
71
-
72
- const sourceCode = computed(() => props.node.value ?? '');
73
- const language = computed(() => props.node.lang?.trim().toLowerCase() || 'text');
74
- const languageLabel = computed(() => language.value === 'vega-lite' ? '' : props.node.lang?.trim() || 'text');
75
- const shouldRenderVega = computed(() => language.value === 'vega-lite');
76
- const codeTheme = computed<IncremarkCodeTheme>(() => {
77
- const requestedTheme = props.theme ?? (prefersDarkMode.value ? props.darkTheme : props.lightTheme);
78
-
79
- if (requestedTheme === 'github-light') {
80
- return 'light';
81
- }
82
-
83
- if (requestedTheme === 'github-dark') {
84
- return 'dark';
85
- }
86
-
87
- return props.fallbackTheme === 'github-light' ? 'light' : 'dark';
88
- });
89
-
90
- watch(
91
- [sourceCode, language, codeTheme, () => props.disableHighlight, () => props.blockStatus],
92
- () => {
93
- scheduleHighlight();
94
- },
95
- { immediate: true }
96
- );
97
-
98
- onMounted(() => {
99
- if (typeof MutationObserver === 'undefined' || typeof document === 'undefined') {
100
- scheduleHighlight();
101
- return;
102
- }
103
-
104
- themeObserver = new MutationObserver(() => {
105
- prefersDarkMode.value = isDarkDocument();
106
- });
107
-
108
- themeObserver.observe(document.documentElement, {
109
- attributes: true,
110
- attributeFilter: ['class'],
111
- });
112
-
113
- scheduleHighlight();
114
- });
115
-
116
- onBeforeUnmount(() => {
117
- renderRequestId += 1;
118
- clearVega();
119
-
120
- if (copyResetTimeout !== null) {
121
- window.clearTimeout(copyResetTimeout);
122
- }
123
-
124
- if (scheduledFrameId !== null) {
125
- window.cancelAnimationFrame(scheduledFrameId);
126
- }
127
-
128
- themeObserver?.disconnect();
129
- });
130
-
131
- async function copyCode() {
132
- if (!sourceCode.value || typeof navigator === 'undefined' || !navigator.clipboard) {
133
- return;
134
- }
135
-
136
- try {
137
- await navigator.clipboard.writeText(sourceCode.value);
138
- copied.value = true;
139
-
140
- if (copyResetTimeout !== null) {
141
- window.clearTimeout(copyResetTimeout);
142
- }
143
-
144
- copyResetTimeout = window.setTimeout(() => {
145
- copied.value = false;
146
- copyResetTimeout = null;
147
- }, 1500);
148
- } catch (error) {
149
- console.error('Failed to copy code block', error);
150
- }
151
- }
152
-
153
- function scheduleHighlight() {
154
- if (typeof window === 'undefined') {
155
- void renderHighlight();
156
- return;
157
- }
158
-
159
- if (scheduledFrameId !== null) {
160
- window.cancelAnimationFrame(scheduledFrameId);
161
- }
162
-
163
- scheduledFrameId = window.requestAnimationFrame(() => {
164
- scheduledFrameId = null;
165
- void renderHighlight();
166
- });
167
- }
168
-
169
- function loadHighlightModule() {
170
- if (!highlightModulePromise) {
171
- highlightModulePromise = import('./incremarkCodeHighlight');
172
- }
173
-
174
- return highlightModulePromise;
175
- }
176
-
177
- async function renderHighlight() {
178
- const requestId = ++renderRequestId;
179
-
180
- if (shouldRenderVega.value) {
181
- renderedHtml.value = '';
182
-
183
- if (!sourceCode.value) {
184
- return;
185
- }
186
-
187
- await nextTick();
188
-
189
- if (requestId !== renderRequestId || !shouldRenderVega.value || !vegaContainer.value) {
190
- return;
191
- }
192
-
193
- try {
194
- clearVega();
195
- const spec = JSON.parse(sourceCode.value);
196
-
197
- if (spec.width == null) {
198
- spec.width = 'container';
199
- }
200
-
201
- if (spec.autosize == null) {
202
- spec.autosize = { type: 'fit-x', contains: 'padding' };
203
- }
204
-
205
- const result = await embed(vegaContainer.value, spec, {
206
- actions: false,
207
- renderer: 'svg',
208
- });
209
-
210
- if (requestId !== renderRequestId) {
211
- result.finalize();
212
- return;
213
- }
214
-
215
- vegaResult = result;
216
- return;
217
- } catch (error) {
218
- clearVega();
219
- console.error('Failed to render Vega-Lite block', error);
220
- }
221
- } else {
222
- clearVega();
223
- }
224
-
225
- if (!sourceCode.value || props.disableHighlight) {
226
- renderedHtml.value = '';
227
- return;
228
- }
229
-
230
- try {
231
- const { highlightCodeSnippetHtml } = await loadHighlightModule();
232
- const html = await highlightCodeSnippetHtml(sourceCode.value, language.value, codeTheme.value);
233
-
234
- if (requestId === renderRequestId) {
235
- renderedHtml.value = html;
236
- }
237
- } catch (error) {
238
- if (requestId === renderRequestId) {
239
- renderedHtml.value = '';
240
- }
241
-
242
- console.error('Failed to highlight streamed code block', error);
243
- }
244
- }
245
-
246
- function isDarkDocument(): boolean {
247
- return typeof document !== 'undefined' && document.documentElement.classList.contains('dark');
248
- }
249
-
250
- function clearVega() {
251
- vegaResult?.finalize();
252
- vegaResult = null;
253
-
254
- if (vegaContainer.value) {
255
- vegaContainer.value.innerHTML = '';
256
- }
257
- }
258
- </script>
259
-
260
- <style scoped>
261
- .incremark-shiki-code {
262
- --incremark-code-border: rgba(148, 163, 184, 0.24);
263
- --incremark-code-toolbar-bg: rgba(248, 250, 252, 0.9);
264
- --incremark-code-toolbar-text: #475569;
265
- --incremark-code-copy-bg: rgba(226, 232, 240, 0.9);
266
- --incremark-code-copy-text: #0f172a;
267
- border: 1px solid var(--incremark-code-border);
268
- border-radius: 16px;
269
- overflow: hidden;
270
- width: 100%;
271
- background:
272
- linear-gradient(180deg, rgba(255, 255, 255, 0.94), rgba(248, 250, 252, 0.96));
273
- box-shadow: 0 14px 30px -24px rgba(15, 23, 42, 0.45);
274
- margin: 16px 0 ;
275
- }
276
-
277
- .dark .incremark-shiki-code {
278
- --incremark-code-border: rgba(100, 116, 139, 0.38);
279
- --incremark-code-toolbar-bg: rgba(15, 23, 42, 0.88);
280
- --incremark-code-toolbar-text: #cbd5e1;
281
- --incremark-code-copy-bg: rgba(30, 41, 59, 0.88);
282
- --incremark-code-copy-text: #e2e8f0;
283
- background:
284
- linear-gradient(180deg, rgba(2, 6, 23, 0.96), rgba(15, 23, 42, 0.98));
285
- }
286
-
287
- .incremark-shiki-code[data-stream-state='pending'],
288
- .incremark-shiki-code[data-stream-state='stable'] {
289
- box-shadow: 0 10px 24px -24px rgba(15, 23, 42, 0.8);
290
- }
291
-
292
- .incremark-shiki-toolbar {
293
- display: flex;
294
- align-items: center;
295
- justify-content: space-between;
296
- gap: 12px;
297
- padding: 10px 14px;
298
- border-bottom: 1px solid var(--incremark-code-border);
299
- background: var(--incremark-code-toolbar-bg);
300
- backdrop-filter: blur(10px);
301
- }
302
-
303
- .incremark-shiki-language {
304
- font-size: 11px;
305
- font-weight: 600;
306
- letter-spacing: 0.12em;
307
- text-transform: uppercase;
308
- color: var(--incremark-code-toolbar-text);
309
- }
310
-
311
- .incremark-shiki-copy {
312
- border: none;
313
- border-radius: 999px;
314
- padding: 6px 10px;
315
- font-size: 11px;
316
- font-weight: 600;
317
- letter-spacing: 0.04em;
318
- background: var(--incremark-code-copy-bg);
319
- color: var(--incremark-code-copy-text);
320
- cursor: pointer;
321
- transition: transform 0.16s ease, opacity 0.16s ease, background-color 0.16s ease;
322
- }
323
-
324
- .incremark-shiki-copy:hover:not(:disabled) {
325
- transform: translateY(-1px);
326
- }
327
-
328
- .incremark-shiki-copy:disabled {
329
- cursor: default;
330
- opacity: 0.5;
331
- }
332
-
333
- .incremark-shiki-copy.is-copied {
334
- background: rgba(16, 185, 129, 0.16);
335
- color: #059669;
336
- }
337
-
338
- .dark .incremark-shiki-copy.is-copied {
339
- background: rgba(16, 185, 129, 0.24);
340
- color: #6ee7b7;
341
- }
342
-
343
- .incremark-shiki-body {
344
- overflow-x: auto;
345
- }
346
-
347
- .incremark-vega {
348
- padding: 18px;
349
- width: 100%;
350
- }
351
-
352
- .incremark-shiki-fallback {
353
- margin: 0;
354
- padding: 18px;
355
- overflow-x: auto;
356
- background: transparent;
357
- color: inherit;
358
- }
359
-
360
- .incremark-shiki-fallback code {
361
- display: block;
362
- font-family: 'JetBrains Mono', 'Fira Code', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
363
- font-size: 13px;
364
- line-height: 1.65;
365
- white-space: pre;
366
- }
367
-
368
- :deep(.incremark-shiki-html pre.shiki) {
369
- margin: 0;
370
- padding: 18px;
371
- overflow-x: auto;
372
- background: transparent !important;
373
- font-size: 13px;
374
- line-height: 1.65;
375
- }
376
-
377
- :deep(.incremark-shiki-html code) {
378
- display: block;
379
- font-family: 'JetBrains Mono', 'Fira Code', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
380
- }
381
-
382
- :deep(.incremark-shiki-html .line) {
383
- min-height: 1.65em;
384
- }
385
-
386
- :deep(.incremark-vega .vega-embed) {
387
- width: 100%;
388
- }
389
-
390
- :deep(.incremark-vega){
391
- padding: 0;
392
- }
393
- </style>
@@ -1,285 +0,0 @@
1
- import {
2
- createBundledHighlighter,
3
- type HighlighterGeneric,
4
- type LanguageInput,
5
- type ThemeInput
6
- } from 'shiki/core';
7
- import { createOnigurumaEngine } from 'shiki/engine/oniguruma';
8
-
9
- export type IncremarkCodeTheme = 'dark' | 'light';
10
-
11
- export const TOP_SHIKI_LANGS = [
12
- 'typescript',
13
- 'javascript',
14
- 'python',
15
- 'html',
16
- 'css',
17
- 'sql',
18
- 'shellscript',
19
- 'json',
20
- 'yaml',
21
- 'markdown',
22
- 'java',
23
- 'csharp',
24
- 'cpp',
25
- 'c',
26
- 'php',
27
- 'go',
28
- 'rust',
29
- 'powershell',
30
- 'kotlin',
31
- 'lua',
32
- 'swift',
33
- 'ruby',
34
- 'dart',
35
- 'scala',
36
- 'perl',
37
- 'r',
38
- 'tsx',
39
- 'jsx',
40
- 'dockerfile',
41
- 'vue'
42
- ] as const;
43
-
44
- type SupportedShikiLanguage = (typeof TOP_SHIKI_LANGS)[number];
45
- type SupportedShikiTheme = 'github-dark' | 'github-light';
46
- type ActiveShikiLanguage = SupportedShikiLanguage | typeof FALLBACK_LANGUAGE;
47
-
48
- const SHIKI_THEME_BY_MODE = {
49
- dark: 'github-dark',
50
- light: 'github-light'
51
- } as const satisfies Record<IncremarkCodeTheme, SupportedShikiTheme>;
52
- const FALLBACK_LANGUAGE = 'text' as const;
53
- const SUPPORTED_SHIKI_LANG_SET = new Set<string>(TOP_SHIKI_LANGS);
54
- const LANGUAGE_ALIASES = {
55
- bash: 'shellscript',
56
- 'c#': 'csharp',
57
- cjs: 'javascript',
58
- 'c++': 'cpp',
59
- cs: 'csharp',
60
- docker: 'dockerfile',
61
- golang: 'go',
62
- html: 'html',
63
- js: 'javascript',
64
- jsx: 'jsx',
65
- kt: 'kotlin',
66
- kts: 'kotlin',
67
- md: 'markdown',
68
- mjs: 'javascript',
69
- ps: 'powershell',
70
- ps1: 'powershell',
71
- py: 'python',
72
- rb: 'ruby',
73
- sh: 'shellscript',
74
- shell: 'shellscript',
75
- ts: 'typescript',
76
- tsx: 'tsx',
77
- yml: 'yaml',
78
- zsh: 'shellscript'
79
- } as const satisfies Record<string, SupportedShikiLanguage>;
80
-
81
- const SHIKI_THEME_LOADERS = {
82
- 'github-dark': () => import('@shikijs/themes/github-dark'),
83
- 'github-light': () => import('@shikijs/themes/github-light')
84
- } as const satisfies Record<SupportedShikiTheme, ThemeInput>;
85
-
86
- const SHIKI_LANGUAGE_LOADERS = {
87
- typescript: () => import('@shikijs/langs/typescript'),
88
- javascript: () => import('@shikijs/langs/javascript'),
89
- python: () => import('@shikijs/langs/python'),
90
- html: () => import('@shikijs/langs/html'),
91
- css: () => import('@shikijs/langs/css'),
92
- sql: () => import('@shikijs/langs/sql'),
93
- shellscript: () => import('@shikijs/langs/shellscript'),
94
- json: () => import('@shikijs/langs/json'),
95
- yaml: () => import('@shikijs/langs/yaml'),
96
- markdown: () => import('@shikijs/langs/markdown'),
97
- java: () => import('@shikijs/langs/java'),
98
- csharp: () => import('@shikijs/langs/csharp'),
99
- cpp: () => import('@shikijs/langs/cpp'),
100
- c: () => import('@shikijs/langs/c'),
101
- php: () => import('@shikijs/langs/php'),
102
- go: () => import('@shikijs/langs/go'),
103
- rust: () => import('@shikijs/langs/rust'),
104
- powershell: () => import('@shikijs/langs/powershell'),
105
- kotlin: () => import('@shikijs/langs/kotlin'),
106
- lua: () => import('@shikijs/langs/lua'),
107
- swift: () => import('@shikijs/langs/swift'),
108
- ruby: () => import('@shikijs/langs/ruby'),
109
- dart: () => import('@shikijs/langs/dart'),
110
- scala: () => import('@shikijs/langs/scala'),
111
- perl: () => import('@shikijs/langs/perl'),
112
- r: () => import('@shikijs/langs/r'),
113
- tsx: () => import('@shikijs/langs/tsx'),
114
- jsx: () => import('@shikijs/langs/jsx'),
115
- dockerfile: () => import('@shikijs/langs/dockerfile'),
116
- vue: () => import('@shikijs/langs/vue')
117
- } as const satisfies Record<SupportedShikiLanguage, LanguageInput>;
118
-
119
- const createShikiHighlighter = createBundledHighlighter({
120
- themes: SHIKI_THEME_LOADERS,
121
- langs: SHIKI_LANGUAGE_LOADERS,
122
- engine: () => createOnigurumaEngine(() => import('shiki/wasm'))
123
- });
124
-
125
- interface HighlighterState {
126
- highlighter: HighlighterGeneric<SupportedShikiLanguage, SupportedShikiTheme>;
127
- loadedLanguages: Set<SupportedShikiLanguage>;
128
- loadedThemes: Set<SupportedShikiTheme>;
129
- }
130
-
131
- const MAX_HIGHLIGHT_CACHE_ENTRIES = 200;
132
- const highlightedHtmlCache = new Map<string, string>();
133
- const unsupportedLanguageCache = new Set<string>();
134
-
135
- let highlighterPromise: Promise<HighlighterState> | null = null;
136
-
137
- export async function highlightCodeSnippetHtml(
138
- code: string,
139
- language: string,
140
- theme: IncremarkCodeTheme = 'dark'
141
- ): Promise<string> {
142
- return highlightCodeToHtml(code, language, theme);
143
- }
144
-
145
- export async function highlightRenderedIncremarkHtml(
146
- html: string,
147
- theme: IncremarkCodeTheme = 'dark'
148
- ): Promise<string> {
149
- if (typeof DOMParser === 'undefined' || !html.includes('incremark-code')) {
150
- return html;
151
- }
152
- const document = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');
153
- const codeBlocks = Array.from(document.body.querySelectorAll('.incremark-code'));
154
-
155
- await Promise.all(codeBlocks.map(async (block) => {
156
- const preElement = block.querySelector('pre');
157
- const codeElement = preElement?.querySelector('code');
158
- if (!preElement || !codeElement) {
159
- return;
160
- }
161
-
162
- const sourceCode = codeElement.textContent ?? '';
163
- if (!sourceCode.trim()) {
164
- return;
165
- }
166
-
167
- const languageClass = Array.from(codeElement.classList).find((className) => className.startsWith('language-'));
168
- const language = languageClass ? languageClass.slice('language-'.length) : FALLBACK_LANGUAGE;
169
- const highlightedHtml = await highlightCodeToHtml(sourceCode, language, theme);
170
- const template = document.createElement('template');
171
- template.innerHTML = highlightedHtml.trim();
172
-
173
- const highlightedPre = template.content.firstElementChild;
174
- if (!highlightedPre) {
175
- return;
176
- }
177
-
178
- highlightedPre.classList.add('incremark-code-highlight');
179
- preElement.replaceWith(highlightedPre);
180
- }));
181
- return document.body.innerHTML;
182
- }
183
-
184
- async function highlightCodeToHtml(
185
- code: string,
186
- language: string,
187
- theme: IncremarkCodeTheme
188
- ): Promise<string> {
189
- const normalizedLanguage = normalizeLanguage(language);
190
- const shikiTheme = SHIKI_THEME_BY_MODE[theme];
191
- const cacheKey = `${shikiTheme}\u0000${normalizedLanguage}\u0000${code}`;
192
- const cachedHtml = highlightedHtmlCache.get(cacheKey);
193
- if (cachedHtml) {
194
- return cachedHtml;
195
- }
196
-
197
- const state = await getHighlighter();
198
- await ensureTheme(state, shikiTheme);
199
- const activeLanguage = await ensureLanguage(state, normalizedLanguage);
200
- const highlightedHtml = state.highlighter.codeToHtml(code, {
201
- lang: activeLanguage,
202
- theme: shikiTheme
203
- });
204
-
205
- setHighlightedHtmlCache(cacheKey, highlightedHtml);
206
- return highlightedHtml;
207
- }
208
-
209
- function setHighlightedHtmlCache(cacheKey: string, highlightedHtml: string): void {
210
- if (highlightedHtmlCache.has(cacheKey)) {
211
- highlightedHtmlCache.delete(cacheKey);
212
- }
213
-
214
- highlightedHtmlCache.set(cacheKey, highlightedHtml);
215
-
216
- if (highlightedHtmlCache.size <= MAX_HIGHLIGHT_CACHE_ENTRIES) {
217
- return;
218
- }
219
-
220
- const oldestCacheKey = highlightedHtmlCache.keys().next().value;
221
- if (oldestCacheKey) {
222
- highlightedHtmlCache.delete(oldestCacheKey);
223
- }
224
- }
225
-
226
- async function getHighlighter(): Promise<HighlighterState> {
227
- if (!highlighterPromise) {
228
- highlighterPromise = (async () => {
229
- const highlighter = await createShikiHighlighter({
230
- themes: [],
231
- langs: []
232
- });
233
-
234
- return {
235
- highlighter,
236
- loadedLanguages: new Set(),
237
- loadedThemes: new Set()
238
- };
239
- })();
240
- }
241
-
242
- return highlighterPromise;
243
- }
244
-
245
- async function ensureTheme(state: HighlighterState, theme: SupportedShikiTheme): Promise<void> {
246
- if (state.loadedThemes.has(theme)) {
247
- return;
248
- }
249
-
250
- await state.highlighter.loadTheme(theme);
251
- state.loadedThemes.add(theme);
252
- }
253
-
254
- async function ensureLanguage(state: HighlighterState, language: string): Promise<ActiveShikiLanguage> {
255
- if (language === FALLBACK_LANGUAGE || unsupportedLanguageCache.has(language)) {
256
- return FALLBACK_LANGUAGE;
257
- }
258
-
259
- if (!isSupportedShikiLanguage(language)) {
260
- unsupportedLanguageCache.add(language);
261
- return FALLBACK_LANGUAGE;
262
- }
263
-
264
- if (state.loadedLanguages.has(language)) {
265
- return language;
266
- }
267
-
268
- await state.highlighter.loadLanguage(language);
269
- state.loadedLanguages.add(language);
270
- return language;
271
- }
272
-
273
- function normalizeLanguage(language: string): string {
274
- const normalized = language.trim().toLowerCase();
275
- if (!normalized) {
276
- return FALLBACK_LANGUAGE;
277
- }
278
-
279
- const aliasedLanguage = LANGUAGE_ALIASES[normalized as keyof typeof LANGUAGE_ALIASES];
280
- return aliasedLanguage ?? normalized;
281
- }
282
-
283
- function isSupportedShikiLanguage(language: string): language is SupportedShikiLanguage {
284
- return SUPPORTED_SHIKI_LANG_SET.has(language);
285
- }