wxcli 1.2.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 (413) hide show
  1. wxcli/__init__.py +4 -0
  2. wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
  3. wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
  4. wxcli/_playbook/.claude/rules/cleanup.md +29 -0
  5. wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
  6. wxcli/_playbook/.claude/rules/org-health.md +14 -0
  7. wxcli/_playbook/.claude/settings.json +8 -0
  8. wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
  9. wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
  10. wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
  11. wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
  12. wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
  13. wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
  14. wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
  15. wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
  16. wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
  17. wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
  18. wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
  19. wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
  20. wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
  21. wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
  22. wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
  23. wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
  24. wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
  25. wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
  26. wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
  27. wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
  28. wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
  29. wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
  30. wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
  31. wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
  32. wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
  33. wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
  34. wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
  35. wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
  36. wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
  37. wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
  38. wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
  39. wxcli/_playbook/CLAUDE.md +373 -0
  40. wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
  41. wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
  42. wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
  43. wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
  44. wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
  45. wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
  46. wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
  47. wxcli/_playbook/docs/reference/admin-partner.md +357 -0
  48. wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
  49. wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
  50. wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
  51. wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
  52. wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
  53. wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
  54. wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
  55. wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
  56. wxcli/_playbook/docs/reference/authentication.md +965 -0
  57. wxcli/_playbook/docs/reference/call-control.md +1205 -0
  58. wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
  59. wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
  60. wxcli/_playbook/docs/reference/call-routing.md +2304 -0
  61. wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
  62. wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
  63. wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
  64. wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
  65. wxcli/_playbook/docs/reference/devices-core.md +1869 -0
  66. wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
  67. wxcli/_playbook/docs/reference/devices-platform.md +467 -0
  68. wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
  69. wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
  70. wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
  71. wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
  72. wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
  73. wxcli/_playbook/docs/reference/meetings-content.md +473 -0
  74. wxcli/_playbook/docs/reference/meetings-core.md +903 -0
  75. wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
  76. wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
  77. wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
  78. wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
  79. wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
  80. wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
  81. wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
  82. wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
  83. wxcli/_playbook/docs/reference/provisioning.md +1366 -0
  84. wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
  85. wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
  86. wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
  87. wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
  88. wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
  89. wxcli/_version.py +24 -0
  90. wxcli/auth.py +137 -0
  91. wxcli/commands/__init__.py +0 -0
  92. wxcli/commands/_registry.py +181 -0
  93. wxcli/commands/activation_email.py +103 -0
  94. wxcli/commands/admin_recordings.py +585 -0
  95. wxcli/commands/analytics.py +105 -0
  96. wxcli/commands/announcement_playlists.py +219 -0
  97. wxcli/commands/announcements.py +519 -0
  98. wxcli/commands/archive_users.py +36 -0
  99. wxcli/commands/attachment_actions.py +60 -0
  100. wxcli/commands/audit_events.py +83 -0
  101. wxcli/commands/authorizations.py +113 -0
  102. wxcli/commands/auto_attendant.py +642 -0
  103. wxcli/commands/broadworks_billing_reports.py +126 -0
  104. wxcli/commands/broadworks_enterprises.py +160 -0
  105. wxcli/commands/broadworks_subscribers.py +319 -0
  106. wxcli/commands/broadworks_workspaces.py +108 -0
  107. wxcli/commands/call_controls.py +1304 -0
  108. wxcli/commands/call_park.py +494 -0
  109. wxcli/commands/call_pickup.py +229 -0
  110. wxcli/commands/call_queue.py +1878 -0
  111. wxcli/commands/call_recording.py +707 -0
  112. wxcli/commands/call_routing.py +1610 -0
  113. wxcli/commands/call_settings_for_me_phase_5.py +212 -0
  114. wxcli/commands/caller_reputation.py +169 -0
  115. wxcli/commands/calling_service.py +305 -0
  116. wxcli/commands/cc_address_book.py +770 -0
  117. wxcli/commands/cc_agent_greetings.py +242 -0
  118. wxcli/commands/cc_agent_summaries.py +39 -0
  119. wxcli/commands/cc_agent_wellbeing.py +216 -0
  120. wxcli/commands/cc_agents.py +425 -0
  121. wxcli/commands/cc_ai_assistant.py +55 -0
  122. wxcli/commands/cc_ai_feature.py +294 -0
  123. wxcli/commands/cc_audio_files.py +149 -0
  124. wxcli/commands/cc_auto_csat.py +311 -0
  125. wxcli/commands/cc_aux_code.py +458 -0
  126. wxcli/commands/cc_business_hour.py +353 -0
  127. wxcli/commands/cc_call_monitoring.py +228 -0
  128. wxcli/commands/cc_callbacks.py +194 -0
  129. wxcli/commands/cc_campaign.py +212 -0
  130. wxcli/commands/cc_captures.py +39 -0
  131. wxcli/commands/cc_contact_list.py +169 -0
  132. wxcli/commands/cc_contact_number.py +295 -0
  133. wxcli/commands/cc_data_sources.py +235 -0
  134. wxcli/commands/cc_desktop_layout.py +380 -0
  135. wxcli/commands/cc_desktop_profile.py +322 -0
  136. wxcli/commands/cc_dial_number.py +511 -0
  137. wxcli/commands/cc_dial_plan.py +347 -0
  138. wxcli/commands/cc_dnc.py +101 -0
  139. wxcli/commands/cc_entry_point.py +545 -0
  140. wxcli/commands/cc_ewt.py +51 -0
  141. wxcli/commands/cc_flow.py +477 -0
  142. wxcli/commands/cc_global_vars.py +430 -0
  143. wxcli/commands/cc_holiday_list.py +335 -0
  144. wxcli/commands/cc_journey.py +1261 -0
  145. wxcli/commands/cc_legacy_flows.py +49 -0
  146. wxcli/commands/cc_multimedia_profile.py +436 -0
  147. wxcli/commands/cc_notification.py +51 -0
  148. wxcli/commands/cc_outdial_ani.py +604 -0
  149. wxcli/commands/cc_overrides.py +341 -0
  150. wxcli/commands/cc_queue.py +1083 -0
  151. wxcli/commands/cc_queue_stats.py +55 -0
  152. wxcli/commands/cc_realtime.py +51 -0
  153. wxcli/commands/cc_resource_collection.py +312 -0
  154. wxcli/commands/cc_search.py +46 -0
  155. wxcli/commands/cc_site.py +400 -0
  156. wxcli/commands/cc_skill.py +350 -0
  157. wxcli/commands/cc_skill_profile.py +289 -0
  158. wxcli/commands/cc_subscriptions.py +426 -0
  159. wxcli/commands/cc_summaries.py +130 -0
  160. wxcli/commands/cc_tasks.py +844 -0
  161. wxcli/commands/cc_team.py +325 -0
  162. wxcli/commands/cc_user_profiles.py +349 -0
  163. wxcli/commands/cc_users.py +701 -0
  164. wxcli/commands/cc_work_types.py +363 -0
  165. wxcli/commands/cdr.py +89 -0
  166. wxcli/commands/classifications.py +38 -0
  167. wxcli/commands/cleanup.py +1427 -0
  168. wxcli/commands/client_settings.py +72 -0
  169. wxcli/commands/conference.py +328 -0
  170. wxcli/commands/configure.py +72 -0
  171. wxcli/commands/converged_recordings.py +347 -0
  172. wxcli/commands/converged_recordings_export.py +310 -0
  173. wxcli/commands/cq_playlists.py +42 -0
  174. wxcli/commands/cucm.py +2794 -0
  175. wxcli/commands/cucm_config.py +129 -0
  176. wxcli/commands/customer_assist.py +373 -0
  177. wxcli/commands/data_sources.py +227 -0
  178. wxcli/commands/dect_devices.py +787 -0
  179. wxcli/commands/device_configurations.py +77 -0
  180. wxcli/commands/device_dynamic_settings.py +320 -0
  181. wxcli/commands/device_settings.py +1489 -0
  182. wxcli/commands/devices.py +280 -0
  183. wxcli/commands/domains.py +142 -0
  184. wxcli/commands/ecm.py +178 -0
  185. wxcli/commands/emergency_services.py +827 -0
  186. wxcli/commands/events.py +83 -0
  187. wxcli/commands/external_voicemail.py +52 -0
  188. wxcli/commands/groups.py +206 -0
  189. wxcli/commands/guest_management.py +76 -0
  190. wxcli/commands/hds.py +340 -0
  191. wxcli/commands/hot_desk.py +67 -0
  192. wxcli/commands/hot_desking_members.py +118 -0
  193. wxcli/commands/hot_desking_portal.py +124 -0
  194. wxcli/commands/hunt_group.py +577 -0
  195. wxcli/commands/hybrid_clusters.py +71 -0
  196. wxcli/commands/hybrid_connectors.py +67 -0
  197. wxcli/commands/identity_org.py +159 -0
  198. wxcli/commands/init_playbook.py +155 -0
  199. wxcli/commands/licenses.py +106 -0
  200. wxcli/commands/live_monitoring.py +40 -0
  201. wxcli/commands/location_call_handling.py +577 -0
  202. wxcli/commands/location_schedules.py +341 -0
  203. wxcli/commands/location_settings.py +1297 -0
  204. wxcli/commands/location_voicemail.py +494 -0
  205. wxcli/commands/locations.py +336 -0
  206. wxcli/commands/meeting_captions.py +110 -0
  207. wxcli/commands/meeting_chats.py +63 -0
  208. wxcli/commands/meeting_invitees.py +234 -0
  209. wxcli/commands/meeting_messages.py +28 -0
  210. wxcli/commands/meeting_participants.py +278 -0
  211. wxcli/commands/meeting_polls.py +111 -0
  212. wxcli/commands/meeting_preferences.py +515 -0
  213. wxcli/commands/meeting_qa.py +78 -0
  214. wxcli/commands/meeting_qualities.py +43 -0
  215. wxcli/commands/meeting_reports.py +101 -0
  216. wxcli/commands/meeting_session_types.py +105 -0
  217. wxcli/commands/meeting_site.py +57 -0
  218. wxcli/commands/meeting_slido.py +44 -0
  219. wxcli/commands/meeting_summaries.py +92 -0
  220. wxcli/commands/meeting_tracking_codes.py +233 -0
  221. wxcli/commands/meeting_transcripts.py +230 -0
  222. wxcli/commands/meetings.py +1997 -0
  223. wxcli/commands/memberships.py +164 -0
  224. wxcli/commands/messages.py +213 -0
  225. wxcli/commands/mode_management.py +244 -0
  226. wxcli/commands/my_call_settings.py +3577 -0
  227. wxcli/commands/numbers.py +405 -0
  228. wxcli/commands/operating_modes.py +410 -0
  229. wxcli/commands/org_contacts.py +284 -0
  230. wxcli/commands/org_health_cli.py +55 -0
  231. wxcli/commands/org_settings.py +71 -0
  232. wxcli/commands/organizations.py +83 -0
  233. wxcli/commands/paging_group.py +257 -0
  234. wxcli/commands/partner_admins.py +141 -0
  235. wxcli/commands/partner_reports.py +188 -0
  236. wxcli/commands/partner_tags.py +216 -0
  237. wxcli/commands/people.py +279 -0
  238. wxcli/commands/person_call_settings.py +71 -0
  239. wxcli/commands/pstn.py +280 -0
  240. wxcli/commands/recording_report.py +154 -0
  241. wxcli/commands/report_templates.py +38 -0
  242. wxcli/commands/reports.py +144 -0
  243. wxcli/commands/resource_group_memberships.py +160 -0
  244. wxcli/commands/resource_groups.py +67 -0
  245. wxcli/commands/roles.py +63 -0
  246. wxcli/commands/room_tabs.py +160 -0
  247. wxcli/commands/rooms.py +225 -0
  248. wxcli/commands/scim_bulk.py +46 -0
  249. wxcli/commands/scim_groups.py +246 -0
  250. wxcli/commands/scim_schemas.py +82 -0
  251. wxcli/commands/scim_users.py +283 -0
  252. wxcli/commands/security_audit.py +54 -0
  253. wxcli/commands/service_apps.py +51 -0
  254. wxcli/commands/single_number_reach.py +209 -0
  255. wxcli/commands/team_memberships.py +155 -0
  256. wxcli/commands/teams.py +153 -0
  257. wxcli/commands/ucm_profile.py +42 -0
  258. wxcli/commands/update.py +219 -0
  259. wxcli/commands/user_settings.py +5116 -0
  260. wxcli/commands/video_mesh.py +1090 -0
  261. wxcli/commands/virtual_extensions.py +502 -0
  262. wxcli/commands/virtual_line_settings.py +2072 -0
  263. wxcli/commands/webhooks.py +176 -0
  264. wxcli/commands/wholesale_billing_reports.py +147 -0
  265. wxcli/commands/wholesale_provisioning.py +523 -0
  266. wxcli/commands/workspace_locations.py +339 -0
  267. wxcli/commands/workspace_metrics.py +103 -0
  268. wxcli/commands/workspace_personalization.py +70 -0
  269. wxcli/commands/workspace_settings.py +3347 -0
  270. wxcli/commands/workspaces.py +279 -0
  271. wxcli/commands/xapi.py +114 -0
  272. wxcli/config.py +139 -0
  273. wxcli/errors.py +77 -0
  274. wxcli/main.py +210 -0
  275. wxcli/migration/CLAUDE.md +106 -0
  276. wxcli/migration/__init__.py +1 -0
  277. wxcli/migration/advisory/CLAUDE.md +196 -0
  278. wxcli/migration/advisory/__init__.py +46 -0
  279. wxcli/migration/advisory/advisor.py +107 -0
  280. wxcli/migration/advisory/advisory_patterns.py +2552 -0
  281. wxcli/migration/advisory/recommendation_rules.py +835 -0
  282. wxcli/migration/cucm/CLAUDE.md +74 -0
  283. wxcli/migration/cucm/__init__.py +5 -0
  284. wxcli/migration/cucm/connection.py +265 -0
  285. wxcli/migration/cucm/discovery.py +225 -0
  286. wxcli/migration/cucm/extractors/__init__.py +1 -0
  287. wxcli/migration/cucm/extractors/announcements.py +92 -0
  288. wxcli/migration/cucm/extractors/base.py +90 -0
  289. wxcli/migration/cucm/extractors/device_profiles.py +98 -0
  290. wxcli/migration/cucm/extractors/devices.py +193 -0
  291. wxcli/migration/cucm/extractors/e911.py +103 -0
  292. wxcli/migration/cucm/extractors/features.py +309 -0
  293. wxcli/migration/cucm/extractors/helpers.py +73 -0
  294. wxcli/migration/cucm/extractors/informational.py +295 -0
  295. wxcli/migration/cucm/extractors/locations.py +221 -0
  296. wxcli/migration/cucm/extractors/moh.py +100 -0
  297. wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
  298. wxcli/migration/cucm/extractors/routing.py +493 -0
  299. wxcli/migration/cucm/extractors/shared_lines.py +146 -0
  300. wxcli/migration/cucm/extractors/templates.py +229 -0
  301. wxcli/migration/cucm/extractors/tier4.py +173 -0
  302. wxcli/migration/cucm/extractors/users.py +240 -0
  303. wxcli/migration/cucm/extractors/voicemail.py +243 -0
  304. wxcli/migration/cucm/extractors/workspaces.py +88 -0
  305. wxcli/migration/cucm/unity_connection.py +304 -0
  306. wxcli/migration/execute/CLAUDE.md +372 -0
  307. wxcli/migration/execute/__init__.py +303 -0
  308. wxcli/migration/execute/batch.py +277 -0
  309. wxcli/migration/execute/dependency.py +483 -0
  310. wxcli/migration/execute/engine.py +964 -0
  311. wxcli/migration/execute/handlers.py +2232 -0
  312. wxcli/migration/execute/planner.py +1939 -0
  313. wxcli/migration/execute/runtime.py +571 -0
  314. wxcli/migration/export/CLAUDE.md +49 -0
  315. wxcli/migration/export/__init__.py +8 -0
  316. wxcli/migration/export/csv_export.py +126 -0
  317. wxcli/migration/export/deployment_plan.py +479 -0
  318. wxcli/migration/export/json_export.py +60 -0
  319. wxcli/migration/models.py +941 -0
  320. wxcli/migration/phone_models.py +50 -0
  321. wxcli/migration/preflight/CLAUDE.md +52 -0
  322. wxcli/migration/preflight/__init__.py +89 -0
  323. wxcli/migration/preflight/checks.py +911 -0
  324. wxcli/migration/preflight/runner.py +293 -0
  325. wxcli/migration/rate_limiter.py +144 -0
  326. wxcli/migration/report/CLAUDE.md +245 -0
  327. wxcli/migration/report/__init__.py +7 -0
  328. wxcli/migration/report/appendix.py +2437 -0
  329. wxcli/migration/report/assembler.py +183 -0
  330. wxcli/migration/report/charts.py +263 -0
  331. wxcli/migration/report/executive.py +776 -0
  332. wxcli/migration/report/explainer.py +704 -0
  333. wxcli/migration/report/helpers.py +74 -0
  334. wxcli/migration/report/ingest.py +152 -0
  335. wxcli/migration/report/notice_templates.py +192 -0
  336. wxcli/migration/report/score.py +375 -0
  337. wxcli/migration/report/styles.py +1052 -0
  338. wxcli/migration/report/user_diff.py +1052 -0
  339. wxcli/migration/report/user_notice.py +425 -0
  340. wxcli/migration/state.py +139 -0
  341. wxcli/migration/store.py +860 -0
  342. wxcli/migration/transform/CLAUDE.md +107 -0
  343. wxcli/migration/transform/__init__.py +12 -0
  344. wxcli/migration/transform/analysis_pipeline.py +453 -0
  345. wxcli/migration/transform/analyzers/__init__.py +142 -0
  346. wxcli/migration/transform/analyzers/css_permission.py +189 -0
  347. wxcli/migration/transform/analyzers/css_routing.py +335 -0
  348. wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
  349. wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
  350. wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
  351. wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
  352. wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
  353. wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
  354. wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
  355. wxcli/migration/transform/analyzers/missing_data.py +300 -0
  356. wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
  357. wxcli/migration/transform/analyzers/shared_line.py +170 -0
  358. wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
  359. wxcli/migration/transform/analyzers/workspace_license.py +212 -0
  360. wxcli/migration/transform/cross_reference.py +1136 -0
  361. wxcli/migration/transform/cucm_pattern.py +246 -0
  362. wxcli/migration/transform/decisions.py +301 -0
  363. wxcli/migration/transform/e164.py +145 -0
  364. wxcli/migration/transform/engine.py +256 -0
  365. wxcli/migration/transform/mappers/CLAUDE.md +123 -0
  366. wxcli/migration/transform/mappers/__init__.py +76 -0
  367. wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
  368. wxcli/migration/transform/mappers/base.py +190 -0
  369. wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
  370. wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
  371. wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
  372. wxcli/migration/transform/mappers/css_mapper.py +868 -0
  373. wxcli/migration/transform/mappers/dect_mapper.py +367 -0
  374. wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
  375. wxcli/migration/transform/mappers/device_mapper.py +227 -0
  376. wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
  377. wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
  378. wxcli/migration/transform/mappers/e911_mapper.py +129 -0
  379. wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
  380. wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
  381. wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
  382. wxcli/migration/transform/mappers/line_mapper.py +310 -0
  383. wxcli/migration/transform/mappers/location_mapper.py +235 -0
  384. wxcli/migration/transform/mappers/moh_mapper.py +114 -0
  385. wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
  386. wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
  387. wxcli/migration/transform/mappers/routing_mapper.py +821 -0
  388. wxcli/migration/transform/mappers/snr_mapper.py +201 -0
  389. wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
  390. wxcli/migration/transform/mappers/user_mapper.py +264 -0
  391. wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
  392. wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
  393. wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
  394. wxcli/migration/transform/normalizers.py +2008 -0
  395. wxcli/migration/transform/pattern_converter.py +106 -0
  396. wxcli/migration/transform/pipeline.py +271 -0
  397. wxcli/migration/transform/rules.py +255 -0
  398. wxcli/org_health/CLAUDE.md +63 -0
  399. wxcli/org_health/__init__.py +7 -0
  400. wxcli/org_health/analyze.py +93 -0
  401. wxcli/org_health/checks.py +458 -0
  402. wxcli/org_health/collector.py +62 -0
  403. wxcli/org_health/models.py +78 -0
  404. wxcli/org_health/report.py +300 -0
  405. wxcli/output.py +101 -0
  406. wxcli-1.2.0.dist-info/METADATA +505 -0
  407. wxcli-1.2.0.dist-info/RECORD +413 -0
  408. wxcli-1.2.0.dist-info/WHEEL +5 -0
  409. wxcli-1.2.0.dist-info/entry_points.txt +2 -0
  410. wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
  411. wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
  412. wxcli-1.2.0.dist-info/scm_version.json +8 -0
  413. wxcli-1.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,284 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+ from wxcli.config import resolve_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Calling org-contacts.")
10
+
11
+
12
+ @app.command("create")
13
+ def create(
14
+ schemas: str = typer.Option(None, "--schemas", help="(required) \"urn:cisco:codev:identity:contact:core:1.0\"."),
15
+ display_name: str = typer.Option(None, "--display-name", help="The full name of the contact."),
16
+ first_name: str = typer.Option(None, "--first-name", help="The first name of the contact."),
17
+ last_name: str = typer.Option(None, "--last-name", help="The last name of the contact."),
18
+ company_name: str = typer.Option(None, "--company-name", help="The company the contact is working for."),
19
+ title: str = typer.Option(None, "--title", help="The contact's title."),
20
+ address: str = typer.Option(None, "--address", help="Contact's address."),
21
+ avatar_url: str = typer.Option(None, "--avatar-url", help="The URL to the person's avatar in PNG format."),
22
+ primary_contact_method: str = typer.Option(None, "--primary-contact-method", help="Choices: SIPADDRESS, EMAIL, PHONE, IMS"),
23
+ source: str = typer.Option(None, "--source", help="(required) Choices: CH, Webex4Broadworks"),
24
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
25
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
26
+ debug: bool = typer.Option(False, "--debug"),
27
+ ):
28
+ """Create a Contact\n\nExample --json-body:\n '{"schemas":"...","source":"CH","displayName":"...","firstName":"...","lastName":"...","companyName":"...","title":"...","address":"..."}'."""
29
+ api = get_api(debug=debug)
30
+ org_id = resolve_org_id(api.session)
31
+ url = f"https://webexapis.com/v1/contacts/organizations/{org_id}/contacts"
32
+ if json_body:
33
+ body = json.loads(json_body)
34
+ else:
35
+ body = {}
36
+ if schemas is not None:
37
+ body["schemas"] = schemas
38
+ if display_name is not None:
39
+ body["displayName"] = display_name
40
+ if first_name is not None:
41
+ body["firstName"] = first_name
42
+ if last_name is not None:
43
+ body["lastName"] = last_name
44
+ if company_name is not None:
45
+ body["companyName"] = company_name
46
+ if title is not None:
47
+ body["title"] = title
48
+ if address is not None:
49
+ body["address"] = address
50
+ if avatar_url is not None:
51
+ body["avatarURL"] = avatar_url
52
+ if primary_contact_method is not None:
53
+ body["primaryContactMethod"] = primary_contact_method
54
+ if source is not None:
55
+ body["source"] = source
56
+ _missing = [f for f in ['schemas', 'source'] if f not in body or body[f] is None]
57
+ if _missing:
58
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
59
+ raise typer.Exit(1)
60
+ try:
61
+ result = api.session.rest_post(url, json=body)
62
+ except WebexError as e:
63
+ handle_rest_error(e)
64
+ if output == "json":
65
+ print_json(result)
66
+ elif isinstance(result, dict) and "contactId" in result:
67
+ typer.echo(f"Created: {result['contactId']}")
68
+ elif isinstance(result, dict) and "id" in result:
69
+ typer.echo(f"Created: {result['id']}")
70
+ elif not result or result == {}:
71
+ typer.echo("Created.")
72
+ else:
73
+ print_json(result)
74
+
75
+
76
+
77
+ @app.command("show")
78
+ def show(
79
+ contact_id: str = typer.Argument(help="contactId"),
80
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
81
+ debug: bool = typer.Option(False, "--debug"),
82
+ ):
83
+ """Get a Contact."""
84
+ api = get_api(debug=debug)
85
+ org_id = resolve_org_id(api.session)
86
+ url = f"https://webexapis.com/v1/contacts/organizations/{org_id}/contacts/{contact_id}"
87
+ try:
88
+ result = api.session.rest_get(url)
89
+ except WebexError as e:
90
+ handle_rest_error(e)
91
+ if output == "json":
92
+ print_json(result)
93
+ else:
94
+ if isinstance(result, dict):
95
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
96
+ elif isinstance(result, list):
97
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
98
+ else:
99
+ print_json(result)
100
+
101
+
102
+
103
+ @app.command("update")
104
+ def update(
105
+ contact_id: str = typer.Argument(help="contactId"),
106
+ schemas: str = typer.Option(None, "--schemas", help="\"urn:cisco:codev:identity:contact:core:1.0\"."),
107
+ display_name: str = typer.Option(None, "--display-name", help="The full name of the contact."),
108
+ first_name: str = typer.Option(None, "--first-name", help="The first name of the contact."),
109
+ last_name: str = typer.Option(None, "--last-name", help="The last name of the contact."),
110
+ company_name: str = typer.Option(None, "--company-name", help="The company the contact is working for."),
111
+ title: str = typer.Option(None, "--title", help="The contact's title."),
112
+ address: str = typer.Option(None, "--address", help="Contact's address."),
113
+ avatar_url: str = typer.Option(None, "--avatar-url", help="The URL to the person's avatar in PNG format."),
114
+ primary_contact_method: str = typer.Option(None, "--primary-contact-method", help="Choices: SIPADDRESS, EMAIL, PHONE, IMS"),
115
+ source: str = typer.Option(None, "--source", help="Choices: CH, Webex4Broadworks"),
116
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
117
+ debug: bool = typer.Option(False, "--debug"),
118
+ ):
119
+ """Update a Contact\n\nExample --json-body:\n '{"schemas":"...","source":"CH","displayName":"...","firstName":"...","lastName":"...","companyName":"...","title":"...","address":"..."}'."""
120
+ api = get_api(debug=debug)
121
+ org_id = resolve_org_id(api.session)
122
+ url = f"https://webexapis.com/v1/contacts/organizations/{org_id}/contacts/{contact_id}"
123
+ if json_body:
124
+ body = json.loads(json_body)
125
+ else:
126
+ body = {}
127
+ if schemas is not None:
128
+ body["schemas"] = schemas
129
+ if display_name is not None:
130
+ body["displayName"] = display_name
131
+ if first_name is not None:
132
+ body["firstName"] = first_name
133
+ if last_name is not None:
134
+ body["lastName"] = last_name
135
+ if company_name is not None:
136
+ body["companyName"] = company_name
137
+ if title is not None:
138
+ body["title"] = title
139
+ if address is not None:
140
+ body["address"] = address
141
+ if avatar_url is not None:
142
+ body["avatarURL"] = avatar_url
143
+ if primary_contact_method is not None:
144
+ body["primaryContactMethod"] = primary_contact_method
145
+ if source is not None:
146
+ body["source"] = source
147
+ try:
148
+ result = api.session.rest_patch(url, json=body)
149
+ except WebexError as e:
150
+ handle_rest_error(e)
151
+ typer.echo(f"Updated.")
152
+
153
+
154
+
155
+ @app.command("delete")
156
+ def delete(
157
+ contact_id: str = typer.Argument(help="contactId"),
158
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
159
+ debug: bool = typer.Option(False, "--debug"),
160
+ ):
161
+ """Delete a Contact."""
162
+ if not force:
163
+ typer.confirm(f"Delete {contact_id}?", abort=True)
164
+ api = get_api(debug=debug)
165
+ org_id = resolve_org_id(api.session)
166
+ url = f"https://webexapis.com/v1/contacts/organizations/{org_id}/contacts/{contact_id}"
167
+ try:
168
+ api.session.rest_delete(url)
169
+ except WebexError as e:
170
+ handle_rest_error(e)
171
+ typer.echo(f"Deleted: {contact_id}")
172
+
173
+
174
+
175
+ @app.command("list")
176
+ def cmd_list(
177
+ keyword: str = typer.Option(None, "--keyword", help="List contacts with a keyword."),
178
+ source: str = typer.Option(None, "--source", help="List contacts with source."),
179
+ group_ids: str = typer.Option(None, "--group-ids", help="Filter contacts based on groups."),
180
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
181
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
182
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
183
+ debug: bool = typer.Option(False, "--debug"),
184
+ ):
185
+ """List Contacts."""
186
+ api = get_api(debug=debug)
187
+ org_id = resolve_org_id(api.session)
188
+ url = f"https://webexapis.com/v1/contacts/organizations/{org_id}/contacts/search"
189
+ params = {}
190
+ if keyword is not None:
191
+ params["keyword"] = keyword
192
+ if source is not None:
193
+ params["source"] = source
194
+ if group_ids is not None:
195
+ params["groupIds"] = group_ids
196
+ if limit > 0:
197
+ params["limit"] = limit
198
+ if offset > 0:
199
+ params["start"] = offset
200
+ result = None
201
+ try:
202
+ result = api.session.rest_get(url, params=params)
203
+ except WebexError as e:
204
+ handle_rest_error(e)
205
+ result = result or []
206
+ items = result.get("result", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
207
+ if output == "json":
208
+ print_json(items)
209
+ else:
210
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
211
+
212
+
213
+
214
+ @app.command("create-bulk")
215
+ def create_bulk(
216
+ schemas: str = typer.Option(None, "--schemas", help="(required) \"urn:cisco:codev:identity:contact:core:1.0\"."),
217
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
218
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
219
+ debug: bool = typer.Option(False, "--debug"),
220
+ ):
221
+ """Bulk Create or Update Contacts\n\nExample --json-body:\n '{"schemas":"...","contacts":[{"source":"...","contactId":"...","displayName":"...","firstName":"...","lastName":"...","companyName":"...","title":"...","address":"..."}]}'."""
222
+ api = get_api(debug=debug)
223
+ org_id = resolve_org_id(api.session)
224
+ url = f"https://webexapis.com/v1/contacts/organizations/{org_id}/contacts/bulk"
225
+ if json_body:
226
+ body = json.loads(json_body)
227
+ else:
228
+ body = {}
229
+ if schemas is not None:
230
+ body["schemas"] = schemas
231
+ _missing = [f for f in ['schemas'] if f not in body or body[f] is None]
232
+ if _missing:
233
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
234
+ raise typer.Exit(1)
235
+ try:
236
+ result = api.session.rest_post(url, json=body)
237
+ except WebexError as e:
238
+ handle_rest_error(e)
239
+ if output == "json":
240
+ print_json(result)
241
+ elif isinstance(result, dict) and "id" in result:
242
+ typer.echo(f"Created: {result['id']}")
243
+ elif not result or result == {}:
244
+ typer.echo("Created.")
245
+ else:
246
+ print_json(result)
247
+
248
+
249
+
250
+ @app.command("create-delete")
251
+ def create_delete(
252
+ schemas: str = typer.Option(None, "--schemas", help="(required) \"urn:cisco:codev:identity:contact:core:1.0\"."),
253
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
254
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
255
+ debug: bool = typer.Option(False, "--debug"),
256
+ ):
257
+ """Bulk Delete Contacts\n\nExample --json-body:\n '{"schemas":"...","objectIds":["..."]}'."""
258
+ api = get_api(debug=debug)
259
+ org_id = resolve_org_id(api.session)
260
+ url = f"https://webexapis.com/v1/contacts/organizations/{org_id}/contacts/bulk/delete"
261
+ if json_body:
262
+ body = json.loads(json_body)
263
+ else:
264
+ body = {}
265
+ if schemas is not None:
266
+ body["schemas"] = schemas
267
+ _missing = [f for f in ['schemas'] if f not in body or body[f] is None]
268
+ if _missing:
269
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
270
+ raise typer.Exit(1)
271
+ try:
272
+ result = api.session.rest_post(url, json=body)
273
+ except WebexError as e:
274
+ handle_rest_error(e)
275
+ if output == "json":
276
+ print_json(result)
277
+ elif isinstance(result, dict) and "id" in result:
278
+ typer.echo(f"Created: {result['id']}")
279
+ elif not result or result == {}:
280
+ typer.echo("Created.")
281
+ else:
282
+ print_json(result)
283
+
284
+
@@ -0,0 +1,55 @@
1
+ """wxcli org-health — analyze collected org data and generate the HTML report.
2
+
3
+ Wraps wxcli.org_health so the org-health skill works under pipx installs,
4
+ where `python3.14 -m wxcli.org_health.*` cannot resolve (spec §4.5).
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ from pathlib import Path
10
+
11
+ import typer
12
+
13
+ from wxcli.org_health.analyze import run_analysis
14
+ from wxcli.org_health.collector import validate_collection
15
+ from wxcli.org_health.report import _deserialize_result, generate_report
16
+
17
+ app = typer.Typer(help="Org health assessment — analyze collected data, generate the report.")
18
+
19
+
20
+ @app.command()
21
+ def analyze(
22
+ collected_dir: Path = typer.Argument(..., help="Path to the collected/ directory"),
23
+ output: Path = typer.Option(..., "--output", help="Directory to write results.json into"),
24
+ ):
25
+ """Run all 18 health checks over collected JSON and write results.json."""
26
+ errors = validate_collection(collected_dir)
27
+ if errors:
28
+ for e in errors:
29
+ typer.echo(f"ERROR: {e}", err=True)
30
+ raise typer.Exit(1)
31
+ result = run_analysis(collected_dir)
32
+ output.mkdir(parents=True, exist_ok=True)
33
+ results_path = output / "results.json"
34
+ results_path.write_text(json.dumps(result.to_dict(), indent=2))
35
+ typer.echo(f"Results written to {results_path}")
36
+ typer.echo(f" Findings: {len(result.findings)} total")
37
+
38
+
39
+ @app.command()
40
+ def report(
41
+ results_dir: Path = typer.Argument(..., help="Path to the results/ directory"),
42
+ brand: str = typer.Option(..., "--brand", help="Customer/org brand name"),
43
+ prepared_by: str = typer.Option(..., "--prepared-by", help="Name of the report author"),
44
+ ):
45
+ """Generate the self-contained HTML report from results.json."""
46
+ results_path = results_dir / "results.json"
47
+ if not results_path.exists():
48
+ typer.echo(f"ERROR: results.json not found in {results_dir}", err=True)
49
+ raise typer.Exit(1)
50
+ result = _deserialize_result(json.loads(results_path.read_text()))
51
+ report_dir = results_dir.parent / "report"
52
+ report_dir.mkdir(parents=True, exist_ok=True)
53
+ report_path = report_dir / "org-health-report.html"
54
+ report_path.write_text(generate_report(result, brand=brand, prepared_by=prepared_by))
55
+ typer.echo(f"Report written to {report_path}")
@@ -0,0 +1,71 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+ from wxcli.config import resolve_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Calling org-settings.")
10
+
11
+
12
+ @app.command("show")
13
+ def show(
14
+ setting_key: str = typer.Argument(help="settingKey"),
15
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
16
+ debug: bool = typer.Option(False, "--debug"),
17
+ ):
18
+ """Get an Organization Setting."""
19
+ api = get_api(debug=debug)
20
+ org_id = resolve_org_id(api.session)
21
+ url = f"https://webexapis.com/v1/settings/organizations/{org_id}/settings/{setting_key}"
22
+ try:
23
+ result = api.session.rest_get(url)
24
+ except WebexError as e:
25
+ handle_rest_error(e)
26
+ if output == "json":
27
+ print_json(result)
28
+ else:
29
+ if isinstance(result, dict):
30
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
31
+ elif isinstance(result, list):
32
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
33
+ else:
34
+ print_json(result)
35
+
36
+
37
+
38
+ @app.command("create")
39
+ def create(
40
+ key: str = typer.Option(None, "--key", help="Key of the setting."),
41
+ value: bool = typer.Option(None, "--value/--no-value", help="Value of the setting."),
42
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
43
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
44
+ debug: bool = typer.Option(False, "--debug"),
45
+ ):
46
+ """Create or Update an Organization Setting."""
47
+ api = get_api(debug=debug)
48
+ org_id = resolve_org_id(api.session)
49
+ url = f"https://webexapis.com/v1/settings/organizations/{org_id}/settings"
50
+ if json_body:
51
+ body = json.loads(json_body)
52
+ else:
53
+ body = {}
54
+ if key is not None:
55
+ body["key"] = key
56
+ if value is not None:
57
+ body["value"] = value
58
+ try:
59
+ result = api.session.rest_post(url, json=body)
60
+ except WebexError as e:
61
+ handle_rest_error(e)
62
+ if output == "json":
63
+ print_json(result)
64
+ elif isinstance(result, dict) and "id" in result:
65
+ typer.echo(f"Created: {result['id']}")
66
+ elif not result or result == {}:
67
+ typer.echo("Created.")
68
+ else:
69
+ print_json(result)
70
+
71
+
@@ -0,0 +1,83 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+ from wxcli.config import resolve_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Calling organizations.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
15
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
16
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
17
+ debug: bool = typer.Option(False, "--debug"),
18
+ ):
19
+ """List Organizations."""
20
+ api = get_api(debug=debug)
21
+ url = f"https://webexapis.com/v1/organizations"
22
+ params = {}
23
+ if limit > 0:
24
+ params["max"] = limit
25
+ if offset > 0:
26
+ params["start"] = offset
27
+ result = None
28
+ try:
29
+ result = api.session.rest_get(url, params=params)
30
+ except WebexError as e:
31
+ handle_rest_error(e)
32
+ result = result or []
33
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
34
+ if output == "json":
35
+ print_json(items)
36
+ else:
37
+ print_table(items, columns=[('ID', 'id'), ('Display Name', 'displayName')], limit=limit)
38
+
39
+
40
+
41
+ @app.command("show")
42
+ def show(
43
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
44
+ debug: bool = typer.Option(False, "--debug"),
45
+ ):
46
+ """Get Organization Details."""
47
+ api = get_api(debug=debug)
48
+ org_id = resolve_org_id(api.session)
49
+ url = f"https://webexapis.com/v1/organizations/{org_id}"
50
+ try:
51
+ result = api.session.rest_get(url)
52
+ except WebexError as e:
53
+ handle_rest_error(e)
54
+ if output == "json":
55
+ print_json(result)
56
+ else:
57
+ if isinstance(result, dict):
58
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
59
+ elif isinstance(result, list):
60
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
61
+ else:
62
+ print_json(result)
63
+
64
+
65
+
66
+ @app.command("delete")
67
+ def delete(
68
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
69
+ debug: bool = typer.Option(False, "--debug"),
70
+ ):
71
+ """Delete Organization."""
72
+ if not force:
73
+ typer.confirm(f"Delete {org_id}?", abort=True)
74
+ api = get_api(debug=debug)
75
+ org_id = resolve_org_id(api.session)
76
+ url = f"https://webexapis.com/v1/organizations/{org_id}"
77
+ try:
78
+ api.session.rest_delete(url)
79
+ except WebexError as e:
80
+ handle_rest_error(e)
81
+ typer.echo(f"Deleted: {org_id}")
82
+
83
+