a2acalling 0.6.73 → 0.6.75

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 (134) hide show
  1. package/.a2a-manifest.json +2 -2
  2. package/.c8rc.json +16 -0
  3. package/.node-version +1 -0
  4. package/.serena/project.yml +126 -0
  5. package/ARCHITECTURE.md +40 -16
  6. package/CONVENTIONS.md +39 -6
  7. package/biome.json +27 -0
  8. package/coverage/base.css +224 -0
  9. package/coverage/block-navigation.js +87 -0
  10. package/coverage/favicon.png +0 -0
  11. package/coverage/index.html +146 -0
  12. package/coverage/prettify.css +1 -0
  13. package/coverage/prettify.js +2 -0
  14. package/coverage/sort-arrow-sprite.png +0 -0
  15. package/coverage/sorter.js +210 -0
  16. package/coverage/src/index.html +131 -0
  17. package/coverage/src/index.js.html +313 -0
  18. package/coverage/src/lib/agent-card.js.html +418 -0
  19. package/coverage/src/lib/call-monitor.js.html +700 -0
  20. package/coverage/src/lib/callbook.js.html +1183 -0
  21. package/coverage/src/lib/claude-subagent.js.html +2173 -0
  22. package/coverage/src/lib/client.js.html +2134 -0
  23. package/coverage/src/lib/config.js.html +1525 -0
  24. package/coverage/src/lib/conversation-driver.js.html +1909 -0
  25. package/coverage/src/lib/conversations.js.html +2575 -0
  26. package/coverage/src/lib/crypto.js.html +424 -0
  27. package/coverage/src/lib/dashboard-events.js.html +724 -0
  28. package/coverage/src/lib/disclosure.js.html +2461 -0
  29. package/coverage/src/lib/external-ip.js.html +718 -0
  30. package/coverage/src/lib/index.html +506 -0
  31. package/coverage/src/lib/invite-host.js.html +754 -0
  32. package/coverage/src/lib/local-request.js.html +292 -0
  33. package/coverage/src/lib/logger.js.html +2116 -0
  34. package/coverage/src/lib/openclaw-integration.js.html +1102 -0
  35. package/coverage/src/lib/pid-file.js.html +394 -0
  36. package/coverage/src/lib/port-scanner.js.html +334 -0
  37. package/coverage/src/lib/prompt-template.js.html +1150 -0
  38. package/coverage/src/lib/runtime-adapter.js.html +2188 -0
  39. package/coverage/src/lib/summarizer.js.html +553 -0
  40. package/coverage/src/lib/summary-formatter.js.html +589 -0
  41. package/coverage/src/lib/summary-prompt.js.html +694 -0
  42. package/coverage/src/lib/tokens.js.html +2689 -0
  43. package/coverage/src/lib/turn-timeout.js.html +241 -0
  44. package/coverage/src/lib/update-checker.js.html +364 -0
  45. package/coverage/src/lib/update-manager.js.html +1024 -0
  46. package/coverage/src/routes/a2a.js.html +3724 -0
  47. package/coverage/src/routes/callbook.js.html +511 -0
  48. package/coverage/src/routes/dashboard.js.html +4819 -0
  49. package/coverage/src/routes/index.html +146 -0
  50. package/coverage/src/server.js.html +3622 -0
  51. package/coverage/tmp/coverage-1605378-1772576706365-0.json +1 -0
  52. package/coverage/tmp/coverage-1605384-1772576607459-0.json +1 -0
  53. package/coverage/tmp/coverage-1605410-1772576631155-0.json +1 -0
  54. package/coverage/tmp/coverage-1606942-1772576636869-0.json +1 -0
  55. package/coverage/tmp/coverage-1607004-1772576637454-0.json +1 -0
  56. package/coverage/tmp/coverage-1607044-1772576637876-0.json +1 -0
  57. package/coverage/tmp/coverage-1607096-1772576638356-0.json +1 -0
  58. package/coverage/tmp/coverage-1607145-1772576638777-0.json +1 -0
  59. package/coverage/tmp/coverage-1607201-1772576639277-0.json +1 -0
  60. package/coverage/tmp/coverage-1607247-1772576639755-0.json +1 -0
  61. package/coverage/tmp/coverage-1607317-1772576640083-0.json +1 -0
  62. package/coverage/tmp/coverage-1607381-1772576640465-0.json +1 -0
  63. package/coverage/tmp/coverage-1607446-1772576640868-0.json +1 -0
  64. package/coverage/tmp/coverage-1607501-1772576641662-0.json +1 -0
  65. package/coverage/tmp/coverage-1607534-1772576641565-0.json +1 -0
  66. package/coverage/tmp/coverage-1607627-1772576641871-0.json +1 -0
  67. package/coverage/tmp/coverage-1607665-1772576642172-0.json +1 -0
  68. package/coverage/tmp/coverage-1607714-1772576642577-0.json +1 -0
  69. package/coverage/tmp/coverage-1607788-1772576643466-0.json +1 -0
  70. package/coverage/tmp/coverage-1607924-1772576644678-0.json +1 -0
  71. package/coverage/tmp/coverage-1607978-1772576645154-0.json +1 -0
  72. package/coverage/tmp/coverage-1608035-1772576645564-0.json +1 -0
  73. package/coverage/tmp/coverage-1608106-1772576645967-0.json +1 -0
  74. package/coverage/tmp/coverage-1608179-1772576648656-0.json +1 -0
  75. package/coverage/tmp/coverage-1608196-1772576647367-0.json +1 -0
  76. package/coverage/tmp/coverage-1608217-1772576648557-0.json +1 -0
  77. package/coverage/tmp/coverage-1608256-1772576651378-0.json +1 -0
  78. package/coverage/tmp/coverage-1608265-1772576650058-0.json +1 -0
  79. package/coverage/tmp/coverage-1608289-1772576651358-0.json +1 -0
  80. package/coverage/tmp/coverage-1608591-1772576660465-0.json +1 -0
  81. package/coverage/tmp/coverage-1608648-1772576659272-0.json +1 -0
  82. package/coverage/tmp/coverage-1608665-1772576660374-0.json +1 -0
  83. package/coverage/tmp/coverage-1608677-1772576661268-0.json +1 -0
  84. package/coverage/tmp/coverage-1608684-1772576663968-0.json +1 -0
  85. package/coverage/tmp/coverage-1608692-1772576662575-0.json +1 -0
  86. package/coverage/tmp/coverage-1608701-1772576663873-0.json +1 -0
  87. package/coverage/tmp/coverage-1608718-1772576666674-0.json +1 -0
  88. package/coverage/tmp/coverage-1608725-1772576665463-0.json +1 -0
  89. package/coverage/tmp/coverage-1608738-1772576666577-0.json +1 -0
  90. package/coverage/tmp/coverage-1608753-1772576669664-0.json +1 -0
  91. package/coverage/tmp/coverage-1608763-1772576668275-0.json +1 -0
  92. package/coverage/tmp/coverage-1608771-1772576669563-0.json +1 -0
  93. package/coverage/tmp/coverage-1608828-1772576676574-0.json +1 -0
  94. package/coverage/tmp/coverage-1609244-1772576675272-0.json +1 -0
  95. package/coverage/tmp/coverage-1609342-1772576676478-0.json +1 -0
  96. package/coverage/tmp/coverage-1609450-1772576686954-0.json +1 -0
  97. package/coverage/tmp/coverage-1609841-1772576685466-0.json +1 -0
  98. package/coverage/tmp/coverage-1609925-1772576686855-0.json +1 -0
  99. package/coverage/tmp/coverage-1610399-1772576692469-0.json +1 -0
  100. package/coverage/tmp/coverage-1611283-1772576703062-0.json +1 -0
  101. package/coverage/tmp/coverage-1611294-1772576703755-0.json +1 -0
  102. package/docs/assessments/2026-02-27-google-a2a-protocol-assessment.md +292 -0
  103. package/docs/plans/2026-03-01-a2a-68-openclaw-integration-tests.md +676 -0
  104. package/docs/plans/2026-03-01-a2a-77-invoke-security-tests.md +661 -0
  105. package/docs/plans/2026-03-03-a2a-91-macos-packaging-plan.md +144 -0
  106. package/docs/signing-setup.md +49 -0
  107. package/eslint.config.js +16 -0
  108. package/knip.json +17 -0
  109. package/native/macos/certs/appldevcert.cer +0 -0
  110. package/native/macos/src-tauri/binaries/.gitkeep +0 -0
  111. package/native/macos/src-tauri/capabilities/default.json +11 -1
  112. package/native/macos/src-tauri/entitlements.plist +14 -0
  113. package/native/macos/src-tauri/src/discovery.rs +14 -3
  114. package/native/macos/src-tauri/src/health.rs +4 -0
  115. package/native/macos/src-tauri/src/lib.rs +52 -11
  116. package/native/macos/src-tauri/src/server.rs +262 -26
  117. package/native/macos/src-tauri/tauri.conf.json +13 -4
  118. package/package.json +16 -2
  119. package/pkg.config.json +14 -0
  120. package/scripts/build-standalone.sh +106 -0
  121. package/scripts/install-openclaw.js +3 -5
  122. package/scripts/smoke-test-standalone.sh +101 -0
  123. package/scripts/sync-version.sh +28 -0
  124. package/scripts/verify-app-bundle.sh +34 -0
  125. package/src/lib/agent-card.js +111 -0
  126. package/src/lib/client.js +290 -49
  127. package/src/lib/conversations.js +2 -0
  128. package/src/lib/local-request.js +69 -0
  129. package/src/lib/logger.js +2 -0
  130. package/src/lib/runtime-adapter.js +41 -1
  131. package/src/routes/a2a.js +393 -66
  132. package/src/routes/dashboard.js +1 -27
  133. package/src/server.js +19 -0
  134. package/.maestro/inbox/release-workflow-spam.md +0 -25
@@ -0,0 +1,2134 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/lib/client.js</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/lib</a> client.js</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">93.11% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>636/683</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">78.28% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>137/175</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">100% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>24/24</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">93.11% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>636/683</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 high'></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>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a>
525
+ <a name='L460'></a><a href='#L460'>460</a>
526
+ <a name='L461'></a><a href='#L461'>461</a>
527
+ <a name='L462'></a><a href='#L462'>462</a>
528
+ <a name='L463'></a><a href='#L463'>463</a>
529
+ <a name='L464'></a><a href='#L464'>464</a>
530
+ <a name='L465'></a><a href='#L465'>465</a>
531
+ <a name='L466'></a><a href='#L466'>466</a>
532
+ <a name='L467'></a><a href='#L467'>467</a>
533
+ <a name='L468'></a><a href='#L468'>468</a>
534
+ <a name='L469'></a><a href='#L469'>469</a>
535
+ <a name='L470'></a><a href='#L470'>470</a>
536
+ <a name='L471'></a><a href='#L471'>471</a>
537
+ <a name='L472'></a><a href='#L472'>472</a>
538
+ <a name='L473'></a><a href='#L473'>473</a>
539
+ <a name='L474'></a><a href='#L474'>474</a>
540
+ <a name='L475'></a><a href='#L475'>475</a>
541
+ <a name='L476'></a><a href='#L476'>476</a>
542
+ <a name='L477'></a><a href='#L477'>477</a>
543
+ <a name='L478'></a><a href='#L478'>478</a>
544
+ <a name='L479'></a><a href='#L479'>479</a>
545
+ <a name='L480'></a><a href='#L480'>480</a>
546
+ <a name='L481'></a><a href='#L481'>481</a>
547
+ <a name='L482'></a><a href='#L482'>482</a>
548
+ <a name='L483'></a><a href='#L483'>483</a>
549
+ <a name='L484'></a><a href='#L484'>484</a>
550
+ <a name='L485'></a><a href='#L485'>485</a>
551
+ <a name='L486'></a><a href='#L486'>486</a>
552
+ <a name='L487'></a><a href='#L487'>487</a>
553
+ <a name='L488'></a><a href='#L488'>488</a>
554
+ <a name='L489'></a><a href='#L489'>489</a>
555
+ <a name='L490'></a><a href='#L490'>490</a>
556
+ <a name='L491'></a><a href='#L491'>491</a>
557
+ <a name='L492'></a><a href='#L492'>492</a>
558
+ <a name='L493'></a><a href='#L493'>493</a>
559
+ <a name='L494'></a><a href='#L494'>494</a>
560
+ <a name='L495'></a><a href='#L495'>495</a>
561
+ <a name='L496'></a><a href='#L496'>496</a>
562
+ <a name='L497'></a><a href='#L497'>497</a>
563
+ <a name='L498'></a><a href='#L498'>498</a>
564
+ <a name='L499'></a><a href='#L499'>499</a>
565
+ <a name='L500'></a><a href='#L500'>500</a>
566
+ <a name='L501'></a><a href='#L501'>501</a>
567
+ <a name='L502'></a><a href='#L502'>502</a>
568
+ <a name='L503'></a><a href='#L503'>503</a>
569
+ <a name='L504'></a><a href='#L504'>504</a>
570
+ <a name='L505'></a><a href='#L505'>505</a>
571
+ <a name='L506'></a><a href='#L506'>506</a>
572
+ <a name='L507'></a><a href='#L507'>507</a>
573
+ <a name='L508'></a><a href='#L508'>508</a>
574
+ <a name='L509'></a><a href='#L509'>509</a>
575
+ <a name='L510'></a><a href='#L510'>510</a>
576
+ <a name='L511'></a><a href='#L511'>511</a>
577
+ <a name='L512'></a><a href='#L512'>512</a>
578
+ <a name='L513'></a><a href='#L513'>513</a>
579
+ <a name='L514'></a><a href='#L514'>514</a>
580
+ <a name='L515'></a><a href='#L515'>515</a>
581
+ <a name='L516'></a><a href='#L516'>516</a>
582
+ <a name='L517'></a><a href='#L517'>517</a>
583
+ <a name='L518'></a><a href='#L518'>518</a>
584
+ <a name='L519'></a><a href='#L519'>519</a>
585
+ <a name='L520'></a><a href='#L520'>520</a>
586
+ <a name='L521'></a><a href='#L521'>521</a>
587
+ <a name='L522'></a><a href='#L522'>522</a>
588
+ <a name='L523'></a><a href='#L523'>523</a>
589
+ <a name='L524'></a><a href='#L524'>524</a>
590
+ <a name='L525'></a><a href='#L525'>525</a>
591
+ <a name='L526'></a><a href='#L526'>526</a>
592
+ <a name='L527'></a><a href='#L527'>527</a>
593
+ <a name='L528'></a><a href='#L528'>528</a>
594
+ <a name='L529'></a><a href='#L529'>529</a>
595
+ <a name='L530'></a><a href='#L530'>530</a>
596
+ <a name='L531'></a><a href='#L531'>531</a>
597
+ <a name='L532'></a><a href='#L532'>532</a>
598
+ <a name='L533'></a><a href='#L533'>533</a>
599
+ <a name='L534'></a><a href='#L534'>534</a>
600
+ <a name='L535'></a><a href='#L535'>535</a>
601
+ <a name='L536'></a><a href='#L536'>536</a>
602
+ <a name='L537'></a><a href='#L537'>537</a>
603
+ <a name='L538'></a><a href='#L538'>538</a>
604
+ <a name='L539'></a><a href='#L539'>539</a>
605
+ <a name='L540'></a><a href='#L540'>540</a>
606
+ <a name='L541'></a><a href='#L541'>541</a>
607
+ <a name='L542'></a><a href='#L542'>542</a>
608
+ <a name='L543'></a><a href='#L543'>543</a>
609
+ <a name='L544'></a><a href='#L544'>544</a>
610
+ <a name='L545'></a><a href='#L545'>545</a>
611
+ <a name='L546'></a><a href='#L546'>546</a>
612
+ <a name='L547'></a><a href='#L547'>547</a>
613
+ <a name='L548'></a><a href='#L548'>548</a>
614
+ <a name='L549'></a><a href='#L549'>549</a>
615
+ <a name='L550'></a><a href='#L550'>550</a>
616
+ <a name='L551'></a><a href='#L551'>551</a>
617
+ <a name='L552'></a><a href='#L552'>552</a>
618
+ <a name='L553'></a><a href='#L553'>553</a>
619
+ <a name='L554'></a><a href='#L554'>554</a>
620
+ <a name='L555'></a><a href='#L555'>555</a>
621
+ <a name='L556'></a><a href='#L556'>556</a>
622
+ <a name='L557'></a><a href='#L557'>557</a>
623
+ <a name='L558'></a><a href='#L558'>558</a>
624
+ <a name='L559'></a><a href='#L559'>559</a>
625
+ <a name='L560'></a><a href='#L560'>560</a>
626
+ <a name='L561'></a><a href='#L561'>561</a>
627
+ <a name='L562'></a><a href='#L562'>562</a>
628
+ <a name='L563'></a><a href='#L563'>563</a>
629
+ <a name='L564'></a><a href='#L564'>564</a>
630
+ <a name='L565'></a><a href='#L565'>565</a>
631
+ <a name='L566'></a><a href='#L566'>566</a>
632
+ <a name='L567'></a><a href='#L567'>567</a>
633
+ <a name='L568'></a><a href='#L568'>568</a>
634
+ <a name='L569'></a><a href='#L569'>569</a>
635
+ <a name='L570'></a><a href='#L570'>570</a>
636
+ <a name='L571'></a><a href='#L571'>571</a>
637
+ <a name='L572'></a><a href='#L572'>572</a>
638
+ <a name='L573'></a><a href='#L573'>573</a>
639
+ <a name='L574'></a><a href='#L574'>574</a>
640
+ <a name='L575'></a><a href='#L575'>575</a>
641
+ <a name='L576'></a><a href='#L576'>576</a>
642
+ <a name='L577'></a><a href='#L577'>577</a>
643
+ <a name='L578'></a><a href='#L578'>578</a>
644
+ <a name='L579'></a><a href='#L579'>579</a>
645
+ <a name='L580'></a><a href='#L580'>580</a>
646
+ <a name='L581'></a><a href='#L581'>581</a>
647
+ <a name='L582'></a><a href='#L582'>582</a>
648
+ <a name='L583'></a><a href='#L583'>583</a>
649
+ <a name='L584'></a><a href='#L584'>584</a>
650
+ <a name='L585'></a><a href='#L585'>585</a>
651
+ <a name='L586'></a><a href='#L586'>586</a>
652
+ <a name='L587'></a><a href='#L587'>587</a>
653
+ <a name='L588'></a><a href='#L588'>588</a>
654
+ <a name='L589'></a><a href='#L589'>589</a>
655
+ <a name='L590'></a><a href='#L590'>590</a>
656
+ <a name='L591'></a><a href='#L591'>591</a>
657
+ <a name='L592'></a><a href='#L592'>592</a>
658
+ <a name='L593'></a><a href='#L593'>593</a>
659
+ <a name='L594'></a><a href='#L594'>594</a>
660
+ <a name='L595'></a><a href='#L595'>595</a>
661
+ <a name='L596'></a><a href='#L596'>596</a>
662
+ <a name='L597'></a><a href='#L597'>597</a>
663
+ <a name='L598'></a><a href='#L598'>598</a>
664
+ <a name='L599'></a><a href='#L599'>599</a>
665
+ <a name='L600'></a><a href='#L600'>600</a>
666
+ <a name='L601'></a><a href='#L601'>601</a>
667
+ <a name='L602'></a><a href='#L602'>602</a>
668
+ <a name='L603'></a><a href='#L603'>603</a>
669
+ <a name='L604'></a><a href='#L604'>604</a>
670
+ <a name='L605'></a><a href='#L605'>605</a>
671
+ <a name='L606'></a><a href='#L606'>606</a>
672
+ <a name='L607'></a><a href='#L607'>607</a>
673
+ <a name='L608'></a><a href='#L608'>608</a>
674
+ <a name='L609'></a><a href='#L609'>609</a>
675
+ <a name='L610'></a><a href='#L610'>610</a>
676
+ <a name='L611'></a><a href='#L611'>611</a>
677
+ <a name='L612'></a><a href='#L612'>612</a>
678
+ <a name='L613'></a><a href='#L613'>613</a>
679
+ <a name='L614'></a><a href='#L614'>614</a>
680
+ <a name='L615'></a><a href='#L615'>615</a>
681
+ <a name='L616'></a><a href='#L616'>616</a>
682
+ <a name='L617'></a><a href='#L617'>617</a>
683
+ <a name='L618'></a><a href='#L618'>618</a>
684
+ <a name='L619'></a><a href='#L619'>619</a>
685
+ <a name='L620'></a><a href='#L620'>620</a>
686
+ <a name='L621'></a><a href='#L621'>621</a>
687
+ <a name='L622'></a><a href='#L622'>622</a>
688
+ <a name='L623'></a><a href='#L623'>623</a>
689
+ <a name='L624'></a><a href='#L624'>624</a>
690
+ <a name='L625'></a><a href='#L625'>625</a>
691
+ <a name='L626'></a><a href='#L626'>626</a>
692
+ <a name='L627'></a><a href='#L627'>627</a>
693
+ <a name='L628'></a><a href='#L628'>628</a>
694
+ <a name='L629'></a><a href='#L629'>629</a>
695
+ <a name='L630'></a><a href='#L630'>630</a>
696
+ <a name='L631'></a><a href='#L631'>631</a>
697
+ <a name='L632'></a><a href='#L632'>632</a>
698
+ <a name='L633'></a><a href='#L633'>633</a>
699
+ <a name='L634'></a><a href='#L634'>634</a>
700
+ <a name='L635'></a><a href='#L635'>635</a>
701
+ <a name='L636'></a><a href='#L636'>636</a>
702
+ <a name='L637'></a><a href='#L637'>637</a>
703
+ <a name='L638'></a><a href='#L638'>638</a>
704
+ <a name='L639'></a><a href='#L639'>639</a>
705
+ <a name='L640'></a><a href='#L640'>640</a>
706
+ <a name='L641'></a><a href='#L641'>641</a>
707
+ <a name='L642'></a><a href='#L642'>642</a>
708
+ <a name='L643'></a><a href='#L643'>643</a>
709
+ <a name='L644'></a><a href='#L644'>644</a>
710
+ <a name='L645'></a><a href='#L645'>645</a>
711
+ <a name='L646'></a><a href='#L646'>646</a>
712
+ <a name='L647'></a><a href='#L647'>647</a>
713
+ <a name='L648'></a><a href='#L648'>648</a>
714
+ <a name='L649'></a><a href='#L649'>649</a>
715
+ <a name='L650'></a><a href='#L650'>650</a>
716
+ <a name='L651'></a><a href='#L651'>651</a>
717
+ <a name='L652'></a><a href='#L652'>652</a>
718
+ <a name='L653'></a><a href='#L653'>653</a>
719
+ <a name='L654'></a><a href='#L654'>654</a>
720
+ <a name='L655'></a><a href='#L655'>655</a>
721
+ <a name='L656'></a><a href='#L656'>656</a>
722
+ <a name='L657'></a><a href='#L657'>657</a>
723
+ <a name='L658'></a><a href='#L658'>658</a>
724
+ <a name='L659'></a><a href='#L659'>659</a>
725
+ <a name='L660'></a><a href='#L660'>660</a>
726
+ <a name='L661'></a><a href='#L661'>661</a>
727
+ <a name='L662'></a><a href='#L662'>662</a>
728
+ <a name='L663'></a><a href='#L663'>663</a>
729
+ <a name='L664'></a><a href='#L664'>664</a>
730
+ <a name='L665'></a><a href='#L665'>665</a>
731
+ <a name='L666'></a><a href='#L666'>666</a>
732
+ <a name='L667'></a><a href='#L667'>667</a>
733
+ <a name='L668'></a><a href='#L668'>668</a>
734
+ <a name='L669'></a><a href='#L669'>669</a>
735
+ <a name='L670'></a><a href='#L670'>670</a>
736
+ <a name='L671'></a><a href='#L671'>671</a>
737
+ <a name='L672'></a><a href='#L672'>672</a>
738
+ <a name='L673'></a><a href='#L673'>673</a>
739
+ <a name='L674'></a><a href='#L674'>674</a>
740
+ <a name='L675'></a><a href='#L675'>675</a>
741
+ <a name='L676'></a><a href='#L676'>676</a>
742
+ <a name='L677'></a><a href='#L677'>677</a>
743
+ <a name='L678'></a><a href='#L678'>678</a>
744
+ <a name='L679'></a><a href='#L679'>679</a>
745
+ <a name='L680'></a><a href='#L680'>680</a>
746
+ <a name='L681'></a><a href='#L681'>681</a>
747
+ <a name='L682'></a><a href='#L682'>682</a>
748
+ <a name='L683'></a><a href='#L683'>683</a>
749
+ <a name='L684'></a><a href='#L684'>684</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">117x</span>
750
+ <span class="cline-any cline-yes">117x</span>
751
+ <span class="cline-any cline-yes">117x</span>
752
+ <span class="cline-any cline-yes">117x</span>
753
+ <span class="cline-any cline-yes">117x</span>
754
+ <span class="cline-any cline-yes">117x</span>
755
+ <span class="cline-any cline-yes">117x</span>
756
+ <span class="cline-any cline-yes">117x</span>
757
+ <span class="cline-any cline-yes">117x</span>
758
+ <span class="cline-any cline-yes">117x</span>
759
+ <span class="cline-any cline-yes">117x</span>
760
+ <span class="cline-any cline-yes">117x</span>
761
+ <span class="cline-any cline-yes">117x</span>
762
+ <span class="cline-any cline-yes">117x</span>
763
+ <span class="cline-any cline-yes">117x</span>
764
+ <span class="cline-any cline-yes">117x</span>
765
+ <span class="cline-any cline-yes">117x</span>
766
+ <span class="cline-any cline-yes">117x</span>
767
+ <span class="cline-any cline-yes">117x</span>
768
+ <span class="cline-any cline-yes">117x</span>
769
+ <span class="cline-any cline-yes">117x</span>
770
+ <span class="cline-any cline-yes">117x</span>
771
+ <span class="cline-any cline-yes">117x</span>
772
+ <span class="cline-any cline-yes">117x</span>
773
+ <span class="cline-any cline-yes">117x</span>
774
+ <span class="cline-any cline-yes">117x</span>
775
+ <span class="cline-any cline-yes">234x</span>
776
+ <span class="cline-any cline-yes">234x</span>
777
+ <span class="cline-any cline-yes">234x</span>
778
+ <span class="cline-any cline-no">&nbsp;</span>
779
+ <span class="cline-any cline-yes">234x</span>
780
+ <span class="cline-any cline-yes">234x</span>
781
+ <span class="cline-any cline-yes">117x</span>
782
+ <span class="cline-any cline-yes">117x</span>
783
+ <span class="cline-any cline-yes">117x</span>
784
+ <span class="cline-any cline-yes">117x</span>
785
+ <span class="cline-any cline-yes">117x</span>
786
+ <span class="cline-any cline-yes">117x</span>
787
+ <span class="cline-any cline-yes">36x</span>
788
+ <span class="cline-any cline-yes">36x</span>
789
+ <span class="cline-any cline-yes">36x</span>
790
+ <span class="cline-any cline-yes">27x</span>
791
+ <span class="cline-any cline-no">&nbsp;</span>
792
+ <span class="cline-any cline-no">&nbsp;</span>
793
+ <span class="cline-any cline-yes">27x</span>
794
+ <span class="cline-any cline-yes">36x</span>
795
+ <span class="cline-any cline-yes">36x</span>
796
+ <span class="cline-any cline-yes">36x</span>
797
+ <span class="cline-any cline-yes">36x</span>
798
+ <span class="cline-any cline-no">&nbsp;</span>
799
+ <span class="cline-any cline-no">&nbsp;</span>
800
+ <span class="cline-any cline-no">&nbsp;</span>
801
+ <span class="cline-any cline-no">&nbsp;</span>
802
+ <span class="cline-any cline-no">&nbsp;</span>
803
+ <span class="cline-any cline-no">&nbsp;</span>
804
+ <span class="cline-any cline-no">&nbsp;</span>
805
+ <span class="cline-any cline-yes">36x</span>
806
+ <span class="cline-any cline-yes">117x</span>
807
+ <span class="cline-any cline-yes">117x</span>
808
+ <span class="cline-any cline-yes">36x</span>
809
+ <span class="cline-any cline-yes">36x</span>
810
+ <span class="cline-any cline-yes">36x</span>
811
+ <span class="cline-any cline-yes">36x</span>
812
+ <span class="cline-any cline-yes">36x</span>
813
+ <span class="cline-any cline-yes">36x</span>
814
+ <span class="cline-any cline-yes">117x</span>
815
+ <span class="cline-any cline-yes">117x</span>
816
+ <span class="cline-any cline-yes">16x</span>
817
+ <span class="cline-any cline-yes">16x</span>
818
+ <span class="cline-any cline-yes">16x</span>
819
+ <span class="cline-any cline-yes">11x</span>
820
+ <span class="cline-any cline-yes">11x</span>
821
+ <span class="cline-any cline-yes">11x</span>
822
+ <span class="cline-any cline-yes">11x</span>
823
+ <span class="cline-any cline-yes">16x</span>
824
+ <span class="cline-any cline-yes">9x</span>
825
+ <span class="cline-any cline-yes">9x</span>
826
+ <span class="cline-any cline-yes">16x</span>
827
+ <span class="cline-any cline-yes">117x</span>
828
+ <span class="cline-any cline-yes">117x</span>
829
+ <span class="cline-any cline-yes">117x</span>
830
+ <span class="cline-any cline-yes">36x</span>
831
+ <span class="cline-any cline-yes">36x</span>
832
+ <span class="cline-any cline-yes">36x</span>
833
+ <span class="cline-any cline-yes">36x</span>
834
+ <span class="cline-any cline-yes">36x</span>
835
+ <span class="cline-any cline-yes">36x</span>
836
+ <span class="cline-any cline-yes">17x</span>
837
+ <span class="cline-any cline-yes">17x</span>
838
+ <span class="cline-any cline-yes">19x</span>
839
+ <span class="cline-any cline-yes">19x</span>
840
+ <span class="cline-any cline-yes">19x</span>
841
+ <span class="cline-any cline-yes">19x</span>
842
+ <span class="cline-any cline-yes">19x</span>
843
+ <span class="cline-any cline-yes">19x</span>
844
+ <span class="cline-any cline-yes">19x</span>
845
+ <span class="cline-any cline-yes">19x</span>
846
+ <span class="cline-any cline-yes">19x</span>
847
+ <span class="cline-any cline-yes">19x</span>
848
+ <span class="cline-any cline-yes">19x</span>
849
+ <span class="cline-any cline-yes">18x</span>
850
+ <span class="cline-any cline-yes">18x</span>
851
+ <span class="cline-any cline-yes">18x</span>
852
+ <span class="cline-any cline-yes">16x</span>
853
+ <span class="cline-any cline-yes">16x</span>
854
+ <span class="cline-any cline-no">&nbsp;</span>
855
+ <span class="cline-any cline-no">&nbsp;</span>
856
+ <span class="cline-any cline-no">&nbsp;</span>
857
+ <span class="cline-any cline-no">&nbsp;</span>
858
+ <span class="cline-any cline-no">&nbsp;</span>
859
+ <span class="cline-any cline-yes">16x</span>
860
+ <span class="cline-any cline-yes">18x</span>
861
+ <span class="cline-any cline-yes">18x</span>
862
+ <span class="cline-any cline-yes">18x</span>
863
+ <span class="cline-any cline-yes">9x</span>
864
+ <span class="cline-any cline-yes">9x</span>
865
+ <span class="cline-any cline-yes">9x</span>
866
+ <span class="cline-any cline-yes">9x</span>
867
+ <span class="cline-any cline-yes">9x</span>
868
+ <span class="cline-any cline-yes">9x</span>
869
+ <span class="cline-any cline-yes">9x</span>
870
+ <span class="cline-any cline-yes">9x</span>
871
+ <span class="cline-any cline-yes">9x</span>
872
+ <span class="cline-any cline-yes">18x</span>
873
+ <span class="cline-any cline-yes">1x</span>
874
+ <span class="cline-any cline-yes">1x</span>
875
+ <span class="cline-any cline-yes">1x</span>
876
+ <span class="cline-any cline-yes">18x</span>
877
+ <span class="cline-any cline-yes">19x</span>
878
+ <span class="cline-any cline-yes">19x</span>
879
+ <span class="cline-any cline-yes">19x</span>
880
+ <span class="cline-any cline-yes">1x</span>
881
+ <span class="cline-any cline-yes">1x</span>
882
+ <span class="cline-any cline-yes">19x</span>
883
+ <span class="cline-any cline-yes">19x</span>
884
+ <span class="cline-any cline-no">&nbsp;</span>
885
+ <span class="cline-any cline-no">&nbsp;</span>
886
+ <span class="cline-any cline-no">&nbsp;</span>
887
+ <span class="cline-any cline-yes">19x</span>
888
+ <span class="cline-any cline-yes">19x</span>
889
+ <span class="cline-any cline-yes">19x</span>
890
+ <span class="cline-any cline-yes">36x</span>
891
+ <span class="cline-any cline-yes">117x</span>
892
+ <span class="cline-any cline-yes">117x</span>
893
+ <span class="cline-any cline-yes">12x</span>
894
+ <span class="cline-any cline-yes">12x</span>
895
+ <span class="cline-any cline-yes">12x</span>
896
+ <span class="cline-any cline-yes">12x</span>
897
+ <span class="cline-any cline-yes">12x</span>
898
+ <span class="cline-any cline-yes">12x</span>
899
+ <span class="cline-any cline-yes">12x</span>
900
+ <span class="cline-any cline-yes">12x</span>
901
+ <span class="cline-any cline-yes">12x</span>
902
+ <span class="cline-any cline-yes">12x</span>
903
+ <span class="cline-any cline-yes">12x</span>
904
+ <span class="cline-any cline-yes">12x</span>
905
+ <span class="cline-any cline-yes">12x</span>
906
+ <span class="cline-any cline-yes">12x</span>
907
+ <span class="cline-any cline-yes">12x</span>
908
+ <span class="cline-any cline-yes">12x</span>
909
+ <span class="cline-any cline-yes">12x</span>
910
+ <span class="cline-any cline-yes">12x</span>
911
+ <span class="cline-any cline-yes">117x</span>
912
+ <span class="cline-any cline-yes">117x</span>
913
+ <span class="cline-any cline-yes">14x</span>
914
+ <span class="cline-any cline-yes">14x</span>
915
+ <span class="cline-any cline-yes">14x</span>
916
+ <span class="cline-any cline-yes">2x</span>
917
+ <span class="cline-any cline-yes">2x</span>
918
+ <span class="cline-any cline-yes">12x</span>
919
+ <span class="cline-any cline-yes">14x</span>
920
+ <span class="cline-any cline-yes">14x</span>
921
+ <span class="cline-any cline-yes">14x</span>
922
+ <span class="cline-any cline-yes">16x</span>
923
+ <span class="cline-any cline-yes">14x</span>
924
+ <span class="cline-any cline-yes">14x</span>
925
+ <span class="cline-any cline-yes">16x</span>
926
+ <span class="cline-any cline-yes">12x</span>
927
+ <span class="cline-any cline-yes">12x</span>
928
+ <span class="cline-any cline-yes">12x</span>
929
+ <span class="cline-any cline-yes">12x</span>
930
+ <span class="cline-any cline-yes">12x</span>
931
+ <span class="cline-any cline-yes">12x</span>
932
+ <span class="cline-any cline-yes">12x</span>
933
+ <span class="cline-any cline-yes">14x</span>
934
+ <span class="cline-any cline-yes">14x</span>
935
+ <span class="cline-any cline-yes">14x</span>
936
+ <span class="cline-any cline-yes">14x</span>
937
+ <span class="cline-any cline-yes">117x</span>
938
+ <span class="cline-any cline-yes">117x</span>
939
+ <span class="cline-any cline-yes">11x</span>
940
+ <span class="cline-any cline-yes">11x</span>
941
+ <span class="cline-any cline-yes">11x</span>
942
+ <span class="cline-any cline-yes">11x</span>
943
+ <span class="cline-any cline-yes">11x</span>
944
+ <span class="cline-any cline-yes">11x</span>
945
+ <span class="cline-any cline-yes">10x</span>
946
+ <span class="cline-any cline-yes">10x</span>
947
+ <span class="cline-any cline-yes">10x</span>
948
+ <span class="cline-any cline-yes">1x</span>
949
+ <span class="cline-any cline-yes">1x</span>
950
+ <span class="cline-any cline-yes">1x</span>
951
+ <span class="cline-any cline-yes">11x</span>
952
+ <span class="cline-any cline-yes">11x</span>
953
+ <span class="cline-any cline-yes">11x</span>
954
+ <span class="cline-any cline-yes">11x</span>
955
+ <span class="cline-any cline-yes">11x</span>
956
+ <span class="cline-any cline-yes">11x</span>
957
+ <span class="cline-any cline-yes">11x</span>
958
+ <span class="cline-any cline-yes">11x</span>
959
+ <span class="cline-any cline-yes">11x</span>
960
+ <span class="cline-any cline-yes">117x</span>
961
+ <span class="cline-any cline-yes">117x</span>
962
+ <span class="cline-any cline-yes">27x</span>
963
+ <span class="cline-any cline-yes">27x</span>
964
+ <span class="cline-any cline-yes">27x</span>
965
+ <span class="cline-any cline-yes">27x</span>
966
+ <span class="cline-any cline-yes">27x</span>
967
+ <span class="cline-any cline-yes">36x</span>
968
+ <span class="cline-any cline-yes">36x</span>
969
+ <span class="cline-any cline-yes">36x</span>
970
+ <span class="cline-any cline-yes">18x</span>
971
+ <span class="cline-any cline-yes">18x</span>
972
+ <span class="cline-any cline-yes">18x</span>
973
+ <span class="cline-any cline-yes">18x</span>
974
+ <span class="cline-any cline-yes">18x</span>
975
+ <span class="cline-any cline-yes">7x</span>
976
+ <span class="cline-any cline-yes">18x</span>
977
+ <span class="cline-any cline-yes">18x</span>
978
+ <span class="cline-any cline-yes">18x</span>
979
+ <span class="cline-any cline-yes">9x</span>
980
+ <span class="cline-any cline-yes">9x</span>
981
+ <span class="cline-any cline-yes">9x</span>
982
+ <span class="cline-any cline-yes">9x</span>
983
+ <span class="cline-any cline-yes">9x</span>
984
+ <span class="cline-any cline-yes">9x</span>
985
+ <span class="cline-any cline-yes">9x</span>
986
+ <span class="cline-any cline-yes">9x</span>
987
+ <span class="cline-any cline-yes">9x</span>
988
+ <span class="cline-any cline-yes">9x</span>
989
+ <span class="cline-any cline-yes">9x</span>
990
+ <span class="cline-any cline-yes">9x</span>
991
+ <span class="cline-any cline-yes">9x</span>
992
+ <span class="cline-any cline-yes">9x</span>
993
+ <span class="cline-any cline-yes">9x</span>
994
+ <span class="cline-any cline-yes">18x</span>
995
+ <span class="cline-any cline-no">&nbsp;</span>
996
+ <span class="cline-any cline-no">&nbsp;</span>
997
+ <span class="cline-any cline-yes">18x</span>
998
+ <span class="cline-any cline-yes">36x</span>
999
+ <span class="cline-any cline-yes">27x</span>
1000
+ <span class="cline-any cline-yes">117x</span>
1001
+ <span class="cline-any cline-yes">95x</span>
1002
+ <span class="cline-any cline-yes">95x</span>
1003
+ <span class="cline-any cline-yes">95x</span>
1004
+ <span class="cline-any cline-yes">93x</span>
1005
+ <span class="cline-any cline-yes">93x</span>
1006
+ <span class="cline-any cline-yes">93x</span>
1007
+ <span class="cline-any cline-yes">95x</span>
1008
+ <span class="cline-any cline-yes">2x</span>
1009
+ <span class="cline-any cline-yes">2x</span>
1010
+ <span class="cline-any cline-yes">2x</span>
1011
+ <span class="cline-any cline-yes">2x</span>
1012
+ <span class="cline-any cline-yes">2x</span>
1013
+ <span class="cline-any cline-yes">91x</span>
1014
+ <span class="cline-any cline-yes">91x</span>
1015
+ <span class="cline-any cline-yes">91x</span>
1016
+ <span class="cline-any cline-yes">95x</span>
1017
+ <span class="cline-any cline-yes">88x</span>
1018
+ <span class="cline-any cline-yes">88x</span>
1019
+ <span class="cline-any cline-yes">88x</span>
1020
+ <span class="cline-any cline-yes">88x</span>
1021
+ <span class="cline-any cline-yes">88x</span>
1022
+ <span class="cline-any cline-yes">88x</span>
1023
+ <span class="cline-any cline-yes">88x</span>
1024
+ <span class="cline-any cline-yes">88x</span>
1025
+ <span class="cline-any cline-yes">3x</span>
1026
+ <span class="cline-any cline-yes">3x</span>
1027
+ <span class="cline-any cline-yes">95x</span>
1028
+ <span class="cline-any cline-yes">117x</span>
1029
+ <span class="cline-any cline-yes">51x</span>
1030
+ <span class="cline-any cline-yes">51x</span>
1031
+ <span class="cline-any cline-yes">51x</span>
1032
+ <span class="cline-any cline-yes">51x</span>
1033
+ <span class="cline-any cline-yes">51x</span>
1034
+ <span class="cline-any cline-yes">51x</span>
1035
+ <span class="cline-any cline-yes">51x</span>
1036
+ <span class="cline-any cline-yes">51x</span>
1037
+ <span class="cline-any cline-yes">51x</span>
1038
+ <span class="cline-any cline-yes">51x</span>
1039
+ <span class="cline-any cline-yes">51x</span>
1040
+ <span class="cline-any cline-yes">51x</span>
1041
+ <span class="cline-any cline-yes">51x</span>
1042
+ <span class="cline-any cline-yes">51x</span>
1043
+ <span class="cline-any cline-yes">51x</span>
1044
+ <span class="cline-any cline-yes">51x</span>
1045
+ <span class="cline-any cline-yes">117x</span>
1046
+ <span class="cline-any cline-yes">117x</span>
1047
+ <span class="cline-any cline-yes">30x</span>
1048
+ <span class="cline-any cline-yes">30x</span>
1049
+ <span class="cline-any cline-yes">30x</span>
1050
+ <span class="cline-any cline-yes">30x</span>
1051
+ <span class="cline-any cline-yes">30x</span>
1052
+ <span class="cline-any cline-yes">30x</span>
1053
+ <span class="cline-any cline-yes">286x</span>
1054
+ <span class="cline-any cline-yes">286x</span>
1055
+ <span class="cline-any cline-yes">4x</span>
1056
+ <span class="cline-any cline-yes">4x</span>
1057
+ <span class="cline-any cline-yes">4x</span>
1058
+ <span class="cline-any cline-yes">4x</span>
1059
+ <span class="cline-any cline-yes">4x</span>
1060
+ <span class="cline-any cline-yes">4x</span>
1061
+ <span class="cline-any cline-yes">4x</span>
1062
+ <span class="cline-any cline-yes">4x</span>
1063
+ <span class="cline-any cline-yes">282x</span>
1064
+ <span class="cline-any cline-yes">30x</span>
1065
+ <span class="cline-any cline-yes">30x</span>
1066
+ <span class="cline-any cline-yes">30x</span>
1067
+ <span class="cline-any cline-yes">26x</span>
1068
+ <span class="cline-any cline-yes">26x</span>
1069
+ <span class="cline-any cline-yes">30x</span>
1070
+ <span class="cline-any cline-yes">30x</span>
1071
+ <span class="cline-any cline-yes">117x</span>
1072
+ <span class="cline-any cline-yes">117x</span>
1073
+ <span class="cline-any cline-yes">117x</span>
1074
+ <span class="cline-any cline-yes">62x</span>
1075
+ <span class="cline-any cline-yes">62x</span>
1076
+ <span class="cline-any cline-yes">62x</span>
1077
+ <span class="cline-any cline-yes">62x</span>
1078
+ <span class="cline-any cline-yes">62x</span>
1079
+ <span class="cline-any cline-yes">62x</span>
1080
+ <span class="cline-any cline-yes">62x</span>
1081
+ <span class="cline-any cline-yes">62x</span>
1082
+ <span class="cline-any cline-yes">117x</span>
1083
+ <span class="cline-any cline-yes">117x</span>
1084
+ <span class="cline-any cline-yes">117x</span>
1085
+ <span class="cline-any cline-yes">30x</span>
1086
+ <span class="cline-any cline-yes">2x</span>
1087
+ <span class="cline-any cline-yes">2x</span>
1088
+ <span class="cline-any cline-yes">2x</span>
1089
+ <span class="cline-any cline-yes">2x</span>
1090
+ <span class="cline-any cline-yes">2x</span>
1091
+ <span class="cline-any cline-yes">2x</span>
1092
+ <span class="cline-any cline-yes">2x</span>
1093
+ <span class="cline-any cline-yes">30x</span>
1094
+ <span class="cline-any cline-yes">117x</span>
1095
+ <span class="cline-any cline-yes">117x</span>
1096
+ <span class="cline-any cline-yes">14x</span>
1097
+ <span class="cline-any cline-yes">14x</span>
1098
+ <span class="cline-any cline-yes">5x</span>
1099
+ <span class="cline-any cline-yes">5x</span>
1100
+ <span class="cline-any cline-yes">9x</span>
1101
+ <span class="cline-any cline-yes">14x</span>
1102
+ <span class="cline-any cline-yes">117x</span>
1103
+ <span class="cline-any cline-yes">117x</span>
1104
+ <span class="cline-any cline-yes">117x</span>
1105
+ <span class="cline-any cline-yes">8x</span>
1106
+ <span class="cline-any cline-yes">8x</span>
1107
+ <span class="cline-any cline-yes">8x</span>
1108
+ <span class="cline-any cline-yes">8x</span>
1109
+ <span class="cline-any cline-yes">8x</span>
1110
+ <span class="cline-any cline-yes">8x</span>
1111
+ <span class="cline-any cline-yes">8x</span>
1112
+ <span class="cline-any cline-yes">8x</span>
1113
+ <span class="cline-any cline-yes">8x</span>
1114
+ <span class="cline-any cline-yes">8x</span>
1115
+ <span class="cline-any cline-yes">8x</span>
1116
+ <span class="cline-any cline-yes">8x</span>
1117
+ <span class="cline-any cline-yes">8x</span>
1118
+ <span class="cline-any cline-yes">8x</span>
1119
+ <span class="cline-any cline-yes">8x</span>
1120
+ <span class="cline-any cline-yes">8x</span>
1121
+ <span class="cline-any cline-yes">8x</span>
1122
+ <span class="cline-any cline-yes">8x</span>
1123
+ <span class="cline-any cline-yes">8x</span>
1124
+ <span class="cline-any cline-yes">8x</span>
1125
+ <span class="cline-any cline-yes">8x</span>
1126
+ <span class="cline-any cline-yes">8x</span>
1127
+ <span class="cline-any cline-yes">8x</span>
1128
+ <span class="cline-any cline-yes">8x</span>
1129
+ <span class="cline-any cline-yes">8x</span>
1130
+ <span class="cline-any cline-yes">8x</span>
1131
+ <span class="cline-any cline-yes">8x</span>
1132
+ <span class="cline-any cline-yes">2x</span>
1133
+ <span class="cline-any cline-yes">2x</span>
1134
+ <span class="cline-any cline-yes">2x</span>
1135
+ <span class="cline-any cline-yes">2x</span>
1136
+ <span class="cline-any cline-yes">2x</span>
1137
+ <span class="cline-any cline-yes">8x</span>
1138
+ <span class="cline-any cline-yes">6x</span>
1139
+ <span class="cline-any cline-yes">6x</span>
1140
+ <span class="cline-any cline-yes">8x</span>
1141
+ <span class="cline-any cline-no">&nbsp;</span>
1142
+ <span class="cline-any cline-no">&nbsp;</span>
1143
+ <span class="cline-any cline-no">&nbsp;</span>
1144
+ <span class="cline-any cline-no">&nbsp;</span>
1145
+ <span class="cline-any cline-no">&nbsp;</span>
1146
+ <span class="cline-any cline-no">&nbsp;</span>
1147
+ <span class="cline-any cline-yes">8x</span>
1148
+ <span class="cline-any cline-yes">8x</span>
1149
+ <span class="cline-any cline-yes">8x</span>
1150
+ <span class="cline-any cline-yes">8x</span>
1151
+ <span class="cline-any cline-no">&nbsp;</span>
1152
+ <span class="cline-any cline-yes">8x</span>
1153
+ <span class="cline-any cline-yes">8x</span>
1154
+ <span class="cline-any cline-yes">8x</span>
1155
+ <span class="cline-any cline-no">&nbsp;</span>
1156
+ <span class="cline-any cline-no">&nbsp;</span>
1157
+ <span class="cline-any cline-yes">8x</span>
1158
+ <span class="cline-any cline-yes">8x</span>
1159
+ <span class="cline-any cline-yes">8x</span>
1160
+ <span class="cline-any cline-yes">8x</span>
1161
+ <span class="cline-any cline-yes">8x</span>
1162
+ <span class="cline-any cline-yes">8x</span>
1163
+ <span class="cline-any cline-yes">8x</span>
1164
+ <span class="cline-any cline-yes">8x</span>
1165
+ <span class="cline-any cline-yes">117x</span>
1166
+ <span class="cline-any cline-yes">117x</span>
1167
+ <span class="cline-any cline-yes">117x</span>
1168
+ <span class="cline-any cline-yes">23x</span>
1169
+ <span class="cline-any cline-yes">23x</span>
1170
+ <span class="cline-any cline-yes">23x</span>
1171
+ <span class="cline-any cline-yes">5x</span>
1172
+ <span class="cline-any cline-yes">23x</span>
1173
+ <span class="cline-any cline-yes">18x</span>
1174
+ <span class="cline-any cline-yes">18x</span>
1175
+ <span class="cline-any cline-yes">23x</span>
1176
+ <span class="cline-any cline-yes">23x</span>
1177
+ <span class="cline-any cline-yes">23x</span>
1178
+ <span class="cline-any cline-yes">23x</span>
1179
+ <span class="cline-any cline-yes">23x</span>
1180
+ <span class="cline-any cline-yes">23x</span>
1181
+ <span class="cline-any cline-yes">23x</span>
1182
+ <span class="cline-any cline-yes">8x</span>
1183
+ <span class="cline-any cline-yes">8x</span>
1184
+ <span class="cline-any cline-yes">8x</span>
1185
+ <span class="cline-any cline-yes">8x</span>
1186
+ <span class="cline-any cline-yes">8x</span>
1187
+ <span class="cline-any cline-yes">8x</span>
1188
+ <span class="cline-any cline-yes">15x</span>
1189
+ <span class="cline-any cline-yes">15x</span>
1190
+ <span class="cline-any cline-yes">15x</span>
1191
+ <span class="cline-any cline-yes">15x</span>
1192
+ <span class="cline-any cline-yes">15x</span>
1193
+ <span class="cline-any cline-yes">15x</span>
1194
+ <span class="cline-any cline-yes">15x</span>
1195
+ <span class="cline-any cline-yes">23x</span>
1196
+ <span class="cline-any cline-yes">23x</span>
1197
+ <span class="cline-any cline-yes">23x</span>
1198
+ <span class="cline-any cline-yes">23x</span>
1199
+ <span class="cline-any cline-yes">23x</span>
1200
+ <span class="cline-any cline-yes">23x</span>
1201
+ <span class="cline-any cline-yes">23x</span>
1202
+ <span class="cline-any cline-yes">23x</span>
1203
+ <span class="cline-any cline-yes">23x</span>
1204
+ <span class="cline-any cline-yes">23x</span>
1205
+ <span class="cline-any cline-yes">23x</span>
1206
+ <span class="cline-any cline-yes">23x</span>
1207
+ <span class="cline-any cline-yes">23x</span>
1208
+ <span class="cline-any cline-yes">23x</span>
1209
+ <span class="cline-any cline-yes">23x</span>
1210
+ <span class="cline-any cline-yes">23x</span>
1211
+ <span class="cline-any cline-yes">23x</span>
1212
+ <span class="cline-any cline-yes">23x</span>
1213
+ <span class="cline-any cline-yes">23x</span>
1214
+ <span class="cline-any cline-yes">23x</span>
1215
+ <span class="cline-any cline-yes">23x</span>
1216
+ <span class="cline-any cline-yes">23x</span>
1217
+ <span class="cline-any cline-yes">13x</span>
1218
+ <span class="cline-any cline-yes">13x</span>
1219
+ <span class="cline-any cline-yes">12x</span>
1220
+ <span class="cline-any cline-yes">12x</span>
1221
+ <span class="cline-any cline-yes">12x</span>
1222
+ <span class="cline-any cline-yes">3x</span>
1223
+ <span class="cline-any cline-yes">12x</span>
1224
+ <span class="cline-any cline-yes">9x</span>
1225
+ <span class="cline-any cline-yes">9x</span>
1226
+ <span class="cline-any cline-yes">12x</span>
1227
+ <span class="cline-any cline-no">&nbsp;</span>
1228
+ <span class="cline-any cline-no">&nbsp;</span>
1229
+ <span class="cline-any cline-yes">13x</span>
1230
+ <span class="cline-any cline-yes">23x</span>
1231
+ <span class="cline-any cline-yes">23x</span>
1232
+ <span class="cline-any cline-yes">23x</span>
1233
+ <span class="cline-any cline-yes">10x</span>
1234
+ <span class="cline-any cline-yes">23x</span>
1235
+ <span class="cline-any cline-yes">23x</span>
1236
+ <span class="cline-any cline-yes">23x</span>
1237
+ <span class="cline-any cline-no">&nbsp;</span>
1238
+ <span class="cline-any cline-no">&nbsp;</span>
1239
+ <span class="cline-any cline-yes">23x</span>
1240
+ <span class="cline-any cline-yes">23x</span>
1241
+ <span class="cline-any cline-yes">23x</span>
1242
+ <span class="cline-any cline-yes">23x</span>
1243
+ <span class="cline-any cline-yes">23x</span>
1244
+ <span class="cline-any cline-yes">23x</span>
1245
+ <span class="cline-any cline-yes">23x</span>
1246
+ <span class="cline-any cline-yes">23x</span>
1247
+ <span class="cline-any cline-yes">117x</span>
1248
+ <span class="cline-any cline-yes">117x</span>
1249
+ <span class="cline-any cline-yes">117x</span>
1250
+ <span class="cline-any cline-yes">7x</span>
1251
+ <span class="cline-any cline-yes">1x</span>
1252
+ <span class="cline-any cline-yes">1x</span>
1253
+ <span class="cline-any cline-yes">6x</span>
1254
+ <span class="cline-any cline-yes">6x</span>
1255
+ <span class="cline-any cline-yes">6x</span>
1256
+ <span class="cline-any cline-yes">7x</span>
1257
+ <span class="cline-any cline-no">&nbsp;</span>
1258
+ <span class="cline-any cline-yes">7x</span>
1259
+ <span class="cline-any cline-yes">6x</span>
1260
+ <span class="cline-any cline-yes">6x</span>
1261
+ <span class="cline-any cline-yes">6x</span>
1262
+ <span class="cline-any cline-yes">6x</span>
1263
+ <span class="cline-any cline-yes">6x</span>
1264
+ <span class="cline-any cline-yes">7x</span>
1265
+ <span class="cline-any cline-yes">2x</span>
1266
+ <span class="cline-any cline-yes">2x</span>
1267
+ <span class="cline-any cline-yes">2x</span>
1268
+ <span class="cline-any cline-yes">2x</span>
1269
+ <span class="cline-any cline-yes">2x</span>
1270
+ <span class="cline-any cline-yes">2x</span>
1271
+ <span class="cline-any cline-yes">4x</span>
1272
+ <span class="cline-any cline-yes">4x</span>
1273
+ <span class="cline-any cline-yes">4x</span>
1274
+ <span class="cline-any cline-yes">4x</span>
1275
+ <span class="cline-any cline-yes">4x</span>
1276
+ <span class="cline-any cline-yes">4x</span>
1277
+ <span class="cline-any cline-yes">4x</span>
1278
+ <span class="cline-any cline-yes">4x</span>
1279
+ <span class="cline-any cline-yes">4x</span>
1280
+ <span class="cline-any cline-yes">4x</span>
1281
+ <span class="cline-any cline-yes">4x</span>
1282
+ <span class="cline-any cline-yes">4x</span>
1283
+ <span class="cline-any cline-yes">5x</span>
1284
+ <span class="cline-any cline-yes">5x</span>
1285
+ <span class="cline-any cline-yes">5x</span>
1286
+ <span class="cline-any cline-yes">5x</span>
1287
+ <span class="cline-any cline-yes">5x</span>
1288
+ <span class="cline-any cline-yes">5x</span>
1289
+ <span class="cline-any cline-yes">5x</span>
1290
+ <span class="cline-any cline-yes">5x</span>
1291
+ <span class="cline-any cline-yes">5x</span>
1292
+ <span class="cline-any cline-yes">5x</span>
1293
+ <span class="cline-any cline-yes">5x</span>
1294
+ <span class="cline-any cline-yes">5x</span>
1295
+ <span class="cline-any cline-yes">5x</span>
1296
+ <span class="cline-any cline-yes">4x</span>
1297
+ <span class="cline-any cline-yes">4x</span>
1298
+ <span class="cline-any cline-yes">3x</span>
1299
+ <span class="cline-any cline-yes">3x</span>
1300
+ <span class="cline-any cline-yes">3x</span>
1301
+ <span class="cline-any cline-no">&nbsp;</span>
1302
+ <span class="cline-any cline-yes">3x</span>
1303
+ <span class="cline-any cline-yes">3x</span>
1304
+ <span class="cline-any cline-yes">3x</span>
1305
+ <span class="cline-any cline-yes">3x</span>
1306
+ <span class="cline-any cline-no">&nbsp;</span>
1307
+ <span class="cline-any cline-no">&nbsp;</span>
1308
+ <span class="cline-any cline-yes">4x</span>
1309
+ <span class="cline-any cline-yes">5x</span>
1310
+ <span class="cline-any cline-yes">5x</span>
1311
+ <span class="cline-any cline-yes">5x</span>
1312
+ <span class="cline-any cline-yes">1x</span>
1313
+ <span class="cline-any cline-yes">5x</span>
1314
+ <span class="cline-any cline-yes">5x</span>
1315
+ <span class="cline-any cline-yes">5x</span>
1316
+ <span class="cline-any cline-no">&nbsp;</span>
1317
+ <span class="cline-any cline-no">&nbsp;</span>
1318
+ <span class="cline-any cline-yes">5x</span>
1319
+ <span class="cline-any cline-yes">5x</span>
1320
+ <span class="cline-any cline-yes">5x</span>
1321
+ <span class="cline-any cline-yes">5x</span>
1322
+ <span class="cline-any cline-yes">4x</span>
1323
+ <span class="cline-any cline-yes">4x</span>
1324
+ <span class="cline-any cline-yes">4x</span>
1325
+ <span class="cline-any cline-yes">7x</span>
1326
+ <span class="cline-any cline-yes">117x</span>
1327
+ <span class="cline-any cline-yes">117x</span>
1328
+ <span class="cline-any cline-yes">4x</span>
1329
+ <span class="cline-any cline-yes">4x</span>
1330
+ <span class="cline-any cline-yes">4x</span>
1331
+ <span class="cline-any cline-no">&nbsp;</span>
1332
+ <span class="cline-any cline-yes">4x</span>
1333
+ <span class="cline-any cline-yes">4x</span>
1334
+ <span class="cline-any cline-yes">4x</span>
1335
+ <span class="cline-any cline-yes">4x</span>
1336
+ <span class="cline-any cline-yes">4x</span>
1337
+ <span class="cline-any cline-yes">4x</span>
1338
+ <span class="cline-any cline-yes">4x</span>
1339
+ <span class="cline-any cline-yes">4x</span>
1340
+ <span class="cline-any cline-yes">4x</span>
1341
+ <span class="cline-any cline-yes">4x</span>
1342
+ <span class="cline-any cline-yes">4x</span>
1343
+ <span class="cline-any cline-yes">4x</span>
1344
+ <span class="cline-any cline-yes">4x</span>
1345
+ <span class="cline-any cline-yes">4x</span>
1346
+ <span class="cline-any cline-yes">4x</span>
1347
+ <span class="cline-any cline-yes">2x</span>
1348
+ <span class="cline-any cline-yes">2x</span>
1349
+ <span class="cline-any cline-yes">1x</span>
1350
+ <span class="cline-any cline-yes">1x</span>
1351
+ <span class="cline-any cline-yes">1x</span>
1352
+ <span class="cline-any cline-no">&nbsp;</span>
1353
+ <span class="cline-any cline-no">&nbsp;</span>
1354
+ <span class="cline-any cline-yes">2x</span>
1355
+ <span class="cline-any cline-yes">4x</span>
1356
+ <span class="cline-any cline-yes">4x</span>
1357
+ <span class="cline-any cline-yes">4x</span>
1358
+ <span class="cline-any cline-yes">4x</span>
1359
+ <span class="cline-any cline-no">&nbsp;</span>
1360
+ <span class="cline-any cline-no">&nbsp;</span>
1361
+ <span class="cline-any cline-yes">4x</span>
1362
+ <span class="cline-any cline-yes">4x</span>
1363
+ <span class="cline-any cline-yes">4x</span>
1364
+ <span class="cline-any cline-yes">4x</span>
1365
+ <span class="cline-any cline-yes">117x</span>
1366
+ <span class="cline-any cline-yes">117x</span>
1367
+ <span class="cline-any cline-yes">4x</span>
1368
+ <span class="cline-any cline-yes">4x</span>
1369
+ <span class="cline-any cline-yes">4x</span>
1370
+ <span class="cline-any cline-no">&nbsp;</span>
1371
+ <span class="cline-any cline-yes">4x</span>
1372
+ <span class="cline-any cline-yes">4x</span>
1373
+ <span class="cline-any cline-yes">4x</span>
1374
+ <span class="cline-any cline-yes">4x</span>
1375
+ <span class="cline-any cline-yes">4x</span>
1376
+ <span class="cline-any cline-yes">4x</span>
1377
+ <span class="cline-any cline-yes">4x</span>
1378
+ <span class="cline-any cline-yes">4x</span>
1379
+ <span class="cline-any cline-yes">4x</span>
1380
+ <span class="cline-any cline-yes">4x</span>
1381
+ <span class="cline-any cline-yes">4x</span>
1382
+ <span class="cline-any cline-yes">4x</span>
1383
+ <span class="cline-any cline-yes">4x</span>
1384
+ <span class="cline-any cline-yes">4x</span>
1385
+ <span class="cline-any cline-yes">4x</span>
1386
+ <span class="cline-any cline-yes">3x</span>
1387
+ <span class="cline-any cline-yes">3x</span>
1388
+ <span class="cline-any cline-yes">2x</span>
1389
+ <span class="cline-any cline-yes">2x</span>
1390
+ <span class="cline-any cline-yes">2x</span>
1391
+ <span class="cline-any cline-yes">1x</span>
1392
+ <span class="cline-any cline-yes">1x</span>
1393
+ <span class="cline-any cline-yes">3x</span>
1394
+ <span class="cline-any cline-yes">4x</span>
1395
+ <span class="cline-any cline-yes">4x</span>
1396
+ <span class="cline-any cline-yes">4x</span>
1397
+ <span class="cline-any cline-yes">4x</span>
1398
+ <span class="cline-any cline-no">&nbsp;</span>
1399
+ <span class="cline-any cline-no">&nbsp;</span>
1400
+ <span class="cline-any cline-yes">4x</span>
1401
+ <span class="cline-any cline-yes">4x</span>
1402
+ <span class="cline-any cline-yes">4x</span>
1403
+ <span class="cline-any cline-yes">4x</span>
1404
+ <span class="cline-any cline-yes">117x</span>
1405
+ <span class="cline-any cline-yes">117x</span>
1406
+ <span class="cline-any cline-yes">117x</span>
1407
+ <span class="cline-any cline-yes">117x</span>
1408
+ <span class="cline-any cline-yes">27x</span>
1409
+ <span class="cline-any cline-yes">27x</span>
1410
+ <span class="cline-any cline-yes">27x</span>
1411
+ <span class="cline-any cline-yes">27x</span>
1412
+ <span class="cline-any cline-yes">27x</span>
1413
+ <span class="cline-any cline-yes">117x</span>
1414
+ <span class="cline-any cline-yes">117x</span>
1415
+ <span class="cline-any cline-yes">117x</span>
1416
+ <span class="cline-any cline-yes">117x</span>
1417
+ <span class="cline-any cline-yes">117x</span>
1418
+ <span class="cline-any cline-yes">117x</span>
1419
+ <span class="cline-any cline-yes">117x</span>
1420
+ <span class="cline-any cline-yes">117x</span>
1421
+ <span class="cline-any cline-yes">117x</span>
1422
+ <span class="cline-any cline-yes">117x</span>
1423
+ <span class="cline-any cline-yes">117x</span>
1424
+ <span class="cline-any cline-yes">117x</span>
1425
+ <span class="cline-any cline-yes">117x</span>
1426
+ <span class="cline-any cline-yes">117x</span>
1427
+ <span class="cline-any cline-yes">117x</span>
1428
+ <span class="cline-any cline-yes">117x</span>
1429
+ <span class="cline-any cline-yes">117x</span>
1430
+ <span class="cline-any cline-yes">117x</span>
1431
+ <span class="cline-any cline-yes">117x</span>
1432
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
1433
+ * A2A Client - Make calls to remote agents
1434
+ */
1435
+ &nbsp;
1436
+ const https = require('https');
1437
+ const http = require('http');
1438
+ const { signRequest } = require('./crypto');
1439
+ // A2A-54: structured logging for retry warnings and size-cap violations
1440
+ const { createLogger } = require('./logger');
1441
+ &nbsp;
1442
+ const logger = createLogger({ component: 'a2a.client' });
1443
+ &nbsp;
1444
+ // A2A-54: response size cap prevents OOM from unbounded accumulation
1445
+ const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
1446
+ &nbsp;
1447
+ // A2A-54: only transient network errors are retryable — HTTP 4xx/5xx are not
1448
+ const RETRYABLE_CODES = ['ECONNRESET', 'ECONNREFUSED', 'EPIPE', 'ENOTFOUND', 'EAI_AGAIN'];
1449
+ &nbsp;
1450
+ // A2A-54: exponential backoff — first retry is immediate, then 1s, then 2s
1451
+ const RETRY_DELAYS = [0, 1000, 2000];
1452
+ &nbsp;
1453
+ // A2A-80: Agent Card cache — module-level Map with TTL and prune-on-access
1454
+ // Each entry: { card: object|null, cachedAt: number }
1455
+ // null card = negative cache (failed fetch)
1456
+ const _agentCardCache = new Map();
1457
+ &nbsp;
1458
+ function _readPositiveIntEnv(name, defaultVal) {
1459
+ const raw = process.env[name];
1460
+ if (!raw) return defaultVal;
1461
+ <span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" > const n = Number.parseInt(raw, 10);</span></span>
1462
+ return Number.isFinite(n) &amp;&amp; n &gt; 0 <span class="branch-0 cbranch-no" title="branch not covered" >? n <span class="branch-0 cbranch-no" title="branch not covered" ></span>: defaultVal;</span>
1463
+ }
1464
+ &nbsp;
1465
+ const AGENT_CARD_TTL_MS = _readPositiveIntEnv('A2A_AGENT_CARD_TTL_MS', 300000);
1466
+ const AGENT_CARD_MAX_ENTRIES = _readPositiveIntEnv('A2A_AGENT_CARD_MAX_ENTRIES', 200);
1467
+ const AGENT_CARD_FETCH_TIMEOUT_MS = 3000;
1468
+ &nbsp;
1469
+ // A2A-80: Prune-on-access eviction (pattern from A2A-69, NOT imported)
1470
+ function _pruneAgentCardCache() {
1471
+ const now = Date.now();
1472
+ for (const [key, entry] of _agentCardCache.entries()) {
1473
+ if (now - entry.cachedAt &gt; AGENT_CARD_TTL_MS) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1474
+ <span class="cstat-no" title="statement not covered" > _agentCardCache.delete(key);</span>
1475
+ <span class="cstat-no" title="statement not covered" > }</span>
1476
+ }
1477
+ &nbsp;
1478
+ if (_agentCardCache.size &lt;= AGENT_CARD_MAX_ENTRIES) {
1479
+ return;
1480
+ }
1481
+ <span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" ></span></span>
1482
+ <span class="cstat-no" title="statement not covered" > const oldest = Array.from(_agentCardCache.entries())</span>
1483
+ <span class="cstat-no" title="statement not covered" > .sort((a, b) =&gt; a[1].cachedAt - b[1].cachedAt);</span>
1484
+ <span class="cstat-no" title="statement not covered" > const toDelete = _agentCardCache.size - AGENT_CARD_MAX_ENTRIES;</span>
1485
+ <span class="cstat-no" title="statement not covered" > for (let i = 0; i &lt; toDelete; i++) {</span>
1486
+ <span class="cstat-no" title="statement not covered" > _agentCardCache.delete(oldest[i][0]);</span>
1487
+ <span class="cstat-no" title="statement not covered" > }</span>
1488
+ }
1489
+ &nbsp;
1490
+ // A2A-80: Cache key is always hostname:port
1491
+ function _agentCardCacheKey(host) {
1492
+ const parsed = splitHostPort(host);
1493
+ const hostname = parsed.hostname;
1494
+ const port = Number.isFinite(parsed.port) ? parsed.port <span class="branch-0 cbranch-no" title="branch not covered" >: 80;</span>
1495
+ return `${hostname}:${port}`;
1496
+ }
1497
+ &nbsp;
1498
+ // A2A-80: Validate Agent Card — needs non-empty interfaces[] with { type: 'rest' }
1499
+ function _parseAgentCard(json) {
1500
+ if (!json || typeof json !== 'object') return null;
1501
+ if (!Array.isArray(json.interfaces) || json.interfaces.length === 0) return null;
1502
+ &nbsp;
1503
+ const restInterface = json.interfaces.find(
1504
+ iface =&gt; iface &amp;&amp; iface.type === 'rest'
1505
+ );
1506
+ if (!restInterface) return null;
1507
+ &nbsp;
1508
+ return json;
1509
+ }
1510
+ &nbsp;
1511
+ // A2A-80: Fetch Agent Card (GET /.well-known/a2a-agent-card, 3s timeout, cached with TTL).
1512
+ // TODO: Concurrent call() to same uncached host may duplicate Agent Card fetches.
1513
+ function fetchRemoteAgentCard(host) {
1514
+ _pruneAgentCardCache();
1515
+ &nbsp;
1516
+ const cacheKey = _agentCardCacheKey(host);
1517
+ const cached = _agentCardCache.get(cacheKey);
1518
+ if (cached) {
1519
+ return Promise.resolve(cached.card);
1520
+ }
1521
+ &nbsp;
1522
+ const { protocol, hostname, port } = resolveProtocolAndPort(host);
1523
+ &nbsp;
1524
+ return new Promise((resolve) =&gt; {
1525
+ const req = protocol.request({
1526
+ hostname,
1527
+ port,
1528
+ path: '/.well-known/a2a-agent-card',
1529
+ method: 'GET',
1530
+ timeout: AGENT_CARD_FETCH_TIMEOUT_MS
1531
+ }, (res) =&gt; {
1532
+ let data = '';
1533
+ let bytes = 0;
1534
+ res.on('data', (chunk) =&gt; {
1535
+ bytes += chunk.length;
1536
+ if (bytes &gt; MAX_RESPONSE_BYTES) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1537
+ <span class="cstat-no" title="statement not covered" > res.destroy();</span>
1538
+ <span class="cstat-no" title="statement not covered" > _agentCardCache.set(cacheKey, { card: null, cachedAt: Date.now() });</span>
1539
+ <span class="cstat-no" title="statement not covered" > resolve(null);</span>
1540
+ <span class="cstat-no" title="statement not covered" > return;</span>
1541
+ <span class="cstat-no" title="statement not covered" > }</span>
1542
+ data += chunk;
1543
+ });
1544
+ res.on('end', () =&gt; {
1545
+ if (res.statusCode !== 200) {
1546
+ _agentCardCache.set(cacheKey, { card: null, cachedAt: Date.now() });
1547
+ resolve(null);
1548
+ return;
1549
+ }
1550
+ try {
1551
+ const json = JSON.parse(data);
1552
+ const card = _parseAgentCard(json);
1553
+ _agentCardCache.set(cacheKey, { card, cachedAt: Date.now() });
1554
+ resolve(card);
1555
+ } catch {
1556
+ _agentCardCache.set(cacheKey, { card: null, cachedAt: Date.now() });
1557
+ resolve(null);
1558
+ }
1559
+ });
1560
+ });
1561
+ &nbsp;
1562
+ req.on('error', () =&gt; {
1563
+ _agentCardCache.set(cacheKey, { card: null, cachedAt: Date.now() });
1564
+ resolve(null);
1565
+ });
1566
+ req.on('timeout', () =&gt; {
1567
+ <span class="cstat-no" title="statement not covered" > req.destroy();</span>
1568
+ <span class="cstat-no" title="statement not covered" > _agentCardCache.set(cacheKey, { card: null, cachedAt: Date.now() });</span>
1569
+ <span class="cstat-no" title="statement not covered" > resolve(null);</span>
1570
+ });
1571
+ req.end();
1572
+ });
1573
+ }
1574
+ &nbsp;
1575
+ // A2A-80: Build Google A2A message/send body (ref: a2a.js translateInternalToGoogle)
1576
+ function _translateToGoogleRequest(message, conversationId, options = {}, caller = {}) {
1577
+ return {
1578
+ message: {
1579
+ role: 'user',
1580
+ parts: [{ content: { text: message } }],
1581
+ ...(conversationId ? { context_id: conversationId } : {})
1582
+ },
1583
+ metadata: {
1584
+ caller_name: String(caller.name || '').slice(0, 100),
1585
+ caller_owner: String(caller.owner || '').slice(0, 100),
1586
+ caller_instance: String(caller.instance || '').slice(0, 200)
1587
+ },
1588
+ configuration: {
1589
+ timeout_seconds: options.timeoutSeconds || 60,
1590
+ blocking: true
1591
+ }
1592
+ };
1593
+ }
1594
+ &nbsp;
1595
+ // A2A-80: Translate Google A2A Task response to internal format (ref: a2a.js translateGoogleToInternal)
1596
+ function _translateGoogleResponse(taskResponse) {
1597
+ const task = taskResponse?.task;
1598
+ if (!task || !task.status) {
1599
+ throw new A2AError('google_a2a_error', 'Invalid Google A2A response: missing task or status');
1600
+ }
1601
+ &nbsp;
1602
+ const parts = task.status.message?.parts <span class="branch-0 cbranch-no" title="branch not covered" >|| [];</span>
1603
+ const textParts = [];
1604
+ for (const part of parts) {
1605
+ if (part?.content &amp;&amp; typeof part.content.text === 'string') {
1606
+ textParts.push(part.content.text);
1607
+ }
1608
+ }
1609
+ &nbsp;
1610
+ const response = textParts.join('\n');
1611
+ const state = task.status.state;
1612
+ const canContinue = state === 'input-required';
1613
+ &nbsp;
1614
+ return {
1615
+ response,
1616
+ conversation_id: task.context_id || null,
1617
+ can_continue: canContinue
1618
+ };
1619
+ }
1620
+ &nbsp;
1621
+ // A2A-80: Resolve message:send URL from Agent Card REST interface (trailing slash stripped)
1622
+ function _resolveGoogleA2AUrl(agentCard, host) {
1623
+ const restInterface = agentCard.interfaces.find(
1624
+ iface =&gt; iface &amp;&amp; iface.type === 'rest'
1625
+ );
1626
+ &nbsp;
1627
+ if (restInterface &amp;&amp; restInterface.url) {
1628
+ const baseUrl = restInterface.url.replace(/\/+$/, '');
1629
+ return `${baseUrl}/message:send`;
1630
+ }
1631
+ &nbsp;
1632
+ // Fallback: build from host
1633
+ const { hostname, port } = splitHostPort(host);
1634
+ const effectivePort = Number.isFinite(port) ? port <span class="branch-0 cbranch-no" title="branch not covered" >: 80;</span>
1635
+ const isLocalhost = hostname === 'localhost' <span class="branch-0 cbranch-no" title="branch not covered" >||</span>
1636
+ hostname === '127.0.0.1' <span class="branch-0 cbranch-no" title="branch not covered" >||</span>
1637
+ hostname === '::1' <span class="branch-0 cbranch-no" title="branch not covered" >||</span>
1638
+ hostname.startsWith('127.');
1639
+ const scheme = (isLocalhost <span class="branch-0 cbranch-no" title="branch not covered" >|| effectivePort === 80 <span class="branch-0 cbranch-no" title="branch not covered" ></span>|| (Number.isFinite(port) &amp;&amp; port !== 443))</span>
1640
+ ? 'http' <span class="branch-0 cbranch-no" title="branch not covered" >: 'https';</span>
1641
+ return `${scheme}://${hostname}:${effectivePort}/message:send`;
1642
+ }
1643
+ &nbsp;
1644
+ // A2A-54: Retry on transient network errors only (not HTTP 4xx/5xx)
1645
+ async function withRetry(fn, options = {}) {
1646
+ const delays = options.delays <span class="branch-0 cbranch-no" title="branch not covered" >|| RETRY_DELAYS;</span>
1647
+ const maxAttempts = delays.length + 1;
1648
+ &nbsp;
1649
+ for (let attempt = 1; attempt &lt;= maxAttempts; attempt++) {
1650
+ try {
1651
+ return await fn();
1652
+ } catch (err) {
1653
+ // A2A-54: only retry transient network errors and timeouts.
1654
+ // HTTP 4xx/5xx errors have err.code set to the server's error code
1655
+ // (e.g. 'bad_request'), so they won't match network_error or timeout.
1656
+ const isRetryable = err instanceof A2AError &amp;&amp; (
1657
+ (err.code === 'network_error' &amp;&amp; RETRYABLE_CODES.some(c =&gt; err.message.includes(c))) ||
1658
+ err.code === 'timeout'
1659
+ );
1660
+ &nbsp;
1661
+ if (!isRetryable || attempt &gt;= maxAttempts) {
1662
+ throw err;
1663
+ }
1664
+ &nbsp;
1665
+ // A2A-54: log each retry at warn level for operator visibility
1666
+ const delay = delays[attempt - 1];
1667
+ logger.warn(`Retrying request (attempt ${attempt + 1}/${maxAttempts})`, {
1668
+ event: 'retry',
1669
+ data: {
1670
+ error_code: err.code,
1671
+ error_message: err.message,
1672
+ attempt: attempt + 1,
1673
+ delay_ms: delay
1674
+ }
1675
+ });
1676
+ &nbsp;
1677
+ if (delay &gt; 0) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1678
+ <span class="cstat-no" title="statement not covered" > await new Promise(resolve =&gt; setTimeout(resolve, delay));</span>
1679
+ <span class="cstat-no" title="statement not covered" > }</span>
1680
+ }
1681
+ }
1682
+ }
1683
+ &nbsp;
1684
+ function splitHostPort(rawHost) {
1685
+ const host = String(rawHost || '').trim();
1686
+ if (!host) return { hostname: '', port: null };
1687
+ &nbsp;
1688
+ // IPv6 in brackets: [::1]:3001
1689
+ const bracketed = host.match(/^\[([^\]]+)\](?::(\d+))?$/);
1690
+ if (bracketed) {
1691
+ return {
1692
+ hostname: bracketed[1],
1693
+ port: bracketed[2] ? Number.parseInt(bracketed[2], 10) : null
1694
+ };
1695
+ }
1696
+ &nbsp;
1697
+ // Only treat the last ":" as a port separator when there's exactly one colon.
1698
+ const lastColon = host.lastIndexOf(':');
1699
+ if (lastColon !== -1 &amp;&amp; host.indexOf(':') === lastColon) {
1700
+ const maybePort = host.slice(lastColon + 1);
1701
+ if (/^\d+$/.test(maybePort)) {
1702
+ return {
1703
+ hostname: host.slice(0, lastColon),
1704
+ port: Number.parseInt(maybePort, 10)
1705
+ };
1706
+ }
1707
+ }
1708
+ &nbsp;
1709
+ return { hostname: host, port: null };
1710
+ }
1711
+ &nbsp;
1712
+ function resolveProtocolAndPort(host) {
1713
+ const parsed = splitHostPort(host);
1714
+ const hostname = parsed.hostname;
1715
+ const hasExplicitPort = Number.isFinite(parsed.port);
1716
+ const isLocalhost = hostname === 'localhost' ||
1717
+ hostname === '127.0.0.1' ||
1718
+ hostname === '::1' ||
1719
+ hostname.startsWith('127.');
1720
+ &nbsp;
1721
+ const port = hasExplicitPort ? parsed.port : 80;
1722
+ // Use HTTP for localhost or explicit non-443 ports, HTTPS otherwise.
1723
+ const useHttp = isLocalhost || port === 80 || (hasExplicitPort &amp;&amp; port !== 443);
1724
+ const protocol = useHttp ? http : https;
1725
+ &nbsp;
1726
+ return { protocol, hostname, port };
1727
+ }
1728
+ &nbsp;
1729
+ // A2A-54: Size-capped response handler — destroys socket if cap exceeded
1730
+ function handleSizeCappedResponse(res, resolve, reject, onComplete) {
1731
+ let data = '';
1732
+ let bytes = 0;
1733
+ let destroyed = false;
1734
+ &nbsp;
1735
+ res.on('data', (chunk) =&gt; {
1736
+ bytes += chunk.length;
1737
+ if (bytes &gt; MAX_RESPONSE_BYTES) {
1738
+ if (!destroyed) {
1739
+ destroyed = true;
1740
+ res.destroy();
1741
+ // A2A-54: reject immediately — the remote sent more data than we allow
1742
+ reject(new A2AError('response_too_large', `Response exceeded ${MAX_RESPONSE_BYTES} bytes`));
1743
+ }
1744
+ return;
1745
+ }
1746
+ data += chunk;
1747
+ });
1748
+ &nbsp;
1749
+ res.on('end', () =&gt; {
1750
+ if (destroyed) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
1751
+ onComplete(data, res.statusCode);
1752
+ });
1753
+ }
1754
+ &nbsp;
1755
+ class A2AClient {
1756
+ constructor(options = {}) {
1757
+ this.timeout = options.timeout || 60000;
1758
+ this.caller = options.caller || {};
1759
+ // A2A-52: Ed25519 identity keys for request signing
1760
+ this.privateKey = options.privateKey || null;
1761
+ this.publicKey = options.publicKey || null;
1762
+ // A2A-54: allow configurable retry delays for testing (fast tests use [0,0,0])
1763
+ this._retryDelays = options._retryDelays || RETRY_DELAYS;
1764
+ }
1765
+ &nbsp;
1766
+ // A2A-52: Build signature headers if keypair available
1767
+ _signHeaders(method, endpoint, body) {
1768
+ if (!this.privateKey || !this.publicKey) return {};
1769
+ return signRequest({
1770
+ privateKey: this.privateKey,
1771
+ publicKey: this.publicKey,
1772
+ method,
1773
+ endpoint,
1774
+ body
1775
+ });
1776
+ }
1777
+ &nbsp;
1778
+ static parseInvite(inviteUrl) {
1779
+ const match = inviteUrl.match(/^a2a:\/\/([^/]+)\/(.+)$/);
1780
+ if (!match) {
1781
+ throw new Error(`Invalid invite URL: ${inviteUrl}`);
1782
+ }
1783
+ return { host: match[1], token: match[2] };
1784
+ }
1785
+ &nbsp;
1786
+ // A2A-80: Send message via Google A2A protocol (message/send format)
1787
+ _callGoogleA2A(host, token, body, agentCard) {
1788
+ const url = _resolveGoogleA2AUrl(agentCard, host);
1789
+ // Parse the URL to extract components for http/https request
1790
+ const parsed = new URL(url);
1791
+ const proto = parsed.protocol === 'https:' <span class="branch-0 cbranch-no" title="branch not covered" >? https </span>: http;
1792
+ const path = parsed.pathname;
1793
+ &nbsp;
1794
+ // A2A-52: attach signature headers when keypair available
1795
+ const sigHeaders = this._signHeaders('POST', path, body);
1796
+ &nbsp;
1797
+ const makeRequest = () =&gt; new Promise((resolve, reject) =&gt; {
1798
+ const req = proto.request({
1799
+ hostname: parsed.hostname,
1800
+ port: parsed.port <span class="branch-0 cbranch-no" title="branch not covered" >|| (parsed.protocol === 'https:' ? 443 : 80),</span>
1801
+ path,
1802
+ method: 'POST',
1803
+ headers: {
1804
+ 'Authorization': `Bearer ${token}`,
1805
+ 'Content-Type': 'application/json',
1806
+ 'Content-Length': Buffer.byteLength(body),
1807
+ ...sigHeaders
1808
+ },
1809
+ timeout: this.timeout
1810
+ }, (res) =&gt; {
1811
+ handleSizeCappedResponse(res, resolve, reject, (data, statusCode) =&gt; {
1812
+ try {
1813
+ const json = JSON.parse(data);
1814
+ if (statusCode &gt;= 400) {
1815
+ // A2A-80: map Google A2A error format to A2AError
1816
+ const errObj = json.error <span class="branch-0 cbranch-no" title="branch not covered" >|| {};</span>
1817
+ const code = errObj.code <span class="branch-0 cbranch-no" title="branch not covered" >|| json.error <span class="branch-0 cbranch-no" title="branch not covered" ></span>|| 'google_a2a_error';</span>
1818
+ const message = errObj.message <span class="branch-0 cbranch-no" title="branch not covered" >|| json.message <span class="branch-0 cbranch-no" title="branch not covered" ></span>|| data;</span>
1819
+ reject(new A2AError(String(code), message, statusCode));
1820
+ } else {
1821
+ resolve(_translateGoogleResponse(json));
1822
+ }
1823
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (e) {</span>
1824
+ <span class="cstat-no" title="statement not covered" > if (e instanceof A2AError) {</span>
1825
+ <span class="cstat-no" title="statement not covered" > reject(e);</span>
1826
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1827
+ <span class="cstat-no" title="statement not covered" > reject(new A2AError('parse_error', `Failed to parse Google A2A response: ${data}`, statusCode));</span>
1828
+ <span class="cstat-no" title="statement not covered" > }</span>
1829
+ <span class="cstat-no" title="statement not covered" > }</span>
1830
+ });
1831
+ });
1832
+ &nbsp;
1833
+ req.on('error', (e) =&gt; {
1834
+ <span class="cstat-no" title="statement not covered" > reject(new A2AError('network_error', e.code ? `${e.code}: ${e.message}` : e.message));</span>
1835
+ });
1836
+ &nbsp;
1837
+ req.on('timeout', () =&gt; {
1838
+ <span class="cstat-no" title="statement not covered" > req.destroy();</span>
1839
+ <span class="cstat-no" title="statement not covered" > reject(new A2AError('timeout', 'Request timed out'));</span>
1840
+ });
1841
+ &nbsp;
1842
+ req.write(body);
1843
+ req.end();
1844
+ });
1845
+ &nbsp;
1846
+ return withRetry(makeRequest, { delays: this._retryDelays });
1847
+ }
1848
+ &nbsp;
1849
+ // Call a remote agent — auto-detects Google A2A via Agent Card
1850
+ async call(endpoint, message, options = {}) {
1851
+ let host, token;
1852
+ &nbsp;
1853
+ if (typeof endpoint === 'string') {
1854
+ ({ host, token } = A2AClient.parseInvite(endpoint));
1855
+ } else {
1856
+ ({ host, token } = endpoint);
1857
+ }
1858
+ &nbsp;
1859
+ const { conversationId, context, timeoutSeconds } = options;
1860
+ &nbsp;
1861
+ // A2A-80: check Agent Card to decide Google A2A vs proprietary format
1862
+ const agentCard = await fetchRemoteAgentCard(host);
1863
+ &nbsp;
1864
+ if (agentCard) {
1865
+ // Google A2A format path
1866
+ const googleBody = JSON.stringify(
1867
+ _translateToGoogleRequest(message, conversationId, { timeoutSeconds }, this.caller)
1868
+ );
1869
+ return this._callGoogleA2A(host, token, googleBody, agentCard);
1870
+ }
1871
+ &nbsp;
1872
+ // Proprietary format path (unchanged)
1873
+ const body = JSON.stringify({
1874
+ message,
1875
+ conversation_id: conversationId,
1876
+ caller: this.caller,
1877
+ context,
1878
+ timeout_seconds: timeoutSeconds || 60
1879
+ });
1880
+ &nbsp;
1881
+ const { protocol, hostname, port } = resolveProtocolAndPort(host);
1882
+ // A2A-52: attach signature headers when keypair available
1883
+ const sigHeaders = this._signHeaders('POST', '/api/a2a/invoke', body);
1884
+ &nbsp;
1885
+ // A2A-54: wrap with retry for transient network failures
1886
+ const makeRequest = () =&gt; new Promise((resolve, reject) =&gt; {
1887
+ const req = protocol.request({
1888
+ hostname,
1889
+ port,
1890
+ path: '/api/a2a/invoke',
1891
+ method: 'POST',
1892
+ headers: {
1893
+ 'Authorization': `Bearer ${token}`,
1894
+ 'Content-Type': 'application/json',
1895
+ 'Content-Length': Buffer.byteLength(body),
1896
+ ...sigHeaders
1897
+ },
1898
+ timeout: this.timeout
1899
+ }, (res) =&gt; {
1900
+ // A2A-54: size-capped response accumulation
1901
+ handleSizeCappedResponse(res, resolve, reject, (data, statusCode) =&gt; {
1902
+ try {
1903
+ const json = JSON.parse(data);
1904
+ if (statusCode &gt;= 400) {
1905
+ reject(new A2AError(json.error <span class="branch-0 cbranch-no" title="branch not covered" >|| 'request_failed',</span> json.message <span class="branch-0 cbranch-no" title="branch not covered" >|| data,</span> statusCode));
1906
+ } else {
1907
+ resolve(json);
1908
+ }
1909
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (e) {</span>
1910
+ <span class="cstat-no" title="statement not covered" > reject(new A2AError('parse_error', `Failed to parse response: ${data}`, statusCode));</span>
1911
+ <span class="cstat-no" title="statement not covered" > }</span>
1912
+ });
1913
+ });
1914
+ &nbsp;
1915
+ req.on('error', (e) =&gt; {
1916
+ reject(new A2AError('network_error', e.code ? `${e.code}: ${e.message}` <span class="branch-0 cbranch-no" title="branch not covered" >: e.message)</span>);
1917
+ });
1918
+ &nbsp;
1919
+ req.on('timeout', () =&gt; {
1920
+ <span class="cstat-no" title="statement not covered" > req.destroy();</span>
1921
+ <span class="cstat-no" title="statement not covered" > reject(new A2AError('timeout', 'Request timed out'));</span>
1922
+ });
1923
+ &nbsp;
1924
+ req.write(body);
1925
+ req.end();
1926
+ });
1927
+ &nbsp;
1928
+ return withRetry(makeRequest, { delays: this._retryDelays });
1929
+ }
1930
+ &nbsp;
1931
+ // End a remote conversation — no-op for Google A2A remotes
1932
+ async end(endpoint, conversationId) {
1933
+ if (!conversationId) {
1934
+ throw new A2AError('missing_conversation_id', 'conversationId is required');
1935
+ }
1936
+ &nbsp;
1937
+ let host, token;
1938
+ &nbsp;
1939
+ if (typeof endpoint === 'string') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1940
+ <span class="cstat-no" title="statement not covered" > ({ host, token } = A2AClient.parseInvite(endpoint));</span>
1941
+ } else {
1942
+ ({ host, token } = endpoint);
1943
+ }
1944
+ &nbsp;
1945
+ // A2A-80: Google A2A remotes don't have an end endpoint — return synthetic response
1946
+ const agentCard = await fetchRemoteAgentCard(host);
1947
+ if (agentCard) {
1948
+ logger.info('Skipping end() for Google A2A remote', {
1949
+ event: 'google_a2a_end_skipped',
1950
+ data: { conversationId, host }
1951
+ });
1952
+ return { ended: true, summary: null };
1953
+ }
1954
+ &nbsp;
1955
+ // Proprietary format path (unchanged)
1956
+ const body = JSON.stringify({
1957
+ conversation_id: conversationId
1958
+ });
1959
+ &nbsp;
1960
+ const { protocol, hostname, port } = resolveProtocolAndPort(host);
1961
+ // A2A-52: attach signature headers when keypair available
1962
+ const sigHeaders = this._signHeaders('POST', '/api/a2a/end', body);
1963
+ &nbsp;
1964
+ // A2A-54: wrap with retry for transient network failures
1965
+ const makeRequest = () =&gt; new Promise((resolve, reject) =&gt; {
1966
+ const req = protocol.request({
1967
+ hostname,
1968
+ port,
1969
+ path: '/api/a2a/end',
1970
+ method: 'POST',
1971
+ headers: {
1972
+ 'Authorization': `Bearer ${token}`,
1973
+ 'Content-Type': 'application/json',
1974
+ 'Content-Length': Buffer.byteLength(body),
1975
+ ...sigHeaders
1976
+ },
1977
+ timeout: this.timeout
1978
+ }, (res) =&gt; {
1979
+ // A2A-54: size-capped response accumulation
1980
+ handleSizeCappedResponse(res, resolve, reject, (data, statusCode) =&gt; {
1981
+ try {
1982
+ const json = JSON.parse(data);
1983
+ if (statusCode &gt;= 400) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1984
+ <span class="cstat-no" title="statement not covered" > reject(new A2AError(json.error || 'request_failed', json.message || data, statusCode));</span>
1985
+ } else {
1986
+ resolve(json);
1987
+ }
1988
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (e) {</span>
1989
+ <span class="cstat-no" title="statement not covered" > reject(new A2AError('parse_error', `Failed to parse response: ${data}`, statusCode));</span>
1990
+ <span class="cstat-no" title="statement not covered" > }</span>
1991
+ });
1992
+ });
1993
+ &nbsp;
1994
+ req.on('error', (e) =&gt; {
1995
+ reject(new A2AError('network_error', e.code ? `${e.code}: ${e.message}` <span class="branch-0 cbranch-no" title="branch not covered" >: e.message)</span>);
1996
+ });
1997
+ &nbsp;
1998
+ req.on('timeout', () =&gt; {
1999
+ <span class="cstat-no" title="statement not covered" > req.destroy();</span>
2000
+ <span class="cstat-no" title="statement not covered" > reject(new A2AError('timeout', 'Request timed out'));</span>
2001
+ });
2002
+ &nbsp;
2003
+ req.write(body);
2004
+ req.end();
2005
+ });
2006
+ &nbsp;
2007
+ return withRetry(makeRequest, { delays: this._retryDelays });
2008
+ }
2009
+ &nbsp;
2010
+ async ping(endpoint) {
2011
+ let host;
2012
+ &nbsp;
2013
+ if (typeof endpoint === 'string') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2014
+ <span class="cstat-no" title="statement not covered" > ({ host } = A2AClient.parseInvite(endpoint));</span>
2015
+ } else {
2016
+ ({ host } = endpoint);
2017
+ }
2018
+ &nbsp;
2019
+ const { protocol, hostname, port } = resolveProtocolAndPort(host);
2020
+ &nbsp;
2021
+ // A2A-54: no retry for ping — it's a lightweight probe, not a critical call
2022
+ return new Promise((resolve, reject) =&gt; {
2023
+ const req = protocol.request({
2024
+ hostname,
2025
+ port,
2026
+ path: '/api/a2a/ping',
2027
+ method: 'GET',
2028
+ timeout: 5000
2029
+ }, (res) =&gt; {
2030
+ // A2A-54: size-capped response accumulation
2031
+ handleSizeCappedResponse(res, resolve, reject, (data, statusCode) =&gt; {
2032
+ try {
2033
+ resolve(JSON.parse(data));
2034
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch {</span>
2035
+ <span class="cstat-no" title="statement not covered" > resolve({ pong: statusCode === 200 });</span>
2036
+ <span class="cstat-no" title="statement not covered" > }</span>
2037
+ });
2038
+ });
2039
+ &nbsp;
2040
+ req.on('error', () =&gt; resolve({ pong: false }));
2041
+ req.on('timeout', () =&gt; {
2042
+ <span class="cstat-no" title="statement not covered" > req.destroy();</span>
2043
+ <span class="cstat-no" title="statement not covered" > resolve({ pong: false });</span>
2044
+ });
2045
+ req.end();
2046
+ });
2047
+ }
2048
+ &nbsp;
2049
+ async status(endpoint) {
2050
+ let host;
2051
+ &nbsp;
2052
+ if (typeof endpoint === 'string') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2053
+ <span class="cstat-no" title="statement not covered" > ({ host } = A2AClient.parseInvite(endpoint));</span>
2054
+ } else {
2055
+ ({ host } = endpoint);
2056
+ }
2057
+ &nbsp;
2058
+ const { protocol, hostname, port } = resolveProtocolAndPort(host);
2059
+ &nbsp;
2060
+ // A2A-54: no retry for status — read-only probe, not a stateful operation
2061
+ return new Promise((resolve, reject) =&gt; {
2062
+ const req = protocol.request({
2063
+ hostname,
2064
+ port,
2065
+ path: '/api/a2a/status',
2066
+ method: 'GET',
2067
+ timeout: 5000
2068
+ }, (res) =&gt; {
2069
+ // A2A-54: size-capped response accumulation
2070
+ handleSizeCappedResponse(res, resolve, reject, (data) =&gt; {
2071
+ try {
2072
+ resolve(JSON.parse(data));
2073
+ } catch {
2074
+ reject(new A2AError('parse_error', 'Invalid status response'));
2075
+ }
2076
+ });
2077
+ });
2078
+ &nbsp;
2079
+ req.on('error', (e) =&gt; reject(new A2AError('network_error', e.code ? `${e.code}: ${e.message}` <span class="branch-0 cbranch-no" title="branch not covered" >: e.message)</span>));
2080
+ req.on('timeout', () =&gt; {
2081
+ <span class="cstat-no" title="statement not covered" > req.destroy();</span>
2082
+ <span class="cstat-no" title="statement not covered" > reject(new A2AError('timeout', 'Request timed out'));</span>
2083
+ });
2084
+ req.end();
2085
+ });
2086
+ }
2087
+ }
2088
+ &nbsp;
2089
+ class A2AError extends Error {
2090
+ constructor(code, message, statusCode = null) {
2091
+ super(message);
2092
+ this.name = 'A2AError';
2093
+ this.code = code;
2094
+ this.statusCode = statusCode;
2095
+ }
2096
+ }
2097
+ &nbsp;
2098
+ // A2A-54: export internals for testing (splitHostPort, resolveProtocolAndPort, constants)
2099
+ // A2A-80: export Agent Card cache and helpers for testing
2100
+ module.exports = {
2101
+ A2AClient,
2102
+ A2AError,
2103
+ _splitHostPort: splitHostPort,
2104
+ _resolveProtocolAndPort: resolveProtocolAndPort,
2105
+ _MAX_RESPONSE_BYTES: MAX_RESPONSE_BYTES,
2106
+ _RETRYABLE_CODES: RETRYABLE_CODES,
2107
+ _RETRY_DELAYS: RETRY_DELAYS,
2108
+ _agentCardCache,
2109
+ _parseAgentCard,
2110
+ _translateToGoogleRequest,
2111
+ _translateGoogleResponse,
2112
+ _resolveGoogleA2AUrl,
2113
+ fetchRemoteAgentCard
2114
+ };
2115
+ &nbsp;</pre></td></tr></table></pre>
2116
+
2117
+ <div class='push'></div><!-- for sticky footer -->
2118
+ </div><!-- /wrapper -->
2119
+ <div class='footer quiet pad2 space-top1 center small'>
2120
+ Code coverage generated by
2121
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
2122
+ at 2026-03-03T22:25:10.857Z
2123
+ </div>
2124
+ <script src="../../prettify.js"></script>
2125
+ <script>
2126
+ window.onload = function () {
2127
+ prettyPrint();
2128
+ };
2129
+ </script>
2130
+ <script src="../../sorter.js"></script>
2131
+ <script src="../../block-navigation.js"></script>
2132
+ </body>
2133
+ </html>
2134
+