primitive-admin 1.1.0-alpha.9 → 1.1.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.
- package/README.md +523 -109
- package/assets/skill/skills/primitive-platform/SKILL.md +289 -0
- package/dist/bin/primitive.d.ts +2 -0
- package/dist/bin/primitive.js +372 -21
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/admins.d.ts +2 -0
- package/dist/src/commands/admins.js +136 -30
- package/dist/src/commands/admins.js.map +1 -1
- package/dist/src/commands/analytics.d.ts +2 -0
- package/dist/src/commands/analytics.js +713 -55
- package/dist/src/commands/analytics.js.map +1 -1
- package/dist/src/commands/apps.d.ts +2 -0
- package/dist/src/commands/apps.js +65 -100
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/auth-sessions.d.ts +7 -0
- package/dist/src/commands/auth-sessions.js +144 -0
- package/dist/src/commands/auth-sessions.js.map +1 -0
- package/dist/src/commands/auth.d.ts +2 -0
- package/dist/src/commands/auth.js +238 -108
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/blob-buckets.d.ts +2 -0
- package/dist/src/commands/blob-buckets.js +331 -0
- package/dist/src/commands/blob-buckets.js.map +1 -0
- package/dist/src/commands/catalog.d.ts +2 -0
- package/dist/src/commands/catalog.js +63 -48
- package/dist/src/commands/catalog.js.map +1 -1
- package/dist/src/commands/collection-type-configs.d.ts +2 -0
- package/dist/src/commands/collection-type-configs.js +85 -0
- package/dist/src/commands/collection-type-configs.js.map +1 -0
- package/dist/src/commands/collections.d.ts +2 -0
- package/dist/src/commands/collections.js +1282 -0
- package/dist/src/commands/collections.js.map +1 -0
- package/dist/src/commands/comparisons.d.ts +2 -0
- package/dist/src/commands/comparisons.js +6 -6
- package/dist/src/commands/comparisons.js.map +1 -1
- package/dist/src/commands/config.d.ts +46 -0
- package/dist/src/commands/config.js +465 -0
- package/dist/src/commands/config.js.map +1 -0
- package/dist/src/commands/connections.d.ts +2 -0
- package/dist/src/commands/connections.js +99 -0
- package/dist/src/commands/connections.js.map +1 -0
- package/dist/src/commands/cron-triggers.d.ts +2 -0
- package/dist/src/commands/cron-triggers.js +266 -0
- package/dist/src/commands/cron-triggers.js.map +1 -0
- package/dist/src/commands/database-type-configs.d.ts +2 -0
- package/dist/src/commands/database-type-configs.js +164 -0
- package/dist/src/commands/database-type-configs.js.map +1 -0
- package/dist/src/commands/database-types.d.ts +2 -0
- package/dist/src/commands/database-types.js +471 -0
- package/dist/src/commands/database-types.js.map +1 -0
- package/dist/src/commands/databases.d.ts +65 -0
- package/dist/src/commands/databases.js +1887 -243
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.d.ts +60 -0
- package/dist/src/commands/documents.js +2888 -22
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/email-templates.d.ts +2 -0
- package/dist/src/commands/email-templates.js +175 -0
- package/dist/src/commands/email-templates.js.map +1 -0
- package/dist/src/commands/env.d.ts +23 -0
- package/dist/src/commands/env.js +395 -0
- package/dist/src/commands/env.js.map +1 -0
- package/dist/src/commands/feature-flags.d.ts +14 -0
- package/dist/src/commands/feature-flags.js +117 -0
- package/dist/src/commands/feature-flags.js.map +1 -0
- package/dist/src/commands/functions.d.ts +20 -0
- package/dist/src/commands/functions.js +1630 -0
- package/dist/src/commands/functions.js.map +1 -0
- package/dist/src/commands/group-type-configs.d.ts +2 -0
- package/dist/src/commands/group-type-configs.js +87 -0
- package/dist/src/commands/group-type-configs.js.map +1 -0
- package/dist/src/commands/groups.d.ts +2 -0
- package/dist/src/commands/groups.js +65 -113
- package/dist/src/commands/groups.js.map +1 -1
- package/dist/src/commands/guides.d.ts +223 -0
- package/dist/src/commands/guides.js +627 -69
- package/dist/src/commands/guides.js.map +1 -1
- package/dist/src/commands/init.d.ts +37 -0
- package/dist/src/commands/init.js +1693 -208
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.d.ts +2 -0
- package/dist/src/commands/integrations.js +428 -187
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/llm.d.ts +2 -0
- package/dist/src/commands/llm.js +4 -2
- package/dist/src/commands/llm.js.map +1 -1
- package/dist/src/commands/locks.d.ts +8 -0
- package/dist/src/commands/locks.js +175 -0
- package/dist/src/commands/locks.js.map +1 -0
- package/dist/src/commands/metadata-category-configs.d.ts +12 -0
- package/dist/src/commands/metadata-category-configs.js +113 -0
- package/dist/src/commands/metadata-category-configs.js.map +1 -0
- package/dist/src/commands/metadata.d.ts +2 -0
- package/dist/src/commands/metadata.js +288 -0
- package/dist/src/commands/metadata.js.map +1 -0
- package/dist/src/commands/prompts.d.ts +2 -0
- package/dist/src/commands/prompts.js +322 -634
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/rule-sets.d.ts +3 -0
- package/dist/src/commands/rule-sets.js +139 -148
- package/dist/src/commands/rule-sets.js.map +1 -1
- package/dist/src/commands/scripts.d.ts +30 -0
- package/dist/src/commands/scripts.js +688 -0
- package/dist/src/commands/scripts.js.map +1 -0
- package/dist/src/commands/secrets.d.ts +2 -0
- package/dist/src/commands/secrets.js +109 -0
- package/dist/src/commands/secrets.js.map +1 -0
- package/dist/src/commands/sessions.d.ts +2 -0
- package/dist/src/commands/sessions.js +76 -0
- package/dist/src/commands/sessions.js.map +1 -0
- package/dist/src/commands/skill.d.ts +2 -0
- package/dist/src/commands/skill.js +29 -0
- package/dist/src/commands/skill.js.map +1 -0
- package/dist/src/commands/sync-app-settings.d.ts +158 -0
- package/dist/src/commands/sync-app-settings.js +328 -0
- package/dist/src/commands/sync-app-settings.js.map +1 -0
- package/dist/src/commands/sync.d.ts +2670 -0
- package/dist/src/commands/sync.js +17144 -834
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.d.ts +2 -0
- package/dist/src/commands/tokens.js +132 -22
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.d.ts +2 -0
- package/dist/src/commands/users.js +542 -24
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/commands/vars.d.ts +8 -0
- package/dist/src/commands/vars.js +97 -0
- package/dist/src/commands/vars.js.map +1 -0
- package/dist/src/commands/waitlist.d.ts +2 -0
- package/dist/src/commands/waitlist.js +12 -11
- package/dist/src/commands/waitlist.js.map +1 -1
- package/dist/src/commands/webhooks.d.ts +31 -0
- package/dist/src/commands/webhooks.js +633 -0
- package/dist/src/commands/webhooks.js.map +1 -0
- package/dist/src/commands/workflows.d.ts +88 -0
- package/dist/src/commands/workflows.js +1568 -742
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/access-rule-display.d.ts +21 -0
- package/dist/src/lib/access-rule-display.js +34 -0
- package/dist/src/lib/access-rule-display.js.map +1 -0
- package/dist/src/lib/api-client.d.ts +2550 -0
- package/dist/src/lib/api-client.js +2503 -160
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/app-settings-descriptor.d.ts +263 -0
- package/dist/src/lib/app-settings-descriptor.js +583 -0
- package/dist/src/lib/app-settings-descriptor.js.map +1 -0
- package/dist/src/lib/auth-flow.d.ts +8 -0
- package/dist/src/lib/batch.d.ts +26 -0
- package/dist/src/lib/batch.js +32 -0
- package/dist/src/lib/batch.js.map +1 -0
- package/dist/src/lib/block-layout.d.ts +160 -0
- package/dist/src/lib/block-layout.js +451 -0
- package/dist/src/lib/block-layout.js.map +1 -0
- package/dist/src/lib/block-selector.d.ts +58 -0
- package/dist/src/lib/block-selector.js +92 -0
- package/dist/src/lib/block-selector.js.map +1 -0
- package/dist/src/lib/canonical-json.d.ts +12 -0
- package/dist/src/lib/canonical-json.js +35 -0
- package/dist/src/lib/canonical-json.js.map +1 -0
- package/dist/src/lib/channel.d.ts +30 -0
- package/dist/src/lib/channel.js +68 -0
- package/dist/src/lib/channel.js.map +1 -0
- package/dist/src/lib/cli-manifest.d.ts +68 -0
- package/dist/src/lib/cli-manifest.js +71 -0
- package/dist/src/lib/cli-manifest.js.map +1 -0
- package/dist/src/lib/codegen-shared/generatedFiles.d.ts +101 -0
- package/dist/src/lib/codegen-shared/generatedFiles.js +191 -0
- package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -0
- package/dist/src/lib/codegen-shared/prettierStable.d.ts +262 -0
- package/dist/src/lib/codegen-shared/prettierStable.js +610 -0
- package/dist/src/lib/codegen-shared/prettierStable.js.map +1 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +38 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +46 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -0
- package/dist/src/lib/collection-export.d.ts +184 -0
- package/dist/src/lib/collection-export.js +252 -0
- package/dist/src/lib/collection-export.js.map +1 -0
- package/dist/src/lib/config-json-field.d.ts +28 -0
- package/dist/src/lib/config-json-field.js +56 -0
- package/dist/src/lib/config-json-field.js.map +1 -0
- package/dist/src/lib/config-object-descriptor.d.ts +127 -0
- package/dist/src/lib/config-object-descriptor.js +740 -0
- package/dist/src/lib/config-object-descriptor.js.map +1 -0
- package/dist/src/lib/config-payload.d.ts +92 -0
- package/dist/src/lib/config-payload.js +161 -0
- package/dist/src/lib/config-payload.js.map +1 -0
- package/dist/src/lib/config-surface.d.ts +141 -0
- package/dist/src/lib/config-surface.js +368 -0
- package/dist/src/lib/config-surface.js.map +1 -0
- package/dist/src/lib/config-toml.d.ts +10 -0
- package/dist/src/lib/config-toml.js +42 -0
- package/dist/src/lib/config-toml.js.map +1 -0
- package/dist/src/lib/config.d.ts +71 -0
- package/dist/src/lib/config.js +71 -68
- package/dist/src/lib/config.js.map +1 -1
- package/dist/src/lib/confirm-prompt.d.ts +83 -0
- package/dist/src/lib/confirm-prompt.js +110 -0
- package/dist/src/lib/confirm-prompt.js.map +1 -0
- package/dist/src/lib/constants.d.ts +11 -0
- package/dist/src/lib/constants.js +12 -0
- package/dist/src/lib/constants.js.map +1 -0
- package/dist/src/lib/crash-handlers.d.ts +20 -0
- package/dist/src/lib/crash-handlers.js +49 -0
- package/dist/src/lib/crash-handlers.js.map +1 -0
- package/dist/src/lib/credentials-store.d.ts +104 -0
- package/dist/src/lib/credentials-store.js +336 -0
- package/dist/src/lib/credentials-store.js.map +1 -0
- package/dist/src/lib/csv.d.ts +47 -0
- package/dist/src/lib/csv.js +172 -0
- package/dist/src/lib/csv.js.map +1 -0
- package/dist/src/lib/data-input.d.ts +23 -0
- package/dist/src/lib/data-input.js +50 -0
- package/dist/src/lib/data-input.js.map +1 -0
- package/dist/src/lib/db-codegen/dbFingerprint.d.ts +10 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js +17 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js.map +1 -0
- package/dist/src/lib/db-codegen/dbGenerator.d.ts +67 -0
- package/dist/src/lib/db-codegen/dbGenerator.js +170 -0
- package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -0
- package/dist/src/lib/db-codegen/dbNaming.d.ts +87 -0
- package/dist/src/lib/db-codegen/dbNaming.js +180 -0
- package/dist/src/lib/db-codegen/dbNaming.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTemplates.d.ts +272 -0
- package/dist/src/lib/db-codegen/dbTemplates.js +480 -0
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTsTypes.d.ts +73 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js +139 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTypeIR.d.ts +146 -0
- package/dist/src/lib/db-codegen/dbTypeIR.js +525 -0
- package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -0
- package/dist/src/lib/db-codegen/generated-operation-def-descriptor.d.ts +112 -0
- package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js +211 -0
- package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js.map +1 -0
- package/dist/src/lib/deprecation.d.ts +22 -0
- package/dist/src/lib/deprecation.js +43 -0
- package/dist/src/lib/deprecation.js.map +1 -0
- package/dist/src/lib/document-export-permissions.d.ts +30 -0
- package/dist/src/lib/document-export-permissions.js +54 -0
- package/dist/src/lib/document-export-permissions.js.map +1 -0
- package/dist/src/lib/document-ingest-artifact.d.ts +120 -0
- package/dist/src/lib/document-ingest-artifact.js +505 -0
- package/dist/src/lib/document-ingest-artifact.js.map +1 -0
- package/dist/src/lib/document-ingest-input.d.ts +51 -0
- package/dist/src/lib/document-ingest-input.js +132 -0
- package/dist/src/lib/document-ingest-input.js.map +1 -0
- package/dist/src/lib/document-ingest-rows.d.ts +137 -0
- package/dist/src/lib/document-ingest-rows.js +181 -0
- package/dist/src/lib/document-ingest-rows.js.map +1 -0
- package/dist/src/lib/document-ingest.d.ts +101 -0
- package/dist/src/lib/document-ingest.js +384 -0
- package/dist/src/lib/document-ingest.js.map +1 -0
- package/dist/src/lib/env-resolver-core.d.ts +258 -0
- package/dist/src/lib/env-resolver-core.js +447 -0
- package/dist/src/lib/env-resolver-core.js.map +1 -0
- package/dist/src/lib/env-resolver.d.ts +99 -0
- package/dist/src/lib/env-resolver.js +153 -0
- package/dist/src/lib/env-resolver.js.map +1 -0
- package/dist/src/lib/fetch.d.ts +5 -0
- package/dist/src/lib/function-bundle.d.ts +147 -0
- package/dist/src/lib/function-bundle.js +341 -0
- package/dist/src/lib/function-bundle.js.map +1 -0
- package/dist/src/lib/function-collect.d.ts +123 -0
- package/dist/src/lib/function-collect.js +610 -0
- package/dist/src/lib/function-collect.js.map +1 -0
- package/dist/src/lib/function-db-types.d.ts +202 -0
- package/dist/src/lib/function-db-types.js +870 -0
- package/dist/src/lib/function-db-types.js.map +1 -0
- package/dist/src/lib/function-document-types.d.ts +144 -0
- package/dist/src/lib/function-document-types.js +370 -0
- package/dist/src/lib/function-document-types.js.map +1 -0
- package/dist/src/lib/function-grants-preflight.d.ts +64 -0
- package/dist/src/lib/function-grants-preflight.js +105 -0
- package/dist/src/lib/function-grants-preflight.js.map +1 -0
- package/dist/src/lib/function-log-lines.d.ts +76 -0
- package/dist/src/lib/function-log-lines.js +160 -0
- package/dist/src/lib/function-log-lines.js.map +1 -0
- package/dist/src/lib/function-log-row.d.ts +29 -0
- package/dist/src/lib/function-log-row.js +73 -0
- package/dist/src/lib/function-log-row.js.map +1 -0
- package/dist/src/lib/function-log-tail.d.ts +132 -0
- package/dist/src/lib/function-log-tail.js +262 -0
- package/dist/src/lib/function-log-tail.js.map +1 -0
- package/dist/src/lib/function-run.d.ts +289 -0
- package/dist/src/lib/function-run.js +389 -0
- package/dist/src/lib/function-run.js.map +1 -0
- package/dist/src/lib/function-schema-codegen.d.ts +143 -0
- package/dist/src/lib/function-schema-codegen.js +420 -0
- package/dist/src/lib/function-schema-codegen.js.map +1 -0
- package/dist/src/lib/function-sync.d.ts +459 -0
- package/dist/src/lib/function-sync.js +1258 -0
- package/dist/src/lib/function-sync.js.map +1 -0
- package/dist/src/lib/function-trigger-listing.d.ts +27 -0
- package/dist/src/lib/function-trigger-listing.js +70 -0
- package/dist/src/lib/function-trigger-listing.js.map +1 -0
- package/dist/src/lib/function-typecheck.d.ts +86 -0
- package/dist/src/lib/function-typecheck.js +370 -0
- package/dist/src/lib/function-typecheck.js.map +1 -0
- package/dist/src/lib/function-versions.d.ts +122 -0
- package/dist/src/lib/function-versions.js +182 -0
- package/dist/src/lib/function-versions.js.map +1 -0
- package/dist/src/lib/generated-allowlist.d.ts +28 -0
- package/dist/src/lib/generated-allowlist.js +281 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -0
- package/dist/src/lib/generated-config-surfaces.d.ts +2936 -0
- package/dist/src/lib/generated-config-surfaces.js +10569 -0
- package/dist/src/lib/generated-config-surfaces.js.map +1 -0
- package/dist/src/lib/generated-sdk-types.d.ts +12 -0
- package/dist/src/lib/generated-sdk-types.js +13 -0
- package/dist/src/lib/generated-sdk-types.js.map +1 -0
- package/dist/src/lib/generated-template-lint.d.ts +212 -0
- package/dist/src/lib/generated-template-lint.js +624 -0
- package/dist/src/lib/generated-template-lint.js.map +1 -0
- package/dist/src/lib/init-adopt.d.ts +16 -0
- package/dist/src/lib/init-adopt.js +34 -0
- package/dist/src/lib/init-adopt.js.map +1 -0
- package/dist/src/lib/init-assets.d.ts +39 -0
- package/dist/src/lib/init-assets.js +97 -0
- package/dist/src/lib/init-assets.js.map +1 -0
- package/dist/src/lib/init-client-platforms.d.ts +14 -0
- package/dist/src/lib/init-client-platforms.js +71 -0
- package/dist/src/lib/init-client-platforms.js.map +1 -0
- package/dist/src/lib/init-config.d.ts +98 -0
- package/dist/src/lib/init-config.js +186 -0
- package/dist/src/lib/init-config.js.map +1 -0
- package/dist/src/lib/init-email-redirect-uris.d.ts +37 -0
- package/dist/src/lib/init-email-redirect-uris.js +46 -0
- package/dist/src/lib/init-email-redirect-uris.js.map +1 -0
- package/dist/src/lib/init-ios-links.d.ts +91 -0
- package/dist/src/lib/init-ios-links.js +219 -0
- package/dist/src/lib/init-ios-links.js.map +1 -0
- package/dist/src/lib/init-plan.d.ts +80 -0
- package/dist/src/lib/init-plan.js +95 -0
- package/dist/src/lib/init-plan.js.map +1 -0
- package/dist/src/lib/init-production-env.d.ts +48 -0
- package/dist/src/lib/init-production-env.js +59 -0
- package/dist/src/lib/init-production-env.js.map +1 -0
- package/dist/src/lib/init-schema.d.ts +74 -0
- package/dist/src/lib/init-schema.js +358 -0
- package/dist/src/lib/init-schema.js.map +1 -0
- package/dist/src/lib/init-xcode.d.ts +34 -0
- package/dist/src/lib/init-xcode.js +138 -0
- package/dist/src/lib/init-xcode.js.map +1 -0
- package/dist/src/lib/integration-request-config.d.ts +30 -0
- package/dist/src/lib/integration-request-config.js +145 -0
- package/dist/src/lib/integration-request-config.js.map +1 -0
- package/dist/src/lib/integration-selector.d.ts +42 -0
- package/dist/src/lib/integration-selector.js +46 -0
- package/dist/src/lib/integration-selector.js.map +1 -0
- package/dist/src/lib/ios-app-id.d.ts +34 -0
- package/dist/src/lib/ios-app-id.js +69 -0
- package/dist/src/lib/ios-app-id.js.map +1 -0
- package/dist/src/lib/list-options.d.ts +68 -0
- package/dist/src/lib/list-options.js +89 -0
- package/dist/src/lib/list-options.js.map +1 -0
- package/dist/src/lib/local-state.d.ts +55 -0
- package/dist/src/lib/local-state.js +167 -0
- package/dist/src/lib/local-state.js.map +1 -0
- package/dist/src/lib/local-test-cases.d.ts +63 -0
- package/dist/src/lib/local-test-cases.js +136 -0
- package/dist/src/lib/local-test-cases.js.map +1 -0
- package/dist/src/lib/log-inspection.d.ts +715 -0
- package/dist/src/lib/log-inspection.js +816 -0
- package/dist/src/lib/log-inspection.js.map +1 -0
- package/dist/src/lib/logout-admin-session.d.ts +33 -0
- package/dist/src/lib/logout-admin-session.js +70 -0
- package/dist/src/lib/logout-admin-session.js.map +1 -0
- package/dist/src/lib/migration-nag.d.ts +49 -0
- package/dist/src/lib/migration-nag.js +163 -0
- package/dist/src/lib/migration-nag.js.map +1 -0
- package/dist/src/lib/object-status-filter.d.ts +22 -0
- package/dist/src/lib/object-status-filter.js +45 -0
- package/dist/src/lib/object-status-filter.js.map +1 -0
- package/dist/src/lib/output.d.ts +124 -0
- package/dist/src/lib/output.js +219 -8
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/package-manager.d.ts +140 -0
- package/dist/src/lib/package-manager.js +305 -0
- package/dist/src/lib/package-manager.js.map +1 -0
- package/dist/src/lib/paginate.d.ts +98 -0
- package/dist/src/lib/paginate.js +112 -0
- package/dist/src/lib/paginate.js.map +1 -0
- package/dist/src/lib/platform-owned.d.ts +63 -0
- package/dist/src/lib/platform-owned.js +85 -0
- package/dist/src/lib/platform-owned.js.map +1 -0
- package/dist/src/lib/project-config.d.ts +122 -0
- package/dist/src/lib/project-config.js +244 -0
- package/dist/src/lib/project-config.js.map +1 -0
- package/dist/src/lib/prompt-cost-format.d.ts +11 -0
- package/dist/src/lib/prompt-cost-format.js +41 -0
- package/dist/src/lib/prompt-cost-format.js.map +1 -0
- package/dist/src/lib/prompt-schema-codegen.d.ts +147 -0
- package/dist/src/lib/prompt-schema-codegen.js +462 -0
- package/dist/src/lib/prompt-schema-codegen.js.map +1 -0
- package/dist/src/lib/query-operators.d.ts +43 -0
- package/dist/src/lib/query-operators.js +80 -0
- package/dist/src/lib/query-operators.js.map +1 -0
- package/dist/src/lib/record-filter.d.ts +18 -0
- package/dist/src/lib/record-filter.js +55 -0
- package/dist/src/lib/record-filter.js.map +1 -0
- package/dist/src/lib/refresh-admin-credentials.d.ts +73 -0
- package/dist/src/lib/refresh-admin-credentials.js +123 -0
- package/dist/src/lib/refresh-admin-credentials.js.map +1 -0
- package/dist/src/lib/resolve-init-dev-port.d.ts +56 -0
- package/dist/src/lib/resolve-init-dev-port.js +55 -0
- package/dist/src/lib/resolve-init-dev-port.js.map +1 -0
- package/dist/src/lib/resolve-init-server.d.ts +64 -0
- package/dist/src/lib/resolve-init-server.js +77 -0
- package/dist/src/lib/resolve-init-server.js.map +1 -0
- package/dist/src/lib/resolve-owner.d.ts +19 -0
- package/dist/src/lib/resolve-owner.js +20 -0
- package/dist/src/lib/resolve-owner.js.map +1 -0
- package/dist/src/lib/resolve-platform.d.ts +74 -0
- package/dist/src/lib/resolve-platform.js +105 -0
- package/dist/src/lib/resolve-platform.js.map +1 -0
- package/dist/src/lib/run-status.d.ts +19 -0
- package/dist/src/lib/run-status.generated.d.ts +39 -0
- package/dist/src/lib/run-status.generated.js +66 -0
- package/dist/src/lib/run-status.generated.js.map +1 -0
- package/dist/src/lib/run-status.js +19 -0
- package/dist/src/lib/run-status.js.map +1 -0
- package/dist/src/lib/server-text-normalization.d.ts +51 -0
- package/dist/src/lib/server-text-normalization.js +90 -0
- package/dist/src/lib/server-text-normalization.js.map +1 -0
- package/dist/src/lib/server-url.d.ts +22 -0
- package/dist/src/lib/server-url.js +33 -0
- package/dist/src/lib/server-url.js.map +1 -0
- package/dist/src/lib/signing-secret-status.d.ts +81 -0
- package/dist/src/lib/signing-secret-status.js +116 -0
- package/dist/src/lib/signing-secret-status.js.map +1 -0
- package/dist/src/lib/skill-installer.d.ts +71 -0
- package/dist/src/lib/skill-installer.js +441 -0
- package/dist/src/lib/skill-installer.js.map +1 -0
- package/dist/src/lib/snapshot-audit-source.d.ts +45 -0
- package/dist/src/lib/snapshot-audit-source.js +58 -0
- package/dist/src/lib/snapshot-audit-source.js.map +1 -0
- package/dist/src/lib/snapshot-audit-store.d.ts +52 -0
- package/dist/src/lib/snapshot-audit-store.js +196 -0
- package/dist/src/lib/snapshot-audit-store.js.map +1 -0
- package/dist/src/lib/snapshot-audit.d.ts +207 -0
- package/dist/src/lib/snapshot-audit.js +431 -0
- package/dist/src/lib/snapshot-audit.js.map +1 -0
- package/dist/src/lib/snapshot-build-rows.d.ts +60 -0
- package/dist/src/lib/snapshot-build-rows.js +87 -0
- package/dist/src/lib/snapshot-build-rows.js.map +1 -0
- package/dist/src/lib/snapshot-build.d.ts +50 -0
- package/dist/src/lib/snapshot-build.js +111 -0
- package/dist/src/lib/snapshot-build.js.map +1 -0
- package/dist/src/lib/snapshot-manifest-layout.d.ts +61 -0
- package/dist/src/lib/snapshot-manifest-layout.js +70 -0
- package/dist/src/lib/snapshot-manifest-layout.js.map +1 -0
- package/dist/src/lib/snapshots.d.ts +98 -0
- package/dist/src/lib/snapshots.js +294 -0
- package/dist/src/lib/snapshots.js.map +1 -0
- package/dist/src/lib/step-run-table.d.ts +43 -0
- package/dist/src/lib/step-run-table.js +129 -0
- package/dist/src/lib/step-run-table.js.map +1 -0
- package/dist/src/lib/storage-pending-retry.d.ts +26 -0
- package/dist/src/lib/storage-pending-retry.js +42 -0
- package/dist/src/lib/storage-pending-retry.js.map +1 -0
- package/dist/src/lib/swift-codegen/agentGenerator.d.ts +42 -0
- package/dist/src/lib/swift-codegen/agentGenerator.js +118 -0
- package/dist/src/lib/swift-codegen/agentGenerator.js.map +1 -0
- package/dist/src/lib/swift-codegen/banners.d.ts +24 -0
- package/dist/src/lib/swift-codegen/banners.js +25 -0
- package/dist/src/lib/swift-codegen/banners.js.map +1 -0
- package/dist/src/lib/swift-codegen/dbGenerator.d.ts +113 -0
- package/dist/src/lib/swift-codegen/dbGenerator.js +926 -0
- package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -0
- package/dist/src/lib/swift-codegen/dbSwiftTypes.d.ts +42 -0
- package/dist/src/lib/swift-codegen/dbSwiftTypes.js +100 -0
- package/dist/src/lib/swift-codegen/dbSwiftTypes.js.map +1 -0
- package/dist/src/lib/swift-codegen/functionGenerator.d.ts +139 -0
- package/dist/src/lib/swift-codegen/functionGenerator.js +462 -0
- package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -0
- package/dist/src/lib/swift-codegen/generator.d.ts +100 -0
- package/dist/src/lib/swift-codegen/generator.js +457 -0
- package/dist/src/lib/swift-codegen/generator.js.map +1 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +87 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.js +661 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.d.ts +94 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.js +155 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.js.map +1 -0
- package/dist/src/lib/swift-codegen/swiftNaming.d.ts +85 -0
- package/dist/src/lib/swift-codegen/swiftNaming.js +198 -0
- package/dist/src/lib/swift-codegen/swiftNaming.js.map +1 -0
- package/dist/src/lib/sync-dir-selector.d.ts +21 -0
- package/dist/src/lib/sync-dir-selector.js +30 -0
- package/dist/src/lib/sync-dir-selector.js.map +1 -0
- package/dist/src/lib/sync-paths.d.ts +128 -0
- package/dist/src/lib/sync-paths.js +195 -0
- package/dist/src/lib/sync-paths.js.map +1 -0
- package/dist/src/lib/sync-resource-types.d.ts +563 -0
- package/dist/src/lib/sync-resource-types.js +1073 -0
- package/dist/src/lib/sync-resource-types.js.map +1 -0
- package/dist/src/lib/sync-selectors.d.ts +138 -0
- package/dist/src/lib/sync-selectors.js +289 -0
- package/dist/src/lib/sync-selectors.js.map +1 -0
- package/dist/src/lib/template.d.ts +170 -0
- package/dist/src/lib/template.js +484 -68
- package/dist/src/lib/template.js.map +1 -1
- package/dist/src/lib/test-case-file-names.d.ts +40 -0
- package/dist/src/lib/test-case-file-names.js +91 -0
- package/dist/src/lib/test-case-file-names.js.map +1 -0
- package/dist/src/lib/test-case-keys.d.ts +29 -0
- package/dist/src/lib/test-case-keys.js +55 -0
- package/dist/src/lib/test-case-keys.js.map +1 -0
- package/dist/src/lib/test-case-variables.d.ts +29 -0
- package/dist/src/lib/test-case-variables.js +71 -0
- package/dist/src/lib/test-case-variables.js.map +1 -0
- package/dist/src/lib/token-inject.d.ts +56 -0
- package/dist/src/lib/token-inject.js +204 -0
- package/dist/src/lib/token-inject.js.map +1 -0
- package/dist/src/lib/toml-database-config.d.ts +123 -0
- package/dist/src/lib/toml-database-config.js +544 -0
- package/dist/src/lib/toml-database-config.js.map +1 -0
- package/dist/src/lib/toml-metadata-config.d.ts +151 -0
- package/dist/src/lib/toml-metadata-config.js +476 -0
- package/dist/src/lib/toml-metadata-config.js.map +1 -0
- package/dist/src/lib/toml-native-form.d.ts +46 -0
- package/dist/src/lib/toml-native-form.js +78 -0
- package/dist/src/lib/toml-native-form.js.map +1 -0
- package/dist/src/lib/toml-params-validator.d.ts +129 -0
- package/dist/src/lib/toml-params-validator.js +298 -0
- package/dist/src/lib/toml-params-validator.js.map +1 -0
- package/dist/src/lib/toml-scalar-edit.d.ts +43 -0
- package/dist/src/lib/toml-scalar-edit.js +283 -0
- package/dist/src/lib/toml-scalar-edit.js.map +1 -0
- package/dist/src/lib/user-selector.d.ts +24 -0
- package/dist/src/lib/user-selector.js +33 -0
- package/dist/src/lib/user-selector.js.map +1 -0
- package/dist/src/lib/version-check.d.ts +35 -0
- package/dist/src/lib/version-check.js +241 -0
- package/dist/src/lib/version-check.js.map +1 -0
- package/dist/src/lib/watch.d.ts +121 -0
- package/dist/src/lib/watch.js +169 -0
- package/dist/src/lib/watch.js.map +1 -0
- package/dist/src/lib/web-url.d.ts +40 -0
- package/dist/src/lib/web-url.js +76 -0
- package/dist/src/lib/web-url.js.map +1 -0
- package/dist/src/lib/webhook-deliver.d.ts +209 -0
- package/dist/src/lib/webhook-deliver.js +519 -0
- package/dist/src/lib/webhook-deliver.js.map +1 -0
- package/dist/src/lib/workflow-apply.d.ts +110 -0
- package/dist/src/lib/workflow-apply.js +164 -0
- package/dist/src/lib/workflow-apply.js.map +1 -0
- package/dist/src/lib/workflow-codegen/generated-schema-descriptor.d.ts +129 -0
- package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js +269 -0
- package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js.map +1 -0
- package/dist/src/lib/workflow-codegen/generator.d.ts +96 -0
- package/dist/src/lib/workflow-codegen/generator.js +361 -0
- package/dist/src/lib/workflow-codegen/generator.js.map +1 -0
- package/dist/src/lib/workflow-codegen/invokerIR.d.ts +94 -0
- package/dist/src/lib/workflow-codegen/invokerIR.js +76 -0
- package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -0
- package/dist/src/lib/workflow-codegen/naming.d.ts +33 -0
- package/dist/src/lib/workflow-codegen/naming.js +81 -0
- package/dist/src/lib/workflow-codegen/naming.js.map +1 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.d.ts +80 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.js +303 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.js.map +1 -0
- package/dist/src/lib/workflow-config-apply.d.ts +70 -0
- package/dist/src/lib/workflow-config-apply.js +137 -0
- package/dist/src/lib/workflow-config-apply.js.map +1 -0
- package/dist/src/lib/workflow-config-sidecar.d.ts +63 -0
- package/dist/src/lib/workflow-config-sidecar.js +96 -0
- package/dist/src/lib/workflow-config-sidecar.js.map +1 -0
- package/dist/src/lib/workflow-defaults.d.ts +29 -0
- package/dist/src/lib/workflow-defaults.js +41 -0
- package/dist/src/lib/workflow-defaults.js.map +1 -0
- package/dist/src/lib/workflow-fragments.d.ts +64 -0
- package/dist/src/lib/workflow-fragments.js +342 -0
- package/dist/src/lib/workflow-fragments.js.map +1 -0
- package/dist/src/lib/workflow-include-preserve.d.ts +76 -0
- package/dist/src/lib/workflow-include-preserve.js +286 -0
- package/dist/src/lib/workflow-include-preserve.js.map +1 -0
- package/dist/src/lib/workflow-payload.d.ts +98 -0
- package/dist/src/lib/workflow-payload.js +178 -0
- package/dist/src/lib/workflow-payload.js.map +1 -0
- package/dist/src/lib/workflow-toml-validator.d.ts +211 -0
- package/dist/src/lib/workflow-toml-validator.js +770 -0
- package/dist/src/lib/workflow-toml-validator.js.map +1 -0
- package/dist/src/lib/workflow-usage.d.ts +196 -0
- package/dist/src/lib/workflow-usage.js +310 -0
- package/dist/src/lib/workflow-usage.js.map +1 -0
- package/dist/src/types/index.d.ts +591 -0
- package/dist/src/validators.d.ts +65 -0
- package/dist/src/validators.js +64 -0
- package/dist/src/validators.js.map +1 -0
- package/package.json +34 -9
|
@@ -1,57 +1,223 @@
|
|
|
1
1
|
import { ApiClient } from "../lib/api-client.js";
|
|
2
2
|
import { resolveAppId } from "../lib/config.js";
|
|
3
|
-
import { error, info,
|
|
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
|
+
// #3787 — per-prompt cost cells, with the cost-unknown and partial-window rules.
|
|
6
|
+
import { formatAvgCostCell, formatCostCell, } from "../lib/prompt-cost-format.js";
|
|
7
|
+
import { ALL_APPS_CONFLICT_ERROR, ALL_APPS_SUPER_ADMIN_ERROR, isAbortStatus, isSuperAdminRole, mergeUsageReports, parseWindowDaysFlag, renderMergedUsageReport, renderUsageReport, usageExitCode, USAGE_CLI_DEFAULT_WINDOW_DAYS, USAGE_CLI_MAX_WINDOW_DAYS, USAGE_CLI_MIN_WINDOW_DAYS, } from "../lib/workflow-usage.js";
|
|
8
|
+
/** Format a value that is already a percentage (e.g. 33.3 → "33.3%") */
|
|
9
|
+
function formatPctRaw(value) {
|
|
10
|
+
if (value === undefined || value === null)
|
|
11
|
+
return "-";
|
|
12
|
+
return `${value.toFixed(1)}%`;
|
|
13
|
+
}
|
|
4
14
|
export function registerAnalyticsCommands(program) {
|
|
5
15
|
const analytics = program
|
|
6
16
|
.command("analytics")
|
|
7
17
|
.description("View usage analytics, user activity, and integration metrics")
|
|
18
|
+
// Subcommands are listed once, by commander, from what is registered
|
|
19
|
+
// below — a second hand-written list drifts (#2860: `errors-groups`
|
|
20
|
+
// shipped and never reached the copy). Examples illustrate; they do not
|
|
21
|
+
// re-list the group.
|
|
8
22
|
.addHelpText("after", `
|
|
9
23
|
Examples:
|
|
10
24
|
$ primitive analytics overview
|
|
11
|
-
$ primitive analytics
|
|
12
|
-
$ primitive analytics
|
|
25
|
+
$ primitive analytics daily-active --window-days 14
|
|
26
|
+
$ primitive analytics top-users --limit 20
|
|
27
|
+
$ primitive analytics user-search --query user@example.com
|
|
28
|
+
$ primitive analytics user-detail <user-ulid>
|
|
29
|
+
$ primitive analytics events --window-days 7 --page 0
|
|
30
|
+
$ primitive analytics events-grouped --group-by feature
|
|
31
|
+
$ primitive analytics errors-groups --window-days 14 --limit 100
|
|
32
|
+
$ primitive analytics cohort-retention
|
|
33
|
+
$ primitive analytics workflows --limit 5
|
|
34
|
+
$ primitive analytics prompts --window-days 14
|
|
35
|
+
$ primitive analytics workflow-usage --window-days 30 --all-apps --json
|
|
13
36
|
`);
|
|
14
|
-
// Overview
|
|
37
|
+
// ── Overview (DAU / WAU / MAU / Growth) ──────────────────────────
|
|
15
38
|
analytics
|
|
16
39
|
.command("overview")
|
|
17
|
-
.description("
|
|
40
|
+
.description("Show DAU, WAU, MAU, and growth accounting")
|
|
18
41
|
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
19
42
|
.option("--app <app-id>", "App ID")
|
|
20
|
-
.option("--window-days <n>", "
|
|
43
|
+
.option("--window-days <n>", "Growth window in days", "28")
|
|
44
|
+
.option("--json", "Output as JSON")
|
|
45
|
+
.action(async (appId, options) => {
|
|
46
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
47
|
+
const client = new ApiClient();
|
|
48
|
+
try {
|
|
49
|
+
const [dau, wau, mau, growth] = await Promise.all([
|
|
50
|
+
client.getAnalyticsOverviewDau(resolvedAppId),
|
|
51
|
+
client.getAnalyticsOverviewWau(resolvedAppId),
|
|
52
|
+
client.getAnalyticsOverviewMau(resolvedAppId),
|
|
53
|
+
client.getAnalyticsOverviewGrowth(resolvedAppId, {
|
|
54
|
+
windowDays: parseInt(options.windowDays),
|
|
55
|
+
}),
|
|
56
|
+
]);
|
|
57
|
+
if (options.json) {
|
|
58
|
+
json({ dau, wau, mau, growth });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
heading("Active Users");
|
|
62
|
+
console.log();
|
|
63
|
+
const formatDelta = (d) => d > 0 ? `+${(d * 100).toFixed(1)}%` : d === 0 ? "0%" : `${(d * 100).toFixed(1)}%`;
|
|
64
|
+
console.log(formatTable([
|
|
65
|
+
{ metric: "DAU", value: dau.value, previous: dau.previous, delta: formatDelta(dau.deltaPct) },
|
|
66
|
+
{ metric: "WAU", value: wau.value, previous: wau.previous, delta: formatDelta(wau.deltaPct) },
|
|
67
|
+
{ metric: "MAU", value: mau.value, previous: mau.previous, delta: formatDelta(mau.deltaPct) },
|
|
68
|
+
], [
|
|
69
|
+
{ header: "METRIC", key: "metric" },
|
|
70
|
+
{ header: "CURRENT", key: "value", align: "right", format: formatNumber },
|
|
71
|
+
{ header: "PREVIOUS", key: "previous", align: "right", format: formatNumber },
|
|
72
|
+
{ header: "CHANGE", key: "delta", align: "right" },
|
|
73
|
+
]));
|
|
74
|
+
console.log();
|
|
75
|
+
heading(`Growth Accounting (${growth.window_days} days)`);
|
|
76
|
+
console.log();
|
|
77
|
+
printResult("Current active", String(growth.current_active));
|
|
78
|
+
printResult("Previous active", String(growth.previous_active));
|
|
79
|
+
printResult("New users", String(growth.new_users));
|
|
80
|
+
printResult("Retained", String(growth.retained_users));
|
|
81
|
+
printResult("Reactivated", String(growth.reactivated_users));
|
|
82
|
+
printResult("Churned", String(growth.churned_users));
|
|
83
|
+
printResult("Delta", formatDelta(growth.deltaPct));
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
error(err.message);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
// ── Daily Active ─────────────────────────────────────────────────
|
|
91
|
+
analytics
|
|
92
|
+
.command("daily-active")
|
|
93
|
+
.description("Daily active users time series")
|
|
94
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
95
|
+
.option("--app <app-id>", "App ID")
|
|
96
|
+
.option("--window-days <n>", "Time window in days (7-90)", "28")
|
|
21
97
|
.option("--json", "Output as JSON")
|
|
22
98
|
.action(async (appId, options) => {
|
|
23
99
|
const resolvedAppId = resolveAppId(appId, options);
|
|
24
100
|
const client = new ApiClient();
|
|
25
101
|
try {
|
|
26
|
-
const result = await client.
|
|
102
|
+
const result = await client.getAnalyticsDailyActive(resolvedAppId, {
|
|
27
103
|
windowDays: parseInt(options.windowDays),
|
|
28
104
|
});
|
|
29
105
|
if (options.json) {
|
|
30
106
|
json(result);
|
|
31
107
|
return;
|
|
32
108
|
}
|
|
33
|
-
heading(`
|
|
109
|
+
heading(`Daily Active Users (${result.window_days} days)`);
|
|
34
110
|
console.log();
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
111
|
+
if (!result.rows || result.rows.length === 0) {
|
|
112
|
+
info("No data found.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
console.log(formatTable(result.rows, [
|
|
116
|
+
{ header: "DATE", key: "day_label" },
|
|
117
|
+
{ header: "ACTIVE USERS", key: "active_users", align: "right", format: formatNumber },
|
|
118
|
+
]));
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
error(err.message);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
// ── Rolling Active ───────────────────────────────────────────────
|
|
126
|
+
analytics
|
|
127
|
+
.command("rolling-active")
|
|
128
|
+
.description("Rolling active users (28 data points)")
|
|
129
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
130
|
+
.option("--app <app-id>", "App ID")
|
|
131
|
+
.option("--window-days <n>", "Rolling window size in days (1-28)", "7")
|
|
132
|
+
.option("--json", "Output as JSON")
|
|
133
|
+
.action(async (appId, options) => {
|
|
134
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
135
|
+
const client = new ApiClient();
|
|
136
|
+
try {
|
|
137
|
+
const result = await client.getAnalyticsRollingActive(resolvedAppId, {
|
|
138
|
+
windowDays: parseInt(options.windowDays),
|
|
139
|
+
});
|
|
140
|
+
if (options.json) {
|
|
141
|
+
json(result);
|
|
142
|
+
return;
|
|
47
143
|
}
|
|
144
|
+
heading(`Rolling Active Users (${result.window_days}-day window)`);
|
|
145
|
+
console.log();
|
|
146
|
+
if (!result.rows || result.rows.length === 0) {
|
|
147
|
+
info("No data found.");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
console.log(formatTable(result.rows, [
|
|
151
|
+
{ header: "DATE", key: "day_label" },
|
|
152
|
+
{ header: "ACTIVE USERS", key: "active_users", align: "right", format: formatNumber },
|
|
153
|
+
]));
|
|
48
154
|
}
|
|
49
155
|
catch (err) {
|
|
50
156
|
error(err.message);
|
|
51
157
|
process.exit(1);
|
|
52
158
|
}
|
|
53
159
|
});
|
|
54
|
-
//
|
|
160
|
+
// ── Cohort Retention ─────────────────────────────────────────────
|
|
161
|
+
analytics
|
|
162
|
+
.command("cohort-retention")
|
|
163
|
+
.description("Weekly cohort retention matrix")
|
|
164
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
165
|
+
.option("--app <app-id>", "App ID")
|
|
166
|
+
.option("--json", "Output as JSON")
|
|
167
|
+
.action(async (appId, options) => {
|
|
168
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
169
|
+
const client = new ApiClient();
|
|
170
|
+
try {
|
|
171
|
+
const result = await client.getAnalyticsCohortRetention(resolvedAppId);
|
|
172
|
+
if (options.json) {
|
|
173
|
+
json(result);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
heading("Cohort Retention");
|
|
177
|
+
console.log();
|
|
178
|
+
if (!result.rows || result.rows.length === 0) {
|
|
179
|
+
info("No cohort data found.");
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
// Build week headers
|
|
183
|
+
const weekHeaders = result.weeks.map((w) => `W${w}`);
|
|
184
|
+
// Build table rows with retention percentages
|
|
185
|
+
const tableRows = result.rows.map((row) => {
|
|
186
|
+
const entry = {
|
|
187
|
+
cohort: row.signup_week_label,
|
|
188
|
+
size: row.cohort_size,
|
|
189
|
+
};
|
|
190
|
+
row.retention.forEach((r, i) => {
|
|
191
|
+
entry[`w${result.weeks[i]}`] =
|
|
192
|
+
r !== null ? `${r.toFixed(0)}%` : "-";
|
|
193
|
+
});
|
|
194
|
+
return entry;
|
|
195
|
+
});
|
|
196
|
+
const columns = [
|
|
197
|
+
{ header: "COHORT", key: "cohort" },
|
|
198
|
+
{ header: "SIZE", key: "size", align: "right", format: formatNumber },
|
|
199
|
+
...weekHeaders.map((h, i) => ({
|
|
200
|
+
header: h,
|
|
201
|
+
key: `w${result.weeks[i]}`,
|
|
202
|
+
align: "right",
|
|
203
|
+
})),
|
|
204
|
+
];
|
|
205
|
+
console.log(formatTable(tableRows, columns));
|
|
206
|
+
// Print averages row
|
|
207
|
+
if (result.averages) {
|
|
208
|
+
const avgStr = result.averages
|
|
209
|
+
.map((a) => a !== null ? `${a.toFixed(0)}%` : "-")
|
|
210
|
+
.join(" ");
|
|
211
|
+
console.log();
|
|
212
|
+
dim(`Averages: ${avgStr}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
error(err.message);
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
// ── Top Users ────────────────────────────────────────────────────
|
|
55
221
|
analytics
|
|
56
222
|
.command("top-users")
|
|
57
223
|
.description("Get top users by activity")
|
|
@@ -80,6 +246,7 @@ Examples:
|
|
|
80
246
|
}
|
|
81
247
|
console.log(formatTable(result.results, [
|
|
82
248
|
{ header: "USER", key: "userUlid", format: formatId },
|
|
249
|
+
{ header: "EMAIL", key: "email" },
|
|
83
250
|
{ header: "EVENTS", key: "eventCount", align: "right" },
|
|
84
251
|
{ header: "FIRST SEEN", key: "firstSeen", format: formatDate },
|
|
85
252
|
{ header: "LAST SEEN", key: "lastSeen", format: formatDate },
|
|
@@ -90,53 +257,134 @@ Examples:
|
|
|
90
257
|
process.exit(1);
|
|
91
258
|
}
|
|
92
259
|
});
|
|
93
|
-
// User
|
|
260
|
+
// ── User Search ──────────────────────────────────────────────────
|
|
94
261
|
analytics
|
|
95
|
-
.command("user")
|
|
96
|
-
.description("
|
|
262
|
+
.command("user-search")
|
|
263
|
+
.description("Search users by email or ULID, or list who signed up on a given day")
|
|
97
264
|
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
98
|
-
.argument("<user-ulid>", "User ULID")
|
|
99
265
|
.option("--app <app-id>", "App ID")
|
|
100
|
-
|
|
266
|
+
// #3127 — no longer required: "who signed up on day D" names no user, so a
|
|
267
|
+
// signup filter is the second way to say what is being asked for.
|
|
268
|
+
.option("--query <q>", "Email or ULID to search for")
|
|
269
|
+
.option("--signup-day <day>", "Users who joined on this UTC day (YYYY-MM-DD)")
|
|
270
|
+
.option("--signup-start-day <day>", "Start of an inclusive signup range (YYYY-MM-DD, at most 90 days)")
|
|
271
|
+
.option("--signup-end-day <day>", "End of an inclusive signup range (YYYY-MM-DD)")
|
|
272
|
+
.option("--offset <n>", "Row offset; page a busy day until the result is not truncated")
|
|
273
|
+
.option("--limit <n>", "Max results", "25")
|
|
101
274
|
.option("--json", "Output as JSON")
|
|
102
|
-
.action(async (
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
275
|
+
.action(async (appId, options) => {
|
|
276
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
277
|
+
const client = new ApiClient();
|
|
278
|
+
const hasSignupFilter = Boolean(options.signupDay || options.signupStartDay || options.signupEndDay);
|
|
279
|
+
if (!options.query && !hasSignupFilter) {
|
|
280
|
+
error("Give --query, or a signup filter (--signup-day, or " +
|
|
281
|
+
"--signup-start-day with --signup-end-day).");
|
|
282
|
+
process.exit(1);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
try {
|
|
286
|
+
const limit = parseInt(options.limit);
|
|
287
|
+
const result = await client.getAnalyticsUserSearch(resolvedAppId, {
|
|
288
|
+
...(options.query ? { q: options.query } : {}),
|
|
289
|
+
limit,
|
|
290
|
+
...(options.signupDay ? { signupDay: options.signupDay } : {}),
|
|
291
|
+
...(options.signupStartDay
|
|
292
|
+
? { signupStartDay: options.signupStartDay }
|
|
293
|
+
: {}),
|
|
294
|
+
...(options.signupEndDay ? { signupEndDay: options.signupEndDay } : {}),
|
|
295
|
+
...(options.offset !== undefined
|
|
296
|
+
? { offset: parseInt(options.offset) }
|
|
297
|
+
: {}),
|
|
298
|
+
});
|
|
299
|
+
if (options.json) {
|
|
300
|
+
json(result);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
heading(hasSignupFilter
|
|
304
|
+
? `Signups: ${result.signupStartDay ?? ""} to ${result.signupEndDay ?? ""}`
|
|
305
|
+
: `User Search: "${result.query}"`);
|
|
306
|
+
console.log();
|
|
307
|
+
if (!result.results || result.results.length === 0) {
|
|
308
|
+
info("No users found.");
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
console.log(formatTable(result.results, [
|
|
312
|
+
{ header: "USER", key: "userUlid", format: formatId },
|
|
313
|
+
{ header: "EMAIL", key: "email" },
|
|
314
|
+
{ header: "NAME", key: "name" },
|
|
315
|
+
{ header: "SIGNED UP", key: "signedUpAt", format: formatDate },
|
|
316
|
+
{ header: "EVENTS", key: "eventCount", align: "right" },
|
|
317
|
+
{ header: "LAST SEEN", key: "lastSeen", format: formatDate },
|
|
318
|
+
]));
|
|
319
|
+
// #3127 — a busy day has more matches than one page. Say so, and say
|
|
320
|
+
// exactly what to run next: silence here is how a digest undercounts.
|
|
321
|
+
//
|
|
322
|
+
// The step is the limit the SERVER used, not the one asked for: it
|
|
323
|
+
// clamps to 100, so advancing by a larger `--limit` would step straight
|
|
324
|
+
// over the users this page could not hold (CR3127-002).
|
|
325
|
+
if (result.truncated) {
|
|
326
|
+
const pageSize = typeof result.limit === "number" && result.limit > 0
|
|
327
|
+
? result.limit
|
|
328
|
+
: limit;
|
|
329
|
+
const nextOffset = (result.offset ?? 0) + pageSize;
|
|
330
|
+
console.log();
|
|
331
|
+
// stdout, with the table it continues — a hint printed to stderr is
|
|
332
|
+
// the one a piped digest never sees.
|
|
333
|
+
console.log(`more results: rerun with --offset ${nextOffset}`);
|
|
334
|
+
}
|
|
108
335
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
336
|
+
catch (err) {
|
|
337
|
+
error(err.message);
|
|
338
|
+
process.exit(1);
|
|
112
339
|
}
|
|
340
|
+
});
|
|
341
|
+
// ── User Detail ──────────────────────────────────────────────────
|
|
342
|
+
analytics
|
|
343
|
+
.command("user-detail")
|
|
344
|
+
.description("Detailed activity for a single user")
|
|
345
|
+
.argument("<user-ulid>", "User ULID")
|
|
346
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
347
|
+
.option("--app <app-id>", "App ID")
|
|
348
|
+
.option("--json", "Output as JSON")
|
|
349
|
+
.action(async (userUlid, appId, options) => {
|
|
350
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
113
351
|
const client = new ApiClient();
|
|
114
352
|
try {
|
|
115
|
-
const result = await client.
|
|
116
|
-
windowDays: parseInt(options.windowDays),
|
|
117
|
-
});
|
|
353
|
+
const result = await client.getAnalyticsUserDetail(resolvedAppId, userUlid);
|
|
118
354
|
if (options.json) {
|
|
119
355
|
json(result);
|
|
120
356
|
return;
|
|
121
357
|
}
|
|
122
|
-
heading(
|
|
123
|
-
keyValue("User", userUlid);
|
|
358
|
+
heading("User Detail");
|
|
124
359
|
console.log();
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
360
|
+
printResult("ULID", result.user.user_ulid);
|
|
361
|
+
if (result.user.email)
|
|
362
|
+
printResult("Email", result.user.email);
|
|
363
|
+
if (result.user.name)
|
|
364
|
+
printResult("Name", result.user.name);
|
|
365
|
+
console.log();
|
|
366
|
+
printResult("First seen", result.stats.first_seen ? formatDate(result.stats.first_seen) : "-");
|
|
367
|
+
printResult("Last active", result.stats.last_active ? formatDate(result.stats.last_active) : "-");
|
|
368
|
+
printResult("Total events", String(result.stats.total_events));
|
|
369
|
+
printResult("Days active", String(result.stats.days_active));
|
|
370
|
+
if (result.events_by_action?.length > 0) {
|
|
371
|
+
console.log();
|
|
372
|
+
heading("Events by Action");
|
|
373
|
+
console.log();
|
|
374
|
+
console.log(formatTable(result.events_by_action, [
|
|
128
375
|
{ header: "ACTION", key: "action" },
|
|
129
|
-
{ header: "
|
|
130
|
-
{ header: "
|
|
131
|
-
{ header: "EVENTS", key: "events", align: "right" },
|
|
376
|
+
{ header: "COUNT", key: "event_count", align: "right", format: formatNumber },
|
|
377
|
+
{ header: "LAST OCCURRED", key: "last_occurred", format: formatDate },
|
|
132
378
|
]));
|
|
133
379
|
}
|
|
134
|
-
if (result.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
console.log(
|
|
138
|
-
|
|
139
|
-
{ header: "
|
|
380
|
+
if (result.events_by_feature?.length > 0) {
|
|
381
|
+
console.log();
|
|
382
|
+
heading("Events by Feature");
|
|
383
|
+
console.log();
|
|
384
|
+
console.log(formatTable(result.events_by_feature, [
|
|
385
|
+
{ header: "FEATURE", key: "feature" },
|
|
386
|
+
{ header: "COUNT", key: "event_count", align: "right", format: formatNumber },
|
|
387
|
+
{ header: "PCT", key: "pct", align: "right", format: formatPctRaw },
|
|
140
388
|
]));
|
|
141
389
|
}
|
|
142
390
|
}
|
|
@@ -145,7 +393,221 @@ Examples:
|
|
|
145
393
|
process.exit(1);
|
|
146
394
|
}
|
|
147
395
|
});
|
|
148
|
-
//
|
|
396
|
+
// ── User Snapshot ────────────────────────────────────────────────
|
|
397
|
+
analytics
|
|
398
|
+
.command("user-snapshot")
|
|
399
|
+
.description("Latest context snapshot for a user")
|
|
400
|
+
.argument("<user-ulid>", "User ULID")
|
|
401
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
402
|
+
.option("--app <app-id>", "App ID")
|
|
403
|
+
.option("--json", "Output as JSON")
|
|
404
|
+
.action(async (userUlid, appId, options) => {
|
|
405
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
406
|
+
const client = new ApiClient();
|
|
407
|
+
try {
|
|
408
|
+
const result = await client.getAnalyticsUserSnapshot(resolvedAppId, userUlid);
|
|
409
|
+
if (options.json) {
|
|
410
|
+
json(result);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
heading("User Snapshot");
|
|
414
|
+
console.log();
|
|
415
|
+
if (!result.snapshot) {
|
|
416
|
+
info("No snapshot found for this user.");
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
printResult("Timestamp", formatDate(result.snapshot.timestamp));
|
|
420
|
+
console.log();
|
|
421
|
+
console.log(JSON.stringify(result.snapshot.values, null, 2));
|
|
422
|
+
}
|
|
423
|
+
catch (err) {
|
|
424
|
+
error(err.message);
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
// ── Events Feed ──────────────────────────────────────────────────
|
|
429
|
+
analytics
|
|
430
|
+
.command("events")
|
|
431
|
+
.description("Paginated event feed")
|
|
432
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
433
|
+
.option("--app <app-id>", "App ID")
|
|
434
|
+
.option("--window-days <n>", "Time window in days", "7")
|
|
435
|
+
.option("--page <n>", "Page number (0-based)", "0")
|
|
436
|
+
.option("--user-id <id>", "Filter to a single user's events")
|
|
437
|
+
.option("--json", "Output as JSON")
|
|
438
|
+
.action(async (appId, options) => {
|
|
439
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
440
|
+
const client = new ApiClient();
|
|
441
|
+
try {
|
|
442
|
+
const result = await client.getAnalyticsEvents(resolvedAppId, {
|
|
443
|
+
windowDays: parseInt(options.windowDays),
|
|
444
|
+
page: parseInt(options.page),
|
|
445
|
+
// The events feed filters by user via the bracketed
|
|
446
|
+
// `filter[user][is]` syntax the analytics route already parses — not
|
|
447
|
+
// a raw query param (behavior 11).
|
|
448
|
+
...(options.userId ? { "filter[user][is]": options.userId } : {}),
|
|
449
|
+
});
|
|
450
|
+
if (options.json) {
|
|
451
|
+
// Normalize the offset-paged response to the shared activity
|
|
452
|
+
// envelope: `{page_size, rows}` → `{pageSize, items}` with the
|
|
453
|
+
// activity allowlist dropping infra fields such as `colo`
|
|
454
|
+
// (behaviors 7, 9).
|
|
455
|
+
json(buildActivityEnvelope(result));
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
heading(`Events (page ${result.page}, ${result.total_rows} total)`);
|
|
459
|
+
console.log();
|
|
460
|
+
if (!result.rows || result.rows.length === 0) {
|
|
461
|
+
info("No events found.");
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
// The USER cell prefers the feed's display name (#3168): only the
|
|
465
|
+
// system principal `sys:<appId>` has one, and its id is 30 characters
|
|
466
|
+
// — `formatId` truncated it at 26, mid-ULID. A column `format` sees
|
|
467
|
+
// only its own cell, so the fallback is folded in here.
|
|
468
|
+
const eventRows = result.rows.map((row) => ({
|
|
469
|
+
...row,
|
|
470
|
+
user_display: row.user_name ?? formatId(row.user_ulid ?? ""),
|
|
471
|
+
}));
|
|
472
|
+
console.log(formatTable(eventRows, [
|
|
473
|
+
{ header: "TIME", key: "timestamp", format: formatDate },
|
|
474
|
+
{ header: "USER", key: "user_display" },
|
|
475
|
+
{ header: "ACTION", key: "action" },
|
|
476
|
+
{ header: "FEATURE", key: "feature" },
|
|
477
|
+
{ header: "ROUTE", key: "route" },
|
|
478
|
+
{ header: "COUNTRY", key: "country" },
|
|
479
|
+
]));
|
|
480
|
+
const totalPages = Math.ceil(result.total_rows / result.page_size);
|
|
481
|
+
if (result.page + 1 < totalPages) {
|
|
482
|
+
console.log();
|
|
483
|
+
dim(`Page ${result.page + 1} of ${totalPages}. Use --page ${result.page + 1} for the next page.`);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
catch (err) {
|
|
487
|
+
error(err.message);
|
|
488
|
+
process.exit(1);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
// ── Events Grouped ───────────────────────────────────────────────
|
|
492
|
+
analytics
|
|
493
|
+
.command("events-grouped")
|
|
494
|
+
.description("Events grouped by a dimension")
|
|
495
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
496
|
+
.option("--app <app-id>", "App ID")
|
|
497
|
+
.option("--group-by <dim>", "Dimension: action, feature, route, country, deviceType, plan, day", "action")
|
|
498
|
+
.option("--window-days <n>", "Time window in days", "7")
|
|
499
|
+
.option("--json", "Output as JSON")
|
|
500
|
+
.action(async (appId, options) => {
|
|
501
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
502
|
+
const client = new ApiClient();
|
|
503
|
+
try {
|
|
504
|
+
const result = await client.getAnalyticsEventsGrouped(resolvedAppId, {
|
|
505
|
+
groupBy: options.groupBy,
|
|
506
|
+
windowDays: parseInt(options.windowDays),
|
|
507
|
+
});
|
|
508
|
+
if (options.json) {
|
|
509
|
+
json(result);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
heading(`Events by ${result.group_by}`);
|
|
513
|
+
console.log();
|
|
514
|
+
if (!result.rows || result.rows.length === 0) {
|
|
515
|
+
info("No events found.");
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
console.log(formatTable(result.rows, [
|
|
519
|
+
{ header: result.group_by.toUpperCase(), key: "group_value" },
|
|
520
|
+
{ header: "EVENTS", key: "events", align: "right", format: formatNumber },
|
|
521
|
+
{ header: "UNIQUE USERS", key: "unique_users", align: "right", format: formatNumber },
|
|
522
|
+
]));
|
|
523
|
+
}
|
|
524
|
+
catch (err) {
|
|
525
|
+
error(err.message);
|
|
526
|
+
process.exit(1);
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
// ── Errors Grouped ───────────────────────────────────────────────
|
|
530
|
+
analytics
|
|
531
|
+
.command("errors-groups")
|
|
532
|
+
.description("Group failure events by fingerprint with per-day count buckets")
|
|
533
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
534
|
+
.option("--app <app-id>", "App ID")
|
|
535
|
+
.option("--window-days <n>", "Time window in days", "7")
|
|
536
|
+
.option("--limit <n>", "Max error groups to return", "50")
|
|
537
|
+
.option("--status-class <class>", "Filter by status class: 4xx, 5xx, transport")
|
|
538
|
+
.option("--source <source>", "Filter by source: workflow_run, workflow_step, integration, " +
|
|
539
|
+
"function_invocation, function_run")
|
|
540
|
+
.option("--verbose", "Also print each group's exemplar (a raw sample of the failure) and where it came from")
|
|
541
|
+
.option("--json", "Output as JSON")
|
|
542
|
+
.action(async (appId, options) => {
|
|
543
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
544
|
+
const client = new ApiClient();
|
|
545
|
+
try {
|
|
546
|
+
const params = {
|
|
547
|
+
windowDays: parseInt(options.windowDays),
|
|
548
|
+
limit: parseInt(options.limit),
|
|
549
|
+
};
|
|
550
|
+
if (options.statusClass) {
|
|
551
|
+
params["filter[statusClass][is]"] = options.statusClass;
|
|
552
|
+
}
|
|
553
|
+
if (options.source) {
|
|
554
|
+
params["filter[source][is]"] = options.source;
|
|
555
|
+
}
|
|
556
|
+
const result = await client.getAnalyticsErrorsGroups(resolvedAppId, params);
|
|
557
|
+
if (options.json) {
|
|
558
|
+
json(result);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
heading(`Error groups (last ${result.window_days} days)`);
|
|
562
|
+
console.log();
|
|
563
|
+
if (!result.rows || result.rows.length === 0) {
|
|
564
|
+
info("No error groups found.");
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
console.log(formatTable(result.rows, [
|
|
568
|
+
{ header: "TITLE", key: "normalized_title" },
|
|
569
|
+
{ header: "SOURCE", key: "source" },
|
|
570
|
+
{ header: "STATUS", key: "status_class" },
|
|
571
|
+
{
|
|
572
|
+
header: "TOTAL",
|
|
573
|
+
key: "total",
|
|
574
|
+
align: "right",
|
|
575
|
+
format: formatNumber,
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
header: "DAYS",
|
|
579
|
+
key: "daily",
|
|
580
|
+
align: "right",
|
|
581
|
+
format: (d) => formatNumber(Array.isArray(d) ? d.length : 0),
|
|
582
|
+
},
|
|
583
|
+
{ header: "LAST SEEN", key: "last_seen", format: formatDate },
|
|
584
|
+
{ header: "FINGERPRINT", key: "fingerprint", format: formatId },
|
|
585
|
+
]));
|
|
586
|
+
// The normalized title is a grouping key, not an explanation — the
|
|
587
|
+
// exemplar is the raw sample plus the run/step it came from, which is
|
|
588
|
+
// what makes a group actionable without paging `analytics events`.
|
|
589
|
+
if (options.verbose) {
|
|
590
|
+
for (const row of result.rows) {
|
|
591
|
+
console.log();
|
|
592
|
+
heading(row.normalized_title || row.fingerprint);
|
|
593
|
+
printResult("Seen", `${row.first_seen ? formatDate(row.first_seen) : "-"} → ${row.last_seen ? formatDate(row.last_seen) : "-"}`);
|
|
594
|
+
if (!row.exemplar) {
|
|
595
|
+
info("No exemplar available for this group.");
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
598
|
+
printResult("Example", row.exemplar.message);
|
|
599
|
+
printResult("Scope", row.exemplar.scope_key || "-");
|
|
600
|
+
printResult("Step", row.exemplar.step_id || "-");
|
|
601
|
+
printResult("Run", row.exemplar.run_id || "-");
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
catch (err) {
|
|
606
|
+
error(err.message);
|
|
607
|
+
process.exit(1);
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
// ── Integration Metrics ──────────────────────────────────────────
|
|
149
611
|
analytics
|
|
150
612
|
.command("integrations")
|
|
151
613
|
.description("Get integration usage metrics")
|
|
@@ -174,8 +636,8 @@ Examples:
|
|
|
174
636
|
{ header: "INTEGRATION", key: "integrationKey" },
|
|
175
637
|
{ header: "CALLS", key: "invocations", align: "right", format: formatNumber },
|
|
176
638
|
{ header: "ERROR RATE", key: "errorRate", align: "right", format: formatPercent },
|
|
177
|
-
{ header: "
|
|
178
|
-
{ header: "P95
|
|
639
|
+
{ header: "MEDIAN", key: "medianDurationMs", align: "right", format: formatDuration },
|
|
640
|
+
{ header: "P95", key: "p95DurationMs", align: "right", format: formatDuration },
|
|
179
641
|
]));
|
|
180
642
|
}
|
|
181
643
|
catch (err) {
|
|
@@ -183,5 +645,201 @@ Examples:
|
|
|
183
645
|
process.exit(1);
|
|
184
646
|
}
|
|
185
647
|
});
|
|
648
|
+
// ── Top Workflows ────────────────────────────────────────────────
|
|
649
|
+
analytics
|
|
650
|
+
.command("workflows")
|
|
651
|
+
.description("Top workflows by runs")
|
|
652
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
653
|
+
.option("--app <app-id>", "App ID")
|
|
654
|
+
.option("--window-days <n>", "Time window in days", "30")
|
|
655
|
+
.option("--limit <n>", "Number of workflows to show", "10")
|
|
656
|
+
.option("--json", "Output as JSON")
|
|
657
|
+
.action(async (appId, options) => {
|
|
658
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
659
|
+
const client = new ApiClient();
|
|
660
|
+
try {
|
|
661
|
+
const result = await client.getAnalyticsTopWorkflows(resolvedAppId, {
|
|
662
|
+
windowDays: parseInt(options.windowDays),
|
|
663
|
+
limit: parseInt(options.limit),
|
|
664
|
+
});
|
|
665
|
+
if (options.json) {
|
|
666
|
+
json(result);
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
heading(`Top Workflows (${result.windowDays} days)`);
|
|
670
|
+
console.log();
|
|
671
|
+
if (!result.workflows || result.workflows.length === 0) {
|
|
672
|
+
info("No workflow data found.");
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
console.log(formatTable(result.workflows, [
|
|
676
|
+
{ header: "WORKFLOW", key: "workflowKey" },
|
|
677
|
+
{ header: "RUNS", key: "runs", align: "right", format: formatNumber },
|
|
678
|
+
{ header: "SUCCESS", key: "successRate", align: "right", format: formatPercent },
|
|
679
|
+
{ header: "MEDIAN", key: "medianDurationMs", align: "right", format: formatDuration },
|
|
680
|
+
{ header: "P95", key: "p95", align: "right", format: formatDuration },
|
|
681
|
+
{ header: "TOKENS", key: "totalTokens", align: "right", format: formatNumber },
|
|
682
|
+
]));
|
|
683
|
+
}
|
|
684
|
+
catch (err) {
|
|
685
|
+
error(err.message);
|
|
686
|
+
process.exit(1);
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
// ── Top Prompts ──────────────────────────────────────────────────
|
|
690
|
+
analytics
|
|
691
|
+
.command("prompts")
|
|
692
|
+
.description("Top prompts by executions")
|
|
693
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
694
|
+
.option("--app <app-id>", "App ID")
|
|
695
|
+
.option("--window-days <n>", "Time window in days", "30")
|
|
696
|
+
.option("--limit <n>", "Number of prompts to show", "10")
|
|
697
|
+
.option("--json", "Output as JSON")
|
|
698
|
+
.action(async (appId, options) => {
|
|
699
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
700
|
+
const client = new ApiClient();
|
|
701
|
+
try {
|
|
702
|
+
const result = await client.getAnalyticsTopPrompts(resolvedAppId, {
|
|
703
|
+
windowDays: parseInt(options.windowDays),
|
|
704
|
+
limit: parseInt(options.limit),
|
|
705
|
+
});
|
|
706
|
+
if (options.json) {
|
|
707
|
+
json(result);
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
heading(`Top Prompts (${result.windowDays} days)`);
|
|
711
|
+
console.log();
|
|
712
|
+
if (!result.prompts || result.prompts.length === 0) {
|
|
713
|
+
info("No prompt data found.");
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
// #3787 — the cost cells read the whole row (the total needs the
|
|
717
|
+
// window's costed count to mark a partial one), and `formatTable`'s
|
|
718
|
+
// `format` sees one cell's value, so they are rendered up front.
|
|
719
|
+
const promptRows = result.prompts.map((prompt) => ({
|
|
720
|
+
...prompt,
|
|
721
|
+
costCell: formatCostCell(prompt),
|
|
722
|
+
avgCostCell: formatAvgCostCell(prompt),
|
|
723
|
+
}));
|
|
724
|
+
console.log(formatTable(promptRows, [
|
|
725
|
+
{ header: "PROMPT", key: "promptKey" },
|
|
726
|
+
{ header: "RUNS", key: "executions", align: "right", format: formatNumber },
|
|
727
|
+
{ header: "MEDIAN", key: "medianDurationMs", align: "right", format: formatDuration },
|
|
728
|
+
{ header: "P95", key: "p95DurationMs", align: "right", format: formatDuration },
|
|
729
|
+
{ header: "TOKENS", key: "totalTokens", align: "right", format: formatNumber },
|
|
730
|
+
{ header: "COST", key: "costCell", align: "right" },
|
|
731
|
+
{ header: "AVG COST", key: "avgCostCell", align: "right" },
|
|
732
|
+
]));
|
|
733
|
+
}
|
|
734
|
+
catch (err) {
|
|
735
|
+
error(err.message);
|
|
736
|
+
process.exit(1);
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
// ── Workflow step usage ──────────────────────────────────────────
|
|
740
|
+
/** Print one report's blocks: headings to stderr, bodies to stdout. */
|
|
741
|
+
function printUsageBlocks(blocks) {
|
|
742
|
+
for (const block of blocks) {
|
|
743
|
+
if (block.heading) {
|
|
744
|
+
console.log();
|
|
745
|
+
heading(block.heading);
|
|
746
|
+
}
|
|
747
|
+
console.log(block.body);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
analytics
|
|
751
|
+
.command("workflow-usage")
|
|
752
|
+
.description("Step kinds this app's workflows configure, their runs in the window, and the sync-callable and idle workflows")
|
|
753
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
754
|
+
.option("--app <app-id>", "App ID")
|
|
755
|
+
.option("--window-days <n>", `Run window in days (${USAGE_CLI_MIN_WINDOW_DAYS}-${USAGE_CLI_MAX_WINDOW_DAYS}, default ${USAGE_CLI_DEFAULT_WINDOW_DAYS})`)
|
|
756
|
+
.option("--all-apps", "Merge the report across every app (super-admin only)")
|
|
757
|
+
.option("--json", "Output as JSON")
|
|
758
|
+
.action(async (appId, options) => {
|
|
759
|
+
// Both boundary checks run before the client is constructed, so an
|
|
760
|
+
// invalid invocation never reaches the network (principle 6).
|
|
761
|
+
if (options.allApps && (appId || options.app)) {
|
|
762
|
+
error(ALL_APPS_CONFLICT_ERROR);
|
|
763
|
+
process.exit(1);
|
|
764
|
+
}
|
|
765
|
+
const window = parseWindowDaysFlag(options.windowDays);
|
|
766
|
+
if ("error" in window) {
|
|
767
|
+
error(window.error);
|
|
768
|
+
process.exit(1);
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
// Omitted means omitted on the wire: the server applies its own default
|
|
772
|
+
// and the CLI reports the same number for a merge that has no request.
|
|
773
|
+
const params = window.omitted
|
|
774
|
+
? undefined
|
|
775
|
+
: { windowDays: window.effective };
|
|
776
|
+
const client = new ApiClient();
|
|
777
|
+
if (options.allApps) {
|
|
778
|
+
try {
|
|
779
|
+
// The role gate comes first: GET /admin/api/apps is super-admin
|
|
780
|
+
// only (#3882), so the client refuses anyone else with its own
|
|
781
|
+
// message before any request rather than meeting the server's 403
|
|
782
|
+
// (D3130-002).
|
|
783
|
+
const me = await client.getMe();
|
|
784
|
+
if (!isSuperAdminRole(me.role)) {
|
|
785
|
+
error(ALL_APPS_SUPER_ADMIN_ERROR);
|
|
786
|
+
process.exit(1);
|
|
787
|
+
}
|
|
788
|
+
// There is no cross-app endpoint by design (intent): the CLI calls
|
|
789
|
+
// the per-app one once per app, over the GLOBAL apps list.
|
|
790
|
+
const apps = await client.listAllAppsGlobal();
|
|
791
|
+
const results = [];
|
|
792
|
+
for (const app of apps) {
|
|
793
|
+
try {
|
|
794
|
+
results.push({
|
|
795
|
+
appId: app.appId,
|
|
796
|
+
report: await client.getWorkflowUsage(app.appId, params),
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
catch (err) {
|
|
800
|
+
// A merged report over a silently chosen subset would answer a
|
|
801
|
+
// different question, so a refusal ends the walk.
|
|
802
|
+
if (isAbortStatus(err?.statusCode))
|
|
803
|
+
throw err;
|
|
804
|
+
results.push({
|
|
805
|
+
appId: app.appId,
|
|
806
|
+
error: err?.message ?? String(err),
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
const merged = mergeUsageReports(window.effective, results);
|
|
811
|
+
if (options.json) {
|
|
812
|
+
json(merged);
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
printUsageBlocks(renderMergedUsageReport(merged));
|
|
816
|
+
}
|
|
817
|
+
// An incomplete report still prints, and still fails (intent).
|
|
818
|
+
// `exitCode` rather than `exit()`: the report is already on stdout
|
|
819
|
+
// and `process.exit` truncates a pipe's pending writes (#1004).
|
|
820
|
+
process.exitCode = usageExitCode(merged);
|
|
821
|
+
}
|
|
822
|
+
catch (err) {
|
|
823
|
+
error(err.message);
|
|
824
|
+
process.exit(1);
|
|
825
|
+
}
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
829
|
+
try {
|
|
830
|
+
const report = await client.getWorkflowUsage(resolvedAppId, params);
|
|
831
|
+
if (options.json) {
|
|
832
|
+
json(report);
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
printUsageBlocks(renderUsageReport(report));
|
|
836
|
+
}
|
|
837
|
+
process.exitCode = usageExitCode(report);
|
|
838
|
+
}
|
|
839
|
+
catch (err) {
|
|
840
|
+
error(err.message);
|
|
841
|
+
process.exit(1);
|
|
842
|
+
}
|
|
843
|
+
});
|
|
186
844
|
}
|
|
187
845
|
//# sourceMappingURL=analytics.js.map
|