|
| 1 | +/* Rust wizard using posthog-agent with PostHog MCP */ |
| 2 | +import * as fs from 'node:fs'; |
| 3 | +import * as path from 'node:path'; |
| 4 | +import type { WizardRunOptions } from '@utils/types'; |
| 5 | +import type { FrameworkConfig } from '@lib/framework-config'; |
| 6 | +import { cargoPackageManager } from '@lib/detection/package-manager'; |
| 7 | +import { Integration } from '@lib/constants'; |
| 8 | + |
| 9 | +type RustContext = { |
| 10 | + asyncRuntime?: boolean; |
| 11 | +}; |
| 12 | + |
| 13 | +function readCargoToml(installDir: string): string | undefined { |
| 14 | + const cargoTomlPath = path.join(installDir, 'Cargo.toml'); |
| 15 | + if (!fs.existsSync(cargoTomlPath)) { |
| 16 | + return undefined; |
| 17 | + } |
| 18 | + return fs.readFileSync(cargoTomlPath, 'utf-8'); |
| 19 | +} |
| 20 | + |
| 21 | +/** posthog-rs defaults to its async client; projects without an async runtime need the blocking one. */ |
| 22 | +function hasAsyncRuntime(installDir: string): boolean { |
| 23 | + const cargoToml = readCargoToml(installDir); |
| 24 | + return !!cargoToml && /^\s*(tokio|async-std|smol)\s*[=.]/m.test(cargoToml); |
| 25 | +} |
| 26 | + |
| 27 | +export const RUST_AGENT_CONFIG: FrameworkConfig<RustContext> = { |
| 28 | + metadata: { |
| 29 | + name: 'Rust', |
| 30 | + integration: Integration.rust, |
| 31 | + docsUrl: 'https://posthog.com/docs/libraries/rust', |
| 32 | + gatherContext: (options: WizardRunOptions) => { |
| 33 | + const asyncRuntime = hasAsyncRuntime(options.installDir); |
| 34 | + return Promise.resolve({ asyncRuntime }); |
| 35 | + }, |
| 36 | + }, |
| 37 | + |
| 38 | + detection: { |
| 39 | + packageName: 'posthog-rs', |
| 40 | + packageDisplayName: 'Rust', |
| 41 | + usesPackageJson: false, |
| 42 | + getVersion: () => undefined, |
| 43 | + // A Cargo.toml with a [package] section marks a crate root. A |
| 44 | + // workspace-root-only manifest ([workspace], no [package]) falls |
| 45 | + // through — the agentic monorepo scan finds the nested crates. |
| 46 | + detect: (options) => { |
| 47 | + const cargoToml = readCargoToml(options.installDir); |
| 48 | + return Promise.resolve(!!cargoToml && /^\s*\[package\]/m.test(cargoToml)); |
| 49 | + }, |
| 50 | + detectPackageManager: cargoPackageManager, |
| 51 | + }, |
| 52 | + |
| 53 | + environment: { |
| 54 | + uploadToHosting: false, |
| 55 | + getEnvVars: (apiKey: string, host: string) => ({ |
| 56 | + POSTHOG_API_KEY: apiKey, |
| 57 | + POSTHOG_HOST: host, |
| 58 | + }), |
| 59 | + }, |
| 60 | + |
| 61 | + analytics: { |
| 62 | + getTags: (context) => ({ |
| 63 | + asyncRuntime: context.asyncRuntime ? 'true' : 'false', |
| 64 | + }), |
| 65 | + }, |
| 66 | + |
| 67 | + prompts: { |
| 68 | + projectTypeDetection: |
| 69 | + 'This is a Rust project. Look for Cargo.toml with a [package] section, src/main.rs or src/lib.rs, and Cargo.lock to confirm.', |
| 70 | + packageInstallation: |
| 71 | + 'Install the PostHog Rust SDK with `cargo add posthog-rs`. Do not manually edit Cargo.toml; cargo updates it automatically.', |
| 72 | + getAdditionalContextLines: (context) => { |
| 73 | + const lines = [ |
| 74 | + `Framework docs ID: rust (use posthog://docs/frameworks/rust for documentation)`, |
| 75 | + 'capture() hands events to a background worker — the client must flush() or shutdown() before the process exits or buffered events are lost.', |
| 76 | + ]; |
| 77 | + if (context.asyncRuntime) { |
| 78 | + lines.push( |
| 79 | + 'An async runtime is present — use the default async posthog-rs client.', |
| 80 | + ); |
| 81 | + } else { |
| 82 | + lines.push( |
| 83 | + 'No async runtime detected — install with `cargo add posthog-rs --no-default-features` and use the blocking client.', |
| 84 | + ); |
| 85 | + } |
| 86 | + return lines; |
| 87 | + }, |
| 88 | + }, |
| 89 | + |
| 90 | + ui: { |
| 91 | + successMessage: 'PostHog integration complete', |
| 92 | + estimatedDurationMinutes: 5, |
| 93 | + getOutroChanges: () => [ |
| 94 | + 'Analyzed your Rust project structure', |
| 95 | + 'Installed the posthog-rs crate via cargo add', |
| 96 | + 'Initialized a shared PostHog client configured from environment variables', |
| 97 | + 'Instrumented meaningful events with client.capture', |
| 98 | + ], |
| 99 | + getOutroNextSteps: () => [ |
| 100 | + 'Run your Rust application and trigger the instrumented code paths', |
| 101 | + 'Visit your PostHog dashboard to see incoming events', |
| 102 | + 'Use Event::new(event_name, distinct_id) and client.capture to track custom events', |
| 103 | + 'Keep flush()/shutdown() in your exit path so queued events are sent', |
| 104 | + ], |
| 105 | + }, |
| 106 | +}; |
0 commit comments