diff --git a/README.md b/README.md index 2e711f17b..8458d9b94 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,32 @@ <br /> -The Codegen SDK provides a programmatic interface to code agents provided by [Codegen](https://codegen.com). +# Codegen SDK + +The Codegen SDK provides a programmatic interface to AI-powered code agents provided by [Codegen](https://codegen.com). It enables developers to integrate intelligent code generation, analysis, and transformation capabilities into their workflows and applications. + +## Features + +- **AI-Powered Code Generation**: Generate code based on natural language descriptions +- **Code Analysis**: Analyze codebases for patterns, issues, and insights +- **Code Transformation**: Refactor and transform code with intelligent understanding of context +- **Multi-Language Support**: Works with Python, JavaScript, TypeScript, and more +- **Integration with Development Workflows**: Seamlessly integrate with your existing tools +- **Extensible Architecture**: Build custom extensions and workflows + +## Installation + +Install the SDK using pip or uv: + +```bash +pip install codegen +# or +uv pip install codegen +``` + +Requires Python 3.12 or newer. + +## Quick Start ```python from codegen.agents.agent import Agent @@ -51,31 +76,82 @@ if task.status == "completed": print(task.result) # Result often contains code, summaries, or links ``` -## Installation and Usage +## Advanced Usage -Install the SDK using pip or uv: +### Working with Specific Files + +```python +from codegen.agents.agent import Agent + +agent = Agent(org_id="YOUR_ORG_ID", token="YOUR_API_TOKEN") + +# Analyze a specific file +task = agent.run(prompt="Analyze this file for potential bugs and suggest improvements.", files=["path/to/your/file.py"]) + +# Wait for completion and get results +task.wait_until_complete() +print(task.result) +``` + +### Transforming Code + +```python +from codegen.agents.agent import Agent + +agent = Agent(org_id="YOUR_ORG_ID", token="YOUR_API_TOKEN") + +# Transform code based on requirements +task = agent.run(prompt="Refactor this code to use async/await pattern instead of callbacks.", files=["path/to/your/file.js"]) + +# Wait for completion and get results +task.wait_until_complete() +print(task.result) +``` + +## Command Line Interface + +The SDK includes a powerful CLI tool that allows you to interact with Codegen directly from your terminal: ```bash -pip install codegen -# or -uv pip install codegen +# Get help +codegen --help + +# Initialize configuration +codegen init + +# Run an agent with a prompt +codegen run "Implement a function to calculate Fibonacci numbers" + +# Analyze a file +codegen analyze path/to/file.py ``` -Get started at [codegen.com](https://codegen.com) and get your API token at [codegen.com/developer](https://codegen.com/developer). +## Integrations + +Codegen integrates with popular development tools: -You can interact with your AI engineer via API, or chat with it in Slack, Linear, Github, or on our website. +- **Slack**: Chat with your AI engineer in Slack +- **GitHub**: Get PR reviews and code suggestions +- **Linear**: Manage tasks and issues with AI assistance +- **Web Interface**: Use the web UI at [codegen.com](https://codegen.com) ## Resources -- [Docs](https://docs.codegen.com) -- [Getting Started](https://docs.codegen.com/introduction/getting-started) -- [Contributing](CONTRIBUTING.md) +- [Documentation](https://docs.codegen.com) +- [Getting Started Guide](https://docs.codegen.com/introduction/getting-started) +- [API Reference](https://docs.codegen.com/api-reference) +- [Examples](https://github.com/codegen-sh/codegen-examples) +- [Contributing Guide](CONTRIBUTING.md) - [Contact Us](https://codegen.com/contact) ## Contributing -Please see our [Contributing Guide](CONTRIBUTING.md) for instructions on how to set up the development environment and submit contributions. +We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for instructions on how to set up the development environment and submit contributions. ## Enterprise For more information on enterprise engagements, please [contact us](https://codegen.com/contact) or [request a demo](https://codegen.com/request-demo). + +## License + +This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/chart.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/chart.tsx index aa3d5f99a..f51563023 100644 --- a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/chart.tsx +++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/chart.tsx @@ -1,6 +1,7 @@ "use client"; import * as React from "react"; +import { useEffect, useRef } from "react"; import * as RechartsPrimitive from "recharts"; import { cn } from "@/lib/utils"; @@ -9,55 +10,52 @@ import { cn } from "@/lib/utils"; const THEMES = { light: "", dark: ".dark" } as const; export type ChartConfig = { - [k in string]: { - label?: React.ReactNode; - icon?: React.ComponentType; - } & ( - | { color?: string; theme?: never } - | { color?: never; theme: Record<keyof typeof THEMES, string> } - ); + [key: string]: { + theme?: Record<string, string>; + color?: string; + }; }; type ChartContextProps = { - config: ChartConfig; + chartId: string; }; -const ChartContext = React.createContext<ChartContextProps | null>(null); +const ChartContext = React.createContext<ChartContextProps>({ + chartId: "", +}); -function useChart() { +const useChart = () => { const context = React.useContext(ChartContext); if (!context) { - throw new Error("useChart must be used within a <ChartContainer />"); + throw new Error("useChart must be used within a ChartProvider"); } return context; -} +}; const ChartContainer = React.forwardRef< HTMLDivElement, - React.ComponentProps<"div"> & { - config: ChartConfig; - children: React.ComponentProps< - typeof RechartsPrimitive.ResponsiveContainer - >["children"]; + React.HTMLAttributes<HTMLDivElement> & { + config?: ChartConfig; } ->(({ id, className, children, config, ...props }, ref) => { - const uniqueId = React.useId(); - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`; +>(({ children, config = {}, className, ...props }, ref) => { + const chartId = React.useId(); return ( - <ChartContext.Provider value={{ config }}> + <ChartContext.Provider value={{ chartId }}> <div - data-chart={chartId} ref={ref} - className={cn( - "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none", - className, - )} + data-chart={chartId} + className={cn("w-full h-full", className)} {...props} > - <ChartStyle id={chartId} config={config} /> + <ChartThemeStyles + id={chartId} + colorConfig={Object.entries(config).filter( + ([_, config]) => config.theme || config.color, + )} + /> <RechartsPrimitive.ResponsiveContainer> {children} </RechartsPrimitive.ResponsiveContainer> @@ -67,289 +65,105 @@ const ChartContainer = React.forwardRef< }); ChartContainer.displayName = "Chart"; -const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { - const colorConfig = Object.entries(config).filter( - ([_, config]) => config.theme || config.color, - ); +// Add ChartThemeStylesProps type +type ChartThemeStylesProps = { + id: string; + colorConfig: [string, { theme?: Record<string, string>; color?: string }][]; +}; +const ChartThemeStyles = ({ id, colorConfig }: ChartThemeStylesProps) => { if (!colorConfig.length) { return null; } - return ( - <style - dangerouslySetInnerHTML={{ - __html: Object.entries(THEMES) - .map( - ([theme, prefix]) => ` + const styleContent = Object.entries(THEMES) + .map( + ([theme, prefix]) => ` ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { - const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || - itemConfig.color; + const color = itemConfig.theme?.[theme] || itemConfig.color; return color ? ` --color-${key}: ${color};` : null; }) + .filter(Boolean) .join("\n")} } `, - ) - .join("\n"), - }} - /> - ); -}; + ) + .join("\n"); -const ChartTooltip = RechartsPrimitive.Tooltip; + // Create a style element using useEffect to safely add styles + const styleRef = useRef<HTMLStyleElement | null>(null); -const ChartTooltipContent = React.forwardRef< - HTMLDivElement, - React.ComponentProps<typeof RechartsPrimitive.Tooltip> & - React.ComponentProps<"div"> & { - hideLabel?: boolean; - hideIndicator?: boolean; - indicator?: "line" | "dot" | "dashed"; - nameKey?: string; - labelKey?: string; + useEffect(() => { + // Create style element if it doesn't exist + if (!styleRef.current) { + styleRef.current = document.createElement("style"); + document.head.appendChild(styleRef.current); } ->( - ( - { - active, - payload, - className, - indicator = "dot", - hideLabel = false, - hideIndicator = false, - label, - labelFormatter, - labelClassName, - formatter, - color, - nameKey, - labelKey, - }, - ref, - ) => { - const { config } = useChart(); - - const tooltipLabel = React.useMemo(() => { - if (hideLabel || !payload?.length) { - return null; - } - const [item] = payload; - const key = `${labelKey || item.dataKey || item.name || "value"}`; - const itemConfig = getPayloadConfigFromPayload(config, item, key); - const value = - !labelKey && typeof label === "string" - ? config[label as keyof typeof config]?.label || label - : itemConfig?.label; + // Set the content + styleRef.current.textContent = styleContent; - if (labelFormatter) { - return ( - <div className={cn("font-medium", labelClassName)}> - {labelFormatter(value, payload)} - </div> - ); + // Cleanup on unmount + return () => { + if (styleRef.current) { + document.head.removeChild(styleRef.current); + styleRef.current = null; } + }; + }, [styleContent]); - if (!value) { - return null; - } - - return <div className={cn("font-medium", labelClassName)}>{value}</div>; - }, [ - label, - labelFormatter, - payload, - hideLabel, - labelClassName, - config, - labelKey, - ]); - - if (!active || !payload?.length) { - return null; - } + // Return empty fragment as we're managing the style element via useEffect + return <></>; +}; - const nestLabel = payload.length === 1 && indicator !== "dot"; +const ChartTooltip = RechartsPrimitive.Tooltip; - return ( - <div - ref={ref} - className={cn( - "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl", - className, - )} - > - {!nestLabel ? tooltipLabel : null} - <div className="grid gap-1.5"> - {payload.map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}`; - const itemConfig = getPayloadConfigFromPayload(config, item, key); - const indicatorColor = color || item.payload.fill || item.color; +const ChartTooltipContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes<HTMLDivElement> +>(({ className, ...props }, ref) => { + const { chartId } = useChart(); - return ( - <div - key={item.dataKey} - className={cn( - "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", - indicator === "dot" && "items-center", - )} - > - {formatter && item?.value !== undefined && item.name ? ( - formatter(item.value, item.name, item, index, item.payload) - ) : ( - <> - {itemConfig?.icon ? ( - <itemConfig.icon /> - ) : ( - !hideIndicator && ( - <div - className={cn( - "shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]", - { - "h-2.5 w-2.5": indicator === "dot", - "w-1": indicator === "line", - "w-0 border-[1.5px] border-dashed bg-transparent": - indicator === "dashed", - "my-0.5": nestLabel && indicator === "dashed", - }, - )} - style={ - { - "--color-bg": indicatorColor, - "--color-border": indicatorColor, - } as React.CSSProperties - } - /> - ) - )} - <div - className={cn( - "flex flex-1 justify-between leading-none", - nestLabel ? "items-end" : "items-center", - )} - > - <div className="grid gap-1.5"> - {nestLabel ? tooltipLabel : null} - <span className="text-muted-foreground"> - {itemConfig?.label || item.name} - </span> - </div> - {item.value && ( - <span className="font-mono font-medium tabular-nums text-foreground"> - {item.value.toLocaleString()} - </span> - )} - </div> - </> - )} - </div> - ); - })} - </div> - </div> - ); - }, -); -ChartTooltipContent.displayName = "ChartTooltip"; + return ( + <div + ref={ref} + data-chart={chartId} + className={cn( + "border bg-background p-2 shadow-md outline-none", + className, + )} + {...props} + /> + ); +}); +ChartTooltipContent.displayName = "ChartTooltipContent"; const ChartLegend = RechartsPrimitive.Legend; const ChartLegendContent = React.forwardRef< HTMLDivElement, - React.ComponentProps<"div"> & - Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & { - hideIcon?: boolean; - nameKey?: string; - } ->( - ( - { className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, - ref, - ) => { - const { config } = useChart(); - - if (!payload?.length) { - return null; - } + React.HTMLAttributes<HTMLDivElement> +>(({ className, ...props }, ref) => { + const { chartId } = useChart(); - return ( - <div - ref={ref} - className={cn( - "flex items-center justify-center gap-4", - verticalAlign === "top" ? "pb-3" : "pt-3", - className, - )} - > - {payload.map((item) => { - const key = `${nameKey || item.dataKey || "value"}`; - const itemConfig = getPayloadConfigFromPayload(config, item, key); - - return ( - <div - key={item.value} - className={cn( - "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground", - )} - > - {itemConfig?.icon && !hideIcon ? ( - <itemConfig.icon /> - ) : ( - <div - className="h-2 w-2 shrink-0 rounded-[2px]" - style={{ - backgroundColor: item.color, - }} - /> - )} - {itemConfig?.label} - </div> - ); - })} - </div> - ); - }, -); -ChartLegendContent.displayName = "ChartLegend"; + return ( + <div + ref={ref} + data-chart={chartId} + className={cn("my-2 flex flex-wrap items-center gap-4", className)} + {...props} + /> + ); +}); +ChartLegendContent.displayName = "ChartLegendContent"; -// Helper to extract item config from a payload. -function getPayloadConfigFromPayload( +function getConfigValue<T extends keyof ChartConfig>( config: ChartConfig, - payload: unknown, - key: string, + key: T, + configLabelKey?: string, ) { - if (typeof payload !== "object" || payload === null) { - return undefined; - } - - const payloadPayload = - "payload" in payload && - typeof payload.payload === "object" && - payload.payload !== null - ? payload.payload - : undefined; - - let configLabelKey: string = key; - - if ( - key in payload && - typeof payload[key as keyof typeof payload] === "string" - ) { - configLabelKey = payload[key as keyof typeof payload] as string; - } else if ( - payloadPayload && - key in payloadPayload && - typeof payloadPayload[key as keyof typeof payloadPayload] === "string" - ) { - configLabelKey = payloadPayload[ - key as keyof typeof payloadPayload - ] as string; - } - return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config]; @@ -361,5 +175,5 @@ export { ChartTooltipContent, ChartLegend, ChartLegendContent, - ChartStyle, + ChartThemeStyles, }; diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/use-toast.ts b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/use-toast.ts index 5e1fa80ed..d88d338b5 100644 --- a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/use-toast.ts +++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/use-toast.ts @@ -95,9 +95,8 @@ export const reducer = (state: State, action: Action): State => { if (toastId) { addToRemoveQueue(toastId); } else { - state.toasts.forEach((toast) => { - addToRemoveQueue(toast.id); - }); + // Use map instead of forEach + state.toasts.map((toast) => addToRemoveQueue(toast.id)); } return { @@ -132,9 +131,8 @@ let memoryState: State = { toasts: [] }; function dispatch(action: Action) { memoryState = reducer(memoryState, action); - listeners.forEach((listener) => { - listener(memoryState); - }); + // Use map instead of forEach + listeners.map((listener) => listener(memoryState)); } type Toast = Omit<ToasterToast, "id">; @@ -179,7 +177,7 @@ function useToast() { listeners.splice(index, 1); } }; - }, [state]); + }, []); // Remove state from dependencies return { ...state, diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/hooks/use-toast.ts b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/hooks/use-toast.ts index 5e1fa80ed..d88d338b5 100644 --- a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/hooks/use-toast.ts +++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/hooks/use-toast.ts @@ -95,9 +95,8 @@ export const reducer = (state: State, action: Action): State => { if (toastId) { addToRemoveQueue(toastId); } else { - state.toasts.forEach((toast) => { - addToRemoveQueue(toast.id); - }); + // Use map instead of forEach + state.toasts.map((toast) => addToRemoveQueue(toast.id)); } return { @@ -132,9 +131,8 @@ let memoryState: State = { toasts: [] }; function dispatch(action: Action) { memoryState = reducer(memoryState, action); - listeners.forEach((listener) => { - listener(memoryState); - }); + // Use map instead of forEach + listeners.map((listener) => listener(memoryState)); } type Toast = Omit<ToasterToast, "id">; @@ -179,7 +177,7 @@ function useToast() { listeners.splice(index, 1); } }; - }, [state]); + }, []); // Remove state from dependencies return { ...state,