entari-plugin-hyw 4.0.0rc7__py3-none-any.whl → 4.0.0rc8__py3-none-any.whl

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.

Potentially problematic release.


This version of entari-plugin-hyw might be problematic. Click here for more details.

Files changed (114) hide show
  1. entari_plugin_hyw/Untitled-1 +1865 -0
  2. entari_plugin_hyw/__init__.py +726 -394
  3. entari_plugin_hyw/history.py +26 -13
  4. entari_plugin_hyw/misc.py +3 -0
  5. entari_plugin_hyw/search_cache.py +154 -0
  6. {entari_plugin_hyw-4.0.0rc7.dist-info → entari_plugin_hyw-4.0.0rc8.dist-info}/METADATA +3 -1
  7. entari_plugin_hyw-4.0.0rc8.dist-info/RECORD +68 -0
  8. {entari_plugin_hyw-4.0.0rc7.dist-info → entari_plugin_hyw-4.0.0rc8.dist-info}/WHEEL +1 -1
  9. {entari_plugin_hyw-4.0.0rc7.dist-info → entari_plugin_hyw-4.0.0rc8.dist-info}/top_level.txt +1 -0
  10. hyw_core/__init__.py +94 -0
  11. hyw_core/browser_control/__init__.py +65 -0
  12. hyw_core/browser_control/assets/card-dist/index.html +409 -0
  13. hyw_core/browser_control/assets/index.html +5691 -0
  14. hyw_core/browser_control/engines/__init__.py +17 -0
  15. {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/duckduckgo.py +42 -8
  16. {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/google.py +1 -1
  17. {entari_plugin_hyw/browser → hyw_core/browser_control}/manager.py +15 -8
  18. entari_plugin_hyw/render_vue.py → hyw_core/browser_control/renderer.py +29 -14
  19. {entari_plugin_hyw/browser → hyw_core/browser_control}/service.py +287 -112
  20. hyw_core/config.py +154 -0
  21. hyw_core/core.py +322 -0
  22. hyw_core/definitions.py +83 -0
  23. entari_plugin_hyw/modular_pipeline.py → hyw_core/pipeline.py +121 -97
  24. {entari_plugin_hyw → hyw_core}/search.py +19 -14
  25. hyw_core/stages/__init__.py +21 -0
  26. entari_plugin_hyw/stage_base.py → hyw_core/stages/base.py +2 -2
  27. entari_plugin_hyw/stage_summary.py → hyw_core/stages/summary.py +34 -11
  28. entari_plugin_hyw/assets/card-dist/index.html +0 -387
  29. entari_plugin_hyw/browser/__init__.py +0 -10
  30. entari_plugin_hyw/browser/engines/bing.py +0 -95
  31. entari_plugin_hyw/card-ui/.gitignore +0 -24
  32. entari_plugin_hyw/card-ui/README.md +0 -5
  33. entari_plugin_hyw/card-ui/index.html +0 -16
  34. entari_plugin_hyw/card-ui/package-lock.json +0 -2342
  35. entari_plugin_hyw/card-ui/package.json +0 -31
  36. entari_plugin_hyw/card-ui/public/logos/anthropic.svg +0 -1
  37. entari_plugin_hyw/card-ui/public/logos/cerebras.svg +0 -9
  38. entari_plugin_hyw/card-ui/public/logos/deepseek.png +0 -0
  39. entari_plugin_hyw/card-ui/public/logos/gemini.svg +0 -1
  40. entari_plugin_hyw/card-ui/public/logos/google.svg +0 -1
  41. entari_plugin_hyw/card-ui/public/logos/grok.png +0 -0
  42. entari_plugin_hyw/card-ui/public/logos/huggingface.png +0 -0
  43. entari_plugin_hyw/card-ui/public/logos/microsoft.svg +0 -15
  44. entari_plugin_hyw/card-ui/public/logos/minimax.png +0 -0
  45. entari_plugin_hyw/card-ui/public/logos/mistral.png +0 -0
  46. entari_plugin_hyw/card-ui/public/logos/nvida.png +0 -0
  47. entari_plugin_hyw/card-ui/public/logos/openai.svg +0 -1
  48. entari_plugin_hyw/card-ui/public/logos/openrouter.png +0 -0
  49. entari_plugin_hyw/card-ui/public/logos/perplexity.svg +0 -24
  50. entari_plugin_hyw/card-ui/public/logos/qwen.png +0 -0
  51. entari_plugin_hyw/card-ui/public/logos/xai.png +0 -0
  52. entari_plugin_hyw/card-ui/public/logos/xiaomi.png +0 -0
  53. entari_plugin_hyw/card-ui/public/logos/zai.png +0 -0
  54. entari_plugin_hyw/card-ui/public/vite.svg +0 -1
  55. entari_plugin_hyw/card-ui/src/App.vue +0 -787
  56. entari_plugin_hyw/card-ui/src/assets/vue.svg +0 -1
  57. entari_plugin_hyw/card-ui/src/components/HelloWorld.vue +0 -41
  58. entari_plugin_hyw/card-ui/src/components/MarkdownContent.vue +0 -382
  59. entari_plugin_hyw/card-ui/src/components/SectionCard.vue +0 -41
  60. entari_plugin_hyw/card-ui/src/components/StageCard.vue +0 -240
  61. entari_plugin_hyw/card-ui/src/main.ts +0 -5
  62. entari_plugin_hyw/card-ui/src/style.css +0 -29
  63. entari_plugin_hyw/card-ui/src/test_regex.js +0 -103
  64. entari_plugin_hyw/card-ui/src/types.ts +0 -61
  65. entari_plugin_hyw/card-ui/tsconfig.app.json +0 -16
  66. entari_plugin_hyw/card-ui/tsconfig.json +0 -7
  67. entari_plugin_hyw/card-ui/tsconfig.node.json +0 -26
  68. entari_plugin_hyw/card-ui/vite.config.ts +0 -16
  69. entari_plugin_hyw/definitions.py +0 -174
  70. entari_plugin_hyw/stage_instruct.py +0 -355
  71. entari_plugin_hyw/stage_instruct_deepsearch.py +0 -104
  72. entari_plugin_hyw/stage_vision.py +0 -113
  73. entari_plugin_hyw-4.0.0rc7.dist-info/RECORD +0 -102
  74. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/anthropic.svg +0 -0
  75. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/cerebras.svg +0 -0
  76. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/deepseek.png +0 -0
  77. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/gemini.svg +0 -0
  78. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/google.svg +0 -0
  79. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/grok.png +0 -0
  80. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/huggingface.png +0 -0
  81. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/microsoft.svg +0 -0
  82. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/minimax.png +0 -0
  83. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/mistral.png +0 -0
  84. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/nvida.png +0 -0
  85. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/openai.svg +0 -0
  86. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/openrouter.png +0 -0
  87. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/perplexity.svg +0 -0
  88. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/qwen.png +0 -0
  89. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/xai.png +0 -0
  90. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/xiaomi.png +0 -0
  91. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/zai.png +0 -0
  92. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/vite.svg +0 -0
  93. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/anthropic.svg +0 -0
  94. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/cerebras.svg +0 -0
  95. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/deepseek.png +0 -0
  96. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/gemini.svg +0 -0
  97. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/google.svg +0 -0
  98. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/grok.png +0 -0
  99. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/huggingface.png +0 -0
  100. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/microsoft.svg +0 -0
  101. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/minimax.png +0 -0
  102. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/mistral.png +0 -0
  103. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/nvida.png +0 -0
  104. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/openai.svg +0 -0
  105. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/openrouter.png +0 -0
  106. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/perplexity.svg +0 -0
  107. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/qwen.png +0 -0
  108. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/xai.png +0 -0
  109. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/xiaomi.png +0 -0
  110. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/zai.png +0 -0
  111. {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/base.py +0 -0
  112. {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/default.py +0 -0
  113. {entari_plugin_hyw/browser → hyw_core/browser_control}/landing.html +0 -0
  114. {entari_plugin_hyw → hyw_core}/image_cache.py +0 -0
@@ -1,240 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, computed } from 'vue'
3
- import { Icon } from '@iconify/vue'
4
- import type { Stage } from '../types'
5
-
6
- const props = defineProps<{
7
- stage: Stage
8
- isFirst?: boolean
9
- isLast?: boolean
10
- prevStageName?: string
11
- refOffset?: number
12
- hideRefs?: boolean
13
- }>()
14
-
15
- const failedImages = ref<Record<string, boolean>>({})
16
- const imageHeights = ref<Record<string, number>>({})
17
-
18
- function handleImageError(url: string) {
19
- failedImages.value[url] = true
20
- }
21
-
22
- function handleImageLoad(url: string, event: Event) {
23
- const img = event.target as HTMLImageElement
24
- if (img.naturalWidth && img.naturalHeight) {
25
- // Store aspect ratio as height per unit width
26
- imageHeights.value[url] = img.naturalHeight / img.naturalWidth
27
- }
28
- }
29
-
30
- // Compute two columns for masonry layout
31
- const imageColumns = computed(() => {
32
- const images = props.stage.image_references || []
33
- const leftColumn: typeof images = []
34
- const rightColumn: typeof images = []
35
- let leftHeight = 0
36
- let rightHeight = 0
37
-
38
- for (const img of images) {
39
- if (failedImages.value[img.url]) continue
40
-
41
- // Get aspect ratio (default to 1 if not loaded yet)
42
- const aspectRatio = imageHeights.value[img.url] || 1
43
-
44
- // Add to shorter column
45
- if (leftHeight <= rightHeight) {
46
- leftColumn.push(img)
47
- leftHeight += aspectRatio
48
- } else {
49
- rightColumn.push(img)
50
- rightHeight += aspectRatio
51
- }
52
- }
53
-
54
- return { leftColumn, rightColumn }
55
- })
56
-
57
-
58
-
59
-
60
-
61
- function getDomain(url: string): string {
62
- try {
63
- const urlObj = new URL(url)
64
- const hostname = urlObj.hostname.replace('www.', '')
65
- const pathname = urlObj.pathname === '/' ? '' : urlObj.pathname
66
- return hostname + pathname
67
- } catch {
68
- return url
69
- }
70
- }
71
-
72
- function getFavicon(url: string): string {
73
- const domain = getDomain(url)
74
- return `https://www.google.com/s2/favicons?domain=${domain}&sz=32`
75
- }
76
-
77
- function formatTime(seconds: number): string {
78
- return `${seconds.toFixed(2)}s`
79
- }
80
-
81
- function formatCost(dollars: number): string {
82
- return dollars > 0 ? `$${dollars.toFixed(6)}` : '$0'
83
- }
84
-
85
- function getModelShort(model: string): string {
86
- const short = model.includes('/') ? model.split('/').pop() || model : model
87
- return short.length > 25 ? short.slice(0, 23) + '…' : short
88
- }
89
-
90
- function getStageTheme(name?: string) {
91
- if (!name) return themes['default']
92
- const key = name.toLowerCase()
93
-
94
- if (key.includes('search')) return themes['search']
95
- if (key.includes('crawl') || key.includes('page')) return themes['crawler']
96
- if (key.includes('agent')) return themes['agent']
97
- if (key.includes('instruct')) return themes['instruct']
98
- if (key.includes('vision')) return themes['vision']
99
-
100
- return themes['default']
101
- }
102
-
103
- const themes: Record<string, any> = {
104
- 'search': { color: 'text-blue-600', bg: 'bg-blue-50', iconBg: 'bg-blue-100/50', icon: 'mdi:magnify' },
105
- 'crawler': { color: 'text-orange-600', bg: 'bg-orange-50', iconBg: 'bg-orange-100/50', icon: 'mdi:web' },
106
- 'agent': { color: 'text-purple-600', bg: 'bg-purple-50', iconBg: 'bg-white/80', icon: 'mdi:robot' },
107
- 'instruct': { color: 'text-red-600', bg: 'bg-red-50', iconBg: 'bg-white/80', icon: 'mdi:lightning-bolt' },
108
- 'vision': { color: 'text-purple-600', bg: 'bg-purple-50', iconBg: 'bg-white/80', icon: 'mdi:eye' },
109
- 'default': { color: 'text-gray-600', bg: 'bg-gray-50', iconBg: 'bg-gray-100/50', icon: 'mdi:circle' }
110
- }
111
-
112
- function getIcon(name: string): string {
113
- const key = name.toLowerCase()
114
- if (key.includes('search')) return 'mdi:magnify'
115
- if (key.includes('crawl') || key.includes('page')) return 'mdi:web'
116
- if (key.includes('agent')) return 'mdi:robot'
117
- if (key.includes('instruct')) return 'mdi:lightning-bolt'
118
- if (key.includes('vision')) return 'mdi:eye'
119
- return 'mdi:circle'
120
- }
121
-
122
- function getModelLogo(model: string): string | undefined {
123
- if (!model) return undefined
124
- const m = model.toLowerCase()
125
- if (m.includes('openai') || m.includes('gpt')) return 'logos/openai.svg'
126
- if (m.includes('claude') || m.includes('anthropic')) return 'logos/anthropic.svg'
127
- if (m.includes('gemini') || m.includes('google')) return 'logos/google.svg'
128
- if (m.includes('deepseek')) return 'logos/deepseek.png'
129
- if (m.includes('huggingface')) return 'logos/huggingface.png'
130
- if (m.includes('mistral')) return 'logos/mistral.png'
131
- if (m.includes('perplexity')) return 'logos/perplexity.svg'
132
- if (m.includes('cerebras')) return 'logos/cerebras.svg'
133
- if (m.includes('grok')) return 'logos/grok.png'
134
- if (m.includes('qwen')) return 'logos/qwen.png'
135
- if (m.includes('minimax')) return 'logos/minimax.png'
136
- if (m.includes('nvidia') || m.includes('nvida')) return 'logos/nvida.png'
137
- if (m.includes('azure') || m.includes('microsoft')) return 'logos/microsoft.svg'
138
- if (m.includes('xai')) return 'logos/xai.png'
139
- if (m.includes('xiaomi')) return 'logos/xiaomi.png'
140
- if (m.includes('zai')) return 'logos/zai.png'
141
- return undefined
142
- }
143
- </script>
144
-
145
- <template>
146
- <div class="relative">
147
- <!-- Content -->
148
- <div class="flex-1 min-w-0 pl-2">
149
- <div class="rounded-none overflow-hidden bg-white">
150
-
151
- <!-- Header -->
152
- <div :class="['bg-white px-4 py-2.5 flex items-center justify-between gap-3']">
153
- <div class="flex items-center gap-3">
154
- <div :class="['w-8 h-8 flex items-center justify-center shrink-0 overflow-hidden border border-gray-100', getStageTheme(stage.name).iconBg, getStageTheme(stage.name).color]">
155
- <img v-if="getModelLogo(stage.model)" :src="getModelLogo(stage.model)" class="w-5 h-5 object-contain" />
156
- <Icon v-else :icon="getIcon(stage.name)" class="text-lg" />
157
- </div>
158
- <div class="flex flex-col">
159
- <span class="font-black text-[18px] text-gray-800 uppercase tracking-tight">{{ stage.name }}</span>
160
- <span class="text-[15.5px] font-mono tabular-nums tracking-tighter" style="color: var(--text-muted)">{{ getModelShort(stage.model) }}</span>
161
- </div>
162
- </div>
163
- <div v-if="stage.time > 0 || stage.cost > 0" class="text-[15.5px] font-mono flex items-center justify-end gap-2 leading-tight min-w-[120px]" style="color: var(--text-muted)">
164
- <span v-if="stage.cost > 0">{{ formatCost(stage.cost) }}</span>
165
- <span v-if="stage.time > 0 && stage.cost > 0" class="text-gray-300">·</span>
166
- <span v-if="stage.time > 0">{{ formatTime(stage.time) }}</span>
167
- </div>
168
- </div>
169
-
170
-
171
- <div v-if="stage.description" class="px-5 py-3 text-[14.5px] text-gray-600 bg-gray-50/40 border-y border-gray-100 italic leading-relaxed font-sans">
172
- <span class="mr-1 text-[var(--theme-color)] not-italic opacity-50">✦</span> {{ stage.description }}
173
- </div>
174
-
175
- <div v-if="stage.references?.length || stage.image_references?.length || stage.crawled_pages?.length || stage.tasks?.length" class="bg-white pl-11 relative">
176
-
177
- <!-- Tasks List -->
178
- <div v-if="stage.tasks?.length" class="pr-3 py-3 relative z-10 border-b border-gray-50 last:border-0">
179
- <div v-for="(task, idx) in stage.tasks" :key="idx" class="flex items-start gap-2.5 mb-2 last:mb-0">
180
- <div class="w-4 h-4 rounded-full border border-[var(--theme-color)] flex items-center justify-center shrink-0 mt-0.5 bg-[var(--theme-color)]/10">
181
- <Icon icon="mdi:check" class="text-[10px] text-[var(--theme-color)]" />
182
- </div>
183
- <span class="text-[15px] text-gray-700 font-medium leading-tight select-text">{{ task }}</span>
184
- </div>
185
- </div>
186
-
187
- <!-- Image Search Results - True Masonry Layout -->
188
- <div v-if="stage.image_references?.length && !hideRefs" class="pr-3 py-3 relative z-10">
189
- <div class="flex gap-2">
190
- <!-- Left Column -->
191
- <div class="flex-1 flex flex-col gap-2">
192
- <a v-for="(img, idx) in imageColumns.leftColumn" :key="`left-${img.url}-${idx}`"
193
- :href="img.url" target="_blank"
194
- class="relative overflow-hidden transition-all hover:opacity-90 group block">
195
- <img :src="img.thumbnail || img.url"
196
- @load="handleImageLoad(img.url, $event)"
197
- @error="handleImageError(img.url)"
198
- class="w-full h-auto block group-hover:scale-[1.02] transition-transform">
199
- </a>
200
- </div>
201
- <!-- Right Column -->
202
- <div class="flex-1 flex flex-col gap-2">
203
- <a v-for="(img, idx) in imageColumns.rightColumn" :key="`right-${img.url}-${idx}`"
204
- :href="img.url" target="_blank"
205
- class="relative overflow-hidden transition-all hover:opacity-90 group block">
206
- <img :src="img.thumbnail || img.url"
207
- @load="handleImageLoad(img.url, $event)"
208
- @error="handleImageError(img.url)"
209
- class="w-full h-auto block group-hover:scale-[1.02] transition-transform">
210
- </a>
211
- </div>
212
- </div>
213
- </div>
214
-
215
- <div v-if="stage.crawled_pages?.length && !hideRefs" class="divide-y divide-gray-50 relative z-10">
216
- <div v-for="(page, idx) in stage.crawled_pages" :key="idx" class="pr-3 py-3 hover:bg-gray-50 transition-colors group">
217
- <!-- Header Row: Title & Link -->
218
- <a :href="page.url" target="_blank" class="flex items-start gap-3 block">
219
- <img :src="getFavicon(page.url)" class="w-4 h-4 rounded-none shrink-0 object-contain mt-[4px]">
220
- <div class="flex-1 min-w-0 flex flex-col">
221
- <div class="flex items-center gap-2">
222
- <span class="flex-1 text-[18px] font-bold text-gray-700 truncate leading-tight tracking-tight group-hover:text-[var(--theme-color)] transition-colors">{{ page.title }}</span>
223
- <!-- Square Badge with Shadow -->
224
- <span class="shrink-0 w-[18px] h-[18px] text-[11px] font-bold flex items-center justify-center" style="background-color: var(--theme-color); color: var(--header-text-color); box-shadow: 0 1px 3px 0 rgba(0,0,0,0.15)">{{ (refOffset || 0) + (stage.references?.length || 0) + idx + 1 }}</span>
225
- </div>
226
- <div class="text-[15.5px] font-mono truncate mt-0.5 tracking-tighter" style="color: var(--text-muted)">{{ getDomain(page.url) }}</div>
227
- </div>
228
- </a>
229
-
230
- <!-- Description Sub-container -->
231
- <div v-if="page.description" class="ml-7 mt-2.5 p-3 bg-gray-100/80 text-[14px] text-gray-600 leading-snug font-sans border-l-[3px] border-[var(--theme-color)] rounded-r-sm">
232
- {{ page.description }}
233
- </div>
234
- </div>
235
- </div>
236
- </div>
237
- </div>
238
- </div>
239
- </div>
240
- </template>
@@ -1,5 +0,0 @@
1
- import { createApp } from 'vue'
2
- import './style.css'
3
- import App from './App.vue'
4
-
5
- createApp(App).mount('#app')
@@ -1,29 +0,0 @@
1
- @import "tailwindcss";
2
- @plugin "daisyui";
3
- @plugin "@tailwindcss/typography";
4
-
5
- /* Custom styles */
6
- body {
7
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
8
- }
9
-
10
- /* Premium reading color scheme - applies to all prose elements */
11
- .prose {
12
- color: var(--text-body, #3a3a3c) !important;
13
- }
14
-
15
- .prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 {
16
- color: var(--text-primary, #2c2c2e) !important;
17
- }
18
-
19
- .prose p, .prose li, .prose td, .prose th {
20
- color: var(--text-body, #3a3a3c) !important;
21
- }
22
-
23
- .prose strong, .prose b {
24
- color: var(--text-primary, #2c2c2e) !important;
25
- }
26
-
27
- .prose code {
28
- color: var(--text-body, #3a3a3c) !important;
29
- }
@@ -1,103 +0,0 @@
1
-
2
- const stripPrefixBeforeH1 = (text) => {
3
- const h1Match = text.match(/^#\s+/m)
4
- if (h1Match && h1Match.index !== undefined) {
5
- return text.substring(h1Match.index)
6
- }
7
- return text
8
- }
9
-
10
- const dedent = (text) => {
11
- const lines = text.split('\n')
12
- // Find minimum indentation of non-empty lines
13
- let minIndent = Infinity
14
- for (const line of lines) {
15
- if (line.trim().length === 0) continue
16
- const leadingSpace = line.match(/^\s*/)?.[0].length || 0
17
- if (leadingSpace < minIndent) minIndent = leadingSpace
18
- }
19
-
20
- if (minIndent === Infinity || minIndent === 0) return text
21
-
22
- return lines.map(line => {
23
- if (line.trim().length === 0) return ''
24
- return line.substring(minIndent)
25
- }).join('\n')
26
- }
27
-
28
- const parse = (rawMd) => {
29
- if (!rawMd) return []
30
-
31
- const md = stripPrefixBeforeH1(rawMd)
32
-
33
- let content = md.replace(/^#\s+.+$/m, '')
34
- content = content.replace(/(?:^|\n)\s*(?:#{1,3}|\*\*)\s*(?:References|Citations|Sources)[\s\S]*$/i, '')
35
- content = content.trim()
36
-
37
- const sections = []
38
-
39
- const combinedRegex = /(```[\s\S]*?```|((?:^|\n)\|[^\n]*\|(?:\n\|[^\n]*\|)*)|<summary>[\s\S]*?<\/summary>)/
40
-
41
- let remaining = content
42
-
43
- while (remaining) {
44
- const match = remaining.match(combinedRegex)
45
- if (!match) {
46
- if (remaining.trim()) {
47
- sections.push({ type: 'markdown', content: remaining.trim() })
48
- }
49
- break
50
- }
51
-
52
- const index = match.index
53
- const matchedStr = match[0]
54
- const preText = remaining.substring(0, index)
55
-
56
- if (preText.trim()) {
57
- sections.push({ type: 'markdown', content: preText.trim() })
58
- }
59
-
60
- const isCode = matchedStr.startsWith('```')
61
- const isSummary = matchedStr.startsWith('<summary>')
62
- const isTable = !isCode && !isSummary && matchedStr.trim().startsWith('|')
63
-
64
- if (isCode || isTable || isSummary) {
65
- let language = ''
66
- let content = matchedStr.trim()
67
-
68
- if (isCode) {
69
- const match = matchedStr.match(/^```(\w+)/)
70
- if (match && match[1]) language = match[1]
71
- } else if (isSummary) {
72
- content = content.replace(/^<summary>/, '').replace(/<\/summary>$/, '')
73
- content = dedent(content)
74
- }
75
-
76
- sections.push({
77
- type: 'card',
78
- title: isCode ? 'Code' : (isSummary ? 'Summary' : 'Table'),
79
- content: content,
80
- contentType: isCode ? 'code' : (isSummary ? 'summary' : 'table'),
81
- language: language
82
- })
83
- } else {
84
- sections.push({ type: 'markdown', content: matchedStr })
85
- }
86
-
87
- remaining = remaining.substring(index + matchedStr.length)
88
- }
89
-
90
- return sections
91
- }
92
-
93
- const test1 = `
94
- # Title
95
-
96
- <summary>
97
- Indented text.
98
- It might become code block.
99
- </summary>
100
- `
101
-
102
- console.log("\n--- Test 2 (After Fix) ---")
103
- console.log(JSON.stringify(parse(test1), null, 2))
@@ -1,61 +0,0 @@
1
- // Type definitions for render data
2
- // Python only passes raw data, all processing happens in frontend
3
-
4
- export interface Stage {
5
- name: string
6
- model: string
7
- provider: string
8
- icon_name?: string // Icon identifier (e.g., "google", "openai")
9
- icon_config?: string // Config key for icon (e.g. "openai")
10
- time: number // Time in seconds (raw number)
11
- cost: number // Cost in dollars (raw number)
12
- usage?: any // Token usage stats
13
- references?: Reference[]
14
- image_references?: ImageReference[]
15
- crawled_pages?: CrawledPage[]
16
- description?: string // Brief intro or thought for this stage
17
- tasks?: string[]
18
- }
19
-
20
- export interface Reference {
21
- title: string
22
- url: string
23
- is_fetched?: boolean
24
- snippet?: string
25
- type?: string
26
- images?: string[] // Extracted images (base64)
27
- }
28
-
29
- export interface ImageReference {
30
- title: string
31
- url: string
32
- thumbnail?: string
33
- }
34
-
35
- export interface CrawledPage {
36
- title: string
37
- url: string
38
- description?: string
39
- }
40
-
41
- export interface Stats {
42
- total_time?: number
43
- vision_duration?: number
44
- }
45
-
46
- export interface Flags {
47
- has_vision: boolean
48
- has_search: boolean
49
- }
50
-
51
- // Raw data from Python - minimal processing
52
- export interface RenderData {
53
- markdown: string // Raw markdown content
54
- stages: Stage[]
55
- references: Reference[] // All references for citation
56
- page_references: Reference[]
57
- image_references: ImageReference[]
58
- stats: Stats
59
- total_time: number
60
- theme_color?: string // Configurable theme color (hex)
61
- }
@@ -1,16 +0,0 @@
1
- {
2
- "extends": "@vue/tsconfig/tsconfig.dom.json",
3
- "compilerOptions": {
4
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5
- "types": ["vite/client"],
6
-
7
- /* Linting */
8
- "strict": true,
9
- "noUnusedLocals": true,
10
- "noUnusedParameters": true,
11
- "erasableSyntaxOnly": true,
12
- "noFallthroughCasesInSwitch": true,
13
- "noUncheckedSideEffectImports": true
14
- },
15
- "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
16
- }
@@ -1,7 +0,0 @@
1
- {
2
- "files": [],
3
- "references": [
4
- { "path": "./tsconfig.app.json" },
5
- { "path": "./tsconfig.node.json" }
6
- ]
7
- }
@@ -1,26 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
- "target": "ES2023",
5
- "lib": ["ES2023"],
6
- "module": "ESNext",
7
- "types": ["node"],
8
- "skipLibCheck": true,
9
-
10
- /* Bundler mode */
11
- "moduleResolution": "bundler",
12
- "allowImportingTsExtensions": true,
13
- "verbatimModuleSyntax": true,
14
- "moduleDetection": "force",
15
- "noEmit": true,
16
-
17
- /* Linting */
18
- "strict": true,
19
- "noUnusedLocals": true,
20
- "noUnusedParameters": true,
21
- "erasableSyntaxOnly": true,
22
- "noFallthroughCasesInSwitch": true,
23
- "noUncheckedSideEffectImports": true
24
- },
25
- "include": ["vite.config.ts"]
26
- }
@@ -1,16 +0,0 @@
1
- import { defineConfig } from 'vite'
2
- import vue from '@vitejs/plugin-vue'
3
- import tailwindcss from '@tailwindcss/vite'
4
- import { viteSingleFile } from 'vite-plugin-singlefile'
5
-
6
- export default defineConfig({
7
- plugins: [
8
- vue(),
9
- tailwindcss(),
10
- viteSingleFile(),
11
- ],
12
- build: {
13
- outDir: '../assets/card-dist',
14
- emptyOutDir: true,
15
- },
16
- })