@vibe-forge/client 0.2.0-alpha.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 (184) hide show
  1. package/LICENSE +21 -0
  2. package/cli.cjs +6 -0
  3. package/index.html +27 -0
  4. package/package.json +42 -0
  5. package/src/App.tsx +174 -0
  6. package/src/api.ts +241 -0
  7. package/src/components/ArchiveView.scss +168 -0
  8. package/src/components/ArchiveView.tsx +299 -0
  9. package/src/components/AutomationView/AutomationView.scss +26 -0
  10. package/src/components/AutomationView/RuleFormPanel.scss +129 -0
  11. package/src/components/AutomationView/RuleFormPanel.tsx +257 -0
  12. package/src/components/AutomationView/RuleSidebar.scss +219 -0
  13. package/src/components/AutomationView/RuleSidebar.tsx +258 -0
  14. package/src/components/AutomationView/RunHistoryPanel.scss +286 -0
  15. package/src/components/AutomationView/RunHistoryPanel.tsx +320 -0
  16. package/src/components/AutomationView/TaskList.scss +128 -0
  17. package/src/components/AutomationView/TaskList.tsx +79 -0
  18. package/src/components/AutomationView/TriggerList.scss +153 -0
  19. package/src/components/AutomationView/TriggerList.tsx +217 -0
  20. package/src/components/AutomationView/index.tsx +228 -0
  21. package/src/components/AutomationView/types.ts +21 -0
  22. package/src/components/Chat.scss +89 -0
  23. package/src/components/Chat.tsx +92 -0
  24. package/src/components/ConfigView.scss +185 -0
  25. package/src/components/ConfigView.tsx +258 -0
  26. package/src/components/NavRail.scss +71 -0
  27. package/src/components/NavRail.tsx +188 -0
  28. package/src/components/Sidebar.scss +112 -0
  29. package/src/components/Sidebar.tsx +291 -0
  30. package/src/components/chat/ChatHeader.scss +401 -0
  31. package/src/components/chat/ChatHeader.tsx +342 -0
  32. package/src/components/chat/ChatHistoryView.tsx +122 -0
  33. package/src/components/chat/ChatSettingsView.tsx +22 -0
  34. package/src/components/chat/ChatTimelineView.scss +53 -0
  35. package/src/components/chat/ChatTimelineView.tsx +158 -0
  36. package/src/components/chat/CodeBlock.scss +87 -0
  37. package/src/components/chat/CodeBlock.tsx +179 -0
  38. package/src/components/chat/CompletionMenu.scss +70 -0
  39. package/src/components/chat/CompletionMenu.tsx +58 -0
  40. package/src/components/chat/CurrentTodoList.scss +217 -0
  41. package/src/components/chat/CurrentTodoList.tsx +103 -0
  42. package/src/components/chat/MarkdownContent.tsx +43 -0
  43. package/src/components/chat/MessageFooter.tsx +48 -0
  44. package/src/components/chat/MessageItem.scss +251 -0
  45. package/src/components/chat/MessageItem.tsx +78 -0
  46. package/src/components/chat/NewSessionGuide.scss +186 -0
  47. package/src/components/chat/NewSessionGuide.tsx +167 -0
  48. package/src/components/chat/Sender.scss +367 -0
  49. package/src/components/chat/Sender.tsx +541 -0
  50. package/src/components/chat/SessionTimelinePanel/EventList.scss +58 -0
  51. package/src/components/chat/SessionTimelinePanel/EventList.tsx +212 -0
  52. package/src/components/chat/SessionTimelinePanel/gantt.ts +177 -0
  53. package/src/components/chat/SessionTimelinePanel/git-graph.ts +518 -0
  54. package/src/components/chat/SessionTimelinePanel/index.scss +28 -0
  55. package/src/components/chat/SessionTimelinePanel/index.tsx +121 -0
  56. package/src/components/chat/SessionTimelinePanel/mermaid.ts +4 -0
  57. package/src/components/chat/SessionTimelinePanel/types.ts +64 -0
  58. package/src/components/chat/SessionTimelinePanel/utils.ts +20 -0
  59. package/src/components/chat/ThinkingStatus.scss +70 -0
  60. package/src/components/chat/ThinkingStatus.tsx +13 -0
  61. package/src/components/chat/ToolCallBox.scss +137 -0
  62. package/src/components/chat/ToolCallBox.tsx +55 -0
  63. package/src/components/chat/ToolGroup.scss +154 -0
  64. package/src/components/chat/ToolGroup.tsx +102 -0
  65. package/src/components/chat/ToolRenderer.tsx +45 -0
  66. package/src/components/chat/messageUtils.ts +171 -0
  67. package/src/components/chat/safeSerialize.ts +84 -0
  68. package/src/components/chat/tools/DefaultTool.tsx +63 -0
  69. package/src/components/chat/tools/adapter-claude/BashTool.scss +71 -0
  70. package/src/components/chat/tools/adapter-claude/BashTool.tsx +82 -0
  71. package/src/components/chat/tools/adapter-claude/GlobTool.scss +88 -0
  72. package/src/components/chat/tools/adapter-claude/GlobTool.tsx +85 -0
  73. package/src/components/chat/tools/adapter-claude/GrepTool.scss +96 -0
  74. package/src/components/chat/tools/adapter-claude/GrepTool.tsx +114 -0
  75. package/src/components/chat/tools/adapter-claude/LSTool.scss +85 -0
  76. package/src/components/chat/tools/adapter-claude/LSTool.tsx +94 -0
  77. package/src/components/chat/tools/adapter-claude/ReadTool.scss +57 -0
  78. package/src/components/chat/tools/adapter-claude/ReadTool.tsx +87 -0
  79. package/src/components/chat/tools/adapter-claude/TodoTool.scss +78 -0
  80. package/src/components/chat/tools/adapter-claude/TodoTool.tsx +60 -0
  81. package/src/components/chat/tools/adapter-claude/WriteTool.scss +92 -0
  82. package/src/components/chat/tools/adapter-claude/WriteTool.tsx +86 -0
  83. package/src/components/chat/tools/adapter-claude/components/FileList.scss +65 -0
  84. package/src/components/chat/tools/adapter-claude/components/FileList.tsx +185 -0
  85. package/src/components/chat/tools/adapter-claude/index.ts +28 -0
  86. package/src/components/chat/tools/defineToolRender.ts +28 -0
  87. package/src/components/chat/tools/task/GetTaskInfoTool.scss +50 -0
  88. package/src/components/chat/tools/task/GetTaskInfoTool.tsx +88 -0
  89. package/src/components/chat/tools/task/ListTasksTool.scss +56 -0
  90. package/src/components/chat/tools/task/ListTasksTool.tsx +83 -0
  91. package/src/components/chat/tools/task/StartTasksTool.scss +56 -0
  92. package/src/components/chat/tools/task/StartTasksTool.tsx +96 -0
  93. package/src/components/chat/tools/task/components/TaskToolCard.scss +127 -0
  94. package/src/components/chat/tools/task/components/TaskToolCard.tsx +177 -0
  95. package/src/components/chat/tools/task/index.ts +15 -0
  96. package/src/components/chat/useChatModels.tsx +206 -0
  97. package/src/components/chat/useChatSession.ts +370 -0
  98. package/src/components/config/ConfigAboutSection.scss +111 -0
  99. package/src/components/config/ConfigAboutSection.tsx +86 -0
  100. package/src/components/config/ConfigDisplayValue.scss +22 -0
  101. package/src/components/config/ConfigDisplayValue.tsx +62 -0
  102. package/src/components/config/ConfigEditors.scss +65 -0
  103. package/src/components/config/ConfigEditors.tsx +98 -0
  104. package/src/components/config/ConfigFieldRow.scss +97 -0
  105. package/src/components/config/ConfigFieldRow.tsx +36 -0
  106. package/src/components/config/ConfigSectionForm.scss +94 -0
  107. package/src/components/config/ConfigSectionForm.tsx +436 -0
  108. package/src/components/config/ConfigSectionPanel.tsx +67 -0
  109. package/src/components/config/ConfigShortcutInput.scss +11 -0
  110. package/src/components/config/ConfigShortcutInput.tsx +52 -0
  111. package/src/components/config/ConfigSourceSwitch.tsx +57 -0
  112. package/src/components/config/configSchema.ts +319 -0
  113. package/src/components/config/configUtils.ts +83 -0
  114. package/src/components/config/index.tsx +5 -0
  115. package/src/components/config/recordEditors/BooleanRecordEditor.scss +1 -0
  116. package/src/components/config/recordEditors/BooleanRecordEditor.tsx +75 -0
  117. package/src/components/config/recordEditors/KeyValueEditor.scss +1 -0
  118. package/src/components/config/recordEditors/KeyValueEditor.tsx +97 -0
  119. package/src/components/config/recordEditors/McpServersRecordEditor.scss +1 -0
  120. package/src/components/config/recordEditors/McpServersRecordEditor.tsx +258 -0
  121. package/src/components/config/recordEditors/ModelServicesRecordEditor.scss +1 -0
  122. package/src/components/config/recordEditors/ModelServicesRecordEditor.tsx +233 -0
  123. package/src/components/config/recordEditors/RecordEditors.scss +117 -0
  124. package/src/components/config/recordEditors/RecordJsonEditor.scss +1 -0
  125. package/src/components/config/recordEditors/RecordJsonEditor.tsx +113 -0
  126. package/src/components/config/recordEditors/index.tsx +5 -0
  127. package/src/components/knowledge-base/KnowledgeBaseView.scss +19 -0
  128. package/src/components/knowledge-base/KnowledgeBaseView.tsx +186 -0
  129. package/src/components/knowledge-base/components/ActionButton.scss +5 -0
  130. package/src/components/knowledge-base/components/ActionButton.tsx +9 -0
  131. package/src/components/knowledge-base/components/EmptyState.scss +19 -0
  132. package/src/components/knowledge-base/components/EmptyState.tsx +42 -0
  133. package/src/components/knowledge-base/components/EntitiesTab.scss +5 -0
  134. package/src/components/knowledge-base/components/EntitiesTab.tsx +80 -0
  135. package/src/components/knowledge-base/components/EntityItem.scss +82 -0
  136. package/src/components/knowledge-base/components/EntityItem.tsx +79 -0
  137. package/src/components/knowledge-base/components/EntityList.scss +5 -0
  138. package/src/components/knowledge-base/components/EntityList.tsx +70 -0
  139. package/src/components/knowledge-base/components/FilterBar.scss +21 -0
  140. package/src/components/knowledge-base/components/FilterBar.tsx +51 -0
  141. package/src/components/knowledge-base/components/FlowsTab.scss +5 -0
  142. package/src/components/knowledge-base/components/FlowsTab.tsx +80 -0
  143. package/src/components/knowledge-base/components/KnowledgeBaseHeader.scss +27 -0
  144. package/src/components/knowledge-base/components/KnowledgeBaseHeader.tsx +29 -0
  145. package/src/components/knowledge-base/components/KnowledgeList.scss +19 -0
  146. package/src/components/knowledge-base/components/KnowledgeList.tsx +19 -0
  147. package/src/components/knowledge-base/components/LoadingState.scss +5 -0
  148. package/src/components/knowledge-base/components/LoadingState.tsx +11 -0
  149. package/src/components/knowledge-base/components/MetaList.scss +19 -0
  150. package/src/components/knowledge-base/components/MetaList.tsx +18 -0
  151. package/src/components/knowledge-base/components/RulesTab.scss +5 -0
  152. package/src/components/knowledge-base/components/RulesTab.tsx +49 -0
  153. package/src/components/knowledge-base/components/SectionHeader.scss +22 -0
  154. package/src/components/knowledge-base/components/SectionHeader.tsx +21 -0
  155. package/src/components/knowledge-base/components/SkillsTab.scss +5 -0
  156. package/src/components/knowledge-base/components/SkillsTab.tsx +49 -0
  157. package/src/components/knowledge-base/components/SpecItem.scss +138 -0
  158. package/src/components/knowledge-base/components/SpecItem.tsx +131 -0
  159. package/src/components/knowledge-base/components/SpecList.scss +5 -0
  160. package/src/components/knowledge-base/components/SpecList.tsx +70 -0
  161. package/src/components/knowledge-base/components/TabContent.scss +8 -0
  162. package/src/components/knowledge-base/components/TabContent.tsx +17 -0
  163. package/src/components/knowledge-base/components/TabLabel.scss +10 -0
  164. package/src/components/knowledge-base/components/TabLabel.tsx +15 -0
  165. package/src/components/knowledge-base/index.tsx +1 -0
  166. package/src/components/sidebar/SessionItem.scss +256 -0
  167. package/src/components/sidebar/SessionItem.tsx +265 -0
  168. package/src/components/sidebar/SessionList.scss +92 -0
  169. package/src/components/sidebar/SessionList.tsx +166 -0
  170. package/src/components/sidebar/SidebarHeader.scss +79 -0
  171. package/src/components/sidebar/SidebarHeader.tsx +128 -0
  172. package/src/connectionManager.ts +172 -0
  173. package/src/hooks/useGlobalShortcut.ts +26 -0
  174. package/src/hooks/useQueryParams.ts +54 -0
  175. package/src/i18n.ts +22 -0
  176. package/src/main.tsx +41 -0
  177. package/src/resources/locales/en.json +765 -0
  178. package/src/resources/locales/zh.json +766 -0
  179. package/src/store/index.ts +23 -0
  180. package/src/styles/global.scss +100 -0
  181. package/src/utils/shortcutUtils.ts +88 -0
  182. package/src/vite-env.d.ts +12 -0
  183. package/src/ws.ts +33 -0
  184. package/vite.config.ts +26 -0
@@ -0,0 +1,23 @@
1
+ import { atom } from 'jotai'
2
+
3
+ // 侧边栏宽度
4
+ export const sidebarWidthAtom = atom(
5
+ Number(localStorage.getItem('sidebarWidth')) || 300
6
+ )
7
+
8
+ // 侧边栏是否正在缩放
9
+ export const isSidebarResizingAtom = atom<boolean>(false)
10
+
11
+ // 侧边栏是否折叠
12
+ export const isSidebarCollapsedAtom = atom(
13
+ localStorage.getItem('sidebarCollapsed') === 'true'
14
+ )
15
+
16
+ // 当前选中的会话 ID (全局 UI 状态,用于控制高亮等)
17
+ export const activeSessionIdAtom = atom<string | undefined>(undefined)
18
+
19
+ // 主题模式: 'light' | 'dark' | 'system'
20
+ export type ThemeMode = 'light' | 'dark' | 'system'
21
+ export const themeAtom = atom<ThemeMode>(
22
+ (localStorage.getItem('theme') as ThemeMode) || 'system'
23
+ )
@@ -0,0 +1,100 @@
1
+ html, body, #root, .ant-app {
2
+ height: 100%;
3
+ margin: 0;
4
+ }
5
+
6
+ .ant-app {
7
+ display: flex;
8
+ flex-direction: column;
9
+ }
10
+
11
+ .ant-btn-icon {
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ }
16
+
17
+ * {
18
+ box-sizing: border-box;
19
+ }
20
+
21
+ [class*='material-symbols'] {
22
+ user-select: none;
23
+ }
24
+
25
+ .material-symbols-rounded {
26
+ font-size: 20px;
27
+ font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 20;
28
+ }
29
+
30
+ :root {
31
+ --bg-color: #ffffff; /* 页面/主容器背景 */
32
+ --sub-bg-color: #f6f6f6; /* 次级容器背景 */
33
+ --sub-sub-bg-color: #e1e1e1; /* 更内层/弱化容器背景 */
34
+
35
+ --text-color: #000000; /* 主文本颜色 */
36
+ --sub-text-color: #1b1b1b; /* 次级容器文本颜色 */
37
+ --sub-sub-text-color: #303030; /* 更内层/弱化容器文本颜色 */
38
+
39
+ --border-color: #d0d0d0; /* 默认边框/分割线 */
40
+ --sub-border-color: #c0c0c0; /* 轻分割线/次级边框 */
41
+ --sub-sub-border-color: #a0a0a0; /* 弱化层级边框 */
42
+
43
+ --placeholder-color: #9ca3af; /* 页面/主容器下的占位符文本颜色 */
44
+
45
+ --tag-bg: #f9fafb; /* 标签/微容器背景 */
46
+ --tag-hover-bg: #f3f4f6; /* 标签/微容器悬浮背景 */
47
+ --code-bg: #f0f2f4; /* 代码块背景 */
48
+ --code-border: #f1f5f9; /* 代码块边框 */
49
+ --star-color: #f59e0b; /* 收藏/星标颜色 */
50
+ --primary-color: #6366f1; /* 主色调/主行动强调 */
51
+ --success-color: #0f766e; /* 成功状态颜色 */
52
+ --warning-color: #b45309; /* 警告状态颜色 */
53
+ --primary-text-color: #1d4ed8; /* 链接/强调文字颜色 */
54
+ --danger-color: #dc2626; /* 危险/错误状态颜色 */
55
+ }
56
+
57
+ html.dark {
58
+ --bg-color: #141414; /* 页面/主容器背景 */
59
+ --sub-bg-color: #262626; /* 次级容器背景 */
60
+ --sub-sub-bg-color: #303030; /* 更内层/弱化容器背景 */
61
+
62
+ --text-color: #ffffff; /* 主文本颜色 */
63
+ --sub-text-color: #8c8c8c; /* 次级说明文本 */
64
+ --sub-sub-text-color: #a5a5a5; /* 辅助弱化文本 */
65
+
66
+ --border-color: #303030; /* 默认边框/分割线 */
67
+ --sub-border-color: #434343; /* 轻分割线/次级边框 */
68
+ --sub-sub-border-color: #595959; /* 弱化层级边框 */
69
+
70
+ --placeholder-color: #575859; /* 页面/主容器下的占位符文本颜色 */
71
+
72
+ --tag-bg: #1f1f1f; /* 标签/微容器背景 */
73
+ --tag-hover-bg: #262626; /* 标签/微容器悬浮背景 */
74
+ --code-bg: #1e293b; /* 代码块背景 */
75
+ --code-border: #334155; /* 代码块边框 */
76
+ --star-color: #ffb81c; /* 收藏/星标颜色 */
77
+ --primary-color: #818cf8; /* 主色调/主行动强调 */
78
+ --success-color: #2dd4bf; /* 成功状态颜色 */
79
+ --warning-color: #f59e0b; /* 警告状态颜色 */
80
+ --primary-text-color: #60a5fa; /* 链接/强调文字颜色 */
81
+ --danger-color: #f87171; /* 危险/错误状态颜色 */
82
+ }
83
+
84
+ .ant-select-dropdown
85
+ .ant-select-item-option-active:not(.ant-select-item-option-disabled) {
86
+ background-color: var(--tag-hover-bg);
87
+ color: var(--text-color);
88
+ }
89
+
90
+ .ant-select-dropdown
91
+ .ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
92
+ background-color: var(--primary-color);
93
+ color: #ffffff;
94
+ }
95
+
96
+ .ant-select-dropdown
97
+ .ant-select-item-option-selected.ant-select-item-option-active:not(.ant-select-item-option-disabled) {
98
+ background-color: var(--primary-color);
99
+ color: #ffffff;
100
+ }
@@ -0,0 +1,88 @@
1
+ import type { KeyboardEvent as ReactKeyboardEvent } from 'react'
2
+
3
+ export type ShortcutSpec = {
4
+ key: string
5
+ metaKey: boolean
6
+ ctrlKey: boolean
7
+ altKey: boolean
8
+ shiftKey: boolean
9
+ }
10
+
11
+ const normalizeKey = (key: string) => {
12
+ if (key === ' ') return 'space'
13
+ return key.toLowerCase()
14
+ }
15
+
16
+ export const parseShortcut = (shortcut: string | undefined, isMac: boolean) => {
17
+ if (shortcut == null || shortcut.trim() === '') return null
18
+ const tokens = shortcut.split('+').map(token => token.trim()).filter(Boolean)
19
+ if (tokens.length === 0) return null
20
+ const parsed: ShortcutSpec = {
21
+ key: '',
22
+ metaKey: false,
23
+ ctrlKey: false,
24
+ altKey: false,
25
+ shiftKey: false
26
+ }
27
+ for (const token of tokens) {
28
+ const lower = token.toLowerCase()
29
+ if (lower === 'cmd' || lower === 'command' || lower === 'meta') {
30
+ parsed.metaKey = true
31
+ } else if (lower === 'ctrl' || lower === 'control') {
32
+ parsed.ctrlKey = true
33
+ } else if (lower === 'alt' || lower === 'option') {
34
+ parsed.altKey = true
35
+ } else if (lower === 'shift') {
36
+ parsed.shiftKey = true
37
+ } else if (lower === 'mod') {
38
+ if (isMac) parsed.metaKey = true
39
+ else parsed.ctrlKey = true
40
+ } else {
41
+ parsed.key = normalizeKey(lower)
42
+ }
43
+ }
44
+ return parsed.key === '' ? null : parsed
45
+ }
46
+
47
+ export const formatShortcutLabel = (shortcut: string | undefined, isMac: boolean) => {
48
+ if (shortcut == null || shortcut.trim() === '') return ''
49
+ const tokens = shortcut.split('+').map(token => token.trim()).filter(Boolean)
50
+ return tokens.map((token) => {
51
+ const lower = token.toLowerCase()
52
+ if (lower === 'mod') return isMac ? '⌘' : 'Ctrl'
53
+ if (lower === 'cmd' || lower === 'command' || lower === 'meta') return '⌘'
54
+ if (lower === 'ctrl' || lower === 'control') return 'Ctrl'
55
+ if (lower === 'alt' || lower === 'option') return 'Alt'
56
+ if (lower === 'shift') return 'Shift'
57
+ if (lower === 'space') return 'Space'
58
+ if (token.length === 1) return token.toUpperCase()
59
+ return token
60
+ }).join('+')
61
+ }
62
+
63
+ export const isShortcutMatch = (
64
+ e: KeyboardEvent | ReactKeyboardEvent,
65
+ shortcut: string | undefined,
66
+ isMac: boolean
67
+ ) => {
68
+ const parsed = parseShortcut(shortcut, isMac)
69
+ if (parsed == null) return false
70
+ if (e.metaKey !== parsed.metaKey) return false
71
+ if (e.ctrlKey !== parsed.ctrlKey) return false
72
+ if (e.altKey !== parsed.altKey) return false
73
+ if (e.shiftKey !== parsed.shiftKey) return false
74
+ return normalizeKey(e.key) === parsed.key
75
+ }
76
+
77
+ export const getShortcutFromEvent = (
78
+ e: KeyboardEvent | ReactKeyboardEvent
79
+ ) => {
80
+ const key = normalizeKey(e.key)
81
+ if (['meta', 'control', 'shift', 'alt'].includes(key)) return null
82
+ const tokens: string[] = []
83
+ if (e.metaKey || e.ctrlKey) tokens.push('mod')
84
+ if (e.shiftKey) tokens.push('shift')
85
+ if (e.altKey) tokens.push('alt')
86
+ tokens.push(key)
87
+ return tokens.join('+')
88
+ }
@@ -0,0 +1,12 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ interface ImportMetaEnv {
4
+ readonly __VF_PROJECT_AI_SERVER_HOST__: string
5
+ readonly __VF_PROJECT_AI_SERVER_PORT__: string
6
+ readonly __VF_PROJECT_AI_CLIENT_HOST__: string
7
+ readonly __VF_PROJECT_AI_CLIENT_PORT__: string
8
+ }
9
+
10
+ interface ImportMeta {
11
+ readonly env: ImportMetaEnv
12
+ }
package/src/ws.ts ADDED
@@ -0,0 +1,33 @@
1
+ import type { WSEvent } from '@vibe-forge/core'
2
+
3
+ const SERVER_HOST = import.meta.env.__VF_PROJECT_AI_SERVER_HOST__ || window.location.hostname
4
+ const SERVER_PORT = import.meta.env.__VF_PROJECT_AI_SERVER_PORT__ || '8787'
5
+ const WS_URL = `ws://${SERVER_HOST}:${SERVER_PORT}/ws`
6
+
7
+ export interface WSHandlers {
8
+ onOpen?: () => void
9
+ onMessage?: (data: WSEvent) => void
10
+ onError?: (err: Event) => void
11
+ onClose?: () => void
12
+ }
13
+
14
+ export function createSocket(handlers: WSHandlers, params?: Record<string, string>) {
15
+ let url = WS_URL
16
+ if (params) {
17
+ const searchParams = new URLSearchParams(params)
18
+ url += (url.includes('?') ? '&' : '?') + searchParams.toString()
19
+ }
20
+ const ws = new WebSocket(url)
21
+ ws.addEventListener('open', () => handlers.onOpen?.())
22
+ ws.addEventListener('message', (ev) => {
23
+ try {
24
+ const data = JSON.parse(String(ev.data)) as unknown
25
+ handlers.onMessage?.(data as WSEvent)
26
+ } catch (e) {
27
+ console.error(e)
28
+ }
29
+ })
30
+ ws.addEventListener('error', (err) => handlers.onError?.(err))
31
+ ws.addEventListener('close', () => handlers.onClose?.())
32
+ return ws
33
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,26 @@
1
+ import process from 'node:process'
2
+
3
+ import react from '@vitejs/plugin-react'
4
+ import { defineConfig } from 'vite'
5
+
6
+ export default defineConfig({
7
+ plugins: [react()],
8
+ root: '.',
9
+ server: {
10
+ host: process.env.__VF_PROJECT_AI_CLIENT_HOST__,
11
+ port: Number(process.env.__VF_PROJECT_AI_CLIENT_PORT__ ?? 5173)
12
+ },
13
+ envPrefix: [
14
+ '__VF_PROJECT_AI_'
15
+ ],
16
+ css: {
17
+ preprocessorOptions: {
18
+ scss: {
19
+ api: 'modern-compiler'
20
+ }
21
+ }
22
+ },
23
+ test: {
24
+ environment: 'node'
25
+ }
26
+ })