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,90 @@
1
+ """Base extractor class and ExtractionResult.
2
+
3
+ All AXL extractors (§2.1-2.6 of 02b) inherit from BaseExtractor.
4
+
5
+ Sources:
6
+ - 02b-cucm-extraction.md §3 (base extractor class, ExtractionResult)
7
+ - 02b-cucm-extraction.md §1 (error handling strategy)
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import logging
13
+ from abc import ABC, abstractmethod
14
+ from dataclasses import dataclass, field
15
+ from typing import Any
16
+
17
+ from wxcli.migration.cucm.connection import AXLConnection
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ @dataclass
23
+ class ExtractionResult:
24
+ """Summary of one extractor's run.
25
+
26
+ (from 02b §3)
27
+ """
28
+
29
+ extractor: str
30
+ total: int = 0
31
+ failed: int = 0
32
+ errors: list[str] = field(default_factory=list)
33
+
34
+ @property
35
+ def success_count(self) -> int:
36
+ return self.total - self.failed
37
+
38
+
39
+ class ExtractionError(Exception):
40
+ """Raised when an extractor encounters an unrecoverable error.
41
+
42
+ (from 02b §1: error handling)
43
+ """
44
+
45
+ def __init__(self, extractor: str, method: str, message: str) -> None:
46
+ self.extractor = extractor
47
+ self.method = method
48
+ super().__init__(f"[{extractor}] {method}: {message}")
49
+
50
+
51
+ class BaseExtractor(ABC):
52
+ """Base class for all CUCM AXL extractors.
53
+
54
+ (from 02b §3)
55
+ """
56
+
57
+ name: str = ""
58
+ page_size: int = 200 # Default AXL page size (from cucm-wxc-migration.md line 307)
59
+
60
+ def __init__(self, connection: AXLConnection) -> None:
61
+ self.conn = connection
62
+
63
+ @abstractmethod
64
+ def extract(self) -> ExtractionResult:
65
+ """Run extraction. Returns count of objects extracted and any errors."""
66
+ ...
67
+
68
+ def paginated_list(
69
+ self,
70
+ method_name: str,
71
+ search_criteria: dict[str, str],
72
+ returned_tags: dict[str, str],
73
+ page_size: int | None = None,
74
+ ) -> list[dict[str, Any]]:
75
+ """Generic paginated AXL list operation.
76
+
77
+ Uses first/skip pagination (from cucm-wxc-migration.md line 307).
78
+ (from 02b §3)
79
+ """
80
+ effective_page_size = page_size or self.page_size
81
+ return self.conn.paginated_list(
82
+ method_name, search_criteria, returned_tags, effective_page_size
83
+ )
84
+
85
+ def get_detail(self, method_name: str, **kwargs: Any) -> dict[str, Any] | None:
86
+ """Single-object get operation (e.g. getPhone by name or UUID).
87
+
88
+ (from 02b §3)
89
+ """
90
+ return self.conn.get_detail(method_name, **kwargs)
@@ -0,0 +1,98 @@
1
+ """Device Profile extractor for CUCM AXL.
2
+
3
+ Pulls Extension Mobility Device Profiles from CUCM.
4
+
5
+ Sources:
6
+ - tier2-enterprise-expansion.md §5 (Extension Mobility extraction)
7
+ - AXL WSDL: listDeviceProfile / getDeviceProfile
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import logging
13
+ from typing import Any
14
+
15
+ from wxcli.migration.cucm.extractors.base import BaseExtractor, ExtractionResult
16
+ from wxcli.migration.cucm.extractors.helpers import to_list
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ DEVICE_PROFILE_LIST_RETURNED_TAGS = {
21
+ "name": "",
22
+ "product": "",
23
+ "protocol": "",
24
+ "class": "",
25
+ "phoneTemplateName": "",
26
+ }
27
+
28
+
29
+ class DeviceProfileExtractor(BaseExtractor):
30
+ """Extract Extension Mobility Device Profiles from CUCM AXL.
31
+
32
+ Device Profiles are virtual phone configurations that users log into.
33
+ When a user logs into a physical phone, the device profile's lines/settings
34
+ replace the phone's default config.
35
+
36
+ (from tier2-enterprise-expansion.md §5)
37
+ """
38
+
39
+ name = "device_profiles"
40
+
41
+ def __init__(self, connection) -> None:
42
+ super().__init__(connection)
43
+ self.results: dict[str, list[dict[str, Any]]] = {}
44
+
45
+ def extract(self) -> ExtractionResult:
46
+ result = ExtractionResult(extractor=self.name)
47
+ self.results["device_profiles"] = self._extract_device_profiles(result)
48
+ return result
49
+
50
+ def _extract_device_profiles(
51
+ self, result: ExtractionResult
52
+ ) -> list[dict[str, Any]]:
53
+ """List all device profiles, then get full detail for each."""
54
+ profiles: list[dict[str, Any]] = []
55
+ try:
56
+ summaries = self.paginated_list(
57
+ "listDeviceProfile",
58
+ {"name": "%"},
59
+ DEVICE_PROFILE_LIST_RETURNED_TAGS,
60
+ )
61
+ except Exception as exc:
62
+ msg = f"listDeviceProfile failed: {exc}"
63
+ logger.error("[%s] %s", self.name, msg)
64
+ result.errors.append(msg)
65
+ return profiles
66
+
67
+ for summary in summaries:
68
+ result.total += 1
69
+ profile_name = summary.get("name", "")
70
+ if not profile_name:
71
+ result.failed += 1
72
+ continue
73
+ try:
74
+ detail = self.get_detail("getDeviceProfile", name=profile_name)
75
+ except Exception as exc:
76
+ logger.warning(
77
+ "[%s] getDeviceProfile error for %s: %s",
78
+ self.name, profile_name, exc,
79
+ )
80
+ profiles.append(summary)
81
+ continue
82
+ if detail is None:
83
+ profiles.append(summary)
84
+ continue
85
+
86
+ # Normalize lines
87
+ lines_raw = detail.get("lines") or {}
88
+ detail["lines"] = to_list(lines_raw, "line")
89
+
90
+ # Count speed dials and BLF entries
91
+ sd_raw = detail.get("speeddials") or {}
92
+ detail["speeddials"] = to_list(sd_raw, "speeddial")
93
+ blf_raw = detail.get("busyLampFields") or {}
94
+ detail["busyLampFields"] = to_list(blf_raw, "busyLampField")
95
+
96
+ profiles.append(detail)
97
+
98
+ return profiles
@@ -0,0 +1,193 @@
1
+ """Device extractor — phones with line appearances.
2
+
3
+ Two-step extraction: listPhone discovers devices, then getPhone fetches
4
+ full detail including nested line/speed-dial data per device.
5
+
6
+ Sources:
7
+ - 02b-cucm-extraction.md §2.3 (device extraction, line appearances)
8
+ - 02b-cucm-extraction.md §3 (base extractor, pagination)
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import logging
14
+ from typing import Any
15
+
16
+ from rich.console import Console
17
+
18
+ from wxcli.migration.cucm.connection import AXLConnection
19
+ from wxcli.migration.cucm.extractors.base import BaseExtractor, ExtractionResult
20
+ from wxcli.migration.cucm.extractors.helpers import ref_value, to_list
21
+
22
+ logger = logging.getLogger(__name__)
23
+ console = Console()
24
+
25
+ # Step 1: listPhone — lightweight discovery
26
+ PHONE_LIST_RETURNED_TAGS = {
27
+ 'name': '', 'model': '', 'ownerUserName': '', 'devicePoolName': '',
28
+ 'protocol': '', 'description': '',
29
+ }
30
+
31
+ # Step 2: getPhone — full detail per device
32
+ PHONE_GET_RETURNED_TAGS = {
33
+ 'name': '', 'model': '', 'description': '', 'ownerUserName': '',
34
+ 'devicePoolName': '', 'protocol': '', 'callingSearchSpaceName': '',
35
+ 'phoneTemplateName': '', 'softkeyTemplateName': '', 'deviceMobilityMode': '',
36
+ 'product': '', 'class': '', 'lines': '',
37
+ 'speeddials': '', 'busyLampFields': '',
38
+ # Device settings fields (for DeviceSettingsMapper)
39
+ 'commonPhoneConfigName': '', 'productSpecificConfiguration': '',
40
+ 'userLocale': '', 'networkLocale': '',
41
+ 'dndOption': '', 'dndStatus': '', 'enableExtensionMobility': '',
42
+ }
43
+
44
+
45
+ class DeviceExtractor(BaseExtractor):
46
+ """Extract phones and their line appearances from CUCM.
47
+
48
+ (from 02b §2.3)
49
+ """
50
+
51
+ name = "devices"
52
+
53
+ def __init__(self, connection: AXLConnection) -> None:
54
+ super().__init__(connection)
55
+ self.results: dict[str, list[dict[str, Any]]] = {}
56
+
57
+ def extract(self) -> ExtractionResult:
58
+ """Run two-step phone extraction.
59
+
60
+ Step 1: listPhone with pagination to discover all devices.
61
+ Step 2: getPhone per device for full line appearance data.
62
+ """
63
+ result = ExtractionResult(extractor=self.name)
64
+
65
+ # Step 1: discover all phones
66
+ logger.info("[%s] Listing phones...", self.name)
67
+ try:
68
+ phone_summaries = self.paginated_list(
69
+ method_name="listPhone",
70
+ search_criteria={"name": "%"},
71
+ returned_tags=PHONE_LIST_RETURNED_TAGS,
72
+ )
73
+ except Exception as exc:
74
+ msg = f"listPhone failed: {exc}"
75
+ logger.error("[%s] %s", self.name, msg)
76
+ result.errors.append(msg)
77
+ self.results["phones"] = []
78
+ return result
79
+ logger.info("[%s] Found %d phones", self.name, len(phone_summaries))
80
+ result.total = len(phone_summaries)
81
+
82
+ # Step 2: get full detail per phone
83
+ phones: list[dict[str, Any]] = []
84
+ total = len(phone_summaries)
85
+ for i, summary in enumerate(phone_summaries, 1):
86
+ if i % 200 == 0:
87
+ console.print(f" phones: {i}/{total}...")
88
+ phone_name = ref_value(summary.get("name")) or summary.get("name")
89
+ if not phone_name:
90
+ result.failed += 1
91
+ result.errors.append("Phone with no name in listPhone result")
92
+ continue
93
+
94
+ detail = self._get_phone_detail(phone_name)
95
+ if detail is None:
96
+ result.failed += 1
97
+ result.errors.append(f"getPhone failed for {phone_name}")
98
+ continue
99
+
100
+ phones.append(detail)
101
+
102
+ self.results["phones"] = phones
103
+ logger.info(
104
+ "[%s] Extracted %d/%d phones (%d failed)",
105
+ self.name, result.success_count, result.total, result.failed,
106
+ )
107
+ return result
108
+
109
+ def _get_phone_detail(self, phone_name: str) -> dict[str, Any] | None:
110
+ """Fetch full phone detail and normalize line appearances.
111
+
112
+ Handles edge cases:
113
+ - lines may be empty dict or None
114
+ - lines.line may be a single dict, not a list
115
+ - Speed dials are interleaved with lines — filter to entries with ``dirn``
116
+ """
117
+ try:
118
+ detail = self.get_detail("getPhone", name=phone_name)
119
+ except Exception as exc:
120
+ logger.warning("[%s] getPhone error for %s: %s", self.name, phone_name, exc)
121
+ return None
122
+
123
+ if detail is None:
124
+ return None
125
+
126
+ # Normalize lines — may be None, empty dict, or populated
127
+ raw_lines = detail.get("lines")
128
+ line_entries = to_list(raw_lines, "line")
129
+
130
+ # Filter: only entries with a ``dirn`` key are real line appearances.
131
+ # Speed dial entries are interleaved but lack ``dirn``.
132
+ line_appearances = []
133
+ for entry in line_entries:
134
+ if not isinstance(entry, dict):
135
+ continue
136
+ if entry.get("dirn") is not None:
137
+ line_appearances.append(entry)
138
+
139
+ detail["lines"] = line_appearances
140
+
141
+ # Enrich each line with call forwarding settings from getLine.
142
+ # getPhone line entries do NOT include callForwardAll/Busy/NoAnswer —
143
+ # those are only on the Line AXL object. The voicemail_mapper needs
144
+ # these to determine sendAllCalls/sendBusyCalls/sendUnansweredCalls.
145
+ # Verified against live CUCM 15.0 (2026-03-23): getLine response
146
+ # includes callForwardAll, callForwardBusy, callForwardNoAnswer with
147
+ # forwardToVoiceMail, destination, and duration fields.
148
+ for line_entry in line_appearances:
149
+ dirn = line_entry.get("dirn")
150
+ if not isinstance(dirn, dict):
151
+ continue
152
+ pattern = dirn.get("pattern")
153
+ partition = ref_value(dirn.get("routePartitionName"))
154
+ if not pattern:
155
+ continue
156
+ self._enrich_line_with_forwarding(line_entry, pattern, partition)
157
+
158
+ return detail
159
+
160
+ def _enrich_line_with_forwarding(
161
+ self, line_entry: dict[str, Any], pattern: str, partition: str | None,
162
+ ) -> None:
163
+ """Fetch getLine for a DN and merge call forwarding settings into the line entry."""
164
+ try:
165
+ kwargs: dict[str, Any] = {"pattern": pattern}
166
+ if partition:
167
+ kwargs["routePartitionName"] = partition
168
+ line_detail = self.get_detail("getLine", **kwargs)
169
+ except Exception as exc:
170
+ logger.debug(
171
+ "[%s] getLine(%s/%s) failed: %s", self.name, pattern, partition, exc,
172
+ )
173
+ return
174
+ if line_detail is None:
175
+ return
176
+ # Merge forwarding fields into the line entry
177
+ for fwd_key in (
178
+ "callForwardAll", "callForwardBusy", "callForwardBusyInt",
179
+ "callForwardNoAnswer", "callForwardNoAnswerInt",
180
+ "callForwardNoCoverage", "callForwardNoCoverageInt",
181
+ "callForwardNotRegistered", "callForwardNotRegisteredInt",
182
+ "callForwardOnFailure",
183
+ ):
184
+ if fwd_key in line_detail:
185
+ line_entry[fwd_key] = line_detail[fwd_key]
186
+ # Also grab voiceMailProfileName if present on the Line
187
+ if "voiceMailProfileName" in line_detail:
188
+ line_entry["voiceMailProfileName"] = line_detail["voiceMailProfileName"]
189
+ # Grab recording fields if present on the Line
190
+ if "recordingProfileName" in line_detail:
191
+ line_entry["recordingProfileName"] = line_detail["recordingProfileName"]
192
+ if "recordingFlag" in line_detail:
193
+ line_entry["recordingFlag"] = line_detail["recordingFlag"]
@@ -0,0 +1,103 @@
1
+ """E911 extractor for CUCM AXL.
2
+
3
+ Pulls ELIN groups and geographic locations from CUCM for E911 advisory.
4
+
5
+ Sources:
6
+ - tier2-enterprise-expansion.md §6 (E911/ELIN extraction)
7
+ - AXL WSDL: listElinGroup / getElinGroup, listGeoLocation / getGeoLocation
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import logging
13
+ from typing import Any
14
+
15
+ from wxcli.migration.cucm.extractors.base import BaseExtractor, ExtractionResult
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ ELIN_GROUP_LIST_RETURNED_TAGS = {
20
+ "name": "",
21
+ "elinNumbers": "",
22
+ }
23
+
24
+ GEO_LOCATION_LIST_RETURNED_TAGS = {
25
+ "name": "",
26
+ "description": "",
27
+ "country": "",
28
+ }
29
+
30
+
31
+ class E911Extractor(BaseExtractor):
32
+ """Extract E911 ELIN groups and geographic locations from CUCM AXL.
33
+
34
+ ELIN groups define E.164 numbers reserved for E911 callback.
35
+ Geographic locations define E911 routing by country/region.
36
+ CER (Cisco Emergency Responder) is out of scope — it has its own DB.
37
+
38
+ (from tier2-enterprise-expansion.md §6)
39
+ """
40
+
41
+ name = "e911"
42
+
43
+ def __init__(self, connection) -> None:
44
+ super().__init__(connection)
45
+ self.results: dict[str, list[dict[str, Any]]] = {}
46
+
47
+ def extract(self) -> ExtractionResult:
48
+ result = ExtractionResult(extractor=self.name)
49
+ self.results["elin_groups"] = self._extract_elin_groups(result)
50
+ self.results["geo_locations"] = self._extract_geo_locations(result)
51
+ return result
52
+
53
+ def _extract_elin_groups(self, result: ExtractionResult) -> list[dict[str, Any]]:
54
+ """List all ELIN groups."""
55
+ groups: list[dict[str, Any]] = []
56
+ try:
57
+ summaries = self.paginated_list(
58
+ "listElinGroup",
59
+ {"name": "%"},
60
+ ELIN_GROUP_LIST_RETURNED_TAGS,
61
+ )
62
+ except Exception as exc:
63
+ msg = f"listElinGroup failed: {exc}"
64
+ logger.error("[%s] %s", self.name, msg)
65
+ result.errors.append(msg)
66
+ return groups
67
+
68
+ for summary in summaries:
69
+ result.total += 1
70
+ name = summary.get("name", "")
71
+ if not name:
72
+ result.failed += 1
73
+ continue
74
+ try:
75
+ detail = self.get_detail("getElinGroup", name=name)
76
+ except Exception as exc:
77
+ logger.warning("[%s] getElinGroup error for %s: %s", self.name, name, exc)
78
+ groups.append(summary)
79
+ continue
80
+ if detail is None:
81
+ groups.append(summary)
82
+ continue
83
+ groups.append({**summary, **detail})
84
+
85
+ return groups
86
+
87
+ def _extract_geo_locations(self, result: ExtractionResult) -> list[dict[str, Any]]:
88
+ """List all geographic locations."""
89
+ locations: list[dict[str, Any]] = []
90
+ try:
91
+ summaries = self.paginated_list(
92
+ "listGeoLocation",
93
+ {"name": "%"},
94
+ GEO_LOCATION_LIST_RETURNED_TAGS,
95
+ )
96
+ locations.extend(summaries)
97
+ result.total += len(summaries)
98
+ except Exception as exc:
99
+ msg = f"listGeoLocation failed: {exc}"
100
+ logger.error("[%s] %s", self.name, msg)
101
+ result.errors.append(msg)
102
+
103
+ return locations