@yancyyu/openhermit 1.6.4 → 1.6.6

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 (76) hide show
  1. package/README.md +52 -140
  2. package/bin/hermit.mjs +79 -297
  3. package/dist-renderer/assets/{ProjectEditorOverlay-BcjkdR8y.js → ProjectEditorOverlay-pgmdlWxa.js} +1 -1
  4. package/dist-renderer/assets/{TeamGraphOverlay-B9PP0b_t.js → TeamGraphOverlay-hN5q6AG0.js} +1 -1
  5. package/dist-renderer/assets/{_basePickBy-CPquAmj5.js → _basePickBy-Bk3vVggp.js} +1 -1
  6. package/dist-renderer/assets/{_baseUniq-A66EsJn2.js → _baseUniq-dMa0BJXs.js} +1 -1
  7. package/dist-renderer/assets/{arc-YLxbV3Qw.js → arc-DJlWrmw7.js} +1 -1
  8. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-wwpiLSwy.js → architectureDiagram-VXUJARFQ-BEk2m-RH.js} +1 -1
  9. package/dist-renderer/assets/{blockDiagram-VD42YOAC-3CHE3NYR.js → blockDiagram-VD42YOAC-DikRTLHM.js} +1 -1
  10. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-K8hDNmEC.js → c4Diagram-YG6GDRKO-2zOWoKX8.js} +1 -1
  11. package/dist-renderer/assets/channel-BL6oUYPL.js +1 -0
  12. package/dist-renderer/assets/{chunk-4BX2VUAB-5OabZrhH.js → chunk-4BX2VUAB-7PeMCF0g.js} +1 -1
  13. package/dist-renderer/assets/{chunk-55IACEB6-v2kdM_aT.js → chunk-55IACEB6-6LuNK7l-.js} +1 -1
  14. package/dist-renderer/assets/{chunk-B4BG7PRW-C0Ju56SH.js → chunk-B4BG7PRW-9Q4M3OpN.js} +1 -1
  15. package/dist-renderer/assets/{chunk-DI55MBZ5-DPTWTKRm.js → chunk-DI55MBZ5-mGGPKOCm.js} +1 -1
  16. package/dist-renderer/assets/{chunk-FMBD7UC4-DSkYppkv.js → chunk-FMBD7UC4-BTZYjAAP.js} +1 -1
  17. package/dist-renderer/assets/{chunk-QN33PNHL-C_4cCLCl.js → chunk-QN33PNHL-D9_yb-Pl.js} +1 -1
  18. package/dist-renderer/assets/{chunk-QZHKN3VN-ojL7PmOD.js → chunk-QZHKN3VN-CVMnt9Of.js} +1 -1
  19. package/dist-renderer/assets/{chunk-TZMSLE5B-D1g7Vl_v.js → chunk-TZMSLE5B-B11BOOB_.js} +1 -1
  20. package/dist-renderer/assets/classDiagram-2ON5EDUG-DLZQJPSd.js +1 -0
  21. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-DLZQJPSd.js +1 -0
  22. package/dist-renderer/assets/clone-CRwa9g7P.js +1 -0
  23. package/dist-renderer/assets/{cose-bilkent-S5V4N54A-TJnGh924.js → cose-bilkent-S5V4N54A-Dx1iOVS_.js} +1 -1
  24. package/dist-renderer/assets/{dagre-6UL2VRFP-cPgfHhoX.js → dagre-6UL2VRFP-BfFhjHyX.js} +1 -1
  25. package/dist-renderer/assets/{diagram-PSM6KHXK-BS5Y-RR6.js → diagram-PSM6KHXK-BjauYjwN.js} +1 -1
  26. package/dist-renderer/assets/{diagram-QEK2KX5R-D9AF7AGJ.js → diagram-QEK2KX5R-DTBnRCua.js} +1 -1
  27. package/dist-renderer/assets/{diagram-S2PKOQOG-DTFUadMS.js → diagram-S2PKOQOG-CBhKzb3E.js} +1 -1
  28. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-DB_StEwC.js → erDiagram-Q2GNP2WA-B0xgzQzS.js} +1 -1
  29. package/dist-renderer/assets/{flowDiagram-NV44I4VS-DGn40aPj.js → flowDiagram-NV44I4VS-klmMoWI3.js} +1 -1
  30. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-9NiFCSBT.js → ganttDiagram-JELNMOA3-BSv5ddzU.js} +1 -1
  31. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-BdveeU3c.js → gitGraphDiagram-V2S2FVAM-CEUBnydU.js} +1 -1
  32. package/dist-renderer/assets/{graph-aQYbgTDH.js → graph-CIysEkgE.js} +1 -1
  33. package/dist-renderer/assets/{index-CrCHolXN.js → index-7EkmxIrp.js} +1 -1
  34. package/dist-renderer/assets/{index-CWqPn0NY.js → index-BK6dwrxm.js} +1 -1
  35. package/dist-renderer/assets/{index-CaG9mf8s.css → index-C4x095x4.css} +1 -1
  36. package/dist-renderer/assets/{index-oyepEosi.js → index-CJLDGPfy.js} +1 -1
  37. package/dist-renderer/assets/{index-DiAK42nd.js → index-CSheMJTk.js} +1 -1
  38. package/dist-renderer/assets/{index-DmgKTZAa.js → index-CcdwUZk9.js} +529 -524
  39. package/dist-renderer/assets/{index-DyEKO6GV.js → index-DA5wdGF_.js} +1 -1
  40. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-Dmc_xn8U.js → infoDiagram-HS3SLOUP-BgF7b8R8.js} +1 -1
  41. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-D9LJr-B5.js → journeyDiagram-XKPGCS4Q-Brnq6sZ9.js} +1 -1
  42. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-CjOWoNys.js → kanban-definition-3W4ZIXB7-oEx_7thy.js} +1 -1
  43. package/dist-renderer/assets/{layout-D6GzYK4K.js → layout-Bb-Myf8p.js} +1 -1
  44. package/dist-renderer/assets/{linear-Dt3GyUQf.js → linear-BC5s25rz.js} +1 -1
  45. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-XwY2hZr8.js → mindmap-definition-VGOIOE7T-MB1jxroI.js} +1 -1
  46. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-BU4nfYd7.js → pieDiagram-ADFJNKIX-DSEfLnAV.js} +1 -1
  47. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-BYk6f63x.js → quadrantDiagram-AYHSOK5B-Bm0Xw7gV.js} +1 -1
  48. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-kbadr_bU.js → requirementDiagram-UZGBJVZJ-Cjn0opjv.js} +1 -1
  49. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-ZstP2Vth.js → sankeyDiagram-TZEHDZUN-P7KZIQkA.js} +1 -1
  50. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-obK_-ssz.js → sequenceDiagram-WL72ISMW-DHDX_5Fl.js} +1 -1
  51. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-BgZDg0VT.js → stateDiagram-FKZM4ZOC-DGyXzpw9.js} +1 -1
  52. package/dist-renderer/assets/{stateDiagram-v2-4FDKWEC3-CMa5sz7x.js → stateDiagram-v2-4FDKWEC3-sTtOoyBH.js} +1 -1
  53. package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BOmCNnab.js → timeline-definition-IT6M3QCI-BLoCrtzz.js} +1 -1
  54. package/dist-renderer/assets/treemap-GDKQZRPO-CI5sRz-0.js +162 -0
  55. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-BzAHNASi.js → xychartDiagram-PRI3JC2R-CkvLu9vG.js} +1 -1
  56. package/dist-renderer/index.html +2 -2
  57. package/package.json +23 -17
  58. package/src/main/server.ts +179 -23
  59. package/src/main/services/teams-mvp/TaskDispatchService.ts +440 -0
  60. package/src/main/services/teams-mvp/TeamProvisioningService.ts +36 -33
  61. package/src/main/services/teams-mvp/TeamWorkspaceService.ts +2 -0
  62. package/src/renderer/components/settings/SettingsTabs.tsx +8 -2
  63. package/src/renderer/components/settings/SettingsView.tsx +4 -0
  64. package/src/renderer/components/settings/sections/GeneralSection.tsx +168 -206
  65. package/src/renderer/components/settings/sections/TaskBusSection.tsx +176 -0
  66. package/src/renderer/components/sidebar/SidebarSessions.tsx +31 -4
  67. package/src/renderer/components/team/kanban/KanbanTaskCard.tsx +37 -0
  68. package/src/renderer/components/team/messages/MessageComposer.tsx +36 -228
  69. package/src/renderer/components/team/messages/MessagesPanel.tsx +0 -3
  70. package/src/renderer/store/slices/teamSlice.ts +30 -1
  71. package/src/shared/types/team.ts +73 -0
  72. package/dist-renderer/assets/channel-BSWYOYIc.js +0 -1
  73. package/dist-renderer/assets/classDiagram-2ON5EDUG-mw4yABob.js +0 -1
  74. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-mw4yABob.js +0 -1
  75. package/dist-renderer/assets/clone-KtZfFt-o.js +0 -1
  76. package/dist-renderer/assets/treemap-GDKQZRPO-BU0ha0Ww.js +0 -162
@@ -1,4 +1,4 @@
1
- import{_ as a,A as ei,B as si,Z as Lt,Y as ni,C as ai,D as ri,I as Et,ae as oi,J as hi,a3 as li,ab as xt,aa as It,ac as ci,av as ui,N as gi,b7 as xi,aD as Tt}from"./index-DmgKTZAa.js";import{i as di}from"./init-Gi6I4Gst.js";import{o as fi}from"./ordinal-Cboi1Yqb.js";import{l as Dt}from"./linear-Dt3GyUQf.js";import"./splashScene-C8lWNnm4.js";import"./defaultLocale-DX6XiGOO.js";function pi(t,i,e){t=+t,i=+i,e=(n=arguments.length)<2?(i=t,t=0,1):n<3?1:+e;for(var s=-1,n=Math.max(0,Math.ceil((i-t)/e))|0,x=new Array(n);++s<n;)x[s]=t+s*e;return x}function ht(){var t=fi().unknown(void 0),i=t.domain,e=t.range,s=0,n=1,x,g,m=!1,S=0,D=0,v=.5;delete t.unknown;function w(){var y=i().length,E=n<s,T=E?n:s,P=E?s:n;x=(P-T)/Math.max(1,y-S+D*2),m&&(x=Math.floor(x)),T+=(P-T-x*(y-S))*v,g=x*(1-S),m&&(T=Math.round(T),g=Math.round(g));var I=pi(y).map(function(p){return T+x*p});return e(E?I.reverse():I)}return t.domain=function(y){return arguments.length?(i(y),w()):i()},t.range=function(y){return arguments.length?([s,n]=y,s=+s,n=+n,w()):[s,n]},t.rangeRound=function(y){return[s,n]=y,s=+s,n=+n,m=!0,w()},t.bandwidth=function(){return g},t.step=function(){return x},t.round=function(y){return arguments.length?(m=!!y,w()):m},t.padding=function(y){return arguments.length?(S=Math.min(1,D=+y),w()):S},t.paddingInner=function(y){return arguments.length?(S=Math.min(1,y),w()):S},t.paddingOuter=function(y){return arguments.length?(D=+y,w()):D},t.align=function(y){return arguments.length?(v=Math.max(0,Math.min(1,y)),w()):v},t.copy=function(){return ht(i(),[s,n]).round(m).paddingInner(S).paddingOuter(D).align(v)},di.apply(w(),arguments)}var lt=function(){var t=a(function(O,o,c,u){for(c=c||{},u=O.length;u--;c[O[u]]=o);return c},"o"),i=[1,10,12,14,16,18,19,21,23],e=[2,6],s=[1,3],n=[1,5],x=[1,6],g=[1,7],m=[1,5,10,12,14,16,18,19,21,23,34,35,36],S=[1,25],D=[1,26],v=[1,28],w=[1,29],y=[1,30],E=[1,31],T=[1,32],P=[1,33],I=[1,34],p=[1,35],_=[1,36],l=[1,37],W=[1,43],z=[1,42],U=[1,47],X=[1,50],h=[1,10,12,14,16,18,19,21,23,34,35,36],L=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36],C=[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],k=[1,64],$={trace:a(function(){},"trace"),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:a(function(o,c,u,d,A,r,j){var f=r.length-1;switch(A){case 5:d.setOrientation(r[f]);break;case 9:d.setDiagramTitle(r[f].text.trim());break;case 12:d.setLineData({text:"",type:"text"},r[f]);break;case 13:d.setLineData(r[f-1],r[f]);break;case 14:d.setBarData({text:"",type:"text"},r[f]);break;case 15:d.setBarData(r[f-1],r[f]);break;case 16:this.$=r[f].trim(),d.setAccTitle(this.$);break;case 17:case 18:this.$=r[f].trim(),d.setAccDescription(this.$);break;case 19:this.$=r[f-1];break;case 20:this.$=[Number(r[f-2]),...r[f]];break;case 21:this.$=[Number(r[f])];break;case 22:d.setXAxisTitle(r[f]);break;case 23:d.setXAxisTitle(r[f-1]);break;case 24:d.setXAxisTitle({type:"text",text:""});break;case 25:d.setXAxisBand(r[f]);break;case 26:d.setXAxisRangeData(Number(r[f-2]),Number(r[f]));break;case 27:this.$=r[f-1];break;case 28:this.$=[r[f-2],...r[f]];break;case 29:this.$=[r[f]];break;case 30:d.setYAxisTitle(r[f]);break;case 31:d.setYAxisTitle(r[f-1]);break;case 32:d.setYAxisTitle({type:"text",text:""});break;case 33:d.setYAxisRangeData(Number(r[f-2]),Number(r[f]));break;case 37:this.$={text:r[f],type:"text"};break;case 38:this.$={text:r[f],type:"text"};break;case 39:this.$={text:r[f],type:"markdown"};break;case 40:this.$=r[f];break;case 41:this.$=r[f-1]+""+r[f];break}},"anonymous"),table:[t(i,e,{3:1,4:2,7:4,5:s,34:n,35:x,36:g}),{1:[3]},t(i,e,{4:2,7:4,3:8,5:s,34:n,35:x,36:g}),t(i,e,{4:2,7:4,6:9,3:10,5:s,8:[1,11],34:n,35:x,36:g}),{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]},t(m,[2,34]),t(m,[2,35]),t(m,[2,36]),{1:[2,1]},t(i,e,{4:2,7:4,3:21,5:s,34:n,35:x,36:g}),{1:[2,3]},t(m,[2,5]),t(i,[2,7],{4:22,34:n,35:x,36:g}),{11:23,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{11:39,13:38,24:W,27:z,29:40,30:41,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{11:45,15:44,27:U,33:46,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{11:49,17:48,24:X,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{11:52,17:51,24:X,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{20:[1,53]},{22:[1,54]},t(h,[2,18]),{1:[2,2]},t(h,[2,8]),t(h,[2,9]),t(L,[2,37],{40:55,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l}),t(L,[2,38]),t(L,[2,39]),t(C,[2,40]),t(C,[2,42]),t(C,[2,43]),t(C,[2,44]),t(C,[2,45]),t(C,[2,46]),t(C,[2,47]),t(C,[2,48]),t(C,[2,49]),t(C,[2,50]),t(C,[2,51]),t(h,[2,10]),t(h,[2,22],{30:41,29:56,24:W,27:z}),t(h,[2,24]),t(h,[2,25]),{31:[1,57]},{11:59,32:58,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},t(h,[2,11]),t(h,[2,30],{33:60,27:U}),t(h,[2,32]),{31:[1,61]},t(h,[2,12]),{17:62,24:X},{25:63,27:k},t(h,[2,14]),{17:65,24:X},t(h,[2,16]),t(h,[2,17]),t(C,[2,41]),t(h,[2,23]),{27:[1,66]},{26:[1,67]},{26:[2,29],28:[1,68]},t(h,[2,31]),{27:[1,69]},t(h,[2,13]),{26:[1,70]},{26:[2,21],28:[1,71]},t(h,[2,15]),t(h,[2,26]),t(h,[2,27]),{11:59,32:72,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},t(h,[2,33]),t(h,[2,19]),{25:73,27:k},{26:[2,28]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],72:[2,28],73:[2,20]},parseError:a(function(o,c){if(c.recoverable)this.trace(o);else{var u=new Error(o);throw u.hash=c,u}},"parseError"),parse:a(function(o){var c=this,u=[0],d=[],A=[null],r=[],j=this.table,f="",J=0,St=0,Zt=2,_t=1,Jt=r.slice.call(arguments,1),R=Object.create(this.lexer),Y={yy:{}};for(var nt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,nt)&&(Y.yy[nt]=this.yy[nt]);R.setInput(o,Y.yy),Y.yy.lexer=R,Y.yy.parser=this,typeof R.yylloc>"u"&&(R.yylloc={});var at=R.yylloc;r.push(at);var ti=R.options&&R.options.ranges;typeof Y.yy.parseError=="function"?this.parseError=Y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ii(V){u.length=u.length-2*V,A.length=A.length-V,r.length=r.length-V}a(ii,"popStack");function kt(){var V;return V=d.pop()||R.lex()||_t,typeof V!="number"&&(V instanceof Array&&(d=V,V=d.pop()),V=c.symbols_[V]||V),V}a(kt,"lex");for(var M,H,B,rt,q={},tt,F,Rt,it;;){if(H=u[u.length-1],this.defaultActions[H]?B=this.defaultActions[H]:((M===null||typeof M>"u")&&(M=kt()),B=j[H]&&j[H][M]),typeof B>"u"||!B.length||!B[0]){var ot="";it=[];for(tt in j[H])this.terminals_[tt]&&tt>Zt&&it.push("'"+this.terminals_[tt]+"'");R.showPosition?ot="Parse error on line "+(J+1)+`:
1
+ import{_ as a,A as ei,B as si,Z as Lt,Y as ni,C as ai,D as ri,I as Et,ae as oi,J as hi,a3 as li,ab as xt,aa as It,ac as ci,av as ui,N as gi,b7 as xi,aD as Tt}from"./index-CcdwUZk9.js";import{i as di}from"./init-Gi6I4Gst.js";import{o as fi}from"./ordinal-Cboi1Yqb.js";import{l as Dt}from"./linear-BC5s25rz.js";import"./splashScene-C8lWNnm4.js";import"./defaultLocale-DX6XiGOO.js";function pi(t,i,e){t=+t,i=+i,e=(n=arguments.length)<2?(i=t,t=0,1):n<3?1:+e;for(var s=-1,n=Math.max(0,Math.ceil((i-t)/e))|0,x=new Array(n);++s<n;)x[s]=t+s*e;return x}function ht(){var t=fi().unknown(void 0),i=t.domain,e=t.range,s=0,n=1,x,g,m=!1,S=0,D=0,v=.5;delete t.unknown;function w(){var y=i().length,E=n<s,T=E?n:s,P=E?s:n;x=(P-T)/Math.max(1,y-S+D*2),m&&(x=Math.floor(x)),T+=(P-T-x*(y-S))*v,g=x*(1-S),m&&(T=Math.round(T),g=Math.round(g));var I=pi(y).map(function(p){return T+x*p});return e(E?I.reverse():I)}return t.domain=function(y){return arguments.length?(i(y),w()):i()},t.range=function(y){return arguments.length?([s,n]=y,s=+s,n=+n,w()):[s,n]},t.rangeRound=function(y){return[s,n]=y,s=+s,n=+n,m=!0,w()},t.bandwidth=function(){return g},t.step=function(){return x},t.round=function(y){return arguments.length?(m=!!y,w()):m},t.padding=function(y){return arguments.length?(S=Math.min(1,D=+y),w()):S},t.paddingInner=function(y){return arguments.length?(S=Math.min(1,y),w()):S},t.paddingOuter=function(y){return arguments.length?(D=+y,w()):D},t.align=function(y){return arguments.length?(v=Math.max(0,Math.min(1,y)),w()):v},t.copy=function(){return ht(i(),[s,n]).round(m).paddingInner(S).paddingOuter(D).align(v)},di.apply(w(),arguments)}var lt=function(){var t=a(function(O,o,c,u){for(c=c||{},u=O.length;u--;c[O[u]]=o);return c},"o"),i=[1,10,12,14,16,18,19,21,23],e=[2,6],s=[1,3],n=[1,5],x=[1,6],g=[1,7],m=[1,5,10,12,14,16,18,19,21,23,34,35,36],S=[1,25],D=[1,26],v=[1,28],w=[1,29],y=[1,30],E=[1,31],T=[1,32],P=[1,33],I=[1,34],p=[1,35],_=[1,36],l=[1,37],W=[1,43],z=[1,42],U=[1,47],X=[1,50],h=[1,10,12,14,16,18,19,21,23,34,35,36],L=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36],C=[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],k=[1,64],$={trace:a(function(){},"trace"),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:a(function(o,c,u,d,A,r,j){var f=r.length-1;switch(A){case 5:d.setOrientation(r[f]);break;case 9:d.setDiagramTitle(r[f].text.trim());break;case 12:d.setLineData({text:"",type:"text"},r[f]);break;case 13:d.setLineData(r[f-1],r[f]);break;case 14:d.setBarData({text:"",type:"text"},r[f]);break;case 15:d.setBarData(r[f-1],r[f]);break;case 16:this.$=r[f].trim(),d.setAccTitle(this.$);break;case 17:case 18:this.$=r[f].trim(),d.setAccDescription(this.$);break;case 19:this.$=r[f-1];break;case 20:this.$=[Number(r[f-2]),...r[f]];break;case 21:this.$=[Number(r[f])];break;case 22:d.setXAxisTitle(r[f]);break;case 23:d.setXAxisTitle(r[f-1]);break;case 24:d.setXAxisTitle({type:"text",text:""});break;case 25:d.setXAxisBand(r[f]);break;case 26:d.setXAxisRangeData(Number(r[f-2]),Number(r[f]));break;case 27:this.$=r[f-1];break;case 28:this.$=[r[f-2],...r[f]];break;case 29:this.$=[r[f]];break;case 30:d.setYAxisTitle(r[f]);break;case 31:d.setYAxisTitle(r[f-1]);break;case 32:d.setYAxisTitle({type:"text",text:""});break;case 33:d.setYAxisRangeData(Number(r[f-2]),Number(r[f]));break;case 37:this.$={text:r[f],type:"text"};break;case 38:this.$={text:r[f],type:"text"};break;case 39:this.$={text:r[f],type:"markdown"};break;case 40:this.$=r[f];break;case 41:this.$=r[f-1]+""+r[f];break}},"anonymous"),table:[t(i,e,{3:1,4:2,7:4,5:s,34:n,35:x,36:g}),{1:[3]},t(i,e,{4:2,7:4,3:8,5:s,34:n,35:x,36:g}),t(i,e,{4:2,7:4,6:9,3:10,5:s,8:[1,11],34:n,35:x,36:g}),{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]},t(m,[2,34]),t(m,[2,35]),t(m,[2,36]),{1:[2,1]},t(i,e,{4:2,7:4,3:21,5:s,34:n,35:x,36:g}),{1:[2,3]},t(m,[2,5]),t(i,[2,7],{4:22,34:n,35:x,36:g}),{11:23,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{11:39,13:38,24:W,27:z,29:40,30:41,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{11:45,15:44,27:U,33:46,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{11:49,17:48,24:X,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{11:52,17:51,24:X,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},{20:[1,53]},{22:[1,54]},t(h,[2,18]),{1:[2,2]},t(h,[2,8]),t(h,[2,9]),t(L,[2,37],{40:55,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l}),t(L,[2,38]),t(L,[2,39]),t(C,[2,40]),t(C,[2,42]),t(C,[2,43]),t(C,[2,44]),t(C,[2,45]),t(C,[2,46]),t(C,[2,47]),t(C,[2,48]),t(C,[2,49]),t(C,[2,50]),t(C,[2,51]),t(h,[2,10]),t(h,[2,22],{30:41,29:56,24:W,27:z}),t(h,[2,24]),t(h,[2,25]),{31:[1,57]},{11:59,32:58,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},t(h,[2,11]),t(h,[2,30],{33:60,27:U}),t(h,[2,32]),{31:[1,61]},t(h,[2,12]),{17:62,24:X},{25:63,27:k},t(h,[2,14]),{17:65,24:X},t(h,[2,16]),t(h,[2,17]),t(C,[2,41]),t(h,[2,23]),{27:[1,66]},{26:[1,67]},{26:[2,29],28:[1,68]},t(h,[2,31]),{27:[1,69]},t(h,[2,13]),{26:[1,70]},{26:[2,21],28:[1,71]},t(h,[2,15]),t(h,[2,26]),t(h,[2,27]),{11:59,32:72,37:24,38:S,39:D,40:27,41:v,42:w,43:y,44:E,45:T,46:P,47:I,48:p,49:_,50:l},t(h,[2,33]),t(h,[2,19]),{25:73,27:k},{26:[2,28]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],72:[2,28],73:[2,20]},parseError:a(function(o,c){if(c.recoverable)this.trace(o);else{var u=new Error(o);throw u.hash=c,u}},"parseError"),parse:a(function(o){var c=this,u=[0],d=[],A=[null],r=[],j=this.table,f="",J=0,St=0,Zt=2,_t=1,Jt=r.slice.call(arguments,1),R=Object.create(this.lexer),Y={yy:{}};for(var nt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,nt)&&(Y.yy[nt]=this.yy[nt]);R.setInput(o,Y.yy),Y.yy.lexer=R,Y.yy.parser=this,typeof R.yylloc>"u"&&(R.yylloc={});var at=R.yylloc;r.push(at);var ti=R.options&&R.options.ranges;typeof Y.yy.parseError=="function"?this.parseError=Y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ii(V){u.length=u.length-2*V,A.length=A.length-V,r.length=r.length-V}a(ii,"popStack");function kt(){var V;return V=d.pop()||R.lex()||_t,typeof V!="number"&&(V instanceof Array&&(d=V,V=d.pop()),V=c.symbols_[V]||V),V}a(kt,"lex");for(var M,H,B,rt,q={},tt,F,Rt,it;;){if(H=u[u.length-1],this.defaultActions[H]?B=this.defaultActions[H]:((M===null||typeof M>"u")&&(M=kt()),B=j[H]&&j[H][M]),typeof B>"u"||!B.length||!B[0]){var ot="";it=[];for(tt in j[H])this.terminals_[tt]&&tt>Zt&&it.push("'"+this.terminals_[tt]+"'");R.showPosition?ot="Parse error on line "+(J+1)+`:
2
2
  `+R.showPosition()+`
3
3
  Expecting `+it.join(", ")+", got '"+(this.terminals_[M]||M)+"'":ot="Parse error on line "+(J+1)+": Unexpected "+(M==_t?"end of input":"'"+(this.terminals_[M]||M)+"'"),this.parseError(ot,{text:R.match,token:this.terminals_[M]||M,line:R.yylineno,loc:at,expected:it})}if(B[0]instanceof Array&&B.length>1)throw new Error("Parse Error: multiple actions possible at state: "+H+", token: "+M);switch(B[0]){case 1:u.push(M),A.push(R.yytext),r.push(R.yylloc),u.push(B[1]),M=null,St=R.yyleng,f=R.yytext,J=R.yylineno,at=R.yylloc;break;case 2:if(F=this.productions_[B[1]][1],q.$=A[A.length-F],q._$={first_line:r[r.length-(F||1)].first_line,last_line:r[r.length-1].last_line,first_column:r[r.length-(F||1)].first_column,last_column:r[r.length-1].last_column},ti&&(q._$.range=[r[r.length-(F||1)].range[0],r[r.length-1].range[1]]),rt=this.performAction.apply(q,[f,St,J,Y.yy,B[1],A,r].concat(Jt)),typeof rt<"u")return rt;F&&(u=u.slice(0,-1*F*2),A=A.slice(0,-1*F),r=r.slice(0,-1*F)),u.push(this.productions_[B[1]][0]),A.push(q.$),r.push(q._$),Rt=j[u[u.length-2]][u[u.length-1]],u.push(Rt);break;case 3:return!0}}return!0},"parse")},Ct=function(){var O={EOF:1,parseError:a(function(c,u){if(this.yy.parser)this.yy.parser.parseError(c,u);else throw new Error(c)},"parseError"),setInput:a(function(o,c){return this.yy=c||this.yy||{},this._input=o,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},"setInput"),input:a(function(){var o=this._input[0];this.yytext+=o,this.yyleng++,this.offset++,this.match+=o,this.matched+=o;var c=o.match(/(?:\r\n?|\n).*/g);return c?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),o},"input"),unput:a(function(o){var c=o.length,u=o.split(/(?:\r\n?|\n)/g);this._input=o+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-c),this.offset-=c;var d=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 A=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===d.length?this.yylloc.first_column:0)+d[d.length-u.length].length-u[0].length:this.yylloc.first_column-c},this.options.ranges&&(this.yylloc.range=[A[0],A[0]+this.yyleng-c]),this.yyleng=this.yytext.length,this},"unput"),more:a(function(){return this._more=!0,this},"more"),reject:a(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},"reject"),less:a(function(o){this.unput(this.match.slice(o))},"less"),pastInput:a(function(){var o=this.matched.substr(0,this.matched.length-this.match.length);return(o.length>20?"...":"")+o.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:a(function(){var o=this.match;return o.length<20&&(o+=this._input.substr(0,20-o.length)),(o.substr(0,20)+(o.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:a(function(){var o=this.pastInput(),c=new Array(o.length+1).join("-");return o+this.upcomingInput()+`
@@ -353,9 +353,9 @@
353
353
  } catch (e) {}
354
354
  })();
355
355
  </script>
356
- <script type="module" crossorigin src="/assets/index-DmgKTZAa.js"></script>
356
+ <script type="module" crossorigin src="/assets/index-CcdwUZk9.js"></script>
357
357
  <link rel="modulepreload" crossorigin href="/assets/splashScene-C8lWNnm4.js">
358
- <link rel="stylesheet" crossorigin href="/assets/index-CaG9mf8s.css">
358
+ <link rel="stylesheet" crossorigin href="/assets/index-C4x095x4.css">
359
359
  </head>
360
360
  <body>
361
361
  <div id="splash">
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yancyyu/openhermit",
3
3
  "type": "module",
4
- "version": "1.6.4",
4
+ "version": "1.6.6",
5
5
  "description": "openHermit: team-oriented agent management workbench atop cc-connect.",
6
6
  "license": "AGPL-3.0",
7
7
  "author": {
@@ -29,6 +29,23 @@
29
29
  "package.json",
30
30
  "README.md"
31
31
  ],
32
+ "scripts": {
33
+ "dev": "node ./scripts/dev-mvp.mjs",
34
+ "dev:server": "tsx watch src/main/server.ts",
35
+ "dev:web": "vite --config vite.web.config.ts",
36
+ "build:web": "vite build --config vite.web.config.ts --outDir ../../dist-renderer --emptyOutDir",
37
+ "prepack": "pnpm build:web",
38
+ "start": "node bin/hermit.mjs",
39
+ "typecheck": "tsc --noEmit",
40
+ "lint": "eslint src/ --cache --cache-location .eslintcache --cache-strategy content",
41
+ "lint:fix": "eslint src/ --fix --cache --cache-location .eslintcache --cache-strategy content",
42
+ "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css}\"",
43
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css}\"",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "test:coverage": "vitest run --coverage",
47
+ "prepare": "husky"
48
+ },
32
49
  "lint-staged": {
33
50
  "src/**/*.{ts,tsx,js,jsx}": [
34
51
  "prettier --write"
@@ -126,6 +143,9 @@
126
143
  "yet-another-react-lightbox": "^3.29.1",
127
144
  "zustand": "^4.5.0"
128
145
  },
146
+ "optionalDependencies": {
147
+ "ioredis": "^5.6.1"
148
+ },
129
149
  "devDependencies": {
130
150
  "@eslint-community/eslint-plugin-eslint-comments": "^4.6.0",
131
151
  "@eslint/js": "^9.39.2",
@@ -164,19 +184,5 @@
164
184
  "vite": "^5.4.2",
165
185
  "vitest": "^3.1.4"
166
186
  },
167
- "scripts": {
168
- "dev": "node ./scripts/dev-mvp.mjs",
169
- "dev:server": "tsx watch src/main/server.ts",
170
- "dev:web": "vite --config vite.web.config.ts",
171
- "build:web": "vite build --config vite.web.config.ts --outDir ../../dist-renderer --emptyOutDir",
172
- "start": "node bin/hermit.mjs",
173
- "typecheck": "tsc --noEmit",
174
- "lint": "eslint src/ --cache --cache-location .eslintcache --cache-strategy content",
175
- "lint:fix": "eslint src/ --fix --cache --cache-location .eslintcache --cache-strategy content",
176
- "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css}\"",
177
- "format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css}\"",
178
- "test": "vitest run",
179
- "test:watch": "vitest",
180
- "test:coverage": "vitest run --coverage"
181
- }
182
- }
187
+ "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319"
188
+ }
@@ -36,6 +36,7 @@ import {
36
36
  } from 'node:fs';
37
37
  import os from 'node:os';
38
38
  import path from 'node:path';
39
+ import fs from 'node:fs/promises';
39
40
  import { fileURLToPath } from 'node:url';
40
41
 
41
42
  import cors from '@fastify/cors';
@@ -45,6 +46,8 @@ import Fastify from 'fastify';
45
46
  import { CcConnectBridge } from './services/ccConnect/CcConnectBridge';
46
47
  import { CcConnectClient } from './services/ccConnect/CcConnectClient';
47
48
  import { TeamProvisioningService } from './services/teams-mvp';
49
+ import { TaskDispatchService } from './services/teams-mvp/TaskDispatchService';
50
+ import type { TaskBusConfig } from '@shared/types/team';
48
51
  import { UpdateService } from './services/UpdateService';
49
52
 
50
53
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -180,6 +183,7 @@ const bridge = new CcConnectBridge({
180
183
  bridgeToken: runtimeConfig.ccBridgeToken || runtimeConfig.ccToken,
181
184
  });
182
185
  const svc = new TeamProvisioningService(cc, bridge);
186
+ const taskDispatch = new TaskDispatchService(svc['workspace']);
183
187
 
184
188
  function normalizeStringArray(value: unknown): string[] {
185
189
  if (!Array.isArray(value)) {
@@ -1618,17 +1622,26 @@ const MCP_TOOLS = [
1618
1622
  },
1619
1623
  },
1620
1624
  {
1621
- name: 'create_task',
1622
- description: '创建任务,可分配给其他团队',
1625
+ name: 'list_teams',
1626
+ description: '列出所有可用的团队(本地和远程)。用于发现可以派发任务的目标团队。',
1627
+ inputSchema: {
1628
+ type: 'object',
1629
+ properties: {},
1630
+ },
1631
+ },
1632
+ {
1633
+ name: 'dispatch_task',
1634
+ description: `将任务派发给另一个团队。当前团队通过 team_slug 参数指定。${taskDispatch.dispatchRulesText}`,
1623
1635
  inputSchema: {
1624
1636
  type: 'object',
1625
1637
  properties: {
1626
- team_slug: { type: 'string', description: '创建任务的团队 slug' },
1627
- title: { type: 'string', description: '任务标题' },
1638
+ team_slug: { type: 'string', description: '当前团队 slug(即发出派发的团队)' },
1639
+ target_team: { type: 'string', description: '目标团队 slug(可通过 list_teams 查询)' },
1640
+ subject: { type: 'string', description: '任务标题' },
1628
1641
  description: { type: 'string', description: '任务描述(可选)' },
1629
- assignee: { type: 'string', description: '分配给哪个团队的 slug(可选)' },
1642
+ prompt: { type: 'string', description: '给目标团队的执行指令(可选)' },
1630
1643
  },
1631
- required: ['team_slug', 'title'],
1644
+ required: ['team_slug', 'target_team', 'subject'],
1632
1645
  },
1633
1646
  },
1634
1647
  ];
@@ -1654,21 +1667,27 @@ async function executeMcpTool(
1654
1667
  const patch: Record<string, unknown> = { status: 'done' };
1655
1668
  if (args.result) patch.result = args.result;
1656
1669
  const task = await svc.patchTask(args.team_slug, args.task_id, patch);
1670
+ // Notify origin team if this was a dispatched task
1671
+ await taskDispatch.onTaskCompleted(args.team_slug, args.task_id).catch(() => {});
1657
1672
  return text(task);
1658
1673
  }
1659
1674
 
1660
- if (toolName === 'create_task') {
1661
- const task = await svc.createTask(args.team_slug, {
1662
- title: args.title,
1663
- description: args.description,
1664
- assignee: args.assignee ?? null,
1665
- });
1666
- if (task.assignee) {
1667
- svc.dispatchTask(args.team_slug, task).catch(() => {
1668
- /* best-effort */
1669
- });
1670
- }
1671
- return text(task);
1675
+ if (toolName === 'list_teams') {
1676
+ const teams = await taskDispatch.listTeams();
1677
+ return text(teams);
1678
+ }
1679
+
1680
+ if (toolName === 'dispatch_task') {
1681
+ const result = await taskDispatch.dispatchTask(
1682
+ args.team_slug,
1683
+ {
1684
+ subject: args.subject,
1685
+ description: args.description,
1686
+ prompt: args.prompt,
1687
+ },
1688
+ args.target_team
1689
+ );
1690
+ return text(result);
1672
1691
  }
1673
1692
 
1674
1693
  throw new Error(`Unknown tool: ${toolName}`);
@@ -3813,12 +3832,149 @@ app.post('/api/teams/tool-approval/read-file', async () => ({ content: '' }));
3813
3832
  // validate-cli-args
3814
3833
  app.post('/api/teams/validate-cli-args', async () => ({ valid: true, args: [], errors: [] }));
3815
3834
 
3816
- // cross-team stubs
3817
- app.post('/api/cross-team/send', async () => ({ ok: true }));
3818
- app.get('/api/cross-team/targets', async () => []);
3819
- app.get<{ Params: { name: string } }>('/api/cross-team/outbox/:name', async () => []);
3835
+ // cross-team task dispatch endpoints
3836
+ app.post<{
3837
+ Body: {
3838
+ fromTeam: string;
3839
+ toTeam: string;
3840
+ subject: string;
3841
+ description?: string;
3842
+ prompt?: string;
3843
+ };
3844
+ }>('/api/cross-team/send', async (request) => {
3845
+ const { fromTeam, toTeam, subject, description, prompt } = request.body ?? {};
3846
+ if (!toTeam || !subject) return { ok: false, error: 'toTeam and subject are required' };
3847
+ const result = await taskDispatch.dispatchTask(
3848
+ fromTeam ?? 'unknown',
3849
+ { subject, description, prompt },
3850
+ toTeam
3851
+ );
3852
+ return { ok: true, dispatchId: result.dispatchId, status: result.status };
3853
+ });
3854
+
3855
+ app.get<{ Querystring: { excludeTeam?: string } }>('/api/cross-team/targets', async (request) => {
3856
+ const excludeTeam = request.query.excludeTeam;
3857
+ // Fetch teams from workspace + alive status from cc-connect
3858
+ const allTeams = await svc.listTeams();
3859
+ let aliveSet = new Set<string>();
3860
+ try {
3861
+ const projects = await cc.listProjects();
3862
+ const states = await Promise.all(
3863
+ projects.map(async (p) => {
3864
+ let isAlive = false;
3865
+ try {
3866
+ const detail = await cc.getProject(p.name);
3867
+ isAlive =
3868
+ Array.isArray(detail.platforms) && detail.platforms.some((pl: any) => pl.connected);
3869
+ } catch {
3870
+ /* degraded */
3871
+ }
3872
+ return { name: p.name, isAlive };
3873
+ })
3874
+ );
3875
+ aliveSet = new Set(states.filter((s) => s.isAlive).map((s) => s.name));
3876
+ } catch {
3877
+ /* cc-connect unavailable */
3878
+ }
3879
+
3880
+ return allTeams
3881
+ .filter((t) => t.slug !== excludeTeam && !t.pendingDelete)
3882
+ .map((t) => ({
3883
+ teamName: t.slug,
3884
+ displayName: t.displayName || t.slug,
3885
+ description: t.description,
3886
+ color: t.color,
3887
+ isOnline: aliveSet.has(t.bindProject),
3888
+ }));
3889
+ });
3890
+
3891
+ app.get<{ Params: { name: string } }>('/api/cross-team/outbox/:name', async (request) => {
3892
+ const teamSlug = request.params.name;
3893
+ const tasks = await svc.readTasks(teamSlug);
3894
+ const pending = tasks.filter(
3895
+ (t: any) => t.dispatchMeta?.status === 'dispatched' && t.dispatchMeta?.originTeam === teamSlug
3896
+ );
3897
+ return { pending };
3898
+ });
3899
+
3900
+ // Task bus settings
3901
+ app.get('/api/settings/task-bus', async () => {
3902
+ const configPath = path.join(os.homedir(), '.hermit', 'settings.json');
3903
+ try {
3904
+ const raw = await fs.readFile(configPath, 'utf-8');
3905
+ const settings = JSON.parse(raw);
3906
+ return settings.taskBus ?? { enabled: false, redis: { host: '127.0.0.1', port: 6379 } };
3907
+ } catch {
3908
+ return { enabled: false, redis: { host: '127.0.0.1', port: 6379 } };
3909
+ }
3910
+ });
3911
+
3912
+ app.put<{ Body: TaskBusConfig }>('/api/settings/task-bus', async (request) => {
3913
+ const config = request.body;
3914
+ const configPath = path.join(os.homedir(), '.hermit', 'settings.json');
3915
+ let settings: Record<string, unknown> = {};
3916
+ try {
3917
+ const raw = await fs.readFile(configPath, 'utf-8');
3918
+ settings = JSON.parse(raw);
3919
+ } catch {
3920
+ // File doesn't exist yet
3921
+ }
3922
+ settings.taskBus = config;
3923
+ await fs.mkdir(path.dirname(configPath), { recursive: true });
3924
+ await fs.writeFile(configPath, JSON.stringify(settings, null, 2));
3925
+
3926
+ // Auto-inject CLAUDE.md instructions when enabling
3927
+ if (config?.enabled) {
3928
+ try {
3929
+ const projects = await cc.listProjects();
3930
+ for (const p of projects) {
3931
+ let workDir = '';
3932
+ let slug = p.name;
3933
+ try {
3934
+ const meta = await svc.readTeamManifest(p.name);
3935
+ if (typeof meta.workDir === 'string') workDir = meta.workDir.trim();
3936
+ if (meta.slug) slug = meta.slug;
3937
+ } catch {
3938
+ /* no local manifest */
3939
+ }
3940
+ if (!workDir) {
3941
+ try {
3942
+ const detail = await cc.getProject(p.name);
3943
+ if (typeof detail.work_dir === 'string') workDir = detail.work_dir.trim();
3944
+ } catch {
3945
+ // ignore
3946
+ }
3947
+ }
3948
+ if (workDir) {
3949
+ await svc.injectTeamInstructions(workDir, slug);
3950
+ }
3951
+ }
3952
+ } catch (err) {
3953
+ request.log.warn({ err }, 'CLAUDE.md injection failed');
3954
+ }
3955
+
3956
+ // Reconnect TaskDispatchService with Redis (optional)
3957
+ taskDispatch.dispose();
3958
+ try {
3959
+ await taskDispatch.start(config);
3960
+ return {
3961
+ ok: true,
3962
+ connected: true,
3963
+ message: `Redis 连接成功,分布式派发已启用`,
3964
+ };
3965
+ } catch {
3966
+ return {
3967
+ ok: true,
3968
+ connected: false,
3969
+ message: `Redis 连接失败,仅本地派发`,
3970
+ };
3971
+ }
3972
+ }
3973
+
3974
+ taskDispatch.dispose();
3975
+ return { ok: true, connected: false, message: 'Task bus disabled' };
3976
+ });
3820
3977
 
3821
- // review stubs
3822
3978
  app.get<{ Params: { name: string; memberName: string } }>(
3823
3979
  '/api/teams/:name/review/agent-changes/:memberName',
3824
3980
  async (request) => ({