@vibe-forge/client 0.3.0 → 0.5.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 (163) hide show
  1. package/cli.cjs +2 -1
  2. package/dist/assets/{arc-CwMXUVsq.js → arc-C4ymrcSQ.js} +1 -1
  3. package/dist/assets/{blockDiagram-c4efeb88-CGxJV7KJ.js → blockDiagram-c4efeb88-CeB7-kgP.js} +1 -1
  4. package/dist/assets/{c4Diagram-c83219d4-BKhin7cY.js → c4Diagram-c83219d4-C935Im8S.js} +1 -1
  5. package/dist/assets/channel-84s1ACzD.js +1 -0
  6. package/dist/assets/{classDiagram-beda092f-BASmn22R.js → classDiagram-beda092f-B9IV13KI.js} +1 -1
  7. package/dist/assets/{classDiagram-v2-2358418a-BUk9rNBX.js → classDiagram-v2-2358418a-CXF_K4fE.js} +1 -1
  8. package/dist/assets/clone-B2E8tddE.js +1 -0
  9. package/dist/assets/{createText-1719965b-2XqnWjQY.js → createText-1719965b-DwX8iC5F.js} +1 -1
  10. package/dist/assets/devicon-BWlTeAUU.woff +0 -0
  11. package/dist/assets/devicon-CirD-cQx.ttf +0 -0
  12. package/dist/assets/devicon-Dg8iWy0i.svg +1211 -0
  13. package/dist/assets/devicon-TqfHp33-.eot +0 -0
  14. package/dist/assets/{edges-96097737-B7e32Jeg.js → edges-96097737-9P1uH1RE.js} +1 -1
  15. package/dist/assets/{erDiagram-0228fc6a-CCR2or72.js → erDiagram-0228fc6a-ixeGTFvg.js} +1 -1
  16. package/dist/assets/{flowDb-c6c81e3f-B72HWT9x.js → flowDb-c6c81e3f-G1gSTTBI.js} +1 -1
  17. package/dist/assets/{flowDiagram-50d868cf-WOi0KARY.js → flowDiagram-50d868cf-CzrG99nD.js} +1 -1
  18. package/dist/assets/flowDiagram-v2-4f6560a1-CJfJYbME.js +1 -0
  19. package/dist/assets/{flowchart-elk-definition-6af322e1-i_Yd0LCE.js → flowchart-elk-definition-6af322e1-sFCoysWa.js} +1 -1
  20. package/dist/assets/{ganttDiagram-a2739b55-CFH9zF14.js → ganttDiagram-a2739b55-Ccsk_Lru.js} +1 -1
  21. package/dist/assets/{gitGraphDiagram-82fe8481-DglKfMze.js → gitGraphDiagram-82fe8481-CwathJ6H.js} +1 -1
  22. package/dist/assets/{graph-BKbBNGPf.js → graph-DRCU-8Rz.js} +1 -1
  23. package/dist/assets/{index-5325376f-BK7F9nSl.js → index-5325376f-Bq-fg2i_.js} +1 -1
  24. package/dist/assets/index-CHMuZ5-1.css +1 -0
  25. package/dist/assets/index-cGZvDhhU.js +542 -0
  26. package/dist/assets/{infoDiagram-8eee0895-BLFL77_D.js → infoDiagram-8eee0895-JBcUkJ6T.js} +1 -1
  27. package/dist/assets/{journeyDiagram-c64418c1-CS9XctDL.js → journeyDiagram-c64418c1-DsdQU-R8.js} +1 -1
  28. package/dist/assets/{layout-By3JZZGt.js → layout-s0slG1OL.js} +1 -1
  29. package/dist/assets/{line-9GUsXbwv.js → line-CymFqgW6.js} +1 -1
  30. package/dist/assets/{linear-DzGV4E9N.js → linear-lDQVZ6aQ.js} +1 -1
  31. package/dist/assets/{mermaid.core-CG3Ib42Q.js → mermaid.core-Cmlqga_E.js} +6 -6
  32. package/dist/assets/{mindmap-definition-8da855dc-WQ3LPKJU.js → mindmap-definition-8da855dc-CqqTDJn_.js} +1 -1
  33. package/dist/assets/{pieDiagram-a8764435-DHVIUZiN.js → pieDiagram-a8764435-BL2Ajx7Z.js} +1 -1
  34. package/dist/assets/{quadrantDiagram-1e28029f-C3G9Ye8-.js → quadrantDiagram-1e28029f-ClL_3ASt.js} +1 -1
  35. package/dist/assets/{requirementDiagram-08caed73-C9ES1D5G.js → requirementDiagram-08caed73-CB1RgE3K.js} +1 -1
  36. package/dist/assets/{sankeyDiagram-a04cb91d-B4BKXclQ.js → sankeyDiagram-a04cb91d-tgleEYiD.js} +1 -1
  37. package/dist/assets/{sequenceDiagram-c5b8d532-DrgEb25G.js → sequenceDiagram-c5b8d532-DlatQT5R.js} +1 -1
  38. package/dist/assets/{stateDiagram-1ecb1508-CF1XWARJ.js → stateDiagram-1ecb1508-B--MLqRs.js} +1 -1
  39. package/dist/assets/{stateDiagram-v2-c2b004d7-IO3i3yXv.js → stateDiagram-v2-c2b004d7-CRMZ6Dpx.js} +1 -1
  40. package/dist/assets/{styles-b4e223ce-DACN9aSc.js → styles-b4e223ce-CPiYHfUz.js} +1 -1
  41. package/dist/assets/{styles-ca3715f6-bekm2WLP.js → styles-ca3715f6-B9UKPAzX.js} +1 -1
  42. package/dist/assets/{styles-d45a18b0-OzTDVBb8.js → styles-d45a18b0-BC1Ak1So.js} +1 -1
  43. package/dist/assets/{svgDrawCommon-b86b1483-BWroJerr.js → svgDrawCommon-b86b1483-DV8R0g-n.js} +1 -1
  44. package/dist/assets/{timeline-definition-faaaa080-CCfRNigO.js → timeline-definition-faaaa080-CiqGS5DC.js} +1 -1
  45. package/dist/assets/{xychartDiagram-f5964ef8-C3cbfVqN.js → xychartDiagram-f5964ef8-h6VSD3GE.js} +1 -1
  46. package/dist/index.html +2 -7
  47. package/index.html +0 -5
  48. package/package.json +12 -6
  49. package/src/App.tsx +2 -0
  50. package/src/api/README.md +26 -0
  51. package/src/api/automation.ts +88 -0
  52. package/src/api/base.ts +54 -0
  53. package/src/api/benchmark.ts +45 -0
  54. package/src/api/config.ts +24 -0
  55. package/src/api/knowledge.ts +72 -0
  56. package/src/api/projects.ts +15 -0
  57. package/src/api/sessions.ts +84 -0
  58. package/src/api/types.ts +20 -0
  59. package/src/api.ts +44 -269
  60. package/src/components/AutomationView/AutomationView.scss +5 -1
  61. package/src/components/AutomationView/RuleFormPanel.tsx +3 -2
  62. package/src/components/AutomationView/TaskList.scss +4 -6
  63. package/src/components/AutomationView/TaskList.tsx +2 -1
  64. package/src/components/AutomationView/TriggerList.scss +4 -1
  65. package/src/components/BenchmarkView/BenchmarkCasePanel.scss +267 -0
  66. package/src/components/BenchmarkView/BenchmarkCasePanel.tsx +309 -0
  67. package/src/components/BenchmarkView/BenchmarkSidebar.scss +182 -0
  68. package/src/components/BenchmarkView/BenchmarkSidebar.tsx +262 -0
  69. package/src/components/BenchmarkView/BenchmarkView.scss +78 -0
  70. package/src/components/BenchmarkView/index.tsx +197 -0
  71. package/src/components/BenchmarkView/types.ts +10 -0
  72. package/src/components/BenchmarkView/utils.ts +21 -0
  73. package/src/components/Chat.tsx +43 -29
  74. package/src/components/{chat/CodeBlock.tsx → CodeBlock.tsx} +3 -1
  75. package/src/components/ConfigView.tsx +32 -25
  76. package/src/components/{chat/MarkdownContent.tsx → MarkdownContent.tsx} +1 -1
  77. package/src/components/NavRail.tsx +7 -0
  78. package/src/components/chat/ChatHeader.scss +37 -19
  79. package/src/components/chat/ChatHeader.tsx +6 -9
  80. package/src/components/chat/ChatHistoryView.tsx +99 -45
  81. package/src/components/chat/CurrentTodoList.tsx +10 -9
  82. package/src/components/chat/{MessageItem.scss → Messages/MessageItem.scss} +14 -0
  83. package/src/components/chat/{MessageItem.tsx → Messages/MessageItem.tsx} +30 -8
  84. package/src/components/chat/{messageUtils.ts → Messages/message-utils.ts} +1 -1
  85. package/src/components/chat/{Sender.scss → Sender/Sender.scss} +146 -3
  86. package/src/components/chat/{Sender.tsx → Sender/Sender.tsx} +183 -5
  87. package/src/components/chat/tools/DefaultTool.tsx +184 -21
  88. package/src/components/chat/tools/adapter-claude/BashTool.scss +67 -51
  89. package/src/components/chat/tools/adapter-claude/BashTool.tsx +83 -49
  90. package/src/components/chat/tools/adapter-claude/GlobTool.scss +0 -79
  91. package/src/components/chat/tools/adapter-claude/GlobTool.tsx +16 -36
  92. package/src/components/chat/tools/adapter-claude/GrepTool.scss +0 -87
  93. package/src/components/chat/tools/adapter-claude/GrepTool.tsx +22 -41
  94. package/src/components/chat/tools/adapter-claude/LSTool.scss +0 -79
  95. package/src/components/chat/tools/adapter-claude/LSTool.tsx +15 -15
  96. package/src/components/chat/tools/adapter-claude/ReadTool.scss +0 -55
  97. package/src/components/chat/tools/adapter-claude/ReadTool.tsx +20 -42
  98. package/src/components/chat/tools/adapter-claude/TodoTool.scss +8 -23
  99. package/src/components/chat/tools/adapter-claude/TodoTool.tsx +24 -11
  100. package/src/components/chat/tools/adapter-claude/WriteTool.scss +21 -69
  101. package/src/components/chat/tools/adapter-claude/WriteTool.tsx +22 -58
  102. package/src/components/chat/tools/adapter-claude/index.ts +4 -10
  103. package/src/components/chat/tools/adapter-claude/utils.ts +54 -0
  104. package/src/components/chat/tools/core/ToolCallBox.scss +356 -0
  105. package/src/components/chat/{ToolGroup.tsx → tools/core/ToolGroup.tsx} +26 -7
  106. package/src/components/chat/{ToolRenderer.tsx → tools/core/ToolRenderer.tsx} +6 -4
  107. package/src/components/chat/tools/plugin-chrome-devtools/ChromeDevtoolsTool.scss +11 -0
  108. package/src/components/chat/tools/plugin-chrome-devtools/ChromeDevtoolsTool.tsx +75 -0
  109. package/src/components/chat/tools/plugin-chrome-devtools/index.ts +45 -0
  110. package/src/components/chat/tools/task/GetTaskInfoTool.scss +2 -27
  111. package/src/components/chat/tools/task/GetTaskInfoTool.tsx +48 -38
  112. package/src/components/chat/tools/task/ListTasksTool.scss +3 -28
  113. package/src/components/chat/tools/task/ListTasksTool.tsx +11 -8
  114. package/src/components/chat/tools/task/StartTasksTool.scss +3 -28
  115. package/src/components/chat/tools/task/StartTasksTool.tsx +14 -17
  116. package/src/components/chat/tools/task/components/TaskRow.scss +105 -0
  117. package/src/components/chat/tools/task/components/TaskRow.tsx +163 -0
  118. package/src/components/chat/tools/task/components/TaskToolCard.scss +15 -15
  119. package/src/components/chat/tools/task/components/TaskToolCard.tsx +8 -6
  120. package/src/components/config/ConfigSectionForm.tsx +12 -1
  121. package/src/components/config/ConfigSourceSwitch.tsx +12 -34
  122. package/src/components/config/channelDefinitions.ts +6 -0
  123. package/src/components/config/configSchema.ts +10 -1
  124. package/src/components/config/recordEditors/ChannelRecordEditor.scss +1 -0
  125. package/src/components/config/recordEditors/ChannelRecordEditor.tsx +397 -0
  126. package/src/components/config/recordEditors/index.tsx +1 -0
  127. package/src/components/knowledge-base/components/RuleItem.tsx +1 -1
  128. package/src/components/knowledge-base/components/SpecItem.tsx +1 -1
  129. package/src/components/sidebar/SessionItem.scss +17 -0
  130. package/src/components/sidebar/SessionItem.tsx +21 -13
  131. package/src/hooks/chat/use-chat-adapter.ts +81 -0
  132. package/src/hooks/chat/use-chat-interaction.ts +26 -0
  133. package/src/{components/chat/useChatModels.tsx → hooks/chat/use-chat-models.tsx} +117 -22
  134. package/src/hooks/chat/use-chat-permission-mode.ts +47 -0
  135. package/src/hooks/chat/use-chat-scroll.ts +51 -0
  136. package/src/hooks/chat/use-chat-session-actions.ts +153 -0
  137. package/src/hooks/chat/use-chat-session-messages.ts +262 -0
  138. package/src/hooks/chat/use-chat-session.ts +63 -0
  139. package/src/hooks/chat/use-chat-view.ts +39 -0
  140. package/src/main.tsx +10 -13
  141. package/src/resources/adapters.ts +20 -0
  142. package/src/resources/locales/en.json +66 -0
  143. package/src/resources/locales/zh.json +66 -0
  144. package/src/runtime-config.ts +52 -0
  145. package/src/vite-env.d.ts +11 -0
  146. package/src/ws.ts +5 -3
  147. package/vite.config.ts +12 -4
  148. package/dist/assets/channel-jbCEHqbG.js +0 -1
  149. package/dist/assets/clone-CCRKqS4L.js +0 -1
  150. package/dist/assets/flowDiagram-v2-4f6560a1-Baslbgn4.js +0 -1
  151. package/dist/assets/index-B0qfCb1G.css +0 -1
  152. package/dist/assets/index-CNo75dYr.js +0 -497
  153. package/src/components/chat/ToolCallBox.scss +0 -137
  154. package/src/components/chat/useChatSession.ts +0 -370
  155. /package/src/components/{chat/CodeBlock.scss → CodeBlock.scss} +0 -0
  156. /package/src/components/chat/{MessageFooter.tsx → Messages/MessageFooter.tsx} +0 -0
  157. /package/src/components/chat/{CompletionMenu.scss → Sender/CompletionMenu.scss} +0 -0
  158. /package/src/components/chat/{CompletionMenu.tsx → Sender/CompletionMenu.tsx} +0 -0
  159. /package/src/components/chat/{ThinkingStatus.scss → Sender/ThinkingStatus.scss} +0 -0
  160. /package/src/components/chat/{ThinkingStatus.tsx → Sender/ThinkingStatus.tsx} +0 -0
  161. /package/src/components/chat/{ToolCallBox.tsx → tools/core/ToolCallBox.tsx} +0 -0
  162. /package/src/components/chat/{ToolGroup.scss → tools/core/ToolGroup.scss} +0 -0
  163. /package/src/{components/chat/safeSerialize.ts → utils/safe-serialize.ts} +0 -0
@@ -0,0 +1,72 @@
1
+ import { createApiUrl, fetchApiJson } from './base'
2
+
3
+ export interface SpecSummary {
4
+ id: string
5
+ name: string
6
+ description: string
7
+ params: { name: string; description?: string }[]
8
+ always: boolean
9
+ tags: string[]
10
+ skills: string[]
11
+ rules: string[]
12
+ }
13
+
14
+ export interface EntitySummary {
15
+ id: string
16
+ name: string
17
+ description: string
18
+ always: boolean
19
+ tags: string[]
20
+ skills: string[]
21
+ rules: string[]
22
+ }
23
+
24
+ export interface RuleSummary {
25
+ id: string
26
+ name: string
27
+ description: string
28
+ always: boolean
29
+ globs?: string[]
30
+ }
31
+
32
+ export interface SpecDetail extends SpecSummary {
33
+ body: string
34
+ }
35
+
36
+ export interface EntityDetail extends EntitySummary {
37
+ body: string
38
+ }
39
+
40
+ export interface RuleDetail extends RuleSummary {
41
+ body: string
42
+ }
43
+
44
+ export async function listSpecs(): Promise<{ specs: SpecSummary[] }> {
45
+ return fetchApiJson<{ specs: SpecSummary[] }>('/api/ai/specs')
46
+ }
47
+
48
+ export async function listEntities(): Promise<{ entities: EntitySummary[] }> {
49
+ return fetchApiJson<{ entities: EntitySummary[] }>('/api/ai/entities')
50
+ }
51
+
52
+ export async function listRules(): Promise<{ rules: RuleSummary[] }> {
53
+ return fetchApiJson<{ rules: RuleSummary[] }>('/api/ai/rules')
54
+ }
55
+
56
+ export async function getSpecDetail(path: string): Promise<{ spec: SpecDetail }> {
57
+ const url = createApiUrl('/api/ai/specs/detail')
58
+ url.searchParams.set('path', path)
59
+ return fetchApiJson<{ spec: SpecDetail }>(url)
60
+ }
61
+
62
+ export async function getEntityDetail(path: string): Promise<{ entity: EntityDetail }> {
63
+ const url = createApiUrl('/api/ai/entities/detail')
64
+ url.searchParams.set('path', path)
65
+ return fetchApiJson<{ entity: EntityDetail }>(url)
66
+ }
67
+
68
+ export async function getRuleDetail(path: string): Promise<{ rule: RuleDetail }> {
69
+ const url = createApiUrl('/api/ai/rules/detail')
70
+ url.searchParams.set('path', path)
71
+ return fetchApiJson<{ rule: RuleDetail }>(url)
72
+ }
@@ -0,0 +1,15 @@
1
+ import type { Project } from '@vibe-forge/core'
2
+
3
+ import { fetchApiJson, jsonHeaders } from './base'
4
+
5
+ export async function listProjects(): Promise<{ projects: Project[] }> {
6
+ return fetchApiJson<{ projects: Project[] }>('/api/projects')
7
+ }
8
+
9
+ export async function createProject(name?: string): Promise<{ project: Project }> {
10
+ return fetchApiJson<{ project: Project }>('/api/projects', {
11
+ method: 'POST',
12
+ headers: jsonHeaders,
13
+ body: JSON.stringify({ name })
14
+ })
15
+ }
@@ -0,0 +1,84 @@
1
+ import type { ChatMessageContent, Session } from '@vibe-forge/core'
2
+
3
+ import { createApiUrl, fetchApiJson, fetchApiJsonOrThrow, jsonHeaders } from './base'
4
+ import type { ApiOkResponse, ApiRemoveResponse, SessionMessagesResponse } from './types'
5
+
6
+ export async function listSessions(
7
+ filter: 'active' | 'archived' | 'all' = 'active'
8
+ ): Promise<{ sessions: Session[] }> {
9
+ const path = filter === 'archived' ? '/api/sessions/archived' : '/api/sessions'
10
+ return fetchApiJson<{ sessions: Session[] }>(path)
11
+ }
12
+
13
+ export async function createSession(
14
+ title?: string,
15
+ initialMessage?: string,
16
+ initialContent?: ChatMessageContent[],
17
+ model?: string,
18
+ options?: {
19
+ start?: boolean
20
+ parentSessionId?: string
21
+ id?: string
22
+ promptType?: 'spec' | 'entity'
23
+ promptName?: string
24
+ permissionMode?: 'default' | 'acceptEdits' | 'plan' | 'dontAsk' | 'bypassPermissions'
25
+ adapter?: string
26
+ }
27
+ ): Promise<{ session: Session }> {
28
+ return fetchApiJson<{ session: Session }>('/api/sessions', {
29
+ method: 'POST',
30
+ headers: jsonHeaders,
31
+ body: JSON.stringify({
32
+ title,
33
+ initialMessage,
34
+ initialContent,
35
+ model,
36
+ start: options?.start,
37
+ parentSessionId: options?.parentSessionId,
38
+ id: options?.id,
39
+ promptType: options?.promptType,
40
+ promptName: options?.promptName,
41
+ permissionMode: options?.permissionMode,
42
+ adapter: options?.adapter
43
+ })
44
+ })
45
+ }
46
+
47
+ export async function forkSession(id: string, title?: string): Promise<{ session: Session }> {
48
+ return fetchApiJson<{ session: Session }>(`/api/sessions/${id}/fork`, {
49
+ method: 'POST',
50
+ headers: jsonHeaders,
51
+ body: JSON.stringify({ title })
52
+ })
53
+ }
54
+
55
+ export async function getSessionMessages(
56
+ id: string,
57
+ limit?: number
58
+ ): Promise<SessionMessagesResponse> {
59
+ const url = createApiUrl(`/api/sessions/${id}/messages`)
60
+ if (limit != null) {
61
+ url.searchParams.set('limit', limit.toString())
62
+ }
63
+ return fetchApiJson<SessionMessagesResponse>(url)
64
+ }
65
+
66
+ export async function deleteSession(id: string): Promise<ApiRemoveResponse> {
67
+ return fetchApiJsonOrThrow<ApiRemoveResponse>(
68
+ `/api/sessions/${id}`,
69
+ { method: 'DELETE' },
70
+ '[api] delete session failed:'
71
+ )
72
+ }
73
+
74
+ export async function updateSession(id: string, data: Partial<Session>): Promise<ApiOkResponse> {
75
+ return fetchApiJson<ApiOkResponse>(`/api/sessions/${id}`, {
76
+ method: 'PATCH',
77
+ headers: jsonHeaders,
78
+ body: JSON.stringify(data)
79
+ })
80
+ }
81
+
82
+ export async function updateSessionTitle(id: string, title: string): Promise<ApiOkResponse> {
83
+ return updateSession(id, { title })
84
+ }
@@ -0,0 +1,20 @@
1
+ import type { AskUserQuestionParams, Session, WSEvent } from '@vibe-forge/core'
2
+
3
+ export interface ApiOkResponse {
4
+ ok: boolean
5
+ }
6
+
7
+ export interface ApiRemoveResponse extends ApiOkResponse {
8
+ removed: boolean
9
+ }
10
+
11
+ export interface SessionInteraction {
12
+ id: string
13
+ payload: AskUserQuestionParams
14
+ }
15
+
16
+ export interface SessionMessagesResponse {
17
+ messages: WSEvent[]
18
+ session?: Session
19
+ interaction?: SessionInteraction
20
+ }
package/src/api.ts CHANGED
@@ -1,269 +1,44 @@
1
- import type { ConfigResponse, ConfigSource, Session } from '@vibe-forge/core'
2
-
3
- export interface SpecSummary {
4
- id: string
5
- name: string
6
- description: string
7
- params: { name: string; description?: string }[]
8
- always: boolean
9
- tags: string[]
10
- skills: string[]
11
- rules: string[]
12
- }
13
-
14
- export interface EntitySummary {
15
- id: string
16
- name: string
17
- description: string
18
- always: boolean
19
- tags: string[]
20
- skills: string[]
21
- rules: string[]
22
- }
23
-
24
- export interface RuleSummary {
25
- id: string
26
- name: string
27
- description: string
28
- always: boolean
29
- globs?: string[]
30
- }
31
-
32
- export interface SpecDetail extends SpecSummary {
33
- body: string
34
- }
35
-
36
- export interface EntityDetail extends EntitySummary {
37
- body: string
38
- }
39
-
40
- export interface RuleDetail extends RuleSummary {
41
- body: string
42
- }
43
-
44
- export interface AutomationTrigger {
45
- id: string
46
- type: 'interval' | 'webhook' | 'cron'
47
- intervalMs?: number | null
48
- cronExpression?: string | null
49
- webhookKey?: string | null
50
- }
51
-
52
- export interface AutomationTask {
53
- id: string
54
- title: string
55
- prompt: string
56
- }
57
-
58
- export interface AutomationRule {
59
- id: string
60
- name: string
61
- description?: string | null
62
- type: 'interval' | 'webhook' | 'cron'
63
- intervalMs?: number | null
64
- webhookKey?: string | null
65
- cronExpression?: string | null
66
- prompt: string
67
- enabled: boolean
68
- createdAt: number
69
- lastRunAt?: number | null
70
- lastSessionId?: string | null
71
- triggers?: AutomationTrigger[]
72
- tasks?: AutomationTask[]
73
- }
74
-
75
- export interface AutomationRun {
76
- id: string
77
- ruleId: string
78
- sessionId: string
79
- runAt: number
80
- taskId?: string | null
81
- taskTitle?: string | null
82
- status?: string
83
- title?: string
84
- lastMessage?: string
85
- lastUserMessage?: string
86
- }
87
-
88
- const SERVER_HOST = (import.meta.env.__VF_PROJECT_AI_SERVER_HOST__ as string | undefined) ?? window.location.hostname
89
- const SERVER_PORT = (import.meta.env.__VF_PROJECT_AI_SERVER_PORT__ as string | undefined) ?? '8787'
90
- const SERVER_URL = `http://${SERVER_HOST}:${SERVER_PORT}`
91
-
92
- export async function listProjects(): Promise<any> {
93
- const res = await fetch(`${SERVER_URL}/api/projects`)
94
- return res.json()
95
- }
96
-
97
- export async function createProject(name?: string): Promise<any> {
98
- const res = await fetch(`${SERVER_URL}/api/projects`, {
99
- method: 'POST',
100
- headers: { 'Content-Type': 'application/json' },
101
- body: JSON.stringify({ name })
102
- })
103
- return res.json()
104
- }
105
-
106
- export async function listSessions(filter: 'active' | 'archived' | 'all' = 'active'): Promise<{ sessions: Session[] }> {
107
- const res = await fetch(`${SERVER_URL}/api/sessions${filter === 'archived' ? '/archived' : ''}`)
108
- return res.json() as Promise<{ sessions: Session[] }>
109
- }
110
-
111
- export async function createSession(
112
- title?: string,
113
- initialMessage?: string,
114
- model?: string
115
- ): Promise<{ session: Session }> {
116
- const res = await fetch(`${SERVER_URL}/api/sessions`, {
117
- method: 'POST',
118
- headers: { 'Content-Type': 'application/json' },
119
- body: JSON.stringify({ title, initialMessage, model })
120
- })
121
- return res.json() as Promise<{ session: Session }>
122
- }
123
-
124
- export async function listSpecs(): Promise<{ specs: SpecSummary[] }> {
125
- const res = await fetch(`${SERVER_URL}/api/ai/specs`)
126
- return res.json() as Promise<{ specs: SpecSummary[] }>
127
- }
128
-
129
- export async function listEntities(): Promise<{ entities: EntitySummary[] }> {
130
- const res = await fetch(`${SERVER_URL}/api/ai/entities`)
131
- return res.json() as Promise<{ entities: EntitySummary[] }>
132
- }
133
-
134
- export async function listRules(): Promise<{ rules: RuleSummary[] }> {
135
- const res = await fetch(`${SERVER_URL}/api/ai/rules`)
136
- return res.json() as Promise<{ rules: RuleSummary[] }>
137
- }
138
-
139
- export async function getSpecDetail(path: string): Promise<{ spec: SpecDetail }> {
140
- const url = new URL(`${SERVER_URL}/api/ai/specs/detail`)
141
- url.searchParams.set('path', path)
142
- const res = await fetch(url.toString())
143
- return res.json() as Promise<{ spec: SpecDetail }>
144
- }
145
-
146
- export async function getEntityDetail(path: string): Promise<{ entity: EntityDetail }> {
147
- const url = new URL(`${SERVER_URL}/api/ai/entities/detail`)
148
- url.searchParams.set('path', path)
149
- const res = await fetch(url.toString())
150
- return res.json() as Promise<{ entity: EntityDetail }>
151
- }
152
-
153
- export async function getRuleDetail(path: string): Promise<{ rule: RuleDetail }> {
154
- const url = new URL(`${SERVER_URL}/api/ai/rules/detail`)
155
- url.searchParams.set('path', path)
156
- const res = await fetch(url.toString())
157
- return res.json() as Promise<{ rule: RuleDetail }>
158
- }
159
-
160
- export async function getConfig(): Promise<ConfigResponse> {
161
- const res = await fetch(`${SERVER_URL}/api/config`)
162
- return res.json() as Promise<ConfigResponse>
163
- }
164
-
165
- export async function listAutomationRules(): Promise<{ rules: AutomationRule[] }> {
166
- const res = await fetch(`${SERVER_URL}/api/automation/rules`)
167
- return res.json() as Promise<{ rules: AutomationRule[] }>
168
- }
169
-
170
- export async function createAutomationRule(rule: Partial<AutomationRule> & { immediateRun?: boolean }): Promise<{ rule: AutomationRule }> {
171
- const res = await fetch(`${SERVER_URL}/api/automation/rules`, {
172
- method: 'POST',
173
- headers: { 'Content-Type': 'application/json' },
174
- body: JSON.stringify(rule)
175
- })
176
- return res.json() as Promise<{ rule: AutomationRule }>
177
- }
178
-
179
- export async function updateAutomationRule(
180
- id: string,
181
- rule: Partial<AutomationRule> & { immediateRun?: boolean }
182
- ): Promise<{ rule: AutomationRule }> {
183
- const res = await fetch(`${SERVER_URL}/api/automation/rules/${id}`, {
184
- method: 'PATCH',
185
- headers: { 'Content-Type': 'application/json' },
186
- body: JSON.stringify(rule)
187
- })
188
- return res.json() as Promise<{ rule: AutomationRule }>
189
- }
190
-
191
- export async function deleteAutomationRule(id: string): Promise<{ ok: boolean; removed: boolean }> {
192
- const res = await fetch(`${SERVER_URL}/api/automation/rules/${id}`, {
193
- method: 'DELETE'
194
- })
195
- return res.json() as Promise<{ ok: boolean; removed: boolean }>
196
- }
197
-
198
- export async function runAutomationRule(id: string): Promise<{ ok: boolean; sessionIds: string[] }> {
199
- const res = await fetch(`${SERVER_URL}/api/automation/rules/${id}/run`, {
200
- method: 'POST'
201
- })
202
- return res.json() as Promise<{ ok: boolean; sessionIds: string[] }>
203
- }
204
-
205
- export async function listAutomationRuns(id: string, limit = 50): Promise<{ runs: AutomationRun[] }> {
206
- const url = new URL(`${SERVER_URL}/api/automation/rules/${id}/runs`)
207
- url.searchParams.set('limit', limit.toString())
208
- const res = await fetch(url.toString())
209
- return res.json() as Promise<{ runs: AutomationRun[] }>
210
- }
211
-
212
- export async function updateConfig(
213
- source: ConfigSource,
214
- section: string,
215
- value: unknown
216
- ): Promise<{ ok: boolean }> {
217
- const res = await fetch(`${SERVER_URL}/api/config`, {
218
- method: 'PATCH',
219
- headers: { 'Content-Type': 'application/json' },
220
- body: JSON.stringify({ source, section, value })
221
- })
222
- if (!res.ok) {
223
- const text = await res.text()
224
- console.error('[api] update config failed:', res.status, text)
225
- throw new Error(`Update config failed: ${res.status} ${text}`)
226
- }
227
- return res.json() as Promise<{ ok: boolean }>
228
- }
229
-
230
- export async function deleteSession(id: string): Promise<{ success: boolean }> {
231
- const url = `${SERVER_URL}/api/sessions/${id}`
232
- const res = await fetch(url, { method: 'DELETE' })
233
- if (!res.ok) {
234
- const text = await res.text()
235
- console.error('[api] delete failed:', res.status, text)
236
- throw new Error(`Delete failed: ${res.status} ${text}`)
237
- }
238
- return res.json() as Promise<{ success: boolean }>
239
- }
240
-
241
- export async function updateSession(id: string, data: Partial<Session>): Promise<{ ok: boolean }> {
242
- const res = await fetch(`${SERVER_URL}/api/sessions/${id}`, {
243
- method: 'PATCH',
244
- headers: { 'Content-Type': 'application/json' },
245
- body: JSON.stringify(data)
246
- })
247
- return res.json() as Promise<{ ok: boolean }>
248
- }
249
-
250
- export async function updateSessionTitle(id: string, title: string): Promise<{ session: Session }> {
251
- const res = await fetch(`${SERVER_URL}/api/sessions/${id}`, {
252
- method: 'PATCH',
253
- headers: { 'Content-Type': 'application/json' },
254
- body: JSON.stringify({ title })
255
- })
256
- return res.json() as Promise<{ session: Session }>
257
- }
258
-
259
- export async function getSessionMessages(
260
- id: string,
261
- limit?: number
262
- ): Promise<{ messages: any[]; session?: Session; interaction?: { id: string; payload: any } }> {
263
- const url = new URL(`${SERVER_URL}/api/sessions/${id}/messages`)
264
- if (limit != null) {
265
- url.searchParams.set('limit', limit.toString())
266
- }
267
- const res = await fetch(url.toString())
268
- return res.json() as Promise<{ messages: any[]; session?: Session; interaction?: { id: string; payload: any } }>
269
- }
1
+ // 自动化规则与执行记录 API
2
+ export type { AutomationRule, AutomationRun, AutomationTask, AutomationTrigger } from './api/automation'
3
+ export {
4
+ createAutomationRule,
5
+ deleteAutomationRule,
6
+ listAutomationRules,
7
+ listAutomationRuns,
8
+ runAutomationRule,
9
+ updateAutomationRule
10
+ } from './api/automation'
11
+
12
+ export {
13
+ getBenchmarkCase,
14
+ getBenchmarkResult,
15
+ getBenchmarkRun,
16
+ listBenchmarkCases,
17
+ listBenchmarkCategories,
18
+ startBenchmarkRun
19
+ } from './api/benchmark'
20
+ // 配置读取与更新 API
21
+ export { getConfig, updateConfig } from './api/config'
22
+
23
+ // 知识库与规则说明 API
24
+ export type { EntityDetail, EntitySummary, RuleDetail, RuleSummary, SpecDetail, SpecSummary } from './api/knowledge'
25
+
26
+ export { getEntityDetail, getRuleDetail, getSpecDetail, listEntities, listRules, listSpecs } from './api/knowledge'
27
+ // 项目与工程 API
28
+ export { createProject, listProjects } from './api/projects'
29
+
30
+ // 会话与消息 API
31
+ export {
32
+ createSession,
33
+ deleteSession,
34
+ forkSession,
35
+ getSessionMessages,
36
+ listSessions,
37
+ updateSession,
38
+ updateSessionTitle
39
+ } from './api/sessions'
40
+
41
+ // 基础响应类型与会话交互类型
42
+ export type { ApiOkResponse, ApiRemoveResponse, SessionInteraction, SessionMessagesResponse } from './api/types'
43
+
44
+ export type { BenchmarkCase, BenchmarkCategory, BenchmarkResult, BenchmarkRunSummary } from '@vibe-forge/core'
@@ -4,6 +4,10 @@
4
4
  padding: 24px;
5
5
  overflow: hidden;
6
6
 
7
+ .ant-form-item {
8
+ margin-bottom: 12px;
9
+ }
10
+
7
11
  &__left {
8
12
  width: 360px;
9
13
  min-width: 320px;
@@ -15,7 +19,7 @@
15
19
  &__divider {
16
20
  width: 1px;
17
21
  background: var(--border-color);
18
- margin: 0 16px;
22
+ margin: 0 24px;
19
23
  }
20
24
 
21
25
  &__right {
@@ -5,6 +5,7 @@ import React, { useCallback, useEffect } from 'react'
5
5
  import { useTranslation } from 'react-i18next'
6
6
 
7
7
  import type { AutomationRule } from '#~/api.js'
8
+ import { getServerHost, getServerPort } from '#~/api/base.js'
8
9
 
9
10
  import { TaskList } from './TaskList'
10
11
  import { TriggerList } from './TriggerList'
@@ -18,8 +19,8 @@ interface RuleFormPanelProps {
18
19
  onCancel: () => void
19
20
  }
20
21
 
21
- const serverHost = (import.meta.env.__VF_PROJECT_AI_SERVER_HOST__ as string | undefined) ?? window.location.hostname
22
- const serverPort = (import.meta.env.__VF_PROJECT_AI_SERVER_PORT__ as string | undefined) ?? '8787'
22
+ const serverHost = getServerHost()
23
+ const serverPort = getServerPort()
23
24
  const serverUrl = `http://${serverHost}:${serverPort}`
24
25
 
25
26
  export function RuleFormPanel({ mode, rule, submitting, onSubmit, onCancel }: RuleFormPanelProps) {
@@ -33,7 +33,6 @@
33
33
  padding: 12px;
34
34
  display: flex;
35
35
  flex-direction: column;
36
- gap: 12px;
37
36
  background: var(--tag-bg);
38
37
  }
39
38
 
@@ -100,11 +99,6 @@
100
99
  font-size: 18px;
101
100
  }
102
101
 
103
- &__button-icon {
104
- font-size: 16px;
105
- margin-right: 4px;
106
- }
107
-
108
102
  &__remove-button {
109
103
  position: absolute;
110
104
  top: 8px;
@@ -112,6 +106,10 @@
112
106
  width: 32px;
113
107
  height: 32px;
114
108
  padding: 0;
109
+ display: inline-flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ border-radius: 50%;
115
113
  }
116
114
 
117
115
  &__task-index {
@@ -46,11 +46,12 @@ export function TaskList() {
46
46
  <Tooltip title={t('automation.remove')}>
47
47
  <Button
48
48
  className='automation-view__remove-button'
49
+ type='text'
49
50
  danger
50
51
  onClick={() => remove(field.name)}
51
52
  disabled={fields.length <= 1}
52
53
  >
53
- <span className='material-symbols-rounded automation-view__button-icon'>close</span>
54
+ <span className='material-symbols-rounded automation-view__action-icon'>close</span>
54
55
  </Button>
55
56
  </Tooltip>
56
57
  <div className='automation-view__list-header'>
@@ -33,7 +33,6 @@
33
33
  padding: 12px;
34
34
  display: flex;
35
35
  flex-direction: column;
36
- gap: 12px;
37
36
  background: var(--tag-bg);
38
37
  }
39
38
 
@@ -107,6 +106,10 @@
107
106
  width: 32px;
108
107
  height: 32px;
109
108
  padding: 0;
109
+ display: inline-flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ border-radius: 50%;
110
113
  }
111
114
 
112
115
  &__input-number {