a2acalling 0.6.74 → 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 (118) 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 +11 -0
  6. package/CONVENTIONS.md +9 -0
  7. package/coverage/base.css +224 -0
  8. package/coverage/block-navigation.js +87 -0
  9. package/coverage/favicon.png +0 -0
  10. package/coverage/index.html +146 -0
  11. package/coverage/prettify.css +1 -0
  12. package/coverage/prettify.js +2 -0
  13. package/coverage/sort-arrow-sprite.png +0 -0
  14. package/coverage/sorter.js +210 -0
  15. package/coverage/src/index.html +131 -0
  16. package/coverage/src/index.js.html +313 -0
  17. package/coverage/src/lib/agent-card.js.html +418 -0
  18. package/coverage/src/lib/call-monitor.js.html +700 -0
  19. package/coverage/src/lib/callbook.js.html +1183 -0
  20. package/coverage/src/lib/claude-subagent.js.html +2173 -0
  21. package/coverage/src/lib/client.js.html +2134 -0
  22. package/coverage/src/lib/config.js.html +1525 -0
  23. package/coverage/src/lib/conversation-driver.js.html +1909 -0
  24. package/coverage/src/lib/conversations.js.html +2575 -0
  25. package/coverage/src/lib/crypto.js.html +424 -0
  26. package/coverage/src/lib/dashboard-events.js.html +724 -0
  27. package/coverage/src/lib/disclosure.js.html +2461 -0
  28. package/coverage/src/lib/external-ip.js.html +718 -0
  29. package/coverage/src/lib/index.html +506 -0
  30. package/coverage/src/lib/invite-host.js.html +754 -0
  31. package/coverage/src/lib/local-request.js.html +292 -0
  32. package/coverage/src/lib/logger.js.html +2116 -0
  33. package/coverage/src/lib/openclaw-integration.js.html +1102 -0
  34. package/coverage/src/lib/pid-file.js.html +394 -0
  35. package/coverage/src/lib/port-scanner.js.html +334 -0
  36. package/coverage/src/lib/prompt-template.js.html +1150 -0
  37. package/coverage/src/lib/runtime-adapter.js.html +2188 -0
  38. package/coverage/src/lib/summarizer.js.html +553 -0
  39. package/coverage/src/lib/summary-formatter.js.html +589 -0
  40. package/coverage/src/lib/summary-prompt.js.html +694 -0
  41. package/coverage/src/lib/tokens.js.html +2689 -0
  42. package/coverage/src/lib/turn-timeout.js.html +241 -0
  43. package/coverage/src/lib/update-checker.js.html +364 -0
  44. package/coverage/src/lib/update-manager.js.html +1024 -0
  45. package/coverage/src/routes/a2a.js.html +3724 -0
  46. package/coverage/src/routes/callbook.js.html +511 -0
  47. package/coverage/src/routes/dashboard.js.html +4819 -0
  48. package/coverage/src/routes/index.html +146 -0
  49. package/coverage/src/server.js.html +3622 -0
  50. package/coverage/tmp/coverage-1605378-1772576706365-0.json +1 -0
  51. package/coverage/tmp/coverage-1605384-1772576607459-0.json +1 -0
  52. package/coverage/tmp/coverage-1605410-1772576631155-0.json +1 -0
  53. package/coverage/tmp/coverage-1606942-1772576636869-0.json +1 -0
  54. package/coverage/tmp/coverage-1607004-1772576637454-0.json +1 -0
  55. package/coverage/tmp/coverage-1607044-1772576637876-0.json +1 -0
  56. package/coverage/tmp/coverage-1607096-1772576638356-0.json +1 -0
  57. package/coverage/tmp/coverage-1607145-1772576638777-0.json +1 -0
  58. package/coverage/tmp/coverage-1607201-1772576639277-0.json +1 -0
  59. package/coverage/tmp/coverage-1607247-1772576639755-0.json +1 -0
  60. package/coverage/tmp/coverage-1607317-1772576640083-0.json +1 -0
  61. package/coverage/tmp/coverage-1607381-1772576640465-0.json +1 -0
  62. package/coverage/tmp/coverage-1607446-1772576640868-0.json +1 -0
  63. package/coverage/tmp/coverage-1607501-1772576641662-0.json +1 -0
  64. package/coverage/tmp/coverage-1607534-1772576641565-0.json +1 -0
  65. package/coverage/tmp/coverage-1607627-1772576641871-0.json +1 -0
  66. package/coverage/tmp/coverage-1607665-1772576642172-0.json +1 -0
  67. package/coverage/tmp/coverage-1607714-1772576642577-0.json +1 -0
  68. package/coverage/tmp/coverage-1607788-1772576643466-0.json +1 -0
  69. package/coverage/tmp/coverage-1607924-1772576644678-0.json +1 -0
  70. package/coverage/tmp/coverage-1607978-1772576645154-0.json +1 -0
  71. package/coverage/tmp/coverage-1608035-1772576645564-0.json +1 -0
  72. package/coverage/tmp/coverage-1608106-1772576645967-0.json +1 -0
  73. package/coverage/tmp/coverage-1608179-1772576648656-0.json +1 -0
  74. package/coverage/tmp/coverage-1608196-1772576647367-0.json +1 -0
  75. package/coverage/tmp/coverage-1608217-1772576648557-0.json +1 -0
  76. package/coverage/tmp/coverage-1608256-1772576651378-0.json +1 -0
  77. package/coverage/tmp/coverage-1608265-1772576650058-0.json +1 -0
  78. package/coverage/tmp/coverage-1608289-1772576651358-0.json +1 -0
  79. package/coverage/tmp/coverage-1608591-1772576660465-0.json +1 -0
  80. package/coverage/tmp/coverage-1608648-1772576659272-0.json +1 -0
  81. package/coverage/tmp/coverage-1608665-1772576660374-0.json +1 -0
  82. package/coverage/tmp/coverage-1608677-1772576661268-0.json +1 -0
  83. package/coverage/tmp/coverage-1608684-1772576663968-0.json +1 -0
  84. package/coverage/tmp/coverage-1608692-1772576662575-0.json +1 -0
  85. package/coverage/tmp/coverage-1608701-1772576663873-0.json +1 -0
  86. package/coverage/tmp/coverage-1608718-1772576666674-0.json +1 -0
  87. package/coverage/tmp/coverage-1608725-1772576665463-0.json +1 -0
  88. package/coverage/tmp/coverage-1608738-1772576666577-0.json +1 -0
  89. package/coverage/tmp/coverage-1608753-1772576669664-0.json +1 -0
  90. package/coverage/tmp/coverage-1608763-1772576668275-0.json +1 -0
  91. package/coverage/tmp/coverage-1608771-1772576669563-0.json +1 -0
  92. package/coverage/tmp/coverage-1608828-1772576676574-0.json +1 -0
  93. package/coverage/tmp/coverage-1609244-1772576675272-0.json +1 -0
  94. package/coverage/tmp/coverage-1609342-1772576676478-0.json +1 -0
  95. package/coverage/tmp/coverage-1609450-1772576686954-0.json +1 -0
  96. package/coverage/tmp/coverage-1609841-1772576685466-0.json +1 -0
  97. package/coverage/tmp/coverage-1609925-1772576686855-0.json +1 -0
  98. package/coverage/tmp/coverage-1610399-1772576692469-0.json +1 -0
  99. package/coverage/tmp/coverage-1611283-1772576703062-0.json +1 -0
  100. package/coverage/tmp/coverage-1611294-1772576703755-0.json +1 -0
  101. package/docs/plans/2026-03-03-a2a-91-macos-packaging-plan.md +144 -0
  102. package/docs/signing-setup.md +49 -0
  103. package/native/macos/certs/appldevcert.cer +0 -0
  104. package/native/macos/src-tauri/binaries/.gitkeep +0 -0
  105. package/native/macos/src-tauri/capabilities/default.json +11 -1
  106. package/native/macos/src-tauri/entitlements.plist +14 -0
  107. package/native/macos/src-tauri/src/discovery.rs +14 -3
  108. package/native/macos/src-tauri/src/health.rs +4 -0
  109. package/native/macos/src-tauri/src/lib.rs +52 -11
  110. package/native/macos/src-tauri/src/server.rs +262 -26
  111. package/native/macos/src-tauri/tauri.conf.json +13 -4
  112. package/package.json +7 -2
  113. package/pkg.config.json +14 -0
  114. package/scripts/build-standalone.sh +106 -0
  115. package/scripts/smoke-test-standalone.sh +101 -0
  116. package/scripts/sync-version.sh +28 -0
  117. package/scripts/verify-app-bundle.sh +34 -0
  118. package/.maestro/inbox/release-workflow-spam.md +0 -25
@@ -0,0 +1,1525 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/lib/config.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> config.js</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">89.79% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>431/480</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">71.56% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>73/102</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">96.42% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>27/28</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">89.79% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>431/480</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></td><td class="line-coverage quiet"><span class="cline-any cline-yes">82x</span>
547
+ <span class="cline-any cline-yes">82x</span>
548
+ <span class="cline-any cline-yes">82x</span>
549
+ <span class="cline-any cline-yes">82x</span>
550
+ <span class="cline-any cline-yes">82x</span>
551
+ <span class="cline-any cline-yes">82x</span>
552
+ <span class="cline-any cline-yes">82x</span>
553
+ <span class="cline-any cline-yes">82x</span>
554
+ <span class="cline-any cline-yes">82x</span>
555
+ <span class="cline-any cline-yes">82x</span>
556
+ <span class="cline-any cline-yes">82x</span>
557
+ <span class="cline-any cline-yes">82x</span>
558
+ <span class="cline-any cline-yes">82x</span>
559
+ <span class="cline-any cline-yes">82x</span>
560
+ <span class="cline-any cline-yes">82x</span>
561
+ <span class="cline-any cline-yes">82x</span>
562
+ <span class="cline-any cline-yes">82x</span>
563
+ <span class="cline-any cline-yes">72x</span>
564
+ <span class="cline-any cline-yes">72x</span>
565
+ <span class="cline-any cline-yes">72x</span>
566
+ <span class="cline-any cline-yes">82x</span>
567
+ <span class="cline-any cline-yes">3x</span>
568
+ <span class="cline-any cline-yes">3x</span>
569
+ <span class="cline-any cline-yes">3x</span>
570
+ <span class="cline-any cline-yes">3x</span>
571
+ <span class="cline-any cline-yes">3x</span>
572
+ <span class="cline-any cline-yes">3x</span>
573
+ <span class="cline-any cline-yes">3x</span>
574
+ <span class="cline-any cline-yes">82x</span>
575
+ <span class="cline-any cline-yes">59x</span>
576
+ <span class="cline-any cline-yes">59x</span>
577
+ <span class="cline-any cline-yes">59x</span>
578
+ <span class="cline-any cline-yes">59x</span>
579
+ <span class="cline-any cline-yes">59x</span>
580
+ <span class="cline-any cline-yes">59x</span>
581
+ <span class="cline-any cline-yes">82x</span>
582
+ <span class="cline-any cline-yes">42x</span>
583
+ <span class="cline-any cline-yes">42x</span>
584
+ <span class="cline-any cline-yes">42x</span>
585
+ <span class="cline-any cline-yes">42x</span>
586
+ <span class="cline-any cline-yes">42x</span>
587
+ <span class="cline-any cline-yes">2x</span>
588
+ <span class="cline-any cline-yes">2x</span>
589
+ <span class="cline-any cline-yes">2x</span>
590
+ <span class="cline-any cline-yes">2x</span>
591
+ <span class="cline-any cline-yes">2x</span>
592
+ <span class="cline-any cline-yes">2x</span>
593
+ <span class="cline-any cline-yes">2x</span>
594
+ <span class="cline-any cline-yes">40x</span>
595
+ <span class="cline-any cline-yes">40x</span>
596
+ <span class="cline-any cline-yes">40x</span>
597
+ <span class="cline-any cline-yes">42x</span>
598
+ <span class="cline-any cline-yes">55x</span>
599
+ <span class="cline-any cline-yes">1x</span>
600
+ <span class="cline-any cline-yes">1x</span>
601
+ <span class="cline-any cline-yes">1x</span>
602
+ <span class="cline-any cline-yes">1x</span>
603
+ <span class="cline-any cline-yes">1x</span>
604
+ <span class="cline-any cline-yes">1x</span>
605
+ <span class="cline-any cline-yes">1x</span>
606
+ <span class="cline-any cline-yes">54x</span>
607
+ <span class="cline-any cline-yes">55x</span>
608
+ <span class="cline-any cline-yes">54x</span>
609
+ <span class="cline-any cline-yes">55x</span>
610
+ <span class="cline-any cline-yes">54x</span>
611
+ <span class="cline-any cline-yes">54x</span>
612
+ <span class="cline-any cline-yes">55x</span>
613
+ <span class="cline-any cline-yes">55x</span>
614
+ <span class="cline-any cline-yes">39x</span>
615
+ <span class="cline-any cline-yes">39x</span>
616
+ <span class="cline-any cline-yes">42x</span>
617
+ <span class="cline-any cline-yes">82x</span>
618
+ <span class="cline-any cline-yes">26x</span>
619
+ <span class="cline-any cline-yes">26x</span>
620
+ <span class="cline-any cline-no">&nbsp;</span>
621
+ <span class="cline-any cline-no">&nbsp;</span>
622
+ <span class="cline-any cline-no">&nbsp;</span>
623
+ <span class="cline-any cline-no">&nbsp;</span>
624
+ <span class="cline-any cline-no">&nbsp;</span>
625
+ <span class="cline-any cline-no">&nbsp;</span>
626
+ <span class="cline-any cline-no">&nbsp;</span>
627
+ <span class="cline-any cline-yes">26x</span>
628
+ <span class="cline-any cline-yes">26x</span>
629
+ <span class="cline-any cline-yes">26x</span>
630
+ <span class="cline-any cline-yes">26x</span>
631
+ <span class="cline-any cline-yes">2x</span>
632
+ <span class="cline-any cline-no">&nbsp;</span>
633
+ <span class="cline-any cline-no">&nbsp;</span>
634
+ <span class="cline-any cline-no">&nbsp;</span>
635
+ <span class="cline-any cline-no">&nbsp;</span>
636
+ <span class="cline-any cline-no">&nbsp;</span>
637
+ <span class="cline-any cline-no">&nbsp;</span>
638
+ <span class="cline-any cline-no">&nbsp;</span>
639
+ <span class="cline-any cline-yes">2x</span>
640
+ <span class="cline-any cline-yes">2x</span>
641
+ <span class="cline-any cline-yes">26x</span>
642
+ <span class="cline-any cline-yes">26x</span>
643
+ <span class="cline-any cline-yes">3x</span>
644
+ <span class="cline-any cline-no">&nbsp;</span>
645
+ <span class="cline-any cline-no">&nbsp;</span>
646
+ <span class="cline-any cline-no">&nbsp;</span>
647
+ <span class="cline-any cline-no">&nbsp;</span>
648
+ <span class="cline-any cline-no">&nbsp;</span>
649
+ <span class="cline-any cline-no">&nbsp;</span>
650
+ <span class="cline-any cline-no">&nbsp;</span>
651
+ <span class="cline-any cline-yes">3x</span>
652
+ <span class="cline-any cline-yes">3x</span>
653
+ <span class="cline-any cline-yes">26x</span>
654
+ <span class="cline-any cline-yes">26x</span>
655
+ <span class="cline-any cline-yes">26x</span>
656
+ <span class="cline-any cline-yes">26x</span>
657
+ <span class="cline-any cline-yes">26x</span>
658
+ <span class="cline-any cline-yes">3x</span>
659
+ <span class="cline-any cline-yes">3x</span>
660
+ <span class="cline-any cline-yes">3x</span>
661
+ <span class="cline-any cline-yes">3x</span>
662
+ <span class="cline-any cline-yes">3x</span>
663
+ <span class="cline-any cline-yes">26x</span>
664
+ <span class="cline-any cline-yes">26x</span>
665
+ <span class="cline-any cline-yes">2x</span>
666
+ <span class="cline-any cline-yes">2x</span>
667
+ <span class="cline-any cline-yes">2x</span>
668
+ <span class="cline-any cline-yes">2x</span>
669
+ <span class="cline-any cline-yes">2x</span>
670
+ <span class="cline-any cline-yes">26x</span>
671
+ <span class="cline-any cline-yes">26x</span>
672
+ <span class="cline-any cline-yes">24x</span>
673
+ <span class="cline-any cline-yes">24x</span>
674
+ <span class="cline-any cline-yes">24x</span>
675
+ <span class="cline-any cline-yes">24x</span>
676
+ <span class="cline-any cline-yes">24x</span>
677
+ <span class="cline-any cline-yes">24x</span>
678
+ <span class="cline-any cline-yes">26x</span>
679
+ <span class="cline-any cline-yes">11x</span>
680
+ <span class="cline-any cline-yes">11x</span>
681
+ <span class="cline-any cline-yes">11x</span>
682
+ <span class="cline-any cline-yes">11x</span>
683
+ <span class="cline-any cline-yes">11x</span>
684
+ <span class="cline-any cline-yes">23x</span>
685
+ <span class="cline-any cline-yes">26x</span>
686
+ <span class="cline-any cline-yes">2x</span>
687
+ <span class="cline-any cline-yes">2x</span>
688
+ <span class="cline-any cline-yes">2x</span>
689
+ <span class="cline-any cline-yes">2x</span>
690
+ <span class="cline-any cline-yes">2x</span>
691
+ <span class="cline-any cline-yes">23x</span>
692
+ <span class="cline-any cline-yes">23x</span>
693
+ <span class="cline-any cline-yes">26x</span>
694
+ <span class="cline-any cline-yes">82x</span>
695
+ <span class="cline-any cline-yes">256x</span>
696
+ <span class="cline-any cline-yes">256x</span>
697
+ <span class="cline-any cline-yes">256x</span>
698
+ <span class="cline-any cline-yes">256x</span>
699
+ <span class="cline-any cline-no">&nbsp;</span>
700
+ <span class="cline-any cline-no">&nbsp;</span>
701
+ <span class="cline-any cline-yes">256x</span>
702
+ <span class="cline-any cline-yes">256x</span>
703
+ <span class="cline-any cline-yes">755x</span>
704
+ <span class="cline-any cline-yes">755x</span>
705
+ <span class="cline-any cline-yes">755x</span>
706
+ <span class="cline-any cline-yes">755x</span>
707
+ <span class="cline-any cline-yes">755x</span>
708
+ <span class="cline-any cline-yes">256x</span>
709
+ <span class="cline-any cline-yes">256x</span>
710
+ <span class="cline-any cline-yes">82x</span>
711
+ <span class="cline-any cline-yes">82x</span>
712
+ <span class="cline-any cline-yes">82x</span>
713
+ <span class="cline-any cline-yes">82x</span>
714
+ <span class="cline-any cline-yes">82x</span>
715
+ <span class="cline-any cline-yes">82x</span>
716
+ <span class="cline-any cline-yes">82x</span>
717
+ <span class="cline-any cline-yes">82x</span>
718
+ <span class="cline-any cline-yes">82x</span>
719
+ <span class="cline-any cline-yes">82x</span>
720
+ <span class="cline-any cline-yes">82x</span>
721
+ <span class="cline-any cline-yes">82x</span>
722
+ <span class="cline-any cline-yes">82x</span>
723
+ <span class="cline-any cline-yes">82x</span>
724
+ <span class="cline-any cline-yes">82x</span>
725
+ <span class="cline-any cline-yes">82x</span>
726
+ <span class="cline-any cline-yes">82x</span>
727
+ <span class="cline-any cline-yes">82x</span>
728
+ <span class="cline-any cline-yes">82x</span>
729
+ <span class="cline-any cline-yes">82x</span>
730
+ <span class="cline-any cline-yes">82x</span>
731
+ <span class="cline-any cline-yes">82x</span>
732
+ <span class="cline-any cline-yes">82x</span>
733
+ <span class="cline-any cline-yes">82x</span>
734
+ <span class="cline-any cline-yes">82x</span>
735
+ <span class="cline-any cline-yes">82x</span>
736
+ <span class="cline-any cline-yes">82x</span>
737
+ <span class="cline-any cline-yes">82x</span>
738
+ <span class="cline-any cline-yes">82x</span>
739
+ <span class="cline-any cline-yes">82x</span>
740
+ <span class="cline-any cline-yes">82x</span>
741
+ <span class="cline-any cline-yes">82x</span>
742
+ <span class="cline-any cline-yes">82x</span>
743
+ <span class="cline-any cline-yes">82x</span>
744
+ <span class="cline-any cline-yes">82x</span>
745
+ <span class="cline-any cline-yes">82x</span>
746
+ <span class="cline-any cline-yes">82x</span>
747
+ <span class="cline-any cline-yes">82x</span>
748
+ <span class="cline-any cline-yes">82x</span>
749
+ <span class="cline-any cline-yes">82x</span>
750
+ <span class="cline-any cline-yes">82x</span>
751
+ <span class="cline-any cline-yes">82x</span>
752
+ <span class="cline-any cline-yes">82x</span>
753
+ <span class="cline-any cline-yes">82x</span>
754
+ <span class="cline-any cline-yes">82x</span>
755
+ <span class="cline-any cline-yes">82x</span>
756
+ <span class="cline-any cline-yes">82x</span>
757
+ <span class="cline-any cline-yes">82x</span>
758
+ <span class="cline-any cline-yes">82x</span>
759
+ <span class="cline-any cline-yes">82x</span>
760
+ <span class="cline-any cline-yes">82x</span>
761
+ <span class="cline-any cline-yes">82x</span>
762
+ <span class="cline-any cline-yes">82x</span>
763
+ <span class="cline-any cline-yes">82x</span>
764
+ <span class="cline-any cline-yes">82x</span>
765
+ <span class="cline-any cline-yes">82x</span>
766
+ <span class="cline-any cline-yes">82x</span>
767
+ <span class="cline-any cline-yes">82x</span>
768
+ <span class="cline-any cline-yes">82x</span>
769
+ <span class="cline-any cline-yes">82x</span>
770
+ <span class="cline-any cline-yes">82x</span>
771
+ <span class="cline-any cline-yes">82x</span>
772
+ <span class="cline-any cline-yes">82x</span>
773
+ <span class="cline-any cline-yes">82x</span>
774
+ <span class="cline-any cline-yes">82x</span>
775
+ <span class="cline-any cline-yes">82x</span>
776
+ <span class="cline-any cline-yes">82x</span>
777
+ <span class="cline-any cline-yes">82x</span>
778
+ <span class="cline-any cline-yes">82x</span>
779
+ <span class="cline-any cline-yes">82x</span>
780
+ <span class="cline-any cline-yes">82x</span>
781
+ <span class="cline-any cline-yes">82x</span>
782
+ <span class="cline-any cline-yes">82x</span>
783
+ <span class="cline-any cline-yes">82x</span>
784
+ <span class="cline-any cline-yes">82x</span>
785
+ <span class="cline-any cline-yes">82x</span>
786
+ <span class="cline-any cline-yes">82x</span>
787
+ <span class="cline-any cline-yes">82x</span>
788
+ <span class="cline-any cline-yes">82x</span>
789
+ <span class="cline-any cline-yes">82x</span>
790
+ <span class="cline-any cline-yes">82x</span>
791
+ <span class="cline-any cline-yes">82x</span>
792
+ <span class="cline-any cline-yes">82x</span>
793
+ <span class="cline-any cline-yes">82x</span>
794
+ <span class="cline-any cline-yes">82x</span>
795
+ <span class="cline-any cline-yes">82x</span>
796
+ <span class="cline-any cline-yes">82x</span>
797
+ <span class="cline-any cline-yes">82x</span>
798
+ <span class="cline-any cline-yes">82x</span>
799
+ <span class="cline-any cline-yes">82x</span>
800
+ <span class="cline-any cline-yes">82x</span>
801
+ <span class="cline-any cline-yes">82x</span>
802
+ <span class="cline-any cline-yes">82x</span>
803
+ <span class="cline-any cline-yes">82x</span>
804
+ <span class="cline-any cline-yes">82x</span>
805
+ <span class="cline-any cline-yes">82x</span>
806
+ <span class="cline-any cline-yes">82x</span>
807
+ <span class="cline-any cline-yes">82x</span>
808
+ <span class="cline-any cline-yes">82x</span>
809
+ <span class="cline-any cline-yes">82x</span>
810
+ <span class="cline-any cline-yes">86x</span>
811
+ <span class="cline-any cline-yes">86x</span>
812
+ <span class="cline-any cline-yes">86x</span>
813
+ <span class="cline-any cline-yes">82x</span>
814
+ <span class="cline-any cline-yes">82x</span>
815
+ <span class="cline-any cline-yes">86x</span>
816
+ <span class="cline-any cline-yes">1x</span>
817
+ <span class="cline-any cline-yes">1x</span>
818
+ <span class="cline-any cline-yes">86x</span>
819
+ <span class="cline-any cline-yes">82x</span>
820
+ <span class="cline-any cline-yes">82x</span>
821
+ <span class="cline-any cline-yes">86x</span>
822
+ <span class="cline-any cline-yes">51x</span>
823
+ <span class="cline-any cline-yes">51x</span>
824
+ <span class="cline-any cline-yes">51x</span>
825
+ <span class="cline-any cline-yes">51x</span>
826
+ <span class="cline-any cline-no">&nbsp;</span>
827
+ <span class="cline-any cline-no">&nbsp;</span>
828
+ <span class="cline-any cline-no">&nbsp;</span>
829
+ <span class="cline-any cline-no">&nbsp;</span>
830
+ <span class="cline-any cline-no">&nbsp;</span>
831
+ <span class="cline-any cline-no">&nbsp;</span>
832
+ <span class="cline-any cline-no">&nbsp;</span>
833
+ <span class="cline-any cline-no">&nbsp;</span>
834
+ <span class="cline-any cline-no">&nbsp;</span>
835
+ <span class="cline-any cline-no">&nbsp;</span>
836
+ <span class="cline-any cline-no">&nbsp;</span>
837
+ <span class="cline-any cline-yes">51x</span>
838
+ <span class="cline-any cline-yes">35x</span>
839
+ <span class="cline-any cline-yes">86x</span>
840
+ <span class="cline-any cline-yes">82x</span>
841
+ <span class="cline-any cline-yes">82x</span>
842
+ <span class="cline-any cline-yes">61x</span>
843
+ <span class="cline-any cline-yes">61x</span>
844
+ <span class="cline-any cline-yes">30x</span>
845
+ <span class="cline-any cline-yes">30x</span>
846
+ <span class="cline-any cline-yes">61x</span>
847
+ <span class="cline-any cline-yes">61x</span>
848
+ <span class="cline-any cline-yes">61x</span>
849
+ <span class="cline-any cline-yes">61x</span>
850
+ <span class="cline-any cline-yes">61x</span>
851
+ <span class="cline-any cline-yes">61x</span>
852
+ <span class="cline-any cline-no">&nbsp;</span>
853
+ <span class="cline-any cline-no">&nbsp;</span>
854
+ <span class="cline-any cline-yes">61x</span>
855
+ <span class="cline-any cline-yes">82x</span>
856
+ <span class="cline-any cline-yes">82x</span>
857
+ <span class="cline-any cline-yes">82x</span>
858
+ <span class="cline-any cline-yes">28x</span>
859
+ <span class="cline-any cline-yes">28x</span>
860
+ <span class="cline-any cline-yes">28x</span>
861
+ <span class="cline-any cline-yes">28x</span>
862
+ <span class="cline-any cline-yes">82x</span>
863
+ <span class="cline-any cline-yes">82x</span>
864
+ <span class="cline-any cline-yes">82x</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">9x</span>
873
+ <span class="cline-any cline-yes">9x</span>
874
+ <span class="cline-any cline-yes">82x</span>
875
+ <span class="cline-any cline-yes">82x</span>
876
+ <span class="cline-any cline-yes">82x</span>
877
+ <span class="cline-any cline-yes">2x</span>
878
+ <span class="cline-any cline-yes">2x</span>
879
+ <span class="cline-any cline-yes">2x</span>
880
+ <span class="cline-any cline-yes">2x</span>
881
+ <span class="cline-any cline-yes">2x</span>
882
+ <span class="cline-any cline-yes">2x</span>
883
+ <span class="cline-any cline-yes">2x</span>
884
+ <span class="cline-any cline-yes">2x</span>
885
+ <span class="cline-any cline-yes">2x</span>
886
+ <span class="cline-any cline-yes">82x</span>
887
+ <span class="cline-any cline-yes">82x</span>
888
+ <span class="cline-any cline-yes">8x</span>
889
+ <span class="cline-any cline-yes">8x</span>
890
+ <span class="cline-any cline-yes">8x</span>
891
+ <span class="cline-any cline-yes">8x</span>
892
+ <span class="cline-any cline-yes">8x</span>
893
+ <span class="cline-any cline-yes">82x</span>
894
+ <span class="cline-any cline-yes">82x</span>
895
+ <span class="cline-any cline-no">&nbsp;</span>
896
+ <span class="cline-any cline-no">&nbsp;</span>
897
+ <span class="cline-any cline-no">&nbsp;</span>
898
+ <span class="cline-any cline-no">&nbsp;</span>
899
+ <span class="cline-any cline-no">&nbsp;</span>
900
+ <span class="cline-any cline-no">&nbsp;</span>
901
+ <span class="cline-any cline-no">&nbsp;</span>
902
+ <span class="cline-any cline-yes">82x</span>
903
+ <span class="cline-any cline-yes">82x</span>
904
+ <span class="cline-any cline-yes">82x</span>
905
+ <span class="cline-any cline-yes">6x</span>
906
+ <span class="cline-any cline-yes">6x</span>
907
+ <span class="cline-any cline-yes">82x</span>
908
+ <span class="cline-any cline-yes">82x</span>
909
+ <span class="cline-any cline-yes">26x</span>
910
+ <span class="cline-any cline-yes">26x</span>
911
+ <span class="cline-any cline-no">&nbsp;</span>
912
+ <span class="cline-any cline-no">&nbsp;</span>
913
+ <span class="cline-any cline-no">&nbsp;</span>
914
+ <span class="cline-any cline-no">&nbsp;</span>
915
+ <span class="cline-any cline-no">&nbsp;</span>
916
+ <span class="cline-any cline-no">&nbsp;</span>
917
+ <span class="cline-any cline-yes">26x</span>
918
+ <span class="cline-any cline-yes">26x</span>
919
+ <span class="cline-any cline-yes">26x</span>
920
+ <span class="cline-any cline-yes">26x</span>
921
+ <span class="cline-any cline-yes">26x</span>
922
+ <span class="cline-any cline-yes">26x</span>
923
+ <span class="cline-any cline-yes">26x</span>
924
+ <span class="cline-any cline-yes">82x</span>
925
+ <span class="cline-any cline-yes">82x</span>
926
+ <span class="cline-any cline-yes">82x</span>
927
+ <span class="cline-any cline-yes">2x</span>
928
+ <span class="cline-any cline-yes">2x</span>
929
+ <span class="cline-any cline-yes">82x</span>
930
+ <span class="cline-any cline-yes">82x</span>
931
+ <span class="cline-any cline-yes">8x</span>
932
+ <span class="cline-any cline-yes">8x</span>
933
+ <span class="cline-any cline-yes">8x</span>
934
+ <span class="cline-any cline-yes">82x</span>
935
+ <span class="cline-any cline-yes">82x</span>
936
+ <span class="cline-any cline-yes">82x</span>
937
+ <span class="cline-any cline-yes">25x</span>
938
+ <span class="cline-any cline-yes">25x</span>
939
+ <span class="cline-any cline-yes">82x</span>
940
+ <span class="cline-any cline-yes">82x</span>
941
+ <span class="cline-any cline-yes">15x</span>
942
+ <span class="cline-any cline-yes">15x</span>
943
+ <span class="cline-any cline-yes">15x</span>
944
+ <span class="cline-any cline-yes">82x</span>
945
+ <span class="cline-any cline-yes">82x</span>
946
+ <span class="cline-any cline-yes">82x</span>
947
+ <span class="cline-any cline-yes">4x</span>
948
+ <span class="cline-any cline-yes">4x</span>
949
+ <span class="cline-any cline-yes">2x</span>
950
+ <span class="cline-any cline-yes">4x</span>
951
+ <span class="cline-any cline-yes">82x</span>
952
+ <span class="cline-any cline-yes">82x</span>
953
+ <span class="cline-any cline-yes">82x</span>
954
+ <span class="cline-any cline-yes">3x</span>
955
+ <span class="cline-any cline-yes">3x</span>
956
+ <span class="cline-any cline-yes">3x</span>
957
+ <span class="cline-any cline-yes">3x</span>
958
+ <span class="cline-any cline-yes">3x</span>
959
+ <span class="cline-any cline-yes">82x</span>
960
+ <span class="cline-any cline-yes">82x</span>
961
+ <span class="cline-any cline-yes">82x</span>
962
+ <span class="cline-any cline-yes">10x</span>
963
+ <span class="cline-any cline-yes">10x</span>
964
+ <span class="cline-any cline-yes">82x</span>
965
+ <span class="cline-any cline-yes">82x</span>
966
+ <span class="cline-any cline-yes">4x</span>
967
+ <span class="cline-any cline-yes">4x</span>
968
+ <span class="cline-any cline-yes">4x</span>
969
+ <span class="cline-any cline-yes">4x</span>
970
+ <span class="cline-any cline-yes">4x</span>
971
+ <span class="cline-any cline-yes">4x</span>
972
+ <span class="cline-any cline-yes">4x</span>
973
+ <span class="cline-any cline-yes">4x</span>
974
+ <span class="cline-any cline-yes">4x</span>
975
+ <span class="cline-any cline-yes">4x</span>
976
+ <span class="cline-any cline-yes">4x</span>
977
+ <span class="cline-any cline-yes">4x</span>
978
+ <span class="cline-any cline-yes">82x</span>
979
+ <span class="cline-any cline-yes">82x</span>
980
+ <span class="cline-any cline-yes">1x</span>
981
+ <span class="cline-any cline-yes">1x</span>
982
+ <span class="cline-any cline-yes">1x</span>
983
+ <span class="cline-any cline-yes">1x</span>
984
+ <span class="cline-any cline-yes">1x</span>
985
+ <span class="cline-any cline-yes">1x</span>
986
+ <span class="cline-any cline-yes">1x</span>
987
+ <span class="cline-any cline-yes">1x</span>
988
+ <span class="cline-any cline-yes">1x</span>
989
+ <span class="cline-any cline-yes">1x</span>
990
+ <span class="cline-any cline-yes">1x</span>
991
+ <span class="cline-any cline-yes">1x</span>
992
+ <span class="cline-any cline-yes">1x</span>
993
+ <span class="cline-any cline-yes">1x</span>
994
+ <span class="cline-any cline-yes">1x</span>
995
+ <span class="cline-any cline-yes">1x</span>
996
+ <span class="cline-any cline-yes">1x</span>
997
+ <span class="cline-any cline-yes">82x</span>
998
+ <span class="cline-any cline-yes">82x</span>
999
+ <span class="cline-any cline-yes">82x</span>
1000
+ <span class="cline-any cline-yes">82x</span>
1001
+ <span class="cline-any cline-yes">82x</span>
1002
+ <span class="cline-any cline-yes">4x</span>
1003
+ <span class="cline-any cline-yes">4x</span>
1004
+ <span class="cline-any cline-yes">4x</span>
1005
+ <span class="cline-any cline-yes">4x</span>
1006
+ <span class="cline-any cline-yes">4x</span>
1007
+ <span class="cline-any cline-yes">4x</span>
1008
+ <span class="cline-any cline-yes">4x</span>
1009
+ <span class="cline-any cline-yes">4x</span>
1010
+ <span class="cline-any cline-yes">4x</span>
1011
+ <span class="cline-any cline-yes">4x</span>
1012
+ <span class="cline-any cline-yes">4x</span>
1013
+ <span class="cline-any cline-yes">82x</span>
1014
+ <span class="cline-any cline-yes">82x</span>
1015
+ <span class="cline-any cline-yes">82x</span>
1016
+ <span class="cline-any cline-yes">2x</span>
1017
+ <span class="cline-any cline-yes">2x</span>
1018
+ <span class="cline-any cline-yes">2x</span>
1019
+ <span class="cline-any cline-yes">2x</span>
1020
+ <span class="cline-any cline-yes">2x</span>
1021
+ <span class="cline-any cline-yes">2x</span>
1022
+ <span class="cline-any cline-yes">2x</span>
1023
+ <span class="cline-any cline-yes">82x</span>
1024
+ <span class="cline-any cline-yes">82x</span>
1025
+ <span class="cline-any cline-yes">82x</span>
1026
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
1027
+ * A2A Configuration Management
1028
+ *
1029
+ * Stores permission tiers, default settings, and user preferences.
1030
+ */
1031
+ &nbsp;
1032
+ const fs = require('fs');
1033
+ const path = require('path');
1034
+ const { createLogger } = require('./logger');
1035
+ &nbsp;
1036
+ const CONFIG_DIR = process.env.A2A_CONFIG_DIR ||
1037
+ process.env.OPENCLAW_CONFIG_DIR ||
1038
+ path.join(process.env.HOME <span class="branch-0 cbranch-no" title="branch not covered" >|| '/tmp',</span> '.config', 'openclaw');
1039
+ &nbsp;
1040
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'a2a-config.json');
1041
+ const logger = createLogger({ component: 'a2a.config' });
1042
+ &nbsp;
1043
+ function isPlainObject(value) {
1044
+ return Boolean(value) &amp;&amp; typeof value === 'object' &amp;&amp; !Array.isArray(value);
1045
+ }
1046
+ &nbsp;
1047
+ function configValidationError(code, message, hint, data) {
1048
+ const err = new Error(message);
1049
+ err.code = code;
1050
+ if (hint) err.hint = hint;
1051
+ if (data) err.data = data;
1052
+ return err;
1053
+ }
1054
+ &nbsp;
1055
+ function sanitizeString(value, maxLength = 200) {
1056
+ return String(value <span class="branch-0 cbranch-no" title="branch not covered" >|| '')</span>
1057
+ .replace(/\s+/g, ' ')
1058
+ .trim()
1059
+ .slice(0, maxLength);
1060
+ }
1061
+ &nbsp;
1062
+ function validateStringArray(value, label, options = {}) {
1063
+ const maxItems = Number.isFinite(options.maxItems) ? options.maxItems <span class="branch-0 cbranch-no" title="branch not covered" >: 200;</span>
1064
+ const itemMaxLength = Number.isFinite(options.itemMaxLength) ? options.itemMaxLength <span class="branch-0 cbranch-no" title="branch not covered" >: 160;</span>
1065
+ &nbsp;
1066
+ if (!Array.isArray(value)) {
1067
+ throw configValidationError(
1068
+ 'A2A_CONFIG_INVALID_ARRAY',
1069
+ `Invalid ${label}: expected an array of strings`,
1070
+ 'Pass an array like ["chat","search"].',
1071
+ { label, received_type: typeof value }
1072
+ );
1073
+ }
1074
+ &nbsp;
1075
+ const unique = [];
1076
+ const seen = new Set();
1077
+ for (const entry of value) {
1078
+ if (typeof entry !== 'string') {
1079
+ throw configValidationError(
1080
+ 'A2A_CONFIG_INVALID_ARRAY_ITEM',
1081
+ `Invalid ${label}: each item must be a string`,
1082
+ 'Ensure your tier topics/goals are string arrays.',
1083
+ { label, received_item_type: typeof entry }
1084
+ );
1085
+ }
1086
+ const cleaned = sanitizeString(entry, itemMaxLength);
1087
+ if (!cleaned) <span class="branch-0 cbranch-no" title="branch not covered" >continue;</span>
1088
+ const key = cleaned.toLowerCase();
1089
+ if (seen.has(key)) <span class="branch-0 cbranch-no" title="branch not covered" >continue;</span>
1090
+ seen.add(key);
1091
+ unique.push(cleaned);
1092
+ if (unique.length &gt;= maxItems) <span class="branch-0 cbranch-no" title="branch not covered" >break;</span>
1093
+ }
1094
+ &nbsp;
1095
+ return unique;
1096
+ }
1097
+ &nbsp;
1098
+ function validateTierPatch(tierName, tierConfig) {
1099
+ if (!isPlainObject(tierConfig)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1100
+ <span class="cstat-no" title="statement not covered" > throw configValidationError(</span>
1101
+ <span class="cstat-no" title="statement not covered" > 'A2A_CONFIG_INVALID_TIER_PATCH',</span>
1102
+ <span class="cstat-no" title="statement not covered" > `Invalid tier config for "${tierName}": expected an object`,</span>
1103
+ <span class="cstat-no" title="statement not covered" > 'Pass an object like { topics: [...], goals: [...] }.',</span>
1104
+ <span class="cstat-no" title="statement not covered" > { tier: tierName, received_type: typeof tierConfig }</span>
1105
+ <span class="cstat-no" title="statement not covered" > );</span>
1106
+ <span class="cstat-no" title="statement not covered" > }</span>
1107
+ &nbsp;
1108
+ const out = {};
1109
+ &nbsp;
1110
+ if (tierConfig.name !== undefined) {
1111
+ if (typeof tierConfig.name !== 'string') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1112
+ <span class="cstat-no" title="statement not covered" > throw configValidationError(</span>
1113
+ <span class="cstat-no" title="statement not covered" > 'A2A_CONFIG_INVALID_TIER_NAME',</span>
1114
+ <span class="cstat-no" title="statement not covered" > `Invalid tier name for "${tierName}": expected string`,</span>
1115
+ <span class="cstat-no" title="statement not covered" > null,</span>
1116
+ <span class="cstat-no" title="statement not covered" > { tier: tierName, received_type: typeof tierConfig.name }</span>
1117
+ <span class="cstat-no" title="statement not covered" > );</span>
1118
+ <span class="cstat-no" title="statement not covered" > }</span>
1119
+ out.name = sanitizeString(tierConfig.name, 120);
1120
+ }
1121
+ &nbsp;
1122
+ if (tierConfig.description !== undefined) {
1123
+ if (typeof tierConfig.description !== 'string') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1124
+ <span class="cstat-no" title="statement not covered" > throw configValidationError(</span>
1125
+ <span class="cstat-no" title="statement not covered" > 'A2A_CONFIG_INVALID_TIER_DESCRIPTION',</span>
1126
+ <span class="cstat-no" title="statement not covered" > `Invalid tier description for "${tierName}": expected string`,</span>
1127
+ <span class="cstat-no" title="statement not covered" > null,</span>
1128
+ <span class="cstat-no" title="statement not covered" > { tier: tierName, received_type: typeof tierConfig.description }</span>
1129
+ <span class="cstat-no" title="statement not covered" > );</span>
1130
+ <span class="cstat-no" title="statement not covered" > }</span>
1131
+ out.description = sanitizeString(tierConfig.description, 300);
1132
+ }
1133
+ &nbsp;
1134
+ // A2A-41: disclosure field intentionally removed. If present in input,
1135
+ // it is silently ignored for backward compatibility with older clients.
1136
+ &nbsp;
1137
+ if (tierConfig.capabilities !== undefined) {
1138
+ out.capabilities = validateStringArray(tierConfig.capabilities, `${tierName}.capabilities`, {
1139
+ maxItems: 100,
1140
+ itemMaxLength: 120
1141
+ });
1142
+ }
1143
+ &nbsp;
1144
+ if (tierConfig.allowed_tools !== undefined) {
1145
+ out.allowed_tools = validateStringArray(tierConfig.allowed_tools, `${tierName}.allowed_tools`, {
1146
+ maxItems: 30,
1147
+ itemMaxLength: 80
1148
+ });
1149
+ }
1150
+ &nbsp;
1151
+ if (tierConfig.topics !== undefined) {
1152
+ out.topics = validateStringArray(tierConfig.topics, `${tierName}.topics`, {
1153
+ maxItems: 200,
1154
+ itemMaxLength: 160
1155
+ });
1156
+ }
1157
+ &nbsp;
1158
+ if (tierConfig.goals !== undefined) {
1159
+ out.goals = validateStringArray(tierConfig.goals, `${tierName}.goals`, {
1160
+ maxItems: 200,
1161
+ itemMaxLength: 160
1162
+ });
1163
+ }
1164
+ &nbsp;
1165
+ if (tierConfig.examples !== undefined) {
1166
+ out.examples = validateStringArray(tierConfig.examples, `${tierName}.examples`, {
1167
+ maxItems: 20,
1168
+ itemMaxLength: 120
1169
+ });
1170
+ }
1171
+ &nbsp;
1172
+ return out;
1173
+ }
1174
+ &nbsp;
1175
+ function deepMerge(base, override) {
1176
+ const baseIsObject = base &amp;&amp; typeof base === 'object' &amp;&amp; !Array.isArray(base);
1177
+ const overrideIsObject = override &amp;&amp; typeof override === 'object' &amp;&amp; !Array.isArray(override);
1178
+ if (!overrideIsObject) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1179
+ <span class="cstat-no" title="statement not covered" > return override === undefined ? base : override;</span>
1180
+ <span class="cstat-no" title="statement not covered" > }</span>
1181
+ const out = baseIsObject ? { ...base } <span class="branch-0 cbranch-no" title="branch not covered" >: {};</span>
1182
+ for (const [key, value] of Object.entries(override)) {
1183
+ const baseValue = baseIsObject ? base[key] <span class="branch-0 cbranch-no" title="branch not covered" >: undefined;</span>
1184
+ const bothObjects = baseValue &amp;&amp; typeof baseValue === 'object' &amp;&amp; !Array.isArray(baseValue) &amp;&amp;
1185
+ value &amp;&amp; typeof value === 'object' &amp;&amp; !Array.isArray(value);
1186
+ out[key] = bothObjects ? deepMerge(baseValue, value) : value;
1187
+ }
1188
+ return out;
1189
+ }
1190
+ &nbsp;
1191
+ const DEFAULT_CONFIG = {
1192
+ onboarding: {
1193
+ version: 2,
1194
+ step: 'not_started', // not_started|tiers|ingress|verify|complete
1195
+ tiers_confirmed: false,
1196
+ ingress_confirmed: false,
1197
+ verify_confirmed: false,
1198
+ last_run_at: null
1199
+ },
1200
+
1201
+ // Permission tiers
1202
+ // A2A-41: disclosure field removed from tiers. It was intended to control
1203
+ // HOW info is shared (freely/minimally/none) but was never consumed by
1204
+ // prompt templates. The disclosure SYSTEM (disclosure.js, manifest) remains.
1205
+ tiers: {
1206
+ public: {
1207
+ name: 'Public',
1208
+ description: 'Basic networking - safe for anyone',
1209
+ capabilities: ['context-read'],
1210
+ allowed_tools: ['Read', 'Grep', 'Glob'],
1211
+ topics: ['chat'],
1212
+ goals: [],
1213
+ examples: ['calendar availability', 'public social posts', 'general questions']
1214
+ },
1215
+ friends: {
1216
+ name: 'Friends',
1217
+ description: 'Most capabilities, no sensitive financial data',
1218
+ capabilities: ['context-read', 'calendar.read', 'email.read', 'search'],
1219
+ allowed_tools: ['Bash(readonly)', 'Read', 'Grep', 'Glob', 'WebSearch', 'WebFetch'],
1220
+ topics: ['chat', 'search', 'openclaw', 'a2a'],
1221
+ goals: [],
1222
+ examples: ['email summaries', 'schedule meetings', 'project discussions']
1223
+ },
1224
+ family: {
1225
+ name: 'Family',
1226
+ description: 'Full access - only for your inner circle',
1227
+ capabilities: ['context-read', 'calendar', 'email', 'search', 'tools', 'memory'],
1228
+ allowed_tools: ['Bash', 'Read', 'Grep', 'Glob', 'WebSearch', 'WebFetch'],
1229
+ topics: ['chat', 'search', 'openclaw', 'a2a', 'tools', 'memory'],
1230
+ goals: [],
1231
+ examples: ['deep collaboration', 'private project context', 'personal notes']
1232
+ },
1233
+ custom: {
1234
+ name: 'Custom',
1235
+ description: 'User-defined permissions',
1236
+ capabilities: ['context-read'],
1237
+ allowed_tools: ['Read', 'Grep', 'Glob'],
1238
+ topics: [],
1239
+ goals: [],
1240
+ examples: []
1241
+ }
1242
+ },
1243
+
1244
+ // Default token settings
1245
+ defaults: {
1246
+ expiration: 'never', // never, 1d, 7d, 30d
1247
+ maxCalls: 100, // per token
1248
+ rateLimit: {
1249
+ perMinute: 10,
1250
+ perHour: 100,
1251
+ perDay: 1000
1252
+ },
1253
+ turnTimeoutMs: 300000, // default Claude turn timeout
1254
+ maxPendingRequests: 5 // max connection requests per hour
1255
+ },
1256
+
1257
+ // Agent info
1258
+ // A2A-52: private_key/public_key store Ed25519 identity (base64 DER)
1259
+ agent: {
1260
+ name: '',
1261
+ description: '',
1262
+ hostname: '',
1263
+ private_key: null,
1264
+ public_key: null
1265
+ },
1266
+ &nbsp;
1267
+ // Auto-updater
1268
+ auto_update: {
1269
+ enabled: true,
1270
+ intervalMs: 60 * 60 * 1000,
1271
+ allowMajor: false,
1272
+ lastGoodVersion: null
1273
+ },
1274
+ &nbsp;
1275
+ // A2A-63: Retention policy defaults for database lifecycle management
1276
+ retention: {
1277
+ conversations_days: 90,
1278
+ logs_days: 30,
1279
+ compress_after_days: 7,
1280
+ token_expiry_grace_days: 30
1281
+ },
1282
+ &nbsp;
1283
+ // Timestamps
1284
+ createdAt: null,
1285
+ updatedAt: null
1286
+ };
1287
+ &nbsp;
1288
+ class A2AConfig {
1289
+ constructor() {
1290
+ this._ensureDir();
1291
+ this.config = this._load();
1292
+ }
1293
+ &nbsp;
1294
+ _ensureDir() {
1295
+ if (!fs.existsSync(CONFIG_DIR)) {
1296
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
1297
+ }
1298
+ }
1299
+ &nbsp;
1300
+ _load() {
1301
+ if (fs.existsSync(CONFIG_FILE)) {
1302
+ try {
1303
+ const saved = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
1304
+ return deepMerge(JSON.parse(JSON.stringify(DEFAULT_CONFIG)), saved);
1305
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (e) {</span>
1306
+ <span class="cstat-no" title="statement not covered" > logger.error('A2A config is corrupted, using defaults', {</span>
1307
+ <span class="cstat-no" title="statement not covered" > event: 'a2a_config_corrupt',</span>
1308
+ <span class="cstat-no" title="statement not covered" > error: e,</span>
1309
+ <span class="cstat-no" title="statement not covered" > error_code: 'A2A_CONFIG_CORRUPTED',</span>
1310
+ <span class="cstat-no" title="statement not covered" > hint: 'Fix invalid JSON in a2a-config.json or regenerate it via setup.',</span>
1311
+ <span class="cstat-no" title="statement not covered" > data: {</span>
1312
+ <span class="cstat-no" title="statement not covered" > config_file: CONFIG_FILE</span>
1313
+ <span class="cstat-no" title="statement not covered" > }</span>
1314
+ <span class="cstat-no" title="statement not covered" > });</span>
1315
+ <span class="cstat-no" title="statement not covered" > return JSON.parse(JSON.stringify(DEFAULT_CONFIG));</span>
1316
+ <span class="cstat-no" title="statement not covered" > }</span>
1317
+ }
1318
+ return JSON.parse(JSON.stringify(DEFAULT_CONFIG));
1319
+ }
1320
+ &nbsp;
1321
+ _save() {
1322
+ this.config.updatedAt = new Date().toISOString();
1323
+ if (!this.config.createdAt) {
1324
+ this.config.createdAt = this.config.updatedAt;
1325
+ }
1326
+ const tmpPath = `${CONFIG_FILE}.tmp`;
1327
+ fs.writeFileSync(tmpPath, JSON.stringify(this.config, null, 2), { mode: 0o600 });
1328
+ fs.renameSync(tmpPath, CONFIG_FILE);
1329
+ try {
1330
+ fs.chmodSync(CONFIG_FILE, 0o600);
1331
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
1332
+ <span class="cstat-no" title="statement not covered" > // Best effort - ignore on platforms without chmod support.</span>
1333
+ <span class="cstat-no" title="statement not covered" > }</span>
1334
+ }
1335
+ &nbsp;
1336
+ // Check if onboarding is complete
1337
+ isOnboarded() {
1338
+ return this.config.onboarding &amp;&amp;
1339
+ this.config.onboarding.version === 2 &amp;&amp;
1340
+ this.config.onboarding.step === 'complete';
1341
+ }
1342
+ &nbsp;
1343
+ // Mark onboarding complete
1344
+ completeOnboarding() {
1345
+ this.config.onboarding = this.config.onboarding <span class="branch-0 cbranch-no" title="branch not covered" >|| {};</span>
1346
+ this.config.onboarding.version = 2;
1347
+ this.config.onboarding.step = 'complete';
1348
+ this.config.onboarding.tiers_confirmed = true;
1349
+ this.config.onboarding.ingress_confirmed = true;
1350
+ this.config.onboarding.verify_confirmed = true;
1351
+ this.config.onboarding.last_run_at = new Date().toISOString();
1352
+ this._save();
1353
+ }
1354
+ &nbsp;
1355
+ // Reset to run onboarding again
1356
+ resetOnboarding() {
1357
+ this.config.onboarding = this.config.onboarding <span class="branch-0 cbranch-no" title="branch not covered" >|| {};</span>
1358
+ this.config.onboarding.version = 2;
1359
+ this.config.onboarding.step = 'not_started';
1360
+ this.config.onboarding.tiers_confirmed = false;
1361
+ this.config.onboarding.ingress_confirmed = false;
1362
+ this.config.onboarding.verify_confirmed = false;
1363
+ this.config.onboarding.last_run_at = new Date().toISOString();
1364
+ this._save();
1365
+ }
1366
+ &nbsp;
1367
+ getOnboarding() {
1368
+ const ob = (this.config &amp;&amp; this.config.onboarding &amp;&amp; typeof this.config.onboarding === 'object')
1369
+ ? this.config.onboarding
1370
+ <span class="branch-0 cbranch-no" title="branch not covered" > : {};</span>
1371
+ return deepMerge(DEFAULT_CONFIG.onboarding, ob);
1372
+ }
1373
+ &nbsp;
1374
+ <span class="fstat-no" title="function not covered" > setOnboarding(patch = {}) {</span>
1375
+ <span class="cstat-no" title="statement not covered" > const current = this.getOnboarding();</span>
1376
+ <span class="cstat-no" title="statement not covered" > const merged = deepMerge(current, patch);</span>
1377
+ <span class="cstat-no" title="statement not covered" > merged.version = 2;</span>
1378
+ <span class="cstat-no" title="statement not covered" > merged.last_run_at = new Date().toISOString();</span>
1379
+ <span class="cstat-no" title="statement not covered" > this.config.onboarding = merged;</span>
1380
+ <span class="cstat-no" title="statement not covered" > this._save();</span>
1381
+ <span class="cstat-no" title="statement not covered" > }</span>
1382
+ &nbsp;
1383
+ // Get/set tiers
1384
+ getTiers() {
1385
+ return this.config.tiers;
1386
+ }
1387
+ &nbsp;
1388
+ setTier(tierName, tierConfig) {
1389
+ const id = String(tierName <span class="branch-0 cbranch-no" title="branch not covered" >|| '')</span>.trim();
1390
+ if (!id) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1391
+ <span class="cstat-no" title="statement not covered" > throw configValidationError(</span>
1392
+ <span class="cstat-no" title="statement not covered" > 'A2A_CONFIG_INVALID_TIER_ID',</span>
1393
+ <span class="cstat-no" title="statement not covered" > 'Tier name is required',</span>
1394
+ <span class="cstat-no" title="statement not covered" > 'Use one of: public|friends|family|custom (or a non-empty custom tier id).'</span>
1395
+ <span class="cstat-no" title="statement not covered" > );</span>
1396
+ <span class="cstat-no" title="statement not covered" > }</span>
1397
+ &nbsp;
1398
+ const patch = validateTierPatch(id, tierConfig);
1399
+ this.config.tiers = isPlainObject(this.config.tiers) ? this.config.tiers <span class="branch-0 cbranch-no" title="branch not covered" >: {};</span>
1400
+ const existing = isPlainObject(this.config.tiers[id]) ? this.config.tiers[id] : {};
1401
+ this.config.tiers[id] = { ...existing, ...patch };
1402
+ this._save();
1403
+ }
1404
+ &nbsp;
1405
+ // Get/set defaults
1406
+ getDefaults() {
1407
+ return this.config.defaults;
1408
+ }
1409
+ &nbsp;
1410
+ setDefaults(defaults) {
1411
+ this.config.defaults = { ...this.config.defaults, ...defaults };
1412
+ this._save();
1413
+ }
1414
+ &nbsp;
1415
+ // Get/set agent info
1416
+ getAgent() {
1417
+ return this.config.agent;
1418
+ }
1419
+ &nbsp;
1420
+ setAgent(agent) {
1421
+ this.config.agent = { ...this.config.agent, ...agent };
1422
+ this._save();
1423
+ }
1424
+ &nbsp;
1425
+ // A2A-52: Get Ed25519 keypair from agent config (null if not generated)
1426
+ getKeypair() {
1427
+ const agent = this.config.agent <span class="branch-0 cbranch-no" title="branch not covered" >|| {};</span>
1428
+ if (!agent.private_key || !agent.public_key) return null;
1429
+ return { privateKey: agent.private_key, publicKey: agent.public_key };
1430
+ }
1431
+ &nbsp;
1432
+ // A2A-52: Store Ed25519 keypair in agent config (already 0o600 via _save)
1433
+ setKeypair(privateKey, publicKey) {
1434
+ this.config.agent = this.config.agent <span class="branch-0 cbranch-no" title="branch not covered" >|| {};</span>
1435
+ this.config.agent.private_key = privateKey;
1436
+ this.config.agent.public_key = publicKey;
1437
+ this._save();
1438
+ }
1439
+ &nbsp;
1440
+ // Get full config
1441
+ getAll() {
1442
+ return this.config;
1443
+ }
1444
+ &nbsp;
1445
+ getAutoUpdate() {
1446
+ const current = (this.config &amp;&amp; typeof this.config.auto_update === 'object' &amp;&amp; this.config.auto_update)
1447
+ ? this.config.auto_update
1448
+ <span class="branch-0 cbranch-no" title="branch not covered" > : {};</span>
1449
+ return {
1450
+ enabled: current.enabled !== false,
1451
+ intervalMs: Number.isFinite(current.intervalMs) &amp;&amp; current.intervalMs &gt; 0
1452
+ ? current.intervalMs
1453
+ <span class="branch-0 cbranch-no" title="branch not covered" > : DEFAULT_CONFIG.auto_update.intervalMs,</span>
1454
+ allowMajor: Boolean(current.allowMajor),
1455
+ lastGoodVersion: current.lastGoodVersion || null
1456
+ };
1457
+ }
1458
+ &nbsp;
1459
+ setAutoUpdate(patch = {}) {
1460
+ const current = this.getAutoUpdate();
1461
+ const next = { ...current };
1462
+ if (patch.enabled !== undefined) next.enabled = Boolean(patch.enabled);
1463
+ if (patch.intervalMs !== undefined) {
1464
+ const parsed = Number.parseInt(String(patch.intervalMs), 10);
1465
+ if (Number.isFinite(parsed) &amp;&amp; parsed &gt; 0) {
1466
+ next.intervalMs = parsed;
1467
+ }
1468
+ }
1469
+ if (patch.allowMajor !== undefined) next.allowMajor = Boolean(patch.allowMajor);
1470
+ if (patch.lastGoodVersion !== undefined) {
1471
+ next.lastGoodVersion = patch.lastGoodVersion ? String(patch.lastGoodVersion).trim() <span class="branch-0 cbranch-no" title="branch not covered" >: null;</span>
1472
+ }
1473
+ this.config.auto_update = next;
1474
+ this._save();
1475
+ return next;
1476
+ }
1477
+ &nbsp;
1478
+ // A2A-63: Retention config accessor — returns merged defaults when
1479
+ // the retention section is missing or partially present in the config file.
1480
+ // Does NOT write defaults to disk automatically.
1481
+ getRetention() {
1482
+ const defaults = DEFAULT_CONFIG.retention;
1483
+ const current = (this.config &amp;&amp; typeof this.config.retention === 'object' &amp;&amp; this.config.retention)
1484
+ ? this.config.retention
1485
+ <span class="branch-0 cbranch-no" title="branch not covered" > : {};</span>
1486
+ return {
1487
+ conversations_days: Number.isFinite(current.conversations_days) ? current.conversations_days : defaults.conversations_days,
1488
+ logs_days: Number.isFinite(current.logs_days) ? current.logs_days : defaults.logs_days,
1489
+ compress_after_days: Number.isFinite(current.compress_after_days) ? current.compress_after_days : defaults.compress_after_days,
1490
+ token_expiry_grace_days: Number.isFinite(current.token_expiry_grace_days) ? current.token_expiry_grace_days <span class="branch-0 cbranch-no" title="branch not covered" >: defaults.token_expiry_grace_days</span>
1491
+ };
1492
+ }
1493
+ &nbsp;
1494
+ // Export for sharing (strips private_key to prevent leakage — A2A-52)
1495
+ export() {
1496
+ const { private_key, ...agentPublic } = this.config.agent <span class="branch-0 cbranch-no" title="branch not covered" >|| {};</span>
1497
+ return {
1498
+ tiers: this.config.tiers,
1499
+ defaults: this.config.defaults,
1500
+ agent: agentPublic
1501
+ };
1502
+ }
1503
+ }
1504
+ &nbsp;
1505
+ module.exports = { A2AConfig, DEFAULT_CONFIG, CONFIG_FILE };
1506
+ &nbsp;</pre></td></tr></table></pre>
1507
+
1508
+ <div class='push'></div><!-- for sticky footer -->
1509
+ </div><!-- /wrapper -->
1510
+ <div class='footer quiet pad2 space-top1 center small'>
1511
+ Code coverage generated by
1512
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1513
+ at 2026-03-03T22:25:10.857Z
1514
+ </div>
1515
+ <script src="../../prettify.js"></script>
1516
+ <script>
1517
+ window.onload = function () {
1518
+ prettyPrint();
1519
+ };
1520
+ </script>
1521
+ <script src="../../sorter.js"></script>
1522
+ <script src="../../block-navigation.js"></script>
1523
+ </body>
1524
+ </html>
1525
+