batrachian-toad 0.5.22__py3-none-any.whl

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 (120) hide show
  1. batrachian_toad-0.5.22.dist-info/METADATA +197 -0
  2. batrachian_toad-0.5.22.dist-info/RECORD +120 -0
  3. batrachian_toad-0.5.22.dist-info/WHEEL +4 -0
  4. batrachian_toad-0.5.22.dist-info/entry_points.txt +2 -0
  5. batrachian_toad-0.5.22.dist-info/licenses/LICENSE +661 -0
  6. toad/__init__.py +46 -0
  7. toad/__main__.py +4 -0
  8. toad/_loop.py +86 -0
  9. toad/about.py +90 -0
  10. toad/acp/agent.py +671 -0
  11. toad/acp/api.py +47 -0
  12. toad/acp/encode_tool_call_id.py +12 -0
  13. toad/acp/messages.py +138 -0
  14. toad/acp/prompt.py +54 -0
  15. toad/acp/protocol.py +426 -0
  16. toad/agent.py +62 -0
  17. toad/agent_schema.py +70 -0
  18. toad/agents.py +45 -0
  19. toad/ansi/__init__.py +1 -0
  20. toad/ansi/_ansi.py +1612 -0
  21. toad/ansi/_ansi_colors.py +264 -0
  22. toad/ansi/_control_codes.py +37 -0
  23. toad/ansi/_keys.py +251 -0
  24. toad/ansi/_sgr_styles.py +64 -0
  25. toad/ansi/_stream_parser.py +418 -0
  26. toad/answer.py +22 -0
  27. toad/app.py +557 -0
  28. toad/atomic.py +37 -0
  29. toad/cli.py +257 -0
  30. toad/code_analyze.py +28 -0
  31. toad/complete.py +34 -0
  32. toad/constants.py +58 -0
  33. toad/conversation_markdown.py +19 -0
  34. toad/danger.py +371 -0
  35. toad/data/agents/ampcode.com.toml +51 -0
  36. toad/data/agents/augmentcode.com.toml +40 -0
  37. toad/data/agents/claude.com.toml +41 -0
  38. toad/data/agents/docker.com.toml +59 -0
  39. toad/data/agents/geminicli.com.toml +28 -0
  40. toad/data/agents/goose.ai.toml +51 -0
  41. toad/data/agents/inference.huggingface.co.toml +33 -0
  42. toad/data/agents/kimi.com.toml +35 -0
  43. toad/data/agents/openai.com.toml +53 -0
  44. toad/data/agents/opencode.ai.toml +61 -0
  45. toad/data/agents/openhands.dev.toml +44 -0
  46. toad/data/agents/stakpak.dev.toml +61 -0
  47. toad/data/agents/vibe.mistral.ai.toml +27 -0
  48. toad/data/agents/vtcode.dev.toml +62 -0
  49. toad/data/images/frog.png +0 -0
  50. toad/data/sounds/turn-over.wav +0 -0
  51. toad/db.py +5 -0
  52. toad/dec.py +332 -0
  53. toad/directory.py +234 -0
  54. toad/directory_watcher.py +96 -0
  55. toad/fuzzy.py +140 -0
  56. toad/gist.py +2 -0
  57. toad/history.py +138 -0
  58. toad/jsonrpc.py +576 -0
  59. toad/menus.py +14 -0
  60. toad/messages.py +74 -0
  61. toad/option_content.py +51 -0
  62. toad/os.py +0 -0
  63. toad/path_complete.py +145 -0
  64. toad/path_filter.py +124 -0
  65. toad/paths.py +71 -0
  66. toad/pill.py +23 -0
  67. toad/prompt/extract.py +19 -0
  68. toad/prompt/resource.py +68 -0
  69. toad/protocol.py +28 -0
  70. toad/screens/action_modal.py +94 -0
  71. toad/screens/agent_modal.py +172 -0
  72. toad/screens/command_edit_modal.py +58 -0
  73. toad/screens/main.py +192 -0
  74. toad/screens/permissions.py +390 -0
  75. toad/screens/permissions.tcss +72 -0
  76. toad/screens/settings.py +254 -0
  77. toad/screens/settings.tcss +101 -0
  78. toad/screens/store.py +476 -0
  79. toad/screens/store.tcss +261 -0
  80. toad/settings.py +354 -0
  81. toad/settings_schema.py +318 -0
  82. toad/shell.py +263 -0
  83. toad/shell_read.py +42 -0
  84. toad/slash_command.py +34 -0
  85. toad/toad.tcss +752 -0
  86. toad/version.py +80 -0
  87. toad/visuals/columns.py +273 -0
  88. toad/widgets/agent_response.py +79 -0
  89. toad/widgets/agent_thought.py +41 -0
  90. toad/widgets/command_pane.py +224 -0
  91. toad/widgets/condensed_path.py +93 -0
  92. toad/widgets/conversation.py +1626 -0
  93. toad/widgets/danger_warning.py +65 -0
  94. toad/widgets/diff_view.py +709 -0
  95. toad/widgets/flash.py +81 -0
  96. toad/widgets/future_text.py +126 -0
  97. toad/widgets/grid_select.py +223 -0
  98. toad/widgets/highlighted_textarea.py +180 -0
  99. toad/widgets/mandelbrot.py +294 -0
  100. toad/widgets/markdown_note.py +13 -0
  101. toad/widgets/menu.py +147 -0
  102. toad/widgets/non_selectable_label.py +5 -0
  103. toad/widgets/note.py +18 -0
  104. toad/widgets/path_search.py +381 -0
  105. toad/widgets/plan.py +180 -0
  106. toad/widgets/project_directory_tree.py +74 -0
  107. toad/widgets/prompt.py +741 -0
  108. toad/widgets/question.py +337 -0
  109. toad/widgets/shell_result.py +35 -0
  110. toad/widgets/shell_terminal.py +18 -0
  111. toad/widgets/side_bar.py +74 -0
  112. toad/widgets/slash_complete.py +211 -0
  113. toad/widgets/strike_text.py +66 -0
  114. toad/widgets/terminal.py +526 -0
  115. toad/widgets/terminal_tool.py +338 -0
  116. toad/widgets/throbber.py +90 -0
  117. toad/widgets/tool_call.py +303 -0
  118. toad/widgets/user_input.py +23 -0
  119. toad/widgets/version.py +5 -0
  120. toad/widgets/welcome.py +31 -0
toad/toad.tcss ADDED
@@ -0,0 +1,752 @@
1
+ .block {
2
+ margin: 1 1 1 0;
3
+ }
4
+
5
+ Markdown {
6
+ layout: stream;
7
+ }
8
+
9
+ LoadingIndicator {
10
+ background: transparent;
11
+ }
12
+
13
+ Throbber {
14
+ width: 100%;
15
+ height: 1;
16
+ overlay: screen;
17
+ visibility: hidden;
18
+ &.-busy {
19
+ visibility: visible;
20
+ }
21
+ }
22
+
23
+ .-hidden {
24
+ display: none;
25
+ }
26
+
27
+ App.-hide-footer {
28
+ #info-container {
29
+ margin: 0 !important;
30
+ }
31
+ Footer {
32
+ display: none;
33
+ }
34
+ }
35
+
36
+ App.-hide-footer.-compact-input {
37
+ #prompt-container {
38
+ margin: 0 0;
39
+ }
40
+ }
41
+
42
+
43
+ App.-hide-thoughts AgentThought {
44
+ display: none;
45
+ }
46
+
47
+ App.-hide-sidebar SideBar {
48
+ layer: sidebar;
49
+ offset-x: -100%;
50
+ &:focus-within {
51
+ offset-x: 0;
52
+ }
53
+ }
54
+
55
+ App.-hide-status-line StatusLine {
56
+ display: none;
57
+ }
58
+
59
+ App.-hide-agent-title AgentInfo {
60
+ display: none;
61
+ }
62
+
63
+ App.-hide-info-bar #info-container {
64
+ height: 1;
65
+ display: none;
66
+ }
67
+
68
+ App.-compact-input {
69
+ Prompt {
70
+ #prompt-container {
71
+ border: none;
72
+ &:focus-within {
73
+ border: none;
74
+ }
75
+ margin: 0 0 0 0;
76
+
77
+ }
78
+ #info-container {
79
+ margin: 0 0;
80
+ }
81
+ }
82
+ }
83
+
84
+ Checkbox {
85
+ # TODO: Bug in Textual?
86
+ text-overflow: clip;
87
+ }
88
+
89
+ Note,MarkdownNote {
90
+ padding: 0 1 0 0;
91
+ &.about MarkdownTable {
92
+ # Make the tables compact in /about
93
+ width: auto;
94
+ }
95
+ &.-error {
96
+ border: heavy $error;
97
+ }
98
+ &.-stop-reason {
99
+ border: wide $error 50%;
100
+ padding: 0 1;
101
+ MarkdownH2 {
102
+ margin: 1 0 1 0;
103
+ }
104
+ }
105
+ }
106
+
107
+
108
+ Toast {
109
+ margin: 0 0;
110
+ padding: 0 1;
111
+ background: $background;
112
+ color: $text-muted;
113
+ .toast--title {
114
+ color: $text;
115
+ }
116
+ &.-information {
117
+ border: round $primary;
118
+ }
119
+ &.-warning {
120
+ border: round $warning;
121
+ }
122
+ &.-error {
123
+ border: round $error;
124
+ }
125
+ }
126
+
127
+ Menu {
128
+ border: round $accent;
129
+ background: transparent;
130
+ }
131
+
132
+
133
+ Loading {
134
+ color: $text-primary;
135
+
136
+ }
137
+
138
+
139
+
140
+ Plan {
141
+ border: panel $secondary;
142
+ background: transparent;
143
+ margin: 1 0 1 0 !important; # Special case because the tall border reduces the apparent width
144
+ padding: 1 0 0 1;
145
+ height: auto;
146
+ grid-size: 2;
147
+ grid-columns: auto 1fr;
148
+ grid-rows: auto;
149
+
150
+ .-no-plan {
151
+ text-style: dim italic;
152
+
153
+ }
154
+
155
+ .plan {
156
+ color: $text-secondary;
157
+ }
158
+ .status {
159
+ padding: 0 0 0 0;
160
+ color: $text-secondary;
161
+ }
162
+ .priority {
163
+ padding: 0 0 0 0;
164
+ }
165
+ .status.status-completed {
166
+ color: $text-success;
167
+ }
168
+ .status-pending {
169
+ opacity: 0.7;
170
+ }
171
+ .plan.status-completed {
172
+
173
+ }
174
+ }
175
+
176
+
177
+ Conversation {
178
+ Window {
179
+ layout: stream;
180
+ margin: 0;
181
+ scrollbar-size-vertical: 2;
182
+ padding: 0 1 0 1;
183
+ height: 1fr;
184
+ align: left bottom;
185
+ }
186
+
187
+ &.-scrollbar-thin {
188
+ Window {
189
+ # scrollbar-gutter: stable;
190
+ scrollbar-size-vertical: 1;
191
+ }
192
+
193
+ }
194
+ &.-scrollbar-hidden {
195
+ Window {
196
+ # scrollbar-gutter: auto;
197
+ scrollbar-size-vertical: 0;
198
+ }
199
+ }
200
+
201
+ height: 1fr;
202
+ layers: base prompt float;
203
+
204
+
205
+ &.-column {
206
+ max-width: 100;
207
+ background: black 7%;
208
+
209
+ #info-container {
210
+ margin: 1 1;
211
+ }
212
+ }
213
+
214
+ Contents {
215
+ layout: stream;
216
+ width: 1fr;
217
+ overflow: hidden;
218
+ height: auto;
219
+ padding: 0 0 0 0;
220
+ }
221
+
222
+ ContentsGrid {
223
+ grid-size: 2;
224
+ grid-columns: 1 1fr;
225
+ grid-rows: auto;
226
+ height: auto;
227
+ }
228
+
229
+ #cursor-container {
230
+ height: auto;
231
+ width: 1;
232
+ outline-left: outer $foreground 7%;
233
+ outline-top: blank;
234
+ &> Cursor {
235
+ height: 0;
236
+ width: 1;
237
+
238
+ border-left: outer $text-accent;
239
+ visibility: visible;
240
+ &.-blink {
241
+ border-left: outer $text-accent 20%;
242
+ }
243
+ }
244
+ }
245
+
246
+ AgentResponse {
247
+ min-height: 1;
248
+ padding: 0 1 0 0;
249
+ overflow-x: auto;
250
+ scrollbar-size-horizontal: 0;
251
+ layout: stream;
252
+ MarkdownBlock:last-child {
253
+ margin-bottom: 0;
254
+ }
255
+ }
256
+
257
+ LoadingIndicator {
258
+ height: 10;
259
+ }
260
+
261
+ AgentThought {
262
+ background: $primary-muted 20%;
263
+ color: $text-primary;
264
+ min-height: 1;
265
+ margin: 1 1 1 0;
266
+ padding: 1 1 1 1;
267
+ overflow-x: auto;
268
+ scrollbar-size-horizontal: 0;
269
+ layout: stream;
270
+ MarkdownBlock:last-child {
271
+ margin-bottom: 0;
272
+ }
273
+
274
+ &.-loading {
275
+ background: transparent !important;
276
+ padding: 0;
277
+ margin: 0;
278
+ }
279
+ max-height: 10;
280
+ overflow-y: auto;
281
+ scrollbar-visibility: hidden;
282
+
283
+ &.-maximized {
284
+ max-height: 100h;
285
+ margin: 1 2;
286
+ scrollbar-visibility: visible;
287
+ &>* {
288
+ padding-right: 1;
289
+ }
290
+ }
291
+ }
292
+
293
+ ToolCall {
294
+ padding: 0 0 0 1;
295
+ width: 1fr;
296
+ layout: stream;
297
+ height: auto;
298
+
299
+ .icon {
300
+ width: auto;
301
+ margin-right: 1;
302
+ }
303
+ #tool-content {
304
+ display: none;
305
+ }
306
+ &.-has-content #tool-content {
307
+ margin-top: 1;
308
+ }
309
+ &.-expanded {
310
+ #tool-content {
311
+ display: block;
312
+ }
313
+ }
314
+
315
+ ToolCallHeader {
316
+ width: auto;
317
+ max-width: 1fr;
318
+ }
319
+ }
320
+
321
+
322
+
323
+ ShellResult {
324
+ border-left: blank $primary;
325
+ background: $foreground 4%;
326
+ padding: 1 0;
327
+ margin: 1 1 1 0;
328
+ #prompt {
329
+ margin: 0 1 0 0;
330
+ color: $text-primary;
331
+ }
332
+ }
333
+
334
+ Terminal {
335
+ width: 1fr;
336
+ height: auto;
337
+ padding: 0 1 0 0;
338
+ margin: 1 0;
339
+ overflow: scroll;
340
+ scrollbar-size: 0 0;
341
+ }
342
+
343
+ TerminalTool {
344
+ height: auto;
345
+ border: panel $text-secondary 90%;
346
+ padding: 1 1 0 1;
347
+ &.-success {
348
+ border: panel $text-success 90%;
349
+ }
350
+ &.-error {
351
+ border: panel $error-muted;
352
+ border-title-color: $text-error;
353
+ border-subtitle-align: right;
354
+ border-subtitle-style: bold;
355
+ }
356
+ }
357
+
358
+ UserInput {
359
+ border-left: blank $secondary;
360
+ background: $secondary 15%;
361
+ padding: 1 1 1 0;
362
+ margin: 1 1 1 0;
363
+ Markdown {
364
+ padding:0 2 0 0;
365
+ }
366
+ Markdown > MarkdownBlock:last-child {
367
+ margin-bottom: 0;
368
+ }
369
+ MarkdownFence {
370
+ margin: 0 2 1 0;
371
+ }
372
+ #prompt {
373
+ margin: 0 1 0 0;
374
+ color: $text-secondary;
375
+ }
376
+ }
377
+
378
+ }
379
+
380
+
381
+ Welcome {
382
+ height: auto;
383
+ #logo {
384
+ color: $text-success;
385
+ }
386
+ #message {
387
+ padding: 0;
388
+ width: 1fr;
389
+ height: auto;
390
+ }
391
+ }
392
+
393
+
394
+ Prompt {
395
+ padding: 0 0 0 0;
396
+ height: auto;
397
+ dock: bottom;
398
+
399
+ &.-shell-mode {
400
+ #prompt-container:focus-within {
401
+ border: tall $primary;
402
+ }
403
+ }
404
+
405
+ PathSearch, SlashComplete {
406
+ display: none;
407
+ height: 16;
408
+ Input {
409
+ margin: 0 1;
410
+ padding: 0 1;
411
+ }
412
+ OptionList {
413
+ border: none;
414
+ height: 1fr;
415
+ padding: 0;
416
+ margin: 0 1;
417
+ overflow: hidden;
418
+ text-wrap: nowrap;
419
+ text-overflow: ellipsis;
420
+ & > .option-list--option {
421
+ padding: 0 1;
422
+
423
+ }
424
+ }
425
+ DirectoryTree {
426
+ margin: 0 1;
427
+ padding: 0 0 0 1;
428
+ &:focus {
429
+ background-tint:transparent;
430
+ }
431
+ }
432
+ .message {
433
+ background: $foreground 8%;
434
+ color: $text 40%;
435
+ margin: 0 1;
436
+ padding: 0 1;
437
+ }
438
+ }
439
+
440
+ &.-show-path-search {
441
+ PathSearch {
442
+ display: block
443
+ }
444
+ }
445
+
446
+ &.-show-slash-complete {
447
+ SlashComplete {
448
+ display: block;
449
+ }
450
+ }
451
+
452
+ Question {
453
+ display: none;
454
+ #prompt {
455
+ width: 1fr;
456
+ }
457
+ }
458
+ &.-mode-ask {
459
+ Question {
460
+ display: block;
461
+ }
462
+ #text-prompt {
463
+ display: none;
464
+ }
465
+ }
466
+
467
+ PromptContainer {
468
+ &:dark {
469
+ background: black 10%;
470
+ }
471
+ &:light {
472
+ background: white 40%;
473
+ }
474
+ height: auto;
475
+ margin: 0 0 1 0;
476
+ border: tall transparent;
477
+ border-subtitle-align: left;
478
+ border-subtitle-style: reverse;
479
+
480
+ &:focus-within {
481
+ border: tall $secondary;
482
+ #prompt {
483
+ text-opacity: 100%;
484
+ }
485
+ }
486
+
487
+ #prompt {
488
+ padding: 0 1;
489
+ text-opacity: 30%;
490
+ }
491
+
492
+ PromptTextArea {
493
+ padding: 0 1 0 0;
494
+ background: transparent;
495
+ border: none;
496
+ height: auto;
497
+ max-height: 50vh;
498
+
499
+ &:blur {
500
+ text-opacity: 0.5;
501
+ }
502
+ }
503
+ }
504
+
505
+ &.-working-directory-out-of-bounds #info-container CondensedPath {
506
+ color: $text-error;
507
+ }
508
+
509
+ #info-container {
510
+
511
+ height: 1;
512
+ margin: 1 1;
513
+ # padding: 1 0;
514
+
515
+ AgentInfo {
516
+ padding: 0 1;
517
+ margin: 0 1 0 0;
518
+ color: $text-primary;
519
+ background: $primary 10%;
520
+ width: auto;
521
+ }
522
+
523
+ CondensedPath {
524
+ &:first-of-type {
525
+ margin: 0 1 0 0;
526
+ }
527
+ margin: 0 1;
528
+ width: 1fr;
529
+ height: 1;
530
+ text-wrap: nowrap;
531
+ color: $text-secondary;
532
+ }
533
+
534
+ StatusLine {
535
+ color: $secondary 70%;
536
+ margin: 0 0;
537
+ width: auto;
538
+ height: 1;
539
+ text-align: right;
540
+ text-wrap: nowrap;
541
+ text-overflow: ellipsis;
542
+ }
543
+
544
+ ModeInfo {
545
+ padding: 0 1;
546
+ margin: 0 0;
547
+ color: $text-secondary;
548
+ background: $secondary 10%;
549
+ dock: right;
550
+ display: none;
551
+ }
552
+ }
553
+
554
+ &.-has-mode #info-container ModeInfo {
555
+ display: block;
556
+ }
557
+
558
+ }
559
+
560
+
561
+ ModeInfo:hover {
562
+ text-style: underline;
563
+ }
564
+
565
+ ModeSwitcher {
566
+
567
+ max-height: 50vh;
568
+
569
+ border: none;
570
+ padding: 0;
571
+ width: auto;
572
+ max-width: 100;
573
+
574
+ overlay: screen;
575
+ overflow: hidden;
576
+ constrain: inside inflect;
577
+ min-width: 12;
578
+ margin: 1 0;
579
+ height: auto;
580
+
581
+ & > .option-list--option {
582
+ padding: 0 1;
583
+ }
584
+
585
+ &:blur {
586
+ display: none;
587
+ }
588
+
589
+ &:focus > .option-list--option-highlighted {
590
+ background: $primary 30%;
591
+ text-style: not bold;
592
+ }
593
+ }
594
+
595
+ MainScreen {
596
+ background: $background;
597
+ layers: sidebar screen base;
598
+
599
+ SideBar {
600
+ border-right: tall black 10%;
601
+ background: transparent;
602
+ dock: left;
603
+
604
+ overflow: hidden scroll;
605
+ scrollbar-size: 0 0;
606
+ box-sizing: border-box;
607
+
608
+ padding: 0 0;
609
+ margin: 0;
610
+ width: 40;
611
+ max-width: 45%;
612
+ min-width: 40;
613
+ height: 1fr;
614
+
615
+ DirectoryTree {
616
+ height: 1fr;
617
+ &:focus {
618
+ background-tint: transparent;
619
+ }
620
+ }
621
+
622
+
623
+ Plan {
624
+ border: none;
625
+ margin: 0 !important;
626
+ padding: 0 1 0 0;
627
+ .plan {
628
+ color: $text-secondary;
629
+ }
630
+ }
631
+
632
+
633
+ Collapsible {
634
+
635
+ width: 1fr;
636
+ height: 1fr;
637
+ min-height: 3;
638
+
639
+ &.-collapsed {
640
+ height: auto;
641
+ }
642
+
643
+ &.-fixed {
644
+ height: auto;
645
+ Contents {
646
+ height: auto;
647
+ }
648
+ }
649
+
650
+ Contents {
651
+ height: 1fr;
652
+ padding: 1 0 0 0;
653
+ }
654
+ }
655
+
656
+
657
+ }
658
+
659
+ }
660
+
661
+
662
+ Version {
663
+ layer: float;
664
+ offset-x: 0;
665
+ overlay: screen;
666
+ width: auto;
667
+ color: $text-success 50%;
668
+ text-style: bold;
669
+ }
670
+
671
+ Explain {
672
+ layer: float;
673
+ padding: 0;
674
+ & > Markdown {
675
+ margin: 1;
676
+ height: auto;
677
+ min-height: 1fr;
678
+ width: 100%;
679
+
680
+ }
681
+ scrollbar-gutter: stable;
682
+ margin: 0;
683
+ dock: bottom;
684
+ border: panel $primary;
685
+ height: 50%;
686
+ margin: 1 0;
687
+ display: none;
688
+ overflow: auto;
689
+ width: 100%;
690
+ }
691
+
692
+
693
+ Footer {
694
+ background: transparent;
695
+ .footer-key--key {
696
+ color: $text;
697
+ background: transparent;
698
+ # text-style: not bold;
699
+ padding: 0 1;
700
+ }
701
+
702
+ .footer-key--description {
703
+ padding: 0 1 0 0;
704
+ color: $text-muted;
705
+ background: $footer-description-background;
706
+ }
707
+
708
+ &:hover {
709
+ color: transparent;
710
+ background: transparent;
711
+ }
712
+
713
+ &.-disabled {
714
+ text-style: dim;
715
+ }
716
+
717
+ &.-compact {
718
+ .footer-key--key {
719
+ padding: 0;
720
+ }
721
+ .footer-key--description {
722
+ padding: 0 0 0 1;
723
+ }
724
+ }
725
+ FooterLabel {
726
+ color: $text-muted;
727
+ background: $footer-description-background;
728
+ }
729
+
730
+ FooterKey.-disabled {
731
+ .footer-key--key {
732
+ text-opacity: 0.6;
733
+ }
734
+ }
735
+ }
736
+
737
+ HelpPanel {
738
+ padding-right: 0;
739
+ KeyPanel {
740
+ scrollbar-gutter: stable;
741
+ &> BindingsTable > .bindings-table--description {
742
+ color: $text-muted;
743
+ }
744
+ .bindings-table--key {
745
+ color: $text;
746
+ }
747
+ &> BindingsTable > .bindings-table--header {
748
+ color: $text-warning;
749
+ text-style: underline;
750
+ }
751
+ }
752
+ }