primitive-admin 1.1.0-alpha.6 → 1.1.0-alpha.60

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 (387) hide show
  1. package/README.md +389 -71
  2. package/assets/skill/skills/primitive-platform/SKILL.md +670 -0
  3. package/dist/bin/primitive.d.ts +2 -0
  4. package/dist/bin/primitive.js +287 -17
  5. package/dist/bin/primitive.js.map +1 -1
  6. package/dist/src/commands/admins.d.ts +2 -0
  7. package/dist/src/commands/admins.js +138 -19
  8. package/dist/src/commands/admins.js.map +1 -1
  9. package/dist/src/commands/analytics.d.ts +2 -0
  10. package/dist/src/commands/analytics.js +554 -55
  11. package/dist/src/commands/analytics.js.map +1 -1
  12. package/dist/src/commands/apps.d.ts +2 -0
  13. package/dist/src/commands/apps.js +27 -80
  14. package/dist/src/commands/apps.js.map +1 -1
  15. package/dist/src/commands/auth.d.ts +2 -0
  16. package/dist/src/commands/auth.js +177 -7
  17. package/dist/src/commands/auth.js.map +1 -1
  18. package/dist/src/commands/blob-buckets.d.ts +2 -0
  19. package/dist/src/commands/blob-buckets.js +330 -0
  20. package/dist/src/commands/blob-buckets.js.map +1 -0
  21. package/dist/src/commands/catalog.d.ts +2 -0
  22. package/dist/src/commands/catalog.js +37 -38
  23. package/dist/src/commands/catalog.js.map +1 -1
  24. package/dist/src/commands/collection-type-configs.d.ts +2 -0
  25. package/dist/src/commands/collection-type-configs.js +92 -0
  26. package/dist/src/commands/collection-type-configs.js.map +1 -0
  27. package/dist/src/commands/collections.d.ts +2 -0
  28. package/dist/src/commands/collections.js +526 -0
  29. package/dist/src/commands/collections.js.map +1 -0
  30. package/dist/src/commands/comparisons.d.ts +2 -0
  31. package/dist/src/commands/comparisons.js +6 -6
  32. package/dist/src/commands/comparisons.js.map +1 -1
  33. package/dist/src/commands/config.d.ts +35 -0
  34. package/dist/src/commands/config.js +437 -0
  35. package/dist/src/commands/config.js.map +1 -0
  36. package/dist/src/commands/connections.d.ts +2 -0
  37. package/dist/src/commands/connections.js +100 -0
  38. package/dist/src/commands/connections.js.map +1 -0
  39. package/dist/src/commands/cron-triggers.d.ts +2 -0
  40. package/dist/src/commands/cron-triggers.js +204 -0
  41. package/dist/src/commands/cron-triggers.js.map +1 -0
  42. package/dist/src/commands/database-types.d.ts +2 -0
  43. package/dist/src/commands/database-types.js +171 -0
  44. package/dist/src/commands/database-types.js.map +1 -0
  45. package/dist/src/commands/databases.d.ts +65 -0
  46. package/dist/src/commands/databases.js +2153 -96
  47. package/dist/src/commands/databases.js.map +1 -1
  48. package/dist/src/commands/documents.d.ts +2 -0
  49. package/dist/src/commands/documents.js +1230 -19
  50. package/dist/src/commands/documents.js.map +1 -1
  51. package/dist/src/commands/email-templates.d.ts +2 -0
  52. package/dist/src/commands/email-templates.js +174 -0
  53. package/dist/src/commands/email-templates.js.map +1 -0
  54. package/dist/src/commands/env.d.ts +12 -0
  55. package/dist/src/commands/env.js +260 -0
  56. package/dist/src/commands/env.js.map +1 -0
  57. package/dist/src/commands/group-type-configs.d.ts +2 -0
  58. package/dist/src/commands/group-type-configs.js +86 -0
  59. package/dist/src/commands/group-type-configs.js.map +1 -0
  60. package/dist/src/commands/groups.d.ts +2 -0
  61. package/dist/src/commands/groups.js +38 -99
  62. package/dist/src/commands/groups.js.map +1 -1
  63. package/dist/src/commands/guides.d.ts +223 -0
  64. package/dist/src/commands/guides.js +617 -65
  65. package/dist/src/commands/guides.js.map +1 -1
  66. package/dist/src/commands/init.d.ts +17 -0
  67. package/dist/src/commands/init.js +964 -202
  68. package/dist/src/commands/init.js.map +1 -1
  69. package/dist/src/commands/integrations.d.ts +2 -0
  70. package/dist/src/commands/integrations.js +484 -205
  71. package/dist/src/commands/integrations.js.map +1 -1
  72. package/dist/src/commands/llm.d.ts +2 -0
  73. package/dist/src/commands/llm.js +13 -8
  74. package/dist/src/commands/llm.js.map +1 -1
  75. package/dist/src/commands/locks.d.ts +8 -0
  76. package/dist/src/commands/locks.js +160 -0
  77. package/dist/src/commands/locks.js.map +1 -0
  78. package/dist/src/commands/metadata.d.ts +2 -0
  79. package/dist/src/commands/metadata.js +406 -0
  80. package/dist/src/commands/metadata.js.map +1 -0
  81. package/dist/src/commands/prompts.d.ts +2 -0
  82. package/dist/src/commands/prompts.js +135 -355
  83. package/dist/src/commands/prompts.js.map +1 -1
  84. package/dist/src/commands/rule-sets.d.ts +3 -0
  85. package/dist/src/commands/rule-sets.js +271 -0
  86. package/dist/src/commands/rule-sets.js.map +1 -0
  87. package/dist/src/commands/scripts.d.ts +20 -0
  88. package/dist/src/commands/scripts.js +739 -0
  89. package/dist/src/commands/scripts.js.map +1 -0
  90. package/dist/src/commands/secrets.d.ts +2 -0
  91. package/dist/src/commands/secrets.js +108 -0
  92. package/dist/src/commands/secrets.js.map +1 -0
  93. package/dist/src/commands/sessions.d.ts +2 -0
  94. package/dist/src/commands/sessions.js +75 -0
  95. package/dist/src/commands/sessions.js.map +1 -0
  96. package/dist/src/commands/settings.d.ts +18 -0
  97. package/dist/src/commands/settings.js +54 -0
  98. package/dist/src/commands/settings.js.map +1 -0
  99. package/dist/src/commands/skill.d.ts +2 -0
  100. package/dist/src/commands/skill.js +29 -0
  101. package/dist/src/commands/skill.js.map +1 -0
  102. package/dist/src/commands/sync-app-settings.d.ts +125 -0
  103. package/dist/src/commands/sync-app-settings.js +380 -0
  104. package/dist/src/commands/sync-app-settings.js.map +1 -0
  105. package/dist/src/commands/sync.d.ts +958 -0
  106. package/dist/src/commands/sync.js +8954 -812
  107. package/dist/src/commands/sync.js.map +1 -1
  108. package/dist/src/commands/tokens.d.ts +2 -0
  109. package/dist/src/commands/tokens.js +130 -21
  110. package/dist/src/commands/tokens.js.map +1 -1
  111. package/dist/src/commands/users.d.ts +2 -0
  112. package/dist/src/commands/users.js +440 -22
  113. package/dist/src/commands/users.js.map +1 -1
  114. package/dist/src/commands/vars.d.ts +8 -0
  115. package/dist/src/commands/vars.js +96 -0
  116. package/dist/src/commands/vars.js.map +1 -0
  117. package/dist/src/commands/waitlist.d.ts +2 -0
  118. package/dist/src/commands/waitlist.js +10 -10
  119. package/dist/src/commands/waitlist.js.map +1 -1
  120. package/dist/src/commands/webhooks.d.ts +2 -0
  121. package/dist/src/commands/webhooks.js +442 -0
  122. package/dist/src/commands/webhooks.js.map +1 -0
  123. package/dist/src/commands/workflows.d.ts +94 -0
  124. package/dist/src/commands/workflows.js +1581 -448
  125. package/dist/src/commands/workflows.js.map +1 -1
  126. package/dist/src/lib/api-client.d.ts +1814 -0
  127. package/dist/src/lib/api-client.js +1655 -103
  128. package/dist/src/lib/api-client.js.map +1 -1
  129. package/dist/src/lib/app-settings-descriptor.d.ts +130 -0
  130. package/dist/src/lib/app-settings-descriptor.js +262 -0
  131. package/dist/src/lib/app-settings-descriptor.js.map +1 -0
  132. package/dist/src/lib/auth-flow.d.ts +8 -0
  133. package/dist/src/lib/batch.d.ts +26 -0
  134. package/dist/src/lib/batch.js +32 -0
  135. package/dist/src/lib/batch.js.map +1 -0
  136. package/dist/src/lib/block-layout.d.ts +160 -0
  137. package/dist/src/lib/block-layout.js +451 -0
  138. package/dist/src/lib/block-layout.js.map +1 -0
  139. package/dist/src/lib/canonical-json.d.ts +12 -0
  140. package/dist/src/lib/canonical-json.js +35 -0
  141. package/dist/src/lib/canonical-json.js.map +1 -0
  142. package/dist/src/lib/channel.d.ts +30 -0
  143. package/dist/src/lib/channel.js +68 -0
  144. package/dist/src/lib/channel.js.map +1 -0
  145. package/dist/src/lib/cli-manifest.d.ts +68 -0
  146. package/dist/src/lib/cli-manifest.js +71 -0
  147. package/dist/src/lib/cli-manifest.js.map +1 -0
  148. package/dist/src/lib/codegen-shared/generatedFiles.d.ts +97 -0
  149. package/dist/src/lib/codegen-shared/generatedFiles.js +184 -0
  150. package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -0
  151. package/dist/src/lib/codegen-shared/prettierStable.d.ts +262 -0
  152. package/dist/src/lib/codegen-shared/prettierStable.js +610 -0
  153. package/dist/src/lib/codegen-shared/prettierStable.js.map +1 -0
  154. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +68 -0
  155. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +168 -0
  156. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -0
  157. package/dist/src/lib/config-object-descriptor.d.ts +108 -0
  158. package/dist/src/lib/config-object-descriptor.js +607 -0
  159. package/dist/src/lib/config-object-descriptor.js.map +1 -0
  160. package/dist/src/lib/config-payload.d.ts +85 -0
  161. package/dist/src/lib/config-payload.js +105 -0
  162. package/dist/src/lib/config-payload.js.map +1 -0
  163. package/dist/src/lib/config-surface.d.ts +93 -0
  164. package/dist/src/lib/config-surface.js +178 -0
  165. package/dist/src/lib/config-surface.js.map +1 -0
  166. package/dist/src/lib/config-toml.d.ts +10 -0
  167. package/dist/src/lib/config-toml.js +42 -0
  168. package/dist/src/lib/config-toml.js.map +1 -0
  169. package/dist/src/lib/config.d.ts +53 -0
  170. package/dist/src/lib/config.js +92 -53
  171. package/dist/src/lib/config.js.map +1 -1
  172. package/dist/src/lib/confirm-prompt.d.ts +83 -0
  173. package/dist/src/lib/confirm-prompt.js +110 -0
  174. package/dist/src/lib/confirm-prompt.js.map +1 -0
  175. package/dist/src/lib/constants.d.ts +11 -0
  176. package/dist/src/lib/constants.js +12 -0
  177. package/dist/src/lib/constants.js.map +1 -0
  178. package/dist/src/lib/crash-handlers.d.ts +20 -0
  179. package/dist/src/lib/crash-handlers.js +49 -0
  180. package/dist/src/lib/crash-handlers.js.map +1 -0
  181. package/dist/src/lib/credentials-store.d.ts +89 -0
  182. package/dist/src/lib/credentials-store.js +330 -0
  183. package/dist/src/lib/credentials-store.js.map +1 -0
  184. package/dist/src/lib/csv.d.ts +47 -0
  185. package/dist/src/lib/csv.js +172 -0
  186. package/dist/src/lib/csv.js.map +1 -0
  187. package/dist/src/lib/data-input.d.ts +23 -0
  188. package/dist/src/lib/data-input.js +50 -0
  189. package/dist/src/lib/data-input.js.map +1 -0
  190. package/dist/src/lib/db-codegen/dbFingerprint.d.ts +10 -0
  191. package/dist/src/lib/db-codegen/dbFingerprint.js +17 -0
  192. package/dist/src/lib/db-codegen/dbFingerprint.js.map +1 -0
  193. package/dist/src/lib/db-codegen/dbGenerator.d.ts +67 -0
  194. package/dist/src/lib/db-codegen/dbGenerator.js +170 -0
  195. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -0
  196. package/dist/src/lib/db-codegen/dbNaming.d.ts +87 -0
  197. package/dist/src/lib/db-codegen/dbNaming.js +180 -0
  198. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -0
  199. package/dist/src/lib/db-codegen/dbTemplates.d.ts +272 -0
  200. package/dist/src/lib/db-codegen/dbTemplates.js +480 -0
  201. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -0
  202. package/dist/src/lib/db-codegen/dbTsTypes.d.ts +73 -0
  203. package/dist/src/lib/db-codegen/dbTsTypes.js +139 -0
  204. package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -0
  205. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +146 -0
  206. package/dist/src/lib/db-codegen/dbTypeIR.js +517 -0
  207. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -0
  208. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.d.ts +112 -0
  209. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js +211 -0
  210. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js.map +1 -0
  211. package/dist/src/lib/env-resolver.d.ts +62 -0
  212. package/dist/src/lib/env-resolver.js +121 -0
  213. package/dist/src/lib/env-resolver.js.map +1 -0
  214. package/dist/src/lib/fetch.d.ts +5 -0
  215. package/dist/src/lib/generated-allowlist.d.ts +28 -0
  216. package/dist/src/lib/generated-allowlist.js +266 -0
  217. package/dist/src/lib/generated-allowlist.js.map +1 -0
  218. package/dist/src/lib/generated-config-surfaces.d.ts +578 -0
  219. package/dist/src/lib/generated-config-surfaces.js +3630 -0
  220. package/dist/src/lib/generated-config-surfaces.js.map +1 -0
  221. package/dist/src/lib/generated-template-lint.d.ts +206 -0
  222. package/dist/src/lib/generated-template-lint.js +589 -0
  223. package/dist/src/lib/generated-template-lint.js.map +1 -0
  224. package/dist/src/lib/generated-workflow-model-fields.d.ts +20 -0
  225. package/dist/src/lib/generated-workflow-model-fields.js +53 -0
  226. package/dist/src/lib/generated-workflow-model-fields.js.map +1 -0
  227. package/dist/src/lib/google-client-secret-status.d.ts +35 -0
  228. package/dist/src/lib/google-client-secret-status.js +56 -0
  229. package/dist/src/lib/google-client-secret-status.js.map +1 -0
  230. package/dist/src/lib/init-config.d.ts +81 -0
  231. package/dist/src/lib/init-config.js +149 -0
  232. package/dist/src/lib/init-config.js.map +1 -0
  233. package/dist/src/lib/log-inspection.d.ts +568 -0
  234. package/dist/src/lib/log-inspection.js +639 -0
  235. package/dist/src/lib/log-inspection.js.map +1 -0
  236. package/dist/src/lib/migration-nag.d.ts +49 -0
  237. package/dist/src/lib/migration-nag.js +163 -0
  238. package/dist/src/lib/migration-nag.js.map +1 -0
  239. package/dist/src/lib/output.d.ts +109 -0
  240. package/dist/src/lib/output.js +191 -8
  241. package/dist/src/lib/output.js.map +1 -1
  242. package/dist/src/lib/package-manager.d.ts +140 -0
  243. package/dist/src/lib/package-manager.js +305 -0
  244. package/dist/src/lib/package-manager.js.map +1 -0
  245. package/dist/src/lib/paginate.d.ts +83 -0
  246. package/dist/src/lib/paginate.js +95 -0
  247. package/dist/src/lib/paginate.js.map +1 -0
  248. package/dist/src/lib/platform-owned.d.ts +51 -0
  249. package/dist/src/lib/platform-owned.js +64 -0
  250. package/dist/src/lib/platform-owned.js.map +1 -0
  251. package/dist/src/lib/project-config.d.ts +97 -0
  252. package/dist/src/lib/project-config.js +219 -0
  253. package/dist/src/lib/project-config.js.map +1 -0
  254. package/dist/src/lib/query-operators.d.ts +43 -0
  255. package/dist/src/lib/query-operators.js +80 -0
  256. package/dist/src/lib/query-operators.js.map +1 -0
  257. package/dist/src/lib/record-filter.d.ts +18 -0
  258. package/dist/src/lib/record-filter.js +55 -0
  259. package/dist/src/lib/record-filter.js.map +1 -0
  260. package/dist/src/lib/refresh-admin-credentials.d.ts +65 -0
  261. package/dist/src/lib/refresh-admin-credentials.js +103 -0
  262. package/dist/src/lib/refresh-admin-credentials.js.map +1 -0
  263. package/dist/src/lib/resolve-init-dev-port.d.ts +56 -0
  264. package/dist/src/lib/resolve-init-dev-port.js +55 -0
  265. package/dist/src/lib/resolve-init-dev-port.js.map +1 -0
  266. package/dist/src/lib/resolve-init-server.d.ts +71 -0
  267. package/dist/src/lib/resolve-init-server.js +94 -0
  268. package/dist/src/lib/resolve-init-server.js.map +1 -0
  269. package/dist/src/lib/resolve-platform.d.ts +45 -0
  270. package/dist/src/lib/resolve-platform.js +43 -0
  271. package/dist/src/lib/resolve-platform.js.map +1 -0
  272. package/dist/src/lib/run-status.d.ts +19 -0
  273. package/dist/src/lib/run-status.generated.d.ts +39 -0
  274. package/dist/src/lib/run-status.generated.js +66 -0
  275. package/dist/src/lib/run-status.generated.js.map +1 -0
  276. package/dist/src/lib/run-status.js +19 -0
  277. package/dist/src/lib/run-status.js.map +1 -0
  278. package/dist/src/lib/signing-secret-status.d.ts +81 -0
  279. package/dist/src/lib/signing-secret-status.js +116 -0
  280. package/dist/src/lib/signing-secret-status.js.map +1 -0
  281. package/dist/src/lib/skill-installer.d.ts +25 -0
  282. package/dist/src/lib/skill-installer.js +266 -0
  283. package/dist/src/lib/skill-installer.js.map +1 -0
  284. package/dist/src/lib/snapshots.d.ts +99 -0
  285. package/dist/src/lib/snapshots.js +357 -0
  286. package/dist/src/lib/snapshots.js.map +1 -0
  287. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +100 -0
  288. package/dist/src/lib/swift-codegen/dbGenerator.js +682 -0
  289. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -0
  290. package/dist/src/lib/swift-codegen/dbSwiftTypes.d.ts +42 -0
  291. package/dist/src/lib/swift-codegen/dbSwiftTypes.js +100 -0
  292. package/dist/src/lib/swift-codegen/dbSwiftTypes.js.map +1 -0
  293. package/dist/src/lib/swift-codegen/generator.d.ts +85 -0
  294. package/dist/src/lib/swift-codegen/generator.js +266 -0
  295. package/dist/src/lib/swift-codegen/generator.js.map +1 -0
  296. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +72 -0
  297. package/dist/src/lib/swift-codegen/schemaToSwift.js +644 -0
  298. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -0
  299. package/dist/src/lib/swift-codegen/siblingSymbols.d.ts +90 -0
  300. package/dist/src/lib/swift-codegen/siblingSymbols.js +152 -0
  301. package/dist/src/lib/swift-codegen/siblingSymbols.js.map +1 -0
  302. package/dist/src/lib/swift-codegen/swiftNaming.d.ts +85 -0
  303. package/dist/src/lib/swift-codegen/swiftNaming.js +198 -0
  304. package/dist/src/lib/swift-codegen/swiftNaming.js.map +1 -0
  305. package/dist/src/lib/sync-paths.d.ts +72 -0
  306. package/dist/src/lib/sync-paths.js +130 -0
  307. package/dist/src/lib/sync-paths.js.map +1 -0
  308. package/dist/src/lib/sync-resource-types.d.ts +445 -0
  309. package/dist/src/lib/sync-resource-types.js +812 -0
  310. package/dist/src/lib/sync-resource-types.js.map +1 -0
  311. package/dist/src/lib/sync-selectors.d.ts +95 -0
  312. package/dist/src/lib/sync-selectors.js +228 -0
  313. package/dist/src/lib/sync-selectors.js.map +1 -0
  314. package/dist/src/lib/template.d.ts +121 -0
  315. package/dist/src/lib/template.js +447 -67
  316. package/dist/src/lib/template.js.map +1 -1
  317. package/dist/src/lib/token-inject.d.ts +56 -0
  318. package/dist/src/lib/token-inject.js +204 -0
  319. package/dist/src/lib/token-inject.js.map +1 -0
  320. package/dist/src/lib/toml-database-config.d.ts +123 -0
  321. package/dist/src/lib/toml-database-config.js +527 -0
  322. package/dist/src/lib/toml-database-config.js.map +1 -0
  323. package/dist/src/lib/toml-metadata-config.d.ts +151 -0
  324. package/dist/src/lib/toml-metadata-config.js +476 -0
  325. package/dist/src/lib/toml-metadata-config.js.map +1 -0
  326. package/dist/src/lib/toml-native-form.d.ts +46 -0
  327. package/dist/src/lib/toml-native-form.js +78 -0
  328. package/dist/src/lib/toml-native-form.js.map +1 -0
  329. package/dist/src/lib/toml-params-validator.d.ts +129 -0
  330. package/dist/src/lib/toml-params-validator.js +298 -0
  331. package/dist/src/lib/toml-params-validator.js.map +1 -0
  332. package/dist/src/lib/toml-scalar-edit.d.ts +43 -0
  333. package/dist/src/lib/toml-scalar-edit.js +283 -0
  334. package/dist/src/lib/toml-scalar-edit.js.map +1 -0
  335. package/dist/src/lib/user-selector.d.ts +24 -0
  336. package/dist/src/lib/user-selector.js +33 -0
  337. package/dist/src/lib/user-selector.js.map +1 -0
  338. package/dist/src/lib/version-check.d.ts +35 -0
  339. package/dist/src/lib/version-check.js +241 -0
  340. package/dist/src/lib/version-check.js.map +1 -0
  341. package/dist/src/lib/watch.d.ts +121 -0
  342. package/dist/src/lib/watch.js +169 -0
  343. package/dist/src/lib/watch.js.map +1 -0
  344. package/dist/src/lib/workflow-apply.d.ts +51 -0
  345. package/dist/src/lib/workflow-apply.js +89 -0
  346. package/dist/src/lib/workflow-apply.js.map +1 -0
  347. package/dist/src/lib/workflow-codegen/generated-schema-descriptor.d.ts +129 -0
  348. package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js +269 -0
  349. package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js.map +1 -0
  350. package/dist/src/lib/workflow-codegen/generator.d.ts +96 -0
  351. package/dist/src/lib/workflow-codegen/generator.js +361 -0
  352. package/dist/src/lib/workflow-codegen/generator.js.map +1 -0
  353. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +83 -0
  354. package/dist/src/lib/workflow-codegen/invokerIR.js +71 -0
  355. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -0
  356. package/dist/src/lib/workflow-codegen/naming.d.ts +33 -0
  357. package/dist/src/lib/workflow-codegen/naming.js +81 -0
  358. package/dist/src/lib/workflow-codegen/naming.js.map +1 -0
  359. package/dist/src/lib/workflow-codegen/schemaToTs.d.ts +80 -0
  360. package/dist/src/lib/workflow-codegen/schemaToTs.js +303 -0
  361. package/dist/src/lib/workflow-codegen/schemaToTs.js.map +1 -0
  362. package/dist/src/lib/workflow-config-apply.d.ts +70 -0
  363. package/dist/src/lib/workflow-config-apply.js +137 -0
  364. package/dist/src/lib/workflow-config-apply.js.map +1 -0
  365. package/dist/src/lib/workflow-config-sidecar.d.ts +63 -0
  366. package/dist/src/lib/workflow-config-sidecar.js +96 -0
  367. package/dist/src/lib/workflow-config-sidecar.js.map +1 -0
  368. package/dist/src/lib/workflow-field-descriptor.d.ts +91 -0
  369. package/dist/src/lib/workflow-field-descriptor.js +153 -0
  370. package/dist/src/lib/workflow-field-descriptor.js.map +1 -0
  371. package/dist/src/lib/workflow-fragments.d.ts +64 -0
  372. package/dist/src/lib/workflow-fragments.js +342 -0
  373. package/dist/src/lib/workflow-fragments.js.map +1 -0
  374. package/dist/src/lib/workflow-include-preserve.d.ts +71 -0
  375. package/dist/src/lib/workflow-include-preserve.js +153 -0
  376. package/dist/src/lib/workflow-include-preserve.js.map +1 -0
  377. package/dist/src/lib/workflow-payload.d.ts +86 -0
  378. package/dist/src/lib/workflow-payload.js +168 -0
  379. package/dist/src/lib/workflow-payload.js.map +1 -0
  380. package/dist/src/lib/workflow-toml-validator.d.ts +199 -0
  381. package/dist/src/lib/workflow-toml-validator.js +754 -0
  382. package/dist/src/lib/workflow-toml-validator.js.map +1 -0
  383. package/dist/src/types/index.d.ts +533 -0
  384. package/dist/src/validators.d.ts +65 -0
  385. package/dist/src/validators.js +64 -0
  386. package/dist/src/validators.js.map +1 -0
  387. package/package.json +32 -6
@@ -1,57 +1,229 @@
1
1
  import { ApiClient } from "../lib/api-client.js";
2
2
  import { resolveAppId } from "../lib/config.js";
3
- import { error, info, keyValue, formatTable, formatId, formatDate, formatNumber, formatPercent, formatDuration, json, divider, heading, } from "../lib/output.js";
3
+ import { error, info, formatTable, formatId, formatDate, formatNumber, formatPercent, formatDuration, json, heading, result as printResult, dim, } from "../lib/output.js";
4
+ import { buildActivityEnvelope } from "../lib/log-inspection.js";
5
+ /** Format a value that is already a percentage (e.g. 33.3 → "33.3%") */
6
+ function formatPctRaw(value) {
7
+ if (value === undefined || value === null)
8
+ return "-";
9
+ return `${value.toFixed(1)}%`;
10
+ }
4
11
  export function registerAnalyticsCommands(program) {
5
12
  const analytics = program
6
13
  .command("analytics")
7
14
  .description("View usage analytics, user activity, and integration metrics")
8
15
  .addHelpText("after", `
16
+ Commands:
17
+ overview DAU / WAU / MAU and growth accounting
18
+ daily-active Daily active users time series
19
+ rolling-active Rolling active users (28 points)
20
+ cohort-retention Weekly cohort retention matrix
21
+ top-users Most active users
22
+ user-search Search users by email or ULID
23
+ user-detail Detailed activity for a single user
24
+ user-snapshot Latest context snapshot for a user
25
+ events Paginated event feed
26
+ events-grouped Events grouped by a dimension
27
+ integrations Integration usage metrics
28
+ workflows Top workflows by runs
29
+ prompts Top prompts by executions
30
+
9
31
  Examples:
10
32
  $ primitive analytics overview
11
- $ primitive analytics top-users --window-days 7 --limit 20
12
- $ primitive analytics integrations
33
+ $ primitive analytics daily-active --window-days 14
34
+ $ primitive analytics top-users --limit 20
35
+ $ primitive analytics user-search --query user@example.com
36
+ $ primitive analytics user-detail <user-ulid>
37
+ $ primitive analytics events --window-days 7 --page 0
38
+ $ primitive analytics events-grouped --group-by feature
39
+ $ primitive analytics cohort-retention
40
+ $ primitive analytics workflows --limit 5
41
+ $ primitive analytics prompts --window-days 14
13
42
  `);
14
- // Overview
43
+ // ── Overview (DAU / WAU / MAU / Growth) ──────────────────────────
15
44
  analytics
16
45
  .command("overview")
17
- .description("Get analytics overview for an app")
46
+ .description("Show DAU, WAU, MAU, and growth accounting")
18
47
  .argument("[app-id]", "App ID (uses current app if not specified)")
19
48
  .option("--app <app-id>", "App ID")
20
- .option("--window-days <n>", "Time window in days", "30")
49
+ .option("--window-days <n>", "Growth window in days", "28")
21
50
  .option("--json", "Output as JSON")
22
51
  .action(async (appId, options) => {
23
52
  const resolvedAppId = resolveAppId(appId, options);
24
53
  const client = new ApiClient();
25
54
  try {
26
- const result = await client.getAnalyticsOverview(resolvedAppId, {
55
+ const [dau, wau, mau, growth] = await Promise.all([
56
+ client.getAnalyticsOverviewDau(resolvedAppId),
57
+ client.getAnalyticsOverviewWau(resolvedAppId),
58
+ client.getAnalyticsOverviewMau(resolvedAppId),
59
+ client.getAnalyticsOverviewGrowth(resolvedAppId, {
60
+ windowDays: parseInt(options.windowDays),
61
+ }),
62
+ ]);
63
+ if (options.json) {
64
+ json({ dau, wau, mau, growth });
65
+ return;
66
+ }
67
+ heading("Active Users");
68
+ console.log();
69
+ const formatDelta = (d) => d > 0 ? `+${(d * 100).toFixed(1)}%` : d === 0 ? "0%" : `${(d * 100).toFixed(1)}%`;
70
+ console.log(formatTable([
71
+ { metric: "DAU", value: dau.value, previous: dau.previous, delta: formatDelta(dau.deltaPct) },
72
+ { metric: "WAU", value: wau.value, previous: wau.previous, delta: formatDelta(wau.deltaPct) },
73
+ { metric: "MAU", value: mau.value, previous: mau.previous, delta: formatDelta(mau.deltaPct) },
74
+ ], [
75
+ { header: "METRIC", key: "metric" },
76
+ { header: "CURRENT", key: "value", align: "right", format: formatNumber },
77
+ { header: "PREVIOUS", key: "previous", align: "right", format: formatNumber },
78
+ { header: "CHANGE", key: "delta", align: "right" },
79
+ ]));
80
+ console.log();
81
+ heading(`Growth Accounting (${growth.window_days} days)`);
82
+ console.log();
83
+ printResult("Current active", String(growth.current_active));
84
+ printResult("Previous active", String(growth.previous_active));
85
+ printResult("New users", String(growth.new_users));
86
+ printResult("Retained", String(growth.retained_users));
87
+ printResult("Reactivated", String(growth.reactivated_users));
88
+ printResult("Churned", String(growth.churned_users));
89
+ printResult("Delta", formatDelta(growth.deltaPct));
90
+ }
91
+ catch (err) {
92
+ error(err.message);
93
+ process.exit(1);
94
+ }
95
+ });
96
+ // ── Daily Active ─────────────────────────────────────────────────
97
+ analytics
98
+ .command("daily-active")
99
+ .description("Daily active users time series")
100
+ .argument("[app-id]", "App ID (uses current app if not specified)")
101
+ .option("--app <app-id>", "App ID")
102
+ .option("--window-days <n>", "Time window in days (7-90)", "28")
103
+ .option("--json", "Output as JSON")
104
+ .action(async (appId, options) => {
105
+ const resolvedAppId = resolveAppId(appId, options);
106
+ const client = new ApiClient();
107
+ try {
108
+ const result = await client.getAnalyticsDailyActive(resolvedAppId, {
27
109
  windowDays: parseInt(options.windowDays),
28
110
  });
29
111
  if (options.json) {
30
112
  json(result);
31
113
  return;
32
114
  }
33
- heading(`Analytics Overview (${result.windowDays} days)`);
115
+ heading(`Daily Active Users (${result.window_days} days)`);
34
116
  console.log();
35
- keyValue("Daily Active Users (DAU)", formatNumber(result.totals.dau));
36
- keyValue("Weekly Active Users (WAU)", formatNumber(result.totals.wau));
37
- keyValue("Monthly Active Users (MAU)", formatNumber(result.totals.mau));
38
- keyValue("Total Events", formatNumber(result.totals.totalEvents));
39
- if (result.series && result.series.length > 0) {
40
- divider();
41
- info("Activity Series:");
42
- console.log(formatTable(result.series.slice(-10), [
43
- { header: "DATE", key: "bucketStart", format: (v) => v.slice(0, 10) },
44
- { header: "USERS", key: "activeUsers", align: "right" },
45
- { header: "EVENTS", key: "totalEvents", align: "right" },
46
- ]));
117
+ if (!result.rows || result.rows.length === 0) {
118
+ info("No data found.");
119
+ return;
47
120
  }
121
+ console.log(formatTable(result.rows, [
122
+ { header: "DATE", key: "day_label" },
123
+ { header: "ACTIVE USERS", key: "active_users", align: "right", format: formatNumber },
124
+ ]));
48
125
  }
49
126
  catch (err) {
50
127
  error(err.message);
51
128
  process.exit(1);
52
129
  }
53
130
  });
54
- // Top users
131
+ // ── Rolling Active ───────────────────────────────────────────────
132
+ analytics
133
+ .command("rolling-active")
134
+ .description("Rolling active users (28 data points)")
135
+ .argument("[app-id]", "App ID (uses current app if not specified)")
136
+ .option("--app <app-id>", "App ID")
137
+ .option("--window-days <n>", "Rolling window size in days (1-28)", "7")
138
+ .option("--json", "Output as JSON")
139
+ .action(async (appId, options) => {
140
+ const resolvedAppId = resolveAppId(appId, options);
141
+ const client = new ApiClient();
142
+ try {
143
+ const result = await client.getAnalyticsRollingActive(resolvedAppId, {
144
+ windowDays: parseInt(options.windowDays),
145
+ });
146
+ if (options.json) {
147
+ json(result);
148
+ return;
149
+ }
150
+ heading(`Rolling Active Users (${result.window_days}-day window)`);
151
+ console.log();
152
+ if (!result.rows || result.rows.length === 0) {
153
+ info("No data found.");
154
+ return;
155
+ }
156
+ console.log(formatTable(result.rows, [
157
+ { header: "DATE", key: "day_label" },
158
+ { header: "ACTIVE USERS", key: "active_users", align: "right", format: formatNumber },
159
+ ]));
160
+ }
161
+ catch (err) {
162
+ error(err.message);
163
+ process.exit(1);
164
+ }
165
+ });
166
+ // ── Cohort Retention ─────────────────────────────────────────────
167
+ analytics
168
+ .command("cohort-retention")
169
+ .description("Weekly cohort retention matrix")
170
+ .argument("[app-id]", "App ID (uses current app if not specified)")
171
+ .option("--app <app-id>", "App ID")
172
+ .option("--json", "Output as JSON")
173
+ .action(async (appId, options) => {
174
+ const resolvedAppId = resolveAppId(appId, options);
175
+ const client = new ApiClient();
176
+ try {
177
+ const result = await client.getAnalyticsCohortRetention(resolvedAppId);
178
+ if (options.json) {
179
+ json(result);
180
+ return;
181
+ }
182
+ heading("Cohort Retention");
183
+ console.log();
184
+ if (!result.rows || result.rows.length === 0) {
185
+ info("No cohort data found.");
186
+ return;
187
+ }
188
+ // Build week headers
189
+ const weekHeaders = result.weeks.map((w) => `W${w}`);
190
+ // Build table rows with retention percentages
191
+ const tableRows = result.rows.map((row) => {
192
+ const entry = {
193
+ cohort: row.signup_week_label,
194
+ size: row.cohort_size,
195
+ };
196
+ row.retention.forEach((r, i) => {
197
+ entry[`w${result.weeks[i]}`] =
198
+ r !== null ? `${r.toFixed(0)}%` : "-";
199
+ });
200
+ return entry;
201
+ });
202
+ const columns = [
203
+ { header: "COHORT", key: "cohort" },
204
+ { header: "SIZE", key: "size", align: "right", format: formatNumber },
205
+ ...weekHeaders.map((h, i) => ({
206
+ header: h,
207
+ key: `w${result.weeks[i]}`,
208
+ align: "right",
209
+ })),
210
+ ];
211
+ console.log(formatTable(tableRows, columns));
212
+ // Print averages row
213
+ if (result.averages) {
214
+ const avgStr = result.averages
215
+ .map((a) => a !== null ? `${a.toFixed(0)}%` : "-")
216
+ .join(" ");
217
+ console.log();
218
+ dim(`Averages: ${avgStr}`);
219
+ }
220
+ }
221
+ catch (err) {
222
+ error(err.message);
223
+ process.exit(1);
224
+ }
225
+ });
226
+ // ── Top Users ────────────────────────────────────────────────────
55
227
  analytics
56
228
  .command("top-users")
57
229
  .description("Get top users by activity")
@@ -80,6 +252,7 @@ Examples:
80
252
  }
81
253
  console.log(formatTable(result.results, [
82
254
  { header: "USER", key: "userUlid", format: formatId },
255
+ { header: "EMAIL", key: "email" },
83
256
  { header: "EVENTS", key: "eventCount", align: "right" },
84
257
  { header: "FIRST SEEN", key: "firstSeen", format: formatDate },
85
258
  { header: "LAST SEEN", key: "lastSeen", format: formatDate },
@@ -90,53 +263,93 @@ Examples:
90
263
  process.exit(1);
91
264
  }
92
265
  });
93
- // User details
266
+ // ── User Search ──────────────────────────────────────────────────
94
267
  analytics
95
- .command("user")
96
- .description("Get analytics for a specific user")
268
+ .command("user-search")
269
+ .description("Search users by email or ULID")
97
270
  .argument("[app-id]", "App ID (uses current app if not specified)")
98
- .argument("<user-ulid>", "User ULID")
99
271
  .option("--app <app-id>", "App ID")
100
- .option("--window-days <n>", "Time window in days", "30")
272
+ .requiredOption("--query <q>", "Email or ULID to search for")
273
+ .option("--limit <n>", "Max results", "25")
101
274
  .option("--json", "Output as JSON")
102
- .action(async (appIdOrUserUlid, userUlidOrUndefined, options) => {
103
- let resolvedAppId;
104
- let userUlid;
105
- if (userUlidOrUndefined) {
106
- resolvedAppId = resolveAppId(appIdOrUserUlid, options);
107
- userUlid = userUlidOrUndefined;
275
+ .action(async (appId, options) => {
276
+ const resolvedAppId = resolveAppId(appId, options);
277
+ const client = new ApiClient();
278
+ try {
279
+ const result = await client.getAnalyticsUserSearch(resolvedAppId, {
280
+ q: options.query,
281
+ limit: parseInt(options.limit),
282
+ });
283
+ if (options.json) {
284
+ json(result);
285
+ return;
286
+ }
287
+ heading(`User Search: "${result.query}"`);
288
+ console.log();
289
+ if (!result.results || result.results.length === 0) {
290
+ info("No users found.");
291
+ return;
292
+ }
293
+ console.log(formatTable(result.results, [
294
+ { header: "USER", key: "userUlid", format: formatId },
295
+ { header: "EMAIL", key: "email" },
296
+ { header: "NAME", key: "name" },
297
+ { header: "EVENTS", key: "eventCount", align: "right" },
298
+ { header: "LAST SEEN", key: "lastSeen", format: formatDate },
299
+ ]));
108
300
  }
109
- else {
110
- resolvedAppId = resolveAppId(undefined, options);
111
- userUlid = appIdOrUserUlid;
301
+ catch (err) {
302
+ error(err.message);
303
+ process.exit(1);
112
304
  }
305
+ });
306
+ // ── User Detail ──────────────────────────────────────────────────
307
+ analytics
308
+ .command("user-detail")
309
+ .description("Detailed activity for a single user")
310
+ .argument("<user-ulid>", "User ULID")
311
+ .argument("[app-id]", "App ID (uses current app if not specified)")
312
+ .option("--app <app-id>", "App ID")
313
+ .option("--json", "Output as JSON")
314
+ .action(async (userUlid, appId, options) => {
315
+ const resolvedAppId = resolveAppId(appId, options);
113
316
  const client = new ApiClient();
114
317
  try {
115
- const result = await client.getAnalyticsUserTimeline(resolvedAppId, userUlid, {
116
- windowDays: parseInt(options.windowDays),
117
- });
318
+ const result = await client.getAnalyticsUserDetail(resolvedAppId, userUlid);
118
319
  if (options.json) {
119
320
  json(result);
120
321
  return;
121
322
  }
122
- heading(`User Activity (${result.windowDays} days)`);
123
- keyValue("User", userUlid);
323
+ heading("User Detail");
324
+ console.log();
325
+ printResult("ULID", result.user.user_ulid);
326
+ if (result.user.email)
327
+ printResult("Email", result.user.email);
328
+ if (result.user.name)
329
+ printResult("Name", result.user.name);
124
330
  console.log();
125
- if (result.breakdown && result.breakdown.length > 0) {
126
- info("Activity Breakdown:");
127
- console.log(formatTable(result.breakdown.slice(0, 15), [
331
+ printResult("First seen", result.stats.first_seen ? formatDate(result.stats.first_seen) : "-");
332
+ printResult("Last active", result.stats.last_active ? formatDate(result.stats.last_active) : "-");
333
+ printResult("Total events", String(result.stats.total_events));
334
+ printResult("Days active", String(result.stats.days_active));
335
+ if (result.events_by_action?.length > 0) {
336
+ console.log();
337
+ heading("Events by Action");
338
+ console.log();
339
+ console.log(formatTable(result.events_by_action, [
128
340
  { header: "ACTION", key: "action" },
129
- { header: "FEATURE", key: "feature" },
130
- { header: "ROUTE", key: "route" },
131
- { header: "EVENTS", key: "events", align: "right" },
341
+ { header: "COUNT", key: "event_count", align: "right", format: formatNumber },
342
+ { header: "LAST OCCURRED", key: "last_occurred", format: formatDate },
132
343
  ]));
133
344
  }
134
- if (result.timeline && result.timeline.length > 0) {
135
- divider();
136
- info("Recent Timeline:");
137
- console.log(formatTable(result.timeline.slice(-10), [
138
- { header: "TIME", key: "bucketStart", format: formatDate },
139
- { header: "EVENTS", key: "events", align: "right" },
345
+ if (result.events_by_feature?.length > 0) {
346
+ console.log();
347
+ heading("Events by Feature");
348
+ console.log();
349
+ console.log(formatTable(result.events_by_feature, [
350
+ { header: "FEATURE", key: "feature" },
351
+ { header: "COUNT", key: "event_count", align: "right", format: formatNumber },
352
+ { header: "PCT", key: "pct", align: "right", format: formatPctRaw },
140
353
  ]));
141
354
  }
142
355
  }
@@ -145,7 +358,212 @@ Examples:
145
358
  process.exit(1);
146
359
  }
147
360
  });
148
- // Integration metrics
361
+ // ── User Snapshot ────────────────────────────────────────────────
362
+ analytics
363
+ .command("user-snapshot")
364
+ .description("Latest context snapshot for a user")
365
+ .argument("<user-ulid>", "User ULID")
366
+ .argument("[app-id]", "App ID (uses current app if not specified)")
367
+ .option("--app <app-id>", "App ID")
368
+ .option("--json", "Output as JSON")
369
+ .action(async (userUlid, appId, options) => {
370
+ const resolvedAppId = resolveAppId(appId, options);
371
+ const client = new ApiClient();
372
+ try {
373
+ const result = await client.getAnalyticsUserSnapshot(resolvedAppId, userUlid);
374
+ if (options.json) {
375
+ json(result);
376
+ return;
377
+ }
378
+ heading("User Snapshot");
379
+ console.log();
380
+ if (!result.snapshot) {
381
+ info("No snapshot found for this user.");
382
+ return;
383
+ }
384
+ printResult("Timestamp", formatDate(result.snapshot.timestamp));
385
+ console.log();
386
+ console.log(JSON.stringify(result.snapshot.values, null, 2));
387
+ }
388
+ catch (err) {
389
+ error(err.message);
390
+ process.exit(1);
391
+ }
392
+ });
393
+ // ── Events Feed ──────────────────────────────────────────────────
394
+ analytics
395
+ .command("events")
396
+ .description("Paginated event feed")
397
+ .argument("[app-id]", "App ID (uses current app if not specified)")
398
+ .option("--app <app-id>", "App ID")
399
+ .option("--window-days <n>", "Time window in days", "7")
400
+ .option("--page <n>", "Page number (0-based)", "0")
401
+ .option("--user-id <id>", "Filter to a single user's events")
402
+ .option("--json", "Output as JSON")
403
+ .action(async (appId, options) => {
404
+ const resolvedAppId = resolveAppId(appId, options);
405
+ const client = new ApiClient();
406
+ try {
407
+ const result = await client.getAnalyticsEvents(resolvedAppId, {
408
+ windowDays: parseInt(options.windowDays),
409
+ page: parseInt(options.page),
410
+ // The events feed filters by user via the bracketed
411
+ // `filter[user][is]` syntax the analytics route already parses — not
412
+ // a raw query param (behavior 11).
413
+ ...(options.userId ? { "filter[user][is]": options.userId } : {}),
414
+ });
415
+ if (options.json) {
416
+ // Normalize the offset-paged response to the shared activity
417
+ // envelope: `{page_size, rows}` → `{pageSize, items}` with the
418
+ // activity allowlist dropping infra fields such as `colo`
419
+ // (behaviors 7, 9).
420
+ json(buildActivityEnvelope(result));
421
+ return;
422
+ }
423
+ heading(`Events (page ${result.page}, ${result.total_rows} total)`);
424
+ console.log();
425
+ if (!result.rows || result.rows.length === 0) {
426
+ info("No events found.");
427
+ return;
428
+ }
429
+ console.log(formatTable(result.rows, [
430
+ { header: "TIME", key: "timestamp", format: formatDate },
431
+ { header: "USER", key: "user_ulid", format: formatId },
432
+ { header: "ACTION", key: "action" },
433
+ { header: "FEATURE", key: "feature" },
434
+ { header: "ROUTE", key: "route" },
435
+ { header: "COUNTRY", key: "country" },
436
+ ]));
437
+ const totalPages = Math.ceil(result.total_rows / result.page_size);
438
+ if (result.page + 1 < totalPages) {
439
+ console.log();
440
+ dim(`Page ${result.page + 1} of ${totalPages}. Use --page ${result.page + 1} for the next page.`);
441
+ }
442
+ }
443
+ catch (err) {
444
+ error(err.message);
445
+ process.exit(1);
446
+ }
447
+ });
448
+ // ── Events Grouped ───────────────────────────────────────────────
449
+ analytics
450
+ .command("events-grouped")
451
+ .description("Events grouped by a dimension")
452
+ .argument("[app-id]", "App ID (uses current app if not specified)")
453
+ .option("--app <app-id>", "App ID")
454
+ .option("--group-by <dim>", "Dimension: action, feature, route, country, deviceType, plan, day", "action")
455
+ .option("--window-days <n>", "Time window in days", "7")
456
+ .option("--json", "Output as JSON")
457
+ .action(async (appId, options) => {
458
+ const resolvedAppId = resolveAppId(appId, options);
459
+ const client = new ApiClient();
460
+ try {
461
+ const result = await client.getAnalyticsEventsGrouped(resolvedAppId, {
462
+ groupBy: options.groupBy,
463
+ windowDays: parseInt(options.windowDays),
464
+ });
465
+ if (options.json) {
466
+ json(result);
467
+ return;
468
+ }
469
+ heading(`Events by ${result.group_by}`);
470
+ console.log();
471
+ if (!result.rows || result.rows.length === 0) {
472
+ info("No events found.");
473
+ return;
474
+ }
475
+ console.log(formatTable(result.rows, [
476
+ { header: result.group_by.toUpperCase(), key: "group_value" },
477
+ { header: "EVENTS", key: "events", align: "right", format: formatNumber },
478
+ { header: "UNIQUE USERS", key: "unique_users", align: "right", format: formatNumber },
479
+ ]));
480
+ }
481
+ catch (err) {
482
+ error(err.message);
483
+ process.exit(1);
484
+ }
485
+ });
486
+ // ── Errors Grouped ───────────────────────────────────────────────
487
+ analytics
488
+ .command("errors-groups")
489
+ .description("Group failure events by fingerprint with per-day count buckets")
490
+ .argument("[app-id]", "App ID (uses current app if not specified)")
491
+ .option("--app <app-id>", "App ID")
492
+ .option("--window-days <n>", "Time window in days", "7")
493
+ .option("--limit <n>", "Max error groups to return", "50")
494
+ .option("--status-class <class>", "Filter by status class: 4xx, 5xx, transport")
495
+ .option("--source <source>", "Filter by source: workflow_run, workflow_step, integration")
496
+ .option("--verbose", "Also print each group's exemplar (a raw sample of the failure) and where it came from")
497
+ .option("--json", "Output as JSON")
498
+ .action(async (appId, options) => {
499
+ const resolvedAppId = resolveAppId(appId, options);
500
+ const client = new ApiClient();
501
+ try {
502
+ const params = {
503
+ windowDays: parseInt(options.windowDays),
504
+ limit: parseInt(options.limit),
505
+ };
506
+ if (options.statusClass) {
507
+ params["filter[statusClass][is]"] = options.statusClass;
508
+ }
509
+ if (options.source) {
510
+ params["filter[source][is]"] = options.source;
511
+ }
512
+ const result = await client.getAnalyticsErrorsGroups(resolvedAppId, params);
513
+ if (options.json) {
514
+ json(result);
515
+ return;
516
+ }
517
+ heading(`Error groups (last ${result.window_days} days)`);
518
+ console.log();
519
+ if (!result.rows || result.rows.length === 0) {
520
+ info("No error groups found.");
521
+ return;
522
+ }
523
+ console.log(formatTable(result.rows, [
524
+ { header: "TITLE", key: "normalized_title" },
525
+ { header: "SOURCE", key: "source" },
526
+ { header: "STATUS", key: "status_class" },
527
+ {
528
+ header: "TOTAL",
529
+ key: "total",
530
+ align: "right",
531
+ format: formatNumber,
532
+ },
533
+ {
534
+ header: "DAYS",
535
+ key: "daily",
536
+ align: "right",
537
+ format: (d) => formatNumber(Array.isArray(d) ? d.length : 0),
538
+ },
539
+ { header: "LAST SEEN", key: "last_seen", format: formatDate },
540
+ { header: "FINGERPRINT", key: "fingerprint", format: formatId },
541
+ ]));
542
+ // The normalized title is a grouping key, not an explanation — the
543
+ // exemplar is the raw sample plus the run/step it came from, which is
544
+ // what makes a group actionable without paging `analytics events`.
545
+ if (options.verbose) {
546
+ for (const row of result.rows) {
547
+ console.log();
548
+ heading(row.normalized_title || row.fingerprint);
549
+ printResult("Seen", `${row.first_seen ? formatDate(row.first_seen) : "-"} → ${row.last_seen ? formatDate(row.last_seen) : "-"}`);
550
+ if (!row.exemplar) {
551
+ info("No exemplar available for this group.");
552
+ continue;
553
+ }
554
+ printResult("Example", row.exemplar.message);
555
+ printResult("Scope", row.exemplar.scope_key || "-");
556
+ printResult("Step", row.exemplar.step_id || "-");
557
+ printResult("Run", row.exemplar.run_id || "-");
558
+ }
559
+ }
560
+ }
561
+ catch (err) {
562
+ error(err.message);
563
+ process.exit(1);
564
+ }
565
+ });
566
+ // ── Integration Metrics ──────────────────────────────────────────
149
567
  analytics
150
568
  .command("integrations")
151
569
  .description("Get integration usage metrics")
@@ -174,8 +592,89 @@ Examples:
174
592
  { header: "INTEGRATION", key: "integrationKey" },
175
593
  { header: "CALLS", key: "invocations", align: "right", format: formatNumber },
176
594
  { header: "ERROR RATE", key: "errorRate", align: "right", format: formatPercent },
177
- { header: "AVG LATENCY", key: "avgDurationMs", align: "right", format: formatDuration },
178
- { header: "P95 LATENCY", key: "p95DurationMs", align: "right", format: formatDuration },
595
+ { header: "MEDIAN", key: "medianDurationMs", align: "right", format: formatDuration },
596
+ { header: "P95", key: "p95DurationMs", align: "right", format: formatDuration },
597
+ ]));
598
+ }
599
+ catch (err) {
600
+ error(err.message);
601
+ process.exit(1);
602
+ }
603
+ });
604
+ // ── Top Workflows ────────────────────────────────────────────────
605
+ analytics
606
+ .command("workflows")
607
+ .description("Top workflows by runs")
608
+ .argument("[app-id]", "App ID (uses current app if not specified)")
609
+ .option("--app <app-id>", "App ID")
610
+ .option("--window-days <n>", "Time window in days", "30")
611
+ .option("--limit <n>", "Number of workflows to show", "10")
612
+ .option("--json", "Output as JSON")
613
+ .action(async (appId, options) => {
614
+ const resolvedAppId = resolveAppId(appId, options);
615
+ const client = new ApiClient();
616
+ try {
617
+ const result = await client.getAnalyticsTopWorkflows(resolvedAppId, {
618
+ windowDays: parseInt(options.windowDays),
619
+ limit: parseInt(options.limit),
620
+ });
621
+ if (options.json) {
622
+ json(result);
623
+ return;
624
+ }
625
+ heading(`Top Workflows (${result.windowDays} days)`);
626
+ console.log();
627
+ if (!result.workflows || result.workflows.length === 0) {
628
+ info("No workflow data found.");
629
+ return;
630
+ }
631
+ console.log(formatTable(result.workflows, [
632
+ { header: "WORKFLOW", key: "workflowKey" },
633
+ { header: "RUNS", key: "runs", align: "right", format: formatNumber },
634
+ { header: "SUCCESS", key: "successRate", align: "right", format: formatPercent },
635
+ { header: "MEDIAN", key: "medianDurationMs", align: "right", format: formatDuration },
636
+ { header: "P95", key: "p95", align: "right", format: formatDuration },
637
+ { header: "TOKENS", key: "totalTokens", align: "right", format: formatNumber },
638
+ ]));
639
+ }
640
+ catch (err) {
641
+ error(err.message);
642
+ process.exit(1);
643
+ }
644
+ });
645
+ // ── Top Prompts ──────────────────────────────────────────────────
646
+ analytics
647
+ .command("prompts")
648
+ .description("Top prompts by executions")
649
+ .argument("[app-id]", "App ID (uses current app if not specified)")
650
+ .option("--app <app-id>", "App ID")
651
+ .option("--window-days <n>", "Time window in days", "30")
652
+ .option("--limit <n>", "Number of prompts to show", "10")
653
+ .option("--json", "Output as JSON")
654
+ .action(async (appId, options) => {
655
+ const resolvedAppId = resolveAppId(appId, options);
656
+ const client = new ApiClient();
657
+ try {
658
+ const result = await client.getAnalyticsTopPrompts(resolvedAppId, {
659
+ windowDays: parseInt(options.windowDays),
660
+ limit: parseInt(options.limit),
661
+ });
662
+ if (options.json) {
663
+ json(result);
664
+ return;
665
+ }
666
+ heading(`Top Prompts (${result.windowDays} days)`);
667
+ console.log();
668
+ if (!result.prompts || result.prompts.length === 0) {
669
+ info("No prompt data found.");
670
+ return;
671
+ }
672
+ console.log(formatTable(result.prompts, [
673
+ { header: "PROMPT", key: "promptKey" },
674
+ { header: "RUNS", key: "executions", align: "right", format: formatNumber },
675
+ { header: "MEDIAN", key: "medianDurationMs", align: "right", format: formatDuration },
676
+ { header: "P95", key: "p95DurationMs", align: "right", format: formatDuration },
677
+ { header: "TOKENS", key: "totalTokens", align: "right", format: formatNumber },
179
678
  ]));
180
679
  }
181
680
  catch (err) {