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.
- package/README.md +389 -71
- package/assets/skill/skills/primitive-platform/SKILL.md +670 -0
- package/dist/bin/primitive.d.ts +2 -0
- package/dist/bin/primitive.js +287 -17
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/admins.d.ts +2 -0
- package/dist/src/commands/admins.js +138 -19
- package/dist/src/commands/admins.js.map +1 -1
- package/dist/src/commands/analytics.d.ts +2 -0
- package/dist/src/commands/analytics.js +554 -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 +27 -80
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/auth.d.ts +2 -0
- package/dist/src/commands/auth.js +177 -7
- 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 +330 -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 +37 -38
- 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 +92 -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 +526 -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 +35 -0
- package/dist/src/commands/config.js +437 -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 +100 -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 +204 -0
- package/dist/src/commands/cron-triggers.js.map +1 -0
- package/dist/src/commands/database-types.d.ts +2 -0
- package/dist/src/commands/database-types.js +171 -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 +2153 -96
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.d.ts +2 -0
- package/dist/src/commands/documents.js +1230 -19
- 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 +174 -0
- package/dist/src/commands/email-templates.js.map +1 -0
- package/dist/src/commands/env.d.ts +12 -0
- package/dist/src/commands/env.js +260 -0
- package/dist/src/commands/env.js.map +1 -0
- package/dist/src/commands/group-type-configs.d.ts +2 -0
- package/dist/src/commands/group-type-configs.js +86 -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 +38 -99
- package/dist/src/commands/groups.js.map +1 -1
- package/dist/src/commands/guides.d.ts +223 -0
- package/dist/src/commands/guides.js +617 -65
- package/dist/src/commands/guides.js.map +1 -1
- package/dist/src/commands/init.d.ts +17 -0
- package/dist/src/commands/init.js +964 -202
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.d.ts +2 -0
- package/dist/src/commands/integrations.js +484 -205
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/llm.d.ts +2 -0
- package/dist/src/commands/llm.js +13 -8
- package/dist/src/commands/llm.js.map +1 -1
- package/dist/src/commands/locks.d.ts +8 -0
- package/dist/src/commands/locks.js +160 -0
- package/dist/src/commands/locks.js.map +1 -0
- package/dist/src/commands/metadata.d.ts +2 -0
- package/dist/src/commands/metadata.js +406 -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 +135 -355
- 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 +271 -0
- package/dist/src/commands/rule-sets.js.map +1 -0
- package/dist/src/commands/scripts.d.ts +20 -0
- package/dist/src/commands/scripts.js +739 -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 +108 -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 +75 -0
- package/dist/src/commands/sessions.js.map +1 -0
- package/dist/src/commands/settings.d.ts +18 -0
- package/dist/src/commands/settings.js +54 -0
- package/dist/src/commands/settings.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 +125 -0
- package/dist/src/commands/sync-app-settings.js +380 -0
- package/dist/src/commands/sync-app-settings.js.map +1 -0
- package/dist/src/commands/sync.d.ts +958 -0
- package/dist/src/commands/sync.js +8954 -812
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.d.ts +2 -0
- package/dist/src/commands/tokens.js +130 -21
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.d.ts +2 -0
- package/dist/src/commands/users.js +440 -22
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/commands/vars.d.ts +8 -0
- package/dist/src/commands/vars.js +96 -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 +10 -10
- package/dist/src/commands/waitlist.js.map +1 -1
- package/dist/src/commands/webhooks.d.ts +2 -0
- package/dist/src/commands/webhooks.js +442 -0
- package/dist/src/commands/webhooks.js.map +1 -0
- package/dist/src/commands/workflows.d.ts +94 -0
- package/dist/src/commands/workflows.js +1581 -448
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +1814 -0
- package/dist/src/lib/api-client.js +1655 -103
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/app-settings-descriptor.d.ts +130 -0
- package/dist/src/lib/app-settings-descriptor.js +262 -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/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 +97 -0
- package/dist/src/lib/codegen-shared/generatedFiles.js +184 -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 +68 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +168 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -0
- package/dist/src/lib/config-object-descriptor.d.ts +108 -0
- package/dist/src/lib/config-object-descriptor.js +607 -0
- package/dist/src/lib/config-object-descriptor.js.map +1 -0
- package/dist/src/lib/config-payload.d.ts +85 -0
- package/dist/src/lib/config-payload.js +105 -0
- package/dist/src/lib/config-payload.js.map +1 -0
- package/dist/src/lib/config-surface.d.ts +93 -0
- package/dist/src/lib/config-surface.js +178 -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 +53 -0
- package/dist/src/lib/config.js +92 -53
- 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 +89 -0
- package/dist/src/lib/credentials-store.js +330 -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 +517 -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/env-resolver.d.ts +62 -0
- package/dist/src/lib/env-resolver.js +121 -0
- package/dist/src/lib/env-resolver.js.map +1 -0
- package/dist/src/lib/fetch.d.ts +5 -0
- package/dist/src/lib/generated-allowlist.d.ts +28 -0
- package/dist/src/lib/generated-allowlist.js +266 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -0
- package/dist/src/lib/generated-config-surfaces.d.ts +578 -0
- package/dist/src/lib/generated-config-surfaces.js +3630 -0
- package/dist/src/lib/generated-config-surfaces.js.map +1 -0
- package/dist/src/lib/generated-template-lint.d.ts +206 -0
- package/dist/src/lib/generated-template-lint.js +589 -0
- package/dist/src/lib/generated-template-lint.js.map +1 -0
- package/dist/src/lib/generated-workflow-model-fields.d.ts +20 -0
- package/dist/src/lib/generated-workflow-model-fields.js +53 -0
- package/dist/src/lib/generated-workflow-model-fields.js.map +1 -0
- package/dist/src/lib/google-client-secret-status.d.ts +35 -0
- package/dist/src/lib/google-client-secret-status.js +56 -0
- package/dist/src/lib/google-client-secret-status.js.map +1 -0
- package/dist/src/lib/init-config.d.ts +81 -0
- package/dist/src/lib/init-config.js +149 -0
- package/dist/src/lib/init-config.js.map +1 -0
- package/dist/src/lib/log-inspection.d.ts +568 -0
- package/dist/src/lib/log-inspection.js +639 -0
- package/dist/src/lib/log-inspection.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/output.d.ts +109 -0
- package/dist/src/lib/output.js +191 -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 +83 -0
- package/dist/src/lib/paginate.js +95 -0
- package/dist/src/lib/paginate.js.map +1 -0
- package/dist/src/lib/platform-owned.d.ts +51 -0
- package/dist/src/lib/platform-owned.js +64 -0
- package/dist/src/lib/platform-owned.js.map +1 -0
- package/dist/src/lib/project-config.d.ts +97 -0
- package/dist/src/lib/project-config.js +219 -0
- package/dist/src/lib/project-config.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 +65 -0
- package/dist/src/lib/refresh-admin-credentials.js +103 -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 +71 -0
- package/dist/src/lib/resolve-init-server.js +94 -0
- package/dist/src/lib/resolve-init-server.js.map +1 -0
- package/dist/src/lib/resolve-platform.d.ts +45 -0
- package/dist/src/lib/resolve-platform.js +43 -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/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 +25 -0
- package/dist/src/lib/skill-installer.js +266 -0
- package/dist/src/lib/skill-installer.js.map +1 -0
- package/dist/src/lib/snapshots.d.ts +99 -0
- package/dist/src/lib/snapshots.js +357 -0
- package/dist/src/lib/snapshots.js.map +1 -0
- package/dist/src/lib/swift-codegen/dbGenerator.d.ts +100 -0
- package/dist/src/lib/swift-codegen/dbGenerator.js +682 -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/generator.d.ts +85 -0
- package/dist/src/lib/swift-codegen/generator.js +266 -0
- package/dist/src/lib/swift-codegen/generator.js.map +1 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +72 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.js +644 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.d.ts +90 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.js +152 -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-paths.d.ts +72 -0
- package/dist/src/lib/sync-paths.js +130 -0
- package/dist/src/lib/sync-paths.js.map +1 -0
- package/dist/src/lib/sync-resource-types.d.ts +445 -0
- package/dist/src/lib/sync-resource-types.js +812 -0
- package/dist/src/lib/sync-resource-types.js.map +1 -0
- package/dist/src/lib/sync-selectors.d.ts +95 -0
- package/dist/src/lib/sync-selectors.js +228 -0
- package/dist/src/lib/sync-selectors.js.map +1 -0
- package/dist/src/lib/template.d.ts +121 -0
- package/dist/src/lib/template.js +447 -67
- package/dist/src/lib/template.js.map +1 -1
- 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 +527 -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/workflow-apply.d.ts +51 -0
- package/dist/src/lib/workflow-apply.js +89 -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 +83 -0
- package/dist/src/lib/workflow-codegen/invokerIR.js +71 -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-field-descriptor.d.ts +91 -0
- package/dist/src/lib/workflow-field-descriptor.js +153 -0
- package/dist/src/lib/workflow-field-descriptor.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 +71 -0
- package/dist/src/lib/workflow-include-preserve.js +153 -0
- package/dist/src/lib/workflow-include-preserve.js.map +1 -0
- package/dist/src/lib/workflow-payload.d.ts +86 -0
- package/dist/src/lib/workflow-payload.js +168 -0
- package/dist/src/lib/workflow-payload.js.map +1 -0
- package/dist/src/lib/workflow-toml-validator.d.ts +199 -0
- package/dist/src/lib/workflow-toml-validator.js +754 -0
- package/dist/src/lib/workflow-toml-validator.js.map +1 -0
- package/dist/src/types/index.d.ts +533 -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 +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,
|
|
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
|
|
12
|
-
$ primitive analytics
|
|
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("
|
|
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>", "
|
|
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
|
|
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(`
|
|
115
|
+
heading(`Daily Active Users (${result.window_days} days)`);
|
|
34
116
|
console.log();
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
//
|
|
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
|
|
266
|
+
// ── User Search ──────────────────────────────────────────────────
|
|
94
267
|
analytics
|
|
95
|
-
.command("user")
|
|
96
|
-
.description("
|
|
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
|
-
.
|
|
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 (
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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.
|
|
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(
|
|
123
|
-
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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: "
|
|
130
|
-
{ header: "
|
|
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.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
console.log(
|
|
138
|
-
|
|
139
|
-
{ header: "
|
|
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
|
-
//
|
|
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: "
|
|
178
|
-
{ header: "P95
|
|
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) {
|