pi-gitnexus-fork 0.7.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 (117) hide show
  1. package/.github/workflows/ci.yml +20 -0
  2. package/.gitnexusignore +11 -0
  3. package/.sg-rules/async-function-must-await-or-return.yml +55 -0
  4. package/.sg-rules/catch-must-log-error.yml +78 -0
  5. package/.sg-rules/class-must-implement-or-extend.yml +61 -0
  6. package/.sg-rules/class-property-must-be-readonly.yml +61 -0
  7. package/.sg-rules/error-must-extend-base.yml +56 -0
  8. package/.sg-rules/generic-must-be-constrained.yml +60 -0
  9. package/.sg-rules/import-reexport-risk.yml +9 -0
  10. package/.sg-rules/missing-session-id-in-api.yml +16 -0
  11. package/.sg-rules/no-any-in-generic-args.yml +57 -0
  12. package/.sg-rules/no-await-in-promise-all.yml +28 -0
  13. package/.sg-rules/no-barrel-export.yml +17 -0
  14. package/.sg-rules/no-bq-write-in-module.yml +65 -0
  15. package/.sg-rules/no-console-except-error.yml +27 -0
  16. package/.sg-rules/no-console-in-server.yml +42 -0
  17. package/.sg-rules/no-empty-catch.yml +20 -0
  18. package/.sg-rules/no-empty-function.yml +24 -0
  19. package/.sg-rules/no-eval.yml +28 -0
  20. package/.sg-rules/no-explicit-any.yml +34 -0
  21. package/.sg-rules/no-hardcoded-placeholder-string.yml +23 -0
  22. package/.sg-rules/no-hardcoded-secrets.yml +32 -0
  23. package/.sg-rules/no-innerHTML.yml +22 -0
  24. package/.sg-rules/no-json-parse-without-trycatch.yml +33 -0
  25. package/.sg-rules/no-magic-numbers.yml +25 -0
  26. package/.sg-rules/no-nested-ternary.yml +21 -0
  27. package/.sg-rules/no-non-null-assertion.yml +25 -0
  28. package/.sg-rules/no-stub-implementation.yml +44 -0
  29. package/.sg-rules/no-throw-literal.yml +50 -0
  30. package/.sg-rules/no-todo-comment.yml +24 -0
  31. package/.sg-rules/no-ts-ignore-comment.yml +48 -0
  32. package/.sg-rules/no-type-assertion-in-jsx.yml +23 -0
  33. package/.sg-rules/no-unguarded-trim.yml +24 -0
  34. package/.sg-rules/no-unknown-without-narrowing.yml +76 -0
  35. package/.sg-rules/no-unsafe-bracket-access.yml +58 -0
  36. package/.sg-rules/no-unsafe-type-assertion.yml +45 -0
  37. package/.sg-rules/switch-must-be-exhaustive.yml +62 -0
  38. package/.sg-rules/zod-async-refine-without-abort.yml +62 -0
  39. package/.sg-rules/zod-enum-unsafe-access.yml +59 -0
  40. package/.sg-rules/zod-nested-object-deep-path.yml +70 -0
  41. package/.sg-rules/zod-optional-without-default-in-route.yml +50 -0
  42. package/.sg-rules/zod-parse-not-safe.yml +42 -0
  43. package/.sg-rules/zod-preprocess-without-fallback.yml +58 -0
  44. package/.sg-rules/zod-refine-no-return-undefined.yml +54 -0
  45. package/.sg-rules/zod-transform-without-output-type.yml +52 -0
  46. package/.sg-sha +1 -0
  47. package/.sgignore +4 -0
  48. package/AGENTS.md +1 -0
  49. package/CHANGELOG.md +99 -0
  50. package/LICENSE +21 -0
  51. package/README.md +113 -0
  52. package/biome.json +25 -0
  53. package/coverage/base.css +224 -0
  54. package/coverage/block-navigation.js +87 -0
  55. package/coverage/clover.xml +890 -0
  56. package/coverage/coverage-final.json +12 -0
  57. package/coverage/favicon.png +0 -0
  58. package/coverage/index.html +131 -0
  59. package/coverage/prettify.css +1 -0
  60. package/coverage/prettify.js +2 -0
  61. package/coverage/sort-arrow-sprite.png +0 -0
  62. package/coverage/sorter.js +210 -0
  63. package/coverage/src/augment-remote.ts.html +274 -0
  64. package/coverage/src/gitnexus.ts.html +1363 -0
  65. package/coverage/src/index.html +236 -0
  66. package/coverage/src/index.ts.html +1561 -0
  67. package/coverage/src/mcp-client-factory.ts.html +367 -0
  68. package/coverage/src/mcp-client-stdio.ts.html +736 -0
  69. package/coverage/src/mcp-client.ts.html +568 -0
  70. package/coverage/src/remote-mcp-client.ts.html +709 -0
  71. package/coverage/src/repo-resolver.ts.html +526 -0
  72. package/coverage/src/tools.ts.html +970 -0
  73. package/coverage/src/ui/index.html +131 -0
  74. package/coverage/src/ui/main-menu.ts.html +502 -0
  75. package/coverage/src/ui/settings-menu.ts.html +460 -0
  76. package/dist/augment-remote.d.ts +11 -0
  77. package/dist/augment-remote.js +55 -0
  78. package/dist/gitnexus.d.ts +103 -0
  79. package/dist/gitnexus.js +410 -0
  80. package/dist/index.d.ts +2 -0
  81. package/dist/index.js +479 -0
  82. package/dist/mcp-client-factory.d.ts +19 -0
  83. package/dist/mcp-client-factory.js +78 -0
  84. package/dist/mcp-client-stdio.d.ts +35 -0
  85. package/dist/mcp-client-stdio.js +186 -0
  86. package/dist/mcp-client.d.ts +45 -0
  87. package/dist/mcp-client.js +145 -0
  88. package/dist/remote-mcp-client.d.ts +43 -0
  89. package/dist/remote-mcp-client.js +181 -0
  90. package/dist/repo-resolver.d.ts +47 -0
  91. package/dist/repo-resolver.js +123 -0
  92. package/dist/tools.d.ts +6 -0
  93. package/dist/tools.js +230 -0
  94. package/dist/ui/main-menu.d.ts +33 -0
  95. package/dist/ui/main-menu.js +102 -0
  96. package/dist/ui/settings-menu.d.ts +16 -0
  97. package/dist/ui/settings-menu.js +95 -0
  98. package/docs/design/remote-mcp-backend.md +153 -0
  99. package/media/screenshot.png +0 -0
  100. package/package.json +61 -0
  101. package/sgconfig.yml +4 -0
  102. package/skills/gitnexus-debugging/SKILL.md +84 -0
  103. package/skills/gitnexus-exploring/SKILL.md +73 -0
  104. package/skills/gitnexus-impact-analysis/SKILL.md +93 -0
  105. package/skills/gitnexus-pr-review/SKILL.md +109 -0
  106. package/skills/gitnexus-refactoring/SKILL.md +85 -0
  107. package/src/augment-remote.ts +63 -0
  108. package/src/gitnexus.ts +426 -0
  109. package/src/index.ts +492 -0
  110. package/src/mcp-client-factory.ts +94 -0
  111. package/src/mcp-client-stdio.ts +217 -0
  112. package/src/mcp-client.ts +208 -0
  113. package/src/remote-mcp-client.ts +250 -0
  114. package/src/repo-resolver.ts +147 -0
  115. package/src/tools.ts +295 -0
  116. package/src/ui/main-menu.ts +139 -0
  117. package/src/ui/settings-menu.ts +125 -0
@@ -0,0 +1,568 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/mcp-client.ts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../prettify.css" />
9
+ <link rel="stylesheet" href="../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../index.html">All files</a> / <a href="index.html">src</a> mcp-client.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">57.14% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>28/49</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">61.53% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>16/26</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">78.57% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>11/14</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">60.46% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>26/43</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line medium'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
228
+ <span class="cline-any cline-neutral">&nbsp;</span>
229
+ <span class="cline-any cline-neutral">&nbsp;</span>
230
+ <span class="cline-any cline-neutral">&nbsp;</span>
231
+ <span class="cline-any cline-neutral">&nbsp;</span>
232
+ <span class="cline-any cline-neutral">&nbsp;</span>
233
+ <span class="cline-any cline-neutral">&nbsp;</span>
234
+ <span class="cline-any cline-neutral">&nbsp;</span>
235
+ <span class="cline-any cline-neutral">&nbsp;</span>
236
+ <span class="cline-any cline-neutral">&nbsp;</span>
237
+ <span class="cline-any cline-neutral">&nbsp;</span>
238
+ <span class="cline-any cline-neutral">&nbsp;</span>
239
+ <span class="cline-any cline-neutral">&nbsp;</span>
240
+ <span class="cline-any cline-neutral">&nbsp;</span>
241
+ <span class="cline-any cline-neutral">&nbsp;</span>
242
+ <span class="cline-any cline-neutral">&nbsp;</span>
243
+ <span class="cline-any cline-neutral">&nbsp;</span>
244
+ <span class="cline-any cline-neutral">&nbsp;</span>
245
+ <span class="cline-any cline-neutral">&nbsp;</span>
246
+ <span class="cline-any cline-neutral">&nbsp;</span>
247
+ <span class="cline-any cline-neutral">&nbsp;</span>
248
+ <span class="cline-any cline-neutral">&nbsp;</span>
249
+ <span class="cline-any cline-neutral">&nbsp;</span>
250
+ <span class="cline-any cline-neutral">&nbsp;</span>
251
+ <span class="cline-any cline-neutral">&nbsp;</span>
252
+ <span class="cline-any cline-neutral">&nbsp;</span>
253
+ <span class="cline-any cline-neutral">&nbsp;</span>
254
+ <span class="cline-any cline-neutral">&nbsp;</span>
255
+ <span class="cline-any cline-neutral">&nbsp;</span>
256
+ <span class="cline-any cline-neutral">&nbsp;</span>
257
+ <span class="cline-any cline-neutral">&nbsp;</span>
258
+ <span class="cline-any cline-neutral">&nbsp;</span>
259
+ <span class="cline-any cline-neutral">&nbsp;</span>
260
+ <span class="cline-any cline-neutral">&nbsp;</span>
261
+ <span class="cline-any cline-neutral">&nbsp;</span>
262
+ <span class="cline-any cline-neutral">&nbsp;</span>
263
+ <span class="cline-any cline-neutral">&nbsp;</span>
264
+ <span class="cline-any cline-yes">7x</span>
265
+ <span class="cline-any cline-yes">7x</span>
266
+ <span class="cline-any cline-neutral">&nbsp;</span>
267
+ <span class="cline-any cline-neutral">&nbsp;</span>
268
+ <span class="cline-any cline-neutral">&nbsp;</span>
269
+ <span class="cline-any cline-neutral">&nbsp;</span>
270
+ <span class="cline-any cline-neutral">&nbsp;</span>
271
+ <span class="cline-any cline-neutral">&nbsp;</span>
272
+ <span class="cline-any cline-neutral">&nbsp;</span>
273
+ <span class="cline-any cline-neutral">&nbsp;</span>
274
+ <span class="cline-any cline-neutral">&nbsp;</span>
275
+ <span class="cline-any cline-neutral">&nbsp;</span>
276
+ <span class="cline-any cline-neutral">&nbsp;</span>
277
+ <span class="cline-any cline-neutral">&nbsp;</span>
278
+ <span class="cline-any cline-neutral">&nbsp;</span>
279
+ <span class="cline-any cline-neutral">&nbsp;</span>
280
+ <span class="cline-any cline-neutral">&nbsp;</span>
281
+ <span class="cline-any cline-neutral">&nbsp;</span>
282
+ <span class="cline-any cline-yes">1x</span>
283
+ <span class="cline-any cline-yes">1x</span>
284
+ <span class="cline-any cline-neutral">&nbsp;</span>
285
+ <span class="cline-any cline-neutral">&nbsp;</span>
286
+ <span class="cline-any cline-neutral">&nbsp;</span>
287
+ <span class="cline-any cline-neutral">&nbsp;</span>
288
+ <span class="cline-any cline-neutral">&nbsp;</span>
289
+ <span class="cline-any cline-no">&nbsp;</span>
290
+ <span class="cline-any cline-no">&nbsp;</span>
291
+ <span class="cline-any cline-neutral">&nbsp;</span>
292
+ <span class="cline-any cline-neutral">&nbsp;</span>
293
+ <span class="cline-any cline-neutral">&nbsp;</span>
294
+ <span class="cline-any cline-neutral">&nbsp;</span>
295
+ <span class="cline-any cline-no">&nbsp;</span>
296
+ <span class="cline-any cline-no">&nbsp;</span>
297
+ <span class="cline-any cline-neutral">&nbsp;</span>
298
+ <span class="cline-any cline-no">&nbsp;</span>
299
+ <span class="cline-any cline-no">&nbsp;</span>
300
+ <span class="cline-any cline-no">&nbsp;</span>
301
+ <span class="cline-any cline-neutral">&nbsp;</span>
302
+ <span class="cline-any cline-no">&nbsp;</span>
303
+ <span class="cline-any cline-no">&nbsp;</span>
304
+ <span class="cline-any cline-neutral">&nbsp;</span>
305
+ <span class="cline-any cline-neutral">&nbsp;</span>
306
+ <span class="cline-any cline-no">&nbsp;</span>
307
+ <span class="cline-any cline-no">&nbsp;</span>
308
+ <span class="cline-any cline-neutral">&nbsp;</span>
309
+ <span class="cline-any cline-neutral">&nbsp;</span>
310
+ <span class="cline-any cline-no">&nbsp;</span>
311
+ <span class="cline-any cline-neutral">&nbsp;</span>
312
+ <span class="cline-any cline-neutral">&nbsp;</span>
313
+ <span class="cline-any cline-neutral">&nbsp;</span>
314
+ <span class="cline-any cline-no">&nbsp;</span>
315
+ <span class="cline-any cline-no">&nbsp;</span>
316
+ <span class="cline-any cline-neutral">&nbsp;</span>
317
+ <span class="cline-any cline-neutral">&nbsp;</span>
318
+ <span class="cline-any cline-neutral">&nbsp;</span>
319
+ <span class="cline-any cline-yes">1x</span>
320
+ <span class="cline-any cline-no">&nbsp;</span>
321
+ <span class="cline-any cline-no">&nbsp;</span>
322
+ <span class="cline-any cline-neutral">&nbsp;</span>
323
+ <span class="cline-any cline-yes">1x</span>
324
+ <span class="cline-any cline-neutral">&nbsp;</span>
325
+ <span class="cline-any cline-neutral">&nbsp;</span>
326
+ <span class="cline-any cline-neutral">&nbsp;</span>
327
+ <span class="cline-any cline-neutral">&nbsp;</span>
328
+ <span class="cline-any cline-neutral">&nbsp;</span>
329
+ <span class="cline-any cline-neutral">&nbsp;</span>
330
+ <span class="cline-any cline-neutral">&nbsp;</span>
331
+ <span class="cline-any cline-neutral">&nbsp;</span>
332
+ <span class="cline-any cline-neutral">&nbsp;</span>
333
+ <span class="cline-any cline-neutral">&nbsp;</span>
334
+ <span class="cline-any cline-neutral">&nbsp;</span>
335
+ <span class="cline-any cline-neutral">&nbsp;</span>
336
+ <span class="cline-any cline-yes">3x</span>
337
+ <span class="cline-any cline-neutral">&nbsp;</span>
338
+ <span class="cline-any cline-yes">1x</span>
339
+ <span class="cline-any cline-neutral">&nbsp;</span>
340
+ <span class="cline-any cline-yes">1x</span>
341
+ <span class="cline-any cline-neutral">&nbsp;</span>
342
+ <span class="cline-any cline-neutral">&nbsp;</span>
343
+ <span class="cline-any cline-neutral">&nbsp;</span>
344
+ <span class="cline-any cline-neutral">&nbsp;</span>
345
+ <span class="cline-any cline-yes">1x</span>
346
+ <span class="cline-any cline-neutral">&nbsp;</span>
347
+ <span class="cline-any cline-neutral">&nbsp;</span>
348
+ <span class="cline-any cline-neutral">&nbsp;</span>
349
+ <span class="cline-any cline-neutral">&nbsp;</span>
350
+ <span class="cline-any cline-neutral">&nbsp;</span>
351
+ <span class="cline-any cline-neutral">&nbsp;</span>
352
+ <span class="cline-any cline-neutral">&nbsp;</span>
353
+ <span class="cline-any cline-neutral">&nbsp;</span>
354
+ <span class="cline-any cline-yes">3x</span>
355
+ <span class="cline-any cline-yes">3x</span>
356
+ <span class="cline-any cline-neutral">&nbsp;</span>
357
+ <span class="cline-any cline-yes">3x</span>
358
+ <span class="cline-any cline-yes">1x</span>
359
+ <span class="cline-any cline-yes">1x</span>
360
+ <span class="cline-any cline-yes">1x</span>
361
+ <span class="cline-any cline-yes">1x</span>
362
+ <span class="cline-any cline-yes">1x</span>
363
+ <span class="cline-any cline-neutral">&nbsp;</span>
364
+ <span class="cline-any cline-yes">1x</span>
365
+ <span class="cline-any cline-neutral">&nbsp;</span>
366
+ <span class="cline-any cline-neutral">&nbsp;</span>
367
+ <span class="cline-any cline-yes">3x</span>
368
+ <span class="cline-any cline-neutral">&nbsp;</span>
369
+ <span class="cline-any cline-yes">7x</span>
370
+ <span class="cline-any cline-yes">5x</span>
371
+ <span class="cline-any cline-neutral">&nbsp;</span>
372
+ <span class="cline-any cline-yes">2x</span>
373
+ <span class="cline-any cline-yes">2x</span>
374
+ <span class="cline-any cline-yes">1x</span>
375
+ <span class="cline-any cline-neutral">&nbsp;</span>
376
+ <span class="cline-any cline-no">&nbsp;</span>
377
+ <span class="cline-any cline-neutral">&nbsp;</span>
378
+ <span class="cline-any cline-neutral">&nbsp;</span>
379
+ <span class="cline-any cline-neutral">&nbsp;</span>
380
+ <span class="cline-any cline-neutral">&nbsp;</span>
381
+ <span class="cline-any cline-neutral">&nbsp;</span>
382
+ <span class="cline-any cline-neutral">&nbsp;</span>
383
+ <span class="cline-any cline-neutral">&nbsp;</span>
384
+ <span class="cline-any cline-neutral">&nbsp;</span>
385
+ <span class="cline-any cline-neutral">&nbsp;</span>
386
+ <span class="cline-any cline-neutral">&nbsp;</span>
387
+ <span class="cline-any cline-yes">2x</span>
388
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">// ── JSON-RPC / MCP types ──────────────────────────────────────────────────────
389
+ &nbsp;
390
+ interface JsonRpcResponse {
391
+ jsonrpc: '2.0';
392
+ id?: number;
393
+ result?: unknown;
394
+ error?: { code: number; message: string };
395
+ }
396
+ &nbsp;
397
+ interface McpContent {
398
+ type: string;
399
+ text?: string;
400
+ isError?: boolean;
401
+ }
402
+ &nbsp;
403
+ interface McpToolResult {
404
+ content: McpContent[];
405
+ isError?: boolean;
406
+ }
407
+ &nbsp;
408
+ // ── McpClient interface ───────────────────────────────────────────────────────
409
+ &nbsp;
410
+ /**
411
+ * Abstraction over MCP transport mechanisms (stdio, remote HTTP).
412
+ * Implementations must be safe for concurrent `callTool()` invocations.
413
+ */
414
+ export interface McpClient {
415
+ /** Call a named MCP tool with the given arguments, scoped to `cwd`. Returns formatted text. */
416
+ callTool(name: string, args: Record&lt;string, unknown&gt;, cwd: string): Promise&lt;string&gt;;
417
+ /** Terminate any open connections / processes. Idempotent. */
418
+ stop(): void;
419
+ }
420
+ &nbsp;
421
+ // ── Error helper ──────────────────────────────────────────────────────────────
422
+ &nbsp;
423
+ /** Create a consistently-prefixed error from an unknown value. */
424
+ export function createMcpError(error: unknown, fallback = 'GitNexus MCP request failed.'): Error {
425
+ const message = error instanceof Error ? error.message : typeof error === 'string' ? error : fallback;
426
+ return new Error(`[GitNexus] ${message || fallback}`);
427
+ }
428
+ &nbsp;
429
+ // ── Re-exports (lazy — avoids circular dependency) ─────────────────────────────
430
+ export { StdioMcpClient } from './mcp-client-stdio';
431
+ &nbsp;
432
+ // ── AutoMcpClient ─────────────────────────────────────────────────────────────
433
+ &nbsp;
434
+ import type { McpMode } from './gitnexus';
435
+ import { RemoteMcpClient } from './remote-mcp-client';
436
+ &nbsp;
437
+ /**
438
+ * Auto-detecting MCP client that probes the local binary on first use.
439
+ * Falls back to remote HTTP if the local binary fails.
440
+ * Once selected, the chosen transport is cached for the session.
441
+ */
442
+ export class AutoMcpClient implements McpClient {
443
+ private delegate: McpClient | null = null;
444
+ private probePromise: Promise&lt;McpClient&gt; | null = null;
445
+ &nbsp;
446
+ /**
447
+ * Probe the local gitnexus binary. Returns true if it responds to --version.
448
+ */
449
+ static async probeLocalBinary(): Promise&lt;boolean&gt; {
450
+ const { StdioMcpClient } = <span class="cstat-no" title="statement not covered" >await import('./mcp-client-stdio');</span>
451
+ <span class="cstat-no" title="statement not covered" > return StdioMcpClient.probeLocalBinary();</span>
452
+ }
453
+ &nbsp;
454
+ /** Resolve the transport. Probes local binary once, then caches the result. */
455
+ private async <span class="fstat-no" title="function not covered" >resolveClient(): Promise&lt;McpClient&gt; {</span>
456
+ <span class="cstat-no" title="statement not covered" > if (this.delegate) <span class="cstat-no" title="statement not covered" >return this.delegate;</span></span>
457
+ <span class="cstat-no" title="statement not covered" > if (this.probePromise) <span class="cstat-no" title="statement not covered" >return this.probePromise;</span></span>
458
+ &nbsp;
459
+ <span class="cstat-no" title="statement not covered" > this.probePromise = (<span class="fstat-no" title="function not covered" >async () =&gt; {</span></span>
460
+ const { McpClientFactory } = <span class="cstat-no" title="statement not covered" >await import('./mcp-client-factory');</span>
461
+ const { serverUrl } = <span class="cstat-no" title="statement not covered" >McpClientFactory.loadConfig();</span>
462
+ &nbsp;
463
+ const localWorks = <span class="cstat-no" title="statement not covered" >await AutoMcpClient.probeLocalBinary();</span>
464
+ const client = <span class="cstat-no" title="statement not covered" >localWorks</span>
465
+ ? await McpClientFactory.createClient({ mode: 'local' })
466
+ : new RemoteMcpClient({ serverUrl: serverUrl! });
467
+ <span class="cstat-no" title="statement not covered" > this.delegate = client;</span>
468
+ <span class="cstat-no" title="statement not covered" > return client;</span>
469
+ })();
470
+ &nbsp;
471
+ <span class="cstat-no" title="statement not covered" > return this.probePromise;</span>
472
+ }
473
+ &nbsp;
474
+ async <span class="fstat-no" title="function not covered" >callTool(n</span>ame: string, args: Record&lt;string, unknown&gt;, cwd: string): Promise&lt;string&gt; {
475
+ const client = <span class="cstat-no" title="statement not covered" >await this.resolveClient();</span>
476
+ <span class="cstat-no" title="statement not covered" > return client.callTool(name, args, cwd);</span>
477
+ }
478
+ &nbsp;
479
+ stop(): void {
480
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (this.delegate) {
481
+ <span class="cstat-no" title="statement not covered" > this.delegate.stop();</span>
482
+ <span class="cstat-no" title="statement not covered" > this.delegate = null;</span>
483
+ }
484
+ this.probePromise = null;
485
+ }
486
+ }
487
+ &nbsp;
488
+ // ── Factory ───────────────────────────────────────────────────────────────────
489
+ &nbsp;
490
+ /**
491
+ * Create an McpClient based on the configured mode.
492
+ *
493
+ * @param mode - Transport mode from config.
494
+ * @param serverUrl - Remote server URL (required for 'remote', optional for 'auto').
495
+ */
496
+ export function createMcpClient(mode: McpMode, serverUrl: string): McpClient {
497
+ switch (mode) {
498
+ case 'remote':
499
+ return new RemoteMcpClient({ serverUrl });
500
+ case 'auto':
501
+ return new AutoMcpClient();
502
+ default:
503
+ // Return a lazy proxy that defers StdioMcpClient instantiation.
504
+ // This avoids circular dependency: mcp-client-stdio imports from this module,
505
+ // so we can't eagerly import it here.
506
+ return createLazyStdioClient();
507
+ }
508
+ }
509
+ &nbsp;
510
+ /**
511
+ * Create a lazy proxy McpClient that defers StdioMcpClient instantiation
512
+ * until the first method call. Avoids circular dependency issues.
513
+ */
514
+ function createLazyStdioClient(): McpClient {
515
+ let _instance: McpClient | null = null;
516
+ let _pending: Promise&lt;McpClient&gt; | null = null;
517
+ &nbsp;
518
+ const getInstance = async (): Promise&lt;McpClient&gt; =&gt; {
519
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (_instance) <span class="cstat-no" title="statement not covered" >return _instance;</span>
520
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (_pending) <span class="cstat-no" title="statement not covered" >return _pending;</span>
521
+ _pending = import('./mcp-client-stdio').then((mod) =&gt; {
522
+ _instance = new mod.StdioMcpClient();
523
+ return _instance;
524
+ });
525
+ return _pending;
526
+ };
527
+ &nbsp;
528
+ return new Proxy({} as McpClient, {
529
+ get(_, prop) {
530
+ if (prop === 'stop') {
531
+ return () =&gt; { _instance?.stop(); };
532
+ }
533
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (prop === 'callTool') {
534
+ return (name: string, args: Record&lt;string, unknown&gt;, cwd: string) =&gt;
535
+ getInstance().then((c) =&gt; c.callTool(name, args, cwd));
536
+ }
537
+ <span class="cstat-no" title="statement not covered" > return undefined;</span>
538
+ },
539
+ });
540
+ }
541
+ &nbsp;
542
+ // ── Singleton (backward-compatible export) ────────────────────────────────────
543
+ &nbsp;
544
+ /**
545
+ * Legacy singleton MCP client instance using stdio transport.
546
+ * Uses a lazy proxy to avoid circular dependency issues at module load time.
547
+ */
548
+ export const mcpClient: McpClient = createLazyStdioClient();
549
+ &nbsp;</pre></td></tr></table></pre>
550
+
551
+ <div class='push'></div><!-- for sticky footer -->
552
+ </div><!-- /wrapper -->
553
+ <div class='footer quiet pad2 space-top1 center small'>
554
+ Code coverage generated by
555
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
556
+ at 2026-05-03T18:51:43.670Z
557
+ </div>
558
+ <script src="../prettify.js"></script>
559
+ <script>
560
+ window.onload = function () {
561
+ prettyPrint();
562
+ };
563
+ </script>
564
+ <script src="../sorter.js"></script>
565
+ <script src="../block-navigation.js"></script>
566
+ </body>
567
+ </html>
568
+