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,350 @@
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, get_cc_base_url, get_cc_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Contact Center cc-skill.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ filter_param: str = typer.Option(None, "--filter", help="Specify a filter based on which the results will be fetched."),
15
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
16
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
17
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
18
+ single_object_response: str = typer.Option(None, "--single-object-response", help="Specifiy whether to include array fields in the response, Th"),
19
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
20
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
21
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
22
+ debug: bool = typer.Option(False, "--debug"),
23
+ ):
24
+ """List Skill(s)."""
25
+ api = get_api(debug=debug)
26
+ cc_base_url = get_cc_base_url()
27
+ orgid = get_cc_org_id(api.session)
28
+ url = f"{cc_base_url}/organization/{orgid}/skill"
29
+ params = {}
30
+ if filter_param is not None:
31
+ params["filter"] = filter_param
32
+ if attributes is not None:
33
+ params["attributes"] = attributes
34
+ if page is not None:
35
+ params["page"] = page
36
+ if page_size is not None:
37
+ params["pageSize"] = page_size
38
+ if single_object_response is not None:
39
+ params["singleObjectResponse"] = single_object_response
40
+ if limit > 0:
41
+ params["max"] = limit
42
+ if offset > 0:
43
+ params["start"] = offset
44
+ result = None
45
+ try:
46
+ result = api.session.rest_get(url, params=params)
47
+ except WebexError as e:
48
+ handle_rest_error(e)
49
+ result = result or []
50
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
51
+ if output == "json":
52
+ print_json(items)
53
+ else:
54
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
55
+
56
+
57
+
58
+ @app.command("create")
59
+ def create(
60
+ payload_dto: str = typer.Option(..., "--payload-dto", help="Skill configuration data"),
61
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
62
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
63
+ debug: bool = typer.Option(False, "--debug"),
64
+ ):
65
+ """Create a new Skill."""
66
+ api = get_api(debug=debug)
67
+ cc_base_url = get_cc_base_url()
68
+ orgid = get_cc_org_id(api.session)
69
+ url = f"{cc_base_url}/organization/{orgid}/skill"
70
+ params = {}
71
+ if payload_dto is not None:
72
+ params["payloadDTO"] = payload_dto
73
+ if json_body:
74
+ body = json.loads(json_body)
75
+ else:
76
+ body = {}
77
+ try:
78
+ result = api.session.rest_post(url, json=body, params=params)
79
+ except WebexError as e:
80
+ handle_rest_error(e)
81
+ if output == "json":
82
+ print_json(result)
83
+ elif isinstance(result, dict) and "id" in result:
84
+ typer.echo(f"Created: {result['id']}")
85
+ elif not result or result == {}:
86
+ typer.echo("Created.")
87
+ else:
88
+ print_json(result)
89
+
90
+
91
+
92
+ @app.command("create-bulk")
93
+ def create_bulk(
94
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
95
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
96
+ debug: bool = typer.Option(False, "--debug"),
97
+ ):
98
+ """Bulk save Skill(s)\n\nExample --json-body:\n '{"items":[{"itemIdentifier":"...","item":"...","requestAction":"..."}]}'."""
99
+ api = get_api(debug=debug)
100
+ cc_base_url = get_cc_base_url()
101
+ orgid = get_cc_org_id(api.session)
102
+ url = f"{cc_base_url}/organization/{orgid}/skill/bulk"
103
+ if json_body:
104
+ body = json.loads(json_body)
105
+ else:
106
+ body = {}
107
+ try:
108
+ result = api.session.rest_post(url, json=body)
109
+ except WebexError as e:
110
+ handle_rest_error(e)
111
+ if output == "json":
112
+ print_json(result)
113
+ elif isinstance(result, dict) and "id" in result:
114
+ typer.echo(f"Created: {result['id']}")
115
+ elif not result or result == {}:
116
+ typer.echo("Created.")
117
+ else:
118
+ print_json(result)
119
+
120
+
121
+
122
+ @app.command("create-populate-json-attr")
123
+ def create_populate_json_attr(
124
+ id: str = typer.Argument(help="id"),
125
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
126
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
127
+ debug: bool = typer.Option(False, "--debug"),
128
+ ):
129
+ """Populate json-attributes field for a given skill-id of an organization."""
130
+ api = get_api(debug=debug)
131
+ cc_base_url = get_cc_base_url()
132
+ orgid = get_cc_org_id(api.session)
133
+ url = f"{cc_base_url}/organization/{orgid}/skill/populate-json-attr/{id}"
134
+ if json_body:
135
+ body = json.loads(json_body)
136
+ else:
137
+ body = {}
138
+ try:
139
+ result = api.session.rest_post(url, json=body)
140
+ except WebexError as e:
141
+ handle_rest_error(e)
142
+ if output == "json":
143
+ print_json(result)
144
+ elif isinstance(result, dict) and "id" in result:
145
+ typer.echo(f"Created: {result['id']}")
146
+ elif not result or result == {}:
147
+ typer.echo("Created.")
148
+ else:
149
+ print_json(result)
150
+
151
+
152
+
153
+ @app.command("create-purge-inactive-entities")
154
+ def create_purge_inactive_entities(
155
+ next_start_id: str = typer.Option(None, "--next-start-id", help="This is the entity ID from which items for the next purge ba"),
156
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
157
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
158
+ debug: bool = typer.Option(False, "--debug"),
159
+ ):
160
+ """Purge inactive Skill(s)."""
161
+ api = get_api(debug=debug)
162
+ cc_base_url = get_cc_base_url()
163
+ orgid = get_cc_org_id(api.session)
164
+ url = f"{cc_base_url}/organization/{orgid}/skill/purge-inactive-entities"
165
+ params = {}
166
+ if next_start_id is not None:
167
+ params["nextStartId"] = next_start_id
168
+ if json_body:
169
+ body = json.loads(json_body)
170
+ else:
171
+ body = {}
172
+ try:
173
+ result = api.session.rest_post(url, json=body, params=params)
174
+ except WebexError as e:
175
+ handle_rest_error(e)
176
+ if output == "json":
177
+ print_json(result)
178
+ elif isinstance(result, dict) and "id" in result:
179
+ typer.echo(f"Created: {result['id']}")
180
+ elif not result or result == {}:
181
+ typer.echo("Created.")
182
+ else:
183
+ print_json(result)
184
+
185
+
186
+
187
+ @app.command("show")
188
+ def show(
189
+ id: str = typer.Argument(help="id"),
190
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
191
+ debug: bool = typer.Option(False, "--debug"),
192
+ ):
193
+ """Get specific Skill by ID."""
194
+ api = get_api(debug=debug)
195
+ cc_base_url = get_cc_base_url()
196
+ orgid = get_cc_org_id(api.session)
197
+ url = f"{cc_base_url}/organization/{orgid}/skill/{id}"
198
+ try:
199
+ result = api.session.rest_get(url)
200
+ except WebexError as e:
201
+ handle_rest_error(e)
202
+ if output == "json":
203
+ print_json(result)
204
+ else:
205
+ if isinstance(result, dict):
206
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
207
+ elif isinstance(result, list):
208
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
209
+ else:
210
+ print_json(result)
211
+
212
+
213
+
214
+ @app.command("update")
215
+ def update(
216
+ id: str = typer.Argument(help="id"),
217
+ payload_dto: str = typer.Option(..., "--payload-dto", help="Skill configuration data for update"),
218
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
219
+ debug: bool = typer.Option(False, "--debug"),
220
+ ):
221
+ """Update specific Skill by ID."""
222
+ api = get_api(debug=debug)
223
+ cc_base_url = get_cc_base_url()
224
+ orgid = get_cc_org_id(api.session)
225
+ url = f"{cc_base_url}/organization/{orgid}/skill/{id}"
226
+ params = {}
227
+ if payload_dto is not None:
228
+ params["payloadDTO"] = payload_dto
229
+ if json_body:
230
+ body = json.loads(json_body)
231
+ else:
232
+ body = {}
233
+ try:
234
+ result = api.session.rest_put(url, json=body, params=params)
235
+ except WebexError as e:
236
+ handle_rest_error(e)
237
+ typer.echo(f"Updated.")
238
+
239
+
240
+
241
+ @app.command("delete")
242
+ def delete(
243
+ id: str = typer.Argument(help="id"),
244
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
245
+ debug: bool = typer.Option(False, "--debug"),
246
+ ):
247
+ """Delete specific Skill by ID."""
248
+ if not force:
249
+ typer.confirm(f"Delete {id}?", abort=True)
250
+ api = get_api(debug=debug)
251
+ cc_base_url = get_cc_base_url()
252
+ orgid = get_cc_org_id(api.session)
253
+ url = f"{cc_base_url}/organization/{orgid}/skill/{id}"
254
+ try:
255
+ api.session.rest_delete(url)
256
+ except WebexError as e:
257
+ handle_rest_error(e)
258
+ typer.echo(f"Deleted: {id}")
259
+
260
+
261
+
262
+ @app.command("list-incoming-references")
263
+ def list_incoming_references(
264
+ id: str = typer.Argument(help="id"),
265
+ type_param: str = typer.Option(None, "--type", help="Entity type of the other entity that has a reference to this"),
266
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
267
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
268
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
269
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
270
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
271
+ debug: bool = typer.Option(False, "--debug"),
272
+ ):
273
+ """List references for a specific Skill."""
274
+ api = get_api(debug=debug)
275
+ cc_base_url = get_cc_base_url()
276
+ orgid = get_cc_org_id(api.session)
277
+ url = f"{cc_base_url}/organization/{orgid}/skill/{id}/incoming-references"
278
+ params = {}
279
+ if type_param is not None:
280
+ params["type"] = type_param
281
+ if page is not None:
282
+ params["page"] = page
283
+ if page_size is not None:
284
+ params["pageSize"] = page_size
285
+ if limit > 0:
286
+ params["max"] = limit
287
+ if offset > 0:
288
+ params["start"] = offset
289
+ result = None
290
+ try:
291
+ result = api.session.rest_get(url, params=params)
292
+ except WebexError as e:
293
+ handle_rest_error(e)
294
+ result = result or []
295
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
296
+ if output == "json":
297
+ print_json(items)
298
+ else:
299
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
300
+
301
+
302
+
303
+ @app.command("list-skill")
304
+ def list_skill(
305
+ filter_param: str = typer.Option(None, "--filter", help="Specify a filter based on which the results will be fetched."),
306
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
307
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
308
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
309
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
310
+ single_object_response: str = typer.Option(None, "--single-object-response", help="Specifiy whether to include array fields in the response, Th"),
311
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
312
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
313
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
314
+ debug: bool = typer.Option(False, "--debug"),
315
+ ):
316
+ """List Skill(s)."""
317
+ api = get_api(debug=debug)
318
+ cc_base_url = get_cc_base_url()
319
+ orgid = get_cc_org_id(api.session)
320
+ url = f"{cc_base_url}/organization/{orgid}/v2/skill"
321
+ params = {}
322
+ if filter_param is not None:
323
+ params["filter"] = filter_param
324
+ if attributes is not None:
325
+ params["attributes"] = attributes
326
+ if search is not None:
327
+ params["search"] = search
328
+ if page is not None:
329
+ params["page"] = page
330
+ if page_size is not None:
331
+ params["pageSize"] = page_size
332
+ if single_object_response is not None:
333
+ params["singleObjectResponse"] = single_object_response
334
+ if limit > 0:
335
+ params["max"] = limit
336
+ if offset > 0:
337
+ params["start"] = offset
338
+ result = None
339
+ try:
340
+ result = api.session.rest_get(url, params=params)
341
+ except WebexError as e:
342
+ handle_rest_error(e)
343
+ result = result or []
344
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
345
+ if output == "json":
346
+ print_json(items)
347
+ else:
348
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
349
+
350
+
@@ -0,0 +1,289 @@
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, get_cc_base_url, get_cc_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Contact Center cc-skill-profile.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ filter_param: str = typer.Option(None, "--filter", help="Specify a filter based on which the results will be fetched."),
15
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
16
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
17
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
18
+ single_object_response: str = typer.Option(None, "--single-object-response", help="Specifiy whether to include array fields in the response, Th"),
19
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
20
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
21
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
22
+ debug: bool = typer.Option(False, "--debug"),
23
+ ):
24
+ """List Skill Profile(s)."""
25
+ api = get_api(debug=debug)
26
+ cc_base_url = get_cc_base_url()
27
+ orgid = get_cc_org_id(api.session)
28
+ url = f"{cc_base_url}/organization/{orgid}/skill-profile"
29
+ params = {}
30
+ if filter_param is not None:
31
+ params["filter"] = filter_param
32
+ if attributes is not None:
33
+ params["attributes"] = attributes
34
+ if page is not None:
35
+ params["page"] = page
36
+ if page_size is not None:
37
+ params["pageSize"] = page_size
38
+ if single_object_response is not None:
39
+ params["singleObjectResponse"] = single_object_response
40
+ if limit > 0:
41
+ params["max"] = limit
42
+ if offset > 0:
43
+ params["start"] = offset
44
+ result = None
45
+ try:
46
+ result = api.session.rest_get(url, params=params)
47
+ except WebexError as e:
48
+ handle_rest_error(e)
49
+ result = result or []
50
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
51
+ if output == "json":
52
+ print_json(items)
53
+ else:
54
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
55
+
56
+
57
+
58
+ @app.command("create")
59
+ def create(
60
+ skill_profile_dto: str = typer.Option(..., "--skill-profile-dto", help="Skill profile configuration data"),
61
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
62
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
63
+ debug: bool = typer.Option(False, "--debug"),
64
+ ):
65
+ """Create a new Skill Profile."""
66
+ api = get_api(debug=debug)
67
+ cc_base_url = get_cc_base_url()
68
+ orgid = get_cc_org_id(api.session)
69
+ url = f"{cc_base_url}/organization/{orgid}/skill-profile"
70
+ params = {}
71
+ if skill_profile_dto is not None:
72
+ params["skillProfileDTO"] = skill_profile_dto
73
+ if json_body:
74
+ body = json.loads(json_body)
75
+ else:
76
+ body = {}
77
+ try:
78
+ result = api.session.rest_post(url, json=body, params=params)
79
+ except WebexError as e:
80
+ handle_rest_error(e)
81
+ if output == "json":
82
+ print_json(result)
83
+ elif isinstance(result, dict) and "id" in result:
84
+ typer.echo(f"Created: {result['id']}")
85
+ elif not result or result == {}:
86
+ typer.echo("Created.")
87
+ else:
88
+ print_json(result)
89
+
90
+
91
+
92
+ @app.command("create-bulk")
93
+ def create_bulk(
94
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
95
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
96
+ debug: bool = typer.Option(False, "--debug"),
97
+ ):
98
+ """Bulk save Skill Profile(s)\n\nExample --json-body:\n '{"items":[{"itemIdentifier":"...","item":"...","requestAction":"..."}]}'."""
99
+ api = get_api(debug=debug)
100
+ cc_base_url = get_cc_base_url()
101
+ orgid = get_cc_org_id(api.session)
102
+ url = f"{cc_base_url}/organization/{orgid}/skill-profile/bulk"
103
+ if json_body:
104
+ body = json.loads(json_body)
105
+ else:
106
+ body = {}
107
+ try:
108
+ result = api.session.rest_post(url, json=body)
109
+ except WebexError as e:
110
+ handle_rest_error(e)
111
+ if output == "json":
112
+ print_json(result)
113
+ elif isinstance(result, dict) and "id" in result:
114
+ typer.echo(f"Created: {result['id']}")
115
+ elif not result or result == {}:
116
+ typer.echo("Created.")
117
+ else:
118
+ print_json(result)
119
+
120
+
121
+
122
+ @app.command("show")
123
+ def show(
124
+ id: str = typer.Argument(help="id"),
125
+ include_skill_details: str = typer.Option(None, "--include-skill-details", help="If set to true returns skill details"),
126
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
127
+ debug: bool = typer.Option(False, "--debug"),
128
+ ):
129
+ """Get specific Skill Profile by ID."""
130
+ api = get_api(debug=debug)
131
+ cc_base_url = get_cc_base_url()
132
+ orgid = get_cc_org_id(api.session)
133
+ url = f"{cc_base_url}/organization/{orgid}/skill-profile/{id}"
134
+ params = {}
135
+ if include_skill_details is not None:
136
+ params["includeSkillDetails"] = include_skill_details
137
+ try:
138
+ result = api.session.rest_get(url, params=params)
139
+ except WebexError as e:
140
+ handle_rest_error(e)
141
+ if output == "json":
142
+ print_json(result)
143
+ else:
144
+ if isinstance(result, dict):
145
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
146
+ elif isinstance(result, list):
147
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
148
+ else:
149
+ print_json(result)
150
+
151
+
152
+
153
+ @app.command("update")
154
+ def update(
155
+ id: str = typer.Argument(help="id"),
156
+ skill_profile_dto: str = typer.Option(..., "--skill-profile-dto", help="Skill profile configuration data for update"),
157
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
158
+ debug: bool = typer.Option(False, "--debug"),
159
+ ):
160
+ """Update specific Skill Profile by ID."""
161
+ api = get_api(debug=debug)
162
+ cc_base_url = get_cc_base_url()
163
+ orgid = get_cc_org_id(api.session)
164
+ url = f"{cc_base_url}/organization/{orgid}/skill-profile/{id}"
165
+ params = {}
166
+ if skill_profile_dto is not None:
167
+ params["skillProfileDTO"] = skill_profile_dto
168
+ if json_body:
169
+ body = json.loads(json_body)
170
+ else:
171
+ body = {}
172
+ try:
173
+ result = api.session.rest_put(url, json=body, params=params)
174
+ except WebexError as e:
175
+ handle_rest_error(e)
176
+ typer.echo(f"Updated.")
177
+
178
+
179
+
180
+ @app.command("delete")
181
+ def delete(
182
+ id: str = typer.Argument(help="id"),
183
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
184
+ debug: bool = typer.Option(False, "--debug"),
185
+ ):
186
+ """Delete specific Skill Profile by ID."""
187
+ if not force:
188
+ typer.confirm(f"Delete {id}?", abort=True)
189
+ api = get_api(debug=debug)
190
+ cc_base_url = get_cc_base_url()
191
+ orgid = get_cc_org_id(api.session)
192
+ url = f"{cc_base_url}/organization/{orgid}/skill-profile/{id}"
193
+ try:
194
+ api.session.rest_delete(url)
195
+ except WebexError as e:
196
+ handle_rest_error(e)
197
+ typer.echo(f"Deleted: {id}")
198
+
199
+
200
+
201
+ @app.command("list-incoming-references")
202
+ def list_incoming_references(
203
+ id: str = typer.Argument(help="id"),
204
+ type_param: str = typer.Option(None, "--type", help="Entity type of the other entity that has a reference to this"),
205
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
206
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
207
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
208
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
209
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
210
+ debug: bool = typer.Option(False, "--debug"),
211
+ ):
212
+ """List references for a specific Skill Profile."""
213
+ api = get_api(debug=debug)
214
+ cc_base_url = get_cc_base_url()
215
+ orgid = get_cc_org_id(api.session)
216
+ url = f"{cc_base_url}/organization/{orgid}/skill-profile/{id}/incoming-references"
217
+ params = {}
218
+ if type_param is not None:
219
+ params["type"] = type_param
220
+ if page is not None:
221
+ params["page"] = page
222
+ if page_size is not None:
223
+ params["pageSize"] = page_size
224
+ if limit > 0:
225
+ params["max"] = limit
226
+ if offset > 0:
227
+ params["start"] = offset
228
+ result = None
229
+ try:
230
+ result = api.session.rest_get(url, params=params)
231
+ except WebexError as e:
232
+ handle_rest_error(e)
233
+ result = result or []
234
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
235
+ if output == "json":
236
+ print_json(items)
237
+ else:
238
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
239
+
240
+
241
+
242
+ @app.command("list-skill-profile")
243
+ def list_skill_profile(
244
+ filter_param: str = typer.Option(None, "--filter", help="Specify a filter based on which the results will be fetched."),
245
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
246
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
247
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
248
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
249
+ single_object_response: str = typer.Option(None, "--single-object-response", help="Specifiy whether to include array fields in the response, Th"),
250
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
251
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
252
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
253
+ debug: bool = typer.Option(False, "--debug"),
254
+ ):
255
+ """List Skill Profile(s)."""
256
+ api = get_api(debug=debug)
257
+ cc_base_url = get_cc_base_url()
258
+ orgid = get_cc_org_id(api.session)
259
+ url = f"{cc_base_url}/organization/{orgid}/v2/skill-profile"
260
+ params = {}
261
+ if filter_param is not None:
262
+ params["filter"] = filter_param
263
+ if attributes is not None:
264
+ params["attributes"] = attributes
265
+ if search is not None:
266
+ params["search"] = search
267
+ if page is not None:
268
+ params["page"] = page
269
+ if page_size is not None:
270
+ params["pageSize"] = page_size
271
+ if single_object_response is not None:
272
+ params["singleObjectResponse"] = single_object_response
273
+ if limit > 0:
274
+ params["max"] = limit
275
+ if offset > 0:
276
+ params["start"] = offset
277
+ result = None
278
+ try:
279
+ result = api.session.rest_get(url, params=params)
280
+ except WebexError as e:
281
+ handle_rest_error(e)
282
+ result = result or []
283
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
284
+ if output == "json":
285
+ print_json(items)
286
+ else:
287
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
288
+
289
+