@vibe-forge/client 0.8.1 → 0.8.4

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 (67) hide show
  1. package/dist/assets/{arc-D8jtzr3m.js → arc-DCuZPvAs.js} +1 -1
  2. package/dist/assets/{blockDiagram-c4efeb88-BJgpwJDu.js → blockDiagram-c4efeb88-C39d7-Bu.js} +1 -1
  3. package/dist/assets/{c4Diagram-c83219d4-D1tglS7Y.js → c4Diagram-c83219d4-jWPBJdeq.js} +1 -1
  4. package/dist/assets/channel-bLjHfx-Q.js +1 -0
  5. package/dist/assets/{classDiagram-beda092f-D0yKhAEF.js → classDiagram-beda092f-Bo7Yvv2T.js} +1 -1
  6. package/dist/assets/{classDiagram-v2-2358418a-HMGLB-Su.js → classDiagram-v2-2358418a-DfoCP9XM.js} +1 -1
  7. package/dist/assets/clone-upfY39Je.js +1 -0
  8. package/dist/assets/{createText-1719965b-CdcVoxJT.js → createText-1719965b-8_Ez5rxh.js} +1 -1
  9. package/dist/assets/{edges-96097737-D8eSYgyp.js → edges-96097737-BEegO-R-.js} +1 -1
  10. package/dist/assets/{erDiagram-0228fc6a-Cz1bZvQg.js → erDiagram-0228fc6a-derRgkLz.js} +1 -1
  11. package/dist/assets/{flowDb-c6c81e3f-2Q7aPB-q.js → flowDb-c6c81e3f-ChtOxgsJ.js} +1 -1
  12. package/dist/assets/{flowDiagram-50d868cf-CADXtRSY.js → flowDiagram-50d868cf-Bm4ufmmA.js} +1 -1
  13. package/dist/assets/flowDiagram-v2-4f6560a1-F66FzZTY.js +1 -0
  14. package/dist/assets/{flowchart-elk-definition-6af322e1-H7s8F7AZ.js → flowchart-elk-definition-6af322e1-BRYLO-BL.js} +1 -1
  15. package/dist/assets/{ganttDiagram-a2739b55-ByPQlmCo.js → ganttDiagram-a2739b55-CbP6dzRO.js} +1 -1
  16. package/dist/assets/{gitGraphDiagram-82fe8481-BZVM0Fl8.js → gitGraphDiagram-82fe8481-Du44v02s.js} +1 -1
  17. package/dist/assets/{graph-ClMJH_U-.js → graph-0_VzJX6O.js} +1 -1
  18. package/dist/assets/{index-5325376f-HWUtfpil.js → index-5325376f-DLP7F7of.js} +1 -1
  19. package/dist/assets/{index-NlU1ELyk.js → index-C1O04Df8.js} +113 -113
  20. package/dist/assets/{index-DGEAe87I.css → index-sE8VA1N7.css} +1 -1
  21. package/dist/assets/{infoDiagram-8eee0895-wi7-H9nz.js → infoDiagram-8eee0895-DY19rRl6.js} +1 -1
  22. package/dist/assets/{journeyDiagram-c64418c1-CZCyqk1X.js → journeyDiagram-c64418c1-4Asnwc86.js} +1 -1
  23. package/dist/assets/{layout-CONWz1Dx.js → layout-BILp7GjD.js} +1 -1
  24. package/dist/assets/{line-ugjigc8g.js → line-D0Xqr8mi.js} +1 -1
  25. package/dist/assets/{linear-CziOoP7o.js → linear-LpL8RZsq.js} +1 -1
  26. package/dist/assets/{mermaid.core-8jQ7wVtv.js → mermaid.core-Bk0Y_0sz.js} +4 -4
  27. package/dist/assets/{mindmap-definition-8da855dc-74YgrTXA.js → mindmap-definition-8da855dc-eCAgn5kY.js} +1 -1
  28. package/dist/assets/{pieDiagram-a8764435-9MHYBe77.js → pieDiagram-a8764435-BeGFFS1p.js} +1 -1
  29. package/dist/assets/{quadrantDiagram-1e28029f-T47Rsmlf.js → quadrantDiagram-1e28029f-tLqbYOHC.js} +1 -1
  30. package/dist/assets/{requirementDiagram-08caed73-DxX3Lp0B.js → requirementDiagram-08caed73-DCverr_g.js} +1 -1
  31. package/dist/assets/{sankeyDiagram-a04cb91d-DtlrXeOV.js → sankeyDiagram-a04cb91d-DidhF5PL.js} +1 -1
  32. package/dist/assets/{sequenceDiagram-c5b8d532-0e8o5pPE.js → sequenceDiagram-c5b8d532-CEKaiwTo.js} +1 -1
  33. package/dist/assets/{stateDiagram-1ecb1508-Uif8hYjc.js → stateDiagram-1ecb1508-Cj9ZY7RH.js} +1 -1
  34. package/dist/assets/{stateDiagram-v2-c2b004d7-D8sWSYsQ.js → stateDiagram-v2-c2b004d7-Gsmps-dk.js} +1 -1
  35. package/dist/assets/{styles-b4e223ce-D43vhmWC.js → styles-b4e223ce-D7E8Th0j.js} +1 -1
  36. package/dist/assets/{styles-ca3715f6-DWma2mkN.js → styles-ca3715f6-tTC26Jsm.js} +1 -1
  37. package/dist/assets/{styles-d45a18b0-kT58cZYw.js → styles-d45a18b0-Bf6oqNdR.js} +1 -1
  38. package/dist/assets/{svgDrawCommon-b86b1483-D5ltvlh8.js → svgDrawCommon-b86b1483-BxKi01m2.js} +1 -1
  39. package/dist/assets/{timeline-definition-faaaa080-PXG_aexc.js → timeline-definition-faaaa080-D6PePEip.js} +1 -1
  40. package/dist/assets/{xychartDiagram-f5964ef8-qTUp7CdK.js → xychartDiagram-f5964ef8-BuP4qfXm.js} +1 -1
  41. package/dist/favicon.svg +5 -0
  42. package/dist/index.html +3 -2
  43. package/index.html +2 -1
  44. package/package.json +8 -8
  45. package/public/favicon.svg +5 -0
  46. package/src/api/benchmark.ts +1 -0
  47. package/src/api/sessions.ts +2 -0
  48. package/src/components/chat/ChatHistoryView.tsx +12 -1
  49. package/src/components/chat/sender/Sender.scss +6 -0
  50. package/src/components/chat/sender/Sender.tsx +33 -3
  51. package/src/components/config/ConfigSectionForm.tsx +0 -1
  52. package/src/components/config/configSchema.ts +15 -23
  53. package/src/hooks/chat/use-chat-effort.ts +55 -0
  54. package/src/hooks/chat/use-chat-model-adapter-selection.tsx +17 -11
  55. package/src/hooks/chat/use-chat-models.tsx +1 -6
  56. package/src/hooks/chat/use-chat-session-actions.ts +7 -0
  57. package/src/hooks/chat/use-chat-session-messages.ts +17 -3
  58. package/src/hooks/chat/use-chat-session.ts +18 -3
  59. package/src/hooks/use-session-subscription.ts +31 -8
  60. package/src/resources/locales/en.json +10 -0
  61. package/src/resources/locales/zh.json +10 -0
  62. package/src/routes/ChatRoute.tsx +6 -0
  63. package/src/runtime-config.ts +18 -9
  64. package/vite.config.ts +4 -2
  65. package/dist/assets/channel-5WTe7pNn.js +0 -1
  66. package/dist/assets/clone-LappdaLy.js +0 -1
  67. package/dist/assets/flowDiagram-v2-4f6560a1-VWENAHeD.js +0 -1
@@ -2,6 +2,7 @@ import { useEffect, useRef } from 'react'
2
2
  import { useTranslation } from 'react-i18next'
3
3
 
4
4
  import type { Session } from '@vibe-forge/core'
5
+ import { useChatEffort } from './use-chat-effort'
5
6
  import { useChatInteraction } from './use-chat-interaction'
6
7
  import { useChatModelAdapterSelection } from './use-chat-model-adapter-selection'
7
8
  import { useChatPermissionMode } from './use-chat-permission-mode'
@@ -28,6 +29,7 @@ export function useChatSession({
28
29
  adapterLocked: session?.id != null
29
30
  })
30
31
  const { permissionMode, setPermissionMode, permissionModeOptions } = useChatPermissionMode()
32
+ const { effort, setEffort, effortOptions } = useChatEffort()
31
33
  const { activeView, setActiveView } = useChatView()
32
34
  const { interactionRequest, setInteractionRequest, handleInteractionResponse } = useChatInteraction({
33
35
  sessionId: session?.id
@@ -35,11 +37,14 @@ export function useChatSession({
35
37
  const { messages, setMessages, sessionInfo, isReady, connectionError, retryConnection } = useChatSessionMessages({
36
38
  session,
37
39
  modelForQuery: selectedModelWithService,
40
+ effort,
38
41
  permissionMode,
39
42
  adapter: selectedAdapter,
40
43
  setInteractionRequest
41
44
  })
42
- const lastObservedSessionRef = useRef<Pick<Session, 'id' | 'model' | 'permissionMode' | 'adapter'> | null>(null)
45
+ const lastObservedSessionRef = useRef<Pick<Session, 'id' | 'model' | 'permissionMode' | 'adapter' | 'effort'> | null>(
46
+ null
47
+ )
43
48
  const isThinking = session?.status === 'running'
44
49
 
45
50
  useEffect(() => {
@@ -62,19 +67,26 @@ export function useChatSession({
62
67
  setPermissionMode(session.permissionMode)
63
68
  }
64
69
 
70
+ if (sessionChanged || previous?.effort !== session.effort) {
71
+ setEffort(session.effort)
72
+ }
73
+
65
74
  lastObservedSessionRef.current = {
66
75
  id: session.id,
67
76
  model: session.model,
68
77
  permissionMode: session.permissionMode,
69
- adapter: session.adapter
78
+ adapter: session.adapter,
79
+ effort: session.effort
70
80
  }
71
81
  }, [
72
82
  session?.adapter,
83
+ session?.effort,
73
84
  session?.id,
74
85
  session?.model,
75
86
  session?.permissionMode,
76
87
  applySessionSelection,
77
- setPermissionMode,
88
+ setEffort,
89
+ setPermissionMode
78
90
  ])
79
91
 
80
92
  return {
@@ -94,6 +106,9 @@ export function useChatSession({
94
106
  selectedModel,
95
107
  modelForQuery: selectedModelWithService,
96
108
  setSelectedModel,
109
+ effort,
110
+ setEffort,
111
+ effortOptions,
97
112
  permissionMode,
98
113
  setPermissionMode,
99
114
  permissionModeOptions,
@@ -71,14 +71,37 @@ export function useSessionSubscription() {
71
71
  useEffect(() => {
72
72
  let disposed = false
73
73
  let socket: WebSocket | undefined
74
- let reconnectTimer: ReturnType<typeof setTimeout> | undefined
74
+ let connectTimer: ReturnType<typeof setTimeout> | undefined
75
+
76
+ const closeSocket = (target: WebSocket | undefined) => {
77
+ if (!target) return
78
+ if (target.readyState === WebSocket.CLOSED || target.readyState === WebSocket.CLOSING) {
79
+ return
80
+ }
81
+ if (target.readyState === WebSocket.CONNECTING) {
82
+ target.addEventListener('open', () => target.close(), { once: true })
83
+ return
84
+ }
85
+ target.close()
86
+ }
87
+
88
+ const scheduleConnect = (delay = 0) => {
89
+ if (disposed) return
90
+ if (connectTimer) {
91
+ clearTimeout(connectTimer)
92
+ }
93
+ connectTimer = setTimeout(() => {
94
+ connectTimer = undefined
95
+ connect()
96
+ }, delay)
97
+ }
75
98
 
76
99
  const connect = () => {
77
100
  if (disposed) return
78
101
 
79
102
  socket = createSocket({
80
103
  onMessage: (data: WSEvent) => {
81
- if (data.type !== 'session_updated') return
104
+ if (disposed || data.type !== 'session_updated') return
82
105
  const updatedSession = data.session as SessionUpdate
83
106
 
84
107
  void mutate('/api/sessions', (prev: SessionListResponse | undefined) => {
@@ -91,22 +114,22 @@ export function useSessionSubscription() {
91
114
  },
92
115
  onClose: () => {
93
116
  if (disposed) return
94
- reconnectTimer = setTimeout(connect, 1000)
117
+ scheduleConnect(1000)
95
118
  },
96
119
  onError: () => {
97
- socket?.close()
120
+ closeSocket(socket)
98
121
  }
99
122
  }, { subscribe: 'sessions' })
100
123
  }
101
124
 
102
- connect()
125
+ scheduleConnect()
103
126
 
104
127
  return () => {
105
128
  disposed = true
106
- if (reconnectTimer) {
107
- clearTimeout(reconnectTimer)
129
+ if (connectTimer) {
130
+ clearTimeout(connectTimer)
108
131
  }
109
- socket?.close()
132
+ closeSocket(socket)
110
133
  }
111
134
  }, [mutate])
112
135
  }
@@ -509,6 +509,12 @@
509
509
  "boolean": "Boolean",
510
510
  "object": "Object",
511
511
  "array": "Array"
512
+ },
513
+ "effort": {
514
+ "low": "Low",
515
+ "medium": "Medium",
516
+ "high": "High",
517
+ "max": "Max"
512
518
  }
513
519
  },
514
520
  "fields": {
@@ -517,6 +523,10 @@
517
523
  "label": "Workspace Folder",
518
524
  "desc": "Default folder for configuration and cache files"
519
525
  },
526
+ "effort": {
527
+ "label": "Default Effort",
528
+ "desc": "Default effort level used when none is specified"
529
+ },
520
530
  "defaultAdapter": {
521
531
  "label": "Default Adapter",
522
532
  "desc": "Adapter used when none is specified"
@@ -510,6 +510,12 @@
510
510
  "boolean": "开关",
511
511
  "object": "对象",
512
512
  "array": "数组"
513
+ },
514
+ "effort": {
515
+ "low": "低",
516
+ "medium": "中",
517
+ "high": "高",
518
+ "max": "最高"
513
519
  }
514
520
  },
515
521
  "fields": {
@@ -518,6 +524,10 @@
518
524
  "label": "工作目录",
519
525
  "desc": "配置文件和缓存的默认目录"
520
526
  },
527
+ "effort": {
528
+ "label": "默认思考强度",
529
+ "desc": "未指定时默认使用的 effort 等级"
530
+ },
521
531
  "defaultAdapter": {
522
532
  "label": "默认适配器",
523
533
  "desc": "未指定时使用的适配器"
@@ -61,6 +61,9 @@ function ChatRouteView({
61
61
  selectedModel,
62
62
  modelForQuery,
63
63
  setSelectedModel,
64
+ effort,
65
+ setEffort,
66
+ effortOptions,
64
67
  permissionMode,
65
68
  setPermissionMode,
66
69
  permissionModeOptions,
@@ -106,6 +109,9 @@ function ChatRouteView({
106
109
  selectedModel={selectedModel}
107
110
  modelForQuery={modelForQuery}
108
111
  onModelChange={setSelectedModel}
112
+ effort={effort}
113
+ effortOptions={effortOptions}
114
+ onEffortChange={setEffort}
109
115
  permissionMode={permissionMode}
110
116
  permissionModeOptions={permissionModeOptions}
111
117
  onPermissionModeChange={setPermissionMode}
@@ -10,16 +10,17 @@ const getGlobalRuntimeEnv = () => {
10
10
  return globalScope.__VF_PROJECT_AI_RUNTIME_ENV__
11
11
  }
12
12
 
13
+ const pickNonEmptyValue = (...values: Array<string | undefined>) => (
14
+ values.find((value) => typeof value === 'string' && value.trim() !== '')
15
+ )
16
+
13
17
  const normalizeBase = (value?: string) => {
14
- let base = value?.trim() ?? ''
15
- if (!base) {
16
- return '/ui/'
17
- }
18
+ let base = value?.trim() ?? '/ui'
18
19
  if (!base.startsWith('/')) {
19
20
  base = `/${base}`
20
21
  }
21
- if (!base.endsWith('/')) {
22
- base += '/'
22
+ if (base.length > 1 && base.endsWith('/')) {
23
+ base = base.slice(0, -1)
23
24
  }
24
25
  return base
25
26
  }
@@ -37,10 +38,18 @@ const normalizePath = (value?: string) => {
37
38
 
38
39
  export const getRuntimeEnv = (): RuntimeEnv => getGlobalRuntimeEnv() ?? {}
39
40
 
40
- export const getClientBase = () =>
41
- normalizeBase(
42
- getRuntimeEnv().__VF_PROJECT_AI_CLIENT_BASE__ ?? import.meta.env.__VF_PROJECT_AI_CLIENT_BASE__
41
+ export const resolveClientBase = (...values: Array<string | undefined>) => (
42
+ normalizeBase(pickNonEmptyValue(...values))
43
+ )
44
+
45
+ export const getClientBase = () => (
46
+ resolveClientBase(
47
+ getRuntimeEnv().__VF_PROJECT_AI_CLIENT_BASE__,
48
+ import.meta.env.__VF_PROJECT_AI_CLIENT_BASE__,
49
+ import.meta.env.BASE_URL,
50
+ '/ui'
43
51
  )
52
+ )
44
53
 
45
54
  export const getServerHostEnv = () =>
46
55
  getRuntimeEnv().__VF_PROJECT_AI_SERVER_HOST__ ??
package/vite.config.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { fileURLToPath } from 'node:url'
2
1
  import process from 'node:process'
2
+ import { fileURLToPath } from 'node:url'
3
3
 
4
4
  import react from '@vitejs/plugin-react'
5
5
  import { defineConfig } from 'vite'
@@ -17,7 +17,9 @@ export default defineConfig({
17
17
  base: clientBase,
18
18
  resolve: {
19
19
  alias: {
20
- '@vibe-forge/utils/model-selection': fileURLToPath(new URL('../../packages/utils/src/model-selection.ts', import.meta.url)),
20
+ '@vibe-forge/utils/model-selection': fileURLToPath(
21
+ new URL('../../packages/utils/src/model-selection.ts', import.meta.url)
22
+ ),
21
23
  '@vibe-forge/utils': fileURLToPath(new URL('../../packages/utils/src/index.ts', import.meta.url))
22
24
  },
23
25
  conditions: ['browser', '__vibe-forge__', 'module', 'import', 'development']
@@ -1 +0,0 @@
1
- import{al as o,am as n}from"./mermaid.core-8jQ7wVtv.js";const l=(a,r)=>o.lang.round(n.parse(a)[r]);export{l as c};
@@ -1 +0,0 @@
1
- import{a as r}from"./graph-ClMJH_U-.js";var a=4;function n(o){return r(o,a)}export{n as c};
@@ -1 +0,0 @@
1
- import{f as o,p as e}from"./flowDb-c6c81e3f-2Q7aPB-q.js";import{f as a,g as t}from"./styles-d45a18b0-kT58cZYw.js";import{ar as i}from"./mermaid.core-8jQ7wVtv.js";import"./graph-ClMJH_U-.js";import"./layout-CONWz1Dx.js";import"./index-NlU1ELyk.js";import"./index-5325376f-HWUtfpil.js";import"./clone-LappdaLy.js";import"./edges-96097737-D8eSYgyp.js";import"./createText-1719965b-CdcVoxJT.js";import"./line-ugjigc8g.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";import"./channel-5WTe7pNn.js";const n={parser:e,db:o,renderer:t,styles:a,init:r=>{r.flowchart||(r.flowchart={}),r.flowchart.arrowMarkerAbsolute=r.arrowMarkerAbsolute,i({flowchart:{arrowMarkerAbsolute:r.arrowMarkerAbsolute}}),t.setConf(r.flowchart),o.clear(),o.setGen("gen-2")}};export{n as diagram};