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,2116 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/lib/logger.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> logger.js</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">87.44% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>592/677</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">71.2% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>136/191</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">92.3% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>36/39</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">87.44% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>592/677</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></td><td class="line-coverage quiet"><span class="cline-any cline-yes">76x</span>
744
+ <span class="cline-any cline-yes">76x</span>
745
+ <span class="cline-any cline-yes">76x</span>
746
+ <span class="cline-any cline-yes">76x</span>
747
+ <span class="cline-any cline-yes">76x</span>
748
+ <span class="cline-any cline-yes">76x</span>
749
+ <span class="cline-any cline-yes">76x</span>
750
+ <span class="cline-any cline-yes">76x</span>
751
+ <span class="cline-any cline-yes">76x</span>
752
+ <span class="cline-any cline-yes">76x</span>
753
+ <span class="cline-any cline-yes">76x</span>
754
+ <span class="cline-any cline-yes">76x</span>
755
+ <span class="cline-any cline-yes">746x</span>
756
+ <span class="cline-any cline-yes">746x</span>
757
+ <span class="cline-any cline-yes">746x</span>
758
+ <span class="cline-any cline-yes">746x</span>
759
+ <span class="cline-any cline-yes">746x</span>
760
+ <span class="cline-any cline-yes">76x</span>
761
+ <span class="cline-any cline-yes">76x</span>
762
+ <span class="cline-any cline-yes">76x</span>
763
+ <span class="cline-any cline-yes">76x</span>
764
+ <span class="cline-any cline-yes">76x</span>
765
+ <span class="cline-any cline-yes">76x</span>
766
+ <span class="cline-any cline-yes">76x</span>
767
+ <span class="cline-any cline-yes">76x</span>
768
+ <span class="cline-any cline-yes">76x</span>
769
+ <span class="cline-any cline-yes">76x</span>
770
+ <span class="cline-any cline-yes">788x</span>
771
+ <span class="cline-any cline-yes">788x</span>
772
+ <span class="cline-any cline-yes">788x</span>
773
+ <span class="cline-any cline-yes">788x</span>
774
+ <span class="cline-any cline-yes">788x</span>
775
+ <span class="cline-any cline-no">&nbsp;</span>
776
+ <span class="cline-any cline-yes">788x</span>
777
+ <span class="cline-any cline-yes">788x</span>
778
+ <span class="cline-any cline-yes">76x</span>
779
+ <span class="cline-any cline-yes">3151x</span>
780
+ <span class="cline-any cline-yes">3151x</span>
781
+ <span class="cline-any cline-yes">3151x</span>
782
+ <span class="cline-any cline-yes">3151x</span>
783
+ <span class="cline-any cline-yes">76x</span>
784
+ <span class="cline-any cline-yes">721x</span>
785
+ <span class="cline-any cline-yes">721x</span>
786
+ <span class="cline-any cline-yes">721x</span>
787
+ <span class="cline-any cline-yes">721x</span>
788
+ <span class="cline-any cline-yes">721x</span>
789
+ <span class="cline-any cline-yes">76x</span>
790
+ <span class="cline-any cline-yes">1367x</span>
791
+ <span class="cline-any cline-yes">1367x</span>
792
+ <span class="cline-any cline-yes">1367x</span>
793
+ <span class="cline-any cline-yes">1367x</span>
794
+ <span class="cline-any cline-yes">1367x</span>
795
+ <span class="cline-any cline-yes">1367x</span>
796
+ <span class="cline-any cline-yes">76x</span>
797
+ <span class="cline-any cline-yes">543x</span>
798
+ <span class="cline-any cline-yes">543x</span>
799
+ <span class="cline-any cline-yes">14x</span>
800
+ <span class="cline-any cline-yes">14x</span>
801
+ <span class="cline-any cline-yes">14x</span>
802
+ <span class="cline-any cline-yes">14x</span>
803
+ <span class="cline-any cline-yes">14x</span>
804
+ <span class="cline-any cline-yes">14x</span>
805
+ <span class="cline-any cline-yes">14x</span>
806
+ <span class="cline-any cline-yes">14x</span>
807
+ <span class="cline-any cline-yes">14x</span>
808
+ <span class="cline-any cline-yes">14x</span>
809
+ <span class="cline-any cline-yes">14x</span>
810
+ <span class="cline-any cline-yes">14x</span>
811
+ <span class="cline-any cline-no">&nbsp;</span>
812
+ <span class="cline-any cline-no">&nbsp;</span>
813
+ <span class="cline-any cline-no">&nbsp;</span>
814
+ <span class="cline-any cline-no">&nbsp;</span>
815
+ <span class="cline-any cline-no">&nbsp;</span>
816
+ <span class="cline-any cline-no">&nbsp;</span>
817
+ <span class="cline-any cline-no">&nbsp;</span>
818
+ <span class="cline-any cline-no">&nbsp;</span>
819
+ <span class="cline-any cline-yes">543x</span>
820
+ <span class="cline-any cline-yes">76x</span>
821
+ <span class="cline-any cline-yes">543x</span>
822
+ <span class="cline-any cline-yes">543x</span>
823
+ <span class="cline-any cline-yes">543x</span>
824
+ <span class="cline-any cline-yes">543x</span>
825
+ <span class="cline-any cline-yes">543x</span>
826
+ <span class="cline-any cline-yes">14x</span>
827
+ <span class="cline-any cline-yes">14x</span>
828
+ <span class="cline-any cline-yes">543x</span>
829
+ <span class="cline-any cline-yes">543x</span>
830
+ <span class="cline-any cline-yes">543x</span>
831
+ <span class="cline-any cline-yes">543x</span>
832
+ <span class="cline-any cline-yes">543x</span>
833
+ <span class="cline-any cline-yes">543x</span>
834
+ <span class="cline-any cline-yes">543x</span>
835
+ <span class="cline-any cline-yes">543x</span>
836
+ <span class="cline-any cline-yes">543x</span>
837
+ <span class="cline-any cline-yes">543x</span>
838
+ <span class="cline-any cline-yes">543x</span>
839
+ <span class="cline-any cline-yes">543x</span>
840
+ <span class="cline-any cline-yes">543x</span>
841
+ <span class="cline-any cline-yes">543x</span>
842
+ <span class="cline-any cline-yes">543x</span>
843
+ <span class="cline-any cline-yes">543x</span>
844
+ <span class="cline-any cline-yes">543x</span>
845
+ <span class="cline-any cline-yes">543x</span>
846
+ <span class="cline-any cline-yes">76x</span>
847
+ <span class="cline-any cline-yes">76x</span>
848
+ <span class="cline-any cline-yes">76x</span>
849
+ <span class="cline-any cline-yes">289x</span>
850
+ <span class="cline-any cline-yes">289x</span>
851
+ <span class="cline-any cline-yes">289x</span>
852
+ <span class="cline-any cline-yes">289x</span>
853
+ <span class="cline-any cline-yes">289x</span>
854
+ <span class="cline-any cline-yes">289x</span>
855
+ <span class="cline-any cline-yes">76x</span>
856
+ <span class="cline-any cline-yes">76x</span>
857
+ <span class="cline-any cline-yes">289x</span>
858
+ <span class="cline-any cline-no">&nbsp;</span>
859
+ <span class="cline-any cline-no">&nbsp;</span>
860
+ <span class="cline-any cline-yes">289x</span>
861
+ <span class="cline-any cline-yes">76x</span>
862
+ <span class="cline-any cline-yes">76x</span>
863
+ <span class="cline-any cline-yes">1580x</span>
864
+ <span class="cline-any cline-yes">1580x</span>
865
+ <span class="cline-any cline-yes">120x</span>
866
+ <span class="cline-any cline-yes">120x</span>
867
+ <span class="cline-any cline-yes">120x</span>
868
+ <span class="cline-any cline-yes">120x</span>
869
+ <span class="cline-any cline-yes">120x</span>
870
+ <span class="cline-any cline-yes">120x</span>
871
+ <span class="cline-any cline-yes">1580x</span>
872
+ <span class="cline-any cline-no">&nbsp;</span>
873
+ <span class="cline-any cline-no">&nbsp;</span>
874
+ <span class="cline-any cline-yes">120x</span>
875
+ <span class="cline-any cline-yes">1580x</span>
876
+ <span class="cline-any cline-no">&nbsp;</span>
877
+ <span class="cline-any cline-no">&nbsp;</span>
878
+ <span class="cline-any cline-no">&nbsp;</span>
879
+ <span class="cline-any cline-no">&nbsp;</span>
880
+ <span class="cline-any cline-no">&nbsp;</span>
881
+ <span class="cline-any cline-no">&nbsp;</span>
882
+ <span class="cline-any cline-no">&nbsp;</span>
883
+ <span class="cline-any cline-no">&nbsp;</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-no">&nbsp;</span>
888
+ <span class="cline-any cline-no">&nbsp;</span>
889
+ <span class="cline-any cline-no">&nbsp;</span>
890
+ <span class="cline-any cline-no">&nbsp;</span>
891
+ <span class="cline-any cline-no">&nbsp;</span>
892
+ <span class="cline-any cline-no">&nbsp;</span>
893
+ <span class="cline-any cline-no">&nbsp;</span>
894
+ <span class="cline-any cline-no">&nbsp;</span>
895
+ <span class="cline-any cline-no">&nbsp;</span>
896
+ <span class="cline-any cline-yes">120x</span>
897
+ <span class="cline-any cline-yes">120x</span>
898
+ <span class="cline-any cline-yes">1580x</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">1580x</span>
903
+ <span class="cline-any cline-yes">76x</span>
904
+ <span class="cline-any cline-yes">76x</span>
905
+ <span class="cline-any cline-yes">120x</span>
906
+ <span class="cline-any cline-yes">120x</span>
907
+ <span class="cline-any cline-yes">120x</span>
908
+ <span class="cline-any cline-yes">120x</span>
909
+ <span class="cline-any cline-yes">120x</span>
910
+ <span class="cline-any cline-yes">120x</span>
911
+ <span class="cline-any cline-yes">120x</span>
912
+ <span class="cline-any cline-yes">120x</span>
913
+ <span class="cline-any cline-yes">120x</span>
914
+ <span class="cline-any cline-yes">120x</span>
915
+ <span class="cline-any cline-yes">120x</span>
916
+ <span class="cline-any cline-yes">120x</span>
917
+ <span class="cline-any cline-yes">120x</span>
918
+ <span class="cline-any cline-yes">120x</span>
919
+ <span class="cline-any cline-yes">120x</span>
920
+ <span class="cline-any cline-yes">120x</span>
921
+ <span class="cline-any cline-yes">120x</span>
922
+ <span class="cline-any cline-yes">120x</span>
923
+ <span class="cline-any cline-yes">120x</span>
924
+ <span class="cline-any cline-yes">120x</span>
925
+ <span class="cline-any cline-yes">120x</span>
926
+ <span class="cline-any cline-yes">120x</span>
927
+ <span class="cline-any cline-yes">120x</span>
928
+ <span class="cline-any cline-yes">120x</span>
929
+ <span class="cline-any cline-yes">120x</span>
930
+ <span class="cline-any cline-yes">120x</span>
931
+ <span class="cline-any cline-yes">120x</span>
932
+ <span class="cline-any cline-yes">120x</span>
933
+ <span class="cline-any cline-yes">120x</span>
934
+ <span class="cline-any cline-yes">120x</span>
935
+ <span class="cline-any cline-yes">120x</span>
936
+ <span class="cline-any cline-yes">120x</span>
937
+ <span class="cline-any cline-yes">120x</span>
938
+ <span class="cline-any cline-yes">120x</span>
939
+ <span class="cline-any cline-yes">76x</span>
940
+ <span class="cline-any cline-yes">76x</span>
941
+ <span class="cline-any cline-yes">120x</span>
942
+ <span class="cline-any cline-yes">120x</span>
943
+ <span class="cline-any cline-yes">120x</span>
944
+ <span class="cline-any cline-yes">120x</span>
945
+ <span class="cline-any cline-yes">120x</span>
946
+ <span class="cline-any cline-yes">120x</span>
947
+ <span class="cline-any cline-yes">120x</span>
948
+ <span class="cline-any cline-yes">120x</span>
949
+ <span class="cline-any cline-yes">120x</span>
950
+ <span class="cline-any cline-yes">76x</span>
951
+ <span class="cline-any cline-yes">76x</span>
952
+ <span class="cline-any cline-no">&nbsp;</span>
953
+ <span class="cline-any cline-no">&nbsp;</span>
954
+ <span class="cline-any cline-yes">76x</span>
955
+ <span class="cline-any cline-yes">76x</span>
956
+ <span class="cline-any cline-no">&nbsp;</span>
957
+ <span class="cline-any cline-no">&nbsp;</span>
958
+ <span class="cline-any cline-no">&nbsp;</span>
959
+ <span class="cline-any cline-yes">76x</span>
960
+ <span class="cline-any cline-yes">76x</span>
961
+ <span class="cline-any cline-yes">1544x</span>
962
+ <span class="cline-any cline-yes">1544x</span>
963
+ <span class="cline-any cline-yes">1544x</span>
964
+ <span class="cline-any cline-yes">1544x</span>
965
+ <span class="cline-any cline-yes">1544x</span>
966
+ <span class="cline-any cline-yes">1544x</span>
967
+ <span class="cline-any cline-yes">1544x</span>
968
+ <span class="cline-any cline-yes">1544x</span>
969
+ <span class="cline-any cline-yes">1544x</span>
970
+ <span class="cline-any cline-yes">1544x</span>
971
+ <span class="cline-any cline-yes">1544x</span>
972
+ <span class="cline-any cline-yes">1544x</span>
973
+ <span class="cline-any cline-yes">1544x</span>
974
+ <span class="cline-any cline-yes">1544x</span>
975
+ <span class="cline-any cline-yes">1544x</span>
976
+ <span class="cline-any cline-yes">1544x</span>
977
+ <span class="cline-any cline-yes">1544x</span>
978
+ <span class="cline-any cline-yes">1544x</span>
979
+ <span class="cline-any cline-yes">1544x</span>
980
+ <span class="cline-any cline-yes">1544x</span>
981
+ <span class="cline-any cline-yes">1544x</span>
982
+ <span class="cline-any cline-yes">1544x</span>
983
+ <span class="cline-any cline-yes">1544x</span>
984
+ <span class="cline-any cline-yes">1544x</span>
985
+ <span class="cline-any cline-yes">2x</span>
986
+ <span class="cline-any cline-yes">2x</span>
987
+ <span class="cline-any cline-yes">2x</span>
988
+ <span class="cline-any cline-yes">2x</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">2x</span>
992
+ <span class="cline-any cline-yes">1544x</span>
993
+ <span class="cline-any cline-yes">1544x</span>
994
+ <span class="cline-any cline-yes">1544x</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-no">&nbsp;</span>
998
+ <span class="cline-any cline-yes">1544x</span>
999
+ <span class="cline-any cline-yes">76x</span>
1000
+ <span class="cline-any cline-yes">76x</span>
1001
+ <span class="cline-any cline-yes">9x</span>
1002
+ <span class="cline-any cline-yes">9x</span>
1003
+ <span class="cline-any cline-yes">9x</span>
1004
+ <span class="cline-any cline-yes">9x</span>
1005
+ <span class="cline-any cline-yes">9x</span>
1006
+ <span class="cline-any cline-yes">9x</span>
1007
+ <span class="cline-any cline-yes">9x</span>
1008
+ <span class="cline-any cline-yes">9x</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">9x</span>
1013
+ <span class="cline-any cline-yes">1x</span>
1014
+ <span class="cline-any cline-yes">1x</span>
1015
+ <span class="cline-any cline-yes">1x</span>
1016
+ <span class="cline-any cline-yes">9x</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">9x</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">2x</span>
1024
+ <span class="cline-any cline-yes">9x</span>
1025
+ <span class="cline-any cline-yes">1x</span>
1026
+ <span class="cline-any cline-yes">1x</span>
1027
+ <span class="cline-any cline-yes">1x</span>
1028
+ <span class="cline-any cline-yes">9x</span>
1029
+ <span class="cline-any cline-no">&nbsp;</span>
1030
+ <span class="cline-any cline-no">&nbsp;</span>
1031
+ <span class="cline-any cline-no">&nbsp;</span>
1032
+ <span class="cline-any cline-yes">9x</span>
1033
+ <span class="cline-any cline-no">&nbsp;</span>
1034
+ <span class="cline-any cline-no">&nbsp;</span>
1035
+ <span class="cline-any cline-no">&nbsp;</span>
1036
+ <span class="cline-any cline-yes">9x</span>
1037
+ <span class="cline-any cline-no">&nbsp;</span>
1038
+ <span class="cline-any cline-no">&nbsp;</span>
1039
+ <span class="cline-any cline-no">&nbsp;</span>
1040
+ <span class="cline-any cline-yes">9x</span>
1041
+ <span class="cline-any cline-no">&nbsp;</span>
1042
+ <span class="cline-any cline-no">&nbsp;</span>
1043
+ <span class="cline-any cline-no">&nbsp;</span>
1044
+ <span class="cline-any cline-yes">9x</span>
1045
+ <span class="cline-any cline-no">&nbsp;</span>
1046
+ <span class="cline-any cline-no">&nbsp;</span>
1047
+ <span class="cline-any cline-no">&nbsp;</span>
1048
+ <span class="cline-any cline-yes">9x</span>
1049
+ <span class="cline-any cline-no">&nbsp;</span>
1050
+ <span class="cline-any cline-no">&nbsp;</span>
1051
+ <span class="cline-any cline-no">&nbsp;</span>
1052
+ <span class="cline-any cline-no">&nbsp;</span>
1053
+ <span class="cline-any cline-yes">9x</span>
1054
+ <span class="cline-any cline-yes">9x</span>
1055
+ <span class="cline-any cline-yes">9x</span>
1056
+ <span class="cline-any cline-yes">9x</span>
1057
+ <span class="cline-any cline-yes">9x</span>
1058
+ <span class="cline-any cline-yes">9x</span>
1059
+ <span class="cline-any cline-yes">9x</span>
1060
+ <span class="cline-any cline-yes">9x</span>
1061
+ <span class="cline-any cline-yes">9x</span>
1062
+ <span class="cline-any cline-yes">9x</span>
1063
+ <span class="cline-any cline-yes">9x</span>
1064
+ <span class="cline-any cline-yes">9x</span>
1065
+ <span class="cline-any cline-yes">13x</span>
1066
+ <span class="cline-any cline-yes">13x</span>
1067
+ <span class="cline-any cline-yes">13x</span>
1068
+ <span class="cline-any cline-yes">13x</span>
1069
+ <span class="cline-any cline-yes">13x</span>
1070
+ <span class="cline-any cline-yes">13x</span>
1071
+ <span class="cline-any cline-yes">13x</span>
1072
+ <span class="cline-any cline-yes">13x</span>
1073
+ <span class="cline-any cline-yes">13x</span>
1074
+ <span class="cline-any cline-yes">13x</span>
1075
+ <span class="cline-any cline-yes">13x</span>
1076
+ <span class="cline-any cline-yes">13x</span>
1077
+ <span class="cline-any cline-yes">13x</span>
1078
+ <span class="cline-any cline-yes">13x</span>
1079
+ <span class="cline-any cline-yes">9x</span>
1080
+ <span class="cline-any cline-yes">9x</span>
1081
+ <span class="cline-any cline-yes">76x</span>
1082
+ <span class="cline-any cline-yes">76x</span>
1083
+ <span class="cline-any cline-yes">3x</span>
1084
+ <span class="cline-any cline-yes">3x</span>
1085
+ <span class="cline-any cline-yes">3x</span>
1086
+ <span class="cline-any cline-yes">3x</span>
1087
+ <span class="cline-any cline-yes">3x</span>
1088
+ <span class="cline-any cline-yes">3x</span>
1089
+ <span class="cline-any cline-yes">3x</span>
1090
+ <span class="cline-any cline-yes">3x</span>
1091
+ <span class="cline-any cline-yes">3x</span>
1092
+ <span class="cline-any cline-yes">3x</span>
1093
+ <span class="cline-any cline-yes">3x</span>
1094
+ <span class="cline-any cline-yes">6x</span>
1095
+ <span class="cline-any cline-yes">6x</span>
1096
+ <span class="cline-any cline-yes">6x</span>
1097
+ <span class="cline-any cline-yes">6x</span>
1098
+ <span class="cline-any cline-yes">6x</span>
1099
+ <span class="cline-any cline-yes">6x</span>
1100
+ <span class="cline-any cline-yes">6x</span>
1101
+ <span class="cline-any cline-yes">6x</span>
1102
+ <span class="cline-any cline-yes">6x</span>
1103
+ <span class="cline-any cline-yes">6x</span>
1104
+ <span class="cline-any cline-yes">6x</span>
1105
+ <span class="cline-any cline-yes">6x</span>
1106
+ <span class="cline-any cline-yes">6x</span>
1107
+ <span class="cline-any cline-yes">6x</span>
1108
+ <span class="cline-any cline-yes">3x</span>
1109
+ <span class="cline-any cline-yes">3x</span>
1110
+ <span class="cline-any cline-yes">76x</span>
1111
+ <span class="cline-any cline-yes">76x</span>
1112
+ <span class="cline-any cline-yes">2x</span>
1113
+ <span class="cline-any cline-yes">2x</span>
1114
+ <span class="cline-any cline-no">&nbsp;</span>
1115
+ <span class="cline-any cline-no">&nbsp;</span>
1116
+ <span class="cline-any cline-no">&nbsp;</span>
1117
+ <span class="cline-any cline-no">&nbsp;</span>
1118
+ <span class="cline-any cline-no">&nbsp;</span>
1119
+ <span class="cline-any cline-no">&nbsp;</span>
1120
+ <span class="cline-any cline-yes">2x</span>
1121
+ <span class="cline-any cline-yes">2x</span>
1122
+ <span class="cline-any cline-yes">2x</span>
1123
+ <span class="cline-any cline-yes">2x</span>
1124
+ <span class="cline-any cline-no">&nbsp;</span>
1125
+ <span class="cline-any cline-no">&nbsp;</span>
1126
+ <span class="cline-any cline-no">&nbsp;</span>
1127
+ <span class="cline-any cline-yes">2x</span>
1128
+ <span class="cline-any cline-no">&nbsp;</span>
1129
+ <span class="cline-any cline-no">&nbsp;</span>
1130
+ <span class="cline-any cline-no">&nbsp;</span>
1131
+ <span class="cline-any cline-yes">2x</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">2x</span>
1138
+ <span class="cline-any cline-yes">2x</span>
1139
+ <span class="cline-any cline-yes">2x</span>
1140
+ <span class="cline-any cline-yes">2x</span>
1141
+ <span class="cline-any cline-yes">2x</span>
1142
+ <span class="cline-any cline-yes">2x</span>
1143
+ <span class="cline-any cline-yes">2x</span>
1144
+ <span class="cline-any cline-yes">2x</span>
1145
+ <span class="cline-any cline-yes">2x</span>
1146
+ <span class="cline-any cline-yes">2x</span>
1147
+ <span class="cline-any cline-yes">6x</span>
1148
+ <span class="cline-any cline-yes">6x</span>
1149
+ <span class="cline-any cline-yes">2x</span>
1150
+ <span class="cline-any cline-yes">2x</span>
1151
+ <span class="cline-any cline-yes">3x</span>
1152
+ <span class="cline-any cline-yes">3x</span>
1153
+ <span class="cline-any cline-yes">2x</span>
1154
+ <span class="cline-any cline-yes">2x</span>
1155
+ <span class="cline-any cline-yes">2x</span>
1156
+ <span class="cline-any cline-yes">2x</span>
1157
+ <span class="cline-any cline-yes">2x</span>
1158
+ <span class="cline-any cline-yes">2x</span>
1159
+ <span class="cline-any cline-yes">2x</span>
1160
+ <span class="cline-any cline-yes">76x</span>
1161
+ <span class="cline-any cline-yes">76x</span>
1162
+ <span class="cline-any cline-yes">47x</span>
1163
+ <span class="cline-any cline-yes">19x</span>
1164
+ <span class="cline-any cline-yes">19x</span>
1165
+ <span class="cline-any cline-yes">19x</span>
1166
+ <span class="cline-any cline-no">&nbsp;</span>
1167
+ <span class="cline-any cline-no">&nbsp;</span>
1168
+ <span class="cline-any cline-yes">19x</span>
1169
+ <span class="cline-any cline-yes">19x</span>
1170
+ <span class="cline-any cline-yes">47x</span>
1171
+ <span class="cline-any cline-yes">76x</span>
1172
+ <span class="cline-any cline-yes">76x</span>
1173
+ <span class="cline-any cline-yes">76x</span>
1174
+ <span class="cline-any cline-yes">76x</span>
1175
+ <span class="cline-any cline-yes">76x</span>
1176
+ <span class="cline-any cline-yes">76x</span>
1177
+ <span class="cline-any cline-yes">76x</span>
1178
+ <span class="cline-any cline-yes">76x</span>
1179
+ <span class="cline-any cline-yes">76x</span>
1180
+ <span class="cline-any cline-yes">7x</span>
1181
+ <span class="cline-any cline-yes">7x</span>
1182
+ <span class="cline-any cline-yes">7x</span>
1183
+ <span class="cline-any cline-yes">7x</span>
1184
+ <span class="cline-any cline-yes">7x</span>
1185
+ <span class="cline-any cline-yes">7x</span>
1186
+ <span class="cline-any cline-yes">7x</span>
1187
+ <span class="cline-any cline-yes">7x</span>
1188
+ <span class="cline-any cline-yes">7x</span>
1189
+ <span class="cline-any cline-yes">7x</span>
1190
+ <span class="cline-any cline-yes">7x</span>
1191
+ <span class="cline-any cline-yes">7x</span>
1192
+ <span class="cline-any cline-yes">7x</span>
1193
+ <span class="cline-any cline-yes">7x</span>
1194
+ <span class="cline-any cline-yes">7x</span>
1195
+ <span class="cline-any cline-yes">7x</span>
1196
+ <span class="cline-any cline-yes">1x</span>
1197
+ <span class="cline-any cline-yes">1x</span>
1198
+ <span class="cline-any cline-yes">7x</span>
1199
+ <span class="cline-any cline-yes">7x</span>
1200
+ <span class="cline-any cline-yes">7x</span>
1201
+ <span class="cline-any cline-yes">7x</span>
1202
+ <span class="cline-any cline-yes">7x</span>
1203
+ <span class="cline-any cline-yes">7x</span>
1204
+ <span class="cline-any cline-yes">7x</span>
1205
+ <span class="cline-any cline-yes">7x</span>
1206
+ <span class="cline-any cline-yes">7x</span>
1207
+ <span class="cline-any cline-yes">7x</span>
1208
+ <span class="cline-any cline-yes">7x</span>
1209
+ <span class="cline-any cline-yes">7x</span>
1210
+ <span class="cline-any cline-yes">7x</span>
1211
+ <span class="cline-any cline-no">&nbsp;</span>
1212
+ <span class="cline-any cline-no">&nbsp;</span>
1213
+ <span class="cline-any cline-yes">7x</span>
1214
+ <span class="cline-any cline-yes">7x</span>
1215
+ <span class="cline-any cline-yes">7x</span>
1216
+ <span class="cline-any cline-yes">76x</span>
1217
+ <span class="cline-any cline-yes">76x</span>
1218
+ <span class="cline-any cline-yes">76x</span>
1219
+ <span class="cline-any cline-yes">76x</span>
1220
+ <span class="cline-any cline-yes">76x</span>
1221
+ <span class="cline-any cline-yes">76x</span>
1222
+ <span class="cline-any cline-yes">76x</span>
1223
+ <span class="cline-any cline-yes">76x</span>
1224
+ <span class="cline-any cline-yes">5x</span>
1225
+ <span class="cline-any cline-yes">5x</span>
1226
+ <span class="cline-any cline-yes">5x</span>
1227
+ <span class="cline-any cline-yes">5x</span>
1228
+ <span class="cline-any cline-yes">5x</span>
1229
+ <span class="cline-any cline-yes">5x</span>
1230
+ <span class="cline-any cline-yes">5x</span>
1231
+ <span class="cline-any cline-yes">5x</span>
1232
+ <span class="cline-any cline-yes">5x</span>
1233
+ <span class="cline-any cline-yes">5x</span>
1234
+ <span class="cline-any cline-yes">5x</span>
1235
+ <span class="cline-any cline-yes">5x</span>
1236
+ <span class="cline-any cline-yes">5x</span>
1237
+ <span class="cline-any cline-yes">76x</span>
1238
+ <span class="cline-any cline-yes">76x</span>
1239
+ <span class="cline-any cline-yes">76x</span>
1240
+ <span class="cline-any cline-yes">76x</span>
1241
+ <span class="cline-any cline-yes">986x</span>
1242
+ <span class="cline-any cline-yes">986x</span>
1243
+ <span class="cline-any cline-yes">986x</span>
1244
+ <span class="cline-any cline-yes">986x</span>
1245
+ <span class="cline-any cline-yes">986x</span>
1246
+ <span class="cline-any cline-yes">986x</span>
1247
+ <span class="cline-any cline-yes">986x</span>
1248
+ <span class="cline-any cline-yes">986x</span>
1249
+ <span class="cline-any cline-yes">986x</span>
1250
+ <span class="cline-any cline-yes">76x</span>
1251
+ <span class="cline-any cline-yes">76x</span>
1252
+ <span class="cline-any cline-yes">197x</span>
1253
+ <span class="cline-any cline-yes">197x</span>
1254
+ <span class="cline-any cline-yes">197x</span>
1255
+ <span class="cline-any cline-yes">197x</span>
1256
+ <span class="cline-any cline-yes">197x</span>
1257
+ <span class="cline-any cline-yes">197x</span>
1258
+ <span class="cline-any cline-yes">197x</span>
1259
+ <span class="cline-any cline-yes">197x</span>
1260
+ <span class="cline-any cline-yes">76x</span>
1261
+ <span class="cline-any cline-yes">76x</span>
1262
+ <span class="cline-any cline-no">&nbsp;</span>
1263
+ <span class="cline-any cline-no">&nbsp;</span>
1264
+ <span class="cline-any cline-yes">76x</span>
1265
+ <span class="cline-any cline-yes">76x</span>
1266
+ <span class="cline-any cline-yes">178x</span>
1267
+ <span class="cline-any cline-yes">178x</span>
1268
+ <span class="cline-any cline-yes">76x</span>
1269
+ <span class="cline-any cline-yes">76x</span>
1270
+ <span class="cline-any cline-yes">486x</span>
1271
+ <span class="cline-any cline-yes">486x</span>
1272
+ <span class="cline-any cline-yes">76x</span>
1273
+ <span class="cline-any cline-yes">76x</span>
1274
+ <span class="cline-any cline-yes">42x</span>
1275
+ <span class="cline-any cline-yes">42x</span>
1276
+ <span class="cline-any cline-yes">76x</span>
1277
+ <span class="cline-any cline-yes">76x</span>
1278
+ <span class="cline-any cline-yes">15x</span>
1279
+ <span class="cline-any cline-yes">15x</span>
1280
+ <span class="cline-any cline-yes">76x</span>
1281
+ <span class="cline-any cline-yes">76x</span>
1282
+ <span class="cline-any cline-yes">721x</span>
1283
+ <span class="cline-any cline-yes">721x</span>
1284
+ <span class="cline-any cline-yes">178x</span>
1285
+ <span class="cline-any cline-yes">178x</span>
1286
+ <span class="cline-any cline-yes">543x</span>
1287
+ <span class="cline-any cline-yes">543x</span>
1288
+ <span class="cline-any cline-yes">543x</span>
1289
+ <span class="cline-any cline-yes">721x</span>
1290
+ <span class="cline-any cline-yes">721x</span>
1291
+ <span class="cline-any cline-yes">721x</span>
1292
+ <span class="cline-any cline-yes">721x</span>
1293
+ <span class="cline-any cline-yes">721x</span>
1294
+ <span class="cline-any cline-yes">721x</span>
1295
+ <span class="cline-any cline-yes">721x</span>
1296
+ <span class="cline-any cline-yes">721x</span>
1297
+ <span class="cline-any cline-yes">721x</span>
1298
+ <span class="cline-any cline-yes">721x</span>
1299
+ <span class="cline-any cline-yes">721x</span>
1300
+ <span class="cline-any cline-yes">721x</span>
1301
+ <span class="cline-any cline-yes">721x</span>
1302
+ <span class="cline-any cline-yes">721x</span>
1303
+ <span class="cline-any cline-yes">721x</span>
1304
+ <span class="cline-any cline-yes">721x</span>
1305
+ <span class="cline-any cline-yes">721x</span>
1306
+ <span class="cline-any cline-yes">721x</span>
1307
+ <span class="cline-any cline-yes">721x</span>
1308
+ <span class="cline-any cline-yes">721x</span>
1309
+ <span class="cline-any cline-yes">721x</span>
1310
+ <span class="cline-any cline-yes">721x</span>
1311
+ <span class="cline-any cline-yes">721x</span>
1312
+ <span class="cline-any cline-yes">721x</span>
1313
+ <span class="cline-any cline-yes">721x</span>
1314
+ <span class="cline-any cline-yes">525x</span>
1315
+ <span class="cline-any cline-yes">525x</span>
1316
+ <span class="cline-any cline-yes">543x</span>
1317
+ <span class="cline-any cline-yes">721x</span>
1318
+ <span class="cline-any cline-yes">76x</span>
1319
+ <span class="cline-any cline-yes">76x</span>
1320
+ <span class="cline-any cline-yes">8x</span>
1321
+ <span class="cline-any cline-yes">8x</span>
1322
+ <span class="cline-any cline-yes">76x</span>
1323
+ <span class="cline-any cline-yes">76x</span>
1324
+ <span class="cline-any cline-yes">3x</span>
1325
+ <span class="cline-any cline-yes">3x</span>
1326
+ <span class="cline-any cline-yes">76x</span>
1327
+ <span class="cline-any cline-yes">76x</span>
1328
+ <span class="cline-any cline-yes">2x</span>
1329
+ <span class="cline-any cline-yes">2x</span>
1330
+ <span class="cline-any cline-yes">76x</span>
1331
+ <span class="cline-any cline-yes">76x</span>
1332
+ <span class="cline-any cline-yes">525x</span>
1333
+ <span class="cline-any cline-yes">525x</span>
1334
+ <span class="cline-any cline-yes">525x</span>
1335
+ <span class="cline-any cline-yes">525x</span>
1336
+ <span class="cline-any cline-yes">525x</span>
1337
+ <span class="cline-any cline-yes">525x</span>
1338
+ <span class="cline-any cline-yes">525x</span>
1339
+ <span class="cline-any cline-yes">525x</span>
1340
+ <span class="cline-any cline-yes">525x</span>
1341
+ <span class="cline-any cline-yes">525x</span>
1342
+ <span class="cline-any cline-yes">525x</span>
1343
+ <span class="cline-any cline-yes">525x</span>
1344
+ <span class="cline-any cline-yes">525x</span>
1345
+ <span class="cline-any cline-yes">501x</span>
1346
+ <span class="cline-any cline-yes">501x</span>
1347
+ <span class="cline-any cline-yes">525x</span>
1348
+ <span class="cline-any cline-yes">525x</span>
1349
+ <span class="cline-any cline-yes">525x</span>
1350
+ <span class="cline-any cline-yes">46x</span>
1351
+ <span class="cline-any cline-yes">525x</span>
1352
+ <span class="cline-any cline-yes">479x</span>
1353
+ <span class="cline-any cline-yes">479x</span>
1354
+ <span class="cline-any cline-yes">525x</span>
1355
+ <span class="cline-any cline-yes">76x</span>
1356
+ <span class="cline-any cline-yes">76x</span>
1357
+ <span class="cline-any cline-yes">19x</span>
1358
+ <span class="cline-any cline-yes">19x</span>
1359
+ <span class="cline-any cline-yes">19x</span>
1360
+ <span class="cline-any cline-yes">19x</span>
1361
+ <span class="cline-any cline-no">&nbsp;</span>
1362
+ <span class="cline-any cline-no">&nbsp;</span>
1363
+ <span class="cline-any cline-yes">19x</span>
1364
+ <span class="cline-any cline-yes">76x</span>
1365
+ <span class="cline-any cline-yes">76x</span>
1366
+ <span class="cline-any cline-yes">76x</span>
1367
+ <span class="cline-any cline-yes">782x</span>
1368
+ <span class="cline-any cline-yes">782x</span>
1369
+ <span class="cline-any cline-yes">782x</span>
1370
+ <span class="cline-any cline-yes">279x</span>
1371
+ <span class="cline-any cline-yes">279x</span>
1372
+ <span class="cline-any cline-yes">782x</span>
1373
+ <span class="cline-any cline-yes">782x</span>
1374
+ <span class="cline-any cline-yes">76x</span>
1375
+ <span class="cline-any cline-yes">782x</span>
1376
+ <span class="cline-any cline-yes">782x</span>
1377
+ <span class="cline-any cline-yes">782x</span>
1378
+ <span class="cline-any cline-yes">782x</span>
1379
+ <span class="cline-any cline-yes">782x</span>
1380
+ <span class="cline-any cline-yes">782x</span>
1381
+ <span class="cline-any cline-yes">782x</span>
1382
+ <span class="cline-any cline-yes">782x</span>
1383
+ <span class="cline-any cline-yes">782x</span>
1384
+ <span class="cline-any cline-yes">782x</span>
1385
+ <span class="cline-any cline-yes">782x</span>
1386
+ <span class="cline-any cline-yes">76x</span>
1387
+ <span class="cline-any cline-yes">229x</span>
1388
+ <span class="cline-any cline-yes">229x</span>
1389
+ <span class="cline-any cline-yes">229x</span>
1390
+ <span class="cline-any cline-yes">76x</span>
1391
+ <span class="cline-any cline-yes">48x</span>
1392
+ <span class="cline-any cline-yes">48x</span>
1393
+ <span class="cline-any cline-yes">37x</span>
1394
+ <span class="cline-any cline-yes">37x</span>
1395
+ <span class="cline-any cline-yes">48x</span>
1396
+ <span class="cline-any cline-yes">48x</span>
1397
+ <span class="cline-any cline-yes">76x</span>
1398
+ <span class="cline-any cline-yes">76x</span>
1399
+ <span class="cline-any cline-yes">76x</span>
1400
+ <span class="cline-any cline-yes">1x</span>
1401
+ <span class="cline-any cline-yes">1x</span>
1402
+ <span class="cline-any cline-yes">1x</span>
1403
+ <span class="cline-any cline-yes">1x</span>
1404
+ <span class="cline-any cline-yes">1x</span>
1405
+ <span class="cline-any cline-yes">1x</span>
1406
+ <span class="cline-any cline-no">&nbsp;</span>
1407
+ <span class="cline-any cline-no">&nbsp;</span>
1408
+ <span class="cline-any cline-yes">1x</span>
1409
+ <span class="cline-any cline-yes">1x</span>
1410
+ <span class="cline-any cline-yes">1x</span>
1411
+ <span class="cline-any cline-yes">76x</span>
1412
+ <span class="cline-any cline-yes">76x</span>
1413
+ <span class="cline-any cline-yes">76x</span>
1414
+ <span class="cline-any cline-yes">76x</span>
1415
+ <span class="cline-any cline-yes">76x</span>
1416
+ <span class="cline-any cline-yes">76x</span>
1417
+ <span class="cline-any cline-yes">76x</span>
1418
+ <span class="cline-any cline-yes">76x</span>
1419
+ <span class="cline-any cline-yes">76x</span>
1420
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
1421
+ * Structured logger with SQLite persistence and stdout output.
1422
+ *
1423
+ * - Writes structured entries to a local SQLite DB
1424
+ * - Prints concise lines to stdout/stderr for operator visibility
1425
+ * - Supports filtering and trace retrieval for dashboard APIs
1426
+ */
1427
+ &nbsp;
1428
+ const path = require('path');
1429
+ const fs = require('fs');
1430
+ const crypto = require('crypto');
1431
+ &nbsp;
1432
+ function resolveDefaultConfigDir() {
1433
+ return process.env.A2A_CONFIG_DIR ||
1434
+ process.env.OPENCLAW_CONFIG_DIR ||
1435
+ path.join(process.env.HOME <span class="branch-0 cbranch-no" title="branch not covered" >|| '/tmp',</span> '.config', 'openclaw');
1436
+ }
1437
+ &nbsp;
1438
+ const LOG_DB_FILENAME = 'a2a-logs.db';
1439
+ const LOG_LEVEL_ORDER = {
1440
+ trace: 10,
1441
+ debug: 20,
1442
+ info: 30,
1443
+ warn: 40,
1444
+ error: 50
1445
+ };
1446
+ &nbsp;
1447
+ function envBool(name, fallback = false) {
1448
+ const raw = process.env[name];
1449
+ if (raw === undefined <span class="branch-0 cbranch-no" title="branch not covered" >|| raw === null <span class="branch-0 cbranch-no" title="branch not covered" ></span>|| raw === '')</span> {
1450
+ return fallback;
1451
+ }
1452
+ <span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" > const normalized = String(raw).trim().toLowerCase();</span></span>
1453
+ return !(normalized === '0' || normalized === 'false' <span class="branch-0 cbranch-no" title="branch not covered" >|| normalized === 'no')</span>;
1454
+ }
1455
+ &nbsp;
1456
+ function normalizeLevel(level) {
1457
+ const normalized = String(level <span class="branch-0 cbranch-no" title="branch not covered" >|| '')</span>.trim().toLowerCase();
1458
+ return LOG_LEVEL_ORDER[normalized] ? normalized <span class="branch-0 cbranch-no" title="branch not covered" >: 'info';</span>
1459
+ }
1460
+ &nbsp;
1461
+ function shouldLog(level, minimumLevel) {
1462
+ const current = LOG_LEVEL_ORDER[normalizeLevel(level)] <span class="branch-0 cbranch-no" title="branch not covered" >|| LOG_LEVEL_ORDER.info;</span>
1463
+ const threshold = LOG_LEVEL_ORDER[normalizeLevel(minimumLevel)] <span class="branch-0 cbranch-no" title="branch not covered" >|| LOG_LEVEL_ORDER.info;</span>
1464
+ return current &gt;= threshold;
1465
+ }
1466
+ &nbsp;
1467
+ function sanitizeText(value, maxLength = 1000) {
1468
+ return String(value <span class="branch-0 cbranch-no" title="branch not covered" >|| '')</span>
1469
+ .replace(/\s+/g, ' ')
1470
+ .trim()
1471
+ .slice(0, maxLength);
1472
+ }
1473
+ &nbsp;
1474
+ function serializeError(error, options = {}) {
1475
+ if (!error) return null;
1476
+ if (error instanceof Error) {
1477
+ const payload = {
1478
+ name: error.name <span class="branch-0 cbranch-no" title="branch not covered" >|| 'Error',</span>
1479
+ message: sanitizeText(error.message <span class="branch-0 cbranch-no" title="branch not covered" >|| 'Unknown error',</span> 2000)
1480
+ };
1481
+ if (error.code) payload.code = String(error.code);
1482
+ if (error.cause) <span class="branch-0 cbranch-no" title="branch not covered" >payload.cause = sanitizeText(String(error.cause), 400);</span>
1483
+ if (options.includeStacks &amp;&amp; error.stack) {
1484
+ payload.stack = String(error.stack).slice(0, 8000);
1485
+ }
1486
+ return payload;
1487
+ }
1488
+ <span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" > if (typeof error === 'object') {</span></span>
1489
+ <span class="cstat-no" title="statement not covered" > try {</span>
1490
+ <span class="cstat-no" title="statement not covered" > return JSON.parse(JSON.stringify(error));</span>
1491
+ <span class="cstat-no" title="statement not covered" > } catch (err) {</span>
1492
+ <span class="cstat-no" title="statement not covered" > return { message: sanitizeText(String(error), 2000) };</span>
1493
+ <span class="cstat-no" title="statement not covered" > }</span>
1494
+ <span class="cstat-no" title="statement not covered" > }</span>
1495
+ <span class="cstat-no" title="statement not covered" > return { message: sanitizeText(String(error), 2000) };</span>
1496
+ }
1497
+ &nbsp;
1498
+ function normalizeContext(context = {}, options = {}) {
1499
+ const entry = context &amp;&amp; typeof context === 'object' ? { ...context } <span class="branch-0 cbranch-no" title="branch not covered" >: {};</span>
1500
+ const errorDetails = serializeError(entry.error, { includeStacks: options.includeStacks });
1501
+ const baseData = entry.data &amp;&amp; typeof entry.data === 'object' ? { ...entry.data } : {};
1502
+ if (errorDetails) {
1503
+ baseData.error = errorDetails;
1504
+ }
1505
+ const hasData = Object.keys(baseData).length &gt; 0;
1506
+ const statusCodeRaw = entry.status_code ?? entry.statusCode;
1507
+ const statusCode = Number.isFinite(Number(statusCodeRaw)) ? Number(statusCodeRaw) : null;
1508
+ const explicitErrorCode = entry.error_code || entry.errorCode || null;
1509
+ const inferredErrorCode = explicitErrorCode || (errorDetails &amp;&amp; errorDetails.code <span class="branch-0 cbranch-no" title="branch not covered" >? errorDetails.code </span>: null);
1510
+ return {
1511
+ event: entry.event ? sanitizeText(entry.event, 120) : null,
1512
+ trace_id: entry.trace_id || entry.traceId || null,
1513
+ conversation_id: entry.conversation_id || entry.conversationId || null,
1514
+ token_id: entry.token_id || entry.tokenId || null,
1515
+ request_id: entry.request_id || entry.requestId || null,
1516
+ error_code: inferredErrorCode ? sanitizeText(inferredErrorCode, 120) : null,
1517
+ hint: entry.hint ? sanitizeText(entry.hint, 500) : null,
1518
+ status_code: statusCode,
1519
+ component: entry.component ? sanitizeText(entry.component, 120) : null,
1520
+ data: hasData ? baseData : null
1521
+ };
1522
+ }
1523
+ &nbsp;
1524
+ class LogStore {
1525
+ constructor(configDir = resolveDefaultConfigDir()) {
1526
+ this.configDir = configDir;
1527
+ this.dbPath = path.join(configDir, LOG_DB_FILENAME);
1528
+ this.db = null;
1529
+ this._dbError = null;
1530
+ this._ensureDir();
1531
+ }
1532
+ &nbsp;
1533
+ _ensureDir() {
1534
+ if (!fs.existsSync(this.configDir)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1535
+ <span class="cstat-no" title="statement not covered" > fs.mkdirSync(this.configDir, { recursive: true });</span>
1536
+ <span class="cstat-no" title="statement not covered" > }</span>
1537
+ }
1538
+ &nbsp;
1539
+ _initDb() {
1540
+ if (this.db) return this.db;
1541
+ if (this._dbError) <span class="branch-0 cbranch-no" title="branch not covered" >return null;</span>
1542
+ &nbsp;
1543
+ try {
1544
+ const Database = require('better-sqlite3');
1545
+ this.db = new Database(this.dbPath);
1546
+ try {
1547
+ fs.chmodSync(this.dbPath, 0o600);
1548
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
1549
+ <span class="cstat-no" title="statement not covered" > // best effort</span>
1550
+ <span class="cstat-no" title="statement not covered" > }</span>
1551
+ const ok = this._ensureSchema();
1552
+ if (!ok) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1553
+ <span class="cstat-no" title="statement not covered" > // Prototyping mode: do not attempt DB migrations; keep the old file and start fresh.</span>
1554
+ <span class="cstat-no" title="statement not covered" > const backupPath = `${this.dbPath}.legacy.${Date.now()}`;</span>
1555
+ <span class="cstat-no" title="statement not covered" > try {</span>
1556
+ <span class="cstat-no" title="statement not covered" > this.db.close();</span>
1557
+ <span class="cstat-no" title="statement not covered" > } catch (err) {</span>
1558
+ <span class="cstat-no" title="statement not covered" > // ignore</span>
1559
+ <span class="cstat-no" title="statement not covered" > }</span>
1560
+ <span class="cstat-no" title="statement not covered" > fs.renameSync(this.dbPath, backupPath);</span>
1561
+ <span class="cstat-no" title="statement not covered" > this.db = new Database(this.dbPath);</span>
1562
+ <span class="cstat-no" title="statement not covered" > try {</span>
1563
+ <span class="cstat-no" title="statement not covered" > fs.chmodSync(this.dbPath, 0o600);</span>
1564
+ <span class="cstat-no" title="statement not covered" > } catch (err) {</span>
1565
+ <span class="cstat-no" title="statement not covered" > // best effort</span>
1566
+ <span class="cstat-no" title="statement not covered" > }</span>
1567
+ <span class="cstat-no" title="statement not covered" > const ok2 = this._ensureSchema();</span>
1568
+ <span class="cstat-no" title="statement not covered" > if (!ok2) {</span>
1569
+ <span class="cstat-no" title="statement not covered" > this._dbError = 'failed_to_initialize_log_db_schema';</span>
1570
+ <span class="cstat-no" title="statement not covered" > return null;</span>
1571
+ <span class="cstat-no" title="statement not covered" > }</span>
1572
+ <span class="cstat-no" title="statement not covered" > }</span>
1573
+ this._prepareStatements();
1574
+ return this.db;
1575
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
1576
+ <span class="cstat-no" title="statement not covered" > this._dbError = err.message || 'failed_to_initialize_log_db';</span>
1577
+ <span class="cstat-no" title="statement not covered" > return null;</span>
1578
+ <span class="cstat-no" title="statement not covered" > }</span>
1579
+ }
1580
+ &nbsp;
1581
+ _ensureSchema() {
1582
+ this.db.exec(`
1583
+ PRAGMA journal_mode = WAL;
1584
+ &nbsp;
1585
+ CREATE TABLE IF NOT EXISTS logs (
1586
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
1587
+ timestamp TEXT NOT NULL,
1588
+ level TEXT NOT NULL,
1589
+ component TEXT NOT NULL,
1590
+ event TEXT,
1591
+ message TEXT NOT NULL,
1592
+ trace_id TEXT,
1593
+ conversation_id TEXT,
1594
+ token_id TEXT,
1595
+ request_id TEXT,
1596
+ error_code TEXT,
1597
+ status_code INTEGER,
1598
+ hint TEXT,
1599
+ data TEXT
1600
+ );
1601
+ &nbsp;
1602
+ CREATE INDEX IF NOT EXISTS idx_logs_timestamp ON logs(timestamp DESC);
1603
+ CREATE INDEX IF NOT EXISTS idx_logs_level ON logs(level);
1604
+ CREATE INDEX IF NOT EXISTS idx_logs_component ON logs(component);
1605
+ CREATE INDEX IF NOT EXISTS idx_logs_trace ON logs(trace_id);
1606
+ CREATE INDEX IF NOT EXISTS idx_logs_conversation ON logs(conversation_id);
1607
+ CREATE INDEX IF NOT EXISTS idx_logs_token ON logs(token_id);
1608
+ CREATE INDEX IF NOT EXISTS idx_logs_error_code ON logs(error_code);
1609
+ `);
1610
+ &nbsp;
1611
+ const columns = this.db.prepare(`PRAGMA table_info(logs)`).all();
1612
+ const names = new Set(columns.map(c =&gt; c &amp;&amp; c.name).filter(Boolean));
1613
+ const required = ['timestamp', 'level', 'component', 'message', 'error_code', 'status_code', 'hint', 'data'];
1614
+ return required.every((name) =&gt; names.has(name));
1615
+ }
1616
+ &nbsp;
1617
+ _prepareStatements() {
1618
+ this.insertStmt = this.db.prepare(`
1619
+ INSERT INTO logs (
1620
+ timestamp, level, component, event, message,
1621
+ trace_id, conversation_id, token_id, request_id, error_code, status_code, hint, data
1622
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1623
+ `);
1624
+ // A2A-64: Prepared statement for time-based retention pruning
1625
+ this.pruneStmt = this.db.prepare('DELETE FROM logs WHERE timestamp &lt; ?');
1626
+ }
1627
+ &nbsp;
1628
+ <span class="fstat-no" title="function not covered" > isAvailable() {</span>
1629
+ <span class="cstat-no" title="statement not covered" > return this._initDb() !== null;</span>
1630
+ <span class="cstat-no" title="statement not covered" > }</span>
1631
+ &nbsp;
1632
+ <span class="fstat-no" title="function not covered" > getError() {</span>
1633
+ <span class="cstat-no" title="statement not covered" > this._initDb();</span>
1634
+ <span class="cstat-no" title="statement not covered" > return this._dbError;</span>
1635
+ <span class="cstat-no" title="statement not covered" > }</span>
1636
+ &nbsp;
1637
+ write(entry) {
1638
+ const db = this._initDb();
1639
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return false;</span>
1640
+ const dataText = entry.data ? JSON.stringify(entry.data) : null;
1641
+ try {
1642
+ this.insertStmt.run(
1643
+ entry.timestamp,
1644
+ entry.level,
1645
+ entry.component,
1646
+ entry.event,
1647
+ entry.message,
1648
+ entry.trace_id,
1649
+ entry.conversation_id,
1650
+ entry.token_id,
1651
+ entry.request_id,
1652
+ entry.error_code,
1653
+ entry.status_code,
1654
+ entry.hint,
1655
+ dataText
1656
+ );
1657
+ &nbsp;
1658
+ // A2A-64: Auto-prune on every 1000th write (dashboard-events.js pattern).
1659
+ // Best effort — prune failures must not affect write operations.
1660
+ this._writeCount = (this._writeCount || 0) + 1;
1661
+ if (this._writeCount % 1000 === 0 &amp;&amp; !this._pruning) {
1662
+ try {
1663
+ const threshold = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
1664
+ this.pruneStmt.run(threshold);
1665
+ } catch (_) {
1666
+ // A2A-64: Best effort — silent catch like dashboard-events.js:149
1667
+ }
1668
+ }
1669
+ &nbsp;
1670
+ return true;
1671
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
1672
+ <span class="cstat-no" title="statement not covered" > this._dbError = err.message || 'failed_to_write_log_entry';</span>
1673
+ <span class="cstat-no" title="statement not covered" > return false;</span>
1674
+ <span class="cstat-no" title="statement not covered" > }</span>
1675
+ }
1676
+ &nbsp;
1677
+ list(options = {}) {
1678
+ const db = this._initDb();
1679
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return [];</span>
1680
+ &nbsp;
1681
+ const limit = Math.min(1000, Math.max(1, Number.parseInt(options.limit <span class="branch-0 cbranch-no" title="branch not covered" >|| '200',</span> 10) <span class="branch-0 cbranch-no" title="branch not covered" >|| 200)</span>);
1682
+ const where = [];
1683
+ const params = [];
1684
+ &nbsp;
1685
+ if (options.level) {
1686
+ where.push('level = ?');
1687
+ params.push(normalizeLevel(options.level));
1688
+ }
1689
+ if (options.component) {
1690
+ where.push('component = ?');
1691
+ params.push(String(options.component));
1692
+ }
1693
+ if (options.event) {
1694
+ where.push('event = ?');
1695
+ params.push(String(options.event));
1696
+ }
1697
+ if (options.errorCode) {
1698
+ where.push('error_code = ?');
1699
+ params.push(String(options.errorCode));
1700
+ }
1701
+ if (options.statusCode !== undefined &amp;&amp; options.statusCode !== null &amp;&amp; options.statusCode !== '') {
1702
+ where.push('status_code = ?');
1703
+ params.push(Number(options.statusCode));
1704
+ }
1705
+ if (options.traceId) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1706
+ <span class="cstat-no" title="statement not covered" > where.push('trace_id = ?');</span>
1707
+ <span class="cstat-no" title="statement not covered" > params.push(String(options.traceId));</span>
1708
+ <span class="cstat-no" title="statement not covered" > }</span>
1709
+ if (options.conversationId) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1710
+ <span class="cstat-no" title="statement not covered" > where.push('conversation_id = ?');</span>
1711
+ <span class="cstat-no" title="statement not covered" > params.push(String(options.conversationId));</span>
1712
+ <span class="cstat-no" title="statement not covered" > }</span>
1713
+ if (options.tokenId) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1714
+ <span class="cstat-no" title="statement not covered" > where.push('token_id = ?');</span>
1715
+ <span class="cstat-no" title="statement not covered" > params.push(String(options.tokenId));</span>
1716
+ <span class="cstat-no" title="statement not covered" > }</span>
1717
+ if (options.from) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1718
+ <span class="cstat-no" title="statement not covered" > where.push('timestamp &gt;= ?');</span>
1719
+ <span class="cstat-no" title="statement not covered" > params.push(String(options.from));</span>
1720
+ <span class="cstat-no" title="statement not covered" > }</span>
1721
+ if (options.to) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1722
+ <span class="cstat-no" title="statement not covered" > where.push('timestamp &lt;= ?');</span>
1723
+ <span class="cstat-no" title="statement not covered" > params.push(String(options.to));</span>
1724
+ <span class="cstat-no" title="statement not covered" > }</span>
1725
+ if (options.search) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1726
+ <span class="cstat-no" title="statement not covered" > where.push('(message LIKE ? OR data LIKE ?)');</span>
1727
+ <span class="cstat-no" title="statement not covered" > const like = `%${String(options.search).replace(/%/g, '')}%`;</span>
1728
+ <span class="cstat-no" title="statement not covered" > params.push(like, like);</span>
1729
+ <span class="cstat-no" title="statement not covered" > }</span>
1730
+ &nbsp;
1731
+ const query = `
1732
+ SELECT id, timestamp, level, component, event, message,
1733
+ trace_id, conversation_id, token_id, request_id, error_code, status_code, hint, data
1734
+ FROM logs
1735
+ ${where.length ? `WHERE ${where.join(' AND ')}` : ''}
1736
+ ORDER BY id DESC
1737
+ LIMIT ?
1738
+ `;
1739
+ params.push(limit);
1740
+ &nbsp;
1741
+ return db.prepare(query).all(...params).map(row =&gt; ({
1742
+ id: row.id,
1743
+ timestamp: row.timestamp,
1744
+ level: row.level,
1745
+ component: row.component,
1746
+ event: row.event,
1747
+ message: row.message,
1748
+ trace_id: row.trace_id,
1749
+ conversation_id: row.conversation_id,
1750
+ token_id: row.token_id,
1751
+ request_id: row.request_id,
1752
+ error_code: row.error_code,
1753
+ status_code: row.status_code,
1754
+ hint: row.hint,
1755
+ data: row.data ? safeJsonParse(row.data) <span class="branch-0 cbranch-no" title="branch not covered" >: null</span>
1756
+ }));
1757
+ }
1758
+ &nbsp;
1759
+ getTrace(traceId, options = {}) {
1760
+ const db = this._initDb();
1761
+ if (!db || !traceId) <span class="branch-0 cbranch-no" title="branch not covered" >return [];</span>
1762
+ const limit = Math.min(1000, Math.max(1, Number.parseInt(options.limit <span class="branch-0 cbranch-no" title="branch not covered" >|| '500',</span> 10) <span class="branch-0 cbranch-no" title="branch not covered" >|| 500)</span>);
1763
+ return db.prepare(`
1764
+ SELECT id, timestamp, level, component, event, message,
1765
+ trace_id, conversation_id, token_id, request_id, error_code, status_code, hint, data
1766
+ FROM logs
1767
+ WHERE trace_id = ?
1768
+ ORDER BY id ASC
1769
+ LIMIT ?
1770
+ `).all(String(traceId), limit).map(row =&gt; ({
1771
+ id: row.id,
1772
+ timestamp: row.timestamp,
1773
+ level: row.level,
1774
+ component: row.component,
1775
+ event: row.event,
1776
+ message: row.message,
1777
+ trace_id: row.trace_id,
1778
+ conversation_id: row.conversation_id,
1779
+ token_id: row.token_id,
1780
+ request_id: row.request_id,
1781
+ error_code: row.error_code,
1782
+ status_code: row.status_code,
1783
+ hint: row.hint,
1784
+ data: row.data ? safeJsonParse(row.data) <span class="branch-0 cbranch-no" title="branch not covered" >: null</span>
1785
+ }));
1786
+ }
1787
+ &nbsp;
1788
+ stats(options = {}) {
1789
+ const db = this._initDb();
1790
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1791
+ <span class="cstat-no" title="statement not covered" > return {</span>
1792
+ <span class="cstat-no" title="statement not covered" > total: 0,</span>
1793
+ <span class="cstat-no" title="statement not covered" > by_level: {},</span>
1794
+ <span class="cstat-no" title="statement not covered" > by_component: {}</span>
1795
+ <span class="cstat-no" title="statement not covered" > };</span>
1796
+ <span class="cstat-no" title="statement not covered" > }</span>
1797
+ &nbsp;
1798
+ const where = [];
1799
+ const params = [];
1800
+ if (options.from) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1801
+ <span class="cstat-no" title="statement not covered" > where.push('timestamp &gt;= ?');</span>
1802
+ <span class="cstat-no" title="statement not covered" > params.push(String(options.from));</span>
1803
+ <span class="cstat-no" title="statement not covered" > }</span>
1804
+ if (options.to) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1805
+ <span class="cstat-no" title="statement not covered" > where.push('timestamp &lt;= ?');</span>
1806
+ <span class="cstat-no" title="statement not covered" > params.push(String(options.to));</span>
1807
+ <span class="cstat-no" title="statement not covered" > }</span>
1808
+ const clause = where.length <span class="branch-0 cbranch-no" title="branch not covered" >? `WHERE ${where.join(' AND ')}` </span>: '';
1809
+ &nbsp;
1810
+ const totalRow = db.prepare(`SELECT COUNT(*) AS count FROM logs ${clause}`).get(...params);
1811
+ const levelRows = db.prepare(`
1812
+ SELECT level, COUNT(*) AS count
1813
+ FROM logs ${clause}
1814
+ GROUP BY level
1815
+ `).all(...params);
1816
+ const componentRows = db.prepare(`
1817
+ SELECT component, COUNT(*) AS count
1818
+ FROM logs ${clause}
1819
+ GROUP BY component
1820
+ `).all(...params);
1821
+ &nbsp;
1822
+ const byLevel = {};
1823
+ for (const row of levelRows) {
1824
+ byLevel[row.level] = row.count;
1825
+ }
1826
+ const byComponent = {};
1827
+ for (const row of componentRows) {
1828
+ byComponent[row.component] = row.count;
1829
+ }
1830
+ &nbsp;
1831
+ return {
1832
+ total: totalRow?.count <span class="branch-0 cbranch-no" title="branch not covered" >|| 0,</span>
1833
+ by_level: byLevel,
1834
+ by_component: byComponent
1835
+ };
1836
+ }
1837
+ &nbsp;
1838
+ close() {
1839
+ if (this.db) {
1840
+ try {
1841
+ this.db.close();
1842
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
1843
+ <span class="cstat-no" title="statement not covered" > // best effort</span>
1844
+ <span class="cstat-no" title="statement not covered" > }</span>
1845
+ this.db = null;
1846
+ }
1847
+ }
1848
+ &nbsp;
1849
+ /**
1850
+ * A2A-64: Delete log entries older than the retention period.
1851
+ *
1852
+ * @param {object} [options]
1853
+ * @param {number} [options.days=30] - Retention period in days
1854
+ * @returns {{ deleted: number }}
1855
+ */
1856
+ pruneOld(options = {}) {
1857
+ const db = this._initDb();
1858
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return { deleted: 0 };</span>
1859
+ &nbsp;
1860
+ const days = Number.isFinite(options.days) ? options.days : 30;
1861
+ const threshold = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
1862
+ &nbsp;
1863
+ // A2A-64: Set _pruning flag to prevent auto-prune recursion if the
1864
+ // cleanup logger writes back to this same store.
1865
+ this._pruning = true;
1866
+ let deleted = 0;
1867
+ try {
1868
+ const result = this.pruneStmt.run(threshold);
1869
+ deleted = result.changes;
1870
+ &nbsp;
1871
+ // A2A-64: Only VACUUM after bulk deletions (&gt;100 rows) to avoid unnecessary I/O
1872
+ if (deleted &gt; 100) {
1873
+ db.exec('VACUUM');
1874
+ }
1875
+ } finally {
1876
+ this._pruning = false;
1877
+ }
1878
+ &nbsp;
1879
+ // A2A-64: Log prune results AFTER prune completes to avoid recursion.
1880
+ // Use a Logger instance with stdout:false for the cleanup component.
1881
+ try {
1882
+ const cleanupLogger = new Logger(this, { component: 'a2a.cleanup', stdout: true, minLevel: 'info' });
1883
+ cleanupLogger.info(`Pruned ${deleted} log entries older than ${days} days`, {
1884
+ event: 'logs_pruned',
1885
+ data: { deleted, days, threshold }
1886
+ });
1887
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (_) {</span>
1888
+ <span class="cstat-no" title="statement not covered" > // A2A-64: Best effort — logging about prune results must not throw</span>
1889
+ <span class="cstat-no" title="statement not covered" > }</span>
1890
+ &nbsp;
1891
+ return { deleted };
1892
+ }
1893
+ &nbsp;
1894
+ /**
1895
+ * A2A-64: Return database-level stats for monitoring.
1896
+ * Complements the existing stats() method which provides level/component breakdowns.
1897
+ *
1898
+ * @returns {{ total: number, oldest_entry: string|null, newest_entry: string|null }}
1899
+ */
1900
+ getDatabaseStats() {
1901
+ const db = this._initDb();
1902
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return { total: 0, oldest_entry: null, newest_entry: null };</span>
1903
+ &nbsp;
1904
+ const row = db.prepare(
1905
+ 'SELECT COUNT(*) AS total, MIN(timestamp) AS oldest, MAX(timestamp) AS newest FROM logs'
1906
+ ).get();
1907
+ &nbsp;
1908
+ return {
1909
+ total: row?.total || 0,
1910
+ oldest_entry: row?.oldest || null,
1911
+ newest_entry: row?.newest || null
1912
+ };
1913
+ }
1914
+ }
1915
+ &nbsp;
1916
+ class Logger {
1917
+ constructor(store, options = {}) {
1918
+ this.store = store;
1919
+ this.component = options.component <span class="branch-0 cbranch-no" title="branch not covered" >|| 'a2a';</span>
1920
+ this.bindings = options.bindings || {};
1921
+ this.stdout = options.stdout !== false;
1922
+ this.minLevel = normalizeLevel(options.minLevel || process.env.A2A_LOG_LEVEL || 'info');
1923
+ this.includeStacks = options.includeStacks !== undefined
1924
+ ? Boolean(options.includeStacks)
1925
+ : envBool('A2A_LOG_STACKS', process.env.NODE_ENV !== 'production');
1926
+ }
1927
+ &nbsp;
1928
+ child(bindings = {}) {
1929
+ return new Logger(this.store, {
1930
+ component: bindings.component || this.component,
1931
+ bindings: { ...this.bindings, ...bindings },
1932
+ stdout: this.stdout,
1933
+ minLevel: this.minLevel,
1934
+ includeStacks: this.includeStacks
1935
+ });
1936
+ }
1937
+ &nbsp;
1938
+ <span class="fstat-no" title="function not covered" > trace(message, context = {}) {</span>
1939
+ <span class="cstat-no" title="statement not covered" > return this.log('trace', message, context);</span>
1940
+ <span class="cstat-no" title="statement not covered" > }</span>
1941
+ &nbsp;
1942
+ debug(message, context = {}) {
1943
+ return this.log('debug', message, context);
1944
+ }
1945
+ &nbsp;
1946
+ info(message, context = {}) {
1947
+ return this.log('info', message, context);
1948
+ }
1949
+ &nbsp;
1950
+ warn(message, context = {}) {
1951
+ return this.log('warn', message, context);
1952
+ }
1953
+ &nbsp;
1954
+ error(message, context = {}) {
1955
+ return this.log('error', message, context);
1956
+ }
1957
+ &nbsp;
1958
+ log(level, message, context = {}) {
1959
+ const normalizedLevel = normalizeLevel(level);
1960
+ if (!shouldLog(normalizedLevel, this.minLevel)) {
1961
+ return null;
1962
+ }
1963
+ &nbsp;
1964
+ const now = new Date().toISOString();
1965
+ const mergedContext = {
1966
+ ...(this.bindings <span class="branch-0 cbranch-no" title="branch not covered" >|| {})</span>,
1967
+ ...(context <span class="branch-0 cbranch-no" title="branch not covered" >|| {})</span>
1968
+ };
1969
+ const normalized = normalizeContext(mergedContext, {
1970
+ includeStacks: this.includeStacks
1971
+ });
1972
+ &nbsp;
1973
+ const entry = {
1974
+ timestamp: now,
1975
+ level: normalizedLevel,
1976
+ component: normalized.component || this.component <span class="branch-0 cbranch-no" title="branch not covered" >|| 'a2a',</span>
1977
+ event: normalized.event,
1978
+ message: sanitizeText(message, 2000) <span class="branch-0 cbranch-no" title="branch not covered" >|| '(empty)',</span>
1979
+ trace_id: normalized.trace_id ? String(normalized.trace_id) : null,
1980
+ conversation_id: normalized.conversation_id ? String(normalized.conversation_id) : null,
1981
+ token_id: normalized.token_id ? String(normalized.token_id) : null,
1982
+ request_id: normalized.request_id ? String(normalized.request_id) : null,
1983
+ error_code: normalized.error_code,
1984
+ status_code: normalized.status_code,
1985
+ hint: normalized.hint,
1986
+ data: normalized.data
1987
+ };
1988
+ &nbsp;
1989
+ this.store.write(entry);
1990
+ if (this.stdout) {
1991
+ this._print(entry);
1992
+ }
1993
+ return entry;
1994
+ }
1995
+ &nbsp;
1996
+ list(options = {}) {
1997
+ return this.store.list(options);
1998
+ }
1999
+ &nbsp;
2000
+ getTrace(traceId, options = {}) {
2001
+ return this.store.getTrace(traceId, options);
2002
+ }
2003
+ &nbsp;
2004
+ stats(options = {}) {
2005
+ return this.store.stats(options);
2006
+ }
2007
+ &nbsp;
2008
+ _print(entry) {
2009
+ const parts = [
2010
+ `[a2a]`,
2011
+ entry.level.toUpperCase(),
2012
+ `${entry.component}${entry.event ? `:${entry.event}` <span class="branch-0 cbranch-no" title="branch not covered" >: ''}</span>`,
2013
+ entry.message
2014
+ ];
2015
+ if (entry.trace_id) parts.push(`trace=${entry.trace_id}`);
2016
+ if (entry.conversation_id) parts.push(`conv=${entry.conversation_id}`);
2017
+ if (entry.token_id) parts.push(`tok=${entry.token_id}`);
2018
+ if (entry.request_id) parts.push(`req=${entry.request_id}`);
2019
+ if (entry.error_code) parts.push(`code=${entry.error_code}`);
2020
+ if (entry.status_code !== null &amp;&amp; entry.status_code !== undefined) parts.push(`status=${entry.status_code}`);
2021
+ if (entry.data &amp;&amp; Object.keys(entry.data).length &gt; 0) {
2022
+ parts.push(`data=${JSON.stringify(entry.data)}`);
2023
+ }
2024
+ if (entry.hint) parts.push(`hint=${entry.hint}`);
2025
+ const line = parts.join(' ');
2026
+ if (entry.level === 'error' || entry.level === 'warn') {
2027
+ console.error(line);
2028
+ } else {
2029
+ console.log(line);
2030
+ }
2031
+ }
2032
+ }
2033
+ &nbsp;
2034
+ function safeJsonParse(value) {
2035
+ try {
2036
+ return JSON.parse(value);
2037
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
2038
+ <span class="cstat-no" title="statement not covered" > return null;</span>
2039
+ <span class="cstat-no" title="statement not covered" > }</span>
2040
+ }
2041
+ &nbsp;
2042
+ const storeCache = new Map();
2043
+ &nbsp;
2044
+ function getStore(configDir) {
2045
+ const resolved = path.resolve(configDir);
2046
+ if (!storeCache.has(resolved)) {
2047
+ storeCache.set(resolved, new LogStore(resolved));
2048
+ }
2049
+ return storeCache.get(resolved);
2050
+ }
2051
+ &nbsp;
2052
+ function createLogger(options = {}) {
2053
+ const configDir = options.configDir || resolveDefaultConfigDir();
2054
+ const store = getStore(configDir);
2055
+ return new Logger(store, {
2056
+ component: options.component <span class="branch-0 cbranch-no" title="branch not covered" >|| 'a2a',</span>
2057
+ bindings: options.bindings || {},
2058
+ stdout: options.stdout !== false,
2059
+ minLevel: options.minLevel,
2060
+ includeStacks: options.includeStacks
2061
+ });
2062
+ }
2063
+ &nbsp;
2064
+ function createTraceId(prefix = 'trace') {
2065
+ return `${prefix}_${crypto.randomBytes(8).toString('hex')}`;
2066
+ }
2067
+ &nbsp;
2068
+ function closeAllLoggerStores() {
2069
+ for (const store of storeCache.values()) {
2070
+ store.close();
2071
+ }
2072
+ storeCache.clear();
2073
+ }
2074
+ &nbsp;
2075
+ // A2A-65: Prune old entries from all cached logger stores.
2076
+ // Best effort — individual store failures are caught and logged.
2077
+ function pruneAllLoggerStores(options = {}) {
2078
+ const results = [];
2079
+ for (const store of storeCache.values()) {
2080
+ try {
2081
+ results.push(store.pruneOld(options));
2082
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (_) {</span>
2083
+ <span class="cstat-no" title="statement not covered" > // A2A-65: Best effort — one store failure must not block others</span>
2084
+ <span class="cstat-no" title="statement not covered" > }</span>
2085
+ }
2086
+ return results;
2087
+ }
2088
+ &nbsp;
2089
+ module.exports = {
2090
+ LOG_DB_FILENAME,
2091
+ LogStore,
2092
+ createLogger,
2093
+ createTraceId,
2094
+ closeAllLoggerStores,
2095
+ pruneAllLoggerStores
2096
+ };
2097
+ &nbsp;</pre></td></tr></table></pre>
2098
+
2099
+ <div class='push'></div><!-- for sticky footer -->
2100
+ </div><!-- /wrapper -->
2101
+ <div class='footer quiet pad2 space-top1 center small'>
2102
+ Code coverage generated by
2103
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
2104
+ at 2026-03-03T22:25:10.857Z
2105
+ </div>
2106
+ <script src="../../prettify.js"></script>
2107
+ <script>
2108
+ window.onload = function () {
2109
+ prettyPrint();
2110
+ };
2111
+ </script>
2112
+ <script src="../../sorter.js"></script>
2113
+ <script src="../../block-navigation.js"></script>
2114
+ </body>
2115
+ </html>
2116
+