@hachej/boring-ui-cli 0.1.17 → 0.1.18

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 (84) hide show
  1. package/README.md +8 -0
  2. package/dist/server/cli.js +189 -8
  3. package/dist/server/scaffoldPlugin.js +72 -0
  4. package/dist/server/verifyPlugin.js +235 -0
  5. package/package.json +6 -5
  6. package/public/assets/{CodeEditor-DQqOn4xz-B6a7H7rM.js → CodeEditor-DQqOn4xz-BpvvkFT7.js} +1 -1
  7. package/public/assets/{FileTree-Dvaud3jU-DNCQ4FDl.js → FileTree-DHVB9rpk-FMcsf2w-.js} +10 -10
  8. package/public/assets/{MarkdownEditor-sLkqTXDj-lFnLm1Im.js → MarkdownEditor-L1KDH0bM-D-LbfGkW.js} +1 -1
  9. package/public/assets/{_baseUniq-DdPJOgPg.js → _baseUniq-CMA9Ia5A.js} +1 -1
  10. package/public/assets/{arc-LgyX0a8W.js → arc-tnXyejqK.js} +1 -1
  11. package/public/assets/{architectureDiagram-Q4EWVU46-GZeUAJwF.js → architectureDiagram-Q4EWVU46-BSOUkwG2.js} +1 -1
  12. package/public/assets/{blockDiagram-DXYQGD6D-OSYK-_zS.js → blockDiagram-DXYQGD6D-beerpyJi.js} +1 -1
  13. package/public/assets/{c4Diagram-AHTNJAMY-BCBP7uHE.js → c4Diagram-AHTNJAMY-uB419B41.js} +1 -1
  14. package/public/assets/channel-C2_9gQqR.js +1 -0
  15. package/public/assets/{chunk-4BX2VUAB-CRy_H01e.js → chunk-4BX2VUAB-CpStyzoR.js} +1 -1
  16. package/public/assets/{chunk-4TB4RGXK-Dpk7ncuw.js → chunk-4TB4RGXK-BL531Lcw.js} +1 -1
  17. package/public/assets/{chunk-55IACEB6-CZYv6OBA.js → chunk-55IACEB6-CRDe66a9.js} +1 -1
  18. package/public/assets/{chunk-EDXVE4YY-NqKsVs05.js → chunk-EDXVE4YY-NaBO_txy.js} +1 -1
  19. package/public/assets/{chunk-FMBD7UC4-BgIQ6c_c.js → chunk-FMBD7UC4-Dn2Fmb5W.js} +1 -1
  20. package/public/assets/{chunk-OYMX7WX6-SyRoLN54.js → chunk-OYMX7WX6-iffOaivX.js} +1 -1
  21. package/public/assets/{chunk-QZHKN3VN-DzGRRm9f.js → chunk-QZHKN3VN-BKRi-Sxw.js} +1 -1
  22. package/public/assets/{chunk-YZCP3GAM-CfIqY3Yu.js → chunk-YZCP3GAM-CFQPe6Lu.js} +1 -1
  23. package/public/assets/classDiagram-6PBFFD2Q-BX66CTk2.js +1 -0
  24. package/public/assets/classDiagram-v2-HSJHXN6E-BX66CTk2.js +1 -0
  25. package/public/assets/clone-BUVN29h2.js +1 -0
  26. package/public/assets/{cose-bilkent-S5V4N54A-DTcdWPD5.js → cose-bilkent-S5V4N54A-BFfdAG94.js} +1 -1
  27. package/public/assets/{dagre-KV5264BT-k2lWP3qf.js → dagre-KV5264BT-BvfHllE1.js} +1 -1
  28. package/public/assets/{diagram-5BDNPKRD-DTUoxviQ.js → diagram-5BDNPKRD-DML8a0lh.js} +1 -1
  29. package/public/assets/{diagram-G4DWMVQ6-CLo507Hm.js → diagram-G4DWMVQ6-DL30StUK.js} +1 -1
  30. package/public/assets/{diagram-MMDJMWI5-Ben6XGgC.js → diagram-MMDJMWI5-D3-Kryyd.js} +1 -1
  31. package/public/assets/{diagram-TYMM5635-BsJA5XC_.js → diagram-TYMM5635-HDTViX5R.js} +1 -1
  32. package/public/assets/{erDiagram-SMLLAGMA-BLbGPA6K.js → erDiagram-SMLLAGMA-DV46TbuX.js} +1 -1
  33. package/public/assets/{flowDiagram-DWJPFMVM-D4Sv719o.js → flowDiagram-DWJPFMVM-BXqQu2_i.js} +1 -1
  34. package/public/assets/{ganttDiagram-T4ZO3ILL-D6kGugJe.js → ganttDiagram-T4ZO3ILL-CnPz0E5a.js} +1 -1
  35. package/public/assets/{gitGraphDiagram-UUTBAWPF-CVyzhaSE.js → gitGraphDiagram-UUTBAWPF-C25lUVfz.js} +1 -1
  36. package/public/assets/{graph-kiXKPMn9.js → graph-CSby6HJp.js} +1 -1
  37. package/public/assets/{highlighted-body-OFNGDK62-DcMPgvKJ.js → highlighted-body-OFNGDK62-D5Bucj_m.js} +1 -1
  38. package/public/assets/{index-BHlQtZ6_.js → index-CrQ5eYxl.js} +301 -295
  39. package/public/assets/{index-BTJucb1M.js → index-DLyovEn7.js} +1 -1
  40. package/public/assets/index-RUcotPWN.css +1 -0
  41. package/public/assets/{infoDiagram-42DDH7IO-BH27HU_c.js → infoDiagram-42DDH7IO-D1tkIwny.js} +1 -1
  42. package/public/assets/{ishikawaDiagram-UXIWVN3A-CdGOupZp.js → ishikawaDiagram-UXIWVN3A-D6zbyxWx.js} +1 -1
  43. package/public/assets/{journeyDiagram-VCZTEJTY-iJT59osB.js → journeyDiagram-VCZTEJTY-ExQUgQxi.js} +1 -1
  44. package/public/assets/{kanban-definition-6JOO6SKY-CZ5wWUdF.js → kanban-definition-6JOO6SKY-E3gNRZLm.js} +1 -1
  45. package/public/assets/{layout-BTIHgp6K.js → layout-BF96CGik.js} +1 -1
  46. package/public/assets/{linear-CCrC51HM.js → linear-6x4QueCv.js} +1 -1
  47. package/public/assets/{min-CrbJ9M-f.js → min-Cyn_UaFw.js} +1 -1
  48. package/public/assets/{mindmap-definition-QFDTVHPH-diXcpv4F.js → mindmap-definition-QFDTVHPH-CcpKJ1lB.js} +1 -1
  49. package/public/assets/{pieDiagram-DEJITSTG-CPIefI_d.js → pieDiagram-DEJITSTG-PVIVMgVu.js} +1 -1
  50. package/public/assets/{quadrantDiagram-34T5L4WZ-oif1uGqW.js → quadrantDiagram-34T5L4WZ-BTyRfzd6.js} +1 -1
  51. package/public/assets/{requirementDiagram-MS252O5E-7TD_ygCy.js → requirementDiagram-MS252O5E-CU9X0jFW.js} +1 -1
  52. package/public/assets/{sankeyDiagram-XADWPNL6-CMu1tHyh.js → sankeyDiagram-XADWPNL6-DyZdSLSv.js} +1 -1
  53. package/public/assets/{sequenceDiagram-FGHM5R23-B9mC8imJ.js → sequenceDiagram-FGHM5R23-CuJRqb6t.js} +1 -1
  54. package/public/assets/{stateDiagram-FHFEXIEX-D6PL1POV.js → stateDiagram-FHFEXIEX-5mIpjfjp.js} +1 -1
  55. package/public/assets/stateDiagram-v2-QKLJ7IA2-yZsODTx6.js +1 -0
  56. package/public/assets/{timeline-definition-GMOUNBTQ-DuQkd9Ua.js → timeline-definition-GMOUNBTQ-DCSOAQyL.js} +1 -1
  57. package/public/assets/{vennDiagram-DHZGUBPP-dF0MNyOc.js → vennDiagram-DHZGUBPP-BXxgH4Ub.js} +1 -1
  58. package/public/assets/{wardley-RL74JXVD-BS64Vt29.js → wardley-RL74JXVD-BWSOnFou.js} +1 -1
  59. package/public/assets/{wardleyDiagram-NUSXRM2D-BRkEc3lh.js → wardleyDiagram-NUSXRM2D-BrsRzGry.js} +1 -1
  60. package/public/assets/{xychartDiagram-5P7HB3ND-CQm5c61-.js → xychartDiagram-5P7HB3ND-CLF12YPc.js} +1 -1
  61. package/public/index.html +2 -2
  62. package/templates/front-canonical.tsx +62 -0
  63. package/templates/package-canonical.json +19 -0
  64. package/templates/plugin/README.md +64 -0
  65. package/templates/plugin/package.json +67 -0
  66. package/templates/plugin/src/front/__tests__/samplePlugin.test.ts +53 -0
  67. package/templates/plugin/src/front/index.ts +45 -0
  68. package/templates/plugin/src/front/panels.tsx +8 -0
  69. package/templates/plugin/src/front/surfaceResolver.ts +19 -0
  70. package/templates/plugin/src/server/index.ts +29 -0
  71. package/templates/plugin/src/shared/constants.ts +2 -0
  72. package/templates/plugin/src/shared/index.ts +2 -0
  73. package/templates/plugin/src/shared/types.ts +3 -0
  74. package/templates/plugin/src/test-setup.ts +43 -0
  75. package/templates/plugin/tsconfig.json +23 -0
  76. package/templates/plugin/tsup.config.ts +21 -0
  77. package/templates/plugin/vitest.config.ts +20 -0
  78. package/templates/server-canonical.ts +42 -0
  79. package/public/assets/channel-BJh30Beu.js +0 -1
  80. package/public/assets/classDiagram-6PBFFD2Q-P4A3FztV.js +0 -1
  81. package/public/assets/classDiagram-v2-HSJHXN6E-P4A3FztV.js +0 -1
  82. package/public/assets/clone-DWkLJZp8.js +0 -1
  83. package/public/assets/index-CyEGNm7Z.css +0 -1
  84. package/public/assets/stateDiagram-v2-QKLJ7IA2-DyoW21-W.js +0 -1
@@ -1,4 +1,4 @@
1
- import{s as gi,g as xi,x as Xt,v as di,a as fi,b as pi,_ as a,l as Yt,P as mi,e as yi,D as bi,I as _t,i as Ai,M as Nt,N as wi,a6 as Ci,aH as Si,ae as Wt}from"./index-BHlQtZ6_.js";import{i as _i}from"./init-Gi6I4Gst.js";import{o as ki}from"./ordinal-Cboi1Yqb.js";import{l as zt}from"./linear-CCrC51HM.js";import"./defaultLocale-DX6XiGOO.js";function Ri(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 bt(){var e=ki().unknown(void 0),t=e.domain,i=e.range,s=0,n=1,o,u,p=!1,f=0,T=0,P=.5;delete e.unknown;function _(){var y=t().length,E=n<s,v=E?n:s,L=E?s:n;o=(L-v)/Math.max(1,y-f+T*2),p&&(o=Math.floor(o)),v+=(L-v-o*(y-f))*P,u=o*(1-f),p&&(v=Math.round(v),u=Math.round(u));var M=Ri(y).map(function(m){return v+o*m});return i(E?M.reverse():M)}return e.domain=function(y){return arguments.length?(t(y),_()):t()},e.range=function(y){return arguments.length?([s,n]=y,s=+s,n=+n,_()):[s,n]},e.rangeRound=function(y){return[s,n]=y,s=+s,n=+n,p=!0,_()},e.bandwidth=function(){return u},e.step=function(){return o},e.round=function(y){return arguments.length?(p=!!y,_()):p},e.padding=function(y){return arguments.length?(f=Math.min(1,T=+y),_()):f},e.paddingInner=function(y){return arguments.length?(f=Math.min(1,y),_()):f},e.paddingOuter=function(y){return arguments.length?(T=+y,_()):T},e.align=function(y){return arguments.length?(P=Math.max(0,Math.min(1,y)),_()):P},e.copy=function(){return bt(t(),[s,n]).round(p).paddingInner(f).paddingOuter(T).align(P)},_i.apply(_(),arguments)}var At=(function(){var e=a(function(F,h,c,g){for(c=c||{},g=F.length;g--;c[F[g]]=h);return c},"o"),t=[1,10,12,14,16,18,19,21,23],i=[2,6],s=[1,3],n=[1,5],o=[1,6],u=[1,7],p=[1,5,10,12,14,16,18,19,21,23,34,35,36],f=[1,25],T=[1,26],P=[1,28],_=[1,29],y=[1,30],E=[1,31],v=[1,32],L=[1,33],M=[1,34],m=[1,35],R=[1,36],l=[1,37],W=[1,43],O=[1,42],X=[1,47],Y=[1,50],S=[1,10,12,14,16,18,19,21,23,34,35,36],U=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36],b=[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],w=[1,64],V={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(h,c,g,x,C,r,rt){var d=r.length-1;switch(C){case 5:x.setOrientation(r[d]);break;case 9:x.setDiagramTitle(r[d].text.trim());break;case 12:x.setLineData({text:"",type:"text"},r[d]);break;case 13:x.setLineData(r[d-1],r[d]);break;case 14:x.setBarData({text:"",type:"text"},r[d]);break;case 15:x.setBarData(r[d-1],r[d]);break;case 16:this.$=r[d].trim(),x.setAccTitle(this.$);break;case 17:case 18:this.$=r[d].trim(),x.setAccDescription(this.$);break;case 19:this.$=r[d-1];break;case 20:this.$=[Number(r[d-2]),...r[d]];break;case 21:this.$=[Number(r[d])];break;case 22:x.setXAxisTitle(r[d]);break;case 23:x.setXAxisTitle(r[d-1]);break;case 24:x.setXAxisTitle({type:"text",text:""});break;case 25:x.setXAxisBand(r[d]);break;case 26:x.setXAxisRangeData(Number(r[d-2]),Number(r[d]));break;case 27:this.$=r[d-1];break;case 28:this.$=[r[d-2],...r[d]];break;case 29:this.$=[r[d]];break;case 30:x.setYAxisTitle(r[d]);break;case 31:x.setYAxisTitle(r[d-1]);break;case 32:x.setYAxisTitle({type:"text",text:""});break;case 33:x.setYAxisRangeData(Number(r[d-2]),Number(r[d]));break;case 37:this.$={text:r[d],type:"text"};break;case 38:this.$={text:r[d],type:"text"};break;case 39:this.$={text:r[d],type:"markdown"};break;case 40:this.$=r[d];break;case 41:this.$=r[d-1]+""+r[d];break}},"anonymous"),table:[e(t,i,{3:1,4:2,7:4,5:s,34:n,35:o,36:u}),{1:[3]},e(t,i,{4:2,7:4,3:8,5:s,34:n,35:o,36:u}),e(t,i,{4:2,7:4,6:9,3:10,5:s,8:[1,11],34:n,35:o,36:u}),{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(p,[2,34]),e(p,[2,35]),e(p,[2,36]),{1:[2,1]},e(t,i,{4:2,7:4,3:21,5:s,34:n,35:o,36:u}),{1:[2,3]},e(p,[2,5]),e(t,[2,7],{4:22,34:n,35:o,36:u}),{11:23,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{11:39,13:38,24:W,27:O,29:40,30:41,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{11:45,15:44,27:X,33:46,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{11:49,17:48,24:Y,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{11:52,17:51,24:Y,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{20:[1,53]},{22:[1,54]},e(S,[2,18]),{1:[2,2]},e(S,[2,8]),e(S,[2,9]),e(U,[2,37],{40:55,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l}),e(U,[2,38]),e(U,[2,39]),e(b,[2,40]),e(b,[2,42]),e(b,[2,43]),e(b,[2,44]),e(b,[2,45]),e(b,[2,46]),e(b,[2,47]),e(b,[2,48]),e(b,[2,49]),e(b,[2,50]),e(b,[2,51]),e(S,[2,10]),e(S,[2,22],{30:41,29:56,24:W,27:O}),e(S,[2,24]),e(S,[2,25]),{31:[1,57]},{11:59,32:58,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},e(S,[2,11]),e(S,[2,30],{33:60,27:X}),e(S,[2,32]),{31:[1,61]},e(S,[2,12]),{17:62,24:Y},{25:63,27:w},e(S,[2,14]),{17:65,24:Y},e(S,[2,16]),e(S,[2,17]),e(b,[2,41]),e(S,[2,23]),{27:[1,66]},{26:[1,67]},{26:[2,29],28:[1,68]},e(S,[2,31]),{27:[1,69]},e(S,[2,13]),{26:[1,70]},{26:[2,21],28:[1,71]},e(S,[2,15]),e(S,[2,26]),e(S,[2,27]),{11:59,32:72,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},e(S,[2,33]),e(S,[2,19]),{25:73,27:w},{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(h,c){if(c.recoverable)this.trace(h);else{var g=new Error(h);throw g.hash=c,g}},"parseError"),parse:a(function(h){var c=this,g=[0],x=[],C=[null],r=[],rt=this.table,d="",ct=0,Mt=0,hi=2,It=1,li=r.slice.call(arguments,1),D=Object.create(this.lexer),$={yy:{}};for(var ft in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ft)&&($.yy[ft]=this.yy[ft]);D.setInput(h,$.yy),$.yy.lexer=D,$.yy.parser=this,typeof D.yylloc>"u"&&(D.yylloc={});var pt=D.yylloc;r.push(pt);var ci=D.options&&D.options.ranges;typeof $.yy.parseError=="function"?this.parseError=$.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ui(B){g.length=g.length-2*B,C.length=C.length-B,r.length=r.length-B}a(ui,"popStack");function Vt(){var B;return B=x.pop()||D.lex()||It,typeof B!="number"&&(B instanceof Array&&(x=B,B=x.pop()),B=c.symbols_[B]||B),B}a(Vt,"lex");for(var I,q,z,mt,G={},ut,N,Bt,gt;;){if(q=g[g.length-1],this.defaultActions[q]?z=this.defaultActions[q]:((I===null||typeof I>"u")&&(I=Vt()),z=rt[q]&&rt[q][I]),typeof z>"u"||!z.length||!z[0]){var yt="";gt=[];for(ut in rt[q])this.terminals_[ut]&&ut>hi&&gt.push("'"+this.terminals_[ut]+"'");D.showPosition?yt="Parse error on line "+(ct+1)+`:
1
+ import{s as gi,g as xi,x as Xt,v as di,a as fi,b as pi,_ as a,l as Yt,P as mi,e as yi,D as bi,I as _t,i as Ai,M as Nt,N as wi,a6 as Ci,aH as Si,ae as Wt}from"./index-CrQ5eYxl.js";import{i as _i}from"./init-Gi6I4Gst.js";import{o as ki}from"./ordinal-Cboi1Yqb.js";import{l as zt}from"./linear-6x4QueCv.js";import"./defaultLocale-DX6XiGOO.js";function Ri(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 bt(){var e=ki().unknown(void 0),t=e.domain,i=e.range,s=0,n=1,o,u,p=!1,f=0,T=0,P=.5;delete e.unknown;function _(){var y=t().length,E=n<s,v=E?n:s,L=E?s:n;o=(L-v)/Math.max(1,y-f+T*2),p&&(o=Math.floor(o)),v+=(L-v-o*(y-f))*P,u=o*(1-f),p&&(v=Math.round(v),u=Math.round(u));var M=Ri(y).map(function(m){return v+o*m});return i(E?M.reverse():M)}return e.domain=function(y){return arguments.length?(t(y),_()):t()},e.range=function(y){return arguments.length?([s,n]=y,s=+s,n=+n,_()):[s,n]},e.rangeRound=function(y){return[s,n]=y,s=+s,n=+n,p=!0,_()},e.bandwidth=function(){return u},e.step=function(){return o},e.round=function(y){return arguments.length?(p=!!y,_()):p},e.padding=function(y){return arguments.length?(f=Math.min(1,T=+y),_()):f},e.paddingInner=function(y){return arguments.length?(f=Math.min(1,y),_()):f},e.paddingOuter=function(y){return arguments.length?(T=+y,_()):T},e.align=function(y){return arguments.length?(P=Math.max(0,Math.min(1,y)),_()):P},e.copy=function(){return bt(t(),[s,n]).round(p).paddingInner(f).paddingOuter(T).align(P)},_i.apply(_(),arguments)}var At=(function(){var e=a(function(F,h,c,g){for(c=c||{},g=F.length;g--;c[F[g]]=h);return c},"o"),t=[1,10,12,14,16,18,19,21,23],i=[2,6],s=[1,3],n=[1,5],o=[1,6],u=[1,7],p=[1,5,10,12,14,16,18,19,21,23,34,35,36],f=[1,25],T=[1,26],P=[1,28],_=[1,29],y=[1,30],E=[1,31],v=[1,32],L=[1,33],M=[1,34],m=[1,35],R=[1,36],l=[1,37],W=[1,43],O=[1,42],X=[1,47],Y=[1,50],S=[1,10,12,14,16,18,19,21,23,34,35,36],U=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36],b=[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],w=[1,64],V={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(h,c,g,x,C,r,rt){var d=r.length-1;switch(C){case 5:x.setOrientation(r[d]);break;case 9:x.setDiagramTitle(r[d].text.trim());break;case 12:x.setLineData({text:"",type:"text"},r[d]);break;case 13:x.setLineData(r[d-1],r[d]);break;case 14:x.setBarData({text:"",type:"text"},r[d]);break;case 15:x.setBarData(r[d-1],r[d]);break;case 16:this.$=r[d].trim(),x.setAccTitle(this.$);break;case 17:case 18:this.$=r[d].trim(),x.setAccDescription(this.$);break;case 19:this.$=r[d-1];break;case 20:this.$=[Number(r[d-2]),...r[d]];break;case 21:this.$=[Number(r[d])];break;case 22:x.setXAxisTitle(r[d]);break;case 23:x.setXAxisTitle(r[d-1]);break;case 24:x.setXAxisTitle({type:"text",text:""});break;case 25:x.setXAxisBand(r[d]);break;case 26:x.setXAxisRangeData(Number(r[d-2]),Number(r[d]));break;case 27:this.$=r[d-1];break;case 28:this.$=[r[d-2],...r[d]];break;case 29:this.$=[r[d]];break;case 30:x.setYAxisTitle(r[d]);break;case 31:x.setYAxisTitle(r[d-1]);break;case 32:x.setYAxisTitle({type:"text",text:""});break;case 33:x.setYAxisRangeData(Number(r[d-2]),Number(r[d]));break;case 37:this.$={text:r[d],type:"text"};break;case 38:this.$={text:r[d],type:"text"};break;case 39:this.$={text:r[d],type:"markdown"};break;case 40:this.$=r[d];break;case 41:this.$=r[d-1]+""+r[d];break}},"anonymous"),table:[e(t,i,{3:1,4:2,7:4,5:s,34:n,35:o,36:u}),{1:[3]},e(t,i,{4:2,7:4,3:8,5:s,34:n,35:o,36:u}),e(t,i,{4:2,7:4,6:9,3:10,5:s,8:[1,11],34:n,35:o,36:u}),{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(p,[2,34]),e(p,[2,35]),e(p,[2,36]),{1:[2,1]},e(t,i,{4:2,7:4,3:21,5:s,34:n,35:o,36:u}),{1:[2,3]},e(p,[2,5]),e(t,[2,7],{4:22,34:n,35:o,36:u}),{11:23,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{11:39,13:38,24:W,27:O,29:40,30:41,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{11:45,15:44,27:X,33:46,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{11:49,17:48,24:Y,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{11:52,17:51,24:Y,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},{20:[1,53]},{22:[1,54]},e(S,[2,18]),{1:[2,2]},e(S,[2,8]),e(S,[2,9]),e(U,[2,37],{40:55,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l}),e(U,[2,38]),e(U,[2,39]),e(b,[2,40]),e(b,[2,42]),e(b,[2,43]),e(b,[2,44]),e(b,[2,45]),e(b,[2,46]),e(b,[2,47]),e(b,[2,48]),e(b,[2,49]),e(b,[2,50]),e(b,[2,51]),e(S,[2,10]),e(S,[2,22],{30:41,29:56,24:W,27:O}),e(S,[2,24]),e(S,[2,25]),{31:[1,57]},{11:59,32:58,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},e(S,[2,11]),e(S,[2,30],{33:60,27:X}),e(S,[2,32]),{31:[1,61]},e(S,[2,12]),{17:62,24:Y},{25:63,27:w},e(S,[2,14]),{17:65,24:Y},e(S,[2,16]),e(S,[2,17]),e(b,[2,41]),e(S,[2,23]),{27:[1,66]},{26:[1,67]},{26:[2,29],28:[1,68]},e(S,[2,31]),{27:[1,69]},e(S,[2,13]),{26:[1,70]},{26:[2,21],28:[1,71]},e(S,[2,15]),e(S,[2,26]),e(S,[2,27]),{11:59,32:72,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:M,48:m,49:R,50:l},e(S,[2,33]),e(S,[2,19]),{25:73,27:w},{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(h,c){if(c.recoverable)this.trace(h);else{var g=new Error(h);throw g.hash=c,g}},"parseError"),parse:a(function(h){var c=this,g=[0],x=[],C=[null],r=[],rt=this.table,d="",ct=0,Mt=0,hi=2,It=1,li=r.slice.call(arguments,1),D=Object.create(this.lexer),$={yy:{}};for(var ft in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ft)&&($.yy[ft]=this.yy[ft]);D.setInput(h,$.yy),$.yy.lexer=D,$.yy.parser=this,typeof D.yylloc>"u"&&(D.yylloc={});var pt=D.yylloc;r.push(pt);var ci=D.options&&D.options.ranges;typeof $.yy.parseError=="function"?this.parseError=$.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ui(B){g.length=g.length-2*B,C.length=C.length-B,r.length=r.length-B}a(ui,"popStack");function Vt(){var B;return B=x.pop()||D.lex()||It,typeof B!="number"&&(B instanceof Array&&(x=B,B=x.pop()),B=c.symbols_[B]||B),B}a(Vt,"lex");for(var I,q,z,mt,G={},ut,N,Bt,gt;;){if(q=g[g.length-1],this.defaultActions[q]?z=this.defaultActions[q]:((I===null||typeof I>"u")&&(I=Vt()),z=rt[q]&&rt[q][I]),typeof z>"u"||!z.length||!z[0]){var yt="";gt=[];for(ut in rt[q])this.terminals_[ut]&&ut>hi&&gt.push("'"+this.terminals_[ut]+"'");D.showPosition?yt="Parse error on line "+(ct+1)+`:
2
2
  `+D.showPosition()+`
3
3
  Expecting `+gt.join(", ")+", got '"+(this.terminals_[I]||I)+"'":yt="Parse error on line "+(ct+1)+": Unexpected "+(I==It?"end of input":"'"+(this.terminals_[I]||I)+"'"),this.parseError(yt,{text:D.match,token:this.terminals_[I]||I,line:D.yylineno,loc:pt,expected:gt})}if(z[0]instanceof Array&&z.length>1)throw new Error("Parse Error: multiple actions possible at state: "+q+", token: "+I);switch(z[0]){case 1:g.push(I),C.push(D.yytext),r.push(D.yylloc),g.push(z[1]),I=null,Mt=D.yyleng,d=D.yytext,ct=D.yylineno,pt=D.yylloc;break;case 2:if(N=this.productions_[z[1]][1],G.$=C[C.length-N],G._$={first_line:r[r.length-(N||1)].first_line,last_line:r[r.length-1].last_line,first_column:r[r.length-(N||1)].first_column,last_column:r[r.length-1].last_column},ci&&(G._$.range=[r[r.length-(N||1)].range[0],r[r.length-1].range[1]]),mt=this.performAction.apply(G,[d,Mt,ct,$.yy,z[1],C,r].concat(li)),typeof mt<"u")return mt;N&&(g=g.slice(0,-1*N*2),C=C.slice(0,-1*N),r=r.slice(0,-1*N)),g.push(this.productions_[z[1]][0]),C.push(G.$),r.push(G._$),Bt=rt[g[g.length-2]][g[g.length-1]],g.push(Bt);break;case 3:return!0}}return!0},"parse")},k=(function(){var F={EOF:1,parseError:a(function(c,g){if(this.yy.parser)this.yy.parser.parseError(c,g);else throw new Error(c)},"parseError"),setInput:a(function(h,c){return this.yy=c||this.yy||{},this._input=h,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 h=this._input[0];this.yytext+=h,this.yyleng++,this.offset++,this.match+=h,this.matched+=h;var c=h.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),h},"input"),unput:a(function(h){var c=h.length,g=h.split(/(?:\r\n?|\n)/g);this._input=h+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-c),this.offset-=c;var x=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),g.length-1&&(this.yylineno-=g.length-1);var C=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:g?(g.length===x.length?this.yylloc.first_column:0)+x[x.length-g.length].length-g[0].length:this.yylloc.first_column-c},this.options.ranges&&(this.yylloc.range=[C[0],C[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(h){this.unput(this.match.slice(h))},"less"),pastInput:a(function(){var h=this.matched.substr(0,this.matched.length-this.match.length);return(h.length>20?"...":"")+h.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:a(function(){var h=this.match;return h.length<20&&(h+=this._input.substr(0,20-h.length)),(h.substr(0,20)+(h.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:a(function(){var h=this.pastInput(),c=new Array(h.length+1).join("-");return h+this.upcomingInput()+`
package/public/index.html CHANGED
@@ -10,8 +10,8 @@
10
10
  href="https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500&display=swap"
11
11
  rel="stylesheet"
12
12
  />
13
- <script type="module" crossorigin src="/assets/index-BHlQtZ6_.js"></script>
14
- <link rel="stylesheet" crossorigin href="/assets/index-CyEGNm7Z.css">
13
+ <script type="module" crossorigin src="/assets/index-CrQ5eYxl.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/assets/index-RUcotPWN.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="root"></div>
@@ -0,0 +1,62 @@
1
+ // CANONICAL front/index.tsx for a boring-ui plugin.
2
+ // Copy this shape — replace <kebab-name> and <Label>.
3
+ //
4
+ // definePlugin takes a single DECLARATIVE config object. For
5
+ // conditional registration or runtime branching that the declarative
6
+ // fields can't express, use the optional `setup: (api) => void`
7
+ // escape hatch — it runs LAST, after every declarative field has
8
+ // been registered.
9
+
10
+ import React from "react"
11
+ import { definePlugin } from "@hachej/boring-workspace/plugin"
12
+
13
+ function MyPane() {
14
+ return <div style={{ padding: 16 }}>Hello from &lt;kebab-name&gt;</div>
15
+ }
16
+
17
+ export default definePlugin({
18
+ id: "<kebab-name>", // contribution namespace; matching package name is recommended
19
+ label: "<Label>",
20
+ panels: [
21
+ { id: "<kebab-name>.panel", label: "<Label>", component: MyPane },
22
+ ],
23
+ commands: [
24
+ { id: "<kebab-name>.open", title: "Open <Label>", panelId: "<kebab-name>.panel" },
25
+ ],
26
+ // Do not add leftTabs by default: left tabs are persistent sidebar
27
+ // navigation. Use them only for always-on tools/catalogs that deserve a
28
+ // permanent sidebar entry; file visualizers should use surfaceResolvers.
29
+ // leftTabs: [
30
+ // { id: "<kebab-name>.tab", title: "<Label>", panelId: "<kebab-name>.panel" },
31
+ // ],
32
+ // File visualizer example: import WORKSPACE_OPEN_PATH_SURFACE_KIND from
33
+ // "@hachej/boring-workspace/plugin", set kind: WORKSPACE_OPEN_PATH_SURFACE_KIND,
34
+ // check request.target (e.g. .endsWith(".csv")), and fetch raw file bytes
35
+ // from /api/v1/files/raw?path=${encodeURIComponent(request.target)}.
36
+ // surfaceResolvers: [
37
+ // { id: "<kebab-name>.surface", kind: WORKSPACE_OPEN_PATH_SURFACE_KIND, resolve(request) { ... } },
38
+ // ],
39
+ //
40
+ // Escape hatch for conditional registration:
41
+ // setup: (api) => { if (env.beta) api.registerPanel(betaPanel) },
42
+ })
43
+
44
+ // All available `definePlugin` config fields:
45
+ // id (required, string)
46
+ // label (optional, string)
47
+ // panels [{ id, label, component }]
48
+ // commands [{ id, title, panelId }]
49
+ // leftTabs [{ id, title, panelId }]
50
+ // surfaceResolvers [{ id, kind, resolve(request) }]
51
+ // providers (rare — context wrappers)
52
+ // bindings (rare — same as provider)
53
+ // catalogs (rare)
54
+ // setup (escape hatch — called last, gets the imperative api)
55
+ //
56
+ // Composition is JS spread + concat:
57
+ // import { baseConfig } from "@hachej/some-base"
58
+ // definePlugin({
59
+ // ...baseConfig,
60
+ // id: "my-extended",
61
+ // commands: [...baseConfig.commands, myExtraCommand],
62
+ // })
@@ -0,0 +1,19 @@
1
+ {
2
+ "_doc_": [
3
+ "CANONICAL package.json for a boring-ui plugin under .pi/extensions/<kebab-name>/.",
4
+ "Strip this _doc_ key when copying. No scripts, no dependencies, no devDependencies — the dev server transforms .tsx on the fly via Vite.",
5
+ "boring.front: relative path to the front factory file.",
6
+ "boring.server: advanced boot-time/static server integration only; omit by default. NEVER true.",
7
+ "pi.extensions: optional, path string(s) to in-process Pi extension files like 'agent/index.ts' — use this for hot-reloadable agent behavior."
8
+ ],
9
+ "name": "<kebab-name>",
10
+ "version": "0.1.0",
11
+ "private": true,
12
+ "boring": {
13
+ "label": "<Label>",
14
+ "front": "front/index.tsx"
15
+ },
16
+ "pi": {
17
+ "systemPrompt": "<Label> plugin — describe what it does so the agent knows when to use it."
18
+ }
19
+ }
@@ -0,0 +1,64 @@
1
+ # Plugin template
2
+
3
+ Reference shape for **app/internal publishable npm-package plugins**.
4
+ The CLI copies this directory when you run:
5
+
6
+ ```sh
7
+ boring-ui plugin create <your-name> --path plugins
8
+ cd plugins/<your-name>
9
+ pnpm install
10
+ pnpm typecheck && pnpm test
11
+ ```
12
+
13
+ Or copy it manually:
14
+
15
+ ```sh
16
+ cp -R packages/cli/templates/plugin plugins/<your-name>
17
+ # rename: `sample` → `<your-name>` in src/, package.json:name,
18
+ # tsup entries, vitest aliases as needed
19
+ ```
20
+
21
+ > **Building a generated/runtime user plugin instead** (hot-reloadable,
22
+ > no build step, drops into a workspace's `.pi/extensions/<name>/`)?
23
+ > Don't copy this template and don't use `npx` from inside the agent
24
+ > runtime — run the workspace-local `boring-ui scaffold-plugin <name>`.
25
+
26
+ ## Shape
27
+
28
+ ```
29
+ plugins/<name>/
30
+ package.json private: true, workspace:* deps, nested exports map
31
+ tsconfig.json paths aliases into packages/workspace/src for fast iteration
32
+ tsup.config.ts nested entries (front/index, server/index, shared/index)
33
+ vitest.config.ts jsdom + @vitejs/plugin-react + globals: true
34
+ setupFiles: ./src/test-setup.ts
35
+ src/
36
+ front/
37
+ index.ts definePlugin({ ... }) entry and re-exports
38
+ panels.tsx
39
+ surfaceResolver.ts
40
+ __tests__/xxxPlugin.test.ts
41
+ server/
42
+ index.ts createXxxServerPlugin() and default server factory
43
+ shared/
44
+ constants.ts ids, surface kinds
45
+ types.ts param/option types
46
+ index.ts re-export
47
+ ```
48
+
49
+ ## What lives where
50
+
51
+ - **front/** — anything that runs in the browser shell: panels, command
52
+ contributions, surface resolvers, providers, bindings.
53
+ - **server/** — anything that runs in the agent backend: agent tools,
54
+ system prompt fragments, server hooks.
55
+ - **shared/** — constants and types used by both sides. Keep it tiny.
56
+ - **`src/test-setup.ts`** — jest-dom matchers, ResizeObserver + Range
57
+ polyfills, testing-library cleanup. Each plugin owns its own copy;
58
+ keep them in sync with `packages/cli/templates/plugin/src/test-setup.ts`
59
+ if the canonical setup changes.
60
+
61
+ ## Invariants
62
+
63
+ `packages/workspace/scripts/check-plugin-invariants.mjs` lints this
64
+ template (and the live plugins) for the plugin contract. Keep it valid.
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@hachej/boring-plugin-template",
3
+ "version": "0.0.0",
4
+ "type": "module",
5
+ "private": true,
6
+ "description": "Reference app/internal boring-ui package-plugin example using declarative definePlugin({ ... }) front contributions plus boot-time server integration. Generated .pi/extensions plugins should use boring-ui scaffold-plugin instead.",
7
+ "boring": {
8
+ "label": "Sample",
9
+ "front": "dist/front/index.js",
10
+ "server": "dist/server/index.js"
11
+ },
12
+ "pi": {
13
+ "systemPrompt": "Sample plugin template \u2014 replace this prompt with a short hint telling the agent when to use your plugin's panels/tools."
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/front/index.d.ts",
21
+ "import": "./dist/front/index.js"
22
+ },
23
+ "./front": {
24
+ "types": "./dist/front/index.d.ts",
25
+ "import": "./dist/front/index.js"
26
+ },
27
+ "./server": {
28
+ "types": "./dist/server/index.d.ts",
29
+ "import": "./dist/server/index.js"
30
+ },
31
+ "./shared": {
32
+ "types": "./dist/shared/index.d.ts",
33
+ "import": "./dist/shared/index.js"
34
+ },
35
+ "./package.json": "./package.json"
36
+ },
37
+ "sideEffects": false,
38
+ "scripts": {
39
+ "build": "tsup",
40
+ "typecheck": "pnpm --filter @hachej/boring-ui-kit build && pnpm --filter @hachej/boring-agent build && pnpm --filter @hachej/boring-workspace build && tsc --noEmit",
41
+ "test": "pnpm --filter @hachej/boring-ui-kit build && vitest run --passWithNoTests",
42
+ "lint": "pnpm run typecheck",
43
+ "clean": "rm -rf dist .tsbuildinfo"
44
+ },
45
+ "peerDependencies": {
46
+ "@hachej/boring-workspace": "workspace:*",
47
+ "react": "^18.0.0 || ^19.0.0",
48
+ "react-dom": "^18.0.0 || ^19.0.0"
49
+ },
50
+ "dependencies": {
51
+ "@hachej/boring-ui-kit": "workspace:*"
52
+ },
53
+ "devDependencies": {
54
+ "@hachej/boring-workspace": "workspace:*",
55
+ "@testing-library/jest-dom": "^6.9.1",
56
+ "@testing-library/react": "^16.3.2",
57
+ "@types/react": "^19.0.0",
58
+ "@types/react-dom": "^19.0.0",
59
+ "@vitejs/plugin-react": "^4.0.0",
60
+ "jsdom": "^29.0.2",
61
+ "react": "^19.0.0",
62
+ "react-dom": "^19.0.0",
63
+ "tsup": "^8.0.0",
64
+ "typescript": "^5.4.0",
65
+ "vitest": "^3.1.3"
66
+ }
67
+ }
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it, vi } from "vitest"
2
+ import samplePlugin, { SAMPLE_PANEL_ID, SamplePanel } from "../index"
3
+ import { SAMPLE_PLUGIN_ID, SAMPLE_SURFACE_KIND } from "../../shared/constants"
4
+
5
+ describe("samplePlugin (BoringFrontFactory)", () => {
6
+ it("registers a panel, a panel command, and a surface resolver", async () => {
7
+ const registerPanel = vi.fn()
8
+ const registerPanelCommand = vi.fn()
9
+ const registerSurfaceResolver = vi.fn()
10
+ const api = {
11
+ registerProvider: vi.fn(),
12
+ registerBinding: vi.fn(),
13
+ registerCatalog: vi.fn(),
14
+ registerPanel,
15
+ registerPanelCommand,
16
+ registerLeftTab: vi.fn(),
17
+ registerSurfaceResolver,
18
+ }
19
+
20
+ await samplePlugin(api)
21
+
22
+ expect(registerPanel).toHaveBeenCalledExactlyOnceWith(
23
+ expect.objectContaining({
24
+ id: SAMPLE_PANEL_ID,
25
+ label: "Sample",
26
+ placement: "center",
27
+ component: SamplePanel,
28
+ }),
29
+ )
30
+ expect(registerPanelCommand).toHaveBeenCalledExactlyOnceWith(
31
+ expect.objectContaining({
32
+ id: "sample.open",
33
+ title: "Open Sample",
34
+ panelId: SAMPLE_PANEL_ID,
35
+ }),
36
+ )
37
+ expect(registerSurfaceResolver).toHaveBeenCalledExactlyOnceWith(
38
+ expect.objectContaining({
39
+ id: "sample",
40
+ kind: SAMPLE_SURFACE_KIND,
41
+ }),
42
+ )
43
+ })
44
+
45
+ it("is the default export (required for hot-reload dynamic import)", () => {
46
+ expect(typeof samplePlugin).toBe("function")
47
+ })
48
+
49
+ it("carries pluginId + pluginLabel metadata (definePlugin contract)", () => {
50
+ expect(samplePlugin.pluginId).toBe(SAMPLE_PLUGIN_ID)
51
+ expect(samplePlugin.pluginLabel).toBe("Sample")
52
+ })
53
+ })
@@ -0,0 +1,45 @@
1
+ import { definePlugin, type BoringFrontFactoryWithId } from "@hachej/boring-workspace/plugin"
2
+ import { SAMPLE_PLUGIN_ID } from "../shared/constants"
3
+ import { SAMPLE_PANEL_ID, SamplePanel } from "./panels"
4
+ import { sampleSurfaceResolver } from "./surfaceResolver"
5
+
6
+ /**
7
+ * Default-exported `BoringFrontFactoryWithId`. The workspace shell
8
+ * accepts this directly in `WorkspaceProvider.plugins`; on bootstrap,
9
+ * it dispatches each declarative field to the corresponding
10
+ * `api.register*` method.
11
+ *
12
+ * `definePlugin(config)` takes a single declarative config object.
13
+ * For imperative composition (calling an external factory), use the
14
+ * `setup: (api) => void` escape hatch — see SKILL.md.
15
+ *
16
+ * Plugins in `.pi/extensions/<name>/` also get hot-reloaded — the
17
+ * workspace dynamically re-imports this module and re-runs the
18
+ * factory.
19
+ */
20
+ const samplePlugin: BoringFrontFactoryWithId = definePlugin({
21
+ id: SAMPLE_PLUGIN_ID,
22
+ label: "Sample",
23
+ panels: [
24
+ {
25
+ id: SAMPLE_PANEL_ID,
26
+ label: "Sample",
27
+ component: SamplePanel,
28
+ placement: "center",
29
+ source: "app",
30
+ },
31
+ ],
32
+ commands: [
33
+ {
34
+ id: "sample.open",
35
+ title: "Open Sample",
36
+ panelId: SAMPLE_PANEL_ID,
37
+ },
38
+ ],
39
+ surfaceResolvers: [sampleSurfaceResolver],
40
+ })
41
+
42
+ export default samplePlugin
43
+
44
+ export { SamplePanel, SAMPLE_PANEL_ID } from "./panels"
45
+ export { sampleSurfaceResolver } from "./surfaceResolver"
@@ -0,0 +1,8 @@
1
+ import type { PaneProps } from "@hachej/boring-workspace"
2
+ import type { SampleParams } from "../shared/types"
3
+
4
+ export const SAMPLE_PANEL_ID = "sample-panel"
5
+
6
+ export function SamplePanel({ params }: PaneProps<SampleParams>) {
7
+ return <div>{params.id}</div>
8
+ }
@@ -0,0 +1,19 @@
1
+ import type { BoringFrontSurfaceResolverRegistration } from "@hachej/boring-workspace/plugin"
2
+ import { SAMPLE_SURFACE_KIND } from "../shared/constants"
3
+ import { SAMPLE_PANEL_ID } from "./panels"
4
+
5
+ export const sampleSurfaceResolver: BoringFrontSurfaceResolverRegistration = {
6
+ id: "sample",
7
+ kind: SAMPLE_SURFACE_KIND,
8
+ source: "app",
9
+ resolve(request) {
10
+ if (request.kind !== SAMPLE_SURFACE_KIND) return undefined
11
+ return {
12
+ id: `sample:${request.target}`,
13
+ component: SAMPLE_PANEL_ID,
14
+ title: request.target,
15
+ params: { id: request.target },
16
+ score: 0,
17
+ }
18
+ },
19
+ }
@@ -0,0 +1,29 @@
1
+ import type { AgentTool } from "@hachej/boring-workspace"
2
+ import {
3
+ defineServerPlugin,
4
+ type WorkspaceServerPlugin,
5
+ } from "@hachej/boring-workspace/server"
6
+ import { SAMPLE_PLUGIN_ID } from "../shared/constants"
7
+
8
+ export function createSampleServerPlugin(): WorkspaceServerPlugin {
9
+ return defineServerPlugin({
10
+ id: SAMPLE_PLUGIN_ID,
11
+ label: "Sample",
12
+ agentTools: [] satisfies AgentTool[],
13
+ systemPrompt: "## Sample Plugin",
14
+ })
15
+ }
16
+
17
+ /**
18
+ * Default export — adapter for the standard `defaultPluginPackages`
19
+ * load process. The workspace's `pluginEntryResolver` calls a
20
+ * dir-source plugin's default-exported factory with `(options, ctx)`
21
+ * where `ctx = { workspaceRoot, bridge }`. The named
22
+ * `createSampleServerPlugin()` factory stays for direct callers.
23
+ */
24
+ export default function defaultSampleServerPlugin(
25
+ _options?: unknown,
26
+ _ctx?: { workspaceRoot: string; bridge: unknown },
27
+ ): WorkspaceServerPlugin {
28
+ return createSampleServerPlugin()
29
+ }
@@ -0,0 +1,2 @@
1
+ export const SAMPLE_PLUGIN_ID = "sample"
2
+ export const SAMPLE_SURFACE_KIND = "sample.open"
@@ -0,0 +1,2 @@
1
+ export * from "./constants"
2
+ export * from "./types"
@@ -0,0 +1,3 @@
1
+ export interface SampleParams {
2
+ id: string
3
+ }
@@ -0,0 +1,43 @@
1
+ // Vitest setup for this plugin. Each plugin owns its own copy of this
2
+ // file; keep them in sync with packages/cli/templates/plugin/src/test-setup.ts when
3
+ // the canonical setup changes (rare — see the comment below).
4
+ //
5
+ // Extends vitest's `expect` with jest-dom matchers manually rather than
6
+ // via `import "@testing-library/jest-dom/vitest"`. The shorthand
7
+ // re-imports `vitest` through jest-dom's own resolution path, which —
8
+ // after lockfile churn in this monorepo — lands on a *different* copy
9
+ // of vitest than test files do. Extensions go nowhere and you get
10
+ // `Invalid Chai property: toBeInTheDocument` everywhere. Doing the
11
+ // extend manually pins both sides to the same expect.
12
+ import { expect, afterEach } from "vitest"
13
+ import * as matchers from "@testing-library/jest-dom/matchers"
14
+ import { cleanup } from "@testing-library/react"
15
+
16
+ expect.extend(matchers)
17
+
18
+ if (typeof globalThis.ResizeObserver === "undefined") {
19
+ globalThis.ResizeObserver = class ResizeObserver {
20
+ observe() {}
21
+ unobserve() {}
22
+ disconnect() {}
23
+ }
24
+ }
25
+
26
+ // jsdom doesn't implement layout. Plugins using tiptap / ProseMirror
27
+ // call getClientRects on Range/Element instances during scrollIntoView;
28
+ // stub them so transactions don't throw.
29
+ if (typeof Range !== "undefined" && !Range.prototype.getClientRects) {
30
+ Range.prototype.getClientRects = function () {
31
+ return { length: 0, item: () => null, [Symbol.iterator]: function* () {} } as any
32
+ }
33
+ Range.prototype.getBoundingClientRect = function () {
34
+ return {
35
+ x: 0, y: 0, top: 0, left: 0, right: 0, bottom: 0,
36
+ width: 0, height: 0, toJSON: () => ({}),
37
+ } as DOMRect
38
+ }
39
+ }
40
+
41
+ afterEach(() => {
42
+ cleanup()
43
+ })
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "resolveJsonModule": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "noEmit": true,
14
+ "types": ["vitest/globals", "@testing-library/jest-dom"],
15
+ "paths": {
16
+ "@hachej/boring-workspace": ["../../packages/workspace/src/index.ts"],
17
+ "@hachej/boring-workspace/server": ["../../packages/workspace/src/server/index.ts"],
18
+ "@hachej/boring-workspace/events": ["../../packages/workspace/src/front/events/index.ts"]
19
+ }
20
+ },
21
+ "include": ["src/**/*"],
22
+ "exclude": ["node_modules", "dist"]
23
+ }
@@ -0,0 +1,21 @@
1
+ import { defineConfig } from "tsup"
2
+
3
+ export default defineConfig({
4
+ entry: {
5
+ "front/index": "src/front/index.ts",
6
+ "server/index": "src/server/index.ts",
7
+ "shared/index": "src/shared/index.ts",
8
+ },
9
+ format: ["esm"],
10
+ dts: true,
11
+ splitting: false,
12
+ clean: true,
13
+ platform: "neutral",
14
+ target: "es2022",
15
+ external: [
16
+ /^@hachej\/boring-/,
17
+ "react",
18
+ "react-dom",
19
+ "react/jsx-runtime",
20
+ ],
21
+ })
@@ -0,0 +1,20 @@
1
+ import { defineConfig } from "vitest/config"
2
+ import { resolve } from "node:path"
3
+ import react from "@vitejs/plugin-react"
4
+
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ resolve: {
8
+ alias: {
9
+ "@hachej/boring-workspace/server": resolve(__dirname, "../../packages/workspace/src/server/index.ts"),
10
+ "@hachej/boring-workspace/events": resolve(__dirname, "../../packages/workspace/src/front/events/index.ts"),
11
+ "@hachej/boring-workspace/plugin": resolve(__dirname, "../../packages/workspace/src/plugin.ts"),
12
+ "@hachej/boring-workspace": resolve(__dirname, "../../packages/workspace/src/index.ts"),
13
+ },
14
+ },
15
+ test: {
16
+ environment: "jsdom",
17
+ globals: true,
18
+ setupFiles: ["./src/test-setup.ts"],
19
+ },
20
+ })
@@ -0,0 +1,42 @@
1
+ // CANONICAL server/index.ts for advanced boring-ui server integration.
2
+ // This is boot-time/static composition only for .pi/extensions plugins:
3
+ // /reload does NOT hot-register these routes or agent tools. Prefer
4
+ // pi.extensions for hot-reloadable agent behavior.
5
+ // Copy this shape only when the host will compose/restart the plugin.
6
+
7
+ import { defineServerPlugin, type WorkspaceServerPlugin } from "@hachej/boring-workspace/server"
8
+
9
+ export default function (
10
+ _options: unknown,
11
+ ctx: { workspaceRoot: string; bridge: unknown },
12
+ ): WorkspaceServerPlugin {
13
+ return defineServerPlugin({
14
+ id: "<kebab-name>", // contribution namespace; matching package name is recommended
15
+ agentTools: [
16
+ {
17
+ name: "<snake_case_tool_name>",
18
+ description: "<what the tool does>",
19
+ parameters: { type: "object", properties: {} },
20
+ async execute() {
21
+ return { content: [{ type: "text", text: "..." }] }
22
+ },
23
+ },
24
+ ],
25
+ systemPrompt: "Use <snake_case_tool_name> when …",
26
+ })
27
+ }
28
+
29
+ // Key rules — agents commonly get these wrong:
30
+ // - Method is `execute` (NOT `handler`).
31
+ // - Return shape MUST be `{ content: [{ type: "text", text: "..." }] }`
32
+ // (NOT a bare string and NOT `{ result: ... }`).
33
+ // - Import from `@hachej/boring-workspace/server`
34
+ // (NOT `@hachej/boring-pi` and NOT `@boring-ui/*`).
35
+ // - Default-export a FUNCTION that returns the plugin object —
36
+ // do NOT `export const eval_cross_ping = { ... }`.
37
+ // - package.json must set `boring.server: "server/index.ts"`
38
+ // (a relative path string). NOT `true` — the manifest validator
39
+ // rejects `true` with `INVALID_PLUGIN_METADATA`. Valid values:
40
+ // a path string, OR `false` (no server), OR omit.
41
+ // - For .pi/extensions user plugins, /reload only refreshes front/Pi
42
+ // assets. Server entries require static composition plus restart.
@@ -1 +0,0 @@
1
- import{U as a,G as n}from"./index-BHlQtZ6_.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-4TB4RGXK-Dpk7ncuw.js";import{_ as i}from"./index-BHlQtZ6_.js";import"./chunk-FMBD7UC4-BgIQ6c_c.js";import"./chunk-YZCP3GAM-CfIqY3Yu.js";import"./chunk-55IACEB6-CZYv6OBA.js";import"./chunk-EDXVE4YY-NqKsVs05.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-4TB4RGXK-Dpk7ncuw.js";import{_ as i}from"./index-BHlQtZ6_.js";import"./chunk-FMBD7UC4-BgIQ6c_c.js";import"./chunk-YZCP3GAM-CfIqY3Yu.js";import"./chunk-55IACEB6-CZYv6OBA.js";import"./chunk-EDXVE4YY-NqKsVs05.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{b as r}from"./graph-kiXKPMn9.js";var e=4;function a(o){return r(o,e)}export{a as c};