@vibe-forge/client 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +37 -0
- package/dist/assets/{arc-C4ymrcSQ.js → arc-CMAHd5G3.js} +1 -1
- package/dist/assets/{blockDiagram-c4efeb88-CeB7-kgP.js → blockDiagram-c4efeb88-DKww-VCP.js} +1 -1
- package/dist/assets/{c4Diagram-c83219d4-C935Im8S.js → c4Diagram-c83219d4-DKrjVHyY.js} +1 -1
- package/dist/assets/channel-Bi4g8rj9.js +1 -0
- package/dist/assets/{classDiagram-beda092f-B9IV13KI.js → classDiagram-beda092f-BXx5rdo3.js} +1 -1
- package/dist/assets/{classDiagram-v2-2358418a-CXF_K4fE.js → classDiagram-v2-2358418a-CnR3WLsr.js} +1 -1
- package/dist/assets/clone-DPrpP2ky.js +1 -0
- package/dist/assets/{createText-1719965b-DwX8iC5F.js → createText-1719965b-CmOsl1W7.js} +1 -1
- package/dist/assets/{edges-96097737-9P1uH1RE.js → edges-96097737-CQeQgpjD.js} +1 -1
- package/dist/assets/{erDiagram-0228fc6a-ixeGTFvg.js → erDiagram-0228fc6a-ZUNB-ucF.js} +1 -1
- package/dist/assets/{flowDb-c6c81e3f-G1gSTTBI.js → flowDb-c6c81e3f-DuuKeSLX.js} +1 -1
- package/dist/assets/{flowDiagram-50d868cf-CzrG99nD.js → flowDiagram-50d868cf-Bc6n85yR.js} +1 -1
- package/dist/assets/flowDiagram-v2-4f6560a1-BZqaeqoh.js +1 -0
- package/dist/assets/{flowchart-elk-definition-6af322e1-sFCoysWa.js → flowchart-elk-definition-6af322e1-cAG5afW9.js} +1 -1
- package/dist/assets/{ganttDiagram-a2739b55-Ccsk_Lru.js → ganttDiagram-a2739b55-Dp6xhY5I.js} +1 -1
- package/dist/assets/{gitGraphDiagram-82fe8481-CwathJ6H.js → gitGraphDiagram-82fe8481-MlIIRBdG.js} +1 -1
- package/dist/assets/{graph-DRCU-8Rz.js → graph-D7Es8jZ-.js} +1 -1
- package/dist/assets/{index-5325376f-Bq-fg2i_.js → index-5325376f-DC18ottv.js} +1 -1
- package/dist/assets/index-D37AbgPQ.js +545 -0
- package/dist/assets/{index-CHMuZ5-1.css → index-fcJ9v94I.css} +1 -1
- package/dist/assets/{infoDiagram-8eee0895-JBcUkJ6T.js → infoDiagram-8eee0895-CXk21kFp.js} +1 -1
- package/dist/assets/{journeyDiagram-c64418c1-DsdQU-R8.js → journeyDiagram-c64418c1-899BKBHL.js} +1 -1
- package/dist/assets/{layout-s0slG1OL.js → layout-DLaxdy48.js} +1 -1
- package/dist/assets/{line-CymFqgW6.js → line-_lw5YbRM.js} +1 -1
- package/dist/assets/{linear-lDQVZ6aQ.js → linear-D5iu84ui.js} +1 -1
- package/dist/assets/{mermaid.core-Cmlqga_E.js → mermaid.core-C6sW3GFM.js} +4 -4
- package/dist/assets/{mindmap-definition-8da855dc-CqqTDJn_.js → mindmap-definition-8da855dc-BS9Xy9KN.js} +1 -1
- package/dist/assets/{pieDiagram-a8764435-BL2Ajx7Z.js → pieDiagram-a8764435-DZt9cEgs.js} +1 -1
- package/dist/assets/{quadrantDiagram-1e28029f-ClL_3ASt.js → quadrantDiagram-1e28029f-BTIeHOgn.js} +1 -1
- package/dist/assets/{requirementDiagram-08caed73-CB1RgE3K.js → requirementDiagram-08caed73-BHJAKD2g.js} +1 -1
- package/dist/assets/{sankeyDiagram-a04cb91d-tgleEYiD.js → sankeyDiagram-a04cb91d-DnAkVOK8.js} +1 -1
- package/dist/assets/{sequenceDiagram-c5b8d532-DlatQT5R.js → sequenceDiagram-c5b8d532-92tE3oFv.js} +1 -1
- package/dist/assets/{stateDiagram-1ecb1508-B--MLqRs.js → stateDiagram-1ecb1508-DG0ObiMg.js} +1 -1
- package/dist/assets/{stateDiagram-v2-c2b004d7-CRMZ6Dpx.js → stateDiagram-v2-c2b004d7-BKoJx2ci.js} +1 -1
- package/dist/assets/{styles-b4e223ce-CPiYHfUz.js → styles-b4e223ce-Ba6G4ri9.js} +1 -1
- package/dist/assets/{styles-ca3715f6-B9UKPAzX.js → styles-ca3715f6-Bn6RIIVW.js} +1 -1
- package/dist/assets/{styles-d45a18b0-BC1Ak1So.js → styles-d45a18b0-_dELBUI6.js} +1 -1
- package/dist/assets/{svgDrawCommon-b86b1483-DV8R0g-n.js → svgDrawCommon-b86b1483-CRK-ZoIs.js} +1 -1
- package/dist/assets/{timeline-definition-faaaa080-CiqGS5DC.js → timeline-definition-faaaa080-DvQ_RA_i.js} +1 -1
- package/dist/assets/{xychartDiagram-f5964ef8-h6VSD3GE.js → xychartDiagram-f5964ef8-CJxeDLfg.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +10 -8
- package/src/App.tsx +20 -168
- package/src/api/base.ts +116 -7
- package/src/api.ts +3 -1
- package/src/components/ArchiveView.tsx +5 -5
- package/src/components/ConfigView.tsx +3 -3
- package/src/components/{AutomationView → automation-view}/index.tsx +10 -9
- package/src/components/{BenchmarkView → benchmark-view}/index.tsx +5 -4
- package/src/components/chat/ChatHeader.tsx +6 -6
- package/src/components/chat/ChatHistoryView.tsx +64 -16
- package/src/components/chat/ChatTimelineView.tsx +3 -3
- package/src/components/chat/CurrentTodoList.scss +56 -27
- package/src/components/chat/{Sender → sender}/Sender.scss +201 -71
- package/src/components/chat/{Sender → sender}/Sender.tsx +104 -42
- package/src/components/chat/tools/core/ToolGroup.tsx +1 -1
- package/src/components/config/ConfigSectionForm.tsx +1 -1
- package/src/components/layout/AppShell.scss +19 -0
- package/src/components/layout/AppShell.tsx +45 -0
- package/src/hooks/chat/model-selector.ts +150 -0
- package/src/hooks/chat/use-chat-adapter.ts +20 -8
- package/src/hooks/chat/use-chat-models.tsx +79 -74
- package/src/hooks/chat/use-chat-permission-mode.ts +14 -10
- package/src/hooks/chat/use-chat-session-actions.ts +13 -10
- package/src/hooks/chat/use-chat-session-messages.ts +46 -6
- package/src/hooks/chat/use-chat-session.ts +42 -1
- package/src/hooks/use-app-preferences.ts +41 -0
- package/src/hooks/use-session-subscription.ts +101 -0
- package/src/hooks/use-sidebar-navigation.ts +35 -0
- package/src/resources/locales/en.json +6 -0
- package/src/resources/locales/zh.json +6 -0
- package/src/routes/AppRoutes.tsx +22 -0
- package/src/routes/ArchiveRoute.tsx +5 -0
- package/src/routes/AutomationRoute.tsx +5 -0
- package/src/routes/BenchmarkRoute.tsx +5 -0
- package/src/{components/Chat.scss → routes/ChatRoute.scss} +35 -0
- package/src/{components/Chat.tsx → routes/ChatRoute.tsx} +54 -28
- package/src/routes/ConfigRoute.tsx +5 -0
- package/src/routes/KnowledgeRoute.tsx +5 -0
- package/dist/assets/channel-84s1ACzD.js +0 -1
- package/dist/assets/clone-B2E8tddE.js +0 -1
- package/dist/assets/flowDiagram-v2-4f6560a1-CJfJYbME.js +0 -1
- package/dist/assets/index-cGZvDhhU.js +0 -542
- /package/src/components/{AutomationView → automation-view}/RuleFormPanel.scss +0 -0
- /package/src/components/{AutomationView → automation-view}/RuleFormPanel.tsx +0 -0
- /package/src/components/{AutomationView → automation-view}/RuleSidebar.scss +0 -0
- /package/src/components/{AutomationView → automation-view}/RuleSidebar.tsx +0 -0
- /package/src/components/{AutomationView → automation-view}/RunHistoryPanel.scss +0 -0
- /package/src/components/{AutomationView → automation-view}/RunHistoryPanel.tsx +0 -0
- /package/src/components/{AutomationView → automation-view}/TaskList.scss +0 -0
- /package/src/components/{AutomationView → automation-view}/TaskList.tsx +0 -0
- /package/src/components/{AutomationView → automation-view}/TriggerList.scss +0 -0
- /package/src/components/{AutomationView → automation-view}/TriggerList.tsx +0 -0
- /package/src/components/{AutomationView/AutomationView.scss → automation-view/index.scss} +0 -0
- /package/src/components/{AutomationView → automation-view}/types.ts +0 -0
- /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkCasePanel.scss +0 -0
- /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkCasePanel.tsx +0 -0
- /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkSidebar.scss +0 -0
- /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkSidebar.tsx +0 -0
- /package/src/components/{BenchmarkView → benchmark-view}/BenchmarkView.scss +0 -0
- /package/src/components/{BenchmarkView → benchmark-view}/types.ts +0 -0
- /package/src/components/{BenchmarkView → benchmark-view}/utils.ts +0 -0
- /package/src/components/chat/{Messages → messages}/MessageFooter.tsx +0 -0
- /package/src/components/chat/{Messages → messages}/MessageItem.scss +0 -0
- /package/src/components/chat/{Messages → messages}/MessageItem.tsx +0 -0
- /package/src/components/chat/{Messages → messages}/message-utils.ts +0 -0
- /package/src/components/chat/{Sender → sender}/CompletionMenu.scss +0 -0
- /package/src/components/chat/{Sender → sender}/CompletionMenu.tsx +0 -0
- /package/src/components/chat/{Sender → sender}/ThinkingStatus.scss +0 -0
- /package/src/components/chat/{Sender → sender}/ThinkingStatus.tsx +0 -0
- /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/EventList.scss +0 -0
- /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/EventList.tsx +0 -0
- /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/gantt.ts +0 -0
- /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/git-graph.ts +0 -0
- /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/index.scss +0 -0
- /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/index.tsx +0 -0
- /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/mermaid.ts +0 -0
- /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/types.ts +0 -0
- /package/src/components/chat/{SessionTimelinePanel → session-timeline-panel}/utils.ts +0 -0
- /package/src/components/config/{recordEditors → record-editors}/BooleanRecordEditor.scss +0 -0
- /package/src/components/config/{recordEditors → record-editors}/BooleanRecordEditor.tsx +0 -0
- /package/src/components/config/{recordEditors → record-editors}/ChannelRecordEditor.scss +0 -0
- /package/src/components/config/{recordEditors → record-editors}/ChannelRecordEditor.tsx +0 -0
- /package/src/components/config/{recordEditors → record-editors}/KeyValueEditor.scss +0 -0
- /package/src/components/config/{recordEditors → record-editors}/KeyValueEditor.tsx +0 -0
- /package/src/components/config/{recordEditors → record-editors}/McpServersRecordEditor.scss +0 -0
- /package/src/components/config/{recordEditors → record-editors}/McpServersRecordEditor.tsx +0 -0
- /package/src/components/config/{recordEditors → record-editors}/ModelServicesRecordEditor.scss +0 -0
- /package/src/components/config/{recordEditors → record-editors}/ModelServicesRecordEditor.tsx +0 -0
- /package/src/components/config/{recordEditors → record-editors}/RecordEditors.scss +0 -0
- /package/src/components/config/{recordEditors → record-editors}/RecordJsonEditor.scss +0 -0
- /package/src/components/config/{recordEditors → record-editors}/RecordJsonEditor.tsx +0 -0
- /package/src/components/config/{recordEditors → record-editors}/index.tsx +0 -0
package/dist/assets/{xychartDiagram-f5964ef8-h6VSD3GE.js → xychartDiagram-f5964ef8-CJxeDLfg.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{s as zt,a as Ft,v as wt,x as Nt,b as Xt,c as Yt,l as St,aH as Ht,e as $t,z as Ut,ap as ot,aJ as Ct,aL as qt,aY as jt,i as Gt}from"./mermaid.core-
|
|
1
|
+
import{s as zt,a as Ft,v as wt,x as Nt,b as Xt,c as Yt,l as St,aH as Ht,e as $t,z as Ut,ap as ot,aJ as Ct,aL as qt,aY as jt,i as Gt}from"./mermaid.core-C6sW3GFM.js";import{a as Qt}from"./createText-1719965b-CmOsl1W7.js";import"./index-D37AbgPQ.js";import{i as Kt}from"./init-Gi6I4Gst.js";import{o as Jt}from"./ordinal-Cboi1Yqb.js";import{l as ft}from"./linear-D5iu84ui.js";import{l as pt}from"./line-_lw5YbRM.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";function Zt(e,t,i){e=+e,t=+t,i=(n=arguments.length)<2?(t=e,e=0,1):n<3?1:+i;for(var s=-1,n=Math.max(0,Math.ceil((t-e)/i))|0,o=new Array(n);++s<n;)o[s]=e+s*i;return o}function st(){var e=Jt().unknown(void 0),t=e.domain,i=e.range,s=0,n=1,o,c,f=!1,d=0,R=0,_=.5;delete e.unknown;function A(){var m=t().length,T=n<s,S=T?n:s,P=T?s:n;o=(P-S)/Math.max(1,m-d+R*2),f&&(o=Math.floor(o)),S+=(P-S-o*(m-d))*_,c=o*(1-d),f&&(S=Math.round(S),c=Math.round(c));var p=Zt(m).map(function(C){return S+o*C});return i(T?p.reverse():p)}return e.domain=function(m){return arguments.length?(t(m),A()):t()},e.range=function(m){return arguments.length?([s,n]=m,s=+s,n=+n,A()):[s,n]},e.rangeRound=function(m){return[s,n]=m,s=+s,n=+n,f=!0,A()},e.bandwidth=function(){return c},e.step=function(){return o},e.round=function(m){return arguments.length?(f=!!m,A()):f},e.padding=function(m){return arguments.length?(d=Math.min(1,R=+m),A()):d},e.paddingInner=function(m){return arguments.length?(d=Math.min(1,m),A()):d},e.paddingOuter=function(m){return arguments.length?(R=+m,A()):R},e.align=function(m){return arguments.length?(_=Math.max(0,Math.min(1,m)),A()):_},e.copy=function(){return st(t(),[s,n]).round(f).paddingInner(d).paddingOuter(R).align(_)},Kt.apply(A(),arguments)}var nt=function(){var e=function(V,r,l,u){for(l=l||{},u=V.length;u--;l[V[u]]=r);return l},t=[1,10,12,14,16,18,19,21,23],i=[2,6],s=[1,3],n=[1,5],o=[1,6],c=[1,7],f=[1,5,10,12,14,16,18,19,21,23,34,35,36],d=[1,25],R=[1,26],_=[1,28],A=[1,29],m=[1,30],T=[1,31],S=[1,32],P=[1,33],p=[1,34],C=[1,35],h=[1,36],L=[1,37],z=[1,43],lt=[1,42],ct=[1,47],$=[1,50],w=[1,10,12,14,16,18,19,21,23,34,35,36],Q=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36],v=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36,41,42,43,44,45,46,47,48,49,50],ut=[1,64],K={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,XYCHART:5,chartConfig:6,document:7,CHART_ORIENTATION:8,statement:9,title:10,text:11,X_AXIS:12,parseXAxis:13,Y_AXIS:14,parseYAxis:15,LINE:16,plotData:17,BAR:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,SQUARE_BRACES_START:24,commaSeparatedNumbers:25,SQUARE_BRACES_END:26,NUMBER_WITH_DECIMAL:27,COMMA:28,xAxisData:29,bandData:30,ARROW_DELIMITER:31,commaSeparatedTexts:32,yAxisData:33,NEWLINE:34,SEMI:35,EOF:36,alphaNum:37,STR:38,MD_STR:39,alphaNumToken:40,AMP:41,NUM:42,ALPHA:43,PLUS:44,EQUALS:45,MULT:46,DOT:47,BRKT:48,MINUS:49,UNDERSCORE:50,$accept:0,$end:1},terminals_:{2:"error",5:"XYCHART",8:"CHART_ORIENTATION",10:"title",12:"X_AXIS",14:"Y_AXIS",16:"LINE",18:"BAR",19:"acc_title",20:"acc_title_value",21:"acc_descr",22:"acc_descr_value",23:"acc_descr_multiline_value",24:"SQUARE_BRACES_START",26:"SQUARE_BRACES_END",27:"NUMBER_WITH_DECIMAL",28:"COMMA",31:"ARROW_DELIMITER",34:"NEWLINE",35:"SEMI",36:"EOF",38:"STR",39:"MD_STR",41:"AMP",42:"NUM",43:"ALPHA",44:"PLUS",45:"EQUALS",46:"MULT",47:"DOT",48:"BRKT",49:"MINUS",50:"UNDERSCORE"},productions_:[0,[3,2],[3,3],[3,2],[3,1],[6,1],[7,0],[7,2],[9,2],[9,2],[9,2],[9,2],[9,2],[9,3],[9,2],[9,3],[9,2],[9,2],[9,1],[17,3],[25,3],[25,1],[13,1],[13,2],[13,1],[29,1],[29,3],[30,3],[32,3],[32,1],[15,1],[15,2],[15,1],[33,3],[4,1],[4,1],[4,1],[11,1],[11,1],[11,1],[37,1],[37,2],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1]],performAction:function(r,l,u,g,b,a,F){var x=a.length-1;switch(b){case 5:g.setOrientation(a[x]);break;case 9:g.setDiagramTitle(a[x].text.trim());break;case 12:g.setLineData({text:"",type:"text"},a[x]);break;case 13:g.setLineData(a[x-1],a[x]);break;case 14:g.setBarData({text:"",type:"text"},a[x]);break;case 15:g.setBarData(a[x-1],a[x]);break;case 16:this.$=a[x].trim(),g.setAccTitle(this.$);break;case 17:case 18:this.$=a[x].trim(),g.setAccDescription(this.$);break;case 19:this.$=a[x-1];break;case 20:this.$=[Number(a[x-2]),...a[x]];break;case 21:this.$=[Number(a[x])];break;case 22:g.setXAxisTitle(a[x]);break;case 23:g.setXAxisTitle(a[x-1]);break;case 24:g.setXAxisTitle({type:"text",text:""});break;case 25:g.setXAxisBand(a[x]);break;case 26:g.setXAxisRangeData(Number(a[x-2]),Number(a[x]));break;case 27:this.$=a[x-1];break;case 28:this.$=[a[x-2],...a[x]];break;case 29:this.$=[a[x]];break;case 30:g.setYAxisTitle(a[x]);break;case 31:g.setYAxisTitle(a[x-1]);break;case 32:g.setYAxisTitle({type:"text",text:""});break;case 33:g.setYAxisRangeData(Number(a[x-2]),Number(a[x]));break;case 37:this.$={text:a[x],type:"text"};break;case 38:this.$={text:a[x],type:"text"};break;case 39:this.$={text:a[x],type:"markdown"};break;case 40:this.$=a[x];break;case 41:this.$=a[x-1]+""+a[x];break}},table:[e(t,i,{3:1,4:2,7:4,5:s,34:n,35:o,36:c}),{1:[3]},e(t,i,{4:2,7:4,3:8,5:s,34:n,35:o,36:c}),e(t,i,{4:2,7:4,6:9,3:10,5:s,8:[1,11],34:n,35:o,36:c}),{1:[2,4],9:12,10:[1,13],12:[1,14],14:[1,15],16:[1,16],18:[1,17],19:[1,18],21:[1,19],23:[1,20]},e(f,[2,34]),e(f,[2,35]),e(f,[2,36]),{1:[2,1]},e(t,i,{4:2,7:4,3:21,5:s,34:n,35:o,36:c}),{1:[2,3]},e(f,[2,5]),e(t,[2,7],{4:22,34:n,35:o,36:c}),{11:23,37:24,38:d,39:R,40:27,41:_,42:A,43:m,44:T,45:S,46:P,47:p,48:C,49:h,50:L},{11:39,13:38,24:z,27:lt,29:40,30:41,37:24,38:d,39:R,40:27,41:_,42:A,43:m,44:T,45:S,46:P,47:p,48:C,49:h,50:L},{11:45,15:44,27:ct,33:46,37:24,38:d,39:R,40:27,41:_,42:A,43:m,44:T,45:S,46:P,47:p,48:C,49:h,50:L},{11:49,17:48,24:$,37:24,38:d,39:R,40:27,41:_,42:A,43:m,44:T,45:S,46:P,47:p,48:C,49:h,50:L},{11:52,17:51,24:$,37:24,38:d,39:R,40:27,41:_,42:A,43:m,44:T,45:S,46:P,47:p,48:C,49:h,50:L},{20:[1,53]},{22:[1,54]},e(w,[2,18]),{1:[2,2]},e(w,[2,8]),e(w,[2,9]),e(Q,[2,37],{40:55,41:_,42:A,43:m,44:T,45:S,46:P,47:p,48:C,49:h,50:L}),e(Q,[2,38]),e(Q,[2,39]),e(v,[2,40]),e(v,[2,42]),e(v,[2,43]),e(v,[2,44]),e(v,[2,45]),e(v,[2,46]),e(v,[2,47]),e(v,[2,48]),e(v,[2,49]),e(v,[2,50]),e(v,[2,51]),e(w,[2,10]),e(w,[2,22],{30:41,29:56,24:z,27:lt}),e(w,[2,24]),e(w,[2,25]),{31:[1,57]},{11:59,32:58,37:24,38:d,39:R,40:27,41:_,42:A,43:m,44:T,45:S,46:P,47:p,48:C,49:h,50:L},e(w,[2,11]),e(w,[2,30],{33:60,27:ct}),e(w,[2,32]),{31:[1,61]},e(w,[2,12]),{17:62,24:$},{25:63,27:ut},e(w,[2,14]),{17:65,24:$},e(w,[2,16]),e(w,[2,17]),e(v,[2,41]),e(w,[2,23]),{27:[1,66]},{26:[1,67]},{26:[2,29],28:[1,68]},e(w,[2,31]),{27:[1,69]},e(w,[2,13]),{26:[1,70]},{26:[2,21],28:[1,71]},e(w,[2,15]),e(w,[2,26]),e(w,[2,27]),{11:59,32:72,37:24,38:d,39:R,40:27,41:_,42:A,43:m,44:T,45:S,46:P,47:p,48:C,49:h,50:L},e(w,[2,33]),e(w,[2,19]),{25:73,27:ut},{26:[2,28]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],72:[2,28],73:[2,20]},parseError:function(r,l){if(l.recoverable)this.trace(r);else{var u=new Error(r);throw u.hash=l,u}},parse:function(r){var l=this,u=[0],g=[],b=[null],a=[],F=this.table,x="",U=0,gt=0,Vt=2,xt=1,Bt=a.slice.call(arguments,1),k=Object.create(this.lexer),B={yy:{}};for(var Z in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Z)&&(B.yy[Z]=this.yy[Z]);k.setInput(r,B.yy),B.yy.lexer=k,B.yy.parser=this,typeof k.yylloc>"u"&&(k.yylloc={});var tt=k.yylloc;a.push(tt);var Wt=k.options&&k.options.ranges;typeof B.yy.parseError=="function"?this.parseError=B.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Ot(){var I;return I=g.pop()||k.lex()||xt,typeof I!="number"&&(I instanceof Array&&(g=I,I=g.pop()),I=l.symbols_[I]||I),I}for(var D,W,E,it,O={},q,M,dt,j;;){if(W=u[u.length-1],this.defaultActions[W]?E=this.defaultActions[W]:((D===null||typeof D>"u")&&(D=Ot()),E=F[W]&&F[W][D]),typeof E>"u"||!E.length||!E[0]){var et="";j=[];for(q in F[W])this.terminals_[q]&&q>Vt&&j.push("'"+this.terminals_[q]+"'");k.showPosition?et="Parse error on line "+(U+1)+`:
|
|
2
2
|
`+k.showPosition()+`
|
|
3
3
|
Expecting `+j.join(", ")+", got '"+(this.terminals_[D]||D)+"'":et="Parse error on line "+(U+1)+": Unexpected "+(D==xt?"end of input":"'"+(this.terminals_[D]||D)+"'"),this.parseError(et,{text:k.match,token:this.terminals_[D]||D,line:k.yylineno,loc:tt,expected:j})}if(E[0]instanceof Array&&E.length>1)throw new Error("Parse Error: multiple actions possible at state: "+W+", token: "+D);switch(E[0]){case 1:u.push(D),b.push(k.yytext),a.push(k.yylloc),u.push(E[1]),D=null,gt=k.yyleng,x=k.yytext,U=k.yylineno,tt=k.yylloc;break;case 2:if(M=this.productions_[E[1]][1],O.$=b[b.length-M],O._$={first_line:a[a.length-(M||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(M||1)].first_column,last_column:a[a.length-1].last_column},Wt&&(O._$.range=[a[a.length-(M||1)].range[0],a[a.length-1].range[1]]),it=this.performAction.apply(O,[x,gt,U,B.yy,E[1],b,a].concat(Bt)),typeof it<"u")return it;M&&(u=u.slice(0,-1*M*2),b=b.slice(0,-1*M),a=a.slice(0,-1*M)),u.push(this.productions_[E[1]][0]),b.push(O.$),a.push(O._$),dt=F[u[u.length-2]][u[u.length-1]],u.push(dt);break;case 3:return!0}}return!0}},It=function(){var V={EOF:1,parseError:function(l,u){if(this.yy.parser)this.yy.parser.parseError(l,u);else throw new Error(l)},setInput:function(r,l){return this.yy=l||this.yy||{},this._input=r,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var r=this._input[0];this.yytext+=r,this.yyleng++,this.offset++,this.match+=r,this.matched+=r;var l=r.match(/(?:\r\n?|\n).*/g);return l?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),r},unput:function(r){var l=r.length,u=r.split(/(?:\r\n?|\n)/g);this._input=r+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-l),this.offset-=l;var g=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),u.length-1&&(this.yylineno-=u.length-1);var b=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:u?(u.length===g.length?this.yylloc.first_column:0)+g[g.length-u.length].length-u[0].length:this.yylloc.first_column-l},this.options.ranges&&(this.yylloc.range=[b[0],b[0]+this.yyleng-l]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
|
|
4
4
|
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(r){this.unput(this.match.slice(r))},pastInput:function(){var r=this.matched.substr(0,this.matched.length-this.match.length);return(r.length>20?"...":"")+r.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var r=this.match;return r.length<20&&(r+=this._input.substr(0,20-r.length)),(r.substr(0,20)+(r.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var r=this.pastInput(),l=new Array(r.length+1).join("-");return r+this.upcomingInput()+`
|
package/dist/index.html
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
|
|
15
15
|
rel="stylesheet"
|
|
16
16
|
>
|
|
17
|
-
<script type="module" crossorigin src="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-
|
|
18
|
-
<link rel="stylesheet" crossorigin href="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-
|
|
17
|
+
<script type="module" crossorigin src="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-D37AbgPQ.js"></script>
|
|
18
|
+
<link rel="stylesheet" crossorigin href="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-fcJ9v94I.css">
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|
|
21
21
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-forge/client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"imports": {
|
|
6
6
|
"#~/*": [
|
|
7
7
|
"./src/*",
|
|
8
8
|
"./src/*.ts",
|
|
9
|
-
"./src/*.tsx"
|
|
9
|
+
"./src/*.tsx",
|
|
10
|
+
"./src/*/index.ts",
|
|
11
|
+
"./src/*/index.tsx"
|
|
10
12
|
]
|
|
11
13
|
},
|
|
12
14
|
"bin": {
|
|
@@ -34,12 +36,12 @@
|
|
|
34
36
|
"swr": "^2.2.5",
|
|
35
37
|
"vite": "^5.4.8",
|
|
36
38
|
"zod": "^3.24.1",
|
|
37
|
-
"@vibe-forge/adapter-
|
|
38
|
-
"@vibe-forge/adapter-
|
|
39
|
-
"@vibe-forge/
|
|
40
|
-
"@vibe-forge/
|
|
41
|
-
"@vibe-forge/
|
|
42
|
-
"@vibe-forge/
|
|
39
|
+
"@vibe-forge/adapter-claude-code": "^0.6.0",
|
|
40
|
+
"@vibe-forge/adapter-codex": "^0.6.0",
|
|
41
|
+
"@vibe-forge/channel-lark": "^0.6.0",
|
|
42
|
+
"@vibe-forge/core": "^0.6.0",
|
|
43
|
+
"@vibe-forge/plugin-chrome-devtools": "^0.6.0",
|
|
44
|
+
"@vibe-forge/register": "^0.6.0"
|
|
43
45
|
},
|
|
44
46
|
"devDependencies": {
|
|
45
47
|
"@types/react": "^18.3.12",
|
package/src/App.tsx
CHANGED
|
@@ -1,176 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useAtom, useAtomValue, useSetAtom } from 'jotai'
|
|
3
|
-
import React, { useCallback, useEffect } from 'react'
|
|
4
|
-
import { useTranslation } from 'react-i18next'
|
|
5
|
-
import { Route, Routes, useLocation, useNavigate, useParams } from 'react-router-dom'
|
|
6
|
-
import useSWR from 'swr'
|
|
1
|
+
import { ConfigProvider } from 'antd'
|
|
7
2
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { KnowledgeBaseView } from '#~/components/knowledge-base'
|
|
14
|
-
import { NavRail } from '#~/components/NavRail'
|
|
15
|
-
import { Sidebar } from '#~/components/Sidebar'
|
|
16
|
-
import type { ConfigResponse, Session } from '@vibe-forge/core'
|
|
17
|
-
import { getConfig } from './api'
|
|
18
|
-
import { isSidebarResizingAtom, sidebarWidthAtom, themeAtom } from './store/index'
|
|
19
|
-
|
|
20
|
-
const MIN_SIDEBAR_WIDTH = 200
|
|
21
|
-
const MAX_SIDEBAR_WIDTH = 600
|
|
22
|
-
|
|
23
|
-
function ChatView() {
|
|
24
|
-
const { t } = useTranslation()
|
|
25
|
-
const { sessionId } = useParams()
|
|
26
|
-
const navigate = useNavigate()
|
|
27
|
-
const { data: sessionsRes } = useSWR<{ sessions: Session[] }>('/api/sessions')
|
|
28
|
-
const sessions = sessionsRes?.sessions ?? []
|
|
29
|
-
const session = sessions.find(s => s.id === sessionId)
|
|
30
|
-
|
|
31
|
-
if (session == null) {
|
|
32
|
-
return (
|
|
33
|
-
<div style={{ height: '100%', display: 'grid', placeItems: 'center', alignContent: 'center', gap: '16px' }}>
|
|
34
|
-
<Empty description={t('common.sessionNotFound')} />
|
|
35
|
-
<Button type='primary' onClick={() => navigate('/')}>{t('common.backToHome')}</Button>
|
|
36
|
-
</div>
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return <Chat session={session} />
|
|
41
|
-
}
|
|
3
|
+
import { AppShell } from '#~/components/layout/AppShell'
|
|
4
|
+
import { useSessionSubscription } from '#~/hooks/use-session-subscription.js'
|
|
5
|
+
import { useAppPreferences } from '#~/hooks/use-app-preferences'
|
|
6
|
+
import { useSidebarNavigation } from '#~/hooks/use-sidebar-navigation'
|
|
7
|
+
import { AppRoutes } from '#~/routes/AppRoutes'
|
|
42
8
|
|
|
43
9
|
export default function App() {
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
const [themeMode] = useAtom(themeAtom)
|
|
48
|
-
|
|
49
|
-
const { data: sessionsRes } = useSWR<{ sessions: Session[] }>('/api/sessions')
|
|
50
|
-
const { data: configRes } = useSWR<ConfigResponse>('/api/config', getConfig)
|
|
51
|
-
const interfaceLanguage = configRes?.sources?.merged?.general?.interfaceLanguage
|
|
52
|
-
|
|
53
|
-
const [sidebarWidth, setSidebarWidth] = useAtom(sidebarWidthAtom)
|
|
54
|
-
const isResizing = useAtomValue(isSidebarResizingAtom)
|
|
55
|
-
const setIsResizing = useSetAtom(isSidebarResizingAtom)
|
|
56
|
-
|
|
57
|
-
const currentPath = location.pathname
|
|
58
|
-
const activeId = currentPath === '/' ? undefined : currentPath.split('/session/')[1]
|
|
59
|
-
|
|
60
|
-
const handleMouseDown = useCallback((e: React.MouseEvent) => {
|
|
61
|
-
setIsResizing(true)
|
|
62
|
-
e.preventDefault()
|
|
63
|
-
}, [])
|
|
64
|
-
|
|
65
|
-
const handleMouseMove = useCallback((e: MouseEvent) => {
|
|
66
|
-
if (!isResizing) return
|
|
67
|
-
|
|
68
|
-
// 获取相对于容器左边缘的坐标
|
|
69
|
-
// 容器由 NavRail (56px) + Sidebar 组成
|
|
70
|
-
let newWidth = e.clientX - 56
|
|
71
|
-
if (newWidth < MIN_SIDEBAR_WIDTH) newWidth = MIN_SIDEBAR_WIDTH
|
|
72
|
-
if (newWidth > MAX_SIDEBAR_WIDTH) newWidth = MAX_SIDEBAR_WIDTH
|
|
73
|
-
|
|
74
|
-
setSidebarWidth(newWidth)
|
|
75
|
-
}, [isResizing, setSidebarWidth])
|
|
76
|
-
|
|
77
|
-
const handleMouseUp = useCallback(() => {
|
|
78
|
-
setIsResizing(false)
|
|
79
|
-
localStorage.setItem('sidebarWidth', sidebarWidth.toString())
|
|
80
|
-
}, [sidebarWidth])
|
|
81
|
-
|
|
82
|
-
useEffect(() => {
|
|
83
|
-
if (isResizing) {
|
|
84
|
-
window.addEventListener('mousemove', handleMouseMove)
|
|
85
|
-
window.addEventListener('mouseup', handleMouseUp)
|
|
86
|
-
document.body.style.cursor = 'col-resize'
|
|
87
|
-
} else {
|
|
88
|
-
window.removeEventListener('mousemove', handleMouseMove)
|
|
89
|
-
window.removeEventListener('mouseup', handleMouseUp)
|
|
90
|
-
document.body.style.cursor = ''
|
|
91
|
-
}
|
|
92
|
-
return () => {
|
|
93
|
-
window.removeEventListener('mousemove', handleMouseMove)
|
|
94
|
-
window.removeEventListener('mouseup', handleMouseUp)
|
|
95
|
-
}
|
|
96
|
-
}, [isResizing, handleMouseMove, handleMouseUp])
|
|
97
|
-
|
|
98
|
-
const isDarkMode = themeMode === 'dark' ||
|
|
99
|
-
(themeMode === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
|
100
|
-
|
|
101
|
-
const showSidebar = currentPath === '/' || currentPath.startsWith('/session/')
|
|
102
|
-
|
|
103
|
-
const handleDeletedSession = useCallback((deletedId: string, nextId?: string) => {
|
|
104
|
-
// 如果删除的不是当前激活的会话,不需要跳转
|
|
105
|
-
if (activeId !== deletedId) return
|
|
106
|
-
|
|
107
|
-
if (nextId) {
|
|
108
|
-
void navigate(`/session/${nextId}`)
|
|
109
|
-
} else {
|
|
110
|
-
void navigate('/')
|
|
111
|
-
}
|
|
112
|
-
}, [activeId, navigate])
|
|
113
|
-
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
if (isDarkMode) {
|
|
116
|
-
document.documentElement.classList.add('dark')
|
|
117
|
-
} else {
|
|
118
|
-
document.documentElement.classList.remove('dark')
|
|
119
|
-
}
|
|
120
|
-
}, [isDarkMode])
|
|
121
|
-
|
|
122
|
-
useEffect(() => {
|
|
123
|
-
if (interfaceLanguage && i18n.language !== interfaceLanguage) {
|
|
124
|
-
void i18n.changeLanguage(interfaceLanguage)
|
|
125
|
-
}
|
|
126
|
-
}, [i18n, interfaceLanguage])
|
|
10
|
+
useSessionSubscription()
|
|
11
|
+
const { isDarkMode, themeConfig } = useAppPreferences()
|
|
12
|
+
const sidebarNavigation = useSidebarNavigation()
|
|
127
13
|
|
|
128
14
|
return (
|
|
129
|
-
<ConfigProvider
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
<>
|
|
141
|
-
<Sidebar
|
|
142
|
-
width={sidebarWidth}
|
|
143
|
-
activeId={activeId}
|
|
144
|
-
onSelectSession={(session: Session, isNew?: boolean) => {
|
|
145
|
-
if (session.id === '') {
|
|
146
|
-
void navigate('/')
|
|
147
|
-
} else {
|
|
148
|
-
void navigate(`/session/${session.id}`)
|
|
149
|
-
}
|
|
150
|
-
}}
|
|
151
|
-
onDeletedSession={handleDeletedSession}
|
|
152
|
-
/>
|
|
153
|
-
</>
|
|
154
|
-
)}
|
|
155
|
-
<Layout.Content
|
|
156
|
-
style={{
|
|
157
|
-
flex: 1,
|
|
158
|
-
position: 'relative',
|
|
159
|
-
overflow: 'hidden',
|
|
160
|
-
backgroundColor: isDarkMode ? '#141414' : '#fff'
|
|
161
|
-
}}
|
|
162
|
-
>
|
|
163
|
-
<Routes>
|
|
164
|
-
<Route path='/' element={<Chat />} />
|
|
165
|
-
<Route path='/session/:sessionId' element={<ChatView />} />
|
|
166
|
-
<Route path='/archive' element={<ArchiveView />} />
|
|
167
|
-
<Route path='/benchmark' element={<BenchmarkView />} />
|
|
168
|
-
<Route path='/automation' element={<AutomationView />} />
|
|
169
|
-
<Route path='/knowledge' element={<KnowledgeBaseView />} />
|
|
170
|
-
<Route path='/config' element={<ConfigView />} />
|
|
171
|
-
</Routes>
|
|
172
|
-
</Layout.Content>
|
|
173
|
-
</Layout>
|
|
15
|
+
<ConfigProvider theme={themeConfig}>
|
|
16
|
+
<AppShell
|
|
17
|
+
activeSessionId={sidebarNavigation.activeSessionId}
|
|
18
|
+
isDarkMode={isDarkMode}
|
|
19
|
+
onDeletedSession={sidebarNavigation.handleDeletedSession}
|
|
20
|
+
onSelectSession={sidebarNavigation.handleSelectSession}
|
|
21
|
+
showSidebar={sidebarNavigation.showSidebar}
|
|
22
|
+
sidebarWidth={sidebarNavigation.sidebarWidth}
|
|
23
|
+
>
|
|
24
|
+
<AppRoutes />
|
|
25
|
+
</AppShell>
|
|
174
26
|
</ConfigProvider>
|
|
175
27
|
)
|
|
176
28
|
}
|
package/src/api/base.ts
CHANGED
|
@@ -32,10 +32,124 @@ export const buildApiUrl = (path: string) => {
|
|
|
32
32
|
|
|
33
33
|
export const createApiUrl = (path: string) => new URL(buildApiUrl(path))
|
|
34
34
|
|
|
35
|
+
export interface ApiSuccessEnvelope<T> {
|
|
36
|
+
success: true
|
|
37
|
+
data: T
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ApiErrorPayload {
|
|
41
|
+
code: string
|
|
42
|
+
message: string
|
|
43
|
+
details?: unknown
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ApiErrorEnvelope {
|
|
47
|
+
success: false
|
|
48
|
+
error: ApiErrorPayload
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export class ApiError extends Error {
|
|
52
|
+
status: number
|
|
53
|
+
code: string
|
|
54
|
+
details?: unknown
|
|
55
|
+
|
|
56
|
+
constructor(status: number, payload: ApiErrorPayload) {
|
|
57
|
+
super(payload.message)
|
|
58
|
+
this.name = 'ApiError'
|
|
59
|
+
this.status = status
|
|
60
|
+
this.code = payload.code
|
|
61
|
+
this.details = payload.details
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const isRecord = (value: unknown): value is Record<string, unknown> => {
|
|
66
|
+
return value != null && typeof value === 'object' && !Array.isArray(value)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const isApiSuccessEnvelope = <T>(value: unknown): value is ApiSuccessEnvelope<T> => {
|
|
70
|
+
return isRecord(value) && value.success === true && 'data' in value
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const isApiErrorEnvelope = (value: unknown): value is ApiErrorEnvelope => {
|
|
74
|
+
return isRecord(value)
|
|
75
|
+
&& value.success === false
|
|
76
|
+
&& isRecord(value.error)
|
|
77
|
+
&& typeof value.error.message === 'string'
|
|
78
|
+
&& typeof value.error.code === 'string'
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const parseResponseBody = async (res: Response): Promise<unknown> => {
|
|
82
|
+
const text = await res.text()
|
|
83
|
+
if (text.trim() === '') {
|
|
84
|
+
return null
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
return JSON.parse(text) as unknown
|
|
88
|
+
} catch {
|
|
89
|
+
return text
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const toApiError = (status: number, body: unknown, fallbackMessage: string) => {
|
|
94
|
+
if (isApiErrorEnvelope(body)) {
|
|
95
|
+
return new ApiError(status, body.error)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (isRecord(body)) {
|
|
99
|
+
const message = typeof body.error === 'string'
|
|
100
|
+
? body.error
|
|
101
|
+
: typeof body.message === 'string'
|
|
102
|
+
? body.message
|
|
103
|
+
: fallbackMessage
|
|
104
|
+
const code = typeof body.code === 'string' ? body.code : 'request_failed'
|
|
105
|
+
return new ApiError(status, {
|
|
106
|
+
code,
|
|
107
|
+
message,
|
|
108
|
+
...(body.details !== undefined ? { details: body.details } : {})
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (typeof body === 'string' && body.trim() !== '') {
|
|
113
|
+
return new ApiError(status, { code: 'request_failed', message: body })
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return new ApiError(status, { code: 'request_failed', message: fallbackMessage })
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const unwrapApiResponse = async <T>(res: Response, errorLabel?: string): Promise<T> => {
|
|
120
|
+
const body = await parseResponseBody(res)
|
|
121
|
+
if (!res.ok) {
|
|
122
|
+
const fallbackMessage = errorLabel ?? `Request failed with status ${res.status}`
|
|
123
|
+
const apiError = toApiError(res.status, body, fallbackMessage)
|
|
124
|
+
console.error(errorLabel ?? '[api] request failed', res.status, apiError.message, apiError.details)
|
|
125
|
+
throw apiError
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (isApiErrorEnvelope(body)) {
|
|
129
|
+
throw new ApiError(res.status, body.error)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (isApiSuccessEnvelope<T>(body)) {
|
|
133
|
+
return body.data
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return body as T
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export const getApiErrorMessage = (error: unknown, fallback: string) => {
|
|
140
|
+
if (error instanceof ApiError && error.message.trim() !== '') {
|
|
141
|
+
return error.message
|
|
142
|
+
}
|
|
143
|
+
if (error instanceof Error && error.message.trim() !== '') {
|
|
144
|
+
return error.message
|
|
145
|
+
}
|
|
146
|
+
return fallback
|
|
147
|
+
}
|
|
148
|
+
|
|
35
149
|
export async function fetchApiJson<T>(pathOrUrl: string | URL, init?: RequestInit): Promise<T> {
|
|
36
150
|
const url = typeof pathOrUrl === 'string' ? buildApiUrl(pathOrUrl) : pathOrUrl.toString()
|
|
37
151
|
const res = await fetch(url, init)
|
|
38
|
-
return
|
|
152
|
+
return unwrapApiResponse<T>(res)
|
|
39
153
|
}
|
|
40
154
|
|
|
41
155
|
export async function fetchApiJsonOrThrow<T>(
|
|
@@ -45,10 +159,5 @@ export async function fetchApiJsonOrThrow<T>(
|
|
|
45
159
|
): Promise<T> {
|
|
46
160
|
const url = typeof pathOrUrl === 'string' ? buildApiUrl(pathOrUrl) : pathOrUrl.toString()
|
|
47
161
|
const res = await fetch(url, init)
|
|
48
|
-
|
|
49
|
-
const text = await res.text()
|
|
50
|
-
console.error(errorLabel, res.status, text)
|
|
51
|
-
throw new Error(`${errorLabel} ${res.status} ${text}`)
|
|
52
|
-
}
|
|
53
|
-
return res.json() as Promise<T>
|
|
162
|
+
return unwrapApiResponse<T>(res, errorLabel)
|
|
54
163
|
}
|
package/src/api.ts
CHANGED
|
@@ -9,6 +9,7 @@ export {
|
|
|
9
9
|
updateAutomationRule
|
|
10
10
|
} from './api/automation'
|
|
11
11
|
|
|
12
|
+
export { ApiError, getApiErrorMessage } from './api/base'
|
|
12
13
|
export {
|
|
13
14
|
getBenchmarkCase,
|
|
14
15
|
getBenchmarkResult,
|
|
@@ -17,13 +18,14 @@ export {
|
|
|
17
18
|
listBenchmarkCategories,
|
|
18
19
|
startBenchmarkRun
|
|
19
20
|
} from './api/benchmark'
|
|
21
|
+
|
|
20
22
|
// 配置读取与更新 API
|
|
21
23
|
export { getConfig, updateConfig } from './api/config'
|
|
22
24
|
|
|
23
25
|
// 知识库与规则说明 API
|
|
24
26
|
export type { EntityDetail, EntitySummary, RuleDetail, RuleSummary, SpecDetail, SpecSummary } from './api/knowledge'
|
|
25
|
-
|
|
26
27
|
export { getEntityDetail, getRuleDetail, getSpecDetail, listEntities, listRules, listSpecs } from './api/knowledge'
|
|
28
|
+
|
|
27
29
|
// 项目与工程 API
|
|
28
30
|
export { createProject, listProjects } from './api/projects'
|
|
29
31
|
|
|
@@ -6,7 +6,7 @@ import dayjs from 'dayjs'
|
|
|
6
6
|
import React, { useMemo, useState } from 'react'
|
|
7
7
|
import { useTranslation } from 'react-i18next'
|
|
8
8
|
import useSWR from 'swr'
|
|
9
|
-
import { deleteSession, listSessions, updateSession } from '../api'
|
|
9
|
+
import { deleteSession, getApiErrorMessage, listSessions, updateSession } from '../api'
|
|
10
10
|
|
|
11
11
|
export function ArchiveView() {
|
|
12
12
|
const { t } = useTranslation()
|
|
@@ -40,7 +40,7 @@ export function ArchiveView() {
|
|
|
40
40
|
void message.success(t('common.restoreSuccess', 'Restored successfully'))
|
|
41
41
|
void mutate()
|
|
42
42
|
} catch (err) {
|
|
43
|
-
void message.error(t('common.restoreFailed', 'Failed to restore'))
|
|
43
|
+
void message.error(getApiErrorMessage(err, t('common.restoreFailed', 'Failed to restore')))
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -50,7 +50,7 @@ export function ArchiveView() {
|
|
|
50
50
|
void message.success(t('common.deleteSuccess', 'Deleted successfully'))
|
|
51
51
|
void mutate()
|
|
52
52
|
} catch (err) {
|
|
53
|
-
void message.error(t('common.deleteFailed', 'Failed to delete'))
|
|
53
|
+
void message.error(getApiErrorMessage(err, t('common.deleteFailed', 'Failed to delete')))
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -80,7 +80,7 @@ export function ArchiveView() {
|
|
|
80
80
|
setIsBatchMode(false)
|
|
81
81
|
void mutate()
|
|
82
82
|
} catch (err) {
|
|
83
|
-
void message.error(t('common.batchRestoreFailed', 'Failed to restore some sessions'))
|
|
83
|
+
void message.error(getApiErrorMessage(err, t('common.batchRestoreFailed', 'Failed to restore some sessions')))
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -92,7 +92,7 @@ export function ArchiveView() {
|
|
|
92
92
|
setIsBatchMode(false)
|
|
93
93
|
void mutate()
|
|
94
94
|
} catch (err) {
|
|
95
|
-
void message.error(t('common.batchDeleteFailed', 'Failed to delete some sessions'))
|
|
95
|
+
void message.error(getApiErrorMessage(err, t('common.batchDeleteFailed', 'Failed to delete some sessions')))
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -7,7 +7,7 @@ import useSWR from 'swr'
|
|
|
7
7
|
|
|
8
8
|
import type { AboutInfo, ConfigResponse, ConfigSource } from '@vibe-forge/core'
|
|
9
9
|
|
|
10
|
-
import { getConfig, updateConfig } from '../api'
|
|
10
|
+
import { getApiErrorMessage, getConfig, updateConfig } from '../api'
|
|
11
11
|
import { useQueryParams } from '../hooks/useQueryParams'
|
|
12
12
|
import { AboutSection, ConfigSectionPanel, ConfigSourceSwitch, DisplayValue } from './config'
|
|
13
13
|
import { AppSettingsPanel } from './config/AppSettingsPanel'
|
|
@@ -158,8 +158,8 @@ export function ConfigView() {
|
|
|
158
158
|
await updateConfig(source, sectionKey, currentValue)
|
|
159
159
|
lastSavedRef.current[draftKey] = currentSerialized
|
|
160
160
|
await mutate()
|
|
161
|
-
} catch {
|
|
162
|
-
void message.error(t('config.saveFailed'))
|
|
161
|
+
} catch (error) {
|
|
162
|
+
void message.error(getApiErrorMessage(error, t('config.saveFailed')))
|
|
163
163
|
} finally {
|
|
164
164
|
savingRef.current[draftKey] = false
|
|
165
165
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './index.scss'
|
|
2
2
|
|
|
3
3
|
import { App } from 'antd'
|
|
4
4
|
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
|
@@ -10,6 +10,7 @@ import type { AutomationRule, AutomationRun } from '#~/api.js'
|
|
|
10
10
|
import {
|
|
11
11
|
createAutomationRule,
|
|
12
12
|
deleteAutomationRule,
|
|
13
|
+
getApiErrorMessage,
|
|
13
14
|
listAutomationRules,
|
|
14
15
|
listAutomationRuns,
|
|
15
16
|
runAutomationRule,
|
|
@@ -127,8 +128,8 @@ export function AutomationView() {
|
|
|
127
128
|
void mutateRuns()
|
|
128
129
|
setPanelMode('view')
|
|
129
130
|
}
|
|
130
|
-
} catch {
|
|
131
|
-
void message.error(t('automation.saveFailed'))
|
|
131
|
+
} catch (error) {
|
|
132
|
+
void message.error(getApiErrorMessage(error, t('automation.saveFailed')))
|
|
132
133
|
} finally {
|
|
133
134
|
setSubmitting(false)
|
|
134
135
|
}
|
|
@@ -143,8 +144,8 @@ export function AutomationView() {
|
|
|
143
144
|
}
|
|
144
145
|
void mutate()
|
|
145
146
|
void message.success(t('automation.deleted'))
|
|
146
|
-
} catch {
|
|
147
|
-
void message.error(t('automation.deleteFailed'))
|
|
147
|
+
} catch (error) {
|
|
148
|
+
void message.error(getApiErrorMessage(error, t('automation.deleteFailed')))
|
|
148
149
|
}
|
|
149
150
|
}, [message, mutate, selectedRuleId, t])
|
|
150
151
|
|
|
@@ -157,8 +158,8 @@ export function AutomationView() {
|
|
|
157
158
|
void mutateRuns()
|
|
158
159
|
void navigate(`/session/${nextSessionId}`)
|
|
159
160
|
}
|
|
160
|
-
} catch {
|
|
161
|
-
void message.error(t('automation.runFailed'))
|
|
161
|
+
} catch (error) {
|
|
162
|
+
void message.error(getApiErrorMessage(error, t('automation.runFailed')))
|
|
162
163
|
}
|
|
163
164
|
}, [message, mutateRuns, navigate, t])
|
|
164
165
|
|
|
@@ -166,8 +167,8 @@ export function AutomationView() {
|
|
|
166
167
|
try {
|
|
167
168
|
await updateAutomationRule(rule.id, { enabled })
|
|
168
169
|
void mutate()
|
|
169
|
-
} catch {
|
|
170
|
-
void message.error(t('automation.toggleFailed'))
|
|
170
|
+
} catch (error) {
|
|
171
|
+
void message.error(getApiErrorMessage(error, t('automation.toggleFailed')))
|
|
171
172
|
}
|
|
172
173
|
}, [message, mutate, t])
|
|
173
174
|
|
|
@@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'
|
|
|
6
6
|
import useSWR from 'swr'
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
+
getApiErrorMessage,
|
|
9
10
|
getBenchmarkResult,
|
|
10
11
|
getBenchmarkRun,
|
|
11
12
|
listBenchmarkCases,
|
|
@@ -88,8 +89,8 @@ export function BenchmarkView() {
|
|
|
88
89
|
const res = await startBenchmarkRun({ category: item.category, title: item.title })
|
|
89
90
|
setActiveRunId(res.run.runId)
|
|
90
91
|
void message.success(t('benchmark.runStarted'))
|
|
91
|
-
} catch {
|
|
92
|
-
void message.error(t('benchmark.runFailed'))
|
|
92
|
+
} catch (error) {
|
|
93
|
+
void message.error(getApiErrorMessage(error, t('benchmark.runFailed')))
|
|
93
94
|
}
|
|
94
95
|
}, [message, t])
|
|
95
96
|
|
|
@@ -98,8 +99,8 @@ export function BenchmarkView() {
|
|
|
98
99
|
const res = await startBenchmarkRun({ category })
|
|
99
100
|
setActiveRunId(res.run.runId)
|
|
100
101
|
void message.success(t('benchmark.categoryRunStarted'))
|
|
101
|
-
} catch {
|
|
102
|
-
void message.error(t('benchmark.runFailed'))
|
|
102
|
+
} catch (error) {
|
|
103
|
+
void message.error(getApiErrorMessage(error, t('benchmark.runFailed')))
|
|
103
104
|
}
|
|
104
105
|
}, [message, t])
|
|
105
106
|
|
|
@@ -7,7 +7,7 @@ import { useAtomValue } from 'jotai'
|
|
|
7
7
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
|
8
8
|
import { useTranslation } from 'react-i18next'
|
|
9
9
|
|
|
10
|
-
import { deleteSession, updateSession } from '../../api'
|
|
10
|
+
import { deleteSession, getApiErrorMessage, updateSession } from '../../api'
|
|
11
11
|
import { isSidebarCollapsedAtom, isSidebarResizingAtom } from '../../store/index'
|
|
12
12
|
import { ConfigSectionPanel } from '../config'
|
|
13
13
|
import type { FieldSpec } from '../config/configSchema'
|
|
@@ -68,7 +68,7 @@ export function ChatHeader({
|
|
|
68
68
|
await updateSession(sessionId, { isStarred: !isStarred })
|
|
69
69
|
void message.success(isStarred ? t('common.unstarred') : t('common.starred'))
|
|
70
70
|
} catch (err) {
|
|
71
|
-
void message.error(t('common.operationFailed'))
|
|
71
|
+
void message.error(getApiErrorMessage(err, t('common.operationFailed')))
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -78,7 +78,7 @@ export function ChatHeader({
|
|
|
78
78
|
await updateSession(sessionId, { isArchived: !isArchived })
|
|
79
79
|
void message.success(isArchived ? t('common.restored') : t('common.archived'))
|
|
80
80
|
} catch (err) {
|
|
81
|
-
void message.error(t('common.operationFailed'))
|
|
81
|
+
void message.error(getApiErrorMessage(err, t('common.operationFailed')))
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -257,8 +257,8 @@ export function SessionSettingsPanel({
|
|
|
257
257
|
tags: Array.isArray(currentValue.tags) ? currentValue.tags : []
|
|
258
258
|
})
|
|
259
259
|
lastSavedRef.current = currentSerialized
|
|
260
|
-
} catch {
|
|
261
|
-
void message.error(t('common.operationFailed'))
|
|
260
|
+
} catch (err) {
|
|
261
|
+
void message.error(getApiErrorMessage(err, t('common.operationFailed')))
|
|
262
262
|
} finally {
|
|
263
263
|
savingRef.current = false
|
|
264
264
|
}
|
|
@@ -292,7 +292,7 @@ export function SessionSettingsPanel({
|
|
|
292
292
|
void message.success(t('common.deleteSuccess'))
|
|
293
293
|
onClose()
|
|
294
294
|
} catch (err) {
|
|
295
|
-
void message.error(t('common.deleteFailed'))
|
|
295
|
+
void message.error(getApiErrorMessage(err, t('common.deleteFailed')))
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
})
|