@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.
- package/README.md +333 -10
- package/dist/application/ports.d.ts +66 -0
- package/dist/application/runTurnUseCase.d.ts +68 -0
- package/dist/application/runTurnUseCase.js +358 -0
- package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +1 -1
- package/dist/{agent → domain}/systemPrompt.js +1 -1
- package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
- package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +40 -35
- package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
- package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
- package/dist/llm/agentModels.js +65 -0
- package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +11 -2
- package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +38 -6
- package/dist/llm/langGraphLlm.d.ts +25 -0
- package/dist/llm/langGraphLlm.js +54 -0
- package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
- package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
- package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
- package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
- package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
- package/dist/llm/streamAdapter.d.ts +18 -0
- package/dist/llm/streamAdapter.js +117 -0
- package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +12 -2
- package/dist/{sessionStore.js → persistence/sessionStore.js} +33 -0
- package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
- package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
- package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +10 -6
- package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
- package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
- package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
- package/dist/{agent/tools → tools}/index.d.ts +1 -1
- package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
- package/dist/{endpoints → transport/http}/context.d.ts +2 -2
- package/dist/transport/http/context.js +1 -0
- package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +3 -3
- package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +7 -1
- package/dist/transport/sse/sseWriter.d.ts +29 -0
- package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +15 -0
- package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
- package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
- package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
- package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
- package/dist/types.d.ts +10 -4
- package/package.json +11 -2
- package/.woodpecker/buildRelease.sh +0 -13
- package/.woodpecker/buildSlackNotify.sh +0 -46
- package/.woodpecker/release.yml +0 -57
- package/agent/checkpointer.ts +0 -329
- package/agent/languageDetect.ts +0 -92
- package/agent/middleware/apiBasedTools.ts +0 -174
- package/agent/middleware/openAiResponsesContinuation.ts +0 -92
- package/agent/middleware/sequenceDebug.ts +0 -429
- package/agent/models/AgentModeResolver.ts +0 -9
- package/agent/models/AgentModelFactory.ts +0 -28
- package/agent/runtime/AgentContext.ts +0 -30
- package/agent/runtime/AgentRuntime.ts +0 -89
- package/agent/simpleAgent.ts +0 -199
- package/agent/skills/registry.ts +0 -162
- package/agent/speech/SpeechTurnService.ts +0 -179
- package/agent/systemPrompt.ts +0 -133
- package/agent/toolCallEvents.ts +0 -135
- package/agent/tools/AgentToolProvider.ts +0 -28
- package/agent/tools/apiTool.ts +0 -66
- package/agent/tools/fetchSkill.ts +0 -68
- package/agent/tools/fetchToolSchema.ts +0 -47
- package/agent/tools/getUserLocation.ts +0 -45
- package/agent/tools/index.ts +0 -31
- package/agent/tools/navigateUser.ts +0 -210
- package/agent/turn/TurnContextBuilder.ts +0 -36
- package/agent/turn/TurnLifecycleService.ts +0 -47
- package/agent/turn/TurnPersistenceService.ts +0 -33
- package/agent/turn/TurnPromptBuilder.ts +0 -51
- package/agent/turn/TurnStreamConsumer.ts +0 -69
- package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
- package/agent/turn/turnTypes.ts +0 -100
- package/agentEvents.ts +0 -75
- package/agentTurnService.ts +0 -314
- package/apiBasedTools.ts +0 -702
- package/build.log +0 -67
- package/chatSurfaceService.ts +0 -319
- package/custom/ChatFooter.vue +0 -173
- package/custom/ChatHeader.vue +0 -78
- package/custom/ChatSurface.vue +0 -160
- package/custom/CustomAutoScrollContainer.vue +0 -164
- package/custom/SessionsHistory.vue +0 -88
- package/custom/chat.ts +0 -82
- package/custom/composables/agentAudio/utils.ts +0 -220
- package/custom/composables/agentStore/constants.ts +0 -19
- package/custom/composables/agentStore/pageContext.ts +0 -8
- package/custom/composables/agentStore/useAgentChat.ts +0 -241
- package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
- package/custom/composables/agentStore/useAgentSessions.ts +0 -350
- package/custom/composables/useAgentAudio.ts +0 -272
- package/custom/composables/useAgentStore.ts +0 -510
- package/custom/composables/useAgentTransitions.ts +0 -58
- package/custom/conversation_area/ConversationArea.vue +0 -301
- package/custom/conversation_area/MessageRenderer.vue +0 -49
- package/custom/conversation_area/ProcessingTimeline.vue +0 -286
- package/custom/conversation_area/ReasoningRenderer.vue +0 -79
- package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
- package/custom/conversation_area/TextRenderer.vue +0 -182
- package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
- package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
- package/custom/conversation_area/ToolRenderer.vue +0 -178
- package/custom/conversation_area/ToolsGroup.vue +0 -59
- package/custom/env.d.ts +0 -7
- package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
- package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
- package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
- package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
- package/custom/package.json +0 -30
- package/custom/pnpm-lock.yaml +0 -2394
- package/custom/public/agentAudio/agent-processing.mp3 +0 -0
- package/custom/skills/analyze_data/SKILL.md +0 -25
- package/custom/skills/charts/SKILL.md +0 -193
- package/custom/skills/fetch_data/SKILL.md +0 -31
- package/custom/skills/mutate_data/SKILL.md +0 -121
- package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
- package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
- package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
- package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
- package/custom/tsconfig.json +0 -15
- package/custom/types.ts +0 -108
- package/custom/utils.ts +0 -38
- package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
- package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
- package/dist/agent/models/AgentModeResolver.d.ts +0 -9
- package/dist/agent/models/AgentModeResolver.js +0 -9
- package/dist/agent/simpleAgent.js +0 -118
- package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
- package/dist/agent/turn/TurnContextBuilder.js +0 -31
- package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
- package/dist/agent/turn/TurnLifecycleService.js +0 -47
- package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
- package/dist/agent/turn/TurnPersistenceService.js +0 -35
- package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
- package/dist/agent/turn/TurnPromptBuilder.js +0 -43
- package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
- package/dist/agent/turn/TurnStreamConsumer.js +0 -84
- package/dist/agentTurnService.d.ts +0 -24
- package/dist/agentTurnService.js +0 -269
- package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
- package/endpoints/chatSurfaces.ts +0 -66
- package/endpoints/context.ts +0 -52
- package/endpoints/core.ts +0 -181
- package/endpoints/sessions.ts +0 -183
- package/errors.ts +0 -10
- package/index.ts +0 -192
- package/pnpm-workspace.yaml +0 -4
- package/sanitizeSpeechText.ts +0 -32
- package/sessionStore.ts +0 -105
- package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
- package/tsconfig.json +0 -14
- package/types.ts +0 -127
- /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
- /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
- /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
- /package/dist/{agent → domain}/languageDetect.js +0 -0
- /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
- /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
- /package/dist/{agent → domain}/toolCallEvents.js +0 -0
- /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
- /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
- /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
- /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
- /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
- /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
- /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
- /package/dist/{errors.js → shared/errors.js} +0 -0
- /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
- /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
- /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
- /package/dist/{agent/tools → tools}/apiTool.js +0 -0
- /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
- /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
- /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
- /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
- /package/dist/{agent/tools → tools}/index.js +0 -0
- /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
- /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
- /package/dist/{agent → tools}/skills/registry.js +0 -0
- /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
- /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
- /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
- /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
|
-
}
|