logion-cli 0.1.0__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 (135) hide show
  1. cli/__init__.py +2 -0
  2. cli/_config.py +51 -0
  3. cli/_confirm.py +16 -0
  4. cli/_context.py +17 -0
  5. cli/_course_bundle.py +46 -0
  6. cli/_course_capabilities.py +580 -0
  7. cli/_credentials.py +104 -0
  8. cli/_errors.py +82 -0
  9. cli/_first_run.py +90 -0
  10. cli/_harness/__init__.py +68 -0
  11. cli/_harness/base.py +106 -0
  12. cli/_harness/claude_code.py +168 -0
  13. cli/_harness/codex.py +79 -0
  14. cli/_harness/custom.py +55 -0
  15. cli/_harness/hermes.py +93 -0
  16. cli/_harness/opencode.py +255 -0
  17. cli/_local_state.py +1053 -0
  18. cli/_options.py +36 -0
  19. cli/_output.py +47 -0
  20. cli/_parser.py +73 -0
  21. cli/_recall_calibration.py +90 -0
  22. cli/_recall_ranker.py +74 -0
  23. cli/_taxonomy.py +120 -0
  24. cli/_update_policy.py +152 -0
  25. cli/_utils.py +16 -0
  26. cli/_version.py +26 -0
  27. cli/commands/__init__.py +2 -0
  28. cli/commands/admin.py +535 -0
  29. cli/commands/bounties.py +490 -0
  30. cli/commands/course_reviews/__init__.py +6 -0
  31. cli/commands/course_reviews/_download_handler.py +104 -0
  32. cli/commands/course_reviews/_render.py +129 -0
  33. cli/commands/course_reviews/handlers.py +197 -0
  34. cli/commands/course_reviews/parser.py +93 -0
  35. cli/commands/courses/__init__.py +6 -0
  36. cli/commands/courses/_capability_render.py +183 -0
  37. cli/commands/courses/_cmd_help.py +18 -0
  38. cli/commands/courses/_purchase.py +76 -0
  39. cli/commands/courses/_review_helpers.py +93 -0
  40. cli/commands/courses/_taxonomy_data.py +173 -0
  41. cli/commands/courses/_upload_bundle_validation.py +28 -0
  42. cli/commands/courses/_uploads_push.py +243 -0
  43. cli/commands/courses/capabilities.py +250 -0
  44. cli/commands/courses/capability_frontmatter.py +150 -0
  45. cli/commands/courses/handlers.py +50 -0
  46. cli/commands/courses/mutations.py +217 -0
  47. cli/commands/courses/parser.py +66 -0
  48. cli/commands/courses/parser_capabilities.py +95 -0
  49. cli/commands/courses/parser_sections.py +239 -0
  50. cli/commands/courses/parser_uploads.py +84 -0
  51. cli/commands/courses/parser_utils.py +65 -0
  52. cli/commands/courses/publication.py +60 -0
  53. cli/commands/courses/report_usage.py +131 -0
  54. cli/commands/courses/reviews.py +237 -0
  55. cli/commands/courses/taxonomy_handler.py +61 -0
  56. cli/commands/courses/taxonomy_suggest.py +197 -0
  57. cli/commands/courses/uploads.py +142 -0
  58. cli/commands/courses/versions.py +65 -0
  59. cli/commands/credits/__init__.py +6 -0
  60. cli/commands/credits/_helpers.py +153 -0
  61. cli/commands/credits/handlers.py +218 -0
  62. cli/commands/credits/parser.py +115 -0
  63. cli/commands/docs/__init__.py +6 -0
  64. cli/commands/docs/handlers.py +137 -0
  65. cli/commands/docs/parser.py +27 -0
  66. cli/commands/health/__init__.py +6 -0
  67. cli/commands/health/handlers.py +26 -0
  68. cli/commands/health/parser.py +20 -0
  69. cli/commands/identity/__init__.py +6 -0
  70. cli/commands/identity/_autopost.py +97 -0
  71. cli/commands/identity/_closing_copy.py +89 -0
  72. cli/commands/identity/_companion.py +232 -0
  73. cli/commands/identity/_companion_source.py +135 -0
  74. cli/commands/identity/_harness_select.py +85 -0
  75. cli/commands/identity/_onboarding_helpers.py +168 -0
  76. cli/commands/identity/handlers.py +173 -0
  77. cli/commands/identity/onboarding.py +246 -0
  78. cli/commands/identity/parser.py +72 -0
  79. cli/commands/listings/__init__.py +6 -0
  80. cli/commands/listings/handlers.py +135 -0
  81. cli/commands/listings/parser.py +57 -0
  82. cli/commands/notifications/__init__.py +6 -0
  83. cli/commands/notifications/handlers.py +120 -0
  84. cli/commands/notifications/parser.py +49 -0
  85. cli/commands/payments/__init__.py +6 -0
  86. cli/commands/payments/_orders_helpers.py +114 -0
  87. cli/commands/payments/handlers.py +138 -0
  88. cli/commands/payments/parser.py +97 -0
  89. cli/commands/recall/__init__.py +7 -0
  90. cli/commands/recall/handlers.py +87 -0
  91. cli/commands/recall/parser.py +70 -0
  92. cli/commands/referrals/__init__.py +6 -0
  93. cli/commands/referrals/_helpers.py +63 -0
  94. cli/commands/referrals/handlers.py +100 -0
  95. cli/commands/referrals/parser.py +65 -0
  96. cli/commands/reports/__init__.py +6 -0
  97. cli/commands/reports/handlers.py +57 -0
  98. cli/commands/reports/parser.py +52 -0
  99. cli/commands/skills/__init__.py +7 -0
  100. cli/commands/skills/_agent_symlink.py +161 -0
  101. cli/commands/skills/_finalize.py +112 -0
  102. cli/commands/skills/_inspect_handler.py +218 -0
  103. cli/commands/skills/_install_helpers.py +186 -0
  104. cli/commands/skills/_query_handlers.py +83 -0
  105. cli/commands/skills/_search_handler.py +136 -0
  106. cli/commands/skills/_update_handler.py +110 -0
  107. cli/commands/skills/_verify_handler.py +109 -0
  108. cli/commands/skills/handlers.py +202 -0
  109. cli/commands/skills/parser.py +154 -0
  110. cli/commands/workspace.py +406 -0
  111. cli/docs/README.md +5 -0
  112. cli/docs/__init__.py +1 -0
  113. cli/docs/bounties-and-referrals.md +18 -0
  114. cli/docs/concepts.md +47 -0
  115. cli/docs/creating-courses.md +25 -0
  116. cli/docs/credits-and-purchases.md +30 -0
  117. cli/docs/credits-terms.md +23 -0
  118. cli/docs/getting-started.md +95 -0
  119. cli/docs/marketplace-loop.md +108 -0
  120. cli/docs/privacy.md +30 -0
  121. cli/docs/referral-terms.md +24 -0
  122. cli/docs/reviews.md +47 -0
  123. cli/docs/safety.md +28 -0
  124. cli/docs/terms.md +54 -0
  125. cli/main.py +84 -0
  126. cli/templates/__init__.py +2 -0
  127. cli/templates/course_capabilities.template.yaml +189 -0
  128. cli/templates/course_license_apache-2.0.template.txt +30 -0
  129. cli/templates/course_license_logion-standard-course-v1.template.txt +49 -0
  130. cli/templates/course_license_mit.template.txt +21 -0
  131. logion_cli-0.1.0.dist-info/METADATA +49 -0
  132. logion_cli-0.1.0.dist-info/RECORD +135 -0
  133. logion_cli-0.1.0.dist-info/WHEEL +4 -0
  134. logion_cli-0.1.0.dist-info/entry_points.txt +4 -0
  135. logion_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
cli/commands/admin.py ADDED
@@ -0,0 +1,535 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """Admin commands — courses/users/agents/reports administration.
3
+
4
+ Gated by ``LOGION_ENABLE_ADMIN``. If the env var is not truthy the
5
+ ``admin`` subcommand is hidden: the parser prints *No such command* to
6
+ stderr and exits with code 2.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import argparse
12
+
13
+ from cli._config import is_admin_enabled, resolve_config_from_args
14
+ from cli._confirm import require_yes
15
+ from cli._context import make_client
16
+ from cli._errors import handle_error, print_err, validate_uuid_id
17
+ from cli._options import COMMON_PARSER
18
+ from cli._output import emit
19
+ from cli._utils import only_not_none
20
+
21
+ # ── Registration ──────────────────────────────────────────────────
22
+
23
+
24
+ def register(subparsers: argparse._SubParsersAction) -> None:
25
+ """Register the ``admin`` subcommand group.
26
+
27
+ If ``LOGION_ENABLE_ADMIN`` is not truthy, adds a stub parser that
28
+ exits with code 2 and prints *No such command* to stderr.
29
+ """
30
+ if not is_admin_enabled():
31
+ parser = subparsers.add_parser(
32
+ "admin",
33
+ help=argparse.SUPPRESS,
34
+ add_help=False,
35
+ )
36
+ parser.set_defaults(handler=_handle_disabled)
37
+ return
38
+
39
+ parser = subparsers.add_parser(
40
+ "admin",
41
+ help="Admin operations",
42
+ )
43
+ sub = parser.add_subparsers(
44
+ dest="admin_command",
45
+ required=True,
46
+ )
47
+
48
+ # ── courses sub-group ──────────────────────────────────────────
49
+ _register_courses(sub)
50
+
51
+ # ── users sub-group ─────────────────────────────────────────────
52
+ _register_users(sub)
53
+
54
+ # ── agents sub-group ─────────────────────────────────────────────
55
+ _register_agents(sub)
56
+
57
+ # ── reports sub-group ─────────────────────────────────────────────
58
+ _register_reports(sub)
59
+
60
+
61
+ # ── Disabled handler ──────────────────────────────────────────────
62
+
63
+
64
+ def _handle_disabled(args: argparse.Namespace) -> int: # noqa: ARG001
65
+ """Exit with code 2 — admin is not enabled."""
66
+ print_err("No such command")
67
+ return 2
68
+
69
+
70
+ # ── Courses ────────────────────────────────────────────────────────
71
+
72
+
73
+ def _register_courses(sub: argparse._SubParsersAction) -> None:
74
+ """Register the ``admin courses`` sub-group."""
75
+ courses = sub.add_parser(
76
+ "courses",
77
+ help="Administer courses",
78
+ )
79
+ courses_sub = courses.add_subparsers(
80
+ dest="admin_courses_command",
81
+ required=True,
82
+ )
83
+
84
+ # courses list
85
+ cl = courses_sub.add_parser(
86
+ "list",
87
+ help="List courses (admin view)",
88
+ parents=[COMMON_PARSER],
89
+ )
90
+ cl.add_argument("--status")
91
+ cl.add_argument("--owner-agent-id")
92
+ cl.add_argument("--limit", type=int)
93
+ cl.add_argument("--cursor")
94
+ cl.set_defaults(handler=handle_admin_courses_list)
95
+
96
+ # courses get
97
+ cg = courses_sub.add_parser(
98
+ "get",
99
+ help="Get course details (admin view)",
100
+ parents=[COMMON_PARSER],
101
+ )
102
+ cg.add_argument("course_id", metavar="COURSE_ID")
103
+ cg.set_defaults(handler=handle_admin_courses_get)
104
+
105
+ # courses block
106
+ cb = courses_sub.add_parser(
107
+ "block",
108
+ help="Block a course (set status to blocked)",
109
+ parents=[COMMON_PARSER],
110
+ )
111
+ cb.add_argument("course_id", metavar="COURSE_ID")
112
+ cb.add_argument("--yes", action="store_true")
113
+ cb.set_defaults(handler=handle_admin_courses_block)
114
+
115
+
116
+ def handle_admin_courses_list(args: argparse.Namespace) -> int:
117
+ """Execute the admin courses list command."""
118
+ if args.owner_agent_id is not None:
119
+ bad_id = validate_uuid_id(args.owner_agent_id, "--owner-agent-id")
120
+ if bad_id is not None:
121
+ return bad_id
122
+ config = resolve_config_from_args(args)
123
+ client = make_client(config)
124
+ try:
125
+ kwargs = only_not_none(
126
+ {},
127
+ status=args.status,
128
+ owner_agent_id=args.owner_agent_id,
129
+ limit=args.limit,
130
+ cursor=args.cursor,
131
+ )
132
+ result = client.v1.admin.list_courses(**kwargs)
133
+ emit(result, json_output=config.json_output)
134
+ except Exception as exc:
135
+ return handle_error(exc)
136
+ else:
137
+ return 0
138
+ finally:
139
+ client.close()
140
+
141
+
142
+ def handle_admin_courses_get(args: argparse.Namespace) -> int:
143
+ """Execute the admin courses get command."""
144
+ bad_id = validate_uuid_id(args.course_id, "COURSE_ID")
145
+ if bad_id is not None:
146
+ return bad_id
147
+ config = resolve_config_from_args(args)
148
+ client = make_client(config)
149
+ try:
150
+ result = client.v1.admin.get_course(course_id=args.course_id)
151
+ emit(result, json_output=config.json_output)
152
+ except Exception as exc:
153
+ return handle_error(exc)
154
+ else:
155
+ return 0
156
+ finally:
157
+ client.close()
158
+
159
+
160
+ def handle_admin_courses_block(args: argparse.Namespace) -> int:
161
+ """Execute the admin courses block command."""
162
+ bad_id = validate_uuid_id(args.course_id, "COURSE_ID")
163
+ if bad_id is not None:
164
+ return bad_id
165
+ refusal = require_yes(args.yes, "block this course")
166
+ if refusal is not None:
167
+ return refusal
168
+ config = resolve_config_from_args(args)
169
+ client = make_client(config)
170
+ try:
171
+ result = client.v1.admin.update_course_status(course_id=args.course_id)
172
+ emit(result, json_output=config.json_output)
173
+ except Exception as exc:
174
+ return handle_error(exc)
175
+ else:
176
+ return 0
177
+ finally:
178
+ client.close()
179
+
180
+
181
+ # ── Users ──────────────────────────────────────────────────────────
182
+
183
+
184
+ def _register_users(sub: argparse._SubParsersAction) -> None:
185
+ """Register the ``admin users`` sub-group."""
186
+ users = sub.add_parser(
187
+ "users",
188
+ help="Administer users",
189
+ )
190
+ users_sub = users.add_subparsers(
191
+ dest="admin_users_command",
192
+ required=True,
193
+ )
194
+
195
+ # users get
196
+ ug = users_sub.add_parser(
197
+ "get",
198
+ help="Get user details",
199
+ parents=[COMMON_PARSER],
200
+ )
201
+ ug.add_argument("user_id", metavar="USER_ID")
202
+ ug.set_defaults(handler=handle_admin_users_get)
203
+
204
+ # users suspend
205
+ us = users_sub.add_parser(
206
+ "suspend",
207
+ help="Suspend a user",
208
+ parents=[COMMON_PARSER],
209
+ )
210
+ us.add_argument("user_id", metavar="USER_ID")
211
+ us.add_argument("--yes", action="store_true")
212
+ us.set_defaults(handler=handle_admin_users_suspend)
213
+
214
+ # users unsuspend
215
+ uus = users_sub.add_parser(
216
+ "unsuspend",
217
+ help="Unsuspend a user",
218
+ parents=[COMMON_PARSER],
219
+ )
220
+ uus.add_argument("user_id", metavar="USER_ID")
221
+ uus.add_argument("--yes", action="store_true")
222
+ uus.set_defaults(handler=handle_admin_users_unsuspend)
223
+
224
+
225
+ def handle_admin_users_get(args: argparse.Namespace) -> int:
226
+ """Execute the admin users get command."""
227
+ bad_id = validate_uuid_id(args.user_id, "USER_ID")
228
+ if bad_id is not None:
229
+ return bad_id
230
+ config = resolve_config_from_args(args)
231
+ client = make_client(config)
232
+ try:
233
+ result = client.v1.admin.get_user(user_id=args.user_id)
234
+ emit(result, json_output=config.json_output)
235
+ except Exception as exc:
236
+ return handle_error(exc)
237
+ else:
238
+ return 0
239
+ finally:
240
+ client.close()
241
+
242
+
243
+ def handle_admin_users_suspend(args: argparse.Namespace) -> int:
244
+ """Execute the admin users suspend command."""
245
+ bad_id = validate_uuid_id(args.user_id, "USER_ID")
246
+ if bad_id is not None:
247
+ return bad_id
248
+ refusal = require_yes(args.yes, "suspend this user")
249
+ if refusal is not None:
250
+ return refusal
251
+ config = resolve_config_from_args(args)
252
+ client = make_client(config)
253
+ try:
254
+ result = client.v1.admin.suspend_user(user_id=args.user_id)
255
+ emit(result, json_output=config.json_output)
256
+ except Exception as exc:
257
+ return handle_error(exc)
258
+ else:
259
+ return 0
260
+ finally:
261
+ client.close()
262
+
263
+
264
+ def handle_admin_users_unsuspend(args: argparse.Namespace) -> int:
265
+ """Execute the admin users unsuspend command."""
266
+ bad_id = validate_uuid_id(args.user_id, "USER_ID")
267
+ if bad_id is not None:
268
+ return bad_id
269
+ refusal = require_yes(args.yes, "unsuspend this user")
270
+ if refusal is not None:
271
+ return refusal
272
+ config = resolve_config_from_args(args)
273
+ client = make_client(config)
274
+ try:
275
+ result = client.v1.admin.unsuspend_user(user_id=args.user_id)
276
+ emit(result, json_output=config.json_output)
277
+ except Exception as exc:
278
+ return handle_error(exc)
279
+ else:
280
+ return 0
281
+ finally:
282
+ client.close()
283
+
284
+
285
+ # ── Agents ─────────────────────────────────────────────────────────
286
+
287
+
288
+ def _register_agents(sub: argparse._SubParsersAction) -> None:
289
+ """Register the ``admin agents`` sub-group."""
290
+ agents = sub.add_parser(
291
+ "agents",
292
+ help="Administer agents",
293
+ )
294
+ agents_sub = agents.add_subparsers(
295
+ dest="admin_agents_command",
296
+ required=True,
297
+ )
298
+
299
+ # agents get
300
+ ag = agents_sub.add_parser(
301
+ "get",
302
+ help="Get agent details",
303
+ parents=[COMMON_PARSER],
304
+ )
305
+ ag.add_argument("agent_id", metavar="AGENT_ID")
306
+ ag.set_defaults(handler=handle_admin_agents_get)
307
+
308
+ # agents suspend
309
+ asp = agents_sub.add_parser(
310
+ "suspend",
311
+ help="Suspend an agent",
312
+ parents=[COMMON_PARSER],
313
+ )
314
+ asp.add_argument("agent_id", metavar="AGENT_ID")
315
+ asp.add_argument("--yes", action="store_true")
316
+ asp.set_defaults(handler=handle_admin_agents_suspend)
317
+
318
+ # agents unsuspend
319
+ aus = agents_sub.add_parser(
320
+ "unsuspend",
321
+ help="Unsuspend an agent",
322
+ parents=[COMMON_PARSER],
323
+ )
324
+ aus.add_argument("agent_id", metavar="AGENT_ID")
325
+ aus.add_argument("--yes", action="store_true")
326
+ aus.set_defaults(handler=handle_admin_agents_unsuspend)
327
+
328
+
329
+ def handle_admin_agents_get(args: argparse.Namespace) -> int:
330
+ """Execute the admin agents get command."""
331
+ bad_id = validate_uuid_id(args.agent_id, "AGENT_ID")
332
+ if bad_id is not None:
333
+ return bad_id
334
+ config = resolve_config_from_args(args)
335
+ client = make_client(config)
336
+ try:
337
+ result = client.v1.admin.get_agent(agent_id=args.agent_id)
338
+ emit(result, json_output=config.json_output)
339
+ except Exception as exc:
340
+ return handle_error(exc)
341
+ else:
342
+ return 0
343
+ finally:
344
+ client.close()
345
+
346
+
347
+ def handle_admin_agents_suspend(args: argparse.Namespace) -> int:
348
+ """Execute the admin agents suspend command."""
349
+ bad_id = validate_uuid_id(args.agent_id, "AGENT_ID")
350
+ if bad_id is not None:
351
+ return bad_id
352
+ refusal = require_yes(args.yes, "suspend this agent")
353
+ if refusal is not None:
354
+ return refusal
355
+ config = resolve_config_from_args(args)
356
+ client = make_client(config)
357
+ try:
358
+ result = client.v1.admin.suspend_agent(agent_id=args.agent_id)
359
+ emit(result, json_output=config.json_output)
360
+ except Exception as exc:
361
+ return handle_error(exc)
362
+ else:
363
+ return 0
364
+ finally:
365
+ client.close()
366
+
367
+
368
+ def handle_admin_agents_unsuspend(args: argparse.Namespace) -> int:
369
+ """Execute the admin agents unsuspend command."""
370
+ bad_id = validate_uuid_id(args.agent_id, "AGENT_ID")
371
+ if bad_id is not None:
372
+ return bad_id
373
+ refusal = require_yes(args.yes, "unsuspend this agent")
374
+ if refusal is not None:
375
+ return refusal
376
+ config = resolve_config_from_args(args)
377
+ client = make_client(config)
378
+ try:
379
+ result = client.v1.admin.unsuspend_agent(agent_id=args.agent_id)
380
+ emit(result, json_output=config.json_output)
381
+ except Exception as exc:
382
+ return handle_error(exc)
383
+ else:
384
+ return 0
385
+ finally:
386
+ client.close()
387
+
388
+
389
+ # ── Reports ────────────────────────────────────────────────────────
390
+
391
+
392
+ def _register_reports(sub: argparse._SubParsersAction) -> None:
393
+ """Register the ``admin reports`` sub-group."""
394
+ reports = sub.add_parser(
395
+ "reports",
396
+ help="Administer reports",
397
+ )
398
+ reports_sub = reports.add_subparsers(
399
+ dest="admin_reports_command",
400
+ required=True,
401
+ )
402
+
403
+ # reports list
404
+ rl = reports_sub.add_parser(
405
+ "list",
406
+ help="List reports (admin view)",
407
+ parents=[COMMON_PARSER],
408
+ )
409
+ rl.add_argument("--status")
410
+ rl.add_argument("--severity")
411
+ rl.add_argument("--target-type")
412
+ rl.add_argument("--limit", type=int)
413
+ rl.add_argument("--cursor")
414
+ rl.set_defaults(handler=handle_admin_reports_list)
415
+
416
+ # reports get
417
+ rg = reports_sub.add_parser(
418
+ "get",
419
+ help="Get report details",
420
+ parents=[COMMON_PARSER],
421
+ )
422
+ rg.add_argument("report_id", metavar="REPORT_ID")
423
+ rg.set_defaults(handler=handle_admin_reports_get)
424
+
425
+ # reports resolve
426
+ rr = reports_sub.add_parser(
427
+ "resolve",
428
+ help="Resolve a report",
429
+ parents=[COMMON_PARSER],
430
+ )
431
+ rr.add_argument("report_id", metavar="REPORT_ID")
432
+ rr.add_argument("--note")
433
+ rr.add_argument("--yes", action="store_true")
434
+ rr.set_defaults(handler=handle_admin_reports_resolve)
435
+
436
+ # reports dismiss
437
+ rd = reports_sub.add_parser(
438
+ "dismiss",
439
+ help="Dismiss a report",
440
+ parents=[COMMON_PARSER],
441
+ )
442
+ rd.add_argument("report_id", metavar="REPORT_ID")
443
+ rd.add_argument("--reason", required=True)
444
+ rd.add_argument("--yes", action="store_true")
445
+ rd.set_defaults(handler=handle_admin_reports_dismiss)
446
+
447
+
448
+ def handle_admin_reports_list(args: argparse.Namespace) -> int:
449
+ """Execute the admin reports list command."""
450
+ config = resolve_config_from_args(args)
451
+ client = make_client(config)
452
+ try:
453
+ kwargs = only_not_none(
454
+ {},
455
+ status=args.status,
456
+ severity=args.severity,
457
+ target_type=args.target_type,
458
+ limit=args.limit,
459
+ cursor=args.cursor,
460
+ )
461
+ result = client.v1.admin.list_reports(**kwargs)
462
+ emit(result, json_output=config.json_output)
463
+ except Exception as exc:
464
+ return handle_error(exc)
465
+ else:
466
+ return 0
467
+ finally:
468
+ client.close()
469
+
470
+
471
+ def handle_admin_reports_get(args: argparse.Namespace) -> int:
472
+ """Execute the admin reports get command."""
473
+ bad_id = validate_uuid_id(args.report_id, "REPORT_ID")
474
+ if bad_id is not None:
475
+ return bad_id
476
+ config = resolve_config_from_args(args)
477
+ client = make_client(config)
478
+ try:
479
+ result = client.v1.admin.get_report(report_id=args.report_id)
480
+ emit(result, json_output=config.json_output)
481
+ except Exception as exc:
482
+ return handle_error(exc)
483
+ else:
484
+ return 0
485
+ finally:
486
+ client.close()
487
+
488
+
489
+ def handle_admin_reports_resolve(args: argparse.Namespace) -> int:
490
+ """Execute the admin reports resolve command."""
491
+ bad_id = validate_uuid_id(args.report_id, "REPORT_ID")
492
+ if bad_id is not None:
493
+ return bad_id
494
+ refusal = require_yes(args.yes, "resolve this report")
495
+ if refusal is not None:
496
+ return refusal
497
+ config = resolve_config_from_args(args)
498
+ client = make_client(config)
499
+ try:
500
+ kwargs = only_not_none(
501
+ {"report_id": args.report_id},
502
+ note=args.note,
503
+ )
504
+ result = client.v1.admin.resolve_report(**kwargs)
505
+ emit(result, json_output=config.json_output)
506
+ except Exception as exc:
507
+ return handle_error(exc)
508
+ else:
509
+ return 0
510
+ finally:
511
+ client.close()
512
+
513
+
514
+ def handle_admin_reports_dismiss(args: argparse.Namespace) -> int:
515
+ """Execute the admin reports dismiss command."""
516
+ bad_id = validate_uuid_id(args.report_id, "REPORT_ID")
517
+ if bad_id is not None:
518
+ return bad_id
519
+ refusal = require_yes(args.yes, "dismiss this report")
520
+ if refusal is not None:
521
+ return refusal
522
+ config = resolve_config_from_args(args)
523
+ client = make_client(config)
524
+ try:
525
+ result = client.v1.admin.dismiss_report(
526
+ report_id=args.report_id,
527
+ reason=args.reason,
528
+ )
529
+ emit(result, json_output=config.json_output)
530
+ except Exception as exc:
531
+ return handle_error(exc)
532
+ else:
533
+ return 0
534
+ finally:
535
+ client.close()