@vibe-forge/client 0.8.1 → 0.8.3

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 (59) hide show
  1. package/dist/assets/{arc-D8jtzr3m.js → arc-CZwEW7WR.js} +1 -1
  2. package/dist/assets/{blockDiagram-c4efeb88-BJgpwJDu.js → blockDiagram-c4efeb88--ejJ1hay.js} +1 -1
  3. package/dist/assets/{c4Diagram-c83219d4-D1tglS7Y.js → c4Diagram-c83219d4-D0N419di.js} +1 -1
  4. package/dist/assets/channel-dXWmEygA.js +1 -0
  5. package/dist/assets/{classDiagram-beda092f-D0yKhAEF.js → classDiagram-beda092f-BRVsm_of.js} +1 -1
  6. package/dist/assets/{classDiagram-v2-2358418a-HMGLB-Su.js → classDiagram-v2-2358418a-OShdAlFU.js} +1 -1
  7. package/dist/assets/clone-C4IafnWc.js +1 -0
  8. package/dist/assets/{createText-1719965b-CdcVoxJT.js → createText-1719965b-psgY2hME.js} +1 -1
  9. package/dist/assets/{edges-96097737-D8eSYgyp.js → edges-96097737-BA56Qmd2.js} +1 -1
  10. package/dist/assets/{erDiagram-0228fc6a-Cz1bZvQg.js → erDiagram-0228fc6a-Dyrrgc5j.js} +1 -1
  11. package/dist/assets/{flowDb-c6c81e3f-2Q7aPB-q.js → flowDb-c6c81e3f-CRgQ7Xd3.js} +1 -1
  12. package/dist/assets/{flowDiagram-50d868cf-CADXtRSY.js → flowDiagram-50d868cf-B73a9Glk.js} +1 -1
  13. package/dist/assets/flowDiagram-v2-4f6560a1-Ccm4QuQe.js +1 -0
  14. package/dist/assets/{flowchart-elk-definition-6af322e1-H7s8F7AZ.js → flowchart-elk-definition-6af322e1-DtsYC0Wf.js} +1 -1
  15. package/dist/assets/{ganttDiagram-a2739b55-ByPQlmCo.js → ganttDiagram-a2739b55-gzdnsQCV.js} +1 -1
  16. package/dist/assets/{gitGraphDiagram-82fe8481-BZVM0Fl8.js → gitGraphDiagram-82fe8481-RHa92Mol.js} +1 -1
  17. package/dist/assets/{graph-ClMJH_U-.js → graph-Uj8iC7DB.js} +1 -1
  18. package/dist/assets/{index-5325376f-HWUtfpil.js → index-5325376f-B2Q_MiDU.js} +1 -1
  19. package/dist/assets/{index-NlU1ELyk.js → index-ADFje5Kc.js} +113 -113
  20. package/dist/assets/{infoDiagram-8eee0895-wi7-H9nz.js → infoDiagram-8eee0895-BIrv_GjX.js} +1 -1
  21. package/dist/assets/{journeyDiagram-c64418c1-CZCyqk1X.js → journeyDiagram-c64418c1-DMZd-Mfh.js} +1 -1
  22. package/dist/assets/{layout-CONWz1Dx.js → layout-Bwa2VjOX.js} +1 -1
  23. package/dist/assets/{line-ugjigc8g.js → line-BDn4wwV7.js} +1 -1
  24. package/dist/assets/{linear-CziOoP7o.js → linear-DQPiAjW8.js} +1 -1
  25. package/dist/assets/{mermaid.core-8jQ7wVtv.js → mermaid.core-B5GfAmDT.js} +4 -4
  26. package/dist/assets/{mindmap-definition-8da855dc-74YgrTXA.js → mindmap-definition-8da855dc-BTOOR2ac.js} +1 -1
  27. package/dist/assets/{pieDiagram-a8764435-9MHYBe77.js → pieDiagram-a8764435-C3QNifd4.js} +1 -1
  28. package/dist/assets/{quadrantDiagram-1e28029f-T47Rsmlf.js → quadrantDiagram-1e28029f-Ds5ATncA.js} +1 -1
  29. package/dist/assets/{requirementDiagram-08caed73-DxX3Lp0B.js → requirementDiagram-08caed73-CVdpqqVi.js} +1 -1
  30. package/dist/assets/{sankeyDiagram-a04cb91d-DtlrXeOV.js → sankeyDiagram-a04cb91d-CxP85079.js} +1 -1
  31. package/dist/assets/{sequenceDiagram-c5b8d532-0e8o5pPE.js → sequenceDiagram-c5b8d532-BeaQEYgt.js} +1 -1
  32. package/dist/assets/{stateDiagram-1ecb1508-Uif8hYjc.js → stateDiagram-1ecb1508-Bv-YlfIf.js} +1 -1
  33. package/dist/assets/{stateDiagram-v2-c2b004d7-D8sWSYsQ.js → stateDiagram-v2-c2b004d7-CWKsGrvN.js} +1 -1
  34. package/dist/assets/{styles-b4e223ce-D43vhmWC.js → styles-b4e223ce-DzdnfR-A.js} +1 -1
  35. package/dist/assets/{styles-ca3715f6-DWma2mkN.js → styles-ca3715f6-BS5E4Xdv.js} +1 -1
  36. package/dist/assets/{styles-d45a18b0-kT58cZYw.js → styles-d45a18b0-t7c5i-_-.js} +1 -1
  37. package/dist/assets/{svgDrawCommon-b86b1483-D5ltvlh8.js → svgDrawCommon-b86b1483-CyA-VVES.js} +1 -1
  38. package/dist/assets/{timeline-definition-faaaa080-PXG_aexc.js → timeline-definition-faaaa080-BuFEjpzk.js} +1 -1
  39. package/dist/assets/{xychartDiagram-f5964ef8-qTUp7CdK.js → xychartDiagram-f5964ef8-B4b4QqYX.js} +1 -1
  40. package/dist/index.html +1 -1
  41. package/package.json +8 -8
  42. package/src/api/benchmark.ts +1 -0
  43. package/src/api/sessions.ts +2 -0
  44. package/src/components/chat/ChatHistoryView.tsx +12 -1
  45. package/src/components/chat/sender/Sender.tsx +33 -3
  46. package/src/components/config/configSchema.ts +13 -0
  47. package/src/hooks/chat/use-chat-effort.ts +55 -0
  48. package/src/hooks/chat/use-chat-model-adapter-selection.tsx +17 -11
  49. package/src/hooks/chat/use-chat-models.tsx +1 -6
  50. package/src/hooks/chat/use-chat-session-actions.ts +7 -0
  51. package/src/hooks/chat/use-chat-session-messages.ts +17 -3
  52. package/src/hooks/chat/use-chat-session.ts +18 -3
  53. package/src/resources/locales/en.json +10 -0
  54. package/src/resources/locales/zh.json +10 -0
  55. package/src/routes/ChatRoute.tsx +6 -0
  56. package/vite.config.ts +4 -2
  57. package/dist/assets/channel-5WTe7pNn.js +0 -1
  58. package/dist/assets/clone-LappdaLy.js +0 -1
  59. package/dist/assets/flowDiagram-v2-4f6560a1-VWENAHeD.js +0 -1
@@ -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-8jQ7wVtv.js";import{a as Qt}from"./createText-1719965b-CdcVoxJT.js";import"./index-NlU1ELyk.js";import{i as Kt}from"./init-Gi6I4Gst.js";import{o as Jt}from"./ordinal-Cboi1Yqb.js";import{l as ft}from"./linear-CziOoP7o.js";import{l as pt}from"./line-ugjigc8g.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)+`:
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-B5GfAmDT.js";import{a as Qt}from"./createText-1719965b-psgY2hME.js";import"./index-ADFje5Kc.js";import{i as Kt}from"./init-Gi6I4Gst.js";import{o as Jt}from"./ordinal-Cboi1Yqb.js";import{l as ft}from"./linear-DQPiAjW8.js";import{l as pt}from"./line-BDn4wwV7.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
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Vibe Forge Web</title>
7
- <script type="module" crossorigin src="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-NlU1ELyk.js"></script>
7
+ <script type="module" crossorigin src="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-ADFje5Kc.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-DGEAe87I.css">
9
9
  </head>
10
10
  <body>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vibe-forge/client",
3
3
  "type": "module",
4
- "version": "0.8.1",
4
+ "version": "0.8.3",
5
5
  "imports": {
6
6
  "#~/*": [
7
7
  "./src/*",
@@ -36,15 +36,15 @@
36
36
  "swr": "^2.2.5",
37
37
  "vite": "^5.4.8",
38
38
  "zod": "^3.24.1",
39
- "@vibe-forge/adapter-codex": "^0.8.0",
40
- "@vibe-forge/adapter-claude-code": "^0.8.0",
41
- "@vibe-forge/adapter-opencode": "^0.8.0",
42
39
  "@vibe-forge/channel-lark": "^0.8.0",
43
- "@vibe-forge/core": "^0.8.0",
44
- "@vibe-forge/register": "^0.8.0",
45
- "@vibe-forge/utils": "^0.8.0",
40
+ "@vibe-forge/core": "^0.8.3",
41
+ "@vibe-forge/adapter-codex": "^0.8.3",
42
+ "@vibe-forge/adapter-claude-code": "^0.8.3",
46
43
  "@vibe-forge/plugin-chrome-devtools": "^0.8.0",
47
- "@vibe-forge/types": "^0.8.0"
44
+ "@vibe-forge/adapter-opencode": "^0.8.3",
45
+ "@vibe-forge/register": "^0.8.0",
46
+ "@vibe-forge/utils": "^0.8.3",
47
+ "@vibe-forge/types": "^0.8.3"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/react": "^18.3.12",
@@ -8,6 +8,7 @@ export interface BenchmarkRunRequest {
8
8
  concurrency?: number
9
9
  adapter?: string
10
10
  model?: string
11
+ effort?: 'low' | 'medium' | 'high' | 'max'
11
12
  systemPrompt?: string
12
13
  permissionMode?: 'default' | 'acceptEdits' | 'plan' | 'dontAsk' | 'bypassPermissions'
13
14
  }
@@ -21,6 +21,7 @@ export async function createSession(
21
21
  id?: string
22
22
  promptType?: 'spec' | 'entity'
23
23
  promptName?: string
24
+ effort?: 'low' | 'medium' | 'high' | 'max'
24
25
  permissionMode?: 'default' | 'acceptEdits' | 'plan' | 'dontAsk' | 'bypassPermissions'
25
26
  adapter?: string
26
27
  }
@@ -38,6 +39,7 @@ export async function createSession(
38
39
  id: options?.id,
39
40
  promptType: options?.promptType,
40
41
  promptName: options?.promptName,
42
+ effort: options?.effort,
41
43
  permissionMode: options?.permissionMode,
42
44
  adapter: options?.adapter
43
45
  })
@@ -1,11 +1,12 @@
1
1
  import React, { useEffect, useMemo, useRef } from 'react'
2
2
  import { useTranslation } from 'react-i18next'
3
3
 
4
+ import type { ChatEffort } from '#~/hooks/chat/use-chat-effort'
4
5
  import type { PermissionMode } from '#~/hooks/chat/use-chat-permission-mode'
5
6
  import { useChatScroll } from '#~/hooks/chat/use-chat-scroll'
6
7
  import { useChatSessionActions } from '#~/hooks/chat/use-chat-session-actions'
7
- import type { SessionInfo } from '@vibe-forge/types'
8
8
  import type { AskUserQuestionParams, ChatMessage, ChatMessageContent, Session } from '@vibe-forge/core'
9
+ import type { SessionInfo } from '@vibe-forge/types'
9
10
  import { CurrentTodoList } from './CurrentTodoList'
10
11
  import { NewSessionGuide } from './NewSessionGuide'
11
12
  import { MessageItem } from './messages/MessageItem'
@@ -41,6 +42,9 @@ export function ChatHistoryView({
41
42
  selectedModel,
42
43
  modelForQuery,
43
44
  onModelChange,
45
+ effort,
46
+ effortOptions,
47
+ onEffortChange,
44
48
  permissionMode,
45
49
  permissionModeOptions,
46
50
  onPermissionModeChange,
@@ -65,6 +69,9 @@ export function ChatHistoryView({
65
69
  selectedModel?: string
66
70
  modelForQuery?: string
67
71
  onModelChange: (model: string) => void
72
+ effort: ChatEffort
73
+ effortOptions: Array<{ value: ChatEffort; label: React.ReactNode }>
74
+ onEffortChange: (effort: ChatEffort) => void
68
75
  permissionMode: PermissionMode
69
76
  permissionModeOptions: Array<{ value: PermissionMode; label: React.ReactNode }>
70
77
  onPermissionModeChange: (mode: PermissionMode) => void
@@ -82,6 +89,7 @@ export function ChatHistoryView({
82
89
  session,
83
90
  modelForQuery,
84
91
  hasAvailableModels,
92
+ effort,
85
93
  permissionMode,
86
94
  adapter: selectedAdapter,
87
95
  onClearMessages
@@ -211,6 +219,9 @@ export function ChatHistoryView({
211
219
  modelOptions={modelOptions}
212
220
  selectedModel={selectedModel}
213
221
  onModelChange={onModelChange}
222
+ effort={effort}
223
+ effortOptions={effortOptions}
224
+ onEffortChange={onEffortChange}
214
225
  permissionMode={permissionMode}
215
226
  permissionModeOptions={permissionModeOptions}
216
227
  onPermissionModeChange={onPermissionModeChange}
@@ -6,9 +6,10 @@ import React, { useRef, useState } from 'react'
6
6
  import { useTranslation } from 'react-i18next'
7
7
  import useSWR from 'swr'
8
8
 
9
+ import type { ChatEffort } from '#~/hooks/chat/use-chat-effort'
9
10
  import type { PermissionMode } from '#~/hooks/chat/use-chat-permission-mode'
10
- import type { SessionInfo } from '@vibe-forge/types'
11
11
  import type { AskUserQuestionParams, ChatMessageContent, SessionStatus } from '@vibe-forge/core'
12
+ import type { SessionInfo } from '@vibe-forge/types'
12
13
  import { isShortcutMatch } from '../../../utils/shortcutUtils'
13
14
  import type { CompletionItem } from './CompletionMenu'
14
15
  import { CompletionMenu } from './CompletionMenu'
@@ -76,6 +77,9 @@ export function Sender({
76
77
  modelOptions,
77
78
  selectedModel,
78
79
  onModelChange,
80
+ effort,
81
+ effortOptions,
82
+ onEffortChange,
79
83
  permissionMode,
80
84
  permissionModeOptions,
81
85
  onPermissionModeChange,
@@ -99,6 +103,9 @@ export function Sender({
99
103
  modelOptions?: ModelSelectGroup[]
100
104
  selectedModel?: string
101
105
  onModelChange?: (model: string) => void
106
+ effort: ChatEffort
107
+ effortOptions: Array<{ value: ChatEffort; label: React.ReactNode }>
108
+ onEffortChange: (effort: ChatEffort) => void
102
109
  permissionMode: PermissionMode
103
110
  permissionModeOptions: Array<{ value: PermissionMode; label: React.ReactNode }>
104
111
  onPermissionModeChange: (mode: PermissionMode) => void
@@ -138,6 +145,8 @@ export function Sender({
138
145
  : 'mod+enter'
139
146
 
140
147
  const isThinking = sessionStatus === 'running'
148
+ const supportsEffort = selectedAdapter === 'codex' || selectedAdapter === 'claude-code' ||
149
+ selectedAdapter === 'opencode'
141
150
  const groupedTools: SenderToolGroup[] = sessionInfo != null && sessionInfo.type === 'init'
142
151
  ? ([
143
152
  {
@@ -721,7 +730,10 @@ export function Sender({
721
730
  <div className='asset-warning-tooltip'>
722
731
  <div className='asset-warning-tooltip__title'>{t('chat.selectionWarningsTitle')}</div>
723
732
  {selectionWarnings.slice(0, 5).map((warning: SessionSelectionWarning, index: number) => (
724
- <div key={`${warning.adapter}:${warning.requestedModel}:${index}`} className='asset-warning-tooltip__item'>
733
+ <div
734
+ key={`${warning.adapter}:${warning.requestedModel}:${index}`}
735
+ className='asset-warning-tooltip__item'
736
+ >
725
737
  <span>{formatSelectionWarning(warning)}</span>
726
738
  </div>
727
739
  ))}
@@ -737,7 +749,9 @@ export function Sender({
737
749
  <span className='info-item-leading'>
738
750
  <span className='material-symbols-rounded'>warning</span>
739
751
  </span>
740
- <span className='info-text'>{t('chat.selectionWarningsCount', { count: selectionWarnings.length })}</span>
752
+ <span className='info-text'>
753
+ {t('chat.selectionWarningsCount', { count: selectionWarnings.length })}
754
+ </span>
741
755
  </div>
742
756
  </Tooltip>
743
757
  )}
@@ -826,6 +840,22 @@ export function Sender({
826
840
  popupMatchSelectWidth={false}
827
841
  />
828
842
 
843
+ {supportsEffort && (
844
+ <Select
845
+ className='effort-select'
846
+ classNames={{ popup: { root: 'effort-select-popup' } }}
847
+ value={effort}
848
+ options={effortOptions}
849
+ showSearch={false}
850
+ allowClear={false}
851
+ disabled={modelUnavailable || isThinking}
852
+ onChange={(value) => onEffortChange(value)}
853
+ placeholder='Effort'
854
+ optionLabelProp='label'
855
+ popupMatchSelectWidth={false}
856
+ />
857
+ )}
858
+
829
859
  <Select
830
860
  className='permission-mode-select'
831
861
  classNames={{ popup: { root: 'permission-mode-select-popup' } }}
@@ -48,6 +48,19 @@ export const configGroupMeta: Record<string, Record<string, { labelKey: string }
48
48
  export const configSchema: Record<string, FieldSpec[]> = {
49
49
  general: [
50
50
  { path: ['baseDir'], type: 'string', defaultValue: '.ai', icon: 'folder', group: 'base' },
51
+ {
52
+ path: ['effort'],
53
+ type: 'select',
54
+ defaultValue: '',
55
+ icon: 'psychology',
56
+ group: 'base',
57
+ options: [
58
+ { value: 'low', label: 'config.options.effort.low' },
59
+ { value: 'medium', label: 'config.options.effort.medium' },
60
+ { value: 'high', label: 'config.options.effort.high' },
61
+ { value: 'max', label: 'config.options.effort.max' }
62
+ ]
63
+ },
51
64
  { path: ['defaultAdapter'], type: 'select', defaultValue: '', icon: 'settings_input_component', group: 'base' },
52
65
  { path: ['defaultModelService'], type: 'select', defaultValue: '', icon: 'hub', group: 'base' },
53
66
  { path: ['defaultModel'], type: 'select', defaultValue: '', icon: 'model_training', group: 'base' },
@@ -0,0 +1,55 @@
1
+ import { useEffect, useMemo, useState } from 'react'
2
+ import type { ReactNode } from 'react'
3
+
4
+ export type ChatEffort = 'default' | 'low' | 'medium' | 'high' | 'max'
5
+
6
+ const EFFORT_STORAGE_KEY = 'vf_chat_effort'
7
+
8
+ export const isChatEffort = (value: string): value is ChatEffort => {
9
+ return value === 'default' ||
10
+ value === 'low' ||
11
+ value === 'medium' ||
12
+ value === 'high' ||
13
+ value === 'max'
14
+ }
15
+
16
+ export function useChatEffort() {
17
+ const [effort, setEffort] = useState<ChatEffort>('default')
18
+
19
+ const updateEffort = (value?: string) => {
20
+ if (value != null && isChatEffort(value)) {
21
+ setEffort(value)
22
+ return
23
+ }
24
+ setEffort('default')
25
+ }
26
+
27
+ useEffect(() => {
28
+ try {
29
+ const raw = localStorage.getItem(EFFORT_STORAGE_KEY)
30
+ if (raw && isChatEffort(raw)) {
31
+ updateEffort(raw)
32
+ }
33
+ } catch {}
34
+ }, [])
35
+
36
+ useEffect(() => {
37
+ try {
38
+ localStorage.setItem(EFFORT_STORAGE_KEY, effort)
39
+ } catch {}
40
+ }, [effort])
41
+
42
+ const effortOptions = useMemo<Array<{ value: ChatEffort; label: ReactNode }>>(() => [
43
+ { value: 'default', label: '默认' },
44
+ { value: 'low', label: '低' },
45
+ { value: 'medium', label: '中' },
46
+ { value: 'high', label: '高' },
47
+ { value: 'max', label: '最高' }
48
+ ], [])
49
+
50
+ return {
51
+ effort,
52
+ setEffort: updateEffort,
53
+ effortOptions
54
+ }
55
+ }
@@ -67,7 +67,9 @@ export function useChatModelAdapterSelection({
67
67
  adapterLocked?: boolean
68
68
  } = {}) {
69
69
  const { t } = useTranslation()
70
- const [selectedAdapter, setSelectedAdapter] = useState<string | undefined>(() => readStorageValue(ADAPTER_STORAGE_KEY))
70
+ const [selectedAdapter, setSelectedAdapter] = useState<string | undefined>(() =>
71
+ readStorageValue(ADAPTER_STORAGE_KEY)
72
+ )
71
73
  const [selectedModel, setSelectedModel] = useState<string | undefined>(() => readStorageValue(MODEL_STORAGE_KEY))
72
74
  const [selectionDriver, setSelectionDriver] = useState<SelectionDriver>(() => readSelectionDriver())
73
75
  const { data: configRes } = useSWR<ConfigResponse>('/api/config', getConfig)
@@ -124,15 +126,18 @@ export function useChatModelAdapterSelection({
124
126
  })
125
127
  }, [availableAdapters, defaultAdapter])
126
128
 
127
- const resolveSelectableModel = useCallback((value?: string, builtinModels?: Iterable<string>, preserveUnknown = false) => {
128
- return resolveChatModelSelection({
129
- value,
130
- builtinModels,
131
- serviceModels: availableServiceModels,
132
- defaultModelService,
133
- preserveUnknown
134
- })
135
- }, [availableServiceModels, defaultModelService])
129
+ const resolveSelectableModel = useCallback(
130
+ (value?: string, builtinModels?: Iterable<string>, preserveUnknown = false) => {
131
+ return resolveChatModelSelection({
132
+ value,
133
+ builtinModels,
134
+ serviceModels: availableServiceModels,
135
+ defaultModelService,
136
+ preserveUnknown
137
+ })
138
+ },
139
+ [availableServiceModels, defaultModelService]
140
+ )
136
141
 
137
142
  const resolveModelForAdapter = useCallback((adapter?: string) => {
138
143
  const builtinModels = buildBuiltinModelValues(
@@ -225,7 +230,8 @@ export function useChatModelAdapterSelection({
225
230
  }
226
231
 
227
232
  if (selectionDriver === 'model') {
228
- const nextModelCandidate = resolveSelectableModel(selectedModel, allBuiltinModelValues, false) ?? resolvedDefaultModel
233
+ const nextModelCandidate = resolveSelectableModel(selectedModel, allBuiltinModelValues, false) ??
234
+ resolvedDefaultModel
229
235
  const nextAdapter = resolveAdapterForModel(nextModelCandidate) ?? resolveAdapterValue(selectedAdapter)
230
236
  const nextModel = resolveCompatibleModelForAdapter(nextAdapter, nextModelCandidate)
231
237
  setSelectedModel((prev) => prev === nextModel ? prev : nextModel)
@@ -3,12 +3,7 @@ import { useTranslation } from 'react-i18next'
3
3
  import useSWR from 'swr'
4
4
 
5
5
  import { getConfig } from '#~/api.js'
6
- import type {
7
- AdapterBuiltinModel,
8
- ConfigResponse,
9
- ModelServiceConfig,
10
- RecommendedModelConfig
11
- } from '@vibe-forge/types'
6
+ import type { AdapterBuiltinModel, ConfigResponse, ModelServiceConfig, RecommendedModelConfig } from '@vibe-forge/types'
12
7
  import {
13
8
  buildServiceModelSelector,
14
9
  listServiceModels,
@@ -7,12 +7,14 @@ import { useSWRConfig } from 'swr'
7
7
  import { createSession, getApiErrorMessage } from '#~/api.js'
8
8
  import { connectionManager } from '#~/connectionManager.js'
9
9
  import type { ChatMessageContent, Session } from '@vibe-forge/core'
10
+ import type { ChatEffort } from './use-chat-effort'
10
11
  import type { PermissionMode } from './use-chat-permission-mode'
11
12
 
12
13
  export function useChatSessionActions({
13
14
  session,
14
15
  modelForQuery,
15
16
  hasAvailableModels,
17
+ effort,
16
18
  permissionMode,
17
19
  adapter,
18
20
  onClearMessages
@@ -20,6 +22,7 @@ export function useChatSessionActions({
20
22
  session?: Session
21
23
  modelForQuery?: string
22
24
  hasAvailableModels: boolean
25
+ effort: ChatEffort
23
26
  permissionMode: PermissionMode
24
27
  adapter?: string
25
28
  onClearMessages: () => void
@@ -47,6 +50,7 @@ export function useChatSessionActions({
47
50
  setIsCreating(true)
48
51
  try {
49
52
  const { session: newSession } = await createSession(undefined, text.trim(), undefined, modelForQuery, {
53
+ effort: effort === 'default' ? undefined : effort,
50
54
  permissionMode,
51
55
  adapter
52
56
  })
@@ -81,6 +85,7 @@ export function useChatSessionActions({
81
85
  message,
82
86
  mutate,
83
87
  navigate,
88
+ effort,
84
89
  permissionMode,
85
90
  modelForQuery,
86
91
  session?.id,
@@ -98,6 +103,7 @@ export function useChatSessionActions({
98
103
  setIsCreating(true)
99
104
  try {
100
105
  const { session: newSession } = await createSession(undefined, undefined, content, modelForQuery, {
106
+ effort: effort === 'default' ? undefined : effort,
101
107
  permissionMode,
102
108
  adapter
103
109
  })
@@ -132,6 +138,7 @@ export function useChatSessionActions({
132
138
  message,
133
139
  mutate,
134
140
  navigate,
141
+ effort,
135
142
  permissionMode,
136
143
  modelForQuery,
137
144
  session?.id,
@@ -4,8 +4,9 @@ import { useSWRConfig } from 'swr'
4
4
 
5
5
  import { getSessionMessages } from '#~/api.js'
6
6
  import { connectionManager } from '#~/connectionManager.js'
7
- import type { SessionInfo } from '@vibe-forge/types'
8
7
  import type { AskUserQuestionParams, ChatMessage, Session, WSEvent } from '@vibe-forge/core'
8
+ import type { SessionInfo } from '@vibe-forge/types'
9
+ import type { ChatEffort } from './use-chat-effort'
9
10
  import type { PermissionMode } from './use-chat-permission-mode'
10
11
 
11
12
  const applyMessageEvent = (currentMessages: ChatMessage[], data: WSEvent) => {
@@ -38,12 +39,14 @@ const applyToolResultEvent = (currentMessages: ChatMessage[], data: WSEvent): Ch
38
39
  export function useChatSessionMessages({
39
40
  session,
40
41
  modelForQuery,
42
+ effort,
41
43
  permissionMode,
42
44
  adapter,
43
45
  setInteractionRequest
44
46
  }: {
45
47
  session?: Session
46
48
  modelForQuery?: string
49
+ effort: ChatEffort
47
50
  permissionMode: PermissionMode
48
51
  adapter?: string
49
52
  setInteractionRequest: (value: { id: string; payload: AskUserQuestionParams } | null) => void
@@ -57,6 +60,7 @@ export function useChatSessionMessages({
57
60
  const [retryCount, setRetryCount] = useState(0)
58
61
  const isInitialLoadRef = useRef<boolean>(true)
59
62
  const lastConnectedModelRef = useRef<string | undefined>(undefined)
63
+ const lastConnectedEffortRef = useRef<string | undefined>(undefined)
60
64
  const lastConnectedPermissionModeRef = useRef<string | undefined>(undefined)
61
65
  const lastConnectedAdapterRef = useRef<string | undefined>(undefined)
62
66
  const expectedCloseRef = useRef(false)
@@ -80,6 +84,7 @@ export function useChatSessionMessages({
80
84
  if (session?.id == null || session.id === '') {
81
85
  setIsReady(true)
82
86
  lastConnectedModelRef.current = undefined
87
+ lastConnectedEffortRef.current = undefined
83
88
  lastConnectedPermissionModeRef.current = undefined
84
89
  lastConnectedAdapterRef.current = undefined
85
90
  return
@@ -153,6 +158,10 @@ export function useChatSessionMessages({
153
158
  lastConnectedModelRef.current != null &&
154
159
  normalizedModel !== lastConnectedModelRef.current &&
155
160
  session?.status !== 'running'
161
+ const normalizedEffort = effort === 'default' ? '' : effort
162
+ const effortChanged = lastConnectedEffortRef.current != null &&
163
+ normalizedEffort !== lastConnectedEffortRef.current &&
164
+ session?.status !== 'running'
156
165
  const normalizedPermissionMode = permissionMode ?? ''
157
166
  const permissionModeChanged = permissionMode != null &&
158
167
  lastConnectedPermissionModeRef.current != null &&
@@ -163,13 +172,14 @@ export function useChatSessionMessages({
163
172
  lastConnectedAdapterRef.current != null &&
164
173
  normalizedAdapter !== lastConnectedAdapterRef.current &&
165
174
  session?.status !== 'running'
166
- if (modelChanged || permissionModeChanged || adapterChanged) {
175
+ if (modelChanged || effortChanged || permissionModeChanged || adapterChanged) {
167
176
  expectedCloseRef.current = true
168
177
  setConnectionError(null)
169
178
  connectionManager.send(session.id, { type: 'terminate_session' })
170
179
  connectionManager.close(session.id)
171
180
  }
172
181
  lastConnectedModelRef.current = normalizedModel
182
+ lastConnectedEffortRef.current = normalizedEffort
173
183
  lastConnectedPermissionModeRef.current = normalizedPermissionMode
174
184
  lastConnectedAdapterRef.current = normalizedAdapter
175
185
 
@@ -180,6 +190,9 @@ export function useChatSessionMessages({
180
190
  if (modelForQuery) {
181
191
  connectionParams.model = modelForQuery
182
192
  }
193
+ if (effort !== 'default') {
194
+ connectionParams.effort = effort
195
+ }
183
196
  if (permissionMode) {
184
197
  connectionParams.permissionMode = permissionMode
185
198
  }
@@ -272,7 +285,7 @@ export function useChatSessionMessages({
272
285
  setConnectionError((current) => current ?? t('chat.connectionClosed'))
273
286
  }
274
287
  }, Object.keys(connectionParams).length > 0 ? connectionParams : undefined)
275
- }, (modelChanged || permissionModeChanged || adapterChanged) ? 200 : 100)
288
+ }, (modelChanged || effortChanged || permissionModeChanged || adapterChanged) ? 200 : 100)
276
289
 
277
290
  return () => {
278
291
  isDisposed = true
@@ -281,6 +294,7 @@ export function useChatSessionMessages({
281
294
  }
282
295
  }, [
283
296
  adapter,
297
+ effort,
284
298
  modelForQuery,
285
299
  mutate,
286
300
  permissionMode,
@@ -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,
@@ -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"