a2acalling 0.6.73 → 0.6.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/.a2a-manifest.json +2 -2
  2. package/.c8rc.json +16 -0
  3. package/.node-version +1 -0
  4. package/.serena/project.yml +126 -0
  5. package/ARCHITECTURE.md +40 -16
  6. package/CONVENTIONS.md +39 -6
  7. package/biome.json +27 -0
  8. package/coverage/base.css +224 -0
  9. package/coverage/block-navigation.js +87 -0
  10. package/coverage/favicon.png +0 -0
  11. package/coverage/index.html +146 -0
  12. package/coverage/prettify.css +1 -0
  13. package/coverage/prettify.js +2 -0
  14. package/coverage/sort-arrow-sprite.png +0 -0
  15. package/coverage/sorter.js +210 -0
  16. package/coverage/src/index.html +131 -0
  17. package/coverage/src/index.js.html +313 -0
  18. package/coverage/src/lib/agent-card.js.html +418 -0
  19. package/coverage/src/lib/call-monitor.js.html +700 -0
  20. package/coverage/src/lib/callbook.js.html +1183 -0
  21. package/coverage/src/lib/claude-subagent.js.html +2173 -0
  22. package/coverage/src/lib/client.js.html +2134 -0
  23. package/coverage/src/lib/config.js.html +1525 -0
  24. package/coverage/src/lib/conversation-driver.js.html +1909 -0
  25. package/coverage/src/lib/conversations.js.html +2575 -0
  26. package/coverage/src/lib/crypto.js.html +424 -0
  27. package/coverage/src/lib/dashboard-events.js.html +724 -0
  28. package/coverage/src/lib/disclosure.js.html +2461 -0
  29. package/coverage/src/lib/external-ip.js.html +718 -0
  30. package/coverage/src/lib/index.html +506 -0
  31. package/coverage/src/lib/invite-host.js.html +754 -0
  32. package/coverage/src/lib/local-request.js.html +292 -0
  33. package/coverage/src/lib/logger.js.html +2116 -0
  34. package/coverage/src/lib/openclaw-integration.js.html +1102 -0
  35. package/coverage/src/lib/pid-file.js.html +394 -0
  36. package/coverage/src/lib/port-scanner.js.html +334 -0
  37. package/coverage/src/lib/prompt-template.js.html +1150 -0
  38. package/coverage/src/lib/runtime-adapter.js.html +2188 -0
  39. package/coverage/src/lib/summarizer.js.html +553 -0
  40. package/coverage/src/lib/summary-formatter.js.html +589 -0
  41. package/coverage/src/lib/summary-prompt.js.html +694 -0
  42. package/coverage/src/lib/tokens.js.html +2689 -0
  43. package/coverage/src/lib/turn-timeout.js.html +241 -0
  44. package/coverage/src/lib/update-checker.js.html +364 -0
  45. package/coverage/src/lib/update-manager.js.html +1024 -0
  46. package/coverage/src/routes/a2a.js.html +3724 -0
  47. package/coverage/src/routes/callbook.js.html +511 -0
  48. package/coverage/src/routes/dashboard.js.html +4819 -0
  49. package/coverage/src/routes/index.html +146 -0
  50. package/coverage/src/server.js.html +3622 -0
  51. package/coverage/tmp/coverage-1605378-1772576706365-0.json +1 -0
  52. package/coverage/tmp/coverage-1605384-1772576607459-0.json +1 -0
  53. package/coverage/tmp/coverage-1605410-1772576631155-0.json +1 -0
  54. package/coverage/tmp/coverage-1606942-1772576636869-0.json +1 -0
  55. package/coverage/tmp/coverage-1607004-1772576637454-0.json +1 -0
  56. package/coverage/tmp/coverage-1607044-1772576637876-0.json +1 -0
  57. package/coverage/tmp/coverage-1607096-1772576638356-0.json +1 -0
  58. package/coverage/tmp/coverage-1607145-1772576638777-0.json +1 -0
  59. package/coverage/tmp/coverage-1607201-1772576639277-0.json +1 -0
  60. package/coverage/tmp/coverage-1607247-1772576639755-0.json +1 -0
  61. package/coverage/tmp/coverage-1607317-1772576640083-0.json +1 -0
  62. package/coverage/tmp/coverage-1607381-1772576640465-0.json +1 -0
  63. package/coverage/tmp/coverage-1607446-1772576640868-0.json +1 -0
  64. package/coverage/tmp/coverage-1607501-1772576641662-0.json +1 -0
  65. package/coverage/tmp/coverage-1607534-1772576641565-0.json +1 -0
  66. package/coverage/tmp/coverage-1607627-1772576641871-0.json +1 -0
  67. package/coverage/tmp/coverage-1607665-1772576642172-0.json +1 -0
  68. package/coverage/tmp/coverage-1607714-1772576642577-0.json +1 -0
  69. package/coverage/tmp/coverage-1607788-1772576643466-0.json +1 -0
  70. package/coverage/tmp/coverage-1607924-1772576644678-0.json +1 -0
  71. package/coverage/tmp/coverage-1607978-1772576645154-0.json +1 -0
  72. package/coverage/tmp/coverage-1608035-1772576645564-0.json +1 -0
  73. package/coverage/tmp/coverage-1608106-1772576645967-0.json +1 -0
  74. package/coverage/tmp/coverage-1608179-1772576648656-0.json +1 -0
  75. package/coverage/tmp/coverage-1608196-1772576647367-0.json +1 -0
  76. package/coverage/tmp/coverage-1608217-1772576648557-0.json +1 -0
  77. package/coverage/tmp/coverage-1608256-1772576651378-0.json +1 -0
  78. package/coverage/tmp/coverage-1608265-1772576650058-0.json +1 -0
  79. package/coverage/tmp/coverage-1608289-1772576651358-0.json +1 -0
  80. package/coverage/tmp/coverage-1608591-1772576660465-0.json +1 -0
  81. package/coverage/tmp/coverage-1608648-1772576659272-0.json +1 -0
  82. package/coverage/tmp/coverage-1608665-1772576660374-0.json +1 -0
  83. package/coverage/tmp/coverage-1608677-1772576661268-0.json +1 -0
  84. package/coverage/tmp/coverage-1608684-1772576663968-0.json +1 -0
  85. package/coverage/tmp/coverage-1608692-1772576662575-0.json +1 -0
  86. package/coverage/tmp/coverage-1608701-1772576663873-0.json +1 -0
  87. package/coverage/tmp/coverage-1608718-1772576666674-0.json +1 -0
  88. package/coverage/tmp/coverage-1608725-1772576665463-0.json +1 -0
  89. package/coverage/tmp/coverage-1608738-1772576666577-0.json +1 -0
  90. package/coverage/tmp/coverage-1608753-1772576669664-0.json +1 -0
  91. package/coverage/tmp/coverage-1608763-1772576668275-0.json +1 -0
  92. package/coverage/tmp/coverage-1608771-1772576669563-0.json +1 -0
  93. package/coverage/tmp/coverage-1608828-1772576676574-0.json +1 -0
  94. package/coverage/tmp/coverage-1609244-1772576675272-0.json +1 -0
  95. package/coverage/tmp/coverage-1609342-1772576676478-0.json +1 -0
  96. package/coverage/tmp/coverage-1609450-1772576686954-0.json +1 -0
  97. package/coverage/tmp/coverage-1609841-1772576685466-0.json +1 -0
  98. package/coverage/tmp/coverage-1609925-1772576686855-0.json +1 -0
  99. package/coverage/tmp/coverage-1610399-1772576692469-0.json +1 -0
  100. package/coverage/tmp/coverage-1611283-1772576703062-0.json +1 -0
  101. package/coverage/tmp/coverage-1611294-1772576703755-0.json +1 -0
  102. package/docs/assessments/2026-02-27-google-a2a-protocol-assessment.md +292 -0
  103. package/docs/plans/2026-03-01-a2a-68-openclaw-integration-tests.md +676 -0
  104. package/docs/plans/2026-03-01-a2a-77-invoke-security-tests.md +661 -0
  105. package/docs/plans/2026-03-03-a2a-91-macos-packaging-plan.md +144 -0
  106. package/docs/signing-setup.md +49 -0
  107. package/eslint.config.js +16 -0
  108. package/knip.json +17 -0
  109. package/native/macos/certs/appldevcert.cer +0 -0
  110. package/native/macos/src-tauri/binaries/.gitkeep +0 -0
  111. package/native/macos/src-tauri/capabilities/default.json +11 -1
  112. package/native/macos/src-tauri/entitlements.plist +14 -0
  113. package/native/macos/src-tauri/src/discovery.rs +14 -3
  114. package/native/macos/src-tauri/src/health.rs +4 -0
  115. package/native/macos/src-tauri/src/lib.rs +52 -11
  116. package/native/macos/src-tauri/src/server.rs +262 -26
  117. package/native/macos/src-tauri/tauri.conf.json +13 -4
  118. package/package.json +16 -2
  119. package/pkg.config.json +14 -0
  120. package/scripts/build-standalone.sh +106 -0
  121. package/scripts/install-openclaw.js +3 -5
  122. package/scripts/smoke-test-standalone.sh +101 -0
  123. package/scripts/sync-version.sh +28 -0
  124. package/scripts/verify-app-bundle.sh +34 -0
  125. package/src/lib/agent-card.js +111 -0
  126. package/src/lib/client.js +290 -49
  127. package/src/lib/conversations.js +2 -0
  128. package/src/lib/local-request.js +69 -0
  129. package/src/lib/logger.js +2 -0
  130. package/src/lib/runtime-adapter.js +41 -1
  131. package/src/routes/a2a.js +393 -66
  132. package/src/routes/dashboard.js +1 -27
  133. package/src/server.js +19 -0
  134. package/.maestro/inbox/release-workflow-spam.md +0 -25
@@ -0,0 +1,2575 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/lib/conversations.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> conversations.js</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">81.08% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>673/830</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">67.56% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>100/148</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">95.83% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>23/24</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">81.08% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>673/830</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line high'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a>
525
+ <a name='L460'></a><a href='#L460'>460</a>
526
+ <a name='L461'></a><a href='#L461'>461</a>
527
+ <a name='L462'></a><a href='#L462'>462</a>
528
+ <a name='L463'></a><a href='#L463'>463</a>
529
+ <a name='L464'></a><a href='#L464'>464</a>
530
+ <a name='L465'></a><a href='#L465'>465</a>
531
+ <a name='L466'></a><a href='#L466'>466</a>
532
+ <a name='L467'></a><a href='#L467'>467</a>
533
+ <a name='L468'></a><a href='#L468'>468</a>
534
+ <a name='L469'></a><a href='#L469'>469</a>
535
+ <a name='L470'></a><a href='#L470'>470</a>
536
+ <a name='L471'></a><a href='#L471'>471</a>
537
+ <a name='L472'></a><a href='#L472'>472</a>
538
+ <a name='L473'></a><a href='#L473'>473</a>
539
+ <a name='L474'></a><a href='#L474'>474</a>
540
+ <a name='L475'></a><a href='#L475'>475</a>
541
+ <a name='L476'></a><a href='#L476'>476</a>
542
+ <a name='L477'></a><a href='#L477'>477</a>
543
+ <a name='L478'></a><a href='#L478'>478</a>
544
+ <a name='L479'></a><a href='#L479'>479</a>
545
+ <a name='L480'></a><a href='#L480'>480</a>
546
+ <a name='L481'></a><a href='#L481'>481</a>
547
+ <a name='L482'></a><a href='#L482'>482</a>
548
+ <a name='L483'></a><a href='#L483'>483</a>
549
+ <a name='L484'></a><a href='#L484'>484</a>
550
+ <a name='L485'></a><a href='#L485'>485</a>
551
+ <a name='L486'></a><a href='#L486'>486</a>
552
+ <a name='L487'></a><a href='#L487'>487</a>
553
+ <a name='L488'></a><a href='#L488'>488</a>
554
+ <a name='L489'></a><a href='#L489'>489</a>
555
+ <a name='L490'></a><a href='#L490'>490</a>
556
+ <a name='L491'></a><a href='#L491'>491</a>
557
+ <a name='L492'></a><a href='#L492'>492</a>
558
+ <a name='L493'></a><a href='#L493'>493</a>
559
+ <a name='L494'></a><a href='#L494'>494</a>
560
+ <a name='L495'></a><a href='#L495'>495</a>
561
+ <a name='L496'></a><a href='#L496'>496</a>
562
+ <a name='L497'></a><a href='#L497'>497</a>
563
+ <a name='L498'></a><a href='#L498'>498</a>
564
+ <a name='L499'></a><a href='#L499'>499</a>
565
+ <a name='L500'></a><a href='#L500'>500</a>
566
+ <a name='L501'></a><a href='#L501'>501</a>
567
+ <a name='L502'></a><a href='#L502'>502</a>
568
+ <a name='L503'></a><a href='#L503'>503</a>
569
+ <a name='L504'></a><a href='#L504'>504</a>
570
+ <a name='L505'></a><a href='#L505'>505</a>
571
+ <a name='L506'></a><a href='#L506'>506</a>
572
+ <a name='L507'></a><a href='#L507'>507</a>
573
+ <a name='L508'></a><a href='#L508'>508</a>
574
+ <a name='L509'></a><a href='#L509'>509</a>
575
+ <a name='L510'></a><a href='#L510'>510</a>
576
+ <a name='L511'></a><a href='#L511'>511</a>
577
+ <a name='L512'></a><a href='#L512'>512</a>
578
+ <a name='L513'></a><a href='#L513'>513</a>
579
+ <a name='L514'></a><a href='#L514'>514</a>
580
+ <a name='L515'></a><a href='#L515'>515</a>
581
+ <a name='L516'></a><a href='#L516'>516</a>
582
+ <a name='L517'></a><a href='#L517'>517</a>
583
+ <a name='L518'></a><a href='#L518'>518</a>
584
+ <a name='L519'></a><a href='#L519'>519</a>
585
+ <a name='L520'></a><a href='#L520'>520</a>
586
+ <a name='L521'></a><a href='#L521'>521</a>
587
+ <a name='L522'></a><a href='#L522'>522</a>
588
+ <a name='L523'></a><a href='#L523'>523</a>
589
+ <a name='L524'></a><a href='#L524'>524</a>
590
+ <a name='L525'></a><a href='#L525'>525</a>
591
+ <a name='L526'></a><a href='#L526'>526</a>
592
+ <a name='L527'></a><a href='#L527'>527</a>
593
+ <a name='L528'></a><a href='#L528'>528</a>
594
+ <a name='L529'></a><a href='#L529'>529</a>
595
+ <a name='L530'></a><a href='#L530'>530</a>
596
+ <a name='L531'></a><a href='#L531'>531</a>
597
+ <a name='L532'></a><a href='#L532'>532</a>
598
+ <a name='L533'></a><a href='#L533'>533</a>
599
+ <a name='L534'></a><a href='#L534'>534</a>
600
+ <a name='L535'></a><a href='#L535'>535</a>
601
+ <a name='L536'></a><a href='#L536'>536</a>
602
+ <a name='L537'></a><a href='#L537'>537</a>
603
+ <a name='L538'></a><a href='#L538'>538</a>
604
+ <a name='L539'></a><a href='#L539'>539</a>
605
+ <a name='L540'></a><a href='#L540'>540</a>
606
+ <a name='L541'></a><a href='#L541'>541</a>
607
+ <a name='L542'></a><a href='#L542'>542</a>
608
+ <a name='L543'></a><a href='#L543'>543</a>
609
+ <a name='L544'></a><a href='#L544'>544</a>
610
+ <a name='L545'></a><a href='#L545'>545</a>
611
+ <a name='L546'></a><a href='#L546'>546</a>
612
+ <a name='L547'></a><a href='#L547'>547</a>
613
+ <a name='L548'></a><a href='#L548'>548</a>
614
+ <a name='L549'></a><a href='#L549'>549</a>
615
+ <a name='L550'></a><a href='#L550'>550</a>
616
+ <a name='L551'></a><a href='#L551'>551</a>
617
+ <a name='L552'></a><a href='#L552'>552</a>
618
+ <a name='L553'></a><a href='#L553'>553</a>
619
+ <a name='L554'></a><a href='#L554'>554</a>
620
+ <a name='L555'></a><a href='#L555'>555</a>
621
+ <a name='L556'></a><a href='#L556'>556</a>
622
+ <a name='L557'></a><a href='#L557'>557</a>
623
+ <a name='L558'></a><a href='#L558'>558</a>
624
+ <a name='L559'></a><a href='#L559'>559</a>
625
+ <a name='L560'></a><a href='#L560'>560</a>
626
+ <a name='L561'></a><a href='#L561'>561</a>
627
+ <a name='L562'></a><a href='#L562'>562</a>
628
+ <a name='L563'></a><a href='#L563'>563</a>
629
+ <a name='L564'></a><a href='#L564'>564</a>
630
+ <a name='L565'></a><a href='#L565'>565</a>
631
+ <a name='L566'></a><a href='#L566'>566</a>
632
+ <a name='L567'></a><a href='#L567'>567</a>
633
+ <a name='L568'></a><a href='#L568'>568</a>
634
+ <a name='L569'></a><a href='#L569'>569</a>
635
+ <a name='L570'></a><a href='#L570'>570</a>
636
+ <a name='L571'></a><a href='#L571'>571</a>
637
+ <a name='L572'></a><a href='#L572'>572</a>
638
+ <a name='L573'></a><a href='#L573'>573</a>
639
+ <a name='L574'></a><a href='#L574'>574</a>
640
+ <a name='L575'></a><a href='#L575'>575</a>
641
+ <a name='L576'></a><a href='#L576'>576</a>
642
+ <a name='L577'></a><a href='#L577'>577</a>
643
+ <a name='L578'></a><a href='#L578'>578</a>
644
+ <a name='L579'></a><a href='#L579'>579</a>
645
+ <a name='L580'></a><a href='#L580'>580</a>
646
+ <a name='L581'></a><a href='#L581'>581</a>
647
+ <a name='L582'></a><a href='#L582'>582</a>
648
+ <a name='L583'></a><a href='#L583'>583</a>
649
+ <a name='L584'></a><a href='#L584'>584</a>
650
+ <a name='L585'></a><a href='#L585'>585</a>
651
+ <a name='L586'></a><a href='#L586'>586</a>
652
+ <a name='L587'></a><a href='#L587'>587</a>
653
+ <a name='L588'></a><a href='#L588'>588</a>
654
+ <a name='L589'></a><a href='#L589'>589</a>
655
+ <a name='L590'></a><a href='#L590'>590</a>
656
+ <a name='L591'></a><a href='#L591'>591</a>
657
+ <a name='L592'></a><a href='#L592'>592</a>
658
+ <a name='L593'></a><a href='#L593'>593</a>
659
+ <a name='L594'></a><a href='#L594'>594</a>
660
+ <a name='L595'></a><a href='#L595'>595</a>
661
+ <a name='L596'></a><a href='#L596'>596</a>
662
+ <a name='L597'></a><a href='#L597'>597</a>
663
+ <a name='L598'></a><a href='#L598'>598</a>
664
+ <a name='L599'></a><a href='#L599'>599</a>
665
+ <a name='L600'></a><a href='#L600'>600</a>
666
+ <a name='L601'></a><a href='#L601'>601</a>
667
+ <a name='L602'></a><a href='#L602'>602</a>
668
+ <a name='L603'></a><a href='#L603'>603</a>
669
+ <a name='L604'></a><a href='#L604'>604</a>
670
+ <a name='L605'></a><a href='#L605'>605</a>
671
+ <a name='L606'></a><a href='#L606'>606</a>
672
+ <a name='L607'></a><a href='#L607'>607</a>
673
+ <a name='L608'></a><a href='#L608'>608</a>
674
+ <a name='L609'></a><a href='#L609'>609</a>
675
+ <a name='L610'></a><a href='#L610'>610</a>
676
+ <a name='L611'></a><a href='#L611'>611</a>
677
+ <a name='L612'></a><a href='#L612'>612</a>
678
+ <a name='L613'></a><a href='#L613'>613</a>
679
+ <a name='L614'></a><a href='#L614'>614</a>
680
+ <a name='L615'></a><a href='#L615'>615</a>
681
+ <a name='L616'></a><a href='#L616'>616</a>
682
+ <a name='L617'></a><a href='#L617'>617</a>
683
+ <a name='L618'></a><a href='#L618'>618</a>
684
+ <a name='L619'></a><a href='#L619'>619</a>
685
+ <a name='L620'></a><a href='#L620'>620</a>
686
+ <a name='L621'></a><a href='#L621'>621</a>
687
+ <a name='L622'></a><a href='#L622'>622</a>
688
+ <a name='L623'></a><a href='#L623'>623</a>
689
+ <a name='L624'></a><a href='#L624'>624</a>
690
+ <a name='L625'></a><a href='#L625'>625</a>
691
+ <a name='L626'></a><a href='#L626'>626</a>
692
+ <a name='L627'></a><a href='#L627'>627</a>
693
+ <a name='L628'></a><a href='#L628'>628</a>
694
+ <a name='L629'></a><a href='#L629'>629</a>
695
+ <a name='L630'></a><a href='#L630'>630</a>
696
+ <a name='L631'></a><a href='#L631'>631</a>
697
+ <a name='L632'></a><a href='#L632'>632</a>
698
+ <a name='L633'></a><a href='#L633'>633</a>
699
+ <a name='L634'></a><a href='#L634'>634</a>
700
+ <a name='L635'></a><a href='#L635'>635</a>
701
+ <a name='L636'></a><a href='#L636'>636</a>
702
+ <a name='L637'></a><a href='#L637'>637</a>
703
+ <a name='L638'></a><a href='#L638'>638</a>
704
+ <a name='L639'></a><a href='#L639'>639</a>
705
+ <a name='L640'></a><a href='#L640'>640</a>
706
+ <a name='L641'></a><a href='#L641'>641</a>
707
+ <a name='L642'></a><a href='#L642'>642</a>
708
+ <a name='L643'></a><a href='#L643'>643</a>
709
+ <a name='L644'></a><a href='#L644'>644</a>
710
+ <a name='L645'></a><a href='#L645'>645</a>
711
+ <a name='L646'></a><a href='#L646'>646</a>
712
+ <a name='L647'></a><a href='#L647'>647</a>
713
+ <a name='L648'></a><a href='#L648'>648</a>
714
+ <a name='L649'></a><a href='#L649'>649</a>
715
+ <a name='L650'></a><a href='#L650'>650</a>
716
+ <a name='L651'></a><a href='#L651'>651</a>
717
+ <a name='L652'></a><a href='#L652'>652</a>
718
+ <a name='L653'></a><a href='#L653'>653</a>
719
+ <a name='L654'></a><a href='#L654'>654</a>
720
+ <a name='L655'></a><a href='#L655'>655</a>
721
+ <a name='L656'></a><a href='#L656'>656</a>
722
+ <a name='L657'></a><a href='#L657'>657</a>
723
+ <a name='L658'></a><a href='#L658'>658</a>
724
+ <a name='L659'></a><a href='#L659'>659</a>
725
+ <a name='L660'></a><a href='#L660'>660</a>
726
+ <a name='L661'></a><a href='#L661'>661</a>
727
+ <a name='L662'></a><a href='#L662'>662</a>
728
+ <a name='L663'></a><a href='#L663'>663</a>
729
+ <a name='L664'></a><a href='#L664'>664</a>
730
+ <a name='L665'></a><a href='#L665'>665</a>
731
+ <a name='L666'></a><a href='#L666'>666</a>
732
+ <a name='L667'></a><a href='#L667'>667</a>
733
+ <a name='L668'></a><a href='#L668'>668</a>
734
+ <a name='L669'></a><a href='#L669'>669</a>
735
+ <a name='L670'></a><a href='#L670'>670</a>
736
+ <a name='L671'></a><a href='#L671'>671</a>
737
+ <a name='L672'></a><a href='#L672'>672</a>
738
+ <a name='L673'></a><a href='#L673'>673</a>
739
+ <a name='L674'></a><a href='#L674'>674</a>
740
+ <a name='L675'></a><a href='#L675'>675</a>
741
+ <a name='L676'></a><a href='#L676'>676</a>
742
+ <a name='L677'></a><a href='#L677'>677</a>
743
+ <a name='L678'></a><a href='#L678'>678</a>
744
+ <a name='L679'></a><a href='#L679'>679</a>
745
+ <a name='L680'></a><a href='#L680'>680</a>
746
+ <a name='L681'></a><a href='#L681'>681</a>
747
+ <a name='L682'></a><a href='#L682'>682</a>
748
+ <a name='L683'></a><a href='#L683'>683</a>
749
+ <a name='L684'></a><a href='#L684'>684</a>
750
+ <a name='L685'></a><a href='#L685'>685</a>
751
+ <a name='L686'></a><a href='#L686'>686</a>
752
+ <a name='L687'></a><a href='#L687'>687</a>
753
+ <a name='L688'></a><a href='#L688'>688</a>
754
+ <a name='L689'></a><a href='#L689'>689</a>
755
+ <a name='L690'></a><a href='#L690'>690</a>
756
+ <a name='L691'></a><a href='#L691'>691</a>
757
+ <a name='L692'></a><a href='#L692'>692</a>
758
+ <a name='L693'></a><a href='#L693'>693</a>
759
+ <a name='L694'></a><a href='#L694'>694</a>
760
+ <a name='L695'></a><a href='#L695'>695</a>
761
+ <a name='L696'></a><a href='#L696'>696</a>
762
+ <a name='L697'></a><a href='#L697'>697</a>
763
+ <a name='L698'></a><a href='#L698'>698</a>
764
+ <a name='L699'></a><a href='#L699'>699</a>
765
+ <a name='L700'></a><a href='#L700'>700</a>
766
+ <a name='L701'></a><a href='#L701'>701</a>
767
+ <a name='L702'></a><a href='#L702'>702</a>
768
+ <a name='L703'></a><a href='#L703'>703</a>
769
+ <a name='L704'></a><a href='#L704'>704</a>
770
+ <a name='L705'></a><a href='#L705'>705</a>
771
+ <a name='L706'></a><a href='#L706'>706</a>
772
+ <a name='L707'></a><a href='#L707'>707</a>
773
+ <a name='L708'></a><a href='#L708'>708</a>
774
+ <a name='L709'></a><a href='#L709'>709</a>
775
+ <a name='L710'></a><a href='#L710'>710</a>
776
+ <a name='L711'></a><a href='#L711'>711</a>
777
+ <a name='L712'></a><a href='#L712'>712</a>
778
+ <a name='L713'></a><a href='#L713'>713</a>
779
+ <a name='L714'></a><a href='#L714'>714</a>
780
+ <a name='L715'></a><a href='#L715'>715</a>
781
+ <a name='L716'></a><a href='#L716'>716</a>
782
+ <a name='L717'></a><a href='#L717'>717</a>
783
+ <a name='L718'></a><a href='#L718'>718</a>
784
+ <a name='L719'></a><a href='#L719'>719</a>
785
+ <a name='L720'></a><a href='#L720'>720</a>
786
+ <a name='L721'></a><a href='#L721'>721</a>
787
+ <a name='L722'></a><a href='#L722'>722</a>
788
+ <a name='L723'></a><a href='#L723'>723</a>
789
+ <a name='L724'></a><a href='#L724'>724</a>
790
+ <a name='L725'></a><a href='#L725'>725</a>
791
+ <a name='L726'></a><a href='#L726'>726</a>
792
+ <a name='L727'></a><a href='#L727'>727</a>
793
+ <a name='L728'></a><a href='#L728'>728</a>
794
+ <a name='L729'></a><a href='#L729'>729</a>
795
+ <a name='L730'></a><a href='#L730'>730</a>
796
+ <a name='L731'></a><a href='#L731'>731</a>
797
+ <a name='L732'></a><a href='#L732'>732</a>
798
+ <a name='L733'></a><a href='#L733'>733</a>
799
+ <a name='L734'></a><a href='#L734'>734</a>
800
+ <a name='L735'></a><a href='#L735'>735</a>
801
+ <a name='L736'></a><a href='#L736'>736</a>
802
+ <a name='L737'></a><a href='#L737'>737</a>
803
+ <a name='L738'></a><a href='#L738'>738</a>
804
+ <a name='L739'></a><a href='#L739'>739</a>
805
+ <a name='L740'></a><a href='#L740'>740</a>
806
+ <a name='L741'></a><a href='#L741'>741</a>
807
+ <a name='L742'></a><a href='#L742'>742</a>
808
+ <a name='L743'></a><a href='#L743'>743</a>
809
+ <a name='L744'></a><a href='#L744'>744</a>
810
+ <a name='L745'></a><a href='#L745'>745</a>
811
+ <a name='L746'></a><a href='#L746'>746</a>
812
+ <a name='L747'></a><a href='#L747'>747</a>
813
+ <a name='L748'></a><a href='#L748'>748</a>
814
+ <a name='L749'></a><a href='#L749'>749</a>
815
+ <a name='L750'></a><a href='#L750'>750</a>
816
+ <a name='L751'></a><a href='#L751'>751</a>
817
+ <a name='L752'></a><a href='#L752'>752</a>
818
+ <a name='L753'></a><a href='#L753'>753</a>
819
+ <a name='L754'></a><a href='#L754'>754</a>
820
+ <a name='L755'></a><a href='#L755'>755</a>
821
+ <a name='L756'></a><a href='#L756'>756</a>
822
+ <a name='L757'></a><a href='#L757'>757</a>
823
+ <a name='L758'></a><a href='#L758'>758</a>
824
+ <a name='L759'></a><a href='#L759'>759</a>
825
+ <a name='L760'></a><a href='#L760'>760</a>
826
+ <a name='L761'></a><a href='#L761'>761</a>
827
+ <a name='L762'></a><a href='#L762'>762</a>
828
+ <a name='L763'></a><a href='#L763'>763</a>
829
+ <a name='L764'></a><a href='#L764'>764</a>
830
+ <a name='L765'></a><a href='#L765'>765</a>
831
+ <a name='L766'></a><a href='#L766'>766</a>
832
+ <a name='L767'></a><a href='#L767'>767</a>
833
+ <a name='L768'></a><a href='#L768'>768</a>
834
+ <a name='L769'></a><a href='#L769'>769</a>
835
+ <a name='L770'></a><a href='#L770'>770</a>
836
+ <a name='L771'></a><a href='#L771'>771</a>
837
+ <a name='L772'></a><a href='#L772'>772</a>
838
+ <a name='L773'></a><a href='#L773'>773</a>
839
+ <a name='L774'></a><a href='#L774'>774</a>
840
+ <a name='L775'></a><a href='#L775'>775</a>
841
+ <a name='L776'></a><a href='#L776'>776</a>
842
+ <a name='L777'></a><a href='#L777'>777</a>
843
+ <a name='L778'></a><a href='#L778'>778</a>
844
+ <a name='L779'></a><a href='#L779'>779</a>
845
+ <a name='L780'></a><a href='#L780'>780</a>
846
+ <a name='L781'></a><a href='#L781'>781</a>
847
+ <a name='L782'></a><a href='#L782'>782</a>
848
+ <a name='L783'></a><a href='#L783'>783</a>
849
+ <a name='L784'></a><a href='#L784'>784</a>
850
+ <a name='L785'></a><a href='#L785'>785</a>
851
+ <a name='L786'></a><a href='#L786'>786</a>
852
+ <a name='L787'></a><a href='#L787'>787</a>
853
+ <a name='L788'></a><a href='#L788'>788</a>
854
+ <a name='L789'></a><a href='#L789'>789</a>
855
+ <a name='L790'></a><a href='#L790'>790</a>
856
+ <a name='L791'></a><a href='#L791'>791</a>
857
+ <a name='L792'></a><a href='#L792'>792</a>
858
+ <a name='L793'></a><a href='#L793'>793</a>
859
+ <a name='L794'></a><a href='#L794'>794</a>
860
+ <a name='L795'></a><a href='#L795'>795</a>
861
+ <a name='L796'></a><a href='#L796'>796</a>
862
+ <a name='L797'></a><a href='#L797'>797</a>
863
+ <a name='L798'></a><a href='#L798'>798</a>
864
+ <a name='L799'></a><a href='#L799'>799</a>
865
+ <a name='L800'></a><a href='#L800'>800</a>
866
+ <a name='L801'></a><a href='#L801'>801</a>
867
+ <a name='L802'></a><a href='#L802'>802</a>
868
+ <a name='L803'></a><a href='#L803'>803</a>
869
+ <a name='L804'></a><a href='#L804'>804</a>
870
+ <a name='L805'></a><a href='#L805'>805</a>
871
+ <a name='L806'></a><a href='#L806'>806</a>
872
+ <a name='L807'></a><a href='#L807'>807</a>
873
+ <a name='L808'></a><a href='#L808'>808</a>
874
+ <a name='L809'></a><a href='#L809'>809</a>
875
+ <a name='L810'></a><a href='#L810'>810</a>
876
+ <a name='L811'></a><a href='#L811'>811</a>
877
+ <a name='L812'></a><a href='#L812'>812</a>
878
+ <a name='L813'></a><a href='#L813'>813</a>
879
+ <a name='L814'></a><a href='#L814'>814</a>
880
+ <a name='L815'></a><a href='#L815'>815</a>
881
+ <a name='L816'></a><a href='#L816'>816</a>
882
+ <a name='L817'></a><a href='#L817'>817</a>
883
+ <a name='L818'></a><a href='#L818'>818</a>
884
+ <a name='L819'></a><a href='#L819'>819</a>
885
+ <a name='L820'></a><a href='#L820'>820</a>
886
+ <a name='L821'></a><a href='#L821'>821</a>
887
+ <a name='L822'></a><a href='#L822'>822</a>
888
+ <a name='L823'></a><a href='#L823'>823</a>
889
+ <a name='L824'></a><a href='#L824'>824</a>
890
+ <a name='L825'></a><a href='#L825'>825</a>
891
+ <a name='L826'></a><a href='#L826'>826</a>
892
+ <a name='L827'></a><a href='#L827'>827</a>
893
+ <a name='L828'></a><a href='#L828'>828</a>
894
+ <a name='L829'></a><a href='#L829'>829</a>
895
+ <a name='L830'></a><a href='#L830'>830</a>
896
+ <a name='L831'></a><a href='#L831'>831</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">72x</span>
897
+ <span class="cline-any cline-yes">72x</span>
898
+ <span class="cline-any cline-yes">72x</span>
899
+ <span class="cline-any cline-yes">72x</span>
900
+ <span class="cline-any cline-yes">72x</span>
901
+ <span class="cline-any cline-yes">72x</span>
902
+ <span class="cline-any cline-yes">72x</span>
903
+ <span class="cline-any cline-yes">72x</span>
904
+ <span class="cline-any cline-yes">72x</span>
905
+ <span class="cline-any cline-yes">72x</span>
906
+ <span class="cline-any cline-yes">72x</span>
907
+ <span class="cline-any cline-yes">72x</span>
908
+ <span class="cline-any cline-yes">72x</span>
909
+ <span class="cline-any cline-yes">72x</span>
910
+ <span class="cline-any cline-yes">72x</span>
911
+ <span class="cline-any cline-yes">72x</span>
912
+ <span class="cline-any cline-yes">72x</span>
913
+ <span class="cline-any cline-yes">72x</span>
914
+ <span class="cline-any cline-yes">72x</span>
915
+ <span class="cline-any cline-yes">72x</span>
916
+ <span class="cline-any cline-yes">72x</span>
917
+ <span class="cline-any cline-yes">72x</span>
918
+ <span class="cline-any cline-yes">72x</span>
919
+ <span class="cline-any cline-yes">153x</span>
920
+ <span class="cline-any cline-yes">153x</span>
921
+ <span class="cline-any cline-yes">153x</span>
922
+ <span class="cline-any cline-yes">153x</span>
923
+ <span class="cline-any cline-yes">153x</span>
924
+ <span class="cline-any cline-yes">153x</span>
925
+ <span class="cline-any cline-yes">72x</span>
926
+ <span class="cline-any cline-yes">72x</span>
927
+ <span class="cline-any cline-yes">153x</span>
928
+ <span class="cline-any cline-no">&nbsp;</span>
929
+ <span class="cline-any cline-no">&nbsp;</span>
930
+ <span class="cline-any cline-yes">153x</span>
931
+ <span class="cline-any cline-yes">72x</span>
932
+ <span class="cline-any cline-yes">72x</span>
933
+ <span class="cline-any cline-yes">72x</span>
934
+ <span class="cline-any cline-yes">72x</span>
935
+ <span class="cline-any cline-yes">72x</span>
936
+ <span class="cline-any cline-yes">913x</span>
937
+ <span class="cline-any cline-yes">913x</span>
938
+ <span class="cline-any cline-yes">133x</span>
939
+ <span class="cline-any cline-yes">133x</span>
940
+ <span class="cline-any cline-yes">133x</span>
941
+ <span class="cline-any cline-yes">133x</span>
942
+ <span class="cline-any cline-yes">133x</span>
943
+ <span class="cline-any cline-yes">133x</span>
944
+ <span class="cline-any cline-yes">913x</span>
945
+ <span class="cline-any cline-no">&nbsp;</span>
946
+ <span class="cline-any cline-no">&nbsp;</span>
947
+ <span class="cline-any cline-yes">133x</span>
948
+ <span class="cline-any cline-yes">133x</span>
949
+ <span class="cline-any cline-yes">133x</span>
950
+ <span class="cline-any cline-yes">913x</span>
951
+ <span class="cline-any cline-no">&nbsp;</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-no">&nbsp;</span>
955
+ <span class="cline-any cline-no">&nbsp;</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-yes">913x</span>
959
+ <span class="cline-any cline-yes">72x</span>
960
+ <span class="cline-any cline-yes">72x</span>
961
+ <span class="cline-any cline-yes">72x</span>
962
+ <span class="cline-any cline-yes">72x</span>
963
+ <span class="cline-any cline-yes">72x</span>
964
+ <span class="cline-any cline-yes">91x</span>
965
+ <span class="cline-any cline-yes">91x</span>
966
+ <span class="cline-any cline-yes">72x</span>
967
+ <span class="cline-any cline-yes">72x</span>
968
+ <span class="cline-any cline-yes">72x</span>
969
+ <span class="cline-any cline-yes">72x</span>
970
+ <span class="cline-any cline-yes">72x</span>
971
+ <span class="cline-any cline-no">&nbsp;</span>
972
+ <span class="cline-any cline-no">&nbsp;</span>
973
+ <span class="cline-any cline-no">&nbsp;</span>
974
+ <span class="cline-any cline-yes">72x</span>
975
+ <span class="cline-any cline-yes">72x</span>
976
+ <span class="cline-any cline-yes">72x</span>
977
+ <span class="cline-any cline-yes">72x</span>
978
+ <span class="cline-any cline-yes">72x</span>
979
+ <span class="cline-any cline-yes">133x</span>
980
+ <span class="cline-any cline-yes">133x</span>
981
+ <span class="cline-any cline-yes">133x</span>
982
+ <span class="cline-any cline-yes">133x</span>
983
+ <span class="cline-any cline-yes">133x</span>
984
+ <span class="cline-any cline-yes">133x</span>
985
+ <span class="cline-any cline-yes">133x</span>
986
+ <span class="cline-any cline-yes">133x</span>
987
+ <span class="cline-any cline-yes">133x</span>
988
+ <span class="cline-any cline-yes">133x</span>
989
+ <span class="cline-any cline-yes">133x</span>
990
+ <span class="cline-any cline-yes">133x</span>
991
+ <span class="cline-any cline-yes">133x</span>
992
+ <span class="cline-any cline-yes">133x</span>
993
+ <span class="cline-any cline-yes">133x</span>
994
+ <span class="cline-any cline-yes">133x</span>
995
+ <span class="cline-any cline-yes">133x</span>
996
+ <span class="cline-any cline-yes">133x</span>
997
+ <span class="cline-any cline-yes">133x</span>
998
+ <span class="cline-any cline-yes">133x</span>
999
+ <span class="cline-any cline-yes">133x</span>
1000
+ <span class="cline-any cline-yes">133x</span>
1001
+ <span class="cline-any cline-yes">133x</span>
1002
+ <span class="cline-any cline-yes">133x</span>
1003
+ <span class="cline-any cline-yes">133x</span>
1004
+ <span class="cline-any cline-yes">133x</span>
1005
+ <span class="cline-any cline-yes">133x</span>
1006
+ <span class="cline-any cline-yes">133x</span>
1007
+ <span class="cline-any cline-yes">133x</span>
1008
+ <span class="cline-any cline-yes">133x</span>
1009
+ <span class="cline-any cline-yes">133x</span>
1010
+ <span class="cline-any cline-yes">133x</span>
1011
+ <span class="cline-any cline-yes">133x</span>
1012
+ <span class="cline-any cline-yes">133x</span>
1013
+ <span class="cline-any cline-yes">133x</span>
1014
+ <span class="cline-any cline-yes">133x</span>
1015
+ <span class="cline-any cline-yes">133x</span>
1016
+ <span class="cline-any cline-yes">133x</span>
1017
+ <span class="cline-any cline-yes">133x</span>
1018
+ <span class="cline-any cline-yes">133x</span>
1019
+ <span class="cline-any cline-yes">133x</span>
1020
+ <span class="cline-any cline-yes">133x</span>
1021
+ <span class="cline-any cline-yes">133x</span>
1022
+ <span class="cline-any cline-yes">133x</span>
1023
+ <span class="cline-any cline-yes">133x</span>
1024
+ <span class="cline-any cline-yes">133x</span>
1025
+ <span class="cline-any cline-yes">133x</span>
1026
+ <span class="cline-any cline-yes">133x</span>
1027
+ <span class="cline-any cline-yes">133x</span>
1028
+ <span class="cline-any cline-yes">133x</span>
1029
+ <span class="cline-any cline-yes">133x</span>
1030
+ <span class="cline-any cline-yes">133x</span>
1031
+ <span class="cline-any cline-yes">133x</span>
1032
+ <span class="cline-any cline-yes">133x</span>
1033
+ <span class="cline-any cline-yes">133x</span>
1034
+ <span class="cline-any cline-yes">133x</span>
1035
+ <span class="cline-any cline-yes">133x</span>
1036
+ <span class="cline-any cline-yes">133x</span>
1037
+ <span class="cline-any cline-yes">133x</span>
1038
+ <span class="cline-any cline-yes">133x</span>
1039
+ <span class="cline-any cline-yes">133x</span>
1040
+ <span class="cline-any cline-yes">133x</span>
1041
+ <span class="cline-any cline-yes">133x</span>
1042
+ <span class="cline-any cline-yes">72x</span>
1043
+ <span class="cline-any cline-yes">72x</span>
1044
+ <span class="cline-any cline-yes">133x</span>
1045
+ <span class="cline-any cline-yes">133x</span>
1046
+ <span class="cline-any cline-yes">133x</span>
1047
+ <span class="cline-any cline-yes">133x</span>
1048
+ <span class="cline-any cline-yes">133x</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-yes">133x</span>
1052
+ <span class="cline-any cline-yes">133x</span>
1053
+ <span class="cline-any cline-yes">133x</span>
1054
+ <span class="cline-any cline-yes">133x</span>
1055
+ <span class="cline-any cline-yes">133x</span>
1056
+ <span class="cline-any cline-yes">133x</span>
1057
+ <span class="cline-any cline-yes">133x</span>
1058
+ <span class="cline-any cline-yes">133x</span>
1059
+ <span class="cline-any cline-yes">133x</span>
1060
+ <span class="cline-any cline-yes">133x</span>
1061
+ <span class="cline-any cline-no">&nbsp;</span>
1062
+ <span class="cline-any cline-no">&nbsp;</span>
1063
+ <span class="cline-any cline-no">&nbsp;</span>
1064
+ <span class="cline-any cline-no">&nbsp;</span>
1065
+ <span class="cline-any cline-no">&nbsp;</span>
1066
+ <span class="cline-any cline-no">&nbsp;</span>
1067
+ <span class="cline-any cline-no">&nbsp;</span>
1068
+ <span class="cline-any cline-no">&nbsp;</span>
1069
+ <span class="cline-any cline-no">&nbsp;</span>
1070
+ <span class="cline-any cline-no">&nbsp;</span>
1071
+ <span class="cline-any cline-no">&nbsp;</span>
1072
+ <span class="cline-any cline-no">&nbsp;</span>
1073
+ <span class="cline-any cline-no">&nbsp;</span>
1074
+ <span class="cline-any cline-no">&nbsp;</span>
1075
+ <span class="cline-any cline-no">&nbsp;</span>
1076
+ <span class="cline-any cline-no">&nbsp;</span>
1077
+ <span class="cline-any cline-no">&nbsp;</span>
1078
+ <span class="cline-any cline-no">&nbsp;</span>
1079
+ <span class="cline-any cline-no">&nbsp;</span>
1080
+ <span class="cline-any cline-no">&nbsp;</span>
1081
+ <span class="cline-any cline-no">&nbsp;</span>
1082
+ <span class="cline-any cline-no">&nbsp;</span>
1083
+ <span class="cline-any cline-no">&nbsp;</span>
1084
+ <span class="cline-any cline-no">&nbsp;</span>
1085
+ <span class="cline-any cline-no">&nbsp;</span>
1086
+ <span class="cline-any cline-no">&nbsp;</span>
1087
+ <span class="cline-any cline-no">&nbsp;</span>
1088
+ <span class="cline-any cline-no">&nbsp;</span>
1089
+ <span class="cline-any cline-no">&nbsp;</span>
1090
+ <span class="cline-any cline-no">&nbsp;</span>
1091
+ <span class="cline-any cline-no">&nbsp;</span>
1092
+ <span class="cline-any cline-no">&nbsp;</span>
1093
+ <span class="cline-any cline-no">&nbsp;</span>
1094
+ <span class="cline-any cline-no">&nbsp;</span>
1095
+ <span class="cline-any cline-no">&nbsp;</span>
1096
+ <span class="cline-any cline-no">&nbsp;</span>
1097
+ <span class="cline-any cline-no">&nbsp;</span>
1098
+ <span class="cline-any cline-no">&nbsp;</span>
1099
+ <span class="cline-any cline-no">&nbsp;</span>
1100
+ <span class="cline-any cline-no">&nbsp;</span>
1101
+ <span class="cline-any cline-no">&nbsp;</span>
1102
+ <span class="cline-any cline-no">&nbsp;</span>
1103
+ <span class="cline-any cline-no">&nbsp;</span>
1104
+ <span class="cline-any cline-no">&nbsp;</span>
1105
+ <span class="cline-any cline-no">&nbsp;</span>
1106
+ <span class="cline-any cline-no">&nbsp;</span>
1107
+ <span class="cline-any cline-no">&nbsp;</span>
1108
+ <span class="cline-any cline-no">&nbsp;</span>
1109
+ <span class="cline-any cline-no">&nbsp;</span>
1110
+ <span class="cline-any cline-no">&nbsp;</span>
1111
+ <span class="cline-any cline-no">&nbsp;</span>
1112
+ <span class="cline-any cline-no">&nbsp;</span>
1113
+ <span class="cline-any cline-no">&nbsp;</span>
1114
+ <span class="cline-any cline-no">&nbsp;</span>
1115
+ <span class="cline-any cline-yes">133x</span>
1116
+ <span class="cline-any cline-yes">72x</span>
1117
+ <span class="cline-any cline-yes">72x</span>
1118
+ <span class="cline-any cline-yes">72x</span>
1119
+ <span class="cline-any cline-yes">72x</span>
1120
+ <span class="cline-any cline-yes">72x</span>
1121
+ <span class="cline-any cline-yes">6x</span>
1122
+ <span class="cline-any cline-yes">6x</span>
1123
+ <span class="cline-any cline-yes">72x</span>
1124
+ <span class="cline-any cline-yes">72x</span>
1125
+ <span class="cline-any cline-yes">72x</span>
1126
+ <span class="cline-any cline-yes">72x</span>
1127
+ <span class="cline-any cline-yes">72x</span>
1128
+ <span class="cline-any cline-yes">158x</span>
1129
+ <span class="cline-any cline-yes">158x</span>
1130
+ <span class="cline-any cline-yes">158x</span>
1131
+ <span class="cline-any cline-yes">158x</span>
1132
+ <span class="cline-any cline-yes">158x</span>
1133
+ <span class="cline-any cline-yes">158x</span>
1134
+ <span class="cline-any cline-yes">158x</span>
1135
+ <span class="cline-any cline-yes">158x</span>
1136
+ <span class="cline-any cline-yes">158x</span>
1137
+ <span class="cline-any cline-yes">158x</span>
1138
+ <span class="cline-any cline-yes">158x</span>
1139
+ <span class="cline-any cline-yes">158x</span>
1140
+ <span class="cline-any cline-yes">15x</span>
1141
+ <span class="cline-any cline-yes">15x</span>
1142
+ <span class="cline-any cline-yes">15x</span>
1143
+ <span class="cline-any cline-yes">15x</span>
1144
+ <span class="cline-any cline-yes">15x</span>
1145
+ <span class="cline-any cline-yes">15x</span>
1146
+ <span class="cline-any cline-yes">15x</span>
1147
+ <span class="cline-any cline-yes">15x</span>
1148
+ <span class="cline-any cline-yes">143x</span>
1149
+ <span class="cline-any cline-yes">143x</span>
1150
+ <span class="cline-any cline-yes">143x</span>
1151
+ <span class="cline-any cline-yes">143x</span>
1152
+ <span class="cline-any cline-yes">143x</span>
1153
+ <span class="cline-any cline-yes">143x</span>
1154
+ <span class="cline-any cline-yes">143x</span>
1155
+ <span class="cline-any cline-yes">143x</span>
1156
+ <span class="cline-any cline-yes">158x</span>
1157
+ <span class="cline-any cline-no">&nbsp;</span>
1158
+ <span class="cline-any cline-no">&nbsp;</span>
1159
+ <span class="cline-any cline-no">&nbsp;</span>
1160
+ <span class="cline-any cline-no">&nbsp;</span>
1161
+ <span class="cline-any cline-no">&nbsp;</span>
1162
+ <span class="cline-any cline-no">&nbsp;</span>
1163
+ <span class="cline-any cline-no">&nbsp;</span>
1164
+ <span class="cline-any cline-no">&nbsp;</span>
1165
+ <span class="cline-any cline-no">&nbsp;</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">143x</span>
1169
+ <span class="cline-any cline-yes">143x</span>
1170
+ <span class="cline-any cline-yes">158x</span>
1171
+ <span class="cline-any cline-yes">72x</span>
1172
+ <span class="cline-any cline-yes">72x</span>
1173
+ <span class="cline-any cline-yes">72x</span>
1174
+ <span class="cline-any cline-yes">72x</span>
1175
+ <span class="cline-any cline-yes">72x</span>
1176
+ <span class="cline-any cline-yes">376x</span>
1177
+ <span class="cline-any cline-yes">376x</span>
1178
+ <span class="cline-any cline-yes">376x</span>
1179
+ <span class="cline-any cline-yes">376x</span>
1180
+ <span class="cline-any cline-yes">376x</span>
1181
+ <span class="cline-any cline-yes">376x</span>
1182
+ <span class="cline-any cline-yes">376x</span>
1183
+ <span class="cline-any cline-yes">376x</span>
1184
+ <span class="cline-any cline-yes">376x</span>
1185
+ <span class="cline-any cline-yes">376x</span>
1186
+ <span class="cline-any cline-yes">376x</span>
1187
+ <span class="cline-any cline-yes">376x</span>
1188
+ <span class="cline-any cline-yes">376x</span>
1189
+ <span class="cline-any cline-yes">376x</span>
1190
+ <span class="cline-any cline-yes">376x</span>
1191
+ <span class="cline-any cline-yes">376x</span>
1192
+ <span class="cline-any cline-yes">376x</span>
1193
+ <span class="cline-any cline-yes">376x</span>
1194
+ <span class="cline-any cline-yes">376x</span>
1195
+ <span class="cline-any cline-yes">376x</span>
1196
+ <span class="cline-any cline-yes">376x</span>
1197
+ <span class="cline-any cline-yes">376x</span>
1198
+ <span class="cline-any cline-yes">376x</span>
1199
+ <span class="cline-any cline-yes">376x</span>
1200
+ <span class="cline-any cline-yes">376x</span>
1201
+ <span class="cline-any cline-no">&nbsp;</span>
1202
+ <span class="cline-any cline-no">&nbsp;</span>
1203
+ <span class="cline-any cline-no">&nbsp;</span>
1204
+ <span class="cline-any cline-no">&nbsp;</span>
1205
+ <span class="cline-any cline-no">&nbsp;</span>
1206
+ <span class="cline-any cline-no">&nbsp;</span>
1207
+ <span class="cline-any cline-yes">375x</span>
1208
+ <span class="cline-any cline-yes">375x</span>
1209
+ <span class="cline-any cline-yes">376x</span>
1210
+ <span class="cline-any cline-yes">72x</span>
1211
+ <span class="cline-any cline-yes">72x</span>
1212
+ <span class="cline-any cline-yes">72x</span>
1213
+ <span class="cline-any cline-yes">72x</span>
1214
+ <span class="cline-any cline-yes">72x</span>
1215
+ <span class="cline-any cline-yes">155x</span>
1216
+ <span class="cline-any cline-yes">155x</span>
1217
+ <span class="cline-any cline-yes">155x</span>
1218
+ <span class="cline-any cline-yes">155x</span>
1219
+ <span class="cline-any cline-yes">155x</span>
1220
+ <span class="cline-any cline-yes">155x</span>
1221
+ <span class="cline-any cline-yes">151x</span>
1222
+ <span class="cline-any cline-yes">151x</span>
1223
+ <span class="cline-any cline-yes">151x</span>
1224
+ <span class="cline-any cline-yes">151x</span>
1225
+ <span class="cline-any cline-yes">151x</span>
1226
+ <span class="cline-any cline-yes">151x</span>
1227
+ <span class="cline-any cline-yes">151x</span>
1228
+ <span class="cline-any cline-yes">151x</span>
1229
+ <span class="cline-any cline-yes">151x</span>
1230
+ <span class="cline-any cline-yes">151x</span>
1231
+ <span class="cline-any cline-yes">151x</span>
1232
+ <span class="cline-any cline-yes">155x</span>
1233
+ <span class="cline-any cline-yes">13x</span>
1234
+ <span class="cline-any cline-yes">13x</span>
1235
+ <span class="cline-any cline-yes">155x</span>
1236
+ <span class="cline-any cline-yes">13x</span>
1237
+ <span class="cline-any cline-yes">13x</span>
1238
+ <span class="cline-any cline-yes">151x</span>
1239
+ <span class="cline-any cline-yes">151x</span>
1240
+ <span class="cline-any cline-yes">155x</span>
1241
+ <span class="cline-any cline-yes">72x</span>
1242
+ <span class="cline-any cline-yes">72x</span>
1243
+ <span class="cline-any cline-yes">72x</span>
1244
+ <span class="cline-any cline-yes">72x</span>
1245
+ <span class="cline-any cline-yes">72x</span>
1246
+ <span class="cline-any cline-yes">9x</span>
1247
+ <span class="cline-any cline-yes">9x</span>
1248
+ <span class="cline-any cline-yes">9x</span>
1249
+ <span class="cline-any cline-yes">9x</span>
1250
+ <span class="cline-any cline-yes">9x</span>
1251
+ <span class="cline-any cline-yes">9x</span>
1252
+ <span class="cline-any cline-yes">9x</span>
1253
+ <span class="cline-any cline-yes">9x</span>
1254
+ <span class="cline-any cline-yes">9x</span>
1255
+ <span class="cline-any cline-yes">9x</span>
1256
+ <span class="cline-any cline-yes">9x</span>
1257
+ <span class="cline-any cline-yes">9x</span>
1258
+ <span class="cline-any cline-yes">9x</span>
1259
+ <span class="cline-any cline-yes">9x</span>
1260
+ <span class="cline-any cline-yes">1x</span>
1261
+ <span class="cline-any cline-yes">1x</span>
1262
+ <span class="cline-any cline-yes">1x</span>
1263
+ <span class="cline-any cline-yes">9x</span>
1264
+ <span class="cline-any cline-yes">1x</span>
1265
+ <span class="cline-any cline-yes">1x</span>
1266
+ <span class="cline-any cline-yes">1x</span>
1267
+ <span class="cline-any cline-yes">9x</span>
1268
+ <span class="cline-any cline-yes">9x</span>
1269
+ <span class="cline-any cline-yes">9x</span>
1270
+ <span class="cline-any cline-yes">9x</span>
1271
+ <span class="cline-any cline-yes">9x</span>
1272
+ <span class="cline-any cline-yes">9x</span>
1273
+ <span class="cline-any cline-yes">9x</span>
1274
+ <span class="cline-any cline-no">&nbsp;</span>
1275
+ <span class="cline-any cline-no">&nbsp;</span>
1276
+ <span class="cline-any cline-no">&nbsp;</span>
1277
+ <span class="cline-any cline-no">&nbsp;</span>
1278
+ <span class="cline-any cline-no">&nbsp;</span>
1279
+ <span class="cline-any cline-no">&nbsp;</span>
1280
+ <span class="cline-any cline-no">&nbsp;</span>
1281
+ <span class="cline-any cline-no">&nbsp;</span>
1282
+ <span class="cline-any cline-no">&nbsp;</span>
1283
+ <span class="cline-any cline-yes">9x</span>
1284
+ <span class="cline-any cline-yes">9x</span>
1285
+ <span class="cline-any cline-yes">9x</span>
1286
+ <span class="cline-any cline-yes">72x</span>
1287
+ <span class="cline-any cline-yes">72x</span>
1288
+ <span class="cline-any cline-yes">72x</span>
1289
+ <span class="cline-any cline-yes">72x</span>
1290
+ <span class="cline-any cline-yes">72x</span>
1291
+ <span class="cline-any cline-yes">72x</span>
1292
+ <span class="cline-any cline-yes">72x</span>
1293
+ <span class="cline-any cline-yes">72x</span>
1294
+ <span class="cline-any cline-yes">72x</span>
1295
+ <span class="cline-any cline-yes">72x</span>
1296
+ <span class="cline-any cline-yes">73x</span>
1297
+ <span class="cline-any cline-yes">73x</span>
1298
+ <span class="cline-any cline-yes">73x</span>
1299
+ <span class="cline-any cline-yes">73x</span>
1300
+ <span class="cline-any cline-yes">73x</span>
1301
+ <span class="cline-any cline-yes">73x</span>
1302
+ <span class="cline-any cline-yes">1x</span>
1303
+ <span class="cline-any cline-yes">1x</span>
1304
+ <span class="cline-any cline-yes">72x</span>
1305
+ <span class="cline-any cline-yes">72x</span>
1306
+ <span class="cline-any cline-yes">72x</span>
1307
+ <span class="cline-any cline-yes">72x</span>
1308
+ <span class="cline-any cline-yes">72x</span>
1309
+ <span class="cline-any cline-yes">72x</span>
1310
+ <span class="cline-any cline-yes">73x</span>
1311
+ <span class="cline-any cline-yes">9x</span>
1312
+ <span class="cline-any cline-yes">9x</span>
1313
+ <span class="cline-any cline-yes">9x</span>
1314
+ <span class="cline-any cline-yes">9x</span>
1315
+ <span class="cline-any cline-yes">9x</span>
1316
+ <span class="cline-any cline-yes">9x</span>
1317
+ <span class="cline-any cline-yes">9x</span>
1318
+ <span class="cline-any cline-yes">9x</span>
1319
+ <span class="cline-any cline-yes">9x</span>
1320
+ <span class="cline-any cline-yes">9x</span>
1321
+ <span class="cline-any cline-yes">9x</span>
1322
+ <span class="cline-any cline-yes">9x</span>
1323
+ <span class="cline-any cline-yes">9x</span>
1324
+ <span class="cline-any cline-yes">9x</span>
1325
+ <span class="cline-any cline-yes">9x</span>
1326
+ <span class="cline-any cline-yes">9x</span>
1327
+ <span class="cline-any cline-yes">9x</span>
1328
+ <span class="cline-any cline-yes">9x</span>
1329
+ <span class="cline-any cline-yes">9x</span>
1330
+ <span class="cline-any cline-yes">9x</span>
1331
+ <span class="cline-any cline-yes">9x</span>
1332
+ <span class="cline-any cline-yes">9x</span>
1333
+ <span class="cline-any cline-yes">9x</span>
1334
+ <span class="cline-any cline-yes">9x</span>
1335
+ <span class="cline-any cline-yes">9x</span>
1336
+ <span class="cline-any cline-yes">9x</span>
1337
+ <span class="cline-any cline-yes">9x</span>
1338
+ <span class="cline-any cline-yes">9x</span>
1339
+ <span class="cline-any cline-yes">9x</span>
1340
+ <span class="cline-any cline-yes">9x</span>
1341
+ <span class="cline-any cline-yes">9x</span>
1342
+ <span class="cline-any cline-yes">9x</span>
1343
+ <span class="cline-any cline-yes">9x</span>
1344
+ <span class="cline-any cline-yes">9x</span>
1345
+ <span class="cline-any cline-yes">9x</span>
1346
+ <span class="cline-any cline-yes">9x</span>
1347
+ <span class="cline-any cline-yes">9x</span>
1348
+ <span class="cline-any cline-yes">9x</span>
1349
+ <span class="cline-any cline-no">&nbsp;</span>
1350
+ <span class="cline-any cline-no">&nbsp;</span>
1351
+ <span class="cline-any cline-no">&nbsp;</span>
1352
+ <span class="cline-any cline-no">&nbsp;</span>
1353
+ <span class="cline-any cline-no">&nbsp;</span>
1354
+ <span class="cline-any cline-no">&nbsp;</span>
1355
+ <span class="cline-any cline-no">&nbsp;</span>
1356
+ <span class="cline-any cline-no">&nbsp;</span>
1357
+ <span class="cline-any cline-no">&nbsp;</span>
1358
+ <span class="cline-any cline-no">&nbsp;</span>
1359
+ <span class="cline-any cline-no">&nbsp;</span>
1360
+ <span class="cline-any cline-no">&nbsp;</span>
1361
+ <span class="cline-any cline-no">&nbsp;</span>
1362
+ <span class="cline-any cline-no">&nbsp;</span>
1363
+ <span class="cline-any cline-no">&nbsp;</span>
1364
+ <span class="cline-any cline-no">&nbsp;</span>
1365
+ <span class="cline-any cline-no">&nbsp;</span>
1366
+ <span class="cline-any cline-yes">73x</span>
1367
+ <span class="cline-any cline-yes">63x</span>
1368
+ <span class="cline-any cline-yes">63x</span>
1369
+ <span class="cline-any cline-yes">63x</span>
1370
+ <span class="cline-any cline-yes">63x</span>
1371
+ <span class="cline-any cline-yes">63x</span>
1372
+ <span class="cline-any cline-yes">63x</span>
1373
+ <span class="cline-any cline-yes">72x</span>
1374
+ <span class="cline-any cline-yes">73x</span>
1375
+ <span class="cline-any cline-no">&nbsp;</span>
1376
+ <span class="cline-any cline-no">&nbsp;</span>
1377
+ <span class="cline-any cline-no">&nbsp;</span>
1378
+ <span class="cline-any cline-no">&nbsp;</span>
1379
+ <span class="cline-any cline-no">&nbsp;</span>
1380
+ <span class="cline-any cline-no">&nbsp;</span>
1381
+ <span class="cline-any cline-no">&nbsp;</span>
1382
+ <span class="cline-any cline-no">&nbsp;</span>
1383
+ <span class="cline-any cline-no">&nbsp;</span>
1384
+ <span class="cline-any cline-no">&nbsp;</span>
1385
+ <span class="cline-any cline-no">&nbsp;</span>
1386
+ <span class="cline-any cline-no">&nbsp;</span>
1387
+ <span class="cline-any cline-no">&nbsp;</span>
1388
+ <span class="cline-any cline-no">&nbsp;</span>
1389
+ <span class="cline-any cline-no">&nbsp;</span>
1390
+ <span class="cline-any cline-no">&nbsp;</span>
1391
+ <span class="cline-any cline-no">&nbsp;</span>
1392
+ <span class="cline-any cline-no">&nbsp;</span>
1393
+ <span class="cline-any cline-no">&nbsp;</span>
1394
+ <span class="cline-any cline-no">&nbsp;</span>
1395
+ <span class="cline-any cline-no">&nbsp;</span>
1396
+ <span class="cline-any cline-no">&nbsp;</span>
1397
+ <span class="cline-any cline-no">&nbsp;</span>
1398
+ <span class="cline-any cline-yes">72x</span>
1399
+ <span class="cline-any cline-yes">72x</span>
1400
+ <span class="cline-any cline-yes">72x</span>
1401
+ <span class="cline-any cline-yes">72x</span>
1402
+ <span class="cline-any cline-yes">72x</span>
1403
+ <span class="cline-any cline-yes">72x</span>
1404
+ <span class="cline-any cline-yes">72x</span>
1405
+ <span class="cline-any cline-yes">72x</span>
1406
+ <span class="cline-any cline-yes">73x</span>
1407
+ <span class="cline-any cline-yes">72x</span>
1408
+ <span class="cline-any cline-yes">72x</span>
1409
+ <span class="cline-any cline-yes">72x</span>
1410
+ <span class="cline-any cline-yes">72x</span>
1411
+ <span class="cline-any cline-yes">72x</span>
1412
+ <span class="cline-any cline-yes">3x</span>
1413
+ <span class="cline-any cline-yes">3x</span>
1414
+ <span class="cline-any cline-yes">3x</span>
1415
+ <span class="cline-any cline-yes">3x</span>
1416
+ <span class="cline-any cline-yes">3x</span>
1417
+ <span class="cline-any cline-yes">3x</span>
1418
+ <span class="cline-any cline-yes">3x</span>
1419
+ <span class="cline-any cline-yes">3x</span>
1420
+ <span class="cline-any cline-yes">3x</span>
1421
+ <span class="cline-any cline-yes">3x</span>
1422
+ <span class="cline-any cline-no">&nbsp;</span>
1423
+ <span class="cline-any cline-no">&nbsp;</span>
1424
+ <span class="cline-any cline-no">&nbsp;</span>
1425
+ <span class="cline-any cline-no">&nbsp;</span>
1426
+ <span class="cline-any cline-no">&nbsp;</span>
1427
+ <span class="cline-any cline-yes">3x</span>
1428
+ <span class="cline-any cline-yes">3x</span>
1429
+ <span class="cline-any cline-yes">3x</span>
1430
+ <span class="cline-any cline-yes">72x</span>
1431
+ <span class="cline-any cline-yes">72x</span>
1432
+ <span class="cline-any cline-yes">72x</span>
1433
+ <span class="cline-any cline-yes">72x</span>
1434
+ <span class="cline-any cline-yes">72x</span>
1435
+ <span class="cline-any cline-yes">1x</span>
1436
+ <span class="cline-any cline-yes">1x</span>
1437
+ <span class="cline-any cline-yes">1x</span>
1438
+ <span class="cline-any cline-yes">1x</span>
1439
+ <span class="cline-any cline-yes">1x</span>
1440
+ <span class="cline-any cline-yes">1x</span>
1441
+ <span class="cline-any cline-yes">1x</span>
1442
+ <span class="cline-any cline-yes">1x</span>
1443
+ <span class="cline-any cline-yes">1x</span>
1444
+ <span class="cline-any cline-yes">72x</span>
1445
+ <span class="cline-any cline-yes">72x</span>
1446
+ <span class="cline-any cline-yes">72x</span>
1447
+ <span class="cline-any cline-yes">72x</span>
1448
+ <span class="cline-any cline-yes">72x</span>
1449
+ <span class="cline-any cline-yes">16x</span>
1450
+ <span class="cline-any cline-yes">16x</span>
1451
+ <span class="cline-any cline-yes">16x</span>
1452
+ <span class="cline-any cline-yes">16x</span>
1453
+ <span class="cline-any cline-yes">16x</span>
1454
+ <span class="cline-any cline-yes">16x</span>
1455
+ <span class="cline-any cline-yes">16x</span>
1456
+ <span class="cline-any cline-yes">16x</span>
1457
+ <span class="cline-any cline-yes">16x</span>
1458
+ <span class="cline-any cline-yes">16x</span>
1459
+ <span class="cline-any cline-yes">16x</span>
1460
+ <span class="cline-any cline-yes">16x</span>
1461
+ <span class="cline-any cline-yes">16x</span>
1462
+ <span class="cline-any cline-yes">16x</span>
1463
+ <span class="cline-any cline-yes">169x</span>
1464
+ <span class="cline-any cline-yes">169x</span>
1465
+ <span class="cline-any cline-yes">169x</span>
1466
+ <span class="cline-any cline-yes">169x</span>
1467
+ <span class="cline-any cline-yes">169x</span>
1468
+ <span class="cline-any cline-no">&nbsp;</span>
1469
+ <span class="cline-any cline-no">&nbsp;</span>
1470
+ <span class="cline-any cline-yes">169x</span>
1471
+ <span class="cline-any cline-yes">16x</span>
1472
+ <span class="cline-any cline-yes">16x</span>
1473
+ <span class="cline-any cline-yes">16x</span>
1474
+ <span class="cline-any cline-yes">72x</span>
1475
+ <span class="cline-any cline-yes">72x</span>
1476
+ <span class="cline-any cline-yes">72x</span>
1477
+ <span class="cline-any cline-yes">72x</span>
1478
+ <span class="cline-any cline-yes">72x</span>
1479
+ <span class="cline-any cline-yes">72x</span>
1480
+ <span class="cline-any cline-yes">72x</span>
1481
+ <span class="cline-any cline-yes">72x</span>
1482
+ <span class="cline-any cline-yes">72x</span>
1483
+ <span class="cline-any cline-yes">72x</span>
1484
+ <span class="cline-any cline-yes">72x</span>
1485
+ <span class="cline-any cline-yes">72x</span>
1486
+ <span class="cline-any cline-yes">72x</span>
1487
+ <span class="cline-any cline-yes">72x</span>
1488
+ <span class="cline-any cline-yes">72x</span>
1489
+ <span class="cline-any cline-yes">72x</span>
1490
+ <span class="cline-any cline-yes">72x</span>
1491
+ <span class="cline-any cline-yes">72x</span>
1492
+ <span class="cline-any cline-yes">15x</span>
1493
+ <span class="cline-any cline-yes">15x</span>
1494
+ <span class="cline-any cline-no">&nbsp;</span>
1495
+ <span class="cline-any cline-no">&nbsp;</span>
1496
+ <span class="cline-any cline-no">&nbsp;</span>
1497
+ <span class="cline-any cline-no">&nbsp;</span>
1498
+ <span class="cline-any cline-no">&nbsp;</span>
1499
+ <span class="cline-any cline-no">&nbsp;</span>
1500
+ <span class="cline-any cline-no">&nbsp;</span>
1501
+ <span class="cline-any cline-no">&nbsp;</span>
1502
+ <span class="cline-any cline-yes">15x</span>
1503
+ <span class="cline-any cline-yes">15x</span>
1504
+ <span class="cline-any cline-yes">15x</span>
1505
+ <span class="cline-any cline-yes">15x</span>
1506
+ <span class="cline-any cline-yes">15x</span>
1507
+ <span class="cline-any cline-yes">15x</span>
1508
+ <span class="cline-any cline-yes">15x</span>
1509
+ <span class="cline-any cline-yes">15x</span>
1510
+ <span class="cline-any cline-yes">15x</span>
1511
+ <span class="cline-any cline-yes">15x</span>
1512
+ <span class="cline-any cline-yes">15x</span>
1513
+ <span class="cline-any cline-yes">15x</span>
1514
+ <span class="cline-any cline-yes">15x</span>
1515
+ <span class="cline-any cline-yes">15x</span>
1516
+ <span class="cline-any cline-yes">15x</span>
1517
+ <span class="cline-any cline-yes">15x</span>
1518
+ <span class="cline-any cline-yes">15x</span>
1519
+ <span class="cline-any cline-yes">15x</span>
1520
+ <span class="cline-any cline-yes">15x</span>
1521
+ <span class="cline-any cline-yes">15x</span>
1522
+ <span class="cline-any cline-yes">15x</span>
1523
+ <span class="cline-any cline-yes">15x</span>
1524
+ <span class="cline-any cline-yes">15x</span>
1525
+ <span class="cline-any cline-yes">15x</span>
1526
+ <span class="cline-any cline-yes">15x</span>
1527
+ <span class="cline-any cline-yes">15x</span>
1528
+ <span class="cline-any cline-yes">15x</span>
1529
+ <span class="cline-any cline-yes">15x</span>
1530
+ <span class="cline-any cline-yes">15x</span>
1531
+ <span class="cline-any cline-yes">8x</span>
1532
+ <span class="cline-any cline-yes">8x</span>
1533
+ <span class="cline-any cline-yes">8x</span>
1534
+ <span class="cline-any cline-yes">8x</span>
1535
+ <span class="cline-any cline-yes">8x</span>
1536
+ <span class="cline-any cline-yes">8x</span>
1537
+ <span class="cline-any cline-yes">8x</span>
1538
+ <span class="cline-any cline-yes">8x</span>
1539
+ <span class="cline-any cline-yes">8x</span>
1540
+ <span class="cline-any cline-yes">8x</span>
1541
+ <span class="cline-any cline-yes">36x</span>
1542
+ <span class="cline-any cline-yes">36x</span>
1543
+ <span class="cline-any cline-yes">36x</span>
1544
+ <span class="cline-any cline-yes">36x</span>
1545
+ <span class="cline-any cline-yes">36x</span>
1546
+ <span class="cline-any cline-yes">8x</span>
1547
+ <span class="cline-any cline-yes">8x</span>
1548
+ <span class="cline-any cline-yes">8x</span>
1549
+ <span class="cline-any cline-yes">8x</span>
1550
+ <span class="cline-any cline-yes">15x</span>
1551
+ <span class="cline-any cline-yes">15x</span>
1552
+ <span class="cline-any cline-yes">15x</span>
1553
+ <span class="cline-any cline-yes">15x</span>
1554
+ <span class="cline-any cline-yes">15x</span>
1555
+ <span class="cline-any cline-yes">1x</span>
1556
+ <span class="cline-any cline-yes">1x</span>
1557
+ <span class="cline-any cline-yes">1x</span>
1558
+ <span class="cline-any cline-yes">1x</span>
1559
+ <span class="cline-any cline-no">&nbsp;</span>
1560
+ <span class="cline-any cline-no">&nbsp;</span>
1561
+ <span class="cline-any cline-yes">1x</span>
1562
+ <span class="cline-any cline-yes">15x</span>
1563
+ <span class="cline-any cline-yes">15x</span>
1564
+ <span class="cline-any cline-yes">15x</span>
1565
+ <span class="cline-any cline-yes">15x</span>
1566
+ <span class="cline-any cline-yes">15x</span>
1567
+ <span class="cline-any cline-yes">15x</span>
1568
+ <span class="cline-any cline-yes">15x</span>
1569
+ <span class="cline-any cline-yes">15x</span>
1570
+ <span class="cline-any cline-yes">15x</span>
1571
+ <span class="cline-any cline-yes">15x</span>
1572
+ <span class="cline-any cline-yes">15x</span>
1573
+ <span class="cline-any cline-yes">15x</span>
1574
+ <span class="cline-any cline-yes">15x</span>
1575
+ <span class="cline-any cline-yes">15x</span>
1576
+ <span class="cline-any cline-yes">15x</span>
1577
+ <span class="cline-any cline-yes">15x</span>
1578
+ <span class="cline-any cline-yes">15x</span>
1579
+ <span class="cline-any cline-yes">15x</span>
1580
+ <span class="cline-any cline-yes">15x</span>
1581
+ <span class="cline-any cline-yes">15x</span>
1582
+ <span class="cline-any cline-yes">15x</span>
1583
+ <span class="cline-any cline-yes">72x</span>
1584
+ <span class="cline-any cline-yes">72x</span>
1585
+ <span class="cline-any cline-yes">72x</span>
1586
+ <span class="cline-any cline-yes">72x</span>
1587
+ <span class="cline-any cline-yes">72x</span>
1588
+ <span class="cline-any cline-yes">72x</span>
1589
+ <span class="cline-any cline-yes">72x</span>
1590
+ <span class="cline-any cline-yes">9x</span>
1591
+ <span class="cline-any cline-yes">9x</span>
1592
+ <span class="cline-any cline-no">&nbsp;</span>
1593
+ <span class="cline-any cline-no">&nbsp;</span>
1594
+ <span class="cline-any cline-yes">9x</span>
1595
+ <span class="cline-any cline-yes">9x</span>
1596
+ <span class="cline-any cline-yes">9x</span>
1597
+ <span class="cline-any cline-yes">9x</span>
1598
+ <span class="cline-any cline-yes">9x</span>
1599
+ <span class="cline-any cline-yes">9x</span>
1600
+ <span class="cline-any cline-yes">9x</span>
1601
+ <span class="cline-any cline-yes">9x</span>
1602
+ <span class="cline-any cline-yes">9x</span>
1603
+ <span class="cline-any cline-yes">72x</span>
1604
+ <span class="cline-any cline-yes">72x</span>
1605
+ <span class="cline-any cline-yes">72x</span>
1606
+ <span class="cline-any cline-yes">72x</span>
1607
+ <span class="cline-any cline-yes">72x</span>
1608
+ <span class="cline-any cline-yes">70x</span>
1609
+ <span class="cline-any cline-yes">70x</span>
1610
+ <span class="cline-any cline-yes">70x</span>
1611
+ <span class="cline-any cline-yes">70x</span>
1612
+ <span class="cline-any cline-yes">70x</span>
1613
+ <span class="cline-any cline-yes">70x</span>
1614
+ <span class="cline-any cline-yes">68x</span>
1615
+ <span class="cline-any cline-yes">68x</span>
1616
+ <span class="cline-any cline-yes">68x</span>
1617
+ <span class="cline-any cline-yes">35x</span>
1618
+ <span class="cline-any cline-yes">35x</span>
1619
+ <span class="cline-any cline-yes">68x</span>
1620
+ <span class="cline-any cline-yes">68x</span>
1621
+ <span class="cline-any cline-yes">68x</span>
1622
+ <span class="cline-any cline-yes">68x</span>
1623
+ <span class="cline-any cline-yes">68x</span>
1624
+ <span class="cline-any cline-yes">68x</span>
1625
+ <span class="cline-any cline-yes">70x</span>
1626
+ <span class="cline-any cline-yes">7x</span>
1627
+ <span class="cline-any cline-yes">7x</span>
1628
+ <span class="cline-any cline-yes">7x</span>
1629
+ <span class="cline-any cline-yes">7x</span>
1630
+ <span class="cline-any cline-yes">7x</span>
1631
+ <span class="cline-any cline-yes">7x</span>
1632
+ <span class="cline-any cline-yes">7x</span>
1633
+ <span class="cline-any cline-yes">7x</span>
1634
+ <span class="cline-any cline-yes">7x</span>
1635
+ <span class="cline-any cline-yes">70x</span>
1636
+ <span class="cline-any cline-yes">70x</span>
1637
+ <span class="cline-any cline-yes">70x</span>
1638
+ <span class="cline-any cline-yes">70x</span>
1639
+ <span class="cline-any cline-yes">70x</span>
1640
+ <span class="cline-any cline-yes">70x</span>
1641
+ <span class="cline-any cline-yes">70x</span>
1642
+ <span class="cline-any cline-yes">70x</span>
1643
+ <span class="cline-any cline-yes">72x</span>
1644
+ <span class="cline-any cline-yes">72x</span>
1645
+ <span class="cline-any cline-yes">72x</span>
1646
+ <span class="cline-any cline-yes">72x</span>
1647
+ <span class="cline-any cline-yes">72x</span>
1648
+ <span class="cline-any cline-yes">3x</span>
1649
+ <span class="cline-any cline-yes">3x</span>
1650
+ <span class="cline-any cline-yes">3x</span>
1651
+ <span class="cline-any cline-no">&nbsp;</span>
1652
+ <span class="cline-any cline-no">&nbsp;</span>
1653
+ <span class="cline-any cline-yes">3x</span>
1654
+ <span class="cline-any cline-yes">3x</span>
1655
+ <span class="cline-any cline-yes">3x</span>
1656
+ <span class="cline-any cline-yes">3x</span>
1657
+ <span class="cline-any cline-yes">3x</span>
1658
+ <span class="cline-any cline-yes">3x</span>
1659
+ <span class="cline-any cline-yes">3x</span>
1660
+ <span class="cline-any cline-yes">3x</span>
1661
+ <span class="cline-any cline-yes">3x</span>
1662
+ <span class="cline-any cline-yes">3x</span>
1663
+ <span class="cline-any cline-yes">3x</span>
1664
+ <span class="cline-any cline-yes">3x</span>
1665
+ <span class="cline-any cline-yes">3x</span>
1666
+ <span class="cline-any cline-yes">3x</span>
1667
+ <span class="cline-any cline-yes">3x</span>
1668
+ <span class="cline-any cline-yes">3x</span>
1669
+ <span class="cline-any cline-yes">3x</span>
1670
+ <span class="cline-any cline-yes">3x</span>
1671
+ <span class="cline-any cline-yes">3x</span>
1672
+ <span class="cline-any cline-yes">3x</span>
1673
+ <span class="cline-any cline-yes">3x</span>
1674
+ <span class="cline-any cline-yes">3x</span>
1675
+ <span class="cline-any cline-yes">3x</span>
1676
+ <span class="cline-any cline-yes">3x</span>
1677
+ <span class="cline-any cline-yes">3x</span>
1678
+ <span class="cline-any cline-yes">3x</span>
1679
+ <span class="cline-any cline-yes">3x</span>
1680
+ <span class="cline-any cline-yes">3x</span>
1681
+ <span class="cline-any cline-yes">3x</span>
1682
+ <span class="cline-any cline-yes">72x</span>
1683
+ <span class="cline-any cline-yes">72x</span>
1684
+ <span class="cline-any cline-yes">72x</span>
1685
+ <span class="cline-any cline-yes">72x</span>
1686
+ <span class="cline-any cline-yes">72x</span>
1687
+ <span class="cline-any cline-yes">4x</span>
1688
+ <span class="cline-any cline-yes">4x</span>
1689
+ <span class="cline-any cline-yes">4x</span>
1690
+ <span class="cline-any cline-yes">4x</span>
1691
+ <span class="cline-any cline-yes">4x</span>
1692
+ <span class="cline-any cline-yes">4x</span>
1693
+ <span class="cline-any cline-yes">4x</span>
1694
+ <span class="cline-any cline-yes">4x</span>
1695
+ <span class="cline-any cline-yes">3x</span>
1696
+ <span class="cline-any cline-yes">3x</span>
1697
+ <span class="cline-any cline-yes">9x</span>
1698
+ <span class="cline-any cline-yes">9x</span>
1699
+ <span class="cline-any cline-yes">3x</span>
1700
+ <span class="cline-any cline-yes">3x</span>
1701
+ <span class="cline-any cline-yes">3x</span>
1702
+ <span class="cline-any cline-yes">3x</span>
1703
+ <span class="cline-any cline-yes">4x</span>
1704
+ <span class="cline-any cline-yes">4x</span>
1705
+ <span class="cline-any cline-yes">4x</span>
1706
+ <span class="cline-any cline-yes">4x</span>
1707
+ <span class="cline-any cline-yes">4x</span>
1708
+ <span class="cline-any cline-yes">4x</span>
1709
+ <span class="cline-any cline-yes">4x</span>
1710
+ <span class="cline-any cline-yes">4x</span>
1711
+ <span class="cline-any cline-yes">4x</span>
1712
+ <span class="cline-any cline-yes">4x</span>
1713
+ <span class="cline-any cline-yes">72x</span>
1714
+ <span class="cline-any cline-yes">72x</span>
1715
+ <span class="cline-any cline-yes">72x</span>
1716
+ <span class="cline-any cline-yes">72x</span>
1717
+ <span class="cline-any cline-yes">72x</span>
1718
+ <span class="cline-any cline-yes">71x</span>
1719
+ <span class="cline-any cline-yes">51x</span>
1720
+ <span class="cline-any cline-yes">51x</span>
1721
+ <span class="cline-any cline-yes">51x</span>
1722
+ <span class="cline-any cline-yes">71x</span>
1723
+ <span class="cline-any cline-yes">72x</span>
1724
+ <span class="cline-any cline-yes">72x</span>
1725
+ <span class="cline-any cline-yes">72x</span>
1726
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
1727
+ * Conversation storage and summarization for A2A
1728
+ *
1729
+ * Uses SQLite for local storage with auto-summarization on call conclusion.
1730
+ */
1731
+ &nbsp;
1732
+ const path = require('path');
1733
+ const fs = require('fs');
1734
+ const crypto = require('crypto');
1735
+ const { createLogger } = require('./logger');
1736
+ &nbsp;
1737
+ // Default config path
1738
+ const DEFAULT_CONFIG_DIR = process.env.A2A_CONFIG_DIR <span class="branch-0 cbranch-no" title="branch not covered" >|| </span>
1739
+ process.env.OPENCLAW_CONFIG_DIR <span class="branch-0 cbranch-no" title="branch not covered" >|| </span>
1740
+ path.join(process.env.HOME || '/tmp', '.config', 'openclaw');
1741
+ &nbsp;
1742
+ const DB_FILENAME = 'a2a-conversations.db';
1743
+ const logger = createLogger({ component: 'a2a.conversations' });
1744
+ // A2A-63: Dedicated cleanup logger for retention pruning operations
1745
+ const cleanupLogger = createLogger({ component: 'a2a.cleanup' });
1746
+ &nbsp;
1747
+ class ConversationStore {
1748
+ constructor(configDir = DEFAULT_CONFIG_DIR, options = {}) {
1749
+ this.configDir = configDir;
1750
+ this.dbPath = path.join(configDir, DB_FILENAME);
1751
+ this.eventStore = options.eventStore || null;
1752
+ this.db = null;
1753
+ this._ensureDir();
1754
+ }
1755
+ &nbsp;
1756
+ _ensureDir() {
1757
+ if (!fs.existsSync(this.configDir)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1758
+ <span class="cstat-no" title="statement not covered" > fs.mkdirSync(this.configDir, { recursive: true });</span>
1759
+ <span class="cstat-no" title="statement not covered" > }</span>
1760
+ }
1761
+ &nbsp;
1762
+ /**
1763
+ * Initialize SQLite database (lazy load better-sqlite3)
1764
+ */
1765
+ _initDb() {
1766
+ if (this.db) return this.db;
1767
+ if (this._dbError) <span class="branch-0 cbranch-no" title="branch not covered" >return null;</span>
1768
+
1769
+ try {
1770
+ const Database = require('better-sqlite3');
1771
+ this.db = new Database(this.dbPath);
1772
+ try {
1773
+ fs.chmodSync(this.dbPath, 0o600);
1774
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
1775
+ <span class="cstat-no" title="statement not covered" > // Best effort - ignore on platforms without chmod support.</span>
1776
+ <span class="cstat-no" title="statement not covered" > }</span>
1777
+ this._migrate();
1778
+ this._ensureLatestSchema(Database);
1779
+ return this.db;
1780
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
1781
+ <span class="cstat-no" title="statement not covered" > if (err.code === 'MODULE_NOT_FOUND') {</span>
1782
+ <span class="cstat-no" title="statement not covered" > this._dbError = 'better-sqlite3 not installed. Run: npm install better-sqlite3';</span>
1783
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1784
+ <span class="cstat-no" title="statement not covered" > this._dbError = err.message;</span>
1785
+ <span class="cstat-no" title="statement not covered" > }</span>
1786
+ <span class="cstat-no" title="statement not covered" > return null;</span>
1787
+ <span class="cstat-no" title="statement not covered" > }</span>
1788
+ }
1789
+ &nbsp;
1790
+ /**
1791
+ * Check if storage is available
1792
+ */
1793
+ isAvailable() {
1794
+ return this._initDb() !== null;
1795
+ }
1796
+ &nbsp;
1797
+ /**
1798
+ * Get error message if storage unavailable
1799
+ */
1800
+ <span class="fstat-no" title="function not covered" > getError() {</span>
1801
+ <span class="cstat-no" title="statement not covered" > this._initDb();</span>
1802
+ <span class="cstat-no" title="statement not covered" > return this._dbError || null;</span>
1803
+ <span class="cstat-no" title="statement not covered" > }</span>
1804
+ &nbsp;
1805
+ /**
1806
+ * Run database migrations
1807
+ */
1808
+ _migrate() {
1809
+ this.db.exec(`
1810
+ PRAGMA journal_mode = WAL;
1811
+ &nbsp;
1812
+ -- Conversations with remote agents
1813
+ CREATE TABLE IF NOT EXISTS conversations (
1814
+ id TEXT PRIMARY KEY,
1815
+ contact_id TEXT,
1816
+ contact_name TEXT,
1817
+ token_id TEXT,
1818
+ direction TEXT NOT NULL, -- 'inbound' or 'outbound'
1819
+ started_at TEXT NOT NULL,
1820
+ ended_at TEXT,
1821
+ last_message_at TEXT,
1822
+ message_count INTEGER DEFAULT 0,
1823
+ status TEXT DEFAULT 'active', -- 'active', 'concluded', 'timeout'
1824
+
1825
+ -- Live collaboration state
1826
+ collab_phase TEXT DEFAULT 'handshake',
1827
+ collab_turn_count INTEGER DEFAULT 0,
1828
+ collab_overlap_score REAL DEFAULT 0.15,
1829
+ collab_active_threads TEXT,
1830
+ collab_candidate_collaborations TEXT,
1831
+ collab_open_questions TEXT,
1832
+ collab_close_signal INTEGER DEFAULT 0,
1833
+ collab_confidence REAL DEFAULT 0.25,
1834
+ collab_updated_at TEXT,
1835
+ &nbsp;
1836
+ -- Raw summary (neutral, could be shared)
1837
+ summary TEXT,
1838
+ summary_at TEXT,
1839
+
1840
+ -- Owner-context summary (private, never shared)
1841
+ owner_summary TEXT,
1842
+ owner_relevance TEXT,
1843
+ owner_goals_touched TEXT, -- JSON array
1844
+ owner_action_items TEXT, -- JSON array (owner's action items)
1845
+ caller_action_items TEXT, -- JSON array (what caller should do)
1846
+ joint_action_items TEXT, -- JSON array (things to do together)
1847
+ collaboration_opportunity TEXT, -- JSON object
1848
+ owner_follow_up TEXT,
1849
+ owner_notes TEXT
1850
+ );
1851
+ &nbsp;
1852
+ -- Individual messages
1853
+ CREATE TABLE IF NOT EXISTS messages (
1854
+ id TEXT PRIMARY KEY,
1855
+ conversation_id TEXT NOT NULL,
1856
+ direction TEXT NOT NULL, -- 'inbound' or 'outbound'
1857
+ role TEXT NOT NULL, -- 'user' or 'assistant'
1858
+ content TEXT NOT NULL,
1859
+ timestamp TEXT NOT NULL,
1860
+ compressed INTEGER DEFAULT 0,
1861
+ metadata TEXT, -- JSON for extra data
1862
+ FOREIGN KEY (conversation_id) REFERENCES conversations(id)
1863
+ );
1864
+ &nbsp;
1865
+ -- Indexes
1866
+ CREATE INDEX IF NOT EXISTS idx_messages_conversation ON messages(conversation_id);
1867
+ CREATE INDEX IF NOT EXISTS idx_messages_timestamp ON messages(timestamp);
1868
+ CREATE INDEX IF NOT EXISTS idx_conversations_contact ON conversations(contact_id);
1869
+ CREATE INDEX IF NOT EXISTS idx_conversations_status ON conversations(status);
1870
+ `);
1871
+ }
1872
+ &nbsp;
1873
+ _ensureLatestSchema(Database) {
1874
+ // Prototype-mode stance: do not attempt in-place migrations.
1875
+ // If schema is missing required columns, back up and recreate the DB.
1876
+ try {
1877
+ const info = this.db.prepare('PRAGMA table_info(conversations)').all();
1878
+ if (!Array.isArray(info) || info.length === 0) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1879
+ <span class="cstat-no" title="statement not covered" > return;</span>
1880
+ <span class="cstat-no" title="statement not covered" > }</span>
1881
+ const cols = new Set(info.map(row =&gt; row &amp;&amp; row.name).filter(Boolean));
1882
+ const required = [
1883
+ 'joint_action_items',
1884
+ 'collaboration_opportunity',
1885
+ 'collab_phase'
1886
+ ];
1887
+ const missing = required.filter(c =&gt; !cols.has(c));
1888
+ if (missing.length === 0) {
1889
+ return;
1890
+ }
1891
+ <span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" ></span></span>
1892
+ <span class="cstat-no" title="statement not covered" > const backupPath = `${this.dbPath}.bak.${Date.now()}`;</span>
1893
+ <span class="cstat-no" title="statement not covered" > logger.warn('Conversation DB schema mismatch; resetting to latest schema', {</span>
1894
+ <span class="cstat-no" title="statement not covered" > event: 'conversation_db_schema_reset',</span>
1895
+ <span class="cstat-no" title="statement not covered" > data: {</span>
1896
+ <span class="cstat-no" title="statement not covered" > db_path: this.dbPath,</span>
1897
+ <span class="cstat-no" title="statement not covered" > backup_path: backupPath,</span>
1898
+ <span class="cstat-no" title="statement not covered" > missing_columns: missing</span>
1899
+ <span class="cstat-no" title="statement not covered" > }</span>
1900
+ <span class="cstat-no" title="statement not covered" > });</span>
1901
+ <span class="cstat-no" title="statement not covered" ></span>
1902
+ <span class="cstat-no" title="statement not covered" > try { this.db.close(); } catch (_) {}</span>
1903
+ <span class="cstat-no" title="statement not covered" > this.db = null;</span>
1904
+ <span class="cstat-no" title="statement not covered" ></span>
1905
+ <span class="cstat-no" title="statement not covered" > try {</span>
1906
+ <span class="cstat-no" title="statement not covered" > fs.renameSync(this.dbPath, backupPath);</span>
1907
+ <span class="cstat-no" title="statement not covered" > } catch (err) {</span>
1908
+ <span class="cstat-no" title="statement not covered" > try {</span>
1909
+ <span class="cstat-no" title="statement not covered" > fs.copyFileSync(this.dbPath, backupPath);</span>
1910
+ <span class="cstat-no" title="statement not covered" > fs.unlinkSync(this.dbPath);</span>
1911
+ <span class="cstat-no" title="statement not covered" > } catch (err2) {</span>
1912
+ <span class="cstat-no" title="statement not covered" > // If we can't move the old DB out of the way, keep going without resetting.</span>
1913
+ <span class="cstat-no" title="statement not covered" > logger.error('Failed to back up conversations DB for schema reset', {</span>
1914
+ <span class="cstat-no" title="statement not covered" > event: 'conversation_db_schema_reset_backup_failed',</span>
1915
+ <span class="cstat-no" title="statement not covered" > error: err2,</span>
1916
+ <span class="cstat-no" title="statement not covered" > error_code: 'CONVERSATION_DB_SCHEMA_RESET_BACKUP_FAILED',</span>
1917
+ <span class="cstat-no" title="statement not covered" > hint: 'Check file permissions on a2a-conversations.db and ensure the process can rename/unlink it.',</span>
1918
+ <span class="cstat-no" title="statement not covered" > data: {</span>
1919
+ <span class="cstat-no" title="statement not covered" > db_path: this.dbPath,</span>
1920
+ <span class="cstat-no" title="statement not covered" > backup_path: backupPath</span>
1921
+ <span class="cstat-no" title="statement not covered" > }</span>
1922
+ <span class="cstat-no" title="statement not covered" > });</span>
1923
+ <span class="cstat-no" title="statement not covered" > const reopen = new Database(this.dbPath);</span>
1924
+ <span class="cstat-no" title="statement not covered" > this.db = reopen;</span>
1925
+ <span class="cstat-no" title="statement not covered" > return;</span>
1926
+ <span class="cstat-no" title="statement not covered" > }</span>
1927
+ <span class="cstat-no" title="statement not covered" > }</span>
1928
+ <span class="cstat-no" title="statement not covered" ></span>
1929
+ <span class="cstat-no" title="statement not covered" > this.db = new Database(this.dbPath);</span>
1930
+ <span class="cstat-no" title="statement not covered" > try {</span>
1931
+ <span class="cstat-no" title="statement not covered" > fs.chmodSync(this.dbPath, 0o600);</span>
1932
+ <span class="cstat-no" title="statement not covered" > } catch (err) {</span>
1933
+ <span class="cstat-no" title="statement not covered" > // Best effort.</span>
1934
+ <span class="cstat-no" title="statement not covered" > }</span>
1935
+ <span class="cstat-no" title="statement not covered" > this._migrate();</span>
1936
+ <span class="cstat-no" title="statement not covered" > } catch (err) {</span>
1937
+ <span class="cstat-no" title="statement not covered" > // Best effort: leave existing DB in place if schema validation fails unexpectedly.</span>
1938
+ <span class="cstat-no" title="statement not covered" > logger.error('Conversation DB schema validation failed', {</span>
1939
+ <span class="cstat-no" title="statement not covered" > event: 'conversation_db_schema_validation_failed',</span>
1940
+ <span class="cstat-no" title="statement not covered" > error: err,</span>
1941
+ <span class="cstat-no" title="statement not covered" > error_code: 'CONVERSATION_DB_SCHEMA_VALIDATION_FAILED',</span>
1942
+ <span class="cstat-no" title="statement not covered" > hint: 'If this persists, delete ~/.config/openclaw/a2a-conversations.db (prototype mode) and restart.'</span>
1943
+ <span class="cstat-no" title="statement not covered" > });</span>
1944
+ <span class="cstat-no" title="statement not covered" > }</span>
1945
+ }
1946
+ &nbsp;
1947
+ /**
1948
+ * Generate a conversation ID (shared between both agents)
1949
+ */
1950
+ static generateConversationId() {
1951
+ return 'conv_' + crypto.randomBytes(12).toString('base64url');
1952
+ }
1953
+ &nbsp;
1954
+ /**
1955
+ * Start or resume a conversation
1956
+ */
1957
+ startConversation(options = {}) {
1958
+ const db = this._initDb();
1959
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return { success: false, error: this._dbError };</span>
1960
+ const {
1961
+ id = ConversationStore.generateConversationId(),
1962
+ contactId = null,
1963
+ contactName = null,
1964
+ tokenId = null,
1965
+ direction = 'inbound'
1966
+ } = options;
1967
+ &nbsp;
1968
+ const existing = db.prepare('SELECT * FROM conversations WHERE id = ?').get(id);
1969
+ if (existing) {
1970
+ // Resume existing conversation
1971
+ db.prepare(`
1972
+ UPDATE conversations
1973
+ SET status = 'active', last_message_at = ?
1974
+ WHERE id = ?
1975
+ `).run(new Date().toISOString(), id);
1976
+ return { id, resumed: true, conversation: existing };
1977
+ }
1978
+ &nbsp;
1979
+ // Create new conversation
1980
+ const now = new Date().toISOString();
1981
+ db.prepare(`
1982
+ INSERT INTO conversations (id, contact_id, contact_name, token_id, direction, started_at, last_message_at, status)
1983
+ VALUES (?, ?, ?, ?, ?, ?, ?, 'active')
1984
+ `).run(id, contactId, contactName, tokenId, direction, now, now);
1985
+ &nbsp;
1986
+ if (this.eventStore <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; this.eventStore.isAvailable <span class="branch-0 cbranch-no" title="branch not covered" ></span>&amp;&amp; this.eventStore.isAvailable())</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1987
+ <span class="cstat-no" title="statement not covered" > this.eventStore.emitEvent('call.updated', {</span>
1988
+ <span class="cstat-no" title="statement not covered" > conversation_id: id,</span>
1989
+ <span class="cstat-no" title="statement not covered" > status: 'active',</span>
1990
+ <span class="cstat-no" title="statement not covered" > direction,</span>
1991
+ <span class="cstat-no" title="statement not covered" > contact_id: contactId || null,</span>
1992
+ <span class="cstat-no" title="statement not covered" > contact_name: contactName || null</span>
1993
+ <span class="cstat-no" title="statement not covered" > }, {</span>
1994
+ <span class="cstat-no" title="statement not covered" > conversationId: id,</span>
1995
+ <span class="cstat-no" title="statement not covered" > contactId: contactId || null</span>
1996
+ <span class="cstat-no" title="statement not covered" > });</span>
1997
+ <span class="cstat-no" title="statement not covered" > }</span>
1998
+ &nbsp;
1999
+ return { id, resumed: false };
2000
+ }
2001
+ &nbsp;
2002
+ /**
2003
+ * Add a message to a conversation
2004
+ */
2005
+ addMessage(conversationId, message) {
2006
+ const db = this._initDb();
2007
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return { success: false, error: this._dbError };</span>
2008
+ const {
2009
+ direction,
2010
+ role,
2011
+ content,
2012
+ metadata = null
2013
+ } = message;
2014
+ &nbsp;
2015
+ const id = 'msg_' + crypto.randomBytes(8).toString('hex');
2016
+ const now = new Date().toISOString();
2017
+ &nbsp;
2018
+ db.prepare(`
2019
+ INSERT INTO messages (id, conversation_id, direction, role, content, timestamp, metadata)
2020
+ VALUES (?, ?, ?, ?, ?, ?, ?)
2021
+ `).run(id, conversationId, direction, role, content, now, metadata ? JSON.stringify(metadata) : null);
2022
+ &nbsp;
2023
+ // Update conversation
2024
+ db.prepare(`
2025
+ UPDATE conversations
2026
+ SET last_message_at = ?, message_count = message_count + 1
2027
+ WHERE id = ?
2028
+ `).run(now, conversationId);
2029
+ &nbsp;
2030
+ if (this.eventStore <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; this.eventStore.isAvailable <span class="branch-0 cbranch-no" title="branch not covered" ></span>&amp;&amp; this.eventStore.isAvailable())</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2031
+ <span class="cstat-no" title="statement not covered" > this.eventStore.emitEvent('call.updated', {</span>
2032
+ <span class="cstat-no" title="statement not covered" > conversation_id: conversationId,</span>
2033
+ <span class="cstat-no" title="statement not covered" > status: 'active',</span>
2034
+ <span class="cstat-no" title="statement not covered" > direction</span>
2035
+ <span class="cstat-no" title="statement not covered" > }, { conversationId });</span>
2036
+ <span class="cstat-no" title="statement not covered" > }</span>
2037
+ &nbsp;
2038
+ return { id, timestamp: now };
2039
+ }
2040
+ &nbsp;
2041
+ /**
2042
+ * Get conversation with messages
2043
+ */
2044
+ getConversation(conversationId, options = {}) {
2045
+ const db = this._initDb();
2046
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return null;</span>
2047
+ const { includeMessages = true, messageLimit = 50 } = options;
2048
+ &nbsp;
2049
+ const conversation = db.prepare('SELECT * FROM conversations WHERE id = ?').get(conversationId);
2050
+ if (!conversation) return null;
2051
+ &nbsp;
2052
+ if (includeMessages) {
2053
+ conversation.messages = db.prepare(`
2054
+ SELECT * FROM messages
2055
+ WHERE conversation_id = ?
2056
+ ORDER BY timestamp DESC
2057
+ LIMIT ?
2058
+ `).all(conversationId, messageLimit).reverse();
2059
+ }
2060
+ &nbsp;
2061
+ // Parse JSON fields
2062
+ if (conversation.owner_goals_touched) {
2063
+ conversation.owner_goals_touched = JSON.parse(conversation.owner_goals_touched);
2064
+ }
2065
+ if (conversation.owner_action_items) {
2066
+ conversation.owner_action_items = JSON.parse(conversation.owner_action_items);
2067
+ }
2068
+ &nbsp;
2069
+ return conversation;
2070
+ }
2071
+ &nbsp;
2072
+ /**
2073
+ * List conversations with optional filters
2074
+ */
2075
+ listConversations(options = {}) {
2076
+ const db = this._initDb();
2077
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return [];</span>
2078
+ const {
2079
+ contactId = null,
2080
+ status = null,
2081
+ limit = 20,
2082
+ includeMessages = false,
2083
+ messageLimit = 5
2084
+ } = options;
2085
+ &nbsp;
2086
+ let query = 'SELECT * FROM conversations WHERE 1=1';
2087
+ const params = [];
2088
+ &nbsp;
2089
+ if (contactId) {
2090
+ query += ' AND contact_id = ?';
2091
+ params.push(contactId);
2092
+ }
2093
+ if (status) {
2094
+ query += ' AND status = ?';
2095
+ params.push(status);
2096
+ }
2097
+ &nbsp;
2098
+ query += ' ORDER BY last_message_at DESC LIMIT ?';
2099
+ params.push(limit);
2100
+ &nbsp;
2101
+ const conversations = db.prepare(query).all(...params);
2102
+ &nbsp;
2103
+ if (includeMessages) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2104
+ <span class="cstat-no" title="statement not covered" > for (const conv of conversations) {</span>
2105
+ <span class="cstat-no" title="statement not covered" > conv.messages = db.prepare(`</span>
2106
+ <span class="cstat-no" title="statement not covered" > SELECT * FROM messages </span>
2107
+ <span class="cstat-no" title="statement not covered" > WHERE conversation_id = ? </span>
2108
+ <span class="cstat-no" title="statement not covered" > ORDER BY timestamp DESC </span>
2109
+ <span class="cstat-no" title="statement not covered" > LIMIT ?</span>
2110
+ <span class="cstat-no" title="statement not covered" > `).all(conv.id, messageLimit).reverse();</span>
2111
+ <span class="cstat-no" title="statement not covered" > }</span>
2112
+ <span class="cstat-no" title="statement not covered" > }</span>
2113
+ &nbsp;
2114
+ return conversations;
2115
+ }
2116
+ &nbsp;
2117
+ /**
2118
+ * Conclude a conversation and generate owner-context summary
2119
+ *
2120
+ * @param {string} conversationId
2121
+ * @param {object} options
2122
+ * @param {function} options.summarizer - async function(messages, ownerContext) =&gt; summary
2123
+ * @param {object} options.ownerContext - owner's goals, preferences, etc.
2124
+ */
2125
+ async concludeConversation(conversationId, options = {}) {
2126
+ const db = this._initDb();
2127
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return { success: false, error: this._dbError };</span>
2128
+ const { summarizer = null, ownerContext = {} } = options;
2129
+ &nbsp;
2130
+ const conversation = this.getConversation(conversationId, { includeMessages: true });
2131
+ if (!conversation) {
2132
+ return { success: false, error: 'conversation_not_found' };
2133
+ }
2134
+ &nbsp;
2135
+ const now = new Date().toISOString();
2136
+ let summary = null;
2137
+ let ownerSummary = null;
2138
+ &nbsp;
2139
+ // Generate summaries if summarizer provided
2140
+ if (summarizer &amp;&amp; conversation.messages.length &gt; 0) {
2141
+ try {
2142
+ const result = await summarizer(conversation.messages, ownerContext);
2143
+ summary = result.summary <span class="branch-0 cbranch-no" title="branch not covered" >|| null;</span>
2144
+ ownerSummary = result.ownerSummary || null;
2145
+ &nbsp;
2146
+ // Store owner-context fields (collaboration-focused)
2147
+ db.prepare(`
2148
+ UPDATE conversations SET
2149
+ ended_at = ?,
2150
+ status = 'concluded',
2151
+ summary = ?,
2152
+ summary_at = ?,
2153
+ owner_summary = ?,
2154
+ owner_relevance = ?,
2155
+ owner_goals_touched = ?,
2156
+ owner_action_items = ?,
2157
+ caller_action_items = ?,
2158
+ joint_action_items = ?,
2159
+ collaboration_opportunity = ?,
2160
+ owner_follow_up = ?,
2161
+ owner_notes = ?
2162
+ WHERE id = ?
2163
+ `).run(
2164
+ now,
2165
+ summary,
2166
+ now,
2167
+ result.ownerSummary || null,
2168
+ result.relevance || null,
2169
+ result.goalsTouched ? JSON.stringify(result.goalsTouched) : null,
2170
+ result.ownerActionItems ? JSON.stringify(result.ownerActionItems) : null,
2171
+ result.callerActionItems ? JSON.stringify(result.callerActionItems) : null,
2172
+ result.jointActionItems ? JSON.stringify(result.jointActionItems) : null,
2173
+ result.collaborationOpportunity ? JSON.stringify(result.collaborationOpportunity) : null,
2174
+ result.followUp || null,
2175
+ result.notes || null,
2176
+ conversationId
2177
+ );
2178
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
2179
+ <span class="cstat-no" title="statement not covered" > logger.error('Summary generation failed while concluding conversation', {</span>
2180
+ <span class="cstat-no" title="statement not covered" > event: 'conversation_summary_failed',</span>
2181
+ <span class="cstat-no" title="statement not covered" > conversation_id: conversationId,</span>
2182
+ <span class="cstat-no" title="statement not covered" > trace_id: ownerContext?.trace_id || ownerContext?.traceId || null,</span>
2183
+ <span class="cstat-no" title="statement not covered" > error: err,</span>
2184
+ <span class="cstat-no" title="statement not covered" > error_code: 'CONVERSATION_SUMMARY_FAILED',</span>
2185
+ <span class="cstat-no" title="statement not covered" > hint: 'Check summarizer runtime output and ensure it returns expected summary fields.',</span>
2186
+ <span class="cstat-no" title="statement not covered" > data: {</span>
2187
+ <span class="cstat-no" title="statement not covered" > message_count: conversation.messages.length</span>
2188
+ <span class="cstat-no" title="statement not covered" > }</span>
2189
+ <span class="cstat-no" title="statement not covered" > });</span>
2190
+ <span class="cstat-no" title="statement not covered" > // Still conclude, just without summary</span>
2191
+ <span class="cstat-no" title="statement not covered" > db.prepare(`</span>
2192
+ <span class="cstat-no" title="statement not covered" > UPDATE conversations SET ended_at = ?, status = 'concluded'</span>
2193
+ <span class="cstat-no" title="statement not covered" > WHERE id = ?</span>
2194
+ <span class="cstat-no" title="statement not covered" > `).run(now, conversationId);</span>
2195
+ <span class="cstat-no" title="statement not covered" > }</span>
2196
+ } else {
2197
+ // No summarizer, just mark concluded
2198
+ db.prepare(`
2199
+ UPDATE conversations SET ended_at = ?, status = 'concluded'
2200
+ WHERE id = ?
2201
+ `).run(now, conversationId);
2202
+ }
2203
+ &nbsp;
2204
+ if (this.eventStore <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; this.eventStore.isAvailable <span class="branch-0 cbranch-no" title="branch not covered" ></span>&amp;&amp; this.eventStore.isAvailable())</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2205
+ <span class="cstat-no" title="statement not covered" > this.eventStore.emitEvent('call.updated', {</span>
2206
+ <span class="cstat-no" title="statement not covered" > conversation_id: conversationId,</span>
2207
+ <span class="cstat-no" title="statement not covered" > status: 'concluded',</span>
2208
+ <span class="cstat-no" title="statement not covered" > contact_id: conversation.contact_id || null,</span>
2209
+ <span class="cstat-no" title="statement not covered" > contact_name: conversation.contact_name || null</span>
2210
+ <span class="cstat-no" title="statement not covered" > }, {</span>
2211
+ <span class="cstat-no" title="statement not covered" > conversationId,</span>
2212
+ <span class="cstat-no" title="statement not covered" > contactId: conversation.contact_id || null</span>
2213
+ <span class="cstat-no" title="statement not covered" > });</span>
2214
+ <span class="cstat-no" title="statement not covered" ></span>
2215
+ <span class="cstat-no" title="statement not covered" > if (summary || ownerSummary) {</span>
2216
+ <span class="cstat-no" title="statement not covered" > this.eventStore.emitEvent('summary.completed', {</span>
2217
+ <span class="cstat-no" title="statement not covered" > conversation_id: conversationId,</span>
2218
+ <span class="cstat-no" title="statement not covered" > contact_id: conversation.contact_id || null,</span>
2219
+ <span class="cstat-no" title="statement not covered" > contact_name: conversation.contact_name || null,</span>
2220
+ <span class="cstat-no" title="statement not covered" > has_summary: Boolean(summary),</span>
2221
+ <span class="cstat-no" title="statement not covered" > has_owner_summary: Boolean(ownerSummary)</span>
2222
+ <span class="cstat-no" title="statement not covered" > }, {</span>
2223
+ <span class="cstat-no" title="statement not covered" > conversationId,</span>
2224
+ <span class="cstat-no" title="statement not covered" > contactId: conversation.contact_id || null</span>
2225
+ <span class="cstat-no" title="statement not covered" > });</span>
2226
+ <span class="cstat-no" title="statement not covered" > }</span>
2227
+ <span class="cstat-no" title="statement not covered" > }</span>
2228
+ &nbsp;
2229
+ return {
2230
+ success: true,
2231
+ conversationId,
2232
+ summary,
2233
+ ownerSummary,
2234
+ endedAt: now
2235
+ };
2236
+ }
2237
+ &nbsp;
2238
+ /**
2239
+ * Mark conversation as timed out
2240
+ */
2241
+ timeoutConversation(conversationId) {
2242
+ const db = this._initDb();
2243
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return { success: false, error: this._dbError };</span>
2244
+ const now = new Date().toISOString();
2245
+
2246
+ db.prepare(`
2247
+ UPDATE conversations SET ended_at = ?, status = 'timeout'
2248
+ WHERE id = ?
2249
+ `).run(now, conversationId);
2250
+ &nbsp;
2251
+ if (this.eventStore <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; this.eventStore.isAvailable <span class="branch-0 cbranch-no" title="branch not covered" ></span>&amp;&amp; this.eventStore.isAvailable())</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2252
+ <span class="cstat-no" title="statement not covered" > this.eventStore.emitEvent('call.updated', {</span>
2253
+ <span class="cstat-no" title="statement not covered" > conversation_id: conversationId,</span>
2254
+ <span class="cstat-no" title="statement not covered" > status: 'timeout'</span>
2255
+ <span class="cstat-no" title="statement not covered" > }, { conversationId });</span>
2256
+ <span class="cstat-no" title="statement not covered" > }</span>
2257
+ &nbsp;
2258
+ return { success: true };
2259
+ }
2260
+ &nbsp;
2261
+ /**
2262
+ * Get active conversations (for timeout checking)
2263
+ */
2264
+ getActiveConversations(idleThresholdMs = 60000) {
2265
+ const db = this._initDb();
2266
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return [];</span>
2267
+ const threshold = new Date(Date.now() - idleThresholdMs).toISOString();
2268
+
2269
+ return db.prepare(`
2270
+ SELECT * FROM conversations
2271
+ WHERE status = 'active' AND last_message_at &lt; ?
2272
+ `).all(threshold);
2273
+ }
2274
+ &nbsp;
2275
+ /**
2276
+ * Compress old messages to save space
2277
+ */
2278
+ compressOldMessages(olderThanDays = 7) {
2279
+ const db = this._initDb();
2280
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return { compressed: 0, total: 0, error: this._dbError };</span>
2281
+ const zlib = require('zlib');
2282
+ const threshold = new Date(Date.now() - olderThanDays * 24 * 60 * 60 * 1000).toISOString();
2283
+ &nbsp;
2284
+ const messages = db.prepare(`
2285
+ SELECT id, content FROM messages
2286
+ WHERE timestamp &lt; ? AND compressed = 0
2287
+ `).all(threshold);
2288
+ &nbsp;
2289
+ let compressed = 0;
2290
+ const update = db.prepare('UPDATE messages SET content = ?, compressed = 1 WHERE id = ?');
2291
+ &nbsp;
2292
+ for (const msg of messages) {
2293
+ try {
2294
+ const compressedContent = zlib.gzipSync(msg.content).toString('base64');
2295
+ update.run(compressedContent, msg.id);
2296
+ compressed++;
2297
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (err) {</span>
2298
+ <span class="cstat-no" title="statement not covered" > // Skip if compression fails</span>
2299
+ <span class="cstat-no" title="statement not covered" > }</span>
2300
+ }
2301
+ &nbsp;
2302
+ return { compressed, total: messages.length };
2303
+ }
2304
+ &nbsp;
2305
+ /**
2306
+ * A2A-63: Prune old concluded/timeout conversations and their messages.
2307
+ *
2308
+ * Pipeline:
2309
+ * 1. Compress messages in the compress window (compress_after_days..conversations_days)
2310
+ * 2. Delete messages belonging to expired conversations
2311
+ * 3. Delete the expired conversations themselves
2312
+ * 4. VACUUM only when &gt;100 total rows deleted
2313
+ *
2314
+ * Active conversations are NEVER deleted regardless of age.
2315
+ *
2316
+ * @param {object} options
2317
+ * @param {number} [options.conversations_days=90] - Delete concluded/timeout conversations older than this
2318
+ * @param {number} [options.compress_after_days=7] - Compress messages older than this
2319
+ * @returns {{ compressed: number, deletedMessages: number, deletedConversations: number, vacuumed: boolean }}
2320
+ */
2321
+ pruneOld(options = {}) {
2322
+ const db = this._initDb();
2323
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2324
+ <span class="cstat-no" title="statement not covered" > return {</span>
2325
+ <span class="cstat-no" title="statement not covered" > compressed: 0,</span>
2326
+ <span class="cstat-no" title="statement not covered" > deletedMessages: 0,</span>
2327
+ <span class="cstat-no" title="statement not covered" > deletedConversations: 0,</span>
2328
+ <span class="cstat-no" title="statement not covered" > vacuumed: false,</span>
2329
+ <span class="cstat-no" title="statement not covered" > error: this._dbError</span>
2330
+ <span class="cstat-no" title="statement not covered" > };</span>
2331
+ <span class="cstat-no" title="statement not covered" > }</span>
2332
+ &nbsp;
2333
+ const conversationsDays = Number.isFinite(options.conversations_days)
2334
+ ? options.conversations_days
2335
+ : 90;
2336
+ const compressAfterDays = Number.isFinite(options.compress_after_days)
2337
+ ? options.compress_after_days
2338
+ : 7;
2339
+ &nbsp;
2340
+ // Step 1: Compress messages in the compress window before deletion
2341
+ const compressResult = this.compressOldMessages(compressAfterDays);
2342
+ &nbsp;
2343
+ // Step 2: Find expired conversations (concluded or timeout, older than retention threshold)
2344
+ // A2A-63: Only prune conversations with a non-NULL ended_at that is older than the threshold.
2345
+ // Active conversations have NULL ended_at and are never touched.
2346
+ const retentionThreshold = new Date(
2347
+ Date.now() - conversationsDays * 24 * 60 * 60 * 1000
2348
+ ).toISOString();
2349
+ &nbsp;
2350
+ const expiredConvIds = db.prepare(`
2351
+ SELECT id FROM conversations
2352
+ WHERE status IN ('concluded', 'timeout')
2353
+ AND ended_at IS NOT NULL
2354
+ AND ended_at &lt; ?
2355
+ `).all(retentionThreshold).map(row =&gt; row.id);
2356
+ &nbsp;
2357
+ let deletedMessages = 0;
2358
+ let deletedConversations = 0;
2359
+ &nbsp;
2360
+ if (expiredConvIds.length &gt; 0) {
2361
+ // A2A-63: Delete messages BEFORE their parent conversations (foreign key safety)
2362
+ const deleteMsgs = db.prepare(
2363
+ 'DELETE FROM messages WHERE conversation_id = ?'
2364
+ );
2365
+ const deleteConv = db.prepare(
2366
+ 'DELETE FROM conversations WHERE id = ?'
2367
+ );
2368
+ &nbsp;
2369
+ const pruneTransaction = db.transaction((ids) =&gt; {
2370
+ for (const id of ids) {
2371
+ const msgResult = deleteMsgs.run(id);
2372
+ deletedMessages += msgResult.changes;
2373
+ const convResult = deleteConv.run(id);
2374
+ deletedConversations += convResult.changes;
2375
+ }
2376
+ });
2377
+ &nbsp;
2378
+ pruneTransaction(expiredConvIds);
2379
+ }
2380
+ &nbsp;
2381
+ // Step 3: VACUUM only when &gt;100 total rows deleted
2382
+ const totalDeleted = deletedMessages + deletedConversations;
2383
+ let vacuumed = false;
2384
+ if (totalDeleted &gt; 100) {
2385
+ try {
2386
+ db.exec('VACUUM');
2387
+ vacuumed = true;
2388
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (_) {</span>
2389
+ <span class="cstat-no" title="statement not covered" > // A2A-63: Best effort — VACUUM can fail if another connection holds a lock</span>
2390
+ <span class="cstat-no" title="statement not covered" > }</span>
2391
+ }
2392
+ &nbsp;
2393
+ // Step 4: Log results
2394
+ cleanupLogger.info('Conversation retention prune completed', {
2395
+ event: 'conversations_pruned',
2396
+ data: {
2397
+ compressed: compressResult.compressed,
2398
+ deleted_messages: deletedMessages,
2399
+ deleted_conversations: deletedConversations,
2400
+ vacuumed,
2401
+ retention_days: conversationsDays,
2402
+ compress_after_days: compressAfterDays
2403
+ }
2404
+ });
2405
+ &nbsp;
2406
+ return {
2407
+ compressed: compressResult.compressed,
2408
+ deletedMessages,
2409
+ deletedConversations,
2410
+ vacuumed
2411
+ };
2412
+ }
2413
+ &nbsp;
2414
+ /**
2415
+ * A2A-63: Get database row counts for monitoring.
2416
+ *
2417
+ * @returns {{ conversations: number, messages: number }}
2418
+ */
2419
+ getDatabaseStats() {
2420
+ const db = this._initDb();
2421
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2422
+ <span class="cstat-no" title="statement not covered" > return { conversations: 0, messages: 0 };</span>
2423
+ <span class="cstat-no" title="statement not covered" > }</span>
2424
+ &nbsp;
2425
+ const convCount = db.prepare('SELECT COUNT(*) AS count FROM conversations').get();
2426
+ const msgCount = db.prepare('SELECT COUNT(*) AS count FROM messages').get();
2427
+ &nbsp;
2428
+ return {
2429
+ conversations: convCount ? convCount.count <span class="branch-0 cbranch-no" title="branch not covered" >: 0,</span>
2430
+ messages: msgCount ? msgCount.count <span class="branch-0 cbranch-no" title="branch not covered" >: 0</span>
2431
+ };
2432
+ }
2433
+ &nbsp;
2434
+ /**
2435
+ * Get conversation context for retrieval (summary + recent messages)
2436
+ */
2437
+ getConversationContext(conversationId, recentMessageCount = 5) {
2438
+ const conversation = this.getConversation(conversationId, {
2439
+ includeMessages: true,
2440
+ messageLimit: recentMessageCount
2441
+ });
2442
+ &nbsp;
2443
+ if (!conversation) return null;
2444
+ &nbsp;
2445
+ // Parse JSON fields
2446
+ const parseJson = (str) =&gt; {
2447
+ if (!str) return null;
2448
+ try { return JSON.parse(str); } catch (e) { return null; }
2449
+ };
2450
+ &nbsp;
2451
+ return {
2452
+ id: conversation.id,
2453
+ contact: conversation.contact_name,
2454
+ summary: conversation.summary,
2455
+ ownerContext: conversation.owner_summary ? {
2456
+ summary: conversation.owner_summary,
2457
+ relevance: conversation.owner_relevance,
2458
+ goalsTouched: parseJson(conversation.owner_goals_touched),
2459
+ ownerActionItems: parseJson(conversation.owner_action_items),
2460
+ callerActionItems: parseJson(conversation.caller_action_items),
2461
+ jointActionItems: parseJson(conversation.joint_action_items),
2462
+ collaborationOpportunity: parseJson(conversation.collaboration_opportunity),
2463
+ followUp: conversation.owner_follow_up,
2464
+ notes: conversation.owner_notes
2465
+ } : null,
2466
+ recentMessages: conversation.messages,
2467
+ messageCount: conversation.message_count,
2468
+ startedAt: conversation.started_at,
2469
+ endedAt: conversation.ended_at,
2470
+ status: conversation.status
2471
+ };
2472
+ }
2473
+ &nbsp;
2474
+ /**
2475
+ * Save live collaboration state for a conversation
2476
+ */
2477
+ saveCollabState(conversationId, collabState) {
2478
+ const db = this._initDb();
2479
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return { success: false, error: this._dbError };</span>
2480
+ if (!collabState || typeof collabState !== 'object') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
2481
+ <span class="cstat-no" title="statement not covered" > return { success: false, error: 'invalid_state' };</span>
2482
+ <span class="cstat-no" title="statement not covered" > }</span>
2483
+ &nbsp;
2484
+ const now = new Date().toISOString();
2485
+ db.prepare(`
2486
+ UPDATE conversations SET
2487
+ collab_phase = ?,
2488
+ collab_turn_count = ?,
2489
+ collab_overlap_score = ?,
2490
+ collab_active_threads = ?,
2491
+ collab_candidate_collaborations = ?,
2492
+ collab_open_questions = ?,
2493
+ collab_close_signal = ?,
2494
+ collab_confidence = ?,
2495
+ collab_updated_at = ?
2496
+ WHERE id = ?
2497
+ `).run(
2498
+ collabState.phase <span class="branch-0 cbranch-no" title="branch not covered" >|| 'handshake',</span>
2499
+ collabState.turnCount <span class="branch-0 cbranch-no" title="branch not covered" >|| 0,</span>
2500
+ collabState.overlapScore != null ? collabState.overlapScore <span class="branch-0 cbranch-no" title="branch not covered" >: 0.15,</span>
2501
+ collabState.activeThreads ? JSON.stringify(collabState.activeThreads) : null,
2502
+ collabState.candidateCollaborations ? JSON.stringify(collabState.candidateCollaborations) : null,
2503
+ collabState.openQuestions ? JSON.stringify(collabState.openQuestions) : null,
2504
+ collabState.closeSignal ? 1 : 0,
2505
+ collabState.confidence != null ? collabState.confidence <span class="branch-0 cbranch-no" title="branch not covered" >: 0.25,</span>
2506
+ now,
2507
+ conversationId
2508
+ );
2509
+ &nbsp;
2510
+ return { success: true };
2511
+ }
2512
+ &nbsp;
2513
+ /**
2514
+ * Load live collaboration state for a conversation
2515
+ */
2516
+ loadCollabState(conversationId) {
2517
+ const db = this._initDb();
2518
+ if (!db) <span class="branch-0 cbranch-no" title="branch not covered" >return null;</span>
2519
+ &nbsp;
2520
+ const row = db.prepare(
2521
+ 'SELECT collab_phase, collab_turn_count, collab_overlap_score, collab_active_threads, collab_candidate_collaborations, collab_open_questions, collab_close_signal, collab_confidence, collab_updated_at FROM conversations WHERE id = ?'
2522
+ ).get(conversationId);
2523
+ &nbsp;
2524
+ if (!row || row.collab_phase == null) return null;
2525
+ &nbsp;
2526
+ const parseJson = (str) =&gt; {
2527
+ if (!str) return [];
2528
+ try { return JSON.parse(str); } <span class="branch-0 cbranch-no" title="branch not covered" >catch { return []; }</span>
2529
+ };
2530
+ &nbsp;
2531
+ return {
2532
+ phase: row.collab_phase,
2533
+ turnCount: row.collab_turn_count <span class="branch-0 cbranch-no" title="branch not covered" >|| 0,</span>
2534
+ overlapScore: row.collab_overlap_score != null ? row.collab_overlap_score <span class="branch-0 cbranch-no" title="branch not covered" >: 0.15,</span>
2535
+ activeThreads: parseJson(row.collab_active_threads),
2536
+ candidateCollaborations: parseJson(row.collab_candidate_collaborations),
2537
+ openQuestions: parseJson(row.collab_open_questions),
2538
+ closeSignal: Boolean(row.collab_close_signal),
2539
+ confidence: row.collab_confidence != null ? row.collab_confidence <span class="branch-0 cbranch-no" title="branch not covered" >: 0.25,</span>
2540
+ updatedAt: row.collab_updated_at
2541
+ };
2542
+ }
2543
+ &nbsp;
2544
+ /**
2545
+ * Close database connection
2546
+ */
2547
+ close() {
2548
+ if (this.db) {
2549
+ this.db.close();
2550
+ this.db = null;
2551
+ }
2552
+ }
2553
+ }
2554
+ &nbsp;
2555
+ module.exports = { ConversationStore };
2556
+ &nbsp;</pre></td></tr></table></pre>
2557
+
2558
+ <div class='push'></div><!-- for sticky footer -->
2559
+ </div><!-- /wrapper -->
2560
+ <div class='footer quiet pad2 space-top1 center small'>
2561
+ Code coverage generated by
2562
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
2563
+ at 2026-03-03T22:25:10.857Z
2564
+ </div>
2565
+ <script src="../../prettify.js"></script>
2566
+ <script>
2567
+ window.onload = function () {
2568
+ prettyPrint();
2569
+ };
2570
+ </script>
2571
+ <script src="../../sorter.js"></script>
2572
+ <script src="../../block-navigation.js"></script>
2573
+ </body>
2574
+ </html>
2575
+