context.dev 1.36.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/README.md +16 -9
  4. data/lib/context_dev/client.rb +7 -0
  5. data/lib/context_dev/models/brand_retrieve_params.rb +1079 -174
  6. data/lib/context_dev/models/monitor_create_params.rb +364 -0
  7. data/lib/context_dev/models/monitor_create_response.rb +608 -0
  8. data/lib/context_dev/models/monitor_delete_params.rb +20 -0
  9. data/lib/context_dev/models/monitor_delete_response.rb +22 -0
  10. data/lib/context_dev/models/monitor_list_account_changes_params.rb +93 -0
  11. data/lib/context_dev/models/monitor_list_account_changes_response.rb +199 -0
  12. data/lib/context_dev/models/monitor_list_account_runs_params.rb +55 -0
  13. data/lib/context_dev/models/monitor_list_account_runs_response.rb +227 -0
  14. data/lib/context_dev/models/monitor_list_changes_params.rb +57 -0
  15. data/lib/context_dev/models/monitor_list_changes_response.rb +198 -0
  16. data/lib/context_dev/models/monitor_list_params.rb +161 -0
  17. data/lib/context_dev/models/monitor_list_response.rb +631 -0
  18. data/lib/context_dev/models/monitor_list_runs_params.rb +62 -0
  19. data/lib/context_dev/models/monitor_list_runs_response.rb +227 -0
  20. data/lib/context_dev/models/monitor_retrieve_change_params.rb +20 -0
  21. data/lib/context_dev/models/monitor_retrieve_change_response.rb +264 -0
  22. data/lib/context_dev/models/monitor_retrieve_params.rb +20 -0
  23. data/lib/context_dev/models/monitor_retrieve_response.rb +608 -0
  24. data/lib/context_dev/models/monitor_run_params.rb +20 -0
  25. data/lib/context_dev/models/monitor_run_response.rb +35 -0
  26. data/lib/context_dev/models/monitor_update_params.rb +371 -0
  27. data/lib/context_dev/models/monitor_update_response.rb +608 -0
  28. data/lib/context_dev/models/utility_prefetch_params.rb +70 -6
  29. data/lib/context_dev/models/utility_prefetch_response.rb +23 -1
  30. data/lib/context_dev/models/web_extract_response.rb +17 -1
  31. data/lib/context_dev/models/web_web_crawl_md_params.rb +11 -1
  32. data/lib/context_dev/models/web_web_scrape_html_params.rb +11 -1
  33. data/lib/context_dev/models/web_web_scrape_html_response.rb +10 -2
  34. data/lib/context_dev/models/web_web_scrape_images_params.rb +12 -1
  35. data/lib/context_dev/models/web_web_scrape_md_params.rb +11 -1
  36. data/lib/context_dev/models.rb +20 -12
  37. data/lib/context_dev/resources/ai.rb +0 -33
  38. data/lib/context_dev/resources/brand.rb +9 -204
  39. data/lib/context_dev/resources/monitors.rb +352 -0
  40. data/lib/context_dev/resources/utility.rb +9 -35
  41. data/lib/context_dev/resources/web.rb +14 -4
  42. data/lib/context_dev/version.rb +1 -1
  43. data/lib/context_dev.rb +23 -14
  44. data/rbi/context_dev/client.rbi +6 -0
  45. data/rbi/context_dev/models/brand_retrieve_params.rbi +3858 -678
  46. data/rbi/context_dev/models/monitor_create_params.rbi +641 -0
  47. data/rbi/context_dev/models/monitor_create_response.rbi +1020 -0
  48. data/rbi/context_dev/models/monitor_delete_params.rbi +35 -0
  49. data/rbi/context_dev/models/monitor_delete_response.rbi +29 -0
  50. data/rbi/context_dev/models/monitor_list_account_changes_params.rbi +211 -0
  51. data/rbi/context_dev/models/monitor_list_account_changes_response.rbi +376 -0
  52. data/rbi/context_dev/models/monitor_list_account_runs_params.rbi +125 -0
  53. data/rbi/context_dev/models/monitor_list_account_runs_response.rbi +464 -0
  54. data/rbi/context_dev/models/monitor_list_changes_params.rbi +91 -0
  55. data/rbi/context_dev/models/monitor_list_changes_response.rbi +372 -0
  56. data/rbi/context_dev/models/monitor_list_params.rbi +335 -0
  57. data/rbi/context_dev/models/monitor_list_response.rbi +1089 -0
  58. data/rbi/context_dev/models/monitor_list_runs_params.rbi +125 -0
  59. data/rbi/context_dev/models/monitor_list_runs_response.rbi +455 -0
  60. data/rbi/context_dev/models/monitor_retrieve_change_params.rbi +38 -0
  61. data/rbi/context_dev/models/monitor_retrieve_change_response.rbi +469 -0
  62. data/rbi/context_dev/models/monitor_retrieve_params.rbi +38 -0
  63. data/rbi/context_dev/models/monitor_retrieve_response.rbi +1028 -0
  64. data/rbi/context_dev/models/monitor_run_params.rbi +35 -0
  65. data/rbi/context_dev/models/monitor_run_response.rbi +48 -0
  66. data/rbi/context_dev/models/monitor_update_params.rbi +681 -0
  67. data/rbi/context_dev/models/monitor_update_response.rbi +1020 -0
  68. data/rbi/context_dev/models/utility_prefetch_params.rbi +129 -7
  69. data/rbi/context_dev/models/utility_prefetch_response.rbi +55 -3
  70. data/rbi/context_dev/models/web_extract_response.rbi +10 -0
  71. data/rbi/context_dev/models/web_web_crawl_md_params.rbi +15 -0
  72. data/rbi/context_dev/models/web_web_scrape_html_params.rbi +15 -0
  73. data/rbi/context_dev/models/web_web_scrape_html_response.rbi +29 -3
  74. data/rbi/context_dev/models/web_web_scrape_images_params.rbi +17 -0
  75. data/rbi/context_dev/models/web_web_scrape_md_params.rbi +15 -0
  76. data/rbi/context_dev/models.rbi +23 -15
  77. data/rbi/context_dev/resources/ai.rbi +0 -28
  78. data/rbi/context_dev/resources/brand.rbi +16 -228
  79. data/rbi/context_dev/resources/monitors.rbi +286 -0
  80. data/rbi/context_dev/resources/utility.rbi +14 -29
  81. data/rbi/context_dev/resources/web.rbi +21 -0
  82. data/sig/context_dev/client.rbs +2 -0
  83. data/sig/context_dev/models/brand_retrieve_params.rbs +1586 -281
  84. data/sig/context_dev/models/monitor_create_params.rbs +301 -0
  85. data/sig/context_dev/models/monitor_create_response.rbs +433 -0
  86. data/sig/context_dev/models/monitor_delete_params.rbs +23 -0
  87. data/sig/context_dev/models/monitor_delete_response.rbs +15 -0
  88. data/sig/context_dev/models/monitor_list_account_changes_params.rbs +104 -0
  89. data/sig/context_dev/models/monitor_list_account_changes_response.rbs +176 -0
  90. data/sig/context_dev/models/monitor_list_account_runs_params.rbs +58 -0
  91. data/sig/context_dev/models/monitor_list_account_runs_response.rbs +184 -0
  92. data/sig/context_dev/models/monitor_list_changes_params.rbs +61 -0
  93. data/sig/context_dev/models/monitor_list_changes_response.rbs +176 -0
  94. data/sig/context_dev/models/monitor_list_params.rbs +160 -0
  95. data/sig/context_dev/models/monitor_list_response.rbs +460 -0
  96. data/sig/context_dev/models/monitor_list_runs_params.rbs +63 -0
  97. data/sig/context_dev/models/monitor_list_runs_response.rbs +184 -0
  98. data/sig/context_dev/models/monitor_retrieve_change_params.rbs +23 -0
  99. data/sig/context_dev/models/monitor_retrieve_change_response.rbs +221 -0
  100. data/sig/context_dev/models/monitor_retrieve_params.rbs +23 -0
  101. data/sig/context_dev/models/monitor_retrieve_response.rbs +433 -0
  102. data/sig/context_dev/models/monitor_run_params.rbs +23 -0
  103. data/sig/context_dev/models/monitor_run_response.rbs +18 -0
  104. data/sig/context_dev/models/monitor_update_params.rbs +321 -0
  105. data/sig/context_dev/models/monitor_update_response.rbs +433 -0
  106. data/sig/context_dev/models/utility_prefetch_params.rbs +52 -4
  107. data/sig/context_dev/models/utility_prefetch_response.rbs +22 -3
  108. data/sig/context_dev/models/web_extract_response.rbs +5 -0
  109. data/sig/context_dev/models/web_web_crawl_md_params.rbs +7 -0
  110. data/sig/context_dev/models/web_web_scrape_html_params.rbs +7 -0
  111. data/sig/context_dev/models/web_web_scrape_html_response.rbs +8 -0
  112. data/sig/context_dev/models/web_web_scrape_images_params.rbs +7 -0
  113. data/sig/context_dev/models/web_web_scrape_md_params.rbs +7 -0
  114. data/sig/context_dev/models.rbs +20 -12
  115. data/sig/context_dev/resources/ai.rbs +0 -8
  116. data/sig/context_dev/resources/brand.rbs +1 -56
  117. data/sig/context_dev/resources/monitors.rbs +101 -0
  118. data/sig/context_dev/resources/utility.rbs +2 -7
  119. data/sig/context_dev/resources/web.rbs +4 -0
  120. metadata +71 -44
  121. data/lib/context_dev/models/ai_ai_query_params.rb +0 -235
  122. data/lib/context_dev/models/ai_ai_query_response.rb +0 -133
  123. data/lib/context_dev/models/brand_identify_from_transaction_params.rb +0 -474
  124. data/lib/context_dev/models/brand_identify_from_transaction_response.rb +0 -1074
  125. data/lib/context_dev/models/brand_retrieve_by_email_params.rb +0 -195
  126. data/lib/context_dev/models/brand_retrieve_by_email_response.rb +0 -1071
  127. data/lib/context_dev/models/brand_retrieve_by_isin_params.rb +0 -195
  128. data/lib/context_dev/models/brand_retrieve_by_isin_response.rb +0 -1070
  129. data/lib/context_dev/models/brand_retrieve_by_name_params.rb +0 -452
  130. data/lib/context_dev/models/brand_retrieve_by_name_response.rb +0 -1070
  131. data/lib/context_dev/models/brand_retrieve_by_ticker_params.rb +0 -283
  132. data/lib/context_dev/models/brand_retrieve_by_ticker_response.rb +0 -1072
  133. data/lib/context_dev/models/utility_prefetch_by_email_params.rb +0 -37
  134. data/lib/context_dev/models/utility_prefetch_by_email_response.rb +0 -68
  135. data/rbi/context_dev/models/ai_ai_query_params.rbi +0 -504
  136. data/rbi/context_dev/models/ai_ai_query_response.rbi +0 -267
  137. data/rbi/context_dev/models/brand_identify_from_transaction_params.rbi +0 -2020
  138. data/rbi/context_dev/models/brand_identify_from_transaction_response.rbi +0 -3515
  139. data/rbi/context_dev/models/brand_retrieve_by_email_params.rbi +0 -743
  140. data/rbi/context_dev/models/brand_retrieve_by_email_response.rbi +0 -3511
  141. data/rbi/context_dev/models/brand_retrieve_by_isin_params.rbi +0 -743
  142. data/rbi/context_dev/models/brand_retrieve_by_isin_response.rbi +0 -3510
  143. data/rbi/context_dev/models/brand_retrieve_by_name_params.rbi +0 -1982
  144. data/rbi/context_dev/models/brand_retrieve_by_name_response.rbi +0 -3510
  145. data/rbi/context_dev/models/brand_retrieve_by_ticker_params.rbi +0 -1153
  146. data/rbi/context_dev/models/brand_retrieve_by_ticker_response.rbi +0 -3512
  147. data/rbi/context_dev/models/utility_prefetch_by_email_params.rbi +0 -65
  148. data/rbi/context_dev/models/utility_prefetch_by_email_response.rbi +0 -132
  149. data/sig/context_dev/models/ai_ai_query_params.rbs +0 -218
  150. data/sig/context_dev/models/ai_ai_query_response.rbs +0 -121
  151. data/sig/context_dev/models/brand_identify_from_transaction_params.rbs +0 -822
  152. data/sig/context_dev/models/brand_identify_from_transaction_response.rbs +0 -1441
  153. data/sig/context_dev/models/brand_retrieve_by_email_params.rbs +0 -305
  154. data/sig/context_dev/models/brand_retrieve_by_email_response.rbs +0 -1441
  155. data/sig/context_dev/models/brand_retrieve_by_isin_params.rbs +0 -305
  156. data/sig/context_dev/models/brand_retrieve_by_isin_response.rbs +0 -1441
  157. data/sig/context_dev/models/brand_retrieve_by_name_params.rbs +0 -801
  158. data/sig/context_dev/models/brand_retrieve_by_name_response.rbs +0 -1441
  159. data/sig/context_dev/models/brand_retrieve_by_ticker_params.rbs +0 -467
  160. data/sig/context_dev/models/brand_retrieve_by_ticker_response.rbs +0 -1441
  161. data/sig/context_dev/models/utility_prefetch_by_email_params.rbs +0 -30
  162. data/sig/context_dev/models/utility_prefetch_by_email_response.rbs +0 -64
@@ -0,0 +1,1020 @@
1
+ # typed: strong
2
+
3
+ module ContextDev
4
+ module Models
5
+ class MonitorCreateResponse < ContextDev::Internal::Type::BaseModel
6
+ OrHash =
7
+ T.type_alias do
8
+ T.any(
9
+ ContextDev::Models::MonitorCreateResponse,
10
+ ContextDev::Internal::AnyHash
11
+ )
12
+ end
13
+
14
+ sig { returns(String) }
15
+ attr_accessor :id
16
+
17
+ # Discriminated union describing how changes are detected.
18
+ sig do
19
+ returns(
20
+ ContextDev::Models::MonitorCreateResponse::ChangeDetection::Variants
21
+ )
22
+ end
23
+ attr_accessor :change_detection
24
+
25
+ sig { returns(Time) }
26
+ attr_accessor :created_at
27
+
28
+ # Top-level monitor category. Always `web` today; the concrete behavior is
29
+ # described by `target` and `change_detection`.
30
+ sig do
31
+ returns(ContextDev::Models::MonitorCreateResponse::Mode::TaggedSymbol)
32
+ end
33
+ attr_accessor :mode
34
+
35
+ sig { returns(String) }
36
+ attr_accessor :name
37
+
38
+ # Run the monitor on a fixed interval defined by a frequency and a unit, e.g.
39
+ # every 6 hours or every 2 days. The total interval (frequency × unit) must be
40
+ # between 10 minutes and 1 year.
41
+ sig { returns(ContextDev::Models::MonitorCreateResponse::Schedule) }
42
+ attr_reader :schedule
43
+
44
+ sig do
45
+ params(
46
+ schedule: ContextDev::Models::MonitorCreateResponse::Schedule::OrHash
47
+ ).void
48
+ end
49
+ attr_writer :schedule
50
+
51
+ # Monitor lifecycle status. `failed` means the most recent run failed (see the
52
+ # monitor's `last_error`); failed monitors keep running on schedule and flip back
53
+ # to `active` on the next successful run. Monitors are auto-`paused` after
54
+ # repeated consecutive failures or insufficient-credit skips; resume by PATCHing
55
+ # status to `active`.
56
+ sig do
57
+ returns(ContextDev::Models::MonitorCreateResponse::Status::TaggedSymbol)
58
+ end
59
+ attr_accessor :status
60
+
61
+ # Discriminated union describing what the monitor watches.
62
+ sig do
63
+ returns(ContextDev::Models::MonitorCreateResponse::Target::Variants)
64
+ end
65
+ attr_accessor :target
66
+
67
+ sig { returns(Time) }
68
+ attr_accessor :updated_at
69
+
70
+ # Current baseline: the last observed value the monitor compares new snapshots
71
+ # against. Its shape follows `target.type` (page/sitemap/extract). Only populated
72
+ # on GET /monitors/{monitor_id}; null until the first baseline run completes (and
73
+ # after a target or change_detection update, which resets the baseline).
74
+ sig do
75
+ returns(
76
+ T.nilable(
77
+ ContextDev::Models::MonitorCreateResponse::Baseline::Variants
78
+ )
79
+ )
80
+ end
81
+ attr_accessor :baseline
82
+
83
+ sig { returns(T.nilable(Time)) }
84
+ attr_accessor :last_change_at
85
+
86
+ # Error from the most recent failed run; null when the last run succeeded.
87
+ sig do
88
+ returns(T.nilable(ContextDev::Models::MonitorCreateResponse::LastError))
89
+ end
90
+ attr_reader :last_error
91
+
92
+ sig do
93
+ params(
94
+ last_error:
95
+ T.nilable(
96
+ ContextDev::Models::MonitorCreateResponse::LastError::OrHash
97
+ )
98
+ ).void
99
+ end
100
+ attr_writer :last_error
101
+
102
+ sig { returns(T.nilable(Time)) }
103
+ attr_accessor :last_run_at
104
+
105
+ # When the next scheduled run is due.
106
+ sig { returns(T.nilable(Time)) }
107
+ attr_accessor :next_run_at
108
+
109
+ # User-defined tags for grouping and filtering monitors and their changes.
110
+ sig { returns(T.nilable(T::Array[String])) }
111
+ attr_reader :tags
112
+
113
+ sig { params(tags: T::Array[String]).void }
114
+ attr_writer :tags
115
+
116
+ sig do
117
+ returns(T.nilable(ContextDev::Models::MonitorCreateResponse::Webhook))
118
+ end
119
+ attr_reader :webhook
120
+
121
+ sig do
122
+ params(
123
+ webhook:
124
+ T.nilable(
125
+ ContextDev::Models::MonitorCreateResponse::Webhook::OrHash
126
+ )
127
+ ).void
128
+ end
129
+ attr_writer :webhook
130
+
131
+ # A web monitor. `mode` is the constant `web`; behavior is described by `target`
132
+ # (page/sitemap/extract) and `change_detection` (exact/semantic).
133
+ sig do
134
+ params(
135
+ id: String,
136
+ change_detection:
137
+ T.any(
138
+ ContextDev::Models::MonitorCreateResponse::ChangeDetection::Exact::OrHash,
139
+ ContextDev::Models::MonitorCreateResponse::ChangeDetection::Semantic::OrHash
140
+ ),
141
+ created_at: Time,
142
+ mode: ContextDev::Models::MonitorCreateResponse::Mode::OrSymbol,
143
+ name: String,
144
+ schedule: ContextDev::Models::MonitorCreateResponse::Schedule::OrHash,
145
+ status: ContextDev::Models::MonitorCreateResponse::Status::OrSymbol,
146
+ target:
147
+ T.any(
148
+ ContextDev::Models::MonitorCreateResponse::Target::Page::OrHash,
149
+ ContextDev::Models::MonitorCreateResponse::Target::Sitemap::OrHash,
150
+ ContextDev::Models::MonitorCreateResponse::Target::Extract::OrHash
151
+ ),
152
+ updated_at: Time,
153
+ baseline:
154
+ T.nilable(
155
+ T.any(
156
+ ContextDev::Models::MonitorCreateResponse::Baseline::MonitorsPageBaseline::OrHash,
157
+ ContextDev::Models::MonitorCreateResponse::Baseline::MonitorsSitemapBaseline::OrHash,
158
+ ContextDev::Models::MonitorCreateResponse::Baseline::MonitorsExtractBaseline::OrHash
159
+ )
160
+ ),
161
+ last_change_at: T.nilable(Time),
162
+ last_error:
163
+ T.nilable(
164
+ ContextDev::Models::MonitorCreateResponse::LastError::OrHash
165
+ ),
166
+ last_run_at: T.nilable(Time),
167
+ next_run_at: T.nilable(Time),
168
+ tags: T::Array[String],
169
+ webhook:
170
+ T.nilable(
171
+ ContextDev::Models::MonitorCreateResponse::Webhook::OrHash
172
+ )
173
+ ).returns(T.attached_class)
174
+ end
175
+ def self.new(
176
+ id:,
177
+ # Discriminated union describing how changes are detected.
178
+ change_detection:,
179
+ created_at:,
180
+ # Top-level monitor category. Always `web` today; the concrete behavior is
181
+ # described by `target` and `change_detection`.
182
+ mode:,
183
+ name:,
184
+ # Run the monitor on a fixed interval defined by a frequency and a unit, e.g.
185
+ # every 6 hours or every 2 days. The total interval (frequency × unit) must be
186
+ # between 10 minutes and 1 year.
187
+ schedule:,
188
+ # Monitor lifecycle status. `failed` means the most recent run failed (see the
189
+ # monitor's `last_error`); failed monitors keep running on schedule and flip back
190
+ # to `active` on the next successful run. Monitors are auto-`paused` after
191
+ # repeated consecutive failures or insufficient-credit skips; resume by PATCHing
192
+ # status to `active`.
193
+ status:,
194
+ # Discriminated union describing what the monitor watches.
195
+ target:,
196
+ updated_at:,
197
+ # Current baseline: the last observed value the monitor compares new snapshots
198
+ # against. Its shape follows `target.type` (page/sitemap/extract). Only populated
199
+ # on GET /monitors/{monitor_id}; null until the first baseline run completes (and
200
+ # after a target or change_detection update, which resets the baseline).
201
+ baseline: nil,
202
+ last_change_at: nil,
203
+ # Error from the most recent failed run; null when the last run succeeded.
204
+ last_error: nil,
205
+ last_run_at: nil,
206
+ # When the next scheduled run is due.
207
+ next_run_at: nil,
208
+ # User-defined tags for grouping and filtering monitors and their changes.
209
+ tags: nil,
210
+ webhook: nil
211
+ )
212
+ end
213
+
214
+ sig do
215
+ override.returns(
216
+ {
217
+ id: String,
218
+ change_detection:
219
+ ContextDev::Models::MonitorCreateResponse::ChangeDetection::Variants,
220
+ created_at: Time,
221
+ mode: ContextDev::Models::MonitorCreateResponse::Mode::TaggedSymbol,
222
+ name: String,
223
+ schedule: ContextDev::Models::MonitorCreateResponse::Schedule,
224
+ status:
225
+ ContextDev::Models::MonitorCreateResponse::Status::TaggedSymbol,
226
+ target: ContextDev::Models::MonitorCreateResponse::Target::Variants,
227
+ updated_at: Time,
228
+ baseline:
229
+ T.nilable(
230
+ ContextDev::Models::MonitorCreateResponse::Baseline::Variants
231
+ ),
232
+ last_change_at: T.nilable(Time),
233
+ last_error:
234
+ T.nilable(ContextDev::Models::MonitorCreateResponse::LastError),
235
+ last_run_at: T.nilable(Time),
236
+ next_run_at: T.nilable(Time),
237
+ tags: T::Array[String],
238
+ webhook:
239
+ T.nilable(ContextDev::Models::MonitorCreateResponse::Webhook)
240
+ }
241
+ )
242
+ end
243
+ def to_hash
244
+ end
245
+
246
+ # Discriminated union describing how changes are detected.
247
+ module ChangeDetection
248
+ extend ContextDev::Internal::Type::Union
249
+
250
+ Variants =
251
+ T.type_alias do
252
+ T.any(
253
+ ContextDev::Models::MonitorCreateResponse::ChangeDetection::Exact,
254
+ ContextDev::Models::MonitorCreateResponse::ChangeDetection::Semantic
255
+ )
256
+ end
257
+
258
+ class Exact < ContextDev::Internal::Type::BaseModel
259
+ OrHash =
260
+ T.type_alias do
261
+ T.any(
262
+ ContextDev::Models::MonitorCreateResponse::ChangeDetection::Exact,
263
+ ContextDev::Internal::AnyHash
264
+ )
265
+ end
266
+
267
+ sig { returns(Symbol) }
268
+ attr_accessor :type
269
+
270
+ # Detect exact changes. For page targets, this means visible text diffs. For
271
+ # sitemap targets, this means URL additions and removals.
272
+ sig { params(type: Symbol).returns(T.attached_class) }
273
+ def self.new(type: :exact)
274
+ end
275
+
276
+ sig { override.returns({ type: Symbol }) }
277
+ def to_hash
278
+ end
279
+ end
280
+
281
+ class Semantic < ContextDev::Internal::Type::BaseModel
282
+ OrHash =
283
+ T.type_alias do
284
+ T.any(
285
+ ContextDev::Models::MonitorCreateResponse::ChangeDetection::Semantic,
286
+ ContextDev::Internal::AnyHash
287
+ )
288
+ end
289
+
290
+ sig { returns(Symbol) }
291
+ attr_accessor :type
292
+
293
+ sig { returns(T.nilable(Float)) }
294
+ attr_reader :confidence_threshold
295
+
296
+ sig { params(confidence_threshold: Float).void }
297
+ attr_writer :confidence_threshold
298
+
299
+ # Detect meaning-level changes to the extracted data, ignoring cosmetic or
300
+ # paraphrase-only differences. What is watched is determined by the extract
301
+ # target's `schema` and `instructions`.
302
+ sig do
303
+ params(confidence_threshold: Float, type: Symbol).returns(
304
+ T.attached_class
305
+ )
306
+ end
307
+ def self.new(confidence_threshold: nil, type: :semantic)
308
+ end
309
+
310
+ sig do
311
+ override.returns({ type: Symbol, confidence_threshold: Float })
312
+ end
313
+ def to_hash
314
+ end
315
+ end
316
+
317
+ sig do
318
+ override.returns(
319
+ T::Array[
320
+ ContextDev::Models::MonitorCreateResponse::ChangeDetection::Variants
321
+ ]
322
+ )
323
+ end
324
+ def self.variants
325
+ end
326
+ end
327
+
328
+ # Top-level monitor category. Always `web` today; the concrete behavior is
329
+ # described by `target` and `change_detection`.
330
+ module Mode
331
+ extend ContextDev::Internal::Type::Enum
332
+
333
+ TaggedSymbol =
334
+ T.type_alias do
335
+ T.all(Symbol, ContextDev::Models::MonitorCreateResponse::Mode)
336
+ end
337
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
338
+
339
+ WEB =
340
+ T.let(
341
+ :web,
342
+ ContextDev::Models::MonitorCreateResponse::Mode::TaggedSymbol
343
+ )
344
+
345
+ sig do
346
+ override.returns(
347
+ T::Array[
348
+ ContextDev::Models::MonitorCreateResponse::Mode::TaggedSymbol
349
+ ]
350
+ )
351
+ end
352
+ def self.values
353
+ end
354
+ end
355
+
356
+ class Schedule < ContextDev::Internal::Type::BaseModel
357
+ OrHash =
358
+ T.type_alias do
359
+ T.any(
360
+ ContextDev::Models::MonitorCreateResponse::Schedule,
361
+ ContextDev::Internal::AnyHash
362
+ )
363
+ end
364
+
365
+ # Number of units between runs. The resulting interval (frequency × unit) must be
366
+ # at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes;
367
+ # maximum 365 when unit is days).
368
+ sig { returns(Integer) }
369
+ attr_accessor :frequency
370
+
371
+ sig do
372
+ returns(
373
+ ContextDev::Models::MonitorCreateResponse::Schedule::Type::TaggedSymbol
374
+ )
375
+ end
376
+ attr_accessor :type
377
+
378
+ sig do
379
+ returns(
380
+ ContextDev::Models::MonitorCreateResponse::Schedule::Unit::TaggedSymbol
381
+ )
382
+ end
383
+ attr_accessor :unit
384
+
385
+ # Run the monitor on a fixed interval defined by a frequency and a unit, e.g.
386
+ # every 6 hours or every 2 days. The total interval (frequency × unit) must be
387
+ # between 10 minutes and 1 year.
388
+ sig do
389
+ params(
390
+ frequency: Integer,
391
+ type:
392
+ ContextDev::Models::MonitorCreateResponse::Schedule::Type::OrSymbol,
393
+ unit:
394
+ ContextDev::Models::MonitorCreateResponse::Schedule::Unit::OrSymbol
395
+ ).returns(T.attached_class)
396
+ end
397
+ def self.new(
398
+ # Number of units between runs. The resulting interval (frequency × unit) must be
399
+ # at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes;
400
+ # maximum 365 when unit is days).
401
+ frequency:,
402
+ type:,
403
+ unit:
404
+ )
405
+ end
406
+
407
+ sig do
408
+ override.returns(
409
+ {
410
+ frequency: Integer,
411
+ type:
412
+ ContextDev::Models::MonitorCreateResponse::Schedule::Type::TaggedSymbol,
413
+ unit:
414
+ ContextDev::Models::MonitorCreateResponse::Schedule::Unit::TaggedSymbol
415
+ }
416
+ )
417
+ end
418
+ def to_hash
419
+ end
420
+
421
+ module Type
422
+ extend ContextDev::Internal::Type::Enum
423
+
424
+ TaggedSymbol =
425
+ T.type_alias do
426
+ T.all(
427
+ Symbol,
428
+ ContextDev::Models::MonitorCreateResponse::Schedule::Type
429
+ )
430
+ end
431
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
432
+
433
+ INTERVAL =
434
+ T.let(
435
+ :interval,
436
+ ContextDev::Models::MonitorCreateResponse::Schedule::Type::TaggedSymbol
437
+ )
438
+
439
+ sig do
440
+ override.returns(
441
+ T::Array[
442
+ ContextDev::Models::MonitorCreateResponse::Schedule::Type::TaggedSymbol
443
+ ]
444
+ )
445
+ end
446
+ def self.values
447
+ end
448
+ end
449
+
450
+ module Unit
451
+ extend ContextDev::Internal::Type::Enum
452
+
453
+ TaggedSymbol =
454
+ T.type_alias do
455
+ T.all(
456
+ Symbol,
457
+ ContextDev::Models::MonitorCreateResponse::Schedule::Unit
458
+ )
459
+ end
460
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
461
+
462
+ MINUTES =
463
+ T.let(
464
+ :minutes,
465
+ ContextDev::Models::MonitorCreateResponse::Schedule::Unit::TaggedSymbol
466
+ )
467
+ HOURS =
468
+ T.let(
469
+ :hours,
470
+ ContextDev::Models::MonitorCreateResponse::Schedule::Unit::TaggedSymbol
471
+ )
472
+ DAYS =
473
+ T.let(
474
+ :days,
475
+ ContextDev::Models::MonitorCreateResponse::Schedule::Unit::TaggedSymbol
476
+ )
477
+
478
+ sig do
479
+ override.returns(
480
+ T::Array[
481
+ ContextDev::Models::MonitorCreateResponse::Schedule::Unit::TaggedSymbol
482
+ ]
483
+ )
484
+ end
485
+ def self.values
486
+ end
487
+ end
488
+ end
489
+
490
+ # Monitor lifecycle status. `failed` means the most recent run failed (see the
491
+ # monitor's `last_error`); failed monitors keep running on schedule and flip back
492
+ # to `active` on the next successful run. Monitors are auto-`paused` after
493
+ # repeated consecutive failures or insufficient-credit skips; resume by PATCHing
494
+ # status to `active`.
495
+ module Status
496
+ extend ContextDev::Internal::Type::Enum
497
+
498
+ TaggedSymbol =
499
+ T.type_alias do
500
+ T.all(Symbol, ContextDev::Models::MonitorCreateResponse::Status)
501
+ end
502
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
503
+
504
+ ACTIVE =
505
+ T.let(
506
+ :active,
507
+ ContextDev::Models::MonitorCreateResponse::Status::TaggedSymbol
508
+ )
509
+ PAUSED =
510
+ T.let(
511
+ :paused,
512
+ ContextDev::Models::MonitorCreateResponse::Status::TaggedSymbol
513
+ )
514
+ FAILED =
515
+ T.let(
516
+ :failed,
517
+ ContextDev::Models::MonitorCreateResponse::Status::TaggedSymbol
518
+ )
519
+
520
+ sig do
521
+ override.returns(
522
+ T::Array[
523
+ ContextDev::Models::MonitorCreateResponse::Status::TaggedSymbol
524
+ ]
525
+ )
526
+ end
527
+ def self.values
528
+ end
529
+ end
530
+
531
+ # Discriminated union describing what the monitor watches.
532
+ module Target
533
+ extend ContextDev::Internal::Type::Union
534
+
535
+ Variants =
536
+ T.type_alias do
537
+ T.any(
538
+ ContextDev::Models::MonitorCreateResponse::Target::Page,
539
+ ContextDev::Models::MonitorCreateResponse::Target::Sitemap,
540
+ ContextDev::Models::MonitorCreateResponse::Target::Extract
541
+ )
542
+ end
543
+
544
+ class Page < ContextDev::Internal::Type::BaseModel
545
+ OrHash =
546
+ T.type_alias do
547
+ T.any(
548
+ ContextDev::Models::MonitorCreateResponse::Target::Page,
549
+ ContextDev::Internal::AnyHash
550
+ )
551
+ end
552
+
553
+ sig { returns(Symbol) }
554
+ attr_accessor :type
555
+
556
+ sig { returns(String) }
557
+ attr_accessor :url
558
+
559
+ # Normalize whitespace before comparing or analyzing text.
560
+ sig { returns(T.nilable(T::Boolean)) }
561
+ attr_reader :normalize_whitespace
562
+
563
+ sig { params(normalize_whitespace: T::Boolean).void }
564
+ attr_writer :normalize_whitespace
565
+
566
+ # Watch a single web page.
567
+ sig do
568
+ params(
569
+ url: String,
570
+ normalize_whitespace: T::Boolean,
571
+ type: Symbol
572
+ ).returns(T.attached_class)
573
+ end
574
+ def self.new(
575
+ url:,
576
+ # Normalize whitespace before comparing or analyzing text.
577
+ normalize_whitespace: nil,
578
+ type: :page
579
+ )
580
+ end
581
+
582
+ sig do
583
+ override.returns(
584
+ { type: Symbol, url: String, normalize_whitespace: T::Boolean }
585
+ )
586
+ end
587
+ def to_hash
588
+ end
589
+ end
590
+
591
+ class Sitemap < ContextDev::Internal::Type::BaseModel
592
+ OrHash =
593
+ T.type_alias do
594
+ T.any(
595
+ ContextDev::Models::MonitorCreateResponse::Target::Sitemap,
596
+ ContextDev::Internal::AnyHash
597
+ )
598
+ end
599
+
600
+ sig { returns(Symbol) }
601
+ attr_accessor :type
602
+
603
+ # Sitemap URL to monitor.
604
+ sig { returns(String) }
605
+ attr_accessor :url
606
+
607
+ # URL path patterns to exclude.
608
+ sig { returns(T.nilable(T::Array[String])) }
609
+ attr_reader :exclude
610
+
611
+ sig { params(exclude: T::Array[String]).void }
612
+ attr_writer :exclude
613
+
614
+ # URL path patterns to include.
615
+ sig { returns(T.nilable(T::Array[String])) }
616
+ attr_reader :include
617
+
618
+ sig { params(include: T::Array[String]).void }
619
+ attr_writer :include
620
+
621
+ # Maximum number of sitemap URLs to track (capped at 10,000).
622
+ sig { returns(T.nilable(Integer)) }
623
+ attr_reader :max_urls
624
+
625
+ sig { params(max_urls: Integer).void }
626
+ attr_writer :max_urls
627
+
628
+ # Watch a sitemap for URL additions and removals. Crawled URLs are normalized
629
+ # (lowercased host, no trailing slash/fragment) and scoped to the monitored site
630
+ # and its subdomains before comparison. On a detected difference the sitemap is
631
+ # re-fetched within the same run and only URLs both observations agree on are
632
+ # reported, suppressing transient crawl flaps.
633
+ sig do
634
+ params(
635
+ url: String,
636
+ exclude: T::Array[String],
637
+ include: T::Array[String],
638
+ max_urls: Integer,
639
+ type: Symbol
640
+ ).returns(T.attached_class)
641
+ end
642
+ def self.new(
643
+ # Sitemap URL to monitor.
644
+ url:,
645
+ # URL path patterns to exclude.
646
+ exclude: nil,
647
+ # URL path patterns to include.
648
+ include: nil,
649
+ # Maximum number of sitemap URLs to track (capped at 10,000).
650
+ max_urls: nil,
651
+ type: :sitemap
652
+ )
653
+ end
654
+
655
+ sig do
656
+ override.returns(
657
+ {
658
+ type: Symbol,
659
+ url: String,
660
+ exclude: T::Array[String],
661
+ include: T::Array[String],
662
+ max_urls: Integer
663
+ }
664
+ )
665
+ end
666
+ def to_hash
667
+ end
668
+ end
669
+
670
+ class Extract < ContextDev::Internal::Type::BaseModel
671
+ OrHash =
672
+ T.type_alias do
673
+ T.any(
674
+ ContextDev::Models::MonitorCreateResponse::Target::Extract,
675
+ ContextDev::Internal::AnyHash
676
+ )
677
+ end
678
+
679
+ # Natural-language instructions guiding which pages and facts to track and which
680
+ # changes to report.
681
+ sig { returns(String) }
682
+ attr_accessor :instructions
683
+
684
+ sig { returns(Symbol) }
685
+ attr_accessor :type
686
+
687
+ # Root URL to extract structured data from.
688
+ sig { returns(String) }
689
+ attr_accessor :url
690
+
691
+ sig { returns(T.nilable(T::Boolean)) }
692
+ attr_reader :follow_subdomains
693
+
694
+ sig { params(follow_subdomains: T::Boolean).void }
695
+ attr_writer :follow_subdomains
696
+
697
+ # Optional maximum link depth from the starting URL (0 = only the starting page).
698
+ sig { returns(T.nilable(Integer)) }
699
+ attr_reader :max_depth
700
+
701
+ sig { params(max_depth: Integer).void }
702
+ attr_writer :max_depth
703
+
704
+ # Maximum number of pages to track.
705
+ sig { returns(T.nilable(Integer)) }
706
+ attr_reader :max_pages
707
+
708
+ sig { params(max_pages: Integer).void }
709
+ attr_writer :max_pages
710
+
711
+ # JSON Schema describing the data you care about. It guides which pages are
712
+ # selected for tracking and gives the change judge context on what matters. If
713
+ # omitted, a default summary + key-points schema is used.
714
+ sig { returns(T.nilable(T::Hash[Symbol, T.anything])) }
715
+ attr_reader :schema
716
+
717
+ sig { params(schema: T::Hash[Symbol, T.anything]).void }
718
+ attr_writer :schema
719
+
720
+ # Watch the monitor-relevant pages of a site for meaningful changes. A crawl
721
+ # guided by `schema`/`instructions` selects up to `max_pages` relevant pages to
722
+ # track; each run re-checks exactly those pages, and confirmed content changes are
723
+ # judged against the monitor's instructions. The tracked page set is refreshed by
724
+ # a periodic re-discovery crawl.
725
+ sig do
726
+ params(
727
+ instructions: String,
728
+ url: String,
729
+ follow_subdomains: T::Boolean,
730
+ max_depth: Integer,
731
+ max_pages: Integer,
732
+ schema: T::Hash[Symbol, T.anything],
733
+ type: Symbol
734
+ ).returns(T.attached_class)
735
+ end
736
+ def self.new(
737
+ # Natural-language instructions guiding which pages and facts to track and which
738
+ # changes to report.
739
+ instructions:,
740
+ # Root URL to extract structured data from.
741
+ url:,
742
+ follow_subdomains: nil,
743
+ # Optional maximum link depth from the starting URL (0 = only the starting page).
744
+ max_depth: nil,
745
+ # Maximum number of pages to track.
746
+ max_pages: nil,
747
+ # JSON Schema describing the data you care about. It guides which pages are
748
+ # selected for tracking and gives the change judge context on what matters. If
749
+ # omitted, a default summary + key-points schema is used.
750
+ schema: nil,
751
+ type: :extract
752
+ )
753
+ end
754
+
755
+ sig do
756
+ override.returns(
757
+ {
758
+ instructions: String,
759
+ type: Symbol,
760
+ url: String,
761
+ follow_subdomains: T::Boolean,
762
+ max_depth: Integer,
763
+ max_pages: Integer,
764
+ schema: T::Hash[Symbol, T.anything]
765
+ }
766
+ )
767
+ end
768
+ def to_hash
769
+ end
770
+ end
771
+
772
+ sig do
773
+ override.returns(
774
+ T::Array[
775
+ ContextDev::Models::MonitorCreateResponse::Target::Variants
776
+ ]
777
+ )
778
+ end
779
+ def self.variants
780
+ end
781
+ end
782
+
783
+ # Current baseline: the last observed value the monitor compares new snapshots
784
+ # against. Its shape follows `target.type` (page/sitemap/extract). Only populated
785
+ # on GET /monitors/{monitor_id}; null until the first baseline run completes (and
786
+ # after a target or change_detection update, which resets the baseline).
787
+ module Baseline
788
+ extend ContextDev::Internal::Type::Union
789
+
790
+ Variants =
791
+ T.type_alias do
792
+ T.any(
793
+ ContextDev::Models::MonitorCreateResponse::Baseline::MonitorsPageBaseline,
794
+ ContextDev::Models::MonitorCreateResponse::Baseline::MonitorsSitemapBaseline,
795
+ ContextDev::Models::MonitorCreateResponse::Baseline::MonitorsExtractBaseline
796
+ )
797
+ end
798
+
799
+ class MonitorsPageBaseline < ContextDev::Internal::Type::BaseModel
800
+ OrHash =
801
+ T.type_alias do
802
+ T.any(
803
+ ContextDev::Models::MonitorCreateResponse::Baseline::MonitorsPageBaseline,
804
+ ContextDev::Internal::AnyHash
805
+ )
806
+ end
807
+
808
+ # When this baseline was last captured or replaced.
809
+ sig { returns(Time) }
810
+ attr_accessor :captured_at
811
+
812
+ # The page's visible text as last observed.
813
+ sig { returns(String) }
814
+ attr_accessor :text
815
+
816
+ # Current baseline of a `page` monitor: the visible page text as last observed.
817
+ sig do
818
+ params(captured_at: Time, text: String).returns(T.attached_class)
819
+ end
820
+ def self.new(
821
+ # When this baseline was last captured or replaced.
822
+ captured_at:,
823
+ # The page's visible text as last observed.
824
+ text:
825
+ )
826
+ end
827
+
828
+ sig { override.returns({ captured_at: Time, text: String }) }
829
+ def to_hash
830
+ end
831
+ end
832
+
833
+ class MonitorsSitemapBaseline < ContextDev::Internal::Type::BaseModel
834
+ OrHash =
835
+ T.type_alias do
836
+ T.any(
837
+ ContextDev::Models::MonitorCreateResponse::Baseline::MonitorsSitemapBaseline,
838
+ ContextDev::Internal::AnyHash
839
+ )
840
+ end
841
+
842
+ # When this baseline was last captured or replaced.
843
+ sig { returns(Time) }
844
+ attr_accessor :captured_at
845
+
846
+ # Number of URLs in the baseline.
847
+ sig { returns(Integer) }
848
+ attr_accessor :url_count
849
+
850
+ # The sitemap URLs as last observed (sorted, normalized).
851
+ sig { returns(T::Array[String]) }
852
+ attr_accessor :urls
853
+
854
+ # Current baseline of a `sitemap` monitor: the normalized URL set as last
855
+ # observed.
856
+ sig do
857
+ params(
858
+ captured_at: Time,
859
+ url_count: Integer,
860
+ urls: T::Array[String]
861
+ ).returns(T.attached_class)
862
+ end
863
+ def self.new(
864
+ # When this baseline was last captured or replaced.
865
+ captured_at:,
866
+ # Number of URLs in the baseline.
867
+ url_count:,
868
+ # The sitemap URLs as last observed (sorted, normalized).
869
+ urls:
870
+ )
871
+ end
872
+
873
+ sig do
874
+ override.returns(
875
+ { captured_at: Time, url_count: Integer, urls: T::Array[String] }
876
+ )
877
+ end
878
+ def to_hash
879
+ end
880
+ end
881
+
882
+ class MonitorsExtractBaseline < ContextDev::Internal::Type::BaseModel
883
+ OrHash =
884
+ T.type_alias do
885
+ T.any(
886
+ ContextDev::Models::MonitorCreateResponse::Baseline::MonitorsExtractBaseline,
887
+ ContextDev::Internal::AnyHash
888
+ )
889
+ end
890
+
891
+ # When this baseline was last captured or replaced.
892
+ sig { returns(Time) }
893
+ attr_accessor :captured_at
894
+
895
+ # The extracted structured data, matching the monitor's extraction schema (same
896
+ # shape as the /web/extract endpoint's `data`). Refreshed when the monitor
897
+ # re-discovers its page set (at most about once a day); `null` when no extraction
898
+ # has been captured yet.
899
+ sig { returns(T.anything) }
900
+ attr_accessor :data
901
+
902
+ # The page URLs the monitor tracks and analyzes for changes.
903
+ sig { returns(T::Array[String]) }
904
+ attr_accessor :urls_analyzed
905
+
906
+ # Current baseline of an `extract` monitor: the pages it tracks and the structured
907
+ # data as last extracted.
908
+ sig do
909
+ params(
910
+ captured_at: Time,
911
+ data: T.anything,
912
+ urls_analyzed: T::Array[String]
913
+ ).returns(T.attached_class)
914
+ end
915
+ def self.new(
916
+ # When this baseline was last captured or replaced.
917
+ captured_at:,
918
+ # The extracted structured data, matching the monitor's extraction schema (same
919
+ # shape as the /web/extract endpoint's `data`). Refreshed when the monitor
920
+ # re-discovers its page set (at most about once a day); `null` when no extraction
921
+ # has been captured yet.
922
+ data:,
923
+ # The page URLs the monitor tracks and analyzes for changes.
924
+ urls_analyzed:
925
+ )
926
+ end
927
+
928
+ sig do
929
+ override.returns(
930
+ {
931
+ captured_at: Time,
932
+ data: T.anything,
933
+ urls_analyzed: T::Array[String]
934
+ }
935
+ )
936
+ end
937
+ def to_hash
938
+ end
939
+ end
940
+
941
+ sig do
942
+ override.returns(
943
+ T::Array[
944
+ ContextDev::Models::MonitorCreateResponse::Baseline::Variants
945
+ ]
946
+ )
947
+ end
948
+ def self.variants
949
+ end
950
+ end
951
+
952
+ class LastError < ContextDev::Internal::Type::BaseModel
953
+ OrHash =
954
+ T.type_alias do
955
+ T.any(
956
+ ContextDev::Models::MonitorCreateResponse::LastError,
957
+ ContextDev::Internal::AnyHash
958
+ )
959
+ end
960
+
961
+ sig { returns(String) }
962
+ attr_accessor :code
963
+
964
+ sig { returns(String) }
965
+ attr_accessor :message
966
+
967
+ # Error from the most recent failed run; null when the last run succeeded.
968
+ sig { params(code: String, message: String).returns(T.attached_class) }
969
+ def self.new(code:, message:)
970
+ end
971
+
972
+ sig { override.returns({ code: String, message: String }) }
973
+ def to_hash
974
+ end
975
+ end
976
+
977
+ class Webhook < ContextDev::Internal::Type::BaseModel
978
+ OrHash =
979
+ T.type_alias do
980
+ T.any(
981
+ ContextDev::Models::MonitorCreateResponse::Webhook,
982
+ ContextDev::Internal::AnyHash
983
+ )
984
+ end
985
+
986
+ # Webhook URL called when a change is detected.
987
+ sig { returns(String) }
988
+ attr_accessor :url
989
+
990
+ # Signing secret used to verify webhook authenticity. Each delivery includes an
991
+ # `X-Context-Signature: t=<unix>,v1=<hmac>` header, where the HMAC is SHA-256 over
992
+ # `"{t}.{rawRequestBody}"` keyed by this secret. Recompute it with a constant-time
993
+ # compare and reject stale timestamps to prevent replay. Generated by the API;
994
+ # cannot be set by clients.
995
+ sig { returns(T.nilable(String)) }
996
+ attr_reader :secret
997
+
998
+ sig { params(secret: String).void }
999
+ attr_writer :secret
1000
+
1001
+ sig { params(url: String, secret: String).returns(T.attached_class) }
1002
+ def self.new(
1003
+ # Webhook URL called when a change is detected.
1004
+ url:,
1005
+ # Signing secret used to verify webhook authenticity. Each delivery includes an
1006
+ # `X-Context-Signature: t=<unix>,v1=<hmac>` header, where the HMAC is SHA-256 over
1007
+ # `"{t}.{rawRequestBody}"` keyed by this secret. Recompute it with a constant-time
1008
+ # compare and reject stale timestamps to prevent replay. Generated by the API;
1009
+ # cannot be set by clients.
1010
+ secret: nil
1011
+ )
1012
+ end
1013
+
1014
+ sig { override.returns({ url: String, secret: String }) }
1015
+ def to_hash
1016
+ end
1017
+ end
1018
+ end
1019
+ end
1020
+ end