@vibe-forge/client 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/cli.cjs +1 -0
  2. package/dist/assets/{arc-DgIxeTMg.js → arc-C4ymrcSQ.js} +1 -1
  3. package/dist/assets/{blockDiagram-c4efeb88-CEAob3X9.js → blockDiagram-c4efeb88-CeB7-kgP.js} +1 -1
  4. package/dist/assets/{c4Diagram-c83219d4-DwIxpDKd.js → c4Diagram-c83219d4-C935Im8S.js} +1 -1
  5. package/dist/assets/channel-84s1ACzD.js +1 -0
  6. package/dist/assets/{classDiagram-beda092f-Cz1q8u_0.js → classDiagram-beda092f-B9IV13KI.js} +1 -1
  7. package/dist/assets/{classDiagram-v2-2358418a-CImgTuwd.js → classDiagram-v2-2358418a-CXF_K4fE.js} +1 -1
  8. package/dist/assets/clone-B2E8tddE.js +1 -0
  9. package/dist/assets/{createText-1719965b-C1_HJcCc.js → createText-1719965b-DwX8iC5F.js} +1 -1
  10. package/dist/assets/{edges-96097737-BU8qStzd.js → edges-96097737-9P1uH1RE.js} +1 -1
  11. package/dist/assets/{erDiagram-0228fc6a-DNA1Fz2L.js → erDiagram-0228fc6a-ixeGTFvg.js} +1 -1
  12. package/dist/assets/{flowDb-c6c81e3f-DjiCStMN.js → flowDb-c6c81e3f-G1gSTTBI.js} +1 -1
  13. package/dist/assets/{flowDiagram-50d868cf-CSDi0-RD.js → flowDiagram-50d868cf-CzrG99nD.js} +1 -1
  14. package/dist/assets/flowDiagram-v2-4f6560a1-CJfJYbME.js +1 -0
  15. package/dist/assets/{flowchart-elk-definition-6af322e1-DrhIMas7.js → flowchart-elk-definition-6af322e1-sFCoysWa.js} +1 -1
  16. package/dist/assets/{ganttDiagram-a2739b55-CTZnUP5z.js → ganttDiagram-a2739b55-Ccsk_Lru.js} +1 -1
  17. package/dist/assets/{gitGraphDiagram-82fe8481-COOW7jTi.js → gitGraphDiagram-82fe8481-CwathJ6H.js} +1 -1
  18. package/dist/assets/{graph-CIkpD4Kx.js → graph-DRCU-8Rz.js} +1 -1
  19. package/dist/assets/{index-5325376f-aVVRRTIu.js → index-5325376f-Bq-fg2i_.js} +1 -1
  20. package/dist/assets/{index-D1giUI7r.css → index-CHMuZ5-1.css} +1 -1
  21. package/dist/assets/{index-DRSI_ZIL.js → index-cGZvDhhU.js} +165 -137
  22. package/dist/assets/{infoDiagram-8eee0895-DQpZ1LVD.js → infoDiagram-8eee0895-JBcUkJ6T.js} +1 -1
  23. package/dist/assets/{journeyDiagram-c64418c1-DoKguIuk.js → journeyDiagram-c64418c1-DsdQU-R8.js} +1 -1
  24. package/dist/assets/{layout-Tnmha8Nh.js → layout-s0slG1OL.js} +1 -1
  25. package/dist/assets/{line-BQR2SOyl.js → line-CymFqgW6.js} +1 -1
  26. package/dist/assets/{linear-DlG0eemV.js → linear-lDQVZ6aQ.js} +1 -1
  27. package/dist/assets/{mermaid.core-BnwYO0He.js → mermaid.core-Cmlqga_E.js} +4 -4
  28. package/dist/assets/{mindmap-definition-8da855dc-BllYwDID.js → mindmap-definition-8da855dc-CqqTDJn_.js} +1 -1
  29. package/dist/assets/{pieDiagram-a8764435-DwCkhPVc.js → pieDiagram-a8764435-BL2Ajx7Z.js} +1 -1
  30. package/dist/assets/{quadrantDiagram-1e28029f-c40GKTU0.js → quadrantDiagram-1e28029f-ClL_3ASt.js} +1 -1
  31. package/dist/assets/{requirementDiagram-08caed73-DnQp2Tk6.js → requirementDiagram-08caed73-CB1RgE3K.js} +1 -1
  32. package/dist/assets/{sankeyDiagram-a04cb91d-CnJrs13b.js → sankeyDiagram-a04cb91d-tgleEYiD.js} +1 -1
  33. package/dist/assets/{sequenceDiagram-c5b8d532-1YBwnpKu.js → sequenceDiagram-c5b8d532-DlatQT5R.js} +1 -1
  34. package/dist/assets/{stateDiagram-1ecb1508-BFBxQ6Fh.js → stateDiagram-1ecb1508-B--MLqRs.js} +1 -1
  35. package/dist/assets/{stateDiagram-v2-c2b004d7-Dmechvv2.js → stateDiagram-v2-c2b004d7-CRMZ6Dpx.js} +1 -1
  36. package/dist/assets/{styles-b4e223ce-DWWfWX8O.js → styles-b4e223ce-CPiYHfUz.js} +1 -1
  37. package/dist/assets/{styles-ca3715f6-CKKvZxaU.js → styles-ca3715f6-B9UKPAzX.js} +1 -1
  38. package/dist/assets/{styles-d45a18b0-dKMOUh9p.js → styles-d45a18b0-BC1Ak1So.js} +1 -1
  39. package/dist/assets/{svgDrawCommon-b86b1483-CBgjChPM.js → svgDrawCommon-b86b1483-DV8R0g-n.js} +1 -1
  40. package/dist/assets/{timeline-definition-faaaa080-NCt-HHmb.js → timeline-definition-faaaa080-CiqGS5DC.js} +1 -1
  41. package/dist/assets/{xychartDiagram-f5964ef8-BJhXS4dG.js → xychartDiagram-f5964ef8-h6VSD3GE.js} +1 -1
  42. package/dist/index.html +2 -2
  43. package/package.json +7 -6
  44. package/src/api/sessions.ts +3 -1
  45. package/src/components/Chat.tsx +6 -0
  46. package/src/components/ConfigView.tsx +25 -25
  47. package/src/components/chat/ChatHistoryView.tsx +10 -0
  48. package/src/components/chat/Sender/Sender.scss +80 -17
  49. package/src/components/chat/Sender/Sender.tsx +22 -0
  50. package/src/components/config/ConfigSourceSwitch.tsx +12 -34
  51. package/src/components/config/channelDefinitions.ts +2 -2
  52. package/src/components/config/recordEditors/ChannelRecordEditor.tsx +33 -33
  53. package/src/components/sidebar/SessionItem.scss +17 -0
  54. package/src/components/sidebar/SessionItem.tsx +21 -13
  55. package/src/hooks/chat/use-chat-adapter.ts +81 -0
  56. package/src/hooks/chat/use-chat-models.tsx +73 -9
  57. package/src/hooks/chat/use-chat-session-actions.ts +9 -3
  58. package/src/hooks/chat/use-chat-session-messages.ts +17 -5
  59. package/src/hooks/chat/use-chat-session.ts +7 -1
  60. package/src/resources/adapters.ts +20 -0
  61. package/dist/assets/channel-DhtnrNJ6.js +0 -1
  62. package/dist/assets/clone-7bHB6YkC.js +0 -1
  63. package/dist/assets/flowDiagram-v2-4f6560a1-_13Sz5Wh.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-BnwYO0He.js";import{a as Qt}from"./createText-1719965b-C1_HJcCc.js";import"./index-DRSI_ZIL.js";import{i as Kt}from"./init-Gi6I4Gst.js";import{o as Jt}from"./ordinal-Cboi1Yqb.js";import{l as ft}from"./linear-DlG0eemV.js";import{l as pt}from"./line-BQR2SOyl.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-Cmlqga_E.js";import{a as Qt}from"./createText-1719965b-DwX8iC5F.js";import"./index-cGZvDhhU.js";import{i as Kt}from"./init-Gi6I4Gst.js";import{o as Jt}from"./ordinal-Cboi1Yqb.js";import{l as ft}from"./linear-lDQVZ6aQ.js";import{l as pt}from"./line-CymFqgW6.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-DRSI_ZIL.js"></script>
18
- <link rel="stylesheet" crossorigin href="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-D1giUI7r.css">
17
+ <script type="module" crossorigin src="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-cGZvDhhU.js"></script>
18
+ <link rel="stylesheet" crossorigin href="/__VF_PROJECT_AI_CLIENT_BASE__/assets/index-CHMuZ5-1.css">
19
19
  </head>
20
20
  <body>
21
21
  <div id="root"></div>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vibe-forge/client",
3
3
  "type": "module",
4
- "version": "0.4.0",
4
+ "version": "0.5.0",
5
5
  "imports": {
6
6
  "#~/*": [
7
7
  "./src/*",
@@ -34,11 +34,12 @@
34
34
  "swr": "^2.2.5",
35
35
  "vite": "^5.4.8",
36
36
  "zod": "^3.24.1",
37
- "@vibe-forge/channel-lark": "^0.4.0",
38
- "@vibe-forge/core": "^0.4.0",
39
- "@vibe-forge/plugin-chrome-devtools": "^0.4.0",
40
- "@vibe-forge/adapter-claude-code": "^0.4.0",
41
- "@vibe-forge/register": "^0.4.0"
37
+ "@vibe-forge/adapter-codex": "^0.5.0",
38
+ "@vibe-forge/adapter-claude-code": "^0.5.0",
39
+ "@vibe-forge/core": "^0.5.0",
40
+ "@vibe-forge/channel-lark": "^0.5.0",
41
+ "@vibe-forge/register": "^0.5.0",
42
+ "@vibe-forge/plugin-chrome-devtools": "^0.5.0"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@types/react": "^18.3.12",
@@ -22,6 +22,7 @@ export async function createSession(
22
22
  promptType?: 'spec' | 'entity'
23
23
  promptName?: string
24
24
  permissionMode?: 'default' | 'acceptEdits' | 'plan' | 'dontAsk' | 'bypassPermissions'
25
+ adapter?: string
25
26
  }
26
27
  ): Promise<{ session: Session }> {
27
28
  return fetchApiJson<{ session: Session }>('/api/sessions', {
@@ -37,7 +38,8 @@ export async function createSession(
37
38
  id: options?.id,
38
39
  promptType: options?.promptType,
39
40
  promptName: options?.promptName,
40
- permissionMode: options?.permissionMode
41
+ permissionMode: options?.permissionMode,
42
+ adapter: options?.adapter
41
43
  })
42
44
  })
43
45
  }
@@ -29,6 +29,9 @@ export function Chat({
29
29
  permissionMode,
30
30
  setPermissionMode,
31
31
  permissionModeOptions,
32
+ selectedAdapter,
33
+ setSelectedAdapter,
34
+ adapterOptions,
32
35
  hasAvailableModels,
33
36
  modelUnavailable
34
37
  } = useChatSession({ session })
@@ -80,6 +83,9 @@ export function Chat({
80
83
  permissionMode={permissionMode}
81
84
  permissionModeOptions={permissionModeOptions}
82
85
  onPermissionModeChange={setPermissionMode}
86
+ selectedAdapter={selectedAdapter}
87
+ adapterOptions={adapterOptions}
88
+ onAdapterChange={setSelectedAdapter}
83
89
  modelUnavailable={modelUnavailable}
84
90
  hasAvailableModels={hasAvailableModels}
85
91
  />
@@ -8,6 +8,7 @@ import useSWR from 'swr'
8
8
  import type { AboutInfo, ConfigResponse, ConfigSource } from '@vibe-forge/core'
9
9
 
10
10
  import { getConfig, updateConfig } from '../api'
11
+ import { useQueryParams } from '../hooks/useQueryParams'
11
12
  import { AboutSection, ConfigSectionPanel, ConfigSourceSwitch, DisplayValue } from './config'
12
13
  import { AppSettingsPanel } from './config/AppSettingsPanel'
13
14
  import { cloneValue, getValueByPath, isEmptyValue } from './config/configUtils'
@@ -16,8 +17,12 @@ export function ConfigView() {
16
17
  const { t } = useTranslation()
17
18
  const { message } = App.useApp()
18
19
  const { data, isLoading, error, mutate } = useSWR<ConfigResponse>('/api/config', getConfig)
19
- const [sourceKey, setSourceKey] = useState<ConfigSource>('project')
20
- const [activeTabKey, setActiveTabKey] = useState('general')
20
+ const { values: queryValues, update: updateQuery, searchParams } = useQueryParams<{ tab: string; source: string }>({
21
+ keys: ['tab', 'source'],
22
+ defaults: { tab: 'general', source: 'project' },
23
+ })
24
+ const sourceKey: ConfigSource = queryValues.source === 'user' ? 'user' : 'project'
25
+ const setSourceKey = (next: ConfigSource) => updateQuery({ source: next })
21
26
  const [drafts, setDrafts] = useState<Record<string, unknown>>({})
22
27
  const configPresent = data?.meta?.configPresent
23
28
  const currentSource = data?.sources?.[sourceKey]
@@ -33,10 +38,11 @@ export function ConfigView() {
33
38
  ])
34
39
 
35
40
  useEffect(() => {
41
+ if (searchParams.get('source') != null) return
36
42
  if (configPresent?.project) {
37
- setSourceKey('project')
43
+ updateQuery({ source: 'project' })
38
44
  } else if (configPresent?.user) {
39
- setSourceKey('user')
45
+ updateQuery({ source: 'user' })
40
46
  }
41
47
  }, [configPresent?.project, configPresent?.user])
42
48
 
@@ -89,26 +95,10 @@ export function ConfigView() {
89
95
  ], [currentSource, data?.meta?.about, data?.meta?.experiments, t])
90
96
  const tabKeys = useMemo(() => new Set(tabs.filter(tab => tab.type !== 'group').map(tab => tab.key)), [tabs])
91
97
 
92
- const activeTab = useMemo(() => tabs.find(tab => tab.key === activeTabKey), [tabs, activeTabKey])
93
-
94
- const initializedTabRef = useRef(false)
95
- useEffect(() => {
96
- if (initializedTabRef.current) return
97
- const params = new URLSearchParams(window.location.search)
98
- const tabKey = params.get('tab')
99
- if (tabKey != null && tabKeys.has(tabKey)) {
100
- setActiveTabKey(tabKey)
101
- }
102
- initializedTabRef.current = true
103
- }, [tabKeys])
98
+ const activeTabKey = tabKeys.has(queryValues.tab) ? queryValues.tab : 'general'
99
+ const setActiveTabKey = (key: string) => updateQuery({ tab: key })
104
100
 
105
- useEffect(() => {
106
- if (!tabKeys.has(activeTabKey)) return
107
- const params = new URLSearchParams(window.location.search)
108
- params.set('tab', activeTabKey)
109
- const nextUrl = `${window.location.pathname}?${params.toString()}${window.location.hash}`
110
- window.history.replaceState(null, '', nextUrl)
111
- }, [activeTabKey, tabKeys])
101
+ const activeTab = useMemo(() => tabs.find(tab => tab.key === activeTabKey), [tabs, activeTabKey])
112
102
 
113
103
  useEffect(() => {
114
104
  if (activeTab == null) return
@@ -251,8 +241,18 @@ export function ConfigView() {
251
241
  <ConfigSourceSwitch
252
242
  value={sourceKey}
253
243
  onChange={setSourceKey}
254
- configPresent={configPresent}
255
- t={t}
244
+ options={[
245
+ {
246
+ value: 'project',
247
+ icon: 'folder',
248
+ label: configPresent?.project === true ? t('config.sources.project') : t('config.sources.projectMissing')
249
+ },
250
+ {
251
+ value: 'user',
252
+ icon: 'person',
253
+ label: configPresent?.user === true ? t('config.sources.user') : t('config.sources.userMissing')
254
+ }
255
+ ]}
256
256
  />
257
257
  </Space>
258
258
  )}
@@ -40,6 +40,9 @@ export function ChatHistoryView({
40
40
  permissionMode,
41
41
  permissionModeOptions,
42
42
  onPermissionModeChange,
43
+ selectedAdapter,
44
+ adapterOptions,
45
+ onAdapterChange,
43
46
  modelUnavailable,
44
47
  hasAvailableModels
45
48
  }: {
@@ -60,6 +63,9 @@ export function ChatHistoryView({
60
63
  permissionMode: PermissionMode
61
64
  permissionModeOptions: Array<{ value: PermissionMode; label: React.ReactNode }>
62
65
  onPermissionModeChange: (mode: PermissionMode) => void
66
+ selectedAdapter?: string
67
+ adapterOptions: Array<{ value: string; label: React.ReactNode }>
68
+ onAdapterChange: (adapter: string) => void
63
69
  modelUnavailable: boolean
64
70
  hasAvailableModels: boolean
65
71
  }) {
@@ -71,6 +77,7 @@ export function ChatHistoryView({
71
77
  modelForQuery,
72
78
  hasAvailableModels,
73
79
  permissionMode,
80
+ adapter: selectedAdapter,
74
81
  onClearMessages
75
82
  })
76
83
  const initialScrollDoneRef = useRef(false)
@@ -158,6 +165,9 @@ export function ChatHistoryView({
158
165
  permissionMode={permissionMode}
159
166
  permissionModeOptions={permissionModeOptions}
160
167
  onPermissionModeChange={onPermissionModeChange}
168
+ selectedAdapter={selectedAdapter}
169
+ adapterOptions={adapterOptions}
170
+ onAdapterChange={onAdapterChange}
161
171
  modelUnavailable={modelUnavailable}
162
172
  />
163
173
  </div>
@@ -267,9 +267,9 @@
267
267
  }
268
268
  }
269
269
 
270
- .model-select {
271
- min-width: 160px;
272
-
270
+ .adapter-select,
271
+ .model-select,
272
+ .permission-mode-select {
273
273
  .ant-select-selector {
274
274
  height: 28px !important;
275
275
  border-radius: 8px !important;
@@ -293,30 +293,33 @@
293
293
  }
294
294
  }
295
295
 
296
- .permission-mode-select {
297
- min-width: 120px;
296
+ .adapter-select {
297
+ min-width: 100px;
298
298
 
299
299
  .ant-select-selector {
300
- height: 28px !important;
301
- border-radius: 8px !important;
302
- border: 1px solid var(--border-color) !important;
303
- background-color: var(--tag-hover-bg, #f3f4f6) !important;
304
- padding: 0 8px !important;
300
+ padding-right: 24px !important;
301
+ }
302
+
303
+ .ant-select-selection-wrap {
305
304
  display: flex;
306
305
  align-items: center;
307
306
  }
308
307
 
309
308
  .ant-select-selection-item,
310
309
  .ant-select-selection-placeholder {
311
- font-size: 12px;
312
- color: var(--text-color);
313
- line-height: 1;
310
+ display: inline-flex;
311
+ align-items: center;
312
+ min-width: 0;
314
313
  }
314
+ }
315
315
 
316
- &.ant-select-disabled .ant-select-selector {
317
- background-color: var(--tag-bg, #f9fafb) !important;
318
- color: var(--sub-text-color, #9ca3af);
319
- }
316
+ .model-select {
317
+ min-width: 160px;
318
+
319
+ }
320
+
321
+ .permission-mode-select {
322
+ min-width: 120px;
320
323
  }
321
324
 
322
325
  .permission-mode-select-popup {
@@ -325,6 +328,66 @@
325
328
  }
326
329
  }
327
330
 
331
+ .adapter-select-popup {
332
+ .ant-select-item-option {
333
+ display: flex;
334
+ align-items: center;
335
+ }
336
+
337
+ .ant-select-item-option-content {
338
+ display: flex;
339
+ align-items: center;
340
+ flex: 1;
341
+ min-height: 20px;
342
+ font-size: 12px;
343
+ }
344
+
345
+ .adapter-option {
346
+ display: flex;
347
+ align-items: center;
348
+ gap: 6px;
349
+ width: 100%;
350
+ }
351
+
352
+ .adapter-option__icon {
353
+ width: 14px;
354
+ height: 14px;
355
+ object-fit: contain;
356
+ flex-shrink: 0;
357
+ }
358
+
359
+ .adapter-option__text {
360
+ display: flex;
361
+ align-items: center;
362
+ min-height: 14px;
363
+ line-height: 1;
364
+ }
365
+
366
+ }
367
+
368
+ .adapter-option {
369
+ display: inline-flex;
370
+ align-items: center;
371
+ gap: 6px;
372
+ min-width: 0;
373
+ }
374
+
375
+ .adapter-option__icon {
376
+ width: 14px;
377
+ height: 14px;
378
+ display: block;
379
+ object-fit: contain;
380
+ flex-shrink: 0;
381
+ }
382
+
383
+ .adapter-option__text {
384
+ display: inline-block;
385
+ min-width: 0;
386
+ overflow: hidden;
387
+ text-overflow: ellipsis;
388
+ white-space: nowrap;
389
+ }
390
+
328
391
  .model-select-popup {
329
392
  .ant-select-item-group {
330
393
  padding: 8px 8px 4px;
@@ -50,6 +50,9 @@ export function Sender({
50
50
  permissionMode,
51
51
  permissionModeOptions,
52
52
  onPermissionModeChange,
53
+ selectedAdapter,
54
+ adapterOptions,
55
+ onAdapterChange,
53
56
  modelUnavailable
54
57
  }: {
55
58
  onSend: (text: string) => void
@@ -67,6 +70,9 @@ export function Sender({
67
70
  permissionMode: PermissionMode
68
71
  permissionModeOptions: Array<{ value: PermissionMode; label: React.ReactNode }>
69
72
  onPermissionModeChange: (mode: PermissionMode) => void
73
+ selectedAdapter?: string
74
+ adapterOptions?: Array<{ value: string; label: React.ReactNode }>
75
+ onAdapterChange?: (adapter: string) => void
70
76
  modelUnavailable?: boolean
71
77
  }) {
72
78
  const { t } = useTranslation()
@@ -646,6 +652,22 @@ export function Sender({
646
652
  </div>
647
653
 
648
654
  <div className='toolbar-right'>
655
+ {adapterOptions && adapterOptions.length > 1 && (
656
+ <Select
657
+ className='adapter-select'
658
+ classNames={{ popup: { root: 'adapter-select-popup' } }}
659
+ value={selectedAdapter}
660
+ options={adapterOptions}
661
+ showSearch={false}
662
+ allowClear={false}
663
+ disabled={modelUnavailable || isThinking}
664
+ onChange={(value) => onAdapterChange?.(value)}
665
+ placeholder={t('chat.adapterSelectPlaceholder', { defaultValue: 'Adapter' })}
666
+ optionLabelProp='label'
667
+ popupMatchSelectWidth={false}
668
+ />
669
+ )}
670
+
649
671
  <Select
650
672
  className='model-select'
651
673
  classNames={{ popup: { root: 'model-select-popup' } }}
@@ -1,19 +1,16 @@
1
1
  import { Radio } from 'antd'
2
+ import type { ReactNode } from 'react'
2
3
 
3
4
  import type { ConfigSource } from '@vibe-forge/core'
4
5
 
5
- import type { TranslationFn } from './configUtils'
6
-
7
6
  export function ConfigSourceSwitch({
8
7
  value,
9
8
  onChange,
10
- configPresent,
11
- t
9
+ options,
12
10
  }: {
13
11
  value: ConfigSource
14
12
  onChange: (value: ConfigSource) => void
15
- configPresent?: { project?: boolean; user?: boolean }
16
- t: TranslationFn
13
+ options: Array<{ value: ConfigSource; icon: string; label: ReactNode }>
17
14
  }) {
18
15
  return (
19
16
  <Radio.Group
@@ -24,34 +21,15 @@ export function ConfigSourceSwitch({
24
21
  onChange={(event) => {
25
22
  onChange(event.target.value as ConfigSource)
26
23
  }}
27
- options={[
28
- {
29
- label: (
30
- <span className='config-view__source-option'>
31
- <span className='material-symbols-rounded'>folder</span>
32
- <span>
33
- {configPresent?.project === true
34
- ? t('config.sources.project')
35
- : t('config.sources.projectMissing')}
36
- </span>
37
- </span>
38
- ),
39
- value: 'project'
40
- },
41
- {
42
- label: (
43
- <span className='config-view__source-option'>
44
- <span className='material-symbols-rounded'>person</span>
45
- <span>
46
- {configPresent?.user === true
47
- ? t('config.sources.user')
48
- : t('config.sources.userMissing')}
49
- </span>
50
- </span>
51
- ),
52
- value: 'user'
53
- }
54
- ]}
24
+ options={options.map(opt => ({
25
+ value: opt.value,
26
+ label: (
27
+ <span className='config-view__source-option'>
28
+ <span className='material-symbols-rounded'>{opt.icon}</span>
29
+ <span>{opt.label}</span>
30
+ </span>
31
+ )
32
+ }))}
55
33
  />
56
34
  )
57
35
  }
@@ -1,6 +1,6 @@
1
- import { larkChannelDefinition } from '@vibe-forge/channel-lark'
1
+ import { channelDefinition } from '@vibe-forge/channel-lark'
2
2
  import type { ChannelDescriptor } from '@vibe-forge/core/channel'
3
3
 
4
4
  export const channelDefinitions: ChannelDescriptor[] = [
5
- larkChannelDefinition
5
+ channelDefinition
6
6
  ]
@@ -257,6 +257,39 @@ export const ChannelRecordEditor = ({
257
257
 
258
258
  return (
259
259
  <div className='config-view__record-list'>
260
+ <div className='config-view__record-add'>
261
+ <div className='config-view__record-add-inputs'>
262
+ <Input
263
+ value={newKey}
264
+ placeholder={keyPlaceholder}
265
+ onChange={(event) => setNewKey(event.target.value)}
266
+ />
267
+ <Select
268
+ value={newType}
269
+ options={typeOptions}
270
+ onChange={(nextValue) => setNewType(nextValue)}
271
+ />
272
+ <Tooltip title={t('common.confirm')}>
273
+ <Button
274
+ size='small'
275
+ type='primary'
276
+ className='config-view__icon-button'
277
+ aria-label={t('common.confirm')}
278
+ icon={<span className='material-symbols-rounded'>check</span>}
279
+ disabled={newKey.trim() === '' || Object.hasOwn(value, newKey) || newType === ''}
280
+ onClick={() => {
281
+ const definition = getChannelDefinition(newType)
282
+ if (!definition) return
283
+ onChange({
284
+ ...value,
285
+ [newKey]: buildRecordDefaults(definition)
286
+ })
287
+ setNewKey('')
288
+ }}
289
+ />
290
+ </Tooltip>
291
+ </div>
292
+ </div>
260
293
  {entries.map(([key, itemValue]) => {
261
294
  const recordValue = (itemValue != null && typeof itemValue === 'object')
262
295
  ? itemValue as ChannelRecordValue
@@ -359,39 +392,6 @@ export const ChannelRecordEditor = ({
359
392
  </div>
360
393
  )
361
394
  })}
362
- <div className='config-view__record-add'>
363
- <div className='config-view__record-add-inputs'>
364
- <Input
365
- value={newKey}
366
- placeholder={keyPlaceholder}
367
- onChange={(event) => setNewKey(event.target.value)}
368
- />
369
- <Select
370
- value={newType}
371
- options={typeOptions}
372
- onChange={(nextValue) => setNewType(nextValue)}
373
- />
374
- <Tooltip title={t('common.confirm')}>
375
- <Button
376
- size='small'
377
- type='primary'
378
- className='config-view__icon-button'
379
- aria-label={t('common.confirm')}
380
- icon={<span className='material-symbols-rounded'>check</span>}
381
- disabled={newKey.trim() === '' || Object.hasOwn(value, newKey) || newType === ''}
382
- onClick={() => {
383
- const definition = getChannelDefinition(newType)
384
- if (!definition) return
385
- onChange({
386
- ...value,
387
- [newKey]: buildRecordDefaults(definition)
388
- })
389
- setNewKey('')
390
- }}
391
- />
392
- </Tooltip>
393
- </div>
394
- </div>
395
395
  </div>
396
396
  )
397
397
  }
@@ -163,11 +163,15 @@
163
163
  align-items: center;
164
164
 
165
165
  .session-tag {
166
+ max-width: 120px;
166
167
  font-size: 10px;
167
168
  margin: 0;
168
169
  padding: 0 4px;
169
170
  line-height: 14px;
170
171
  border-radius: 2px;
172
+ display: inline-flex;
173
+ align-items: center;
174
+ white-space: nowrap;
171
175
 
172
176
  &--automation {
173
177
  padding: 0 6px;
@@ -176,6 +180,19 @@
176
180
  &__link {
177
181
  color: var(--primary-color);
178
182
  text-decoration: none;
183
+ display: inline-block;
184
+ max-width: 100%;
185
+ overflow: hidden;
186
+ text-overflow: ellipsis;
187
+ white-space: nowrap;
188
+ }
189
+
190
+ &__text {
191
+ display: inline-block;
192
+ max-width: 100%;
193
+ overflow: hidden;
194
+ text-overflow: ellipsis;
195
+ white-space: nowrap;
179
196
  }
180
197
  }
181
198
  }
@@ -226,28 +226,36 @@ export function SessionItem({
226
226
  if (automationTag) {
227
227
  const href = `/automation?rule=${encodeURIComponent(automationTag.ruleId)}`
228
228
  return (
229
- <Tag
229
+ <Tooltip
230
230
  key={tag}
231
- className='session-tag session-tag--automation'
232
- onClick={(event) => event.stopPropagation()}
231
+ title={automationTag.ruleTitle}
233
232
  >
234
- <a
235
- className='session-tag__link'
236
- href={href}
233
+ <Tag
234
+ className='session-tag session-tag--automation'
237
235
  onClick={(event) => event.stopPropagation()}
238
236
  >
239
- {automationTag.ruleTitle}
240
- </a>
241
- </Tag>
237
+ <a
238
+ className='session-tag__link'
239
+ href={href}
240
+ onClick={(event) => event.stopPropagation()}
241
+ >
242
+ {automationTag.ruleTitle}
243
+ </a>
244
+ </Tag>
245
+ </Tooltip>
242
246
  )
243
247
  }
244
248
  return (
245
- <Tag
249
+ <Tooltip
246
250
  key={tag}
247
- className='session-tag'
251
+ title={tag}
248
252
  >
249
- {tag}
250
- </Tag>
253
+ <Tag className='session-tag'>
254
+ <span className='session-tag__text'>
255
+ {tag}
256
+ </span>
257
+ </Tag>
258
+ </Tooltip>
251
259
  )
252
260
  })}
253
261
  </div>