@uipath/skills 1.197.2 → 1.198.0

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 (144) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CODEOWNERS +18 -11
  4. package/README.md +1 -0
  5. package/assets/skill-status.json +8 -0
  6. package/hooks/hooks.json +44 -8
  7. package/hooks/send-telemetry.ps1 +392 -0
  8. package/hooks/send-telemetry.sh +118 -86
  9. package/hooks/set-session-env.ps1 +72 -0
  10. package/hooks/set-session-env.sh +64 -0
  11. package/hooks/suggest-permissions.ps1 +45 -0
  12. package/hooks/suggest-permissions.sh +4 -0
  13. package/package.json +1 -1
  14. package/skills/uipath-admin/references/audit-commands.md +2 -2
  15. package/skills/uipath-admin/references/audit-workflow-guide.md +4 -4
  16. package/skills/uipath-agents/references/coded/capabilities/batch-transform/planning.md +1 -1
  17. package/skills/uipath-agents/references/coded/capabilities/deeprag/planning.md +1 -1
  18. package/skills/uipath-agents/references/coded/capabilities/guardrails/guardrails-recommend.md +5 -2
  19. package/skills/uipath-agents/references/coded/capabilities/guardrails/guardrails.md +8 -4
  20. package/skills/uipath-agents/references/coded/embedding-in-flows.md +1 -1
  21. package/skills/uipath-agents/references/coded/flow-integration.md +2 -2
  22. package/skills/uipath-agents/references/coded/lifecycle/build.md +0 -1
  23. package/skills/uipath-agents/references/coded/lifecycle/setup.md +0 -1
  24. package/skills/uipath-agents/references/coded/quickstart.md +1 -1
  25. package/skills/uipath-agents/references/lowcode/agent-definition.md +24 -5
  26. package/skills/uipath-agents/references/lowcode/capabilities/built-in-tools/batch-transform/planning.md +1 -1
  27. package/skills/uipath-agents/references/lowcode/capabilities/built-in-tools/deeprag/planning.md +1 -1
  28. package/skills/uipath-agents/references/lowcode/capabilities/context/attachments.md +1 -0
  29. package/skills/uipath-agents/references/lowcode/capabilities/guardrails/guardrails-recommend.md +1 -0
  30. package/skills/uipath-api-workflow/references/cli-reference.md +1 -1
  31. package/skills/uipath-api-workflow/references/connector-activity-discovery.md +1 -1
  32. package/skills/uipath-api-workflow/references/troubleshooting.md +1 -1
  33. package/skills/uipath-automation-discovery/SKILL.md +26 -1
  34. package/skills/uipath-automation-discovery/assets/templates/estimation-worksheet-template.md +80 -0
  35. package/skills/uipath-automation-discovery/references/estimation-guide.md +104 -0
  36. package/skills/uipath-connector-builder/SKILL.md +6 -4
  37. package/skills/uipath-connector-builder/references/auth.md +137 -13
  38. package/skills/uipath-connector-builder/references/configuration.md +29 -7
  39. package/skills/uipath-connector-builder/references/debugging.md +1 -1
  40. package/skills/uipath-connector-builder/references/standard-resources.md +162 -13
  41. package/skills/uipath-feedback/SKILL.md +12 -6
  42. package/skills/uipath-governance/references/cli-cheatsheet.md +3 -3
  43. package/skills/uipath-governance/references/diagnose/references/failure-modes.md +5 -5
  44. package/skills/uipath-insights/SKILL.md +277 -0
  45. package/skills/uipath-insights/references/investigation-playbook-guide.md +145 -0
  46. package/skills/uipath-insights/references/jobs-commands-guide.md +144 -0
  47. package/skills/uipath-ixp/SKILL.md +6 -3
  48. package/skills/uipath-ixp/references/cli-reference.md +19 -4
  49. package/skills/uipath-maestro-bpmn/references/cli-conventions.md +2 -0
  50. package/skills/uipath-maestro-bpmn/validator/README.md +12 -2
  51. package/skills/uipath-maestro-case/SKILL.md +27 -13
  52. package/skills/uipath-maestro-case/assets/templates/sdd-template-examples.md +37 -4
  53. package/skills/uipath-maestro-case/assets/templates/sdd-template.md +20 -9
  54. package/skills/uipath-maestro-case/assets/templates/sdd-viewer.html +8 -7
  55. package/skills/uipath-maestro-case/references/bindings-v2-sync.md +5 -1
  56. package/skills/uipath-maestro-case/references/brownfield.md +86 -0
  57. package/skills/uipath-maestro-case/references/case-commands.md +8 -0
  58. package/skills/uipath-maestro-case/references/case-editing-operations.md +230 -21
  59. package/skills/uipath-maestro-case/references/case-schema.md +29 -11
  60. package/skills/uipath-maestro-case/references/connector-integration.md +1 -1
  61. package/skills/uipath-maestro-case/references/connector-trigger-common.md +1 -1
  62. package/skills/uipath-maestro-case/references/entry-points-sync.md +204 -0
  63. package/skills/uipath-maestro-case/references/implementation.md +19 -9
  64. package/skills/uipath-maestro-case/references/phase-0-interview.md +10 -8
  65. package/skills/uipath-maestro-case/references/phased-execution.md +11 -4
  66. package/skills/uipath-maestro-case/references/placeholder-tasks.md +24 -2
  67. package/skills/uipath-maestro-case/references/planning.md +9 -3
  68. package/skills/uipath-maestro-case/references/plugins/case/planning.md +2 -0
  69. package/skills/uipath-maestro-case/references/plugins/sla/impl-json.md +1 -1
  70. package/skills/uipath-maestro-case/references/plugins/sla/planning.md +1 -1
  71. package/skills/uipath-maestro-case/references/plugins/stages/impl-json.md +11 -10
  72. package/skills/uipath-maestro-case/references/plugins/stages/planning.md +13 -14
  73. package/skills/uipath-maestro-case/references/plugins/tasks/agent/impl-json.md +3 -1
  74. package/skills/uipath-maestro-case/references/plugins/tasks/agent/planning.md +91 -2
  75. package/skills/uipath-maestro-case/references/plugins/tasks/api-workflow/impl-json.md +3 -1
  76. package/skills/uipath-maestro-case/references/plugins/tasks/api-workflow/planning.md +87 -2
  77. package/skills/uipath-maestro-case/references/plugins/tasks/connector-activity/planning.md +1 -1
  78. package/skills/uipath-maestro-case/references/plugins/triggers/event/impl-json.md +1 -1
  79. package/skills/uipath-maestro-case/references/plugins/triggers/manual/impl-json.md +3 -1
  80. package/skills/uipath-maestro-case/references/plugins/triggers/timer/impl-json.md +2 -1
  81. package/skills/uipath-maestro-case/references/plugins/variables/bindings/impl-json.md +2 -0
  82. package/skills/uipath-maestro-case/references/plugins/variables/global-vars/impl-json.md +20 -10
  83. package/skills/uipath-maestro-case/references/plugins/variables/global-vars/planning.md +9 -8
  84. package/skills/uipath-maestro-case/references/plugins/variables/io-binding/impl-json.md +1 -1
  85. package/skills/uipath-maestro-case/references/plugins/variables/io-binding/planning.md +1 -1
  86. package/skills/uipath-maestro-case/references/registry-discovery.md +87 -10
  87. package/skills/uipath-maestro-case/references/sdd-generation-rules.md +34 -26
  88. package/skills/uipath-maestro-flow/SKILL.md +4 -1
  89. package/skills/uipath-maestro-flow/references/author/CAPABILITY.md +1 -2
  90. package/skills/uipath-maestro-flow/references/author/references/editing-operations-json.md +3 -3
  91. package/skills/uipath-maestro-flow/references/author/references/greenfield.md +4 -2
  92. package/skills/uipath-maestro-flow/references/author/references/planning-arch.md +0 -1
  93. package/skills/uipath-maestro-flow/references/author/references/planning-impl.md +0 -1
  94. package/skills/uipath-maestro-flow/references/author/references/plugins/connector/impl.md +1 -0
  95. package/skills/uipath-maestro-flow/references/author/references/plugins/connector-trigger/impl.md +7 -7
  96. package/skills/uipath-maestro-flow/references/author/references/plugins/ixp/impl.md +14 -14
  97. package/skills/uipath-maestro-flow/references/author/references/plugins/script/impl.md +10 -6
  98. package/skills/uipath-maestro-flow/references/shared/cli-conventions.md +7 -0
  99. package/skills/uipath-maestro-flow/references/shared/file-format.md +1 -1
  100. package/skills/uipath-mcp-servers/references/is-activity-workflow.md +3 -3
  101. package/skills/uipath-planner/SKILL.md +1 -1
  102. package/skills/uipath-platform/SKILL.md +4 -14
  103. package/skills/uipath-platform/references/data-fabric/data-fabric.md +1 -1
  104. package/skills/uipath-platform/references/integration-service/agent-workflow.md +4 -4
  105. package/skills/uipath-platform/references/integration-service/reference-resolution.md +1 -1
  106. package/skills/uipath-platform/references/integration-service/resources.md +5 -5
  107. package/skills/uipath-platform/references/integration-service/triggers.md +10 -9
  108. package/skills/uipath-platform/references/orchestrator/setup-environment.md +2 -0
  109. package/skills/uipath-review/SKILL.md +8 -4
  110. package/skills/uipath-review/references/agents/agent-review-checklist.md +1 -22
  111. package/skills/uipath-review/references/agents/agents-coded-rules.md +24 -7
  112. package/skills/uipath-review/references/agents/agents-lowcode-rules.md +0 -1
  113. package/skills/uipath-review/references/agents/guardrails/coded-guardrails-review.md +231 -0
  114. package/skills/uipath-review/references/rule-catalog-workflow.md +4 -2
  115. package/skills/uipath-rpa/SKILL.md +2 -2
  116. package/skills/uipath-rpa/references/activity-docs/UiPath.DataService.Activities/guides/data-service-filter-builder-guide.md +1 -1
  117. package/skills/uipath-rpa/references/activity-docs/UiPath.Web.Activities/2.5/coded/coded-api.md +1 -1
  118. package/skills/uipath-rpa/references/activity-docs/UiPath.Web.Activities/2.5/coded/curl-import.md +3 -3
  119. package/skills/uipath-rpa/references/activity-docs/UiPath.Web.Activities/2.5/coded/http-request-upgrade.md +3 -3
  120. package/skills/uipath-rpa/references/activity-docs/UiPath.Web.Activities/2.5/coded/service-discovery.md +2 -2
  121. package/skills/uipath-rpa/references/coded/coding-guidelines.md +1 -1
  122. package/skills/uipath-rpa/references/ui-automation-guide.md +7 -7
  123. package/skills/uipath-rpa/references/uia-configure-target-workflows.md +5 -5
  124. package/skills/uipath-rpa/references/uia-elements-interaction-guide.md +19 -10
  125. package/skills/uipath-rpa/references/uia-prerequisites.md +7 -7
  126. package/skills/uipath-rpa/references/validation-guide.md +2 -2
  127. package/skills/uipath-rpa/references/xaml/common-pitfalls.md +4 -0
  128. package/skills/uipath-rpa/references/xaml/csharp-activity-binding-guide.md +3 -1
  129. package/skills/uipath-rpa/references/xaml/csharp-expression-pitfalls.md +9 -4
  130. package/skills/uipath-rpa/references/xaml/workflow-guide.md +2 -2
  131. package/skills/uipath-rpa/references/xaml/xaml-basics-and-rules.md +1 -1
  132. package/skills/uipath-solution/SKILL.md +4 -4
  133. package/skills/uipath-solution/references/activate-and-manage.md +6 -1
  134. package/skills/uipath-solution/references/develop-solution.md +24 -5
  135. package/skills/uipath-solution/references/pack-and-deploy.md +5 -2
  136. package/skills/uipath-solution/references/scenarios/manual-edits.md +2 -2
  137. package/skills/uipath-solution/references/solution-overview.md +2 -2
  138. package/skills/uipath-troubleshoot/SKILL.md +3 -3
  139. package/skills/uipath-troubleshoot/references/products/agents/playbooks/context-grounding-index-not-found.md +0 -2
  140. package/skills/uipath-troubleshoot/references/products/maestro/playbooks/personal-automation-quota.md +1 -1
  141. package/version-manifest.json +3 -3
  142. package/hooks/ensure-uip.sh +0 -220
  143. package/skills/uipath-maestro-flow/references/author/references/plugins/connector/data-fabric/impl.md +0 -683
  144. package/skills/uipath-maestro-flow/references/author/references/plugins/connector/data-fabric/planning.md +0 -45
@@ -9,7 +9,7 @@
9
9
  "name": "uipath",
10
10
  "source": "./",
11
11
  "description": "UiPath plugin for Claude Code — custom skills, agents, hooks, and MCP servers for UiPath workflows, UI automation, UI testing and UiPath troubleshoot",
12
- "version": "1.197.2",
12
+ "version": "1.198.0",
13
13
  "author": {
14
14
  "name": "UiPath"
15
15
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uipath",
3
- "version": "1.197.2",
3
+ "version": "1.198.0",
4
4
  "description": "UiPath plugin for Claude Code — custom skills, agents, hooks, and MCP servers for UiPath RPA workflows, UI automation, UI testing, Python coded agents and UiPath troubleshoot",
5
5
  "author": {
6
6
  "name": "UiPath"
package/CODEOWNERS CHANGED
@@ -23,12 +23,12 @@
23
23
  /tests/tasks/uipath-rpa/ @DragosUnguru @RaduAna-Maria @gabrielavaduva @AlvinStanescu @Mihaiii
24
24
 
25
25
  # Platform skill
26
- /skills/uipath-platform/ @gabrielavaduva @alexenica @andreiopr @vlad-voinea-uipath @emanueldejanu @gcoman @puscasu-ion-daniel @razvalex @aeremencu @alinahornet @DinuDanNicolae @florin-munteanu-uipath @StefanPopaUi @razvanpotcoveanu @vladbucur-8 @busesorin94 @dmorosanu @MarinRzv @vladimir-cozma @UiPath/team-merlot @UiPath/team-orange
26
+ /skills/uipath-platform/ @gabrielavaduva @alexenica @andreiopr @vlad-voinea-uipath @emanueldejanu @gcoman @puscasu-ion-daniel @razvalex @aeremencu @alinahornet @DinuDanNicolae @florin-munteanu-uipath @StefanPopaUi @razvanpotcoveanu @vladbucur-8 @busesorin94 @dmorosanu @MarinRzv @vladimir-cozma @UiPath/team-merlot @UiPath/team-orange @UiPath/DatafabricCodingAgent
27
27
  /skills/uipath-platform/references/traces/ @UiPath/llmops-team
28
28
  /skills/uipath-platform/references/integration-service/ @chandusailella @baishalighosh
29
29
  /skills/uipath-platform/references/data-fabric/ @UiPath/DatafabricCodingAgent
30
30
  /skills/uipath-platform/references/llmgateway/ @denispetre @vstoleru-uipath @dragosvelcea
31
- /tests/tasks/uipath-platform/ @gabrielavaduva @alexenica @andreiopr @vlad-voinea-uipath @emanueldejanu @gcoman @puscasu-ion-daniel @razvalex @aeremencu @alinahornet @DinuDanNicolae @florin-munteanu-uipath @StefanPopaUi @razvanpotcoveanu @vladbucur-8 @busesorin94 @dmorosanu @MarinRzv @vladimir-cozma @UiPath/team-merlot @UiPath/team-orange
31
+ /tests/tasks/uipath-platform/ @gabrielavaduva @alexenica @andreiopr @vlad-voinea-uipath @emanueldejanu @gcoman @puscasu-ion-daniel @razvalex @aeremencu @alinahornet @DinuDanNicolae @florin-munteanu-uipath @StefanPopaUi @razvanpotcoveanu @vladbucur-8 @busesorin94 @dmorosanu @MarinRzv @vladimir-cozma @UiPath/team-merlot @UiPath/team-orange @UiPath/DatafabricCodingAgent
32
32
  /tests/tasks/uipath-platform/orchestrator/ @gabrielavaduva @alexenica @andreiopr @vlad-voinea-uipath @emanueldejanu @gcoman @puscasu-ion-daniel @razvalex @aeremencu @alinahornet @DinuDanNicolae @florin-munteanu-uipath @StefanPopaUi @razvanpotcoveanu @vladbucur-8 @busesorin94 @dmorosanu @MarinRzv @vladimir-cozma @UiPath/team-merlot @UiPath/team-orange
33
33
  /tests/tasks/uipath-platform/resources/ @gabrielavaduva @alexenica @andreiopr @vlad-voinea-uipath @emanueldejanu @gcoman @puscasu-ion-daniel @razvalex @aeremencu @alinahornet @DinuDanNicolae @florin-munteanu-uipath @StefanPopaUi @razvanpotcoveanu @vladbucur-8 @busesorin94 @dmorosanu @MarinRzv @vladimir-cozma @UiPath/team-merlot @UiPath/team-orange
34
34
  /tests/tasks/uipath-platform/integration-service/ @chandusailella @baishalighosh
@@ -62,6 +62,8 @@
62
62
  # Guardrails tests (folder-level ownership)
63
63
  /tests/tasks/uipath-agents/lowcode/guardrails/ @apetraru-uipath @valentinabojan @ctiliescuuipath
64
64
  /tests/tasks/uipath-agents/coded/guardrails/ @apetraru-uipath @valentinabojan @ctiliescuuipath
65
+ # Guardrails in lowcode/conversational (more specific than /lowcode/conversational/ above — wins via last-match)
66
+ /tests/tasks/uipath-agents/lowcode/conversational/guardrails/ @apetraru-uipath @valentinabojan @ctiliescuuipath
65
67
 
66
68
  # Functions skill (Python Coded Functions — Phase 1; JS HTTP/background Phase 2/3)
67
69
  /skills/uipath-functions/ @AlexBizon @UiPath/team-coded-agents
@@ -77,9 +79,9 @@
77
79
  /tests/tasks/uipath-solution/ @UiPath/team-merlot @UiPath/team-orange
78
80
 
79
81
  # Flow skill
80
- /skills/uipath-maestro-flow/ @bai-uipath @rockymadden @gozhang2 @tmatup @akshaylive @jiyangzh @nikhil-maryala @baishalighosh
82
+ /skills/uipath-maestro-flow/ @bai-uipath @rockymadden @gozhang2 @tmatup @akshaylive @jiyangzh @nikhil-maryala @baishalighosh @DevMomo
81
83
  # Flow test tasks (general) — more specific subfolder rules below override this
82
- /tests/tasks/uipath-maestro-flow/ @bai-uipath @rockymadden @gozhang2 @tmatup @akshaylive @jiyangzh @nikhil-maryala @baishalighosh
84
+ /tests/tasks/uipath-maestro-flow/ @bai-uipath @rockymadden @gozhang2 @tmatup @akshaylive @jiyangzh @nikhil-maryala @baishalighosh @DevMomo
83
85
 
84
86
  # Context grounding team — flow plugins (Summarize/Batch Transform) + tasks
85
87
  /skills/uipath-maestro-flow/references/author/references/plugins/summarize/ @gcuip @JeremyReist2 @cfauchere @CalebMartinUiPath @jordan-uipath @eteodorovici @pateljay43 @swathiJayav
@@ -87,8 +89,8 @@
87
89
  /tests/tasks/uipath-maestro-flow/context-grounding/ @gcuip @JeremyReist2 @cfauchere @CalebMartinUiPath @jordan-uipath @eteodorovici @pateljay43 @swathiJayav
88
90
 
89
91
  # Maestro BPMN skill
90
- /skills/uipath-maestro-bpmn/ @bai-uipath @rockymadden @gozhang2 @tmatup @akshaylive @jiyangzh @nikhil-maryala @baishalighosh
91
- /tests/tasks/uipath-maestro-bpmn/ @bai-uipath @rockymadden @gozhang2 @tmatup @akshaylive @jiyangzh @nikhil-maryala @baishalighosh
92
+ /skills/uipath-maestro-bpmn/ @bai-uipath @rockymadden @gozhang2 @tmatup @akshaylive @jiyangzh @nikhil-maryala @baishalighosh @DevMomo
93
+ /tests/tasks/uipath-maestro-bpmn/ @bai-uipath @rockymadden @gozhang2 @tmatup @akshaylive @jiyangzh @nikhil-maryala @baishalighosh @DevMomo
92
94
  # API Workflow skill
93
95
  /skills/uipath-api-workflow/ @rares-baesu-uipath @liviubobocu @mirastroie
94
96
  /tests/tasks/uipath-api-workflow/ @rares-baesu-uipath @liviubobocu @mirastroie
@@ -100,6 +102,7 @@
100
102
  # Case Management skill
101
103
  /skills/uipath-maestro-case/ @charlesliu9 @song-zhao-25 @jundayin
102
104
  /tests/tasks/uipath-maestro-case/ @charlesliu9 @song-zhao-25 @jundayin
105
+ /tests/tasks/uipath-maestro-case/guardrails/ @apetraru-uipath @valentinabojan @ctiliescuuipath
103
106
 
104
107
  # Coded Apps skill
105
108
  /skills/uipath-coded-apps/ @Raina451 @deepeshrai-tech @Sandeepan-Ghosh-0312 @swati354
@@ -111,8 +114,8 @@
111
114
 
112
115
  # Flow skill — plugin guides (away team owned)
113
116
  # Add your team here when contributing a new plugin category
114
- /skills/uipath-maestro-flow/references/plugins/connector/ @baishalighosh @chandusailella @bai-uipath @rockymadden
115
- /skills/uipath-maestro-flow/references/plugins/connector-trigger/ @baishalighosh @chandusailella @bai-uipath @rockymadden
117
+ /skills/uipath-maestro-flow/references/plugins/connector/ @baishalighosh @chandusailella @bai-uipath @rockymadden @DevMomo
118
+ /skills/uipath-maestro-flow/references/plugins/connector-trigger/ @baishalighosh @chandusailella @bai-uipath @rockymadden @DevMomo
116
119
  /skills/uipath-maestro-flow/references/author/references/plugins/inline-agent/ @AlexandruCGhimisi @andreibalas-uipath @al3xanndru
117
120
  /tests/tasks/uipath-maestro-flow/connector_features/ @baishalighosh
118
121
 
@@ -122,6 +125,7 @@
122
125
 
123
126
  # Review skill
124
127
  /skills/uipath-review/ @AlvinStanescu @gabrielavaduva @roalexandru
128
+ /skills/uipath-review/references/agents/guardrails/ @apetraru-uipath @valentinabojan @ctiliescuuipath
125
129
  /tests/tasks/uipath-review/ @AlvinStanescu @gabrielavaduva @roalexandru
126
130
 
127
131
  # Legacy RPA — merged into uipath-rpa
@@ -151,12 +155,15 @@
151
155
  /tests/tasks/uipath-admin/ @sriramva-uipath @bansal-anushree @jianjunwang2 @t-hsia @ZuerWang99 @litheon @IsabellaCapriottiUIPath @uipathswapnil @ashleyetheridge @yadvender-uipath @CalinMPopa @chandhanshanth
152
156
 
153
157
  # IXP skill
154
- /skills/uipath-ixp/ @cezara98t @paul-ciobanu @misupantea-uipath @andrei-uipath
155
- /skills/uipath-ixp/ @cezara98t @paul-ciobanu @misupantea-uipath @andrei-uipath
156
- /tests/tasks/uipath-ixp/ @cezara98t @paul-ciobanu @misupantea-uipath @andrei-uipath
158
+ /skills/uipath-ixp/ @cezara98t @paul-ciobanu @misupantea-uipath @andrei-uipath @alexandrujircan
159
+ /tests/tasks/uipath-ixp/ @cezara98t @paul-ciobanu @misupantea-uipath @andrei-uipath @alexandrujircan
157
160
  # MCP skill (UiPath AgentHub MCP server registration + tool authoring)
158
161
  /skills/uipath-mcp-servers/ @cosminpaunel @UiPath/team-coded-agents
159
162
  /tests/tasks/uipath-mcp-servers/ @cosminpaunel @UiPath/team-coded-agents
160
163
 
164
+ # Insights skill (job monitoring and analytics)
165
+ /skills/uipath-insights/ @suranabhavya @rliuup
166
+ /tests/tasks/uipath-insights/ @suranabhavya @rliuup
167
+
161
168
  # Automation Discovery skill
162
169
  /skills/uipath-automation-discovery/ @uisherif
package/README.md CHANGED
@@ -98,6 +98,7 @@ Every skill's maturity is tracked in [`assets/skill-status.json`](assets/skill-s
98
98
  | `uipath-functions` | Preview |
99
99
  | `uipath-governance` | In-development |
100
100
  | `uipath-human-in-the-loop` | In-development |
101
+ | `uipath-insights` | Preview |
101
102
  | `uipath-ixp` | In-development |
102
103
  | `uipath-maestro-bpmn` | In-development |
103
104
  | `uipath-maestro-case` | In-development |
@@ -94,6 +94,14 @@
94
94
  },
95
95
  "last_synced": null
96
96
  },
97
+ "uipath-insights": {
98
+ "status": "preview",
99
+ "confluence": {
100
+ "page_id": "90824180832",
101
+ "url": "https://uipath.atlassian.net/wiki/spaces/CA/pages/90824180832"
102
+ },
103
+ "last_synced": null
104
+ },
97
105
  "uipath-ixp": {
98
106
  "status": "in-development",
99
107
  "confluence": {
package/hooks/hooks.json CHANGED
@@ -5,16 +5,19 @@
5
5
  "hooks": [
6
6
  {
7
7
  "type": "command",
8
- "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/ensure-uip.sh\"",
9
- "timeout": 180,
10
- "once": true,
11
- "statusMessage": "Checking uip and rpa-tool installation..."
8
+ "command": "echo `# <#` >/dev/null\nbash \"${CLAUDE_PLUGIN_ROOT}/hooks/suggest-permissions.sh\"\nexit $?\n: <<'POLYEOF' #> > $null\n& \"${CLAUDE_PLUGIN_ROOT}/hooks/suggest-permissions.ps1\"\nif ($null -eq $LASTEXITCODE) { exit 1 } else { exit $LASTEXITCODE }\nPOLYEOF\n",
9
+ "timeout": 5,
10
+ "once": true
12
11
  },
13
12
  {
14
13
  "type": "command",
15
- "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/suggest-permissions.sh\"",
16
- "timeout": 5,
17
- "once": true
14
+ "command": "echo `# <#` >/dev/null\nbash \"${CLAUDE_PLUGIN_ROOT}/hooks/set-session-env.sh\"\nexit $?\n: <<'POLYEOF' #> > $null\n& \"${CLAUDE_PLUGIN_ROOT}/hooks/set-session-env.ps1\"\nif ($null -eq $LASTEXITCODE) { exit 1 } else { exit $LASTEXITCODE }\nPOLYEOF\n",
15
+ "timeout": 5
16
+ },
17
+ {
18
+ "type": "command",
19
+ "command": "echo `# <#` >/dev/null\nbash \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.sh\"\nexit $?\n: <<'POLYEOF' #> > $null\n& \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.ps1\"\nif ($null -eq $LASTEXITCODE) { exit 1 } else { exit $LASTEXITCODE }\nPOLYEOF\n",
20
+ "async": true
18
21
  }
19
22
  ]
20
23
  }
@@ -25,7 +28,40 @@
25
28
  "hooks": [
26
29
  {
27
30
  "type": "command",
28
- "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.sh\"",
31
+ "command": "echo `# <#` >/dev/null\nbash \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.sh\"\nexit $?\n: <<'POLYEOF' #> > $null\n& \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.ps1\"\nif ($null -eq $LASTEXITCODE) { exit 1 } else { exit $LASTEXITCODE }\nPOLYEOF\n",
32
+ "async": true
33
+ }
34
+ ]
35
+ }
36
+ ],
37
+ "SessionEnd": [
38
+ {
39
+ "hooks": [
40
+ {
41
+ "type": "command",
42
+ "command": "echo `# <#` >/dev/null\nbash \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.sh\"\nexit $?\n: <<'POLYEOF' #> > $null\n& \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.ps1\"\nif ($null -eq $LASTEXITCODE) { exit 1 } else { exit $LASTEXITCODE }\nPOLYEOF\n",
43
+ "timeout": 30
44
+ }
45
+ ]
46
+ }
47
+ ],
48
+ "Stop": [
49
+ {
50
+ "hooks": [
51
+ {
52
+ "type": "command",
53
+ "command": "echo `# <#` >/dev/null\nbash \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.sh\"\nexit $?\n: <<'POLYEOF' #> > $null\n& \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.ps1\"\nif ($null -eq $LASTEXITCODE) { exit 1 } else { exit $LASTEXITCODE }\nPOLYEOF\n",
54
+ "async": true
55
+ }
56
+ ]
57
+ }
58
+ ],
59
+ "StopFailure": [
60
+ {
61
+ "hooks": [
62
+ {
63
+ "type": "command",
64
+ "command": "echo `# <#` >/dev/null\nbash \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.sh\"\nexit $?\n: <<'POLYEOF' #> > $null\n& \"${CLAUDE_PLUGIN_ROOT}/hooks/send-telemetry.ps1\"\nif ($null -eq $LASTEXITCODE) { exit 1 } else { exit $LASTEXITCODE }\nPOLYEOF\n",
29
65
  "async": true
30
66
  }
31
67
  ]
@@ -0,0 +1,392 @@
1
+ # Telemetry hook for the UiPath skills plugin (Claude Code).
2
+ #
3
+ # TWIN SCRIPT: hooks/send-telemetry.sh is the bash twin of this file — any
4
+ # behavioral change here MUST be mirrored there in the same PR (see CLAUDE.md).
5
+ # hooks.json runs whichever twin matches the executing shell via a
6
+ # bash/PowerShell polyglot command.
7
+ #
8
+ # Registered on multiple Claude Code hook events (PostToolUse, SessionStart,
9
+ # SessionEnd, Stop, StopFailure). Reads the hook JSON payload from stdin, maps
10
+ # the event to a canonical eventName, and pipes one flat JSON object to
11
+ # `uip track`, which forwards it through the CLI's own telemetry tracker as a
12
+ # single uip.skills.<event> Application Insights event.
13
+ #
14
+ # tool-use is per-call and gated on plugin attribution (skill gate) — calls from
15
+ # other plugins or bare Claude Code are dropped. Lifecycle events (session-start,
16
+ # session-end, completion) are session-scoped and fire for every session where
17
+ # this plugin is installed.
18
+ #
19
+ # The CLI (see UiPath/cli#2600) owns transport, the App Insights connection,
20
+ # the event name, the authenticated cloud identity, the `source:
21
+ # "skills-plugin"` dimension, and — since UiPath/cli#2806 — the
22
+ # environment/base_url/region base dimensions stamped fresh on every event
23
+ # from its own auth context (so this hook sends no environment info). This
24
+ # hook only derives + sanitizes fields and gates on the opt-out flag; value
25
+ # sanitization stays the hook's responsibility because the CLI and skills
26
+ # ship co-versioned.
27
+ #
28
+ # REGION-SCOPED EXTRACTION: the payload embeds free-form customer content
29
+ # (prompts, command lines, stdout/stderr, file contents). A naive text scan
30
+ # over the whole payload mis-extracts fields when that content contains
31
+ # JSON-shaped text (`"success":false`, `uip solution publish`, `.flow"`,
32
+ # `"resolvedModel":"..."`). So the payload is parsed as real JSON
33
+ # (ConvertFrom-Json) and each field is read ONLY from the region it lives in:
34
+ # ENVELOPE (top-level) -> toolName, toolUseId, session_id, permissionMode,
35
+ # durationMs, effortLevel (effort.level), agentType,
36
+ # source (-> session_source), reason (session-end),
37
+ # model (-> agent_model; Claude sends it on
38
+ # SessionStart, Codex on every event)
39
+ # tool_input -> skillName, uipSubcommand (command), fileExtension
40
+ # (file_path), subagentType (subagent_type, or
41
+ # agent_type for a Codex spawn_agent call)
42
+ # tool_response -> outcome (interrupted/success), subagentModel
43
+ # (resolvedModel)
44
+ #
45
+ # CROSS-AGENT: registered as a PostToolUse hook, this also runs under other
46
+ # coding agents that honor hooks.json (e.g. Codex). Codex's envelope matches
47
+ # Claude's (hook_event_name, tool_name, tool_use_id, session_id,
48
+ # permission_mode, tool_input/{command,file_path}), so Bash-`uip` and file
49
+ # attribution work unchanged. Differences handled / accepted: agent spawns use
50
+ # `spawn_agent` + tool_input.agent_type (see Test-UipathCall + extraction);
51
+ # Codex omits duration_ms / effort.level (-> durationMs null, effortLevel "")
52
+ # and serializes tool_response as a JSON STRING, not an object, so success /
53
+ # interrupted / resolvedModel are absent and outcome is ok|unknown only.
54
+ # Only derived, low-cardinality, PII-free values ever leave the machine.
55
+ #
56
+ # Non-blocking by contract: registered as an async hook in hooks.json
57
+ # ("async": true) on every event EXCEPT SessionEnd, so Claude Code runs it in
58
+ # the background and never waits for it. SessionEnd is registered
59
+ # SYNCHRONOUSLY (30s timeout): async hooks still running at session teardown
60
+ # are killed after a short grace window — shorter than this hook's PowerShell
61
+ # + `uip track` startup — which would silently drop the session-end event.
62
+ # Always exits 0 and swallows every error. Runs under Windows PowerShell 5.1
63
+ # and PowerShell 7+ (pwsh) on Windows, macOS, and Linux — no jq, node, or
64
+ # python.
65
+ #
66
+ # Structure: pure helpers (below), driven by Main (bottom). Configuration is
67
+ # env only:
68
+ # UIPATH_TELEMETRY_DISABLED Gate. Reuses the uip CLI's variable name.
69
+ # Opt-out: send by DEFAULT. Skip ONLY when set to
70
+ # "1". Unset (default) or "0" -> send. Absent is
71
+ # treated as enabled.
72
+
73
+ $ErrorActionPreference = 'SilentlyContinue'
74
+
75
+ # schemaVersion of the emitted event. Bump on ANY change to the key set so App
76
+ # Insights can segment events emitted with older/churned schemas. v2: adds the
77
+ # eventName / session_source / reason / agent_model keys, renames
78
+ # sessionId -> session_id (canonical casing, matches the CLI command stream,
79
+ # UiPath/cli#2800), and drops environment/baseUrl (the CLI stamps fresh
80
+ # environment/base_url/region base dimensions itself, UiPath/cli#2806).
81
+ $SCHEMA_VERSION = 2
82
+
83
+ # --- extraction helpers ------------------------------------------------------
84
+
85
+ # Safe property read on a ConvertFrom-Json PSCustomObject: $null when the key
86
+ # is absent (never throws, never falls back to another region).
87
+ function Get-Prop($Obj, [string]$Name) {
88
+ if ($null -eq $Obj) { return $null }
89
+ $p = $Obj.PSObject.Properties[$Name]
90
+ if ($p) { return $p.Value }
91
+ return $null
92
+ }
93
+
94
+ function Test-JsonObject($Value) {
95
+ return ($Value -is [System.Management.Automation.PSCustomObject])
96
+ }
97
+
98
+ # JSON booleans -> the literal strings 'true'/'false'; everything else -> ''.
99
+ function ConvertTo-BoolString($Value) {
100
+ if ($Value -is [bool]) { if ($Value) { return 'true' } return 'false' }
101
+ return ''
102
+ }
103
+
104
+ # --- relevance gate --------------------------------------------------------
105
+
106
+ # Test-UipathCall: $true if this call is attributable to the plugin, else
107
+ # $false. No "active plugin" field exists, so attribute per-call from
108
+ # tool_input signals only (command / file_path), so stdout or prompt content
109
+ # can never over-attribute. Matching is case-sensitive to mirror the CLI's
110
+ # own casing (file extensions are the deliberate case-insensitive exception).
111
+ function Test-UipathCall([string]$Tool, [string]$Skill, [string]$SubagentType, [string]$Command, [string]$FilePath) {
112
+ switch ($Tool) {
113
+ 'Skill' {
114
+ if ($Skill -clike 'uipath:*' -or $Skill -clike 'uipath-*') { return $true }
115
+ break
116
+ }
117
+ { $_ -cin @('Agent', 'spawn_agent') } {
118
+ # UiPath agents, or a built-in/generic agent type — NOT custom agents from
119
+ # other plugins (`<plugin>:<name>`) or user-defined ones. Claude Code spawns
120
+ # via `Agent` + tool_input.subagent_type; Codex via `spawn_agent` +
121
+ # tool_input.agent_type (extraction normalizes that to subagent_type).
122
+ # `default` is Codex's generic agent — the equivalent of Claude's
123
+ # general-purpose/claude.
124
+ if ($SubagentType -clike 'uipath:*' -or $SubagentType -clike 'uipath-*') { return $true }
125
+ if (@('general-purpose', 'Explore', 'Plan', 'claude', 'claude-code-guide', 'statusline-setup', 'fork', 'default') -ccontains $SubagentType) { return $true }
126
+ break
127
+ }
128
+ { $_ -cin @('Bash', 'PowerShell') } {
129
+ if ($Command -cmatch '(^|[\\";|&(\s])(uip|rpa-tool)\s' -or $Command -cmatch '\$UIP\b') { return $true }
130
+ break
131
+ }
132
+ { $_ -cin @('Edit', 'Write', 'Read', 'Glob', 'Grep') } {
133
+ if ($FilePath -imatch '\.(cs|flow|xaml|uipx|bpmn)$' -or $FilePath -imatch '(^|[/\\])(agent|caseplan|project|app\.config|action-schema)\.json$') { return $true }
134
+ break
135
+ }
136
+ }
137
+ return $false
138
+ }
139
+
140
+ # --- field derivation ------------------------------------------------------
141
+
142
+ # Get-DerivedFields: skillName, uipSubcommand, fileExt from the parsed
143
+ # tool_input values (so stdout content can't leak in).
144
+ function Get-DerivedFields([string]$Tool, [string]$Skill, [string]$Command, [string]$FilePath) {
145
+ $derived = @{ skillName = ''; uipSubcommand = ''; fileExt = '' }
146
+ switch ($Tool) {
147
+ 'Skill' {
148
+ $derived.skillName = $Skill
149
+ break
150
+ }
151
+ { $_ -cin @('Bash', 'PowerShell') } {
152
+ # e.g. "solution publish" from "uip solution publish --output json".
153
+ $m = [regex]::Match($Command, '(uip|\$UIP)\s+[a-z][a-z-]*(\s+[a-z][a-z-]*)?')
154
+ if ($m.Success) {
155
+ $derived.uipSubcommand = $m.Value -creplace '^(uip|\$UIP)\s+', ''
156
+ }
157
+ break
158
+ }
159
+ { $_ -cin @('Edit', 'Write', 'Read', 'Glob', 'Grep') } {
160
+ $m = [regex]::Match($FilePath, '\.[A-Za-z0-9]+$')
161
+ if ($m.Success) { $derived.fileExt = $m.Value }
162
+ if ($FilePath -clike '*agent.json') { $derived.fileExt = 'agent.json' }
163
+ if ($FilePath -clike '*caseplan.json') { $derived.fileExt = 'caseplan.json' }
164
+ break
165
+ }
166
+ }
167
+ return $derived
168
+ }
169
+
170
+ # Get-Outcome: outcome from the tool_response region ONLY — content never
171
+ # flips it.
172
+ # interrupted == true -> interrupted (takes precedence)
173
+ # success == false -> failure
174
+ # tool_response present, no failure signal -> ok (Read/Edit/Write/most MCP)
175
+ # no tool_response at all -> unknown
176
+ function Get-Outcome([string]$Interrupted, [string]$Success, [bool]$ResponseSeen) {
177
+ if ($Interrupted -eq 'true') { return 'interrupted' }
178
+ if ($Success -eq 'false') { return 'failure' }
179
+ if ($ResponseSeen) { return 'ok' }
180
+ return 'unknown'
181
+ }
182
+
183
+ # Get-EventName: translate the agent hook event into the canonical eventName
184
+ # token the CLI's `uip track` maps to a uip.skills.<event> event. An
185
+ # unrecognized event returns empty so Main drops it. Stop and StopFailure both
186
+ # map to `completion`, distinguished by outcome (see Get-LifecycleOutcome).
187
+ # CROSS-AGENT: Codex fires SessionStart and Stop under these SAME names with a
188
+ # matching envelope (session_id/source/model; docs: developers.openai.com/
189
+ # codex/hooks), so both map here unchanged. Codex has NO SessionEnd (completion
190
+ # is its terminal signal) and no StopFailure (its API-error turns are not
191
+ # distinguished). Gemini/Cursor use different hook names — separate follow-ups.
192
+ function Get-EventName([string]$HookEvent) {
193
+ switch ($HookEvent) {
194
+ 'PostToolUse' { return 'tool-use' }
195
+ 'SessionStart' { return 'session-start' }
196
+ 'SessionEnd' { return 'session-end' }
197
+ 'Stop' { return 'completion' }
198
+ 'StopFailure' { return 'completion' }
199
+ }
200
+ return ''
201
+ }
202
+
203
+ # Get-LifecycleOutcome: outcome for the non-tool events. A normal turn end
204
+ # (Stop) is `ok`; an API-error turn end (StopFailure) is `failure`.
205
+ # session-start and session-end carry no turn outcome (session-end's `reason`
206
+ # conveys the why).
207
+ function Get-LifecycleOutcome([string]$HookEvent) {
208
+ switch ($HookEvent) {
209
+ 'Stop' { return 'ok' }
210
+ 'StopFailure' { return 'failure' }
211
+ }
212
+ return ''
213
+ }
214
+
215
+ # Get-ModelFamily: the low-cardinality family, dropping the context-window
216
+ # marker (e.g. claude-opus-4-8[1m] -> opus). Empty when absent (plain
217
+ # main-loop call); `other` for an unrecognized family.
218
+ function Get-ModelFamily([string]$Model) {
219
+ if (-not $Model) { return '' }
220
+ if ($Model -clike '*opus*') { return 'opus' }
221
+ if ($Model -clike '*sonnet*') { return 'sonnet' }
222
+ if ($Model -clike '*haiku*') { return 'haiku' }
223
+ if ($Model -clike '*fable*') { return 'fable' }
224
+ return 'other'
225
+ }
226
+
227
+ # Read-SkillsVersion: skills/CLI co-version from version-manifest.json (NOT
228
+ # git, NOT the plugin package version). The CLI's own app version already rides
229
+ # the tracker as application_Version, so no separate cliVersion is sent.
230
+ function Read-SkillsVersion {
231
+ $root = $env:CLAUDE_PLUGIN_ROOT
232
+ if (-not $root) { $root = '.' }
233
+ try { $text = [System.IO.File]::ReadAllText((Join-Path $root 'version-manifest.json')) }
234
+ catch { return '' }
235
+ $m = [regex]::Match($text, '"skillsVersion"\s*:\s*"([^"]*)"')
236
+ if ($m.Success) { return $m.Groups[1].Value }
237
+ return ''
238
+ }
239
+
240
+ # Get-Sanitized: sanitize free-ish text to keep the assembled JSON valid and
241
+ # bounded. Strips anything outside a safe charset (so no quotes / backslashes /
242
+ # control chars / pipes survive) and caps length.
243
+ function Get-Sanitized([string]$Value) {
244
+ if ($null -eq $Value) { return '' }
245
+ $s = $Value -creplace '[^A-Za-z0-9:._/ -]', '_'
246
+ if ($s.Length -gt 120) { $s = $s.Substring(0, 120) }
247
+ return $s
248
+ }
249
+
250
+ # --- main ------------------------------------------------------------------
251
+ function Main {
252
+ # Opt-out: send by default; skip only when telemetry is explicitly disabled
253
+ # (UIPATH_TELEMETRY_DISABLED=1 or =true). Matches the CLI's isTelemetryDisabled()
254
+ # gate, so `uip track` and this hook short-circuit on the same values.
255
+ if ($env:UIPATH_TELEMETRY_DISABLED -cin @('1', 'true')) { exit 0 }
256
+
257
+ $raw = ''
258
+ try { $raw = [Console]::In.ReadToEnd() } catch { exit 0 }
259
+ $payload = $null
260
+ try { $payload = $raw | ConvertFrom-Json -ErrorAction Stop } catch { exit 0 }
261
+ if (-not (Test-JsonObject $payload)) { exit 0 }
262
+
263
+ # ENVELOPE region.
264
+ $hookEvent = [string](Get-Prop $payload 'hook_event_name')
265
+ $tool = [string](Get-Prop $payload 'tool_name')
266
+ $toolUseId = [string](Get-Prop $payload 'tool_use_id')
267
+ $sessionId = [string](Get-Prop $payload 'session_id')
268
+ $permissionMode = [string](Get-Prop $payload 'permission_mode')
269
+ $durationMs = Get-Prop $payload 'duration_ms'
270
+ $agentType = [string](Get-Prop $payload 'agent_type')
271
+ $sessionSource = [string](Get-Prop $payload 'source')
272
+ $reason = [string](Get-Prop $payload 'reason')
273
+ $agentModel = [string](Get-Prop $payload 'model')
274
+
275
+ $effortLevel = ''
276
+ $effort = Get-Prop $payload 'effort'
277
+ if (Test-JsonObject $effort) { $effortLevel = [string](Get-Prop $effort 'level') }
278
+
279
+ # tool_input region.
280
+ $skill = ''; $command = ''; $filePath = ''; $subagentType = ''
281
+ $toolInput = Get-Prop $payload 'tool_input'
282
+ if (Test-JsonObject $toolInput) {
283
+ $skill = [string](Get-Prop $toolInput 'skill')
284
+ $command = [string](Get-Prop $toolInput 'command')
285
+ $filePath = [string](Get-Prop $toolInput 'file_path')
286
+ $subagentType = [string](Get-Prop $toolInput 'subagent_type')
287
+ # Codex spawn_agent carries the spawned type in tool_input.agent_type;
288
+ # normalize it to subagentType so it lands in the same field as Claude and
289
+ # never collides with the envelope agent_type (agentType).
290
+ if (-not $subagentType) { $subagentType = [string](Get-Prop $toolInput 'agent_type') }
291
+ }
292
+
293
+ # tool_response region. Presence of the KEY (any value shape) marks the
294
+ # response as seen; the fields are read only when it is a real object
295
+ # (Codex serializes tool_response as a JSON string -> ok|unknown only).
296
+ $responseSeen = [bool]$payload.PSObject.Properties['tool_response']
297
+ $interrupted = ''; $success = ''; $resolvedModel = ''
298
+ $toolResponse = Get-Prop $payload 'tool_response'
299
+ if (Test-JsonObject $toolResponse) {
300
+ $interrupted = ConvertTo-BoolString (Get-Prop $toolResponse 'interrupted')
301
+ $success = ConvertTo-BoolString (Get-Prop $toolResponse 'success')
302
+ $resolvedModel = [string](Get-Prop $toolResponse 'resolvedModel')
303
+ }
304
+
305
+ # Map the hook event to a canonical eventName; drop unrecognized events.
306
+ $eventName = Get-EventName $hookEvent
307
+ if (-not $eventName) { exit 0 }
308
+
309
+ # Derived only on tool-use; keep defined so the fixed key set always assembles.
310
+ $skillName = ''; $uipSubcommand = ''; $fileExt = ''; $subagentModel = ''
311
+
312
+ if ($eventName -eq 'tool-use') {
313
+ # tool-use is per-call: gate on plugin attribution, then derive tool fields.
314
+ if (-not (Test-UipathCall $tool $skill $subagentType $command $filePath)) { exit 0 }
315
+ $derived = Get-DerivedFields $tool $skill $command $filePath
316
+ $skillName = $derived.skillName
317
+ $uipSubcommand = $derived.uipSubcommand
318
+ $fileExt = $derived.fileExt
319
+ $outcome = Get-Outcome $interrupted $success $responseSeen
320
+ $subagentModel = Get-ModelFamily $resolvedModel
321
+ }
322
+ else {
323
+ # Lifecycle events are session-scoped — they fire for every session where
324
+ # this plugin is installed (the activation-rate denominator), so they skip
325
+ # the per-call attribution gate and tool-field derivation.
326
+ $outcome = Get-LifecycleOutcome $hookEvent
327
+ }
328
+
329
+ # Enforce the per-event field scoping the contract documents: session_source
330
+ # only on session-start, reason only on session-end. `source`/`reason` are
331
+ # extracted from ANY event's envelope, so a future payload that adds either
332
+ # key to another event must not bleed into these dimensions.
333
+ if ($eventName -ne 'session-start') { $sessionSource = '' }
334
+ if ($eventName -ne 'session-end') { $reason = '' }
335
+
336
+ $skillsVer = Read-SkillsVersion
337
+
338
+ # durationMs is a JSON number. Emit JSON null (not 0) when absent, so a missing
339
+ # value doesn't skew latency aggregations. The CLI drops a null-valued
340
+ # property, so a missing duration records as "no data". Stays unquoted.
341
+ $durJson = 'null'
342
+ if ($null -ne $durationMs -and "$durationMs" -cmatch '^[0-9]+$') { $durJson = "$durationMs" }
343
+
344
+ # Assemble the canonical, ordered, flat JSON. The key set is defined ONCE
345
+ # here (fixed order, every key always emitted). Each row is
346
+ # (name, kind, value): `s` -> JSON string, `n` -> JSON number/literal. Every
347
+ # string value passes Get-Sanitized, so no quote/backslash can survive into
348
+ # the assembled JSON.
349
+ $spec = @(
350
+ @('schemaVersion', 'n', "$SCHEMA_VERSION"),
351
+ @('eventName', 's', $eventName),
352
+ @('toolName', 's', $tool),
353
+ @('skillName', 's', $skillName),
354
+ @('uipSubcommand', 's', $uipSubcommand),
355
+ @('fileExtension', 's', $fileExt),
356
+ @('outcome', 's', $outcome),
357
+ @('permissionMode', 's', $permissionMode),
358
+ @('effortLevel', 's', $effortLevel),
359
+ @('skillsVersion', 's', $skillsVer),
360
+ @('toolUseId', 's', $toolUseId),
361
+ @('session_id', 's', $sessionId),
362
+ @('subagentModel', 's', $subagentModel),
363
+ @('subagentType', 's', $subagentType),
364
+ @('agentType', 's', $agentType),
365
+ @('agent_model', 's', $agentModel),
366
+ @('session_source', 's', $sessionSource),
367
+ @('reason', 's', $reason),
368
+ @('durationMs', 'n', $durJson)
369
+ )
370
+ $parts = foreach ($field in $spec) {
371
+ if ($field[1] -eq 'n') { '"' + $field[0] + '":' + $field[2] }
372
+ else { '"' + $field[0] + '":"' + (Get-Sanitized $field[2]) + '"' }
373
+ }
374
+ $json = '{' + ($parts -join ',') + '}'
375
+
376
+ # Hand off to the CLI telemetry tracker. The CLI maps our eventName token to
377
+ # the uip.skills.<event> name, stamps source: "skills-plugin", attaches the
378
+ # authenticated cloud identity + CLI app version, owns transport + flush,
379
+ # redacts PII, and drops any non-scalar value (so a null durationMs
380
+ # disappears). Send no envelope and no `source` (the CLI overrides it).
381
+ #
382
+ # `uip track` is never-fail (exits 0, emits nothing when telemetry is opted
383
+ # out); piping to it is harmless even if the CLI is absent (the catch
384
+ # swallows the command-not-found error). The hook is registered async in
385
+ # hooks.json (sync with a 30s timeout on SessionEnd — see header), so the
386
+ # agent never waits on this call mid-session.
387
+ try { $json | & uip track *> $null } catch { }
388
+
389
+ exit 0
390
+ }
391
+
392
+ Main