@adminforth/agent 2.0.10 → 2.2.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 (201) hide show
  1. package/README.md +333 -10
  2. package/dist/application/ports.d.ts +66 -0
  3. package/dist/application/runTurnUseCase.d.ts +71 -0
  4. package/dist/application/runTurnUseCase.js +364 -0
  5. package/dist/custom/ChatFooter.vue +58 -30
  6. package/dist/custom/SteerDebugPanel.vue +45 -0
  7. package/dist/custom/SteerQueue.vue +54 -0
  8. package/dist/custom/composables/agentStore/constants.ts +1 -0
  9. package/dist/custom/composables/agentStore/useAgentSessions.ts +35 -16
  10. package/dist/custom/composables/agentStore/useAgentSteerQueue.ts +114 -0
  11. package/dist/custom/composables/useAgentStore.ts +46 -1
  12. package/dist/custom/conversation_area/MessageRenderer.vue +7 -1
  13. package/dist/custom/speech_recognition_frontend/AudioLines.vue +1 -1
  14. package/dist/custom/speech_recognition_frontend/MicrophoneButon.vue +3 -3
  15. package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +5 -1
  16. package/dist/domain/steerBuffer.d.ts +33 -0
  17. package/dist/domain/steerBuffer.js +51 -0
  18. package/dist/{agent → domain}/systemPrompt.js +1 -1
  19. package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
  20. package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
  21. package/dist/index.d.ts +4 -2
  22. package/dist/index.js +49 -35
  23. package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
  24. package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
  25. package/dist/llm/agentModels.js +65 -0
  26. package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +14 -2
  27. package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +41 -6
  28. package/dist/llm/langGraphLlm.d.ts +25 -0
  29. package/dist/llm/langGraphLlm.js +54 -0
  30. package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
  31. package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
  32. package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
  33. package/dist/llm/middleware/steerMiddleware.d.ts +21 -0
  34. package/dist/llm/middleware/steerMiddleware.js +50 -0
  35. package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
  36. package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
  37. package/dist/llm/streamAdapter.d.ts +18 -0
  38. package/dist/llm/streamAdapter.js +117 -0
  39. package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +19 -2
  40. package/dist/{sessionStore.js → persistence/sessionStore.js} +53 -0
  41. package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
  42. package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
  43. package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +0 -3
  44. package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
  45. package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
  46. package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
  47. package/dist/{agent/tools → tools}/index.d.ts +1 -1
  48. package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
  49. package/dist/{endpoints → transport/http}/context.d.ts +12 -4
  50. package/dist/transport/http/context.js +1 -0
  51. package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +23 -3
  52. package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +36 -1
  53. package/dist/transport/sse/sseWriter.d.ts +29 -0
  54. package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +27 -0
  55. package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
  56. package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
  57. package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
  58. package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
  59. package/dist/types.d.ts +10 -4
  60. package/package.json +11 -2
  61. package/.woodpecker/buildRelease.sh +0 -13
  62. package/.woodpecker/buildSlackNotify.sh +0 -46
  63. package/.woodpecker/release.yml +0 -57
  64. package/agent/checkpointer.ts +0 -329
  65. package/agent/languageDetect.ts +0 -92
  66. package/agent/middleware/apiBasedTools.ts +0 -174
  67. package/agent/middleware/openAiResponsesContinuation.ts +0 -92
  68. package/agent/middleware/sequenceDebug.ts +0 -429
  69. package/agent/models/AgentModeResolver.ts +0 -9
  70. package/agent/models/AgentModelFactory.ts +0 -28
  71. package/agent/runtime/AgentContext.ts +0 -30
  72. package/agent/runtime/AgentRuntime.ts +0 -89
  73. package/agent/simpleAgent.ts +0 -199
  74. package/agent/skills/registry.ts +0 -162
  75. package/agent/speech/SpeechTurnService.ts +0 -179
  76. package/agent/systemPrompt.ts +0 -133
  77. package/agent/toolCallEvents.ts +0 -135
  78. package/agent/tools/AgentToolProvider.ts +0 -28
  79. package/agent/tools/apiTool.ts +0 -66
  80. package/agent/tools/fetchSkill.ts +0 -68
  81. package/agent/tools/fetchToolSchema.ts +0 -47
  82. package/agent/tools/getUserLocation.ts +0 -45
  83. package/agent/tools/index.ts +0 -31
  84. package/agent/tools/navigateUser.ts +0 -210
  85. package/agent/turn/TurnContextBuilder.ts +0 -36
  86. package/agent/turn/TurnLifecycleService.ts +0 -47
  87. package/agent/turn/TurnPersistenceService.ts +0 -33
  88. package/agent/turn/TurnPromptBuilder.ts +0 -51
  89. package/agent/turn/TurnStreamConsumer.ts +0 -69
  90. package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
  91. package/agent/turn/turnTypes.ts +0 -100
  92. package/agentEvents.ts +0 -75
  93. package/agentTurnService.ts +0 -314
  94. package/apiBasedTools.ts +0 -712
  95. package/build.log +0 -67
  96. package/chatSurfaceService.ts +0 -319
  97. package/custom/ChatFooter.vue +0 -173
  98. package/custom/ChatHeader.vue +0 -78
  99. package/custom/ChatSurface.vue +0 -160
  100. package/custom/CustomAutoScrollContainer.vue +0 -164
  101. package/custom/SessionsHistory.vue +0 -88
  102. package/custom/chat.ts +0 -82
  103. package/custom/composables/agentAudio/utils.ts +0 -220
  104. package/custom/composables/agentStore/constants.ts +0 -19
  105. package/custom/composables/agentStore/pageContext.ts +0 -8
  106. package/custom/composables/agentStore/useAgentChat.ts +0 -241
  107. package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
  108. package/custom/composables/agentStore/useAgentSessions.ts +0 -350
  109. package/custom/composables/useAgentAudio.ts +0 -272
  110. package/custom/composables/useAgentStore.ts +0 -510
  111. package/custom/composables/useAgentTransitions.ts +0 -58
  112. package/custom/conversation_area/ConversationArea.vue +0 -301
  113. package/custom/conversation_area/MessageRenderer.vue +0 -49
  114. package/custom/conversation_area/ProcessingTimeline.vue +0 -286
  115. package/custom/conversation_area/ReasoningRenderer.vue +0 -79
  116. package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
  117. package/custom/conversation_area/TextRenderer.vue +0 -182
  118. package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
  119. package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
  120. package/custom/conversation_area/ToolRenderer.vue +0 -178
  121. package/custom/conversation_area/ToolsGroup.vue +0 -59
  122. package/custom/env.d.ts +0 -7
  123. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
  124. package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
  125. package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
  126. package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
  127. package/custom/package.json +0 -30
  128. package/custom/pnpm-lock.yaml +0 -2394
  129. package/custom/public/agentAudio/agent-processing.mp3 +0 -0
  130. package/custom/skills/analyze_data/SKILL.md +0 -25
  131. package/custom/skills/charts/SKILL.md +0 -193
  132. package/custom/skills/fetch_data/SKILL.md +0 -31
  133. package/custom/skills/mutate_data/SKILL.md +0 -121
  134. package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
  135. package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
  136. package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
  137. package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
  138. package/custom/tsconfig.json +0 -15
  139. package/custom/types.ts +0 -108
  140. package/custom/utils.ts +0 -38
  141. package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
  142. package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
  143. package/dist/agent/models/AgentModeResolver.d.ts +0 -9
  144. package/dist/agent/models/AgentModeResolver.js +0 -9
  145. package/dist/agent/simpleAgent.js +0 -118
  146. package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
  147. package/dist/agent/turn/TurnContextBuilder.js +0 -31
  148. package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
  149. package/dist/agent/turn/TurnLifecycleService.js +0 -47
  150. package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
  151. package/dist/agent/turn/TurnPersistenceService.js +0 -35
  152. package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
  153. package/dist/agent/turn/TurnPromptBuilder.js +0 -43
  154. package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
  155. package/dist/agent/turn/TurnStreamConsumer.js +0 -84
  156. package/dist/agentTurnService.d.ts +0 -24
  157. package/dist/agentTurnService.js +0 -269
  158. package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
  159. package/endpoints/chatSurfaces.ts +0 -66
  160. package/endpoints/context.ts +0 -52
  161. package/endpoints/core.ts +0 -181
  162. package/endpoints/sessions.ts +0 -183
  163. package/errors.ts +0 -10
  164. package/index.ts +0 -192
  165. package/pnpm-workspace.yaml +0 -4
  166. package/sanitizeSpeechText.ts +0 -32
  167. package/sessionStore.ts +0 -105
  168. package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
  169. package/tsconfig.json +0 -14
  170. package/types.ts +0 -127
  171. /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
  172. /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
  173. /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
  174. /package/dist/{agent → domain}/languageDetect.js +0 -0
  175. /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
  176. /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
  177. /package/dist/{agent → domain}/toolCallEvents.js +0 -0
  178. /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
  179. /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
  180. /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
  181. /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
  182. /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
  183. /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
  184. /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
  185. /package/dist/{errors.js → shared/errors.js} +0 -0
  186. /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
  187. /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
  188. /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
  189. /package/dist/{agent/tools → tools}/apiTool.js +0 -0
  190. /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
  191. /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
  192. /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
  193. /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
  194. /package/dist/{agent/tools → tools}/index.js +0 -0
  195. /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
  196. /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
  197. /package/dist/{agent → tools}/skills/registry.js +0 -0
  198. /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
  199. /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
  200. /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
  201. /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
- }