From fe26ff8818fcd5473aae36ace2fc018696e5a9f6 Mon Sep 17 00:00:00 2001 From: Jay Hack Date: Mon, 3 Mar 2025 17:41:25 -0800 Subject: [PATCH 01/66] fix: slack event type for rich text (#727) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- src/codegen/extensions/slack/types.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/codegen/extensions/slack/types.py b/src/codegen/extensions/slack/types.py index 04d96e433..f5c27325e 100644 --- a/src/codegen/extensions/slack/types.py +++ b/src/codegen/extensions/slack/types.py @@ -7,15 +7,19 @@ class RichTextElement(BaseModel): type: str user_id: str | None = None text: str | None = None + style: dict | None = None + url: str | None = None + channel_id: str | None = None class RichTextSection(BaseModel): - type: Literal["rich_text_section"] + type: Literal["rich_text_section", "rich_text_list", "rich_text_quote", "rich_text_preformatted", "text", "channel", "user", "emoji", "link"] elements: list[RichTextElement] + style: dict | None = None class Block(BaseModel): - type: Literal["rich_text"] + type: Literal["rich_text", "section", "divider", "header", "context", "actions", "image"] block_id: str elements: list[RichTextSection] From 9c453a6fbd2f865a11e669b3ac6ae60e7c98b4c6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 4 Mar 2025 01:44:22 +0000 Subject: [PATCH 02/66] update changelog --- docs/changelog/changelog.mdx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 223a470cc..3705180a3 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,11 @@ icon: "clock" iconType: "solid" --- + +### [Fixes Slack event type handling for rich text.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.44.3) +- Fix Slack event type handling for rich text + + ### [Fixes and improvements to event handling and codebase.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.44.2) - Fix Slack event handling with thread-ts addition From d648646b6c5f9ad33009fb4ec9de4d910936cccf Mon Sep 17 00:00:00 2001 From: Jay Hack Date: Mon, 3 Mar 2025 18:08:07 -0800 Subject: [PATCH 03/66] fix: another slack schema error (#728) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- src/codegen/extensions/slack/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/extensions/slack/types.py b/src/codegen/extensions/slack/types.py index f5c27325e..a7203c526 100644 --- a/src/codegen/extensions/slack/types.py +++ b/src/codegen/extensions/slack/types.py @@ -15,7 +15,7 @@ class RichTextElement(BaseModel): class RichTextSection(BaseModel): type: Literal["rich_text_section", "rich_text_list", "rich_text_quote", "rich_text_preformatted", "text", "channel", "user", "emoji", "link"] elements: list[RichTextElement] - style: dict | None = None + style: dict | str | None = None # Can be either a dict for rich text styling or a string for list styles (e.g. "bullet") class Block(BaseModel): From 09b2a0822f59a1d7188d42279601c6c110784264 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 4 Mar 2025 02:11:30 +0000 Subject: [PATCH 04/66] update changelog --- docs/changelog/changelog.mdx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 3705180a3..2e614ffce 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,11 @@ icon: "clock" iconType: "solid" --- + +### [Fixes a Slack schema error.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.44.4) +- Fix Slack schema error + + ### [Fixes Slack event type handling for rich text.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.44.3) - Fix Slack event type handling for rich text From 007c49906123942a12d4da5b16a50d15d981d144 Mon Sep 17 00:00:00 2001 From: Jay Hack Date: Tue, 4 Mar 2025 08:31:16 -0800 Subject: [PATCH 05/66] docs: devin blog post (#730) --- docs/blog/devin.mdx | 92 ++++ docs/blog/posts.mdx | 16 +- docs/images/devin-edits-codemod.png | Bin 0 -> 686463 bytes docs/mint.json | 755 ++++++++++++++-------------- 4 files changed, 484 insertions(+), 379 deletions(-) create mode 100644 docs/blog/devin.mdx create mode 100644 docs/images/devin-edits-codemod.png diff --git a/docs/blog/devin.mdx b/docs/blog/devin.mdx new file mode 100644 index 000000000..c6c286117 --- /dev/null +++ b/docs/blog/devin.mdx @@ -0,0 +1,92 @@ +--- +title: "SWE Agents are Better with Codemods" +sidebarTitle: "Devin" +icon: "robot" +iconType: "solid" +--- + +Coding assistants like Cursor have introduced a new era of programming. But there's a class of programming tasks they can't handle: large-scale, systematic modifications across large codebases. You wouldn't ask an AI to delete all dead code or reorganize your entire component hierarchy - the tooling just isn't there. + +That's where codemods come in. A codemod is a program that operates on your codebase, and when you give an AI agent the ability to write and execute them, these tasks fall below the high-water mark of AI capabilities. + +Here's a real example: we asked [Devin](https://docs.devin.ai/get-started/devin-intro) (an autonomous SWE agent) to "delete all dead code" from our codebase. Instead of trying to make hundreds of individual edits, Devin [wrote and debugged a program](https://github.com/codegen-sh/codegen/pull/660/files#diff-199b0c459adf1639f664fed248fa48bb640412aeacbe61cd89475d6598284b5f) that systematically removed unused code while handling edge cases like tests, decorators and indirect references. + +- [View the PR](https://github.com/codegen-sh/codegen/pull/660) +- [View on Devin](app.devin.ai/sessions/a49eac87da644fa9ac1144fe130b847e) + + + + + +This modifies over 40 files and correctly removes old code, passes lint + tests, etc. + +What made this work? + +Devin operates like a state machine: write a codemod, run it through the linter, analyze failures, and refine. Each iteration adds handling for new edge cases until the codemod successfully transforms the entire codebase. This is the same cycle developers use for many large-scale refactors, just automated. + +```mermaid +flowchart LR + style EditRun fill:#ff6b6b,stroke:#000,stroke-width:3px,color:#000,font-weight:bold,font-size:16px + style Linter fill:#4dabf7,stroke:#000,stroke-width:3px,color:#000,font-weight:bold,font-size:16px + style Success fill:#cc5de8,stroke:#000,stroke-width:3px,color:#000,font-weight:bold,font-size:16px + + EditRun["Edit + Run
Codemod"] --> Linter["Run
Linter"] + Linter --"success?"--- Success["Success"] + Linter --"errors found"--- EditRun + + linkStyle default stroke-width:2px + classDef edgeLabel fill:#e9ecef,color:#000,font-weight:bold + class success?,errors edgeLabel +``` + +The nice part about this approach is that we don't have to blindly trust the AI. There's no magic - it's just a program we can run and verify through linter/test output. The codemod is easy to review, and we can update it if we need to add exceptions or edge cases. Much better than trying to manually review hundreds of individual edits. + +## Try it yourself + +Want to experience this with your own Devin instance? Install the Codegen CLI in your Devin box: + +```bash +uv tool install codegen --python 3.13 +``` + +Then use the following prompt: + + + Download System Prompt + + +Or try it with other platform-level modifications supported by Codegen: + + + + Automatically convert Promise chains to async/await syntax across your codebase. + + + Move and organize code safely with automatic import and dependency handling. + + + Convert class components to hooks, standardize props, and organize components. + + + Automatically convert unittest test suites to modern pytest style. + + + +We'd love to hear how it works for you! Let us know in our [community](https://community.codegen.com) and share other tasks that it is helpful in performing. \ No newline at end of file diff --git a/docs/blog/posts.mdx b/docs/blog/posts.mdx index 2d1b27ed1..ad92465be 100644 --- a/docs/blog/posts.mdx +++ b/docs/blog/posts.mdx @@ -4,7 +4,21 @@ icon: "clock" iconType: "solid" --- - + + +## Agents are Better with Codemods + +How AI agents like Devin can use codemods to safely make systematic changes across entire codebases, from deleting dead code to modernizing React components. + + + + + + ## Act via Code diff --git a/docs/images/devin-edits-codemod.png b/docs/images/devin-edits-codemod.png new file mode 100644 index 0000000000000000000000000000000000000000..3349b95891b887baa430c7e5511936399500d338 GIT binary patch literal 686463 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�D9ySs#CEUQ=2TDj8$3H8%bdnr9WB>2Lr9sL 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 TCXQ_bziwXB{59vw?STIUo4Pt) literal 0 HcmV?d00001 diff --git a/docs/mint.json b/docs/mint.json index d5062557c..0afb81e64 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -1,379 +1,378 @@ { - "$schema": "https://mintlify.com/schema.json", - "name": "Codegen", - "logo": { - "dark": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45a3e32761c42b324b_Codegen_Logomark_Dark.svg", - "light": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45bf55446746125835_Codegen_Logomark_Light.svg" - }, - "modeToggle": { - "default": "dark" - }, - "metadata": { - "og:site_name": "Codegen", - "og:title": "Codegen - Manipulate Code at Scale", - "og:description": "A scriptable interface to a powerful, multi-lingual language server built on top of Tree-sitter.", - "og:url": "https://docs.codegen.com", - "og:locale": "en_US", - "og:logo": "https://i.imgur.com/f4OVOqI.png", - "article:publisher": "Codegen, Inc.", - "twitter:site": "@codegen" - }, - "favicon": "/favicon.svg", - "colors": { - "primary": "#a277ff", - "light": "#a277ff", - "dark": "#a277ff", - "anchors": { - "from": "#61ffca", - "to": "#61ffca" - } - }, - "theme": "prism", - "background": { - "style": "gradient" - }, - "analytics": { - "posthog": { - "apiKey": "phc_GLxaINoQJnuyCyxDmTciQqzdKBYFVDkY7bRBO4bDdso" - } - }, - "feedback": { - "thumbsRating": true - }, - "topbarCtaButton": { - "name": "GitHub", - "url": "https://github.com/codegen-sh/codegen-sdk" - }, - "tabs": [ - { - "name": "API Reference", - "url": "/api-reference" - }, - { - "name": "CLI", - "url": "/cli" - }, - { - "name": "Blog", - "url": "/blog" - }, - { - "name": "Changelog", - "url": "/changelog" - } - ], - "navigation": [ - { - "group": "Introduction", - "pages": [ - "introduction/overview", - "introduction/getting-started", - "introduction/installation", - "introduction/ide-usage", - "introduction/work-with-ai", - "introduction/how-it-works", - "introduction/guiding-principles", - "introduction/community", - "introduction/about", - "introduction/faq" - ] - }, - { - "group": "Tutorials", - "pages": [ - "tutorials/at-a-glance", - "tutorials/build-code-agent", - "tutorials/slack-bot", - "tutorials/github-review-bot", - "tutorials/deep-code-research", - "tutorials/training-data", - "tutorials/codebase-visualization", - "tutorials/migrating-apis", - "tutorials/organize-your-codebase", - "tutorials/promise-to-async-await", - "tutorials/modularity", - "tutorials/manage-feature-flags", - "tutorials/deleting-dead-code", - "tutorials/increase-type-coverage", - "tutorials/managing-typescript-exports", - "tutorials/converting-default-exports", - "tutorials/creating-documentation", - "tutorials/react-modernization", - "tutorials/unittest-to-pytest", - "tutorials/sqlalchemy-1.6-to-2.0", - "tutorials/fixing-import-loops-in-pytorch", - "tutorials/python2-to-python3", - "tutorials/flask-to-fastapi", - "tutorials/build-mcp", - "tutorials/neo4j-graph" - ] - }, - { - "group": "Building with Codegen", - "pages": [ - "building-with-codegen/at-a-glance", - "building-with-codegen/parsing-codebases", - "building-with-codegen/reusable-codemods", - "building-with-codegen/dot-codegen", - "building-with-codegen/function-decorator", - "building-with-codegen/language-support", - "building-with-codegen/commit-and-reset", - "building-with-codegen/git-operations", - "building-with-codegen/files-and-directories", - "building-with-codegen/the-editable-api", - "building-with-codegen/symbol-api", - "building-with-codegen/class-api", - "building-with-codegen/imports", - "building-with-codegen/exports", - "building-with-codegen/inheritable-behaviors", - "building-with-codegen/statements-and-code-blocks", - "building-with-codegen/dependencies-and-usages", - "building-with-codegen/function-calls-and-callsites", - "building-with-codegen/variable-assignments", - "building-with-codegen/local-variables", - "building-with-codegen/comments-and-docstrings", - "building-with-codegen/external-modules", - "building-with-codegen/type-annotations", - "building-with-codegen/moving-symbols", - "building-with-codegen/collections", - "building-with-codegen/traversing-the-call-graph", - "building-with-codegen/react-and-jsx", - "building-with-codegen/codebase-visualization", - "building-with-codegen/flagging-symbols", - "building-with-codegen/calling-out-to-llms", - "building-with-codegen/semantic-code-search", - "building-with-codegen/reducing-conditions" - ] - }, - { - "group": "CLI", - "pages": [ - "cli/about", - "cli/init", - "cli/notebook", - "cli/create", - "cli/run", - "cli/reset", - "cli/expert" - ] - }, - { - "group": "Changelog", - "pages": [ - "changelog/changelog" - ] - }, - { - "group": "Blog", - "pages": [ - "blog/posts", - "blog/act-via-code", - "blog/promise-to-async-await-twilio", - "blog/fixing-import-loops" - ] - }, - { - "group": "API Reference", - "pages": [ - "api-reference/index", - { - "group": "Core", - "icon": "code", - "pages": [ - "api-reference/core/Argument", - "api-reference/core/Assignment", - "api-reference/core/AssignmentStatement", - "api-reference/core/Attribute", - "api-reference/core/AwaitExpression", - "api-reference/core/BinaryExpression", - "api-reference/core/BlockStatement", - "api-reference/core/Boolean", - "api-reference/core/Callable", - "api-reference/core/CatchStatement", - "api-reference/core/ChainedAttribute", - "api-reference/core/Class", - "api-reference/core/CodeBlock", - "api-reference/core/CodeOwner", - "api-reference/core/Codebase", - "api-reference/core/Comment", - "api-reference/core/CommentGroup", - "api-reference/core/ComparisonExpression", - "api-reference/core/Decorator", - "api-reference/core/Dict", - "api-reference/core/Directory", - "api-reference/core/Editable", - "api-reference/core/Export", - "api-reference/core/ExportStatement", - "api-reference/core/Exportable", - "api-reference/core/Expression", - "api-reference/core/ExpressionGroup", - "api-reference/core/ExpressionStatement", - "api-reference/core/ExternalModule", - "api-reference/core/File", - "api-reference/core/FlagKwargs", - "api-reference/core/ForLoopStatement", - "api-reference/core/Function", - "api-reference/core/FunctionCall", - "api-reference/core/GenericType", - "api-reference/core/HasBlock", - "api-reference/core/HasName", - "api-reference/core/HasValue", - "api-reference/core/IfBlockStatement", - "api-reference/core/Import", - "api-reference/core/ImportStatement", - "api-reference/core/ImportType", - "api-reference/core/Importable", - "api-reference/core/Interface", - "api-reference/core/List", - "api-reference/core/MessageType", - "api-reference/core/MultiExpression", - "api-reference/core/MultiLineCollection", - "api-reference/core/Name", - "api-reference/core/NamedType", - "api-reference/core/NoneType", - "api-reference/core/Number", - "api-reference/core/Pair", - "api-reference/core/Parameter", - "api-reference/core/ParenthesizedExpression", - "api-reference/core/Placeholder", - "api-reference/core/PlaceholderType", - "api-reference/core/RaiseStatement", - "api-reference/core/ReturnStatement", - "api-reference/core/SourceFile", - "api-reference/core/Span", - "api-reference/core/Statement", - "api-reference/core/StatementType", - "api-reference/core/String", - "api-reference/core/StubPlaceholder", - "api-reference/core/SubscriptExpression", - "api-reference/core/SwitchCase", - "api-reference/core/SwitchStatement", - "api-reference/core/Symbol", - "api-reference/core/SymbolGroup", - "api-reference/core/SymbolStatement", - "api-reference/core/TernaryExpression", - "api-reference/core/TryCatchStatement", - "api-reference/core/Tuple", - "api-reference/core/TupleType", - "api-reference/core/Type", - "api-reference/core/TypeAlias", - "api-reference/core/TypePlaceholder", - "api-reference/core/Typeable", - "api-reference/core/UnaryExpression", - "api-reference/core/UnionType", - "api-reference/core/Unpack", - "api-reference/core/Unwrappable", - "api-reference/core/Usable", - "api-reference/core/Usage", - "api-reference/core/UsageKind", - "api-reference/core/UsageType", - "api-reference/core/Value", - "api-reference/core/WhileStatement", - "api-reference/core/WithStatement" - ] - }, - { - "group": "Python", - "icon": "python", - "pages": [ - "api-reference/python/PyAssignment", - "api-reference/python/PyAssignmentStatement", - "api-reference/python/PyAttribute", - "api-reference/python/PyBlockStatement", - "api-reference/python/PyBreakStatement", - "api-reference/python/PyCatchStatement", - "api-reference/python/PyChainedAttribute", - "api-reference/python/PyClass", - "api-reference/python/PyCodeBlock", - "api-reference/python/PyComment", - "api-reference/python/PyCommentGroup", - "api-reference/python/PyCommentType", - "api-reference/python/PyConditionalExpression", - "api-reference/python/PyDecorator", - "api-reference/python/PyFile", - "api-reference/python/PyForLoopStatement", - "api-reference/python/PyFunction", - "api-reference/python/PyGenericType", - "api-reference/python/PyHasBlock", - "api-reference/python/PyIfBlockStatement", - "api-reference/python/PyImport", - "api-reference/python/PyImportStatement", - "api-reference/python/PyMatchCase", - "api-reference/python/PyMatchStatement", - "api-reference/python/PyNamedType", - "api-reference/python/PyParameter", - "api-reference/python/PyPassStatement", - "api-reference/python/PyReturnTypePlaceholder", - "api-reference/python/PyString", - "api-reference/python/PySymbol", - "api-reference/python/PyTryCatchStatement", - "api-reference/python/PyUnionType", - "api-reference/python/PyWhileStatement" - ] - }, - { - "group": "Typescript", - "icon": "js", - "pages": [ - "api-reference/typescript/JSXElement", - "api-reference/typescript/JSXExpression", - "api-reference/typescript/JSXProp", - "api-reference/typescript/TSArrayType", - "api-reference/typescript/TSAssignment", - "api-reference/typescript/TSAssignmentStatement", - "api-reference/typescript/TSAttribute", - "api-reference/typescript/TSBlockStatement", - "api-reference/typescript/TSCatchStatement", - "api-reference/typescript/TSChainedAttribute", - "api-reference/typescript/TSClass", - "api-reference/typescript/TSCodeBlock", - "api-reference/typescript/TSComment", - "api-reference/typescript/TSCommentGroup", - "api-reference/typescript/TSCommentType", - "api-reference/typescript/TSConditionalType", - "api-reference/typescript/TSConfig", - "api-reference/typescript/TSDecorator", - "api-reference/typescript/TSDict", - "api-reference/typescript/TSEnum", - "api-reference/typescript/TSExport", - "api-reference/typescript/TSExpressionType", - "api-reference/typescript/TSFile", - "api-reference/typescript/TSForLoopStatement", - "api-reference/typescript/TSFunction", - "api-reference/typescript/TSFunctionType", - "api-reference/typescript/TSGenericType", - "api-reference/typescript/TSHasBlock", - "api-reference/typescript/TSIfBlockStatement", - "api-reference/typescript/TSImport", - "api-reference/typescript/TSImportStatement", - "api-reference/typescript/TSInterface", - "api-reference/typescript/TSLabeledStatement", - "api-reference/typescript/TSLookupType", - "api-reference/typescript/TSNamedType", - "api-reference/typescript/TSNamespace", - "api-reference/typescript/TSObjectType", - "api-reference/typescript/TSPair", - "api-reference/typescript/TSParameter", - "api-reference/typescript/TSQueryType", - "api-reference/typescript/TSReadonlyType", - "api-reference/typescript/TSReturnTypePlaceholder", - "api-reference/typescript/TSString", - "api-reference/typescript/TSSwitchCase", - "api-reference/typescript/TSSwitchStatement", - "api-reference/typescript/TSSymbol", - "api-reference/typescript/TSTernaryExpression", - "api-reference/typescript/TSTryCatchStatement", - "api-reference/typescript/TSTypeAlias", - "api-reference/typescript/TSUndefinedType", - "api-reference/typescript/TSUnionType", - "api-reference/typescript/TSWhileStatement" - ] - } - ] - } - ], - "footerSocials": { - "x": "https://x.com/codegen", - "linkedin": "https://linkedin.com/company/codegen-dot-com" - } -} \ No newline at end of file + "$schema": "https://mintlify.com/schema.json", + "name": "Codegen", + "logo": { + "dark": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45a3e32761c42b324b_Codegen_Logomark_Dark.svg", + "light": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45bf55446746125835_Codegen_Logomark_Light.svg" + }, + "modeToggle": { + "default": "dark" + }, + "metadata": { + "og:site_name": "Codegen", + "og:title": "Codegen - Manipulate Code at Scale", + "og:description": "A scriptable interface to a powerful, multi-lingual language server built on top of Tree-sitter.", + "og:url": "https://docs.codegen.com", + "og:locale": "en_US", + "og:logo": "https://i.imgur.com/f4OVOqI.png", + "article:publisher": "Codegen, Inc.", + "twitter:site": "@codegen" + }, + "favicon": "/favicon.svg", + "colors": { + "primary": "#a277ff", + "light": "#a277ff", + "dark": "#a277ff", + "anchors": { + "from": "#61ffca", + "to": "#61ffca" + } + }, + "theme": "prism", + "background": { + "style": "gradient" + }, + "analytics": { + "posthog": { + "apiKey": "phc_GLxaINoQJnuyCyxDmTciQqzdKBYFVDkY7bRBO4bDdso" + } + }, + "feedback": { + "thumbsRating": true + }, + "topbarCtaButton": { + "name": "GitHub", + "url": "https://github.com/codegen-sh/codegen-sdk" + }, + "tabs": [ + { + "name": "API Reference", + "url": "/api-reference" + }, + { + "name": "CLI", + "url": "/cli" + }, + { + "name": "Blog", + "url": "/blog" + }, + { + "name": "Changelog", + "url": "/changelog" + } + ], + "navigation": [ + { + "group": "Introduction", + "pages": [ + "introduction/overview", + "introduction/getting-started", + "introduction/installation", + "introduction/ide-usage", + "introduction/work-with-ai", + "introduction/how-it-works", + "introduction/guiding-principles", + "introduction/community", + "introduction/about", + "introduction/faq" + ] + }, + { + "group": "Tutorials", + "pages": [ + "tutorials/at-a-glance", + "tutorials/build-code-agent", + "tutorials/slack-bot", + "tutorials/github-review-bot", + "tutorials/deep-code-research", + "tutorials/training-data", + "tutorials/codebase-visualization", + "tutorials/migrating-apis", + "tutorials/organize-your-codebase", + "tutorials/promise-to-async-await", + "tutorials/modularity", + "tutorials/manage-feature-flags", + "tutorials/deleting-dead-code", + "tutorials/increase-type-coverage", + "tutorials/managing-typescript-exports", + "tutorials/converting-default-exports", + "tutorials/creating-documentation", + "tutorials/react-modernization", + "tutorials/unittest-to-pytest", + "tutorials/sqlalchemy-1.6-to-2.0", + "tutorials/fixing-import-loops-in-pytorch", + "tutorials/python2-to-python3", + "tutorials/flask-to-fastapi", + "tutorials/build-mcp", + "tutorials/neo4j-graph" + ] + }, + { + "group": "Building with Codegen", + "pages": [ + "building-with-codegen/at-a-glance", + "building-with-codegen/parsing-codebases", + "building-with-codegen/reusable-codemods", + "building-with-codegen/dot-codegen", + "building-with-codegen/function-decorator", + "building-with-codegen/language-support", + "building-with-codegen/commit-and-reset", + "building-with-codegen/git-operations", + "building-with-codegen/files-and-directories", + "building-with-codegen/the-editable-api", + "building-with-codegen/symbol-api", + "building-with-codegen/class-api", + "building-with-codegen/imports", + "building-with-codegen/exports", + "building-with-codegen/inheritable-behaviors", + "building-with-codegen/statements-and-code-blocks", + "building-with-codegen/dependencies-and-usages", + "building-with-codegen/function-calls-and-callsites", + "building-with-codegen/variable-assignments", + "building-with-codegen/local-variables", + "building-with-codegen/comments-and-docstrings", + "building-with-codegen/external-modules", + "building-with-codegen/type-annotations", + "building-with-codegen/moving-symbols", + "building-with-codegen/collections", + "building-with-codegen/traversing-the-call-graph", + "building-with-codegen/react-and-jsx", + "building-with-codegen/codebase-visualization", + "building-with-codegen/flagging-symbols", + "building-with-codegen/calling-out-to-llms", + "building-with-codegen/semantic-code-search", + "building-with-codegen/reducing-conditions" + ] + }, + { + "group": "CLI", + "pages": [ + "cli/about", + "cli/init", + "cli/notebook", + "cli/create", + "cli/run", + "cli/reset", + "cli/expert" + ] + }, + { + "group": "Changelog", + "pages": ["changelog/changelog"] + }, + { + "group": "Blog", + "pages": [ + "blog/posts", + "blog/devin", + "blog/act-via-code", + "blog/promise-to-async-await-twilio", + "blog/fixing-import-loops" + ] + }, + { + "group": "API Reference", + "pages": [ + "api-reference/index", + { + "group": "Core", + "icon": "code", + "pages": [ + "api-reference/core/Argument", + "api-reference/core/Assignment", + "api-reference/core/AssignmentStatement", + "api-reference/core/Attribute", + "api-reference/core/AwaitExpression", + "api-reference/core/BinaryExpression", + "api-reference/core/BlockStatement", + "api-reference/core/Boolean", + "api-reference/core/Callable", + "api-reference/core/CatchStatement", + "api-reference/core/ChainedAttribute", + "api-reference/core/Class", + "api-reference/core/CodeBlock", + "api-reference/core/CodeOwner", + "api-reference/core/Codebase", + "api-reference/core/Comment", + "api-reference/core/CommentGroup", + "api-reference/core/ComparisonExpression", + "api-reference/core/Decorator", + "api-reference/core/Dict", + "api-reference/core/Directory", + "api-reference/core/Editable", + "api-reference/core/Export", + "api-reference/core/ExportStatement", + "api-reference/core/Exportable", + "api-reference/core/Expression", + "api-reference/core/ExpressionGroup", + "api-reference/core/ExpressionStatement", + "api-reference/core/ExternalModule", + "api-reference/core/File", + "api-reference/core/FlagKwargs", + "api-reference/core/ForLoopStatement", + "api-reference/core/Function", + "api-reference/core/FunctionCall", + "api-reference/core/GenericType", + "api-reference/core/HasBlock", + "api-reference/core/HasName", + "api-reference/core/HasValue", + "api-reference/core/IfBlockStatement", + "api-reference/core/Import", + "api-reference/core/ImportStatement", + "api-reference/core/ImportType", + "api-reference/core/Importable", + "api-reference/core/Interface", + "api-reference/core/List", + "api-reference/core/MessageType", + "api-reference/core/MultiExpression", + "api-reference/core/MultiLineCollection", + "api-reference/core/Name", + "api-reference/core/NamedType", + "api-reference/core/NoneType", + "api-reference/core/Number", + "api-reference/core/Pair", + "api-reference/core/Parameter", + "api-reference/core/ParenthesizedExpression", + "api-reference/core/Placeholder", + "api-reference/core/PlaceholderType", + "api-reference/core/RaiseStatement", + "api-reference/core/ReturnStatement", + "api-reference/core/SourceFile", + "api-reference/core/Span", + "api-reference/core/Statement", + "api-reference/core/StatementType", + "api-reference/core/String", + "api-reference/core/StubPlaceholder", + "api-reference/core/SubscriptExpression", + "api-reference/core/SwitchCase", + "api-reference/core/SwitchStatement", + "api-reference/core/Symbol", + "api-reference/core/SymbolGroup", + "api-reference/core/SymbolStatement", + "api-reference/core/TernaryExpression", + "api-reference/core/TryCatchStatement", + "api-reference/core/Tuple", + "api-reference/core/TupleType", + "api-reference/core/Type", + "api-reference/core/TypeAlias", + "api-reference/core/TypePlaceholder", + "api-reference/core/Typeable", + "api-reference/core/UnaryExpression", + "api-reference/core/UnionType", + "api-reference/core/Unpack", + "api-reference/core/Unwrappable", + "api-reference/core/Usable", + "api-reference/core/Usage", + "api-reference/core/UsageKind", + "api-reference/core/UsageType", + "api-reference/core/Value", + "api-reference/core/WhileStatement", + "api-reference/core/WithStatement" + ] + }, + { + "group": "Python", + "icon": "python", + "pages": [ + "api-reference/python/PyAssignment", + "api-reference/python/PyAssignmentStatement", + "api-reference/python/PyAttribute", + "api-reference/python/PyBlockStatement", + "api-reference/python/PyBreakStatement", + "api-reference/python/PyCatchStatement", + "api-reference/python/PyChainedAttribute", + "api-reference/python/PyClass", + "api-reference/python/PyCodeBlock", + "api-reference/python/PyComment", + "api-reference/python/PyCommentGroup", + "api-reference/python/PyCommentType", + "api-reference/python/PyConditionalExpression", + "api-reference/python/PyDecorator", + "api-reference/python/PyFile", + "api-reference/python/PyForLoopStatement", + "api-reference/python/PyFunction", + "api-reference/python/PyGenericType", + "api-reference/python/PyHasBlock", + "api-reference/python/PyIfBlockStatement", + "api-reference/python/PyImport", + "api-reference/python/PyImportStatement", + "api-reference/python/PyMatchCase", + "api-reference/python/PyMatchStatement", + "api-reference/python/PyNamedType", + "api-reference/python/PyParameter", + "api-reference/python/PyPassStatement", + "api-reference/python/PyReturnTypePlaceholder", + "api-reference/python/PyString", + "api-reference/python/PySymbol", + "api-reference/python/PyTryCatchStatement", + "api-reference/python/PyUnionType", + "api-reference/python/PyWhileStatement" + ] + }, + { + "group": "Typescript", + "icon": "js", + "pages": [ + "api-reference/typescript/JSXElement", + "api-reference/typescript/JSXExpression", + "api-reference/typescript/JSXProp", + "api-reference/typescript/TSArrayType", + "api-reference/typescript/TSAssignment", + "api-reference/typescript/TSAssignmentStatement", + "api-reference/typescript/TSAttribute", + "api-reference/typescript/TSBlockStatement", + "api-reference/typescript/TSCatchStatement", + "api-reference/typescript/TSChainedAttribute", + "api-reference/typescript/TSClass", + "api-reference/typescript/TSCodeBlock", + "api-reference/typescript/TSComment", + "api-reference/typescript/TSCommentGroup", + "api-reference/typescript/TSCommentType", + "api-reference/typescript/TSConditionalType", + "api-reference/typescript/TSConfig", + "api-reference/typescript/TSDecorator", + "api-reference/typescript/TSDict", + "api-reference/typescript/TSEnum", + "api-reference/typescript/TSExport", + "api-reference/typescript/TSExpressionType", + "api-reference/typescript/TSFile", + "api-reference/typescript/TSForLoopStatement", + "api-reference/typescript/TSFunction", + "api-reference/typescript/TSFunctionType", + "api-reference/typescript/TSGenericType", + "api-reference/typescript/TSHasBlock", + "api-reference/typescript/TSIfBlockStatement", + "api-reference/typescript/TSImport", + "api-reference/typescript/TSImportStatement", + "api-reference/typescript/TSInterface", + "api-reference/typescript/TSLabeledStatement", + "api-reference/typescript/TSLookupType", + "api-reference/typescript/TSNamedType", + "api-reference/typescript/TSNamespace", + "api-reference/typescript/TSObjectType", + "api-reference/typescript/TSPair", + "api-reference/typescript/TSParameter", + "api-reference/typescript/TSQueryType", + "api-reference/typescript/TSReadonlyType", + "api-reference/typescript/TSReturnTypePlaceholder", + "api-reference/typescript/TSString", + "api-reference/typescript/TSSwitchCase", + "api-reference/typescript/TSSwitchStatement", + "api-reference/typescript/TSSymbol", + "api-reference/typescript/TSTernaryExpression", + "api-reference/typescript/TSTryCatchStatement", + "api-reference/typescript/TSTypeAlias", + "api-reference/typescript/TSUndefinedType", + "api-reference/typescript/TSUnionType", + "api-reference/typescript/TSWhileStatement" + ] + } + ] + } + ], + "footerSocials": { + "x": "https://x.com/codegen", + "linkedin": "https://linkedin.com/company/codegen-dot-com" + } +} From a4994ee193e94667c0897251147f27e59653672a Mon Sep 17 00:00:00 2001 From: codegen-team Date: Tue, 4 Mar 2025 16:33:08 +0000 Subject: [PATCH 06/66] docs: updated API reference --- docs/mint.json | 756 +++++++++++++++++++++++++------------------------ 1 file changed, 379 insertions(+), 377 deletions(-) diff --git a/docs/mint.json b/docs/mint.json index 0afb81e64..d0bb0c07b 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -1,378 +1,380 @@ { - "$schema": "https://mintlify.com/schema.json", - "name": "Codegen", - "logo": { - "dark": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45a3e32761c42b324b_Codegen_Logomark_Dark.svg", - "light": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45bf55446746125835_Codegen_Logomark_Light.svg" - }, - "modeToggle": { - "default": "dark" - }, - "metadata": { - "og:site_name": "Codegen", - "og:title": "Codegen - Manipulate Code at Scale", - "og:description": "A scriptable interface to a powerful, multi-lingual language server built on top of Tree-sitter.", - "og:url": "https://docs.codegen.com", - "og:locale": "en_US", - "og:logo": "https://i.imgur.com/f4OVOqI.png", - "article:publisher": "Codegen, Inc.", - "twitter:site": "@codegen" - }, - "favicon": "/favicon.svg", - "colors": { - "primary": "#a277ff", - "light": "#a277ff", - "dark": "#a277ff", - "anchors": { - "from": "#61ffca", - "to": "#61ffca" - } - }, - "theme": "prism", - "background": { - "style": "gradient" - }, - "analytics": { - "posthog": { - "apiKey": "phc_GLxaINoQJnuyCyxDmTciQqzdKBYFVDkY7bRBO4bDdso" - } - }, - "feedback": { - "thumbsRating": true - }, - "topbarCtaButton": { - "name": "GitHub", - "url": "https://github.com/codegen-sh/codegen-sdk" - }, - "tabs": [ - { - "name": "API Reference", - "url": "/api-reference" - }, - { - "name": "CLI", - "url": "/cli" - }, - { - "name": "Blog", - "url": "/blog" - }, - { - "name": "Changelog", - "url": "/changelog" - } - ], - "navigation": [ - { - "group": "Introduction", - "pages": [ - "introduction/overview", - "introduction/getting-started", - "introduction/installation", - "introduction/ide-usage", - "introduction/work-with-ai", - "introduction/how-it-works", - "introduction/guiding-principles", - "introduction/community", - "introduction/about", - "introduction/faq" - ] - }, - { - "group": "Tutorials", - "pages": [ - "tutorials/at-a-glance", - "tutorials/build-code-agent", - "tutorials/slack-bot", - "tutorials/github-review-bot", - "tutorials/deep-code-research", - "tutorials/training-data", - "tutorials/codebase-visualization", - "tutorials/migrating-apis", - "tutorials/organize-your-codebase", - "tutorials/promise-to-async-await", - "tutorials/modularity", - "tutorials/manage-feature-flags", - "tutorials/deleting-dead-code", - "tutorials/increase-type-coverage", - "tutorials/managing-typescript-exports", - "tutorials/converting-default-exports", - "tutorials/creating-documentation", - "tutorials/react-modernization", - "tutorials/unittest-to-pytest", - "tutorials/sqlalchemy-1.6-to-2.0", - "tutorials/fixing-import-loops-in-pytorch", - "tutorials/python2-to-python3", - "tutorials/flask-to-fastapi", - "tutorials/build-mcp", - "tutorials/neo4j-graph" - ] - }, - { - "group": "Building with Codegen", - "pages": [ - "building-with-codegen/at-a-glance", - "building-with-codegen/parsing-codebases", - "building-with-codegen/reusable-codemods", - "building-with-codegen/dot-codegen", - "building-with-codegen/function-decorator", - "building-with-codegen/language-support", - "building-with-codegen/commit-and-reset", - "building-with-codegen/git-operations", - "building-with-codegen/files-and-directories", - "building-with-codegen/the-editable-api", - "building-with-codegen/symbol-api", - "building-with-codegen/class-api", - "building-with-codegen/imports", - "building-with-codegen/exports", - "building-with-codegen/inheritable-behaviors", - "building-with-codegen/statements-and-code-blocks", - "building-with-codegen/dependencies-and-usages", - "building-with-codegen/function-calls-and-callsites", - "building-with-codegen/variable-assignments", - "building-with-codegen/local-variables", - "building-with-codegen/comments-and-docstrings", - "building-with-codegen/external-modules", - "building-with-codegen/type-annotations", - "building-with-codegen/moving-symbols", - "building-with-codegen/collections", - "building-with-codegen/traversing-the-call-graph", - "building-with-codegen/react-and-jsx", - "building-with-codegen/codebase-visualization", - "building-with-codegen/flagging-symbols", - "building-with-codegen/calling-out-to-llms", - "building-with-codegen/semantic-code-search", - "building-with-codegen/reducing-conditions" - ] - }, - { - "group": "CLI", - "pages": [ - "cli/about", - "cli/init", - "cli/notebook", - "cli/create", - "cli/run", - "cli/reset", - "cli/expert" - ] - }, - { - "group": "Changelog", - "pages": ["changelog/changelog"] - }, - { - "group": "Blog", - "pages": [ - "blog/posts", - "blog/devin", - "blog/act-via-code", - "blog/promise-to-async-await-twilio", - "blog/fixing-import-loops" - ] - }, - { - "group": "API Reference", - "pages": [ - "api-reference/index", - { - "group": "Core", - "icon": "code", - "pages": [ - "api-reference/core/Argument", - "api-reference/core/Assignment", - "api-reference/core/AssignmentStatement", - "api-reference/core/Attribute", - "api-reference/core/AwaitExpression", - "api-reference/core/BinaryExpression", - "api-reference/core/BlockStatement", - "api-reference/core/Boolean", - "api-reference/core/Callable", - "api-reference/core/CatchStatement", - "api-reference/core/ChainedAttribute", - "api-reference/core/Class", - "api-reference/core/CodeBlock", - "api-reference/core/CodeOwner", - "api-reference/core/Codebase", - "api-reference/core/Comment", - "api-reference/core/CommentGroup", - "api-reference/core/ComparisonExpression", - "api-reference/core/Decorator", - "api-reference/core/Dict", - "api-reference/core/Directory", - "api-reference/core/Editable", - "api-reference/core/Export", - "api-reference/core/ExportStatement", - "api-reference/core/Exportable", - "api-reference/core/Expression", - "api-reference/core/ExpressionGroup", - "api-reference/core/ExpressionStatement", - "api-reference/core/ExternalModule", - "api-reference/core/File", - "api-reference/core/FlagKwargs", - "api-reference/core/ForLoopStatement", - "api-reference/core/Function", - "api-reference/core/FunctionCall", - "api-reference/core/GenericType", - "api-reference/core/HasBlock", - "api-reference/core/HasName", - "api-reference/core/HasValue", - "api-reference/core/IfBlockStatement", - "api-reference/core/Import", - "api-reference/core/ImportStatement", - "api-reference/core/ImportType", - "api-reference/core/Importable", - "api-reference/core/Interface", - "api-reference/core/List", - "api-reference/core/MessageType", - "api-reference/core/MultiExpression", - "api-reference/core/MultiLineCollection", - "api-reference/core/Name", - "api-reference/core/NamedType", - "api-reference/core/NoneType", - "api-reference/core/Number", - "api-reference/core/Pair", - "api-reference/core/Parameter", - "api-reference/core/ParenthesizedExpression", - "api-reference/core/Placeholder", - "api-reference/core/PlaceholderType", - "api-reference/core/RaiseStatement", - "api-reference/core/ReturnStatement", - "api-reference/core/SourceFile", - "api-reference/core/Span", - "api-reference/core/Statement", - "api-reference/core/StatementType", - "api-reference/core/String", - "api-reference/core/StubPlaceholder", - "api-reference/core/SubscriptExpression", - "api-reference/core/SwitchCase", - "api-reference/core/SwitchStatement", - "api-reference/core/Symbol", - "api-reference/core/SymbolGroup", - "api-reference/core/SymbolStatement", - "api-reference/core/TernaryExpression", - "api-reference/core/TryCatchStatement", - "api-reference/core/Tuple", - "api-reference/core/TupleType", - "api-reference/core/Type", - "api-reference/core/TypeAlias", - "api-reference/core/TypePlaceholder", - "api-reference/core/Typeable", - "api-reference/core/UnaryExpression", - "api-reference/core/UnionType", - "api-reference/core/Unpack", - "api-reference/core/Unwrappable", - "api-reference/core/Usable", - "api-reference/core/Usage", - "api-reference/core/UsageKind", - "api-reference/core/UsageType", - "api-reference/core/Value", - "api-reference/core/WhileStatement", - "api-reference/core/WithStatement" - ] - }, - { - "group": "Python", - "icon": "python", - "pages": [ - "api-reference/python/PyAssignment", - "api-reference/python/PyAssignmentStatement", - "api-reference/python/PyAttribute", - "api-reference/python/PyBlockStatement", - "api-reference/python/PyBreakStatement", - "api-reference/python/PyCatchStatement", - "api-reference/python/PyChainedAttribute", - "api-reference/python/PyClass", - "api-reference/python/PyCodeBlock", - "api-reference/python/PyComment", - "api-reference/python/PyCommentGroup", - "api-reference/python/PyCommentType", - "api-reference/python/PyConditionalExpression", - "api-reference/python/PyDecorator", - "api-reference/python/PyFile", - "api-reference/python/PyForLoopStatement", - "api-reference/python/PyFunction", - "api-reference/python/PyGenericType", - "api-reference/python/PyHasBlock", - "api-reference/python/PyIfBlockStatement", - "api-reference/python/PyImport", - "api-reference/python/PyImportStatement", - "api-reference/python/PyMatchCase", - "api-reference/python/PyMatchStatement", - "api-reference/python/PyNamedType", - "api-reference/python/PyParameter", - "api-reference/python/PyPassStatement", - "api-reference/python/PyReturnTypePlaceholder", - "api-reference/python/PyString", - "api-reference/python/PySymbol", - "api-reference/python/PyTryCatchStatement", - "api-reference/python/PyUnionType", - "api-reference/python/PyWhileStatement" - ] - }, - { - "group": "Typescript", - "icon": "js", - "pages": [ - "api-reference/typescript/JSXElement", - "api-reference/typescript/JSXExpression", - "api-reference/typescript/JSXProp", - "api-reference/typescript/TSArrayType", - "api-reference/typescript/TSAssignment", - "api-reference/typescript/TSAssignmentStatement", - "api-reference/typescript/TSAttribute", - "api-reference/typescript/TSBlockStatement", - "api-reference/typescript/TSCatchStatement", - "api-reference/typescript/TSChainedAttribute", - "api-reference/typescript/TSClass", - "api-reference/typescript/TSCodeBlock", - "api-reference/typescript/TSComment", - "api-reference/typescript/TSCommentGroup", - "api-reference/typescript/TSCommentType", - "api-reference/typescript/TSConditionalType", - "api-reference/typescript/TSConfig", - "api-reference/typescript/TSDecorator", - "api-reference/typescript/TSDict", - "api-reference/typescript/TSEnum", - "api-reference/typescript/TSExport", - "api-reference/typescript/TSExpressionType", - "api-reference/typescript/TSFile", - "api-reference/typescript/TSForLoopStatement", - "api-reference/typescript/TSFunction", - "api-reference/typescript/TSFunctionType", - "api-reference/typescript/TSGenericType", - "api-reference/typescript/TSHasBlock", - "api-reference/typescript/TSIfBlockStatement", - "api-reference/typescript/TSImport", - "api-reference/typescript/TSImportStatement", - "api-reference/typescript/TSInterface", - "api-reference/typescript/TSLabeledStatement", - "api-reference/typescript/TSLookupType", - "api-reference/typescript/TSNamedType", - "api-reference/typescript/TSNamespace", - "api-reference/typescript/TSObjectType", - "api-reference/typescript/TSPair", - "api-reference/typescript/TSParameter", - "api-reference/typescript/TSQueryType", - "api-reference/typescript/TSReadonlyType", - "api-reference/typescript/TSReturnTypePlaceholder", - "api-reference/typescript/TSString", - "api-reference/typescript/TSSwitchCase", - "api-reference/typescript/TSSwitchStatement", - "api-reference/typescript/TSSymbol", - "api-reference/typescript/TSTernaryExpression", - "api-reference/typescript/TSTryCatchStatement", - "api-reference/typescript/TSTypeAlias", - "api-reference/typescript/TSUndefinedType", - "api-reference/typescript/TSUnionType", - "api-reference/typescript/TSWhileStatement" - ] - } - ] - } - ], - "footerSocials": { - "x": "https://x.com/codegen", - "linkedin": "https://linkedin.com/company/codegen-dot-com" - } -} + "$schema": "https://mintlify.com/schema.json", + "name": "Codegen", + "logo": { + "dark": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45a3e32761c42b324b_Codegen_Logomark_Dark.svg", + "light": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45bf55446746125835_Codegen_Logomark_Light.svg" + }, + "modeToggle": { + "default": "dark" + }, + "metadata": { + "og:site_name": "Codegen", + "og:title": "Codegen - Manipulate Code at Scale", + "og:description": "A scriptable interface to a powerful, multi-lingual language server built on top of Tree-sitter.", + "og:url": "https://docs.codegen.com", + "og:locale": "en_US", + "og:logo": "https://i.imgur.com/f4OVOqI.png", + "article:publisher": "Codegen, Inc.", + "twitter:site": "@codegen" + }, + "favicon": "/favicon.svg", + "colors": { + "primary": "#a277ff", + "light": "#a277ff", + "dark": "#a277ff", + "anchors": { + "from": "#61ffca", + "to": "#61ffca" + } + }, + "theme": "prism", + "background": { + "style": "gradient" + }, + "analytics": { + "posthog": { + "apiKey": "phc_GLxaINoQJnuyCyxDmTciQqzdKBYFVDkY7bRBO4bDdso" + } + }, + "feedback": { + "thumbsRating": true + }, + "topbarCtaButton": { + "name": "GitHub", + "url": "https://github.com/codegen-sh/codegen-sdk" + }, + "tabs": [ + { + "name": "API Reference", + "url": "/api-reference" + }, + { + "name": "CLI", + "url": "/cli" + }, + { + "name": "Blog", + "url": "/blog" + }, + { + "name": "Changelog", + "url": "/changelog" + } + ], + "navigation": [ + { + "group": "Introduction", + "pages": [ + "introduction/overview", + "introduction/getting-started", + "introduction/installation", + "introduction/ide-usage", + "introduction/work-with-ai", + "introduction/how-it-works", + "introduction/guiding-principles", + "introduction/community", + "introduction/about", + "introduction/faq" + ] + }, + { + "group": "Tutorials", + "pages": [ + "tutorials/at-a-glance", + "tutorials/build-code-agent", + "tutorials/slack-bot", + "tutorials/github-review-bot", + "tutorials/deep-code-research", + "tutorials/training-data", + "tutorials/codebase-visualization", + "tutorials/migrating-apis", + "tutorials/organize-your-codebase", + "tutorials/promise-to-async-await", + "tutorials/modularity", + "tutorials/manage-feature-flags", + "tutorials/deleting-dead-code", + "tutorials/increase-type-coverage", + "tutorials/managing-typescript-exports", + "tutorials/converting-default-exports", + "tutorials/creating-documentation", + "tutorials/react-modernization", + "tutorials/unittest-to-pytest", + "tutorials/sqlalchemy-1.6-to-2.0", + "tutorials/fixing-import-loops-in-pytorch", + "tutorials/python2-to-python3", + "tutorials/flask-to-fastapi", + "tutorials/build-mcp", + "tutorials/neo4j-graph" + ] + }, + { + "group": "Building with Codegen", + "pages": [ + "building-with-codegen/at-a-glance", + "building-with-codegen/parsing-codebases", + "building-with-codegen/reusable-codemods", + "building-with-codegen/dot-codegen", + "building-with-codegen/function-decorator", + "building-with-codegen/language-support", + "building-with-codegen/commit-and-reset", + "building-with-codegen/git-operations", + "building-with-codegen/files-and-directories", + "building-with-codegen/the-editable-api", + "building-with-codegen/symbol-api", + "building-with-codegen/class-api", + "building-with-codegen/imports", + "building-with-codegen/exports", + "building-with-codegen/inheritable-behaviors", + "building-with-codegen/statements-and-code-blocks", + "building-with-codegen/dependencies-and-usages", + "building-with-codegen/function-calls-and-callsites", + "building-with-codegen/variable-assignments", + "building-with-codegen/local-variables", + "building-with-codegen/comments-and-docstrings", + "building-with-codegen/external-modules", + "building-with-codegen/type-annotations", + "building-with-codegen/moving-symbols", + "building-with-codegen/collections", + "building-with-codegen/traversing-the-call-graph", + "building-with-codegen/react-and-jsx", + "building-with-codegen/codebase-visualization", + "building-with-codegen/flagging-symbols", + "building-with-codegen/calling-out-to-llms", + "building-with-codegen/semantic-code-search", + "building-with-codegen/reducing-conditions" + ] + }, + { + "group": "CLI", + "pages": [ + "cli/about", + "cli/init", + "cli/notebook", + "cli/create", + "cli/run", + "cli/reset", + "cli/expert" + ] + }, + { + "group": "Changelog", + "pages": [ + "changelog/changelog" + ] + }, + { + "group": "Blog", + "pages": [ + "blog/posts", + "blog/devin", + "blog/act-via-code", + "blog/promise-to-async-await-twilio", + "blog/fixing-import-loops" + ] + }, + { + "group": "API Reference", + "pages": [ + "api-reference/index", + { + "group": "Core", + "icon": "code", + "pages": [ + "api-reference/core/Argument", + "api-reference/core/Assignment", + "api-reference/core/AssignmentStatement", + "api-reference/core/Attribute", + "api-reference/core/AwaitExpression", + "api-reference/core/BinaryExpression", + "api-reference/core/BlockStatement", + "api-reference/core/Boolean", + "api-reference/core/Callable", + "api-reference/core/CatchStatement", + "api-reference/core/ChainedAttribute", + "api-reference/core/Class", + "api-reference/core/CodeBlock", + "api-reference/core/CodeOwner", + "api-reference/core/Codebase", + "api-reference/core/Comment", + "api-reference/core/CommentGroup", + "api-reference/core/ComparisonExpression", + "api-reference/core/Decorator", + "api-reference/core/Dict", + "api-reference/core/Directory", + "api-reference/core/Editable", + "api-reference/core/Export", + "api-reference/core/ExportStatement", + "api-reference/core/Exportable", + "api-reference/core/Expression", + "api-reference/core/ExpressionGroup", + "api-reference/core/ExpressionStatement", + "api-reference/core/ExternalModule", + "api-reference/core/File", + "api-reference/core/FlagKwargs", + "api-reference/core/ForLoopStatement", + "api-reference/core/Function", + "api-reference/core/FunctionCall", + "api-reference/core/GenericType", + "api-reference/core/HasBlock", + "api-reference/core/HasName", + "api-reference/core/HasValue", + "api-reference/core/IfBlockStatement", + "api-reference/core/Import", + "api-reference/core/ImportStatement", + "api-reference/core/ImportType", + "api-reference/core/Importable", + "api-reference/core/Interface", + "api-reference/core/List", + "api-reference/core/MessageType", + "api-reference/core/MultiExpression", + "api-reference/core/MultiLineCollection", + "api-reference/core/Name", + "api-reference/core/NamedType", + "api-reference/core/NoneType", + "api-reference/core/Number", + "api-reference/core/Pair", + "api-reference/core/Parameter", + "api-reference/core/ParenthesizedExpression", + "api-reference/core/Placeholder", + "api-reference/core/PlaceholderType", + "api-reference/core/RaiseStatement", + "api-reference/core/ReturnStatement", + "api-reference/core/SourceFile", + "api-reference/core/Span", + "api-reference/core/Statement", + "api-reference/core/StatementType", + "api-reference/core/String", + "api-reference/core/StubPlaceholder", + "api-reference/core/SubscriptExpression", + "api-reference/core/SwitchCase", + "api-reference/core/SwitchStatement", + "api-reference/core/Symbol", + "api-reference/core/SymbolGroup", + "api-reference/core/SymbolStatement", + "api-reference/core/TernaryExpression", + "api-reference/core/TryCatchStatement", + "api-reference/core/Tuple", + "api-reference/core/TupleType", + "api-reference/core/Type", + "api-reference/core/TypeAlias", + "api-reference/core/TypePlaceholder", + "api-reference/core/Typeable", + "api-reference/core/UnaryExpression", + "api-reference/core/UnionType", + "api-reference/core/Unpack", + "api-reference/core/Unwrappable", + "api-reference/core/Usable", + "api-reference/core/Usage", + "api-reference/core/UsageKind", + "api-reference/core/UsageType", + "api-reference/core/Value", + "api-reference/core/WhileStatement", + "api-reference/core/WithStatement" + ] + }, + { + "group": "Python", + "icon": "python", + "pages": [ + "api-reference/python/PyAssignment", + "api-reference/python/PyAssignmentStatement", + "api-reference/python/PyAttribute", + "api-reference/python/PyBlockStatement", + "api-reference/python/PyBreakStatement", + "api-reference/python/PyCatchStatement", + "api-reference/python/PyChainedAttribute", + "api-reference/python/PyClass", + "api-reference/python/PyCodeBlock", + "api-reference/python/PyComment", + "api-reference/python/PyCommentGroup", + "api-reference/python/PyCommentType", + "api-reference/python/PyConditionalExpression", + "api-reference/python/PyDecorator", + "api-reference/python/PyFile", + "api-reference/python/PyForLoopStatement", + "api-reference/python/PyFunction", + "api-reference/python/PyGenericType", + "api-reference/python/PyHasBlock", + "api-reference/python/PyIfBlockStatement", + "api-reference/python/PyImport", + "api-reference/python/PyImportStatement", + "api-reference/python/PyMatchCase", + "api-reference/python/PyMatchStatement", + "api-reference/python/PyNamedType", + "api-reference/python/PyParameter", + "api-reference/python/PyPassStatement", + "api-reference/python/PyReturnTypePlaceholder", + "api-reference/python/PyString", + "api-reference/python/PySymbol", + "api-reference/python/PyTryCatchStatement", + "api-reference/python/PyUnionType", + "api-reference/python/PyWhileStatement" + ] + }, + { + "group": "Typescript", + "icon": "js", + "pages": [ + "api-reference/typescript/JSXElement", + "api-reference/typescript/JSXExpression", + "api-reference/typescript/JSXProp", + "api-reference/typescript/TSArrayType", + "api-reference/typescript/TSAssignment", + "api-reference/typescript/TSAssignmentStatement", + "api-reference/typescript/TSAttribute", + "api-reference/typescript/TSBlockStatement", + "api-reference/typescript/TSCatchStatement", + "api-reference/typescript/TSChainedAttribute", + "api-reference/typescript/TSClass", + "api-reference/typescript/TSCodeBlock", + "api-reference/typescript/TSComment", + "api-reference/typescript/TSCommentGroup", + "api-reference/typescript/TSCommentType", + "api-reference/typescript/TSConditionalType", + "api-reference/typescript/TSConfig", + "api-reference/typescript/TSDecorator", + "api-reference/typescript/TSDict", + "api-reference/typescript/TSEnum", + "api-reference/typescript/TSExport", + "api-reference/typescript/TSExpressionType", + "api-reference/typescript/TSFile", + "api-reference/typescript/TSForLoopStatement", + "api-reference/typescript/TSFunction", + "api-reference/typescript/TSFunctionType", + "api-reference/typescript/TSGenericType", + "api-reference/typescript/TSHasBlock", + "api-reference/typescript/TSIfBlockStatement", + "api-reference/typescript/TSImport", + "api-reference/typescript/TSImportStatement", + "api-reference/typescript/TSInterface", + "api-reference/typescript/TSLabeledStatement", + "api-reference/typescript/TSLookupType", + "api-reference/typescript/TSNamedType", + "api-reference/typescript/TSNamespace", + "api-reference/typescript/TSObjectType", + "api-reference/typescript/TSPair", + "api-reference/typescript/TSParameter", + "api-reference/typescript/TSQueryType", + "api-reference/typescript/TSReadonlyType", + "api-reference/typescript/TSReturnTypePlaceholder", + "api-reference/typescript/TSString", + "api-reference/typescript/TSSwitchCase", + "api-reference/typescript/TSSwitchStatement", + "api-reference/typescript/TSSymbol", + "api-reference/typescript/TSTernaryExpression", + "api-reference/typescript/TSTryCatchStatement", + "api-reference/typescript/TSTypeAlias", + "api-reference/typescript/TSUndefinedType", + "api-reference/typescript/TSUnionType", + "api-reference/typescript/TSWhileStatement" + ] + } + ] + } + ], + "footerSocials": { + "x": "https://x.com/codegen", + "linkedin": "https://linkedin.com/company/codegen-dot-com" + } +} \ No newline at end of file From adf4b3f3e178795062b16697b981b322e3106166 Mon Sep 17 00:00:00 2001 From: Jay Hack Date: Tue, 4 Mar 2025 08:46:07 -0800 Subject: [PATCH 07/66] docs: fixes broken links (#731) --- docs/blog/devin.mdx | 8 +++--- docs/tutorials/at-a-glance.mdx | 2 +- docs/tutorials/github-review-bot.mdx | 35 +---------------------- docs/tutorials/promise-to-async-await.mdx | 2 +- 4 files changed, 7 insertions(+), 40 deletions(-) diff --git a/docs/blog/devin.mdx b/docs/blog/devin.mdx index c6c286117..25eb50beb 100644 --- a/docs/blog/devin.mdx +++ b/docs/blog/devin.mdx @@ -5,14 +5,14 @@ icon: "robot" iconType: "solid" --- -Coding assistants like Cursor have introduced a new era of programming. But there's a class of programming tasks they can't handle: large-scale, systematic modifications across large codebases. You wouldn't ask an AI to delete all dead code or reorganize your entire component hierarchy - the tooling just isn't there. +Coding assistants like Cursor have brought us into a new era of programming. But there's a class of programming tasks that remain outside their reach: large-scale, systematic modifications across large codebases. You wouldn't ask an AI to delete all your dead code or reorganize your entire component hierarchy - the tooling just isn't there. -That's where codemods come in. A codemod is a program that operates on your codebase, and when you give an AI agent the ability to write and execute them, these tasks fall below the high-water mark of AI capabilities. +That's where codemods come in. A codemod is a program that operates on a codebase, and when you give an AI agent the ability to write and execute them, these platform-level tasks fall below the high-water mark of AI capabilities. Here's a real example: we asked [Devin](https://docs.devin.ai/get-started/devin-intro) (an autonomous SWE agent) to "delete all dead code" from our codebase. Instead of trying to make hundreds of individual edits, Devin [wrote and debugged a program](https://github.com/codegen-sh/codegen/pull/660/files#diff-199b0c459adf1639f664fed248fa48bb640412aeacbe61cd89475d6598284b5f) that systematically removed unused code while handling edge cases like tests, decorators and indirect references. - [View the PR](https://github.com/codegen-sh/codegen/pull/660) -- [View on Devin](app.devin.ai/sessions/a49eac87da644fa9ac1144fe130b847e) +- [View on Devin](https://app.devin.ai/sessions/a49eac87da644fa9ac1144fe130b847e) @@ -89,4 +89,4 @@ Or try it with other platform-level modifications supported by Codegen: -We'd love to hear how it works for you! Let us know in our [community](https://community.codegen.com) and share other tasks that it is helpful in performing. \ No newline at end of file +We'd love to hear how it works for you! Let us know in our [community](https://community.codegen.com) and share your experience developing codemods with Devin or other code assistants. \ No newline at end of file diff --git a/docs/tutorials/at-a-glance.mdx b/docs/tutorials/at-a-glance.mdx index 1bdd1ce11..87c8f467f 100644 --- a/docs/tutorials/at-a-glance.mdx +++ b/docs/tutorials/at-a-glance.mdx @@ -53,7 +53,7 @@ Explore our tutorials to learn how to use Codegen for various code transformatio Update SQLAlchemy code to use the new 2.0-style query interface and patterns. diff --git a/docs/tutorials/github-review-bot.mdx b/docs/tutorials/github-review-bot.mdx index ab8b0ad8f..9b9a669fd 100644 --- a/docs/tutorials/github-review-bot.mdx +++ b/docs/tutorials/github-review-bot.mdx @@ -186,37 +186,4 @@ While this example demonstrates a basic PR review bot, you can extend it to: - Add automatic fix suggestions - ... etc. -Check out our [Code Agent tutorial](/tutorials/build-code-agent) to learn more about building sophisticated AI agents with Codegen - -## Learn More - - - - Learn how to build intelligent code agents with Codegen. - - - Explore Codegen's GitHub integration features. - - - Learn about deploying apps with Modal. - - - Understand code review patterns and best practices. - - \ No newline at end of file +Check out our [Code Agent tutorial](/tutorials/build-code-agent) to learn more about building sophisticated AI agents with Codegen \ No newline at end of file diff --git a/docs/tutorials/promise-to-async-await.mdx b/docs/tutorials/promise-to-async-await.mdx index 9e30cf3c4..2811ee2ae 100644 --- a/docs/tutorials/promise-to-async-await.mdx +++ b/docs/tutorials/promise-to-async-await.mdx @@ -96,7 +96,7 @@ new_code = promise_statement.edit( - Ambiguous/conditional return blocks -A list of all the covered cases can be found in the [example notebook](codegen-examples/examples/promises_to_async_await/promise_to_async_await.ipynb). +A list of all the covered cases can be found in the [example notebook](https://github.com/codegen-sh/codegen-sdk/tree/codegen-examples/examples/promises_to_async_await/promise_to_async_await.ipynb). From 5c3ccf81638d15c28745bedd99de9f93971e994f Mon Sep 17 00:00:00 2001 From: codegen-team Date: Tue, 4 Mar 2025 16:47:32 +0000 Subject: [PATCH 08/66] docs: updated API reference --- src/codegen/sdk/system-prompt.txt | 37 ++----------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/src/codegen/sdk/system-prompt.txt b/src/codegen/sdk/system-prompt.txt index e2fee43ec..e5b616c1b 100644 --- a/src/codegen/sdk/system-prompt.txt +++ b/src/codegen/sdk/system-prompt.txt @@ -6358,7 +6358,7 @@ Explore our tutorials to learn how to use Codegen for various code transformatio Update SQLAlchemy code to use the new 2.0-style query interface and patterns. @@ -7050,39 +7050,6 @@ While this example demonstrates a basic PR review bot, you can extend it to: Check out our [Code Agent tutorial](/tutorials/build-code-agent) to learn more about building sophisticated AI agents with Codegen -## Learn More - - - - Learn how to build intelligent code agents with Codegen. - - - Explore Codegen's GitHub integration features. - - - Learn about deploying apps with Modal. - - - Understand code review patterns and best practices. - - - --- title: "Deep Code Research with AI" sidebarTitle: "Code Research Agent" @@ -8470,7 +8437,7 @@ new_code = promise_statement.edit( - Ambiguous/conditional return blocks -A list of all the covered cases can be found in the [example notebook](codegen-examples/examples/promises_to_async_await/promise_to_async_await.ipynb). +A list of all the covered cases can be found in the [example notebook](https://github.com/codegen-sh/codegen-sdk/tree/codegen-examples/examples/promises_to_async_await/promise_to_async_await.ipynb). From 839f11d3869fdb9f17b10a7bd8533d5fc388e489 Mon Sep 17 00:00:00 2001 From: jemeza-codegen <165736868+jemeza-codegen@users.noreply.github.com> Date: Tue, 4 Mar 2025 09:13:16 -0800 Subject: [PATCH 09/66] chore: speeding up benchmark with concurrent requests (#720) # Motivation Leverages asyncio to optimize API limit usage. # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- .../examples/swebench_agent_run/run_eval.py | 156 ++++++++++-------- 1 file changed, 87 insertions(+), 69 deletions(-) diff --git a/codegen-examples/examples/swebench_agent_run/run_eval.py b/codegen-examples/examples/swebench_agent_run/run_eval.py index b39cede6f..ff349266c 100644 --- a/codegen-examples/examples/swebench_agent_run/run_eval.py +++ b/codegen-examples/examples/swebench_agent_run/run_eval.py @@ -17,93 +17,106 @@ run_agent_modal = modal.Function.from_name(app_name="swebench-agent-run", name="run_agent_modal") -async def process_batch_modal(examples: list[SweBenchExample], batch_size=10): - """Process a batch of examples concurrently. +async def process_batch_modal(examples: list[SweBenchExample], num_workers=10, max_retries=3): + """Process a batch of examples concurrently using a queue system. Args: examples: List of SweBenchExample objects to process - batch_size: Number of examples to process concurrently. - Default is 50 which provides good parallelization - while staying well within Modal's limits. + num_workers: Number of examples to process concurrently + max_retries: Maximum number of retries for failed requests """ - results = [] - - # Process examples in batches - for i in range(0, len(examples), batch_size): - batch = examples[i : i + batch_size] + results = {} + queue = asyncio.Queue() - # Create tasks for this batch - batch_tasks = [run_agent_modal.remote.aio(example) for example in batch] - - # Wait for all tasks in this batch to complete - print(f"Processing batch {i // batch_size + 1}/{len(examples) // batch_size + 1} (examples {i + 1}-{min(i + batch_size, len(examples))})") + # Initialize the queue with (example, attempt) tuples + for example in examples: + await queue.put((example, 0)) # 0 represents first attempt + async def process_example(example, attempt): try: - batch_results = await asyncio.gather(*batch_tasks, return_exceptions=True) - - # Store results - for example, result in zip(batch, batch_results): - error_info = None - - if isinstance(result, Exception): - error_type = type(result).__name__ - error_info = { - "error_type": error_type, - "error_message": str(result), - "traceback": traceback.format_exception(type(result), result, result.__traceback__), - } - - if isinstance(result, modal.exception.Error): - error_info["modal_error_code"] = getattr(result, "code", None) - error_info["modal_error_details"] = getattr(result, "details", None) - - print(f"Error processing {example.instance_id}:") - print(f"Type: {error_type}") - print(f"Message: {str(result)}") - print("Traceback:") - print("".join(error_info["traceback"])) - - results.append({"instance_id": example.instance_id, "status": "error", "error_info": error_info}) - else: - if result is None: - print(f"Warning: Null result for {example.instance_id}") - results.append({"instance_id": example.instance_id, "status": "error", "error_info": {"error_type": "NullResult", "error_message": "Process returned None"}}) - else: - results.append(result) + result = await run_agent_modal.remote.aio(example) + + if result is None: + print(f"Warning: Null result for {example.instance_id}") + return {"instance_id": example.instance_id, "status": "error", "error_info": {"error_type": "NullResult", "error_message": "Process returned None"}} + return result except Exception as e: - print("Batch processing error:") - print(f"Type: {type(e).__name__}") + error_type = type(e).__name__ + error_info = { + "error_type": error_type, + "error_message": str(e), + "traceback": traceback.format_exception(type(e), e, e.__traceback__), + } + + if isinstance(e, modal.exception.Error): + error_info["modal_error_code"] = getattr(e, "code", None) + error_info["modal_error_details"] = getattr(e, "details", None) + + print(f"Error processing {example.instance_id} (attempt {attempt + 1}):") + print(f"Type: {error_type}") print(f"Message: {str(e)}") - traceback.print_exc() - - # Mark all examples in the batch as failed - for example in batch: - results.append( - { - "instance_id": example.instance_id, - "status": "error", - "error_info": {"error_type": type(e).__name__, "error_message": str(e), "traceback": traceback.format_exc(), "batch_failure": True}, - } - ) + print("Traceback:") + print("".join(error_info["traceback"])) - return results + if attempt < max_retries: + await queue.put((example, attempt + 1)) + return None + + return {"instance_id": example.instance_id, "status": "error", "error_info": error_info} + + async def worker(): + while True: + try: + example, attempt = await queue.get() + + if example.instance_id in results: + queue.task_done() + continue + + result = await process_example(example, attempt) + + if result is not None: + results[example.instance_id] = result + + queue.task_done() + + except Exception as e: + print(f"Worker error: {str(e)}") + traceback.print_exc() + queue.task_done() + + # Start workers + workers = [asyncio.create_task(worker()) for _ in range(num_workers)] + + # Wait for queue to be fully processed + await queue.join() + + # Cancel workers + for w in workers: + w.cancel() + + # Wait for all workers to be cancelled + await asyncio.gather(*workers, return_exceptions=True) + + # Return results in the same order as input examples + return [results[example.instance_id] for example in examples] -def process_batch_local(examples: list[SweBenchExample], batch_size=10, codebases: dict[str, Codebase] = {}): +def process_batch_local(examples: list[SweBenchExample], num_workers=5, codebases: dict[str, Codebase] = {}): """Process a batch of examples synchronously. Args: examples: List of SweBenchExample objects to process - batch_size: Number of examples to process in each batch. + num_workers: Number of examples to process in each batch. Default is 10 to avoid overwhelming the system. """ results = [] # Process examples in batches - for i in range(0, len(examples), batch_size): - batch = examples[i : i + batch_size] - print(f"Processing batch {i // batch_size + 1}/{len(examples) // batch_size + 1} (examples {i + 1}-{min(i + batch_size, len(examples))})") + for i in range(0, len(examples), num_workers): + batch = examples[i : i + num_workers] + print(f"Processing batch {i // num_workers + 1}/{len(examples) // num_workers + 1} (examples {i + 1}-{min(i + num_workers, len(examples))})") # Process each example in the batch for example in batch: @@ -134,7 +147,9 @@ def process_batch_local(examples: list[SweBenchExample], batch_size=10, codebase return results -async def run_eval(use_existing_preds: str | None, dataset: str, length: int, instance_id: str | None = None, local: bool = False, codebases: dict[str, Codebase] = {}, repo: str | None = None): +async def run_eval( + use_existing_preds: str | None, dataset: str, length: int, instance_id: str | None = None, local: bool = False, codebases: dict[str, Codebase] = {}, repo: str | None = None, num_workers: int = 5 +): run_id = use_existing_preds or str(uuid.uuid4()) print(f"Run ID: {run_id}") predictions_dir = PREDS_DNAME / f"results_{run_id}" @@ -162,7 +177,7 @@ async def run_eval(use_existing_preds: str | None, dataset: str, length: int, in if local: results = process_batch_local(examples, codebases=codebases) else: - results = await process_batch_modal(examples) + results = await process_batch_modal(examples, num_workers=num_workers) # Save individual results for result in results: @@ -218,9 +233,12 @@ async def run_eval(use_existing_preds: str | None, dataset: str, length: int, in @click.option("--instance-id", help="The instance ID of the example to process.", type=str, default=None) @click.option("--local", help="Run the evaluation locally.", is_flag=True, default=False) @click.option("--repo", help="The repo to use.", type=str, default=None) -def run_eval_command(use_existing_preds, dataset, length, instance_id, local, repo): +@click.option( + "--num-workers", help="The number of workers to use. This is the number of examples that will be processed concurrently. A large number may lead to rate limiting issues.", type=int, default=5 +) +def run_eval_command(use_existing_preds, dataset, length, instance_id, local, repo, num_workers): print(f"Repo: {repo}") - asyncio.run(run_eval(use_existing_preds=use_existing_preds, dataset=dataset, length=length, instance_id=instance_id, codebases=None, local=local, repo=repo)) + asyncio.run(run_eval(use_existing_preds=use_existing_preds, dataset=dataset, length=length, instance_id=instance_id, codebases=None, local=local, repo=repo, num_workers=num_workers)) if __name__ == "__main__": From ee58fb68d8ee29845b8828894e3758229751a87a Mon Sep 17 00:00:00 2001 From: Christine Wang Date: Tue, 4 Mar 2025 11:49:49 -0800 Subject: [PATCH 10/66] chore(ci): use 3.13 codecov-cli (#735) --- .github/actions/setup-environment/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-environment/action.yml b/.github/actions/setup-environment/action.yml index b4984bdf9..299e831e9 100644 --- a/.github/actions/setup-environment/action.yml +++ b/.github/actions/setup-environment/action.yml @@ -26,5 +26,5 @@ runs: - name: Install codecov shell: bash run: | - uv tool install codecov-cli@10.0.1 --python 3.10 + uv tool install codecov-cli@10.0.1 uv tool update-shell From 5493f3448afb4e9c2d340d9f9a70d26e39b43632 Mon Sep 17 00:00:00 2001 From: Edward Li Date: Tue, 4 Mar 2025 12:22:51 -0800 Subject: [PATCH 11/66] Speed up directory tree generation (#736) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- src/codegen/git/repo_operator/repo_operator.py | 8 ++++++-- src/codegen/sdk/codebase/codebase_context.py | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/codegen/git/repo_operator/repo_operator.py b/src/codegen/git/repo_operator/repo_operator.py index 42d9c7e47..d2a323e60 100644 --- a/src/codegen/git/repo_operator/repo_operator.py +++ b/src/codegen/git/repo_operator/repo_operator.py @@ -616,6 +616,7 @@ def iter_files( subdirs: list[str] | None = None, extensions: list[str] | None = None, ignore_list: list[str] | None = None, + skip_content: bool = False, ) -> Generator[tuple[str, str]]: """Iterates over all files in the codebase, yielding the filepath and its content. @@ -642,8 +643,11 @@ def iter_files( if extensions is None or any(filepath.endswith(e) for e in extensions): try: - content = self.get_file(filepath) - yield rel_filepath, content + if not skip_content: + content = self.get_file(filepath) + yield rel_filepath, content + else: + yield rel_filepath, "" except Exception as e: logger.warning(f"Error reading file {filepath}: {e}") diff --git a/src/codegen/sdk/codebase/codebase_context.py b/src/codegen/sdk/codebase/codebase_context.py index 9a015ba10..7f1fdc29e 100644 --- a/src/codegen/sdk/codebase/codebase_context.py +++ b/src/codegen/sdk/codebase/codebase_context.py @@ -365,7 +365,11 @@ def build_directory_tree(self) -> None: # Reset and rebuild the directory tree self.directories = dict() - for file_path, _ in self.projects[0].repo_operator.iter_files(subdirs=self.projects[0].subdirectories, ignore_list=GLOBAL_FILE_IGNORE_LIST): + for file_path, _ in self.projects[0].repo_operator.iter_files( + subdirs=self.projects[0].subdirectories, + ignore_list=GLOBAL_FILE_IGNORE_LIST, + skip_content=True, + ): file_path = Path(file_path) directory = self.get_directory(file_path.parent, create_on_missing=True) directory._add_file(file_path.name) @@ -510,7 +514,6 @@ def _process_diff_files(self, files_to_sync: Mapping[SyncType, list[Path]], incr # Step 6: Build directory tree logger.info("> Building directory tree") - files = [f for f in sort_editables(self.get_nodes(NodeType.FILE), alphabetical=True, dedupe=False)] self.build_directory_tree() # Step 7: Build configs From 0058abefa3ef0fa1dcfa54ff73fde1bbd8300340 Mon Sep 17 00:00:00 2001 From: Jay Hack Date: Tue, 4 Mar 2025 12:26:20 -0800 Subject: [PATCH 12/66] fix: removes fancy tools from default agent implementation (#738) Removes `RevealSymbol` and `MoveSymbol` from default tools --- src/codegen/extensions/langchain/agent.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen/extensions/langchain/agent.py b/src/codegen/extensions/langchain/agent.py index d834b7b6a..aabc57847 100644 --- a/src/codegen/extensions/langchain/agent.py +++ b/src/codegen/extensions/langchain/agent.py @@ -67,8 +67,8 @@ def create_codebase_agent( CreateFileTool(codebase), DeleteFileTool(codebase), RenameFileTool(codebase), - MoveSymbolTool(codebase), - RevealSymbolTool(codebase), + # MoveSymbolTool(codebase), + # RevealSymbolTool(codebase), # SemanticEditTool(codebase), ReplacementEditTool(codebase), RelaceEditTool(codebase), From c5b3ba443cf0bc51ff4aae703cdfafe319406257 Mon Sep 17 00:00:00 2001 From: Edo Pujol Date: Tue, 4 Mar 2025 15:35:01 -0500 Subject: [PATCH 13/66] feat: runner tooling (#733) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --------- Co-authored-by: kopekC <28070492+kopekC@users.noreply.github.com> --- codegen-examples/examples/swebench_agent_run/entry_point.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen-examples/examples/swebench_agent_run/entry_point.py b/codegen-examples/examples/swebench_agent_run/entry_point.py index 411b09d3b..79fd19575 100644 --- a/codegen-examples/examples/swebench_agent_run/entry_point.py +++ b/codegen-examples/examples/swebench_agent_run/entry_point.py @@ -13,7 +13,7 @@ app = modal.App(name="swebench-agent-run", image=image, secrets=[modal.Secret.from_dotenv()]) -@app.function(timeout=10 * 60) +@app.function(timeout=43200) async def run_agent_modal(entry: SweBenchExample): """Modal function to process a single example from the SWE-bench dataset.""" return run_agent_on_entry(entry) From c06d1c635c6d611feec9e6ecfc504cfe39333596 Mon Sep 17 00:00:00 2001 From: Edward Li Date: Tue, 4 Mar 2025 13:05:11 -0800 Subject: [PATCH 14/66] Fix tests??? Somehow? (#740) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- src/codegen/git/repo_operator/repo_operator.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/codegen/git/repo_operator/repo_operator.py b/src/codegen/git/repo_operator/repo_operator.py index d2a323e60..9f1f58007 100644 --- a/src/codegen/git/repo_operator/repo_operator.py +++ b/src/codegen/git/repo_operator/repo_operator.py @@ -647,6 +647,8 @@ def iter_files( content = self.get_file(filepath) yield rel_filepath, content else: + # WTF??? A no-op file read here fixes file parsing somehow? + open(filepath).close() yield rel_filepath, "" except Exception as e: logger.warning(f"Error reading file {filepath}: {e}") From 36625f0158c2101962f385edaa3a5b269ed9ce8d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 4 Mar 2025 21:09:40 +0000 Subject: [PATCH 15/66] update changelog --- docs/changelog/changelog.mdx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 2e614ffce..639ad1b2e 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,14 @@ icon: "clock" iconType: "solid" --- + +### [Improve performance and update documentation.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.45.0) +- Add runner tooling feature +- Speed up directory tree generation +- Remove unnecessary tools from agent implementation +- Update API reference and fix documentation links + + ### [Fixes a Slack schema error.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.44.4) - Fix Slack schema error From ae8dd56d6128de62e1ecdcbcbcb368486541d259 Mon Sep 17 00:00:00 2001 From: Edward Li Date: Tue, 4 Mar 2025 13:53:33 -0800 Subject: [PATCH 16/66] Gitignore pyrightconfig.json (#743) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 54c7b88c0..2c38ccae0 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ supabase/config.toml **/scripts/*.md **/scripts/Personal/* **/infrastructure/aws_infra/.terraform/* +pyrightconfig.json Edwards Scratchpad.ipynb # Allowing .env files to exist in repository, but not allowing updates From ed493063c7a419f357fecb4f3b2af99a91c027c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:56:05 +0000 Subject: [PATCH 17/66] fix(deps): update dependency openai to v1.65.3 (#744) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [openai](https://redirect.github.com/openai/openai-python) | `==1.65.2` -> `==1.65.3` | [![age](https://developer.mend.io/api/mc/badges/age/pypi/openai/1.65.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/openai/1.65.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/openai/1.65.2/1.65.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/openai/1.65.2/1.65.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes

openai/openai-python (openai) ### [`v1.65.3`](https://redirect.github.com/openai/openai-python/blob/HEAD/CHANGELOG.md#1653-2025-03-04) [Compare Source](https://redirect.github.com/openai/openai-python/compare/v1.65.2...v1.65.3) Full Changelog: [v1.65.2...v1.65.3](https://redirect.github.com/openai/openai-python/compare/v1.65.2...v1.65.3) ##### Chores - **internal:** remove unused http client options forwarding ([#​2158](https://redirect.github.com/openai/openai-python/issues/2158)) ([76ec464](https://redirect.github.com/openai/openai-python/commit/76ec464cfe3db3fa59a766259d6d6ee5bb889f86)) - **internal:** run example files in CI ([#​2160](https://redirect.github.com/openai/openai-python/issues/2160)) ([9979345](https://redirect.github.com/openai/openai-python/commit/9979345038594440eec2f500c0c7cc5417cc7c08))
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - "* 0-3 * * 1" (UTC). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/codegen-sh/codegen). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- uv.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e2a7470d1..93d695eb8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" # renovate: datasource=python-version depName=python requires-python = ">=3.12, <3.14" dependencies = [ - "openai==1.65.2", + "openai==1.65.3", "tiktoken<1.0.0,>=0.5.1", "tabulate>=0.9.0,<1.0.0", "codeowners<1.0.0,>=0.6.0", diff --git a/uv.lock b/uv.lock index 2c51348b3..5340f0dad 100644 --- a/uv.lock +++ b/uv.lock @@ -701,7 +701,7 @@ requires-dist = [ { name = "neo4j" }, { name = "networkx", specifier = ">=3.4.1" }, { name = "numpy", specifier = ">=2.2.2" }, - { name = "openai", specifier = "==1.65.2" }, + { name = "openai", specifier = "==1.65.3" }, { name = "packaging", specifier = ">=24.2" }, { name = "pip", specifier = ">=24.3.1" }, { name = "plotly", specifier = ">=5.24.0,<7.0.0" }, @@ -2716,7 +2716,7 @@ wheels = [ [[package]] name = "openai" -version = "1.65.2" +version = "1.65.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2728,9 +2728,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f6/03/0bbf201a7e44920d892db0445874c8111be4255cb9495379df18d6d36ea1/openai-1.65.2.tar.gz", hash = "sha256:729623efc3fd91c956f35dd387fa5c718edd528c4bed9f00b40ef290200fb2ce", size = 359185 } +sdist = { url = "https://files.pythonhosted.org/packages/32/4f/b34b6fad12e1f6b3f42922214c161d5ef74a50fa97d9ae7d680db0958ff4/openai-1.65.3.tar.gz", hash = "sha256:9b7cd8f79140d03d77f4ed8aeec6009be5dcd79bbc02f03b0e8cd83356004f71", size = 358821 } wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/3b/722ed868cb56f70264190ed479b38b3e46d14daa267d559a3fe3bd9061cf/openai-1.65.2-py3-none-any.whl", hash = "sha256:27d9fe8de876e31394c2553c4e6226378b6ed85e480f586ccfe25b7193fb1750", size = 473206 }, + { url = "https://files.pythonhosted.org/packages/86/d5/b8378be0f4cf192992aa3080eb9ddcdca3109b399be61984424aaa79f847/openai-1.65.3-py3-none-any.whl", hash = "sha256:a155fa5d60eccda516384d3d60d923e083909cc126f383fe4a350f79185c232a", size = 472758 }, ] [[package]] From 4d4b079bfc47c189b4516b68cb764494ee312e3f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 4 Mar 2025 21:58:15 +0000 Subject: [PATCH 18/66] update changelog --- docs/changelog/changelog.mdx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 639ad1b2e..1cd40baab 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,11 @@ icon: "clock" iconType: "solid" --- + +### [Improved bug fixes with updated dependency.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.45.1) +- Update dependency to improve bug fixes + + ### [Improve performance and update documentation.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.45.0) - Add runner tooling feature From e23dac4d792a1567aeab09634f557b5f07ab7b2f Mon Sep 17 00:00:00 2001 From: jemeza-codegen <165736868+jemeza-codegen@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:01:45 -0800 Subject: [PATCH 19/66] Dynamic scaling of asyncio request (#721) # Motivation Scales number of concurrent request dynamically based on whether or not rate limits are hit. # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- .../examples/swebench_agent_run/run_eval.py | 165 +++++++++++++++--- 1 file changed, 142 insertions(+), 23 deletions(-) diff --git a/codegen-examples/examples/swebench_agent_run/run_eval.py b/codegen-examples/examples/swebench_agent_run/run_eval.py index ff349266c..65d4b1518 100644 --- a/codegen-examples/examples/swebench_agent_run/run_eval.py +++ b/codegen-examples/examples/swebench_agent_run/run_eval.py @@ -5,7 +5,7 @@ import uuid import modal import click -from datetime import datetime +import time from codegen.extensions.swebench.harness import run_agent_on_entry from codegen.extensions.swebench.utils import SWEBenchDataset, SweBenchExample, get_swe_bench_examples from codegen.extensions.swebench.report import generate_report @@ -17,28 +17,112 @@ run_agent_modal = modal.Function.from_name(app_name="swebench-agent-run", name="run_agent_modal") -async def process_batch_modal(examples: list[SweBenchExample], num_workers=10, max_retries=3): - """Process a batch of examples concurrently using a queue system. +async def process_batch_modal(examples: list[SweBenchExample], num_workers=5, min_workers=1, max_retries=3): + """Process a batch of examples concurrently using a queue system with incremental worker scaling. Args: examples: List of SweBenchExample objects to process - num_workers: Number of examples to process concurrently + num_workers: Initial number of examples to process concurrently + min_workers: Minimum number of concurrent workers to maintain max_retries: Maximum number of retries for failed requests """ results = {} queue = asyncio.Queue() + # Shared state for worker management + state = { + "active_workers": num_workers, + "success_streak": 0, + "last_scaling_time": time.time(), + "scaling_cooldown": 0, # seconds between scaling operations + "worker_tasks": [], + "running": True, + } + + # Use a lock to protect shared state during adjustments + state_lock = asyncio.Lock() + # Initialize the queue with (example, attempt) tuples for example in examples: await queue.put((example, 0)) # 0 represents first attempt - async def process_example(example, attempt): + async def scale_down_worker(task_to_cancel=None): + """Remove a single worker when rate limiting is detected""" + async with state_lock: + # Only scale if cooldown period has passed and we're above min_workers + current_time = time.time() + if current_time - state["last_scaling_time"] < state["scaling_cooldown"] or state["active_workers"] <= min_workers: + return False + + # Reset success streak when scaling down + state["success_streak"] = 0 + state["last_scaling_time"] = current_time + + # If a specific task was provided, cancel it + if task_to_cancel and task_to_cancel in state["worker_tasks"]: + print(f"Rate limiting detected! Removing 1 worker, going from {state['active_workers']} to {state['active_workers'] - 1}") + state["worker_tasks"].remove(task_to_cancel) + task_to_cancel.cancel() + state["active_workers"] -= 1 + return True + + # Otherwise, cancel the most recently added worker + elif state["worker_tasks"]: + print(f"Rate limiting detected! Removing 1 worker, going from {state['active_workers']} to {state['active_workers'] - 1}") + task = state["worker_tasks"].pop() + task.cancel() + state["active_workers"] -= 1 + return True + + return False + + async def scale_up_worker(): + """Add a single worker when operations have been consistently successful""" + async with state_lock: + # Only scale if cooldown period has passed and we're below num_workers + current_time = time.time() + if current_time - state["last_scaling_time"] < state["scaling_cooldown"] or state["active_workers"] >= num_workers: + return False + + # Add a worker after a streak of successful operations + if state["success_streak"] >= 5: + print(f"Operations succeeding! Adding 1 worker, going from {state['active_workers']} to {state['active_workers'] + 1}") + + # Create new worker + if state["running"]: + new_task = asyncio.create_task(worker()) + state["worker_tasks"].append(new_task) + state["active_workers"] += 1 + state["success_streak"] = 0 + state["last_scaling_time"] = current_time + return True + + return False + + async def is_rate_limit_error(error): + """Determine if an error is due to rate limiting""" + # Check for common rate limit error patterns + if isinstance(error, modal.exception.Error): + error_msg = str(error).lower() + rate_limit_indicators = ["rate limit", "too many requests", "429", "throttle", "quota exceeded", "capacity", "limit exceeded"] + return any(indicator in error_msg for indicator in rate_limit_indicators) + return False + + async def process_example(example, attempt, current_task): try: result = await run_agent_modal.remote.aio(example) if result is None: print(f"Warning: Null result for {example.instance_id}") - return {"instance_id": example.instance_id, "status": "error", "error_info": {"error_type": "NullResult", "error_message": "Process returned None"}} + return {"status": "error", "instance_id": example.instance_id, "error_info": {"error_type": "NullResult", "error_message": "Process returned None"}} + + # Increment success streak and potentially scale up + async with state_lock: + state["success_streak"] += 1 + + if state["success_streak"] % 5 == 0: # Check after every 5 successes + await scale_up_worker() + return result except Exception as e: @@ -56,51 +140,86 @@ async def process_example(example, attempt): print(f"Error processing {example.instance_id} (attempt {attempt + 1}):") print(f"Type: {error_type}") print(f"Message: {str(e)}") - print("Traceback:") - print("".join(error_info["traceback"])) + + # Check if this is a rate limit error + if await is_rate_limit_error(e): + print(f"Rate limit detected on task for {example.instance_id}") + + # Scale down by removing this specific worker + scaled_down = await scale_down_worker(current_task) + + # If we're removing this worker, we need to requeue the task for another worker + if scaled_down: + # Requeue this example with the same attempt count (not incrementing) + await queue.put((example, attempt)) + return None + + # Otherwise add a small delay before retrying + await asyncio.sleep(2 * (attempt + 1)) # Exponential backoff if attempt < max_retries: await queue.put((example, attempt + 1)) return None - return {"instance_id": example.instance_id, "status": "error", "error_info": error_info} + return {"status": "error", "instance_id": example.instance_id, "error_info": error_info} async def worker(): - while True: + # Store this task reference to allow targeted cancellation + current_task = asyncio.current_task() + + while state["running"]: try: - example, attempt = await queue.get() + # Use a timeout to allow worker to check if it should exit + try: + example, attempt = await asyncio.wait_for(queue.get(), timeout=1.0) + except asyncio.TimeoutError: + continue if example.instance_id in results: queue.task_done() continue + print(f"Processing example {example.instance_id}") + process_result = await process_example(example, attempt, current_task) - result = await process_example(example, attempt) - - if result is not None: - results[example.instance_id] = result + # If we're still processing this task (not requeued due to rate limiting) + if process_result is not None: + results[example.instance_id] = {"instance_id": example.instance_id, **process_result} + print(f"Processed example {example.instance_id}") + queue.task_done() - queue.task_done() + # If None is returned, the task was requeued due to rate limiting + # and this worker is being shut down, so exit the loop + else: + print(f"Task for {example.instance_id} has been requeued") + queue.task_done() + if current_task not in state["worker_tasks"]: + break + except asyncio.CancelledError: + # Handle graceful cancellation + print("Worker task cancelled") + break except Exception as e: print(f"Worker error: {str(e)}") traceback.print_exc() queue.task_done() - # Start workers - workers = [asyncio.create_task(worker()) for _ in range(num_workers)] + # Start initial workers + state["worker_tasks"] = [asyncio.create_task(worker()) for _ in range(num_workers)] # Wait for queue to be fully processed await queue.join() - # Cancel workers - for w in workers: + # Mark as not running and cancel remaining workers + state["running"] = False + for w in state["worker_tasks"]: w.cancel() # Wait for all workers to be cancelled - await asyncio.gather(*workers, return_exceptions=True) + await asyncio.gather(*state["worker_tasks"], return_exceptions=True) # Return results in the same order as input examples - return [results[example.instance_id] for example in examples] + return [results.get(example.instance_id, {"instance_id": example.instance_id, "status": "missing"}) for example in examples] def process_batch_local(examples: list[SweBenchExample], num_workers=5, codebases: dict[str, Codebase] = {}): @@ -171,7 +290,7 @@ async def run_eval( predictions_dir.mkdir(exist_ok=True, parents=True) # Create a timestamp for this run - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + timestamp = time.strftime("%Y-%m-%d %H:%M %Z", time.localtime(time.time())) # Process all examples in parallel batches if local: From fc318679344b95f62d008b75551fcb8ae3f5c314 Mon Sep 17 00:00:00 2001 From: jemeza-codegen <165736868+jemeza-codegen@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:04:04 -0800 Subject: [PATCH 20/66] chore: allows evaluator to run on existing predictions (#734) # Motivation Allows evaluation to be run on an existing predictions jsonl file. # Content - modified logic that loads predictions to check for a consolidated jsonl file before creating one. # Testing Tested by running locally # Please check the following before marking your PR as ready for review - [x] I have added tests for my changes - [X] I have updated the documentation or added new documentation as needed --- .../examples/swebench_agent_run/run_eval.py | 6 ++-- src/codegen/extensions/swebench/report.py | 34 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/codegen-examples/examples/swebench_agent_run/run_eval.py b/codegen-examples/examples/swebench_agent_run/run_eval.py index 65d4b1518..92752d976 100644 --- a/codegen-examples/examples/swebench_agent_run/run_eval.py +++ b/codegen-examples/examples/swebench_agent_run/run_eval.py @@ -278,14 +278,14 @@ async def run_eval( "verified": SWEBenchDataset.VERIFIED, } dataset_enum = dataset_dict[dataset] - print(repo) + examples = get_swe_bench_examples(dataset=dataset_enum, length=length, instance_id=instance_id, repo=repo) - print(f"Examples:\n{'\n'.join([f'{e.instance_id} - {e.repo} - {e.base_commit}' for e in examples])}") try: if use_existing_preds is None: + print(f"Repo: {repo}") + print(f"Examples:\n{'\n'.join([f'{e.instance_id} - {e.repo} - {e.base_commit}' for e in examples])}") print(f"Processing {len(examples)} examples...") - # Create output directory if it doesn't exist predictions_dir.mkdir(exist_ok=True, parents=True) diff --git a/src/codegen/extensions/swebench/report.py b/src/codegen/extensions/swebench/report.py index a2b624bb5..a373e87e1 100755 --- a/src/codegen/extensions/swebench/report.py +++ b/src/codegen/extensions/swebench/report.py @@ -113,6 +113,8 @@ def generate_report(predictions_dir: Path, logs_dir: Path, dataset: SWEBenchData print(f"Directory does not exist: {predictions_dir}") return 1 + predictions_jsonl = predictions_dir / "all_preds.jsonl" + existing_preds = predictions_jsonl.exists() prediction_files = list(predictions_dir.glob("*.json")) print(f"Found {len(prediction_files)} prediction files") @@ -126,29 +128,27 @@ def generate_report(predictions_dir: Path, logs_dir: Path, dataset: SWEBenchData except json.JSONDecodeError: print(f"Error reading JSON from {file_path}") continue + if not existing_preds: + if not predictions: + print("No valid predictions found") + return 1 - print(f"Successfully loaded {len(predictions)} predictions") + print(f"Successfully loaded {len(predictions)} predictions") - if predictions: - # Create predictions JSONL file predictions_jsonl = preds_to_jsonl(predictions, predictions_dir) - print(f"\nCreated predictions JSONL: {predictions_jsonl}") - # Setup log directory - log_dir = logs_dir / "results" - log_dir.mkdir(exist_ok=True, parents=True) - print(f"Using log directory: {log_dir}") + # Setup log directory + log_dir = logs_dir / "results" + log_dir.mkdir(exist_ok=True, parents=True) + print(f"Using log directory: {log_dir}") - # Run evaluations - run_evals(predictions_jsonl, logs_dir, dataset, run_id) + # Run evaluations + run_evals(predictions_jsonl, logs_dir, dataset, run_id) - # Get and display report - report = get_report(predictions_jsonl, logs_dir) + # Get and display report + report = get_report(predictions_jsonl, logs_dir) - # Update prediction JSONs with results - predictions = update_pred_json(predictions, report, predictions_dir) - else: - print("No valid predictions found") - return 1 + # Update prediction JSONs with results + predictions = update_pred_json(predictions, report, predictions_dir) return 0 From cf4522146a5a6566a139635439e39322ae16dfeb Mon Sep 17 00:00:00 2001 From: Edo Pujol Date: Tue, 4 Mar 2025 17:10:45 -0500 Subject: [PATCH 21/66] feat: Better search tool (#739) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --------- Co-authored-by: kopekC <28070492+kopekC@users.noreply.github.com> --- src/codegen/extensions/index/file_index.py | 163 ++++++++++++++++- src/codegen/extensions/langchain/tools.py | 158 ++++++++++++++--- src/codegen/extensions/tools/search.py | 185 +++++++++----------- tests/unit/codegen/extensions/test_tools.py | 103 ----------- 4 files changed, 373 insertions(+), 236 deletions(-) diff --git a/src/codegen/extensions/index/file_index.py b/src/codegen/extensions/index/file_index.py index 6672221c4..a76e62d5e 100644 --- a/src/codegen/extensions/index/file_index.py +++ b/src/codegen/extensions/index/file_index.py @@ -2,7 +2,9 @@ import pickle from pathlib import Path +from typing import Optional +import modal import numpy as np import tiktoken from openai import OpenAI @@ -26,6 +28,7 @@ class FileIndex(CodeIndex): EMBEDDING_MODEL = "text-embedding-3-small" MAX_TOKENS = 8000 BATCH_SIZE = 100 + USE_MODAL_DICT = True # Flag to control whether to use Modal Dict def __init__(self, codebase: Codebase): """Initialize the file index. @@ -37,10 +40,87 @@ def __init__(self, codebase: Codebase): self.client = OpenAI() self.encoding = tiktoken.get_encoding("cl100k_base") + def set_use_modal_dict(self, use_modal: bool) -> None: + """Set whether to use Modal Dict for storage. + + Args: + use_modal: Whether to use Modal Dict for storage + """ + self.USE_MODAL_DICT = use_modal + logger.info(f"Modal Dict storage {'enabled' if use_modal else 'disabled'}") + @property def save_file_name(self) -> str: return "file_index_{commit}.pkl" + @property + def modal_dict_id(self) -> str: + """Get the Modal Dict ID based on the same naming convention as the pickle file.""" + if not self.commit_hash: + return "file_index_latest" + return f"file_index_{self.commit_hash}" + + def delete_modal_dict(self) -> bool: + """Delete the Modal Dict storage for this index. + + Returns: + bool: True if successfully deleted, False otherwise + """ + if not self.USE_MODAL_DICT: + logger.warning("Modal Dict storage is disabled") + return False + + try: + dict_id = self.modal_dict_id + logger.info(f"Deleting Modal Dict: {dict_id}") + + # Check if the dict exists before trying to delete + try: + # Use modal.Dict.delete to properly delete the dict + modal.Dict.delete(dict_id) + logger.info(f"Successfully deleted Modal Dict: {dict_id}") + return True + except Exception as e: + logger.info(f"Modal Dict {dict_id} does not exist or cannot be deleted: {e}") + return False + except Exception as e: + logger.exception(f"Failed to delete Modal Dict: {e}") + return False + + def modal_dict_exists(self, commit_hash: Optional[str] = None) -> bool: + """Check if a Modal Dict exists for a specific commit. + + Args: + commit_hash: The commit hash to check, or None to use the current commit + + Returns: + bool: True if the Modal Dict exists, False otherwise + """ + if not self.USE_MODAL_DICT: + return False + + try: + # Use provided commit hash or current one + old_commit = self.commit_hash + if commit_hash is not None: + self.commit_hash = commit_hash + + dict_id = self.modal_dict_id + + # Restore original commit hash + if commit_hash is not None: + self.commit_hash = old_commit + + try: + # Try to access the dict - this will raise an exception if it doesn't exist + modal_dict = modal.Dict.from_name(dict_id, create_if_missing=False) + # Check if our data is in the dict + return "index_data" in modal_dict + except Exception: + return False + except Exception: + return False + def _split_by_tokens(self, text: str) -> list[str]: """Split text into chunks that fit within token limit.""" tokens = self.encoding.encode(text) @@ -135,17 +215,69 @@ def _get_changed_items(self) -> set[File]: return changed_files def _save_index(self, path: Path) -> None: - """Save index data to disk.""" + """Save index data to disk and optionally to Modal Dict.""" + # Save to local pickle file with open(path, "wb") as f: pickle.dump({"E": self.E, "items": self.items, "commit_hash": self.commit_hash}, f) + # Save to Modal Dict if enabled + if self.USE_MODAL_DICT: + try: + dict_id = self.modal_dict_id + logger.info(f"Saving index to Modal Dict: {dict_id}") + + # Convert numpy arrays to lists for JSON serialization + modal_data = {"E": self.E.tolist() if self.E is not None else None, "items": self.items.tolist() if self.items is not None else None, "commit_hash": self.commit_hash} + + # Create or update Modal Dict + # Note: from_name is lazy, so we need to explicitly set the data + modal_dict = modal.Dict.from_name(dict_id, create_if_missing=True) + modal_dict["index_data"] = modal_data + + logger.info(f"Successfully saved index to Modal Dict: {dict_id}") + except Exception as e: + logger.exception(f"Failed to save index to Modal Dict: {e}") + def _load_index(self, path: Path) -> None: - """Load index data from disk.""" - with open(path, "rb") as f: - data = pickle.load(f) - self.E = data["E"] - self.items = data["items"] - self.commit_hash = data["commit_hash"] + """Load index data from disk or Modal Dict.""" + # Try loading from Modal Dict first if enabled + if self.USE_MODAL_DICT: + try: + dict_id = self.modal_dict_id + logger.info(f"Attempting to load index from Modal Dict: {dict_id}") + + # from_name is lazy, so we need to check if the dict exists first + try: + modal_dict = modal.Dict.from_name(dict_id, create_if_missing=False) + # Check if the dict contains our data + if "index_data" in modal_dict: + data = modal_dict["index_data"] + + # Convert lists back to numpy arrays + self.E = np.array(data["E"]) if data["E"] is not None else None + self.items = np.array(data["items"]) if data["items"] is not None else None + self.commit_hash = data["commit_hash"] + + logger.info(f"Successfully loaded index from Modal Dict: {dict_id}") + return + else: + logger.info(f"No index data found in Modal Dict: {dict_id}") + except Exception as e: + logger.warning(f"Modal Dict {dict_id} not found or error accessing it: {e}") + except Exception as e: + logger.warning(f"Failed to load index from Modal Dict, falling back to local file: {e}") + + # Fall back to loading from local file + try: + with open(path, "rb") as f: + data = pickle.load(f) + self.E = data["E"] + self.items = data["items"] + self.commit_hash = data["commit_hash"] + logger.info(f"Loaded index from local file: {path}") + except Exception as e: + logger.exception(f"Failed to load index from local file: {e}") + raise def similarity_search(self, query: str, k: int = 5) -> list[tuple[File, float]]: """Find the k most similar files to a query. @@ -216,3 +348,20 @@ def update(self) -> None: # Update commit hash self.commit_hash = self._get_current_commit() + + # Save updated index to Modal Dict if enabled + if self.USE_MODAL_DICT and (num_updated > 0 or num_added > 0): + try: + dict_id = self.modal_dict_id + logger.info(f"Updating index in Modal Dict: {dict_id}") + + # Convert numpy arrays to lists for JSON serialization + modal_data = {"E": self.E.tolist() if self.E is not None else None, "items": self.items.tolist() if self.items is not None else None, "commit_hash": self.commit_hash} + + # Create or update Modal Dict + modal_dict = modal.Dict.from_name(dict_id, create_if_missing=True) + modal_dict["index_data"] = modal_data + + logger.info(f"Successfully updated index in Modal Dict: {dict_id}") + except Exception as e: + logger.exception(f"Failed to update index in Modal Dict: {e}") diff --git a/src/codegen/extensions/langchain/tools.py b/src/codegen/extensions/langchain/tools.py index f4fc68471..acfbdaf59 100644 --- a/src/codegen/extensions/langchain/tools.py +++ b/src/codegen/extensions/langchain/tools.py @@ -110,25 +110,111 @@ def _run(self, dirpath: str = "./", depth: int = 1) -> str: class SearchInput(BaseModel): - """Input for searching the codebase.""" - query: str = Field( ..., - description="The search query to find in the codebase. When ripgrep is available, this will be passed as a ripgrep pattern. " - "For regex searches, set use_regex=True. Ripgrep is the preferred method.", + description="""The text or pattern to search for in the codebase. + + For simple text search (use_regex=False): + - Uses ripgrep's fixed-strings mode (--fixed-strings) + - Case-insensitive matching (--ignore-case) + - All characters are treated literally, including special regex characters + - Exact string matching (no regex interpretation) + + For regex search (use_regex=True): + - Full regex pattern support + - Case-sensitive by default + - Special characters have regex meaning and need proper escaping + - Uses ripgrep's default regex mode + + If no exact matches are found, automatically falls back to semantic search + to find relevant code even without exact text matches.""", + ) + + target_directories: Optional[list[str]] = Field( + default=None, + description="""Optional list of directories to limit the search scope. + + - Paths should be relative to the workspace root + - Multiple directories are searched in parallel + - If None, searches the entire codebase + + Example: ["src/frontend", "tests/unit"]""", + ) + + file_extensions: Optional[list[str]] = Field( + default=None, + description="""Optional list of file extensions to filter the search. + + - Include the dot in extensions (e.g. ['.py', '.ts']) + - Multiple extensions are combined with OR logic + - If None, searches all file types + - Binary files are automatically excluded + + Example: [".py", ".tsx", ".md"]""", + ) + + page: int = Field( + default=1, + description="""Page number for paginated results (1-based indexing). + + - Use with files_per_page to navigate large result sets + - If page exceeds available pages, returns last available page + - Note: When falling back to semantic search, pagination is not supported + + Example: page=2 with files_per_page=10 shows files 11-20""", + ) + + files_per_page: int = Field( + default=10, + description="""Number of files to show per page. + + - Each file can contain multiple matching lines + - Reasonable values are between 5 and 50 + - Larger values may impact performance + - When falling back to semantic search, this becomes the number of semantic results + + Example: files_per_page=20 shows up to 20 files with matches""", + ) + + use_regex: bool = Field( + default=False, + description="""Whether to treat the query as a regex pattern. + + - False (default): Simple text search, case-insensitive + - True: Full regex syntax, case-sensitive + - Invalid regex patterns will return an error + - Note: Semantic fallback is used regardless of this setting when no matches found + + Example: Set to True to use patterns like "test_.*_func.*" """, ) - target_directories: Optional[list[str]] = Field(default=None, description="Optional list of directories to search in") - file_extensions: Optional[list[str]] = Field(default=None, description="Optional list of file extensions to search (e.g. ['.py', '.ts'])") - page: int = Field(default=1, description="Page number to return (1-based, default: 1)") - files_per_page: int = Field(default=10, description="Number of files to return per page (default: 10)") - use_regex: bool = Field(default=False, description="Whether to treat query as a regex pattern (default: False)") class SearchTool(BaseTool): """Tool for searching the codebase.""" name: ClassVar[str] = "search" - description: ClassVar[str] = "Search the codebase using text search or regex pattern matching" + description: ClassVar[str] = r"""Search the codebase using text search or regex pattern matching. + + This tool provides powerful text-based search capabilities across your codebase, + with support for both simple text matching and regular expressions. It uses ripgrep + when available for high-performance searches. + + If no exact matches are found, automatically falls back to semantic search to find + relevant code even without exact text matches. + + Features: + - Plain text or regex pattern matching + - Directory and file type filtering + - Paginated results for large codebases + - Case-insensitive by default for simple text searches + - Semantic fallback for finding related code + + Example queries: + 1. Simple text: "function calculateTotal" (matches exactly, case-insensitive) + 2. Regex: "def.*calculate.*\(.*\)" (with use_regex=True) + 3. File-specific: "TODO" with file_extensions=[".py", ".ts"] + 4. Directory-specific: "api" with target_directories=["src/backend"] + """ args_schema: ClassVar[type[BaseModel]] = SearchInput codebase: Codebase = Field(exclude=True) @@ -151,7 +237,27 @@ class EditFileTool(BaseTool): """Tool for editing files.""" name: ClassVar[str] = "edit_file" - description: ClassVar[str] = "Edit a file by replacing its entire content. This tool should only be used for replacing entire file contents." + description: ClassVar[str] = r""" +Edit a file by replacing its entire content. This tool should only be used for replacing entire file contents. +Input for searching the codebase. + + This tool provides powerful text-based search capabilities across your codebase, + with support for both simple text matching and regular expressions. It uses ripgrep + when available for high-performance searches, falling back to Python's regex engine + when necessary. + + Features: + - Plain text or regex pattern matching + - Directory and file type filtering + - Paginated results for large codebases + - Case-insensitive by default for simple text searches + + Example queries: + 1. Simple text: "function calculateTotal" (matches exactly, case-insensitive) + 2. Regex: "def.*calculate.*\(.*\)" (with use_regex=True) + 3. File-specific: "TODO" with file_extensions=[".py", ".ts"] + 4. Directory-specific: "api" with target_directories=["src/backend"] + """ args_schema: ClassVar[type[BaseModel]] = EditFileInput codebase: Codebase = Field(exclude=True) @@ -741,7 +847,7 @@ def get_workspace_tools(codebase: Codebase) -> list["BaseTool"]: RunBashCommandTool(), # Note: This tool doesn't need the codebase SearchTool(codebase), # SemanticEditTool(codebase), - SemanticSearchTool(codebase), + # SemanticSearchTool(codebase), ViewFileTool(codebase), RelaceEditTool(codebase), ReflectionTool(codebase), @@ -761,14 +867,26 @@ def get_workspace_tools(codebase: Codebase) -> list["BaseTool"]: class ReplacementEditInput(BaseModel): - """Input for regex-based replacement editing.""" - - filepath: str = Field(..., description="Path to the file to edit") - pattern: str = Field(..., description="Regex pattern to match") - replacement: str = Field(..., description="Replacement text (can include regex groups)") - start: int = Field(default=1, description="Starting line number (1-indexed, inclusive). Default is 1.") - end: int = Field(default=-1, description="Ending line number (1-indexed, inclusive). Default is -1 (end of file).") - count: Optional[int] = Field(default=None, description="Maximum number of replacements. Default is None (replace all).") + filepath: str = Field(..., description="Path to the file to edit relative to the workspace root. The file must exist and be a text file.") + pattern: str = Field( + ..., + description="Regular expression pattern to match text that should be replaced. Supports all Python regex syntax including capture groups (\1, \2, etc). The pattern is compiled with re.MULTILINE flag by default.", + ) + replacement: str = Field( + ..., + description="Text to replace matched patterns with. Can reference regex capture groups using \1, \2, etc. If using regex groups in pattern, make sure to preserve them in replacement if needed.", + ) + start: int = Field( + default=1, description="Starting line number (1-indexed, inclusive) to begin replacements from. Use this with 'end' to limit changes to a specific region. Default is 1 (start of file)." + ) + end: int = Field( + default=-1, + description="Ending line number (1-indexed, inclusive) to stop replacements at. Use -1 to indicate end of file. Use this with 'start' to limit changes to a specific region. Default is -1 (end of file).", + ) + count: Optional[int] = Field( + default=None, + description="Maximum number of replacements to make. Use None to replace all occurrences (default), or specify a number to limit replacements. Useful when you only want to replace the first N occurrences.", + ) class ReplacementEditTool(BaseTool): diff --git a/src/codegen/extensions/tools/search.py b/src/codegen/extensions/tools/search.py index 4bcdfb74e..8083e7db8 100644 --- a/src/codegen/extensions/tools/search.py +++ b/src/codegen/extensions/tools/search.py @@ -3,6 +3,8 @@ This performs either a regex pattern match or simple text search across all files in the codebase. Each matching line will be returned with its line number. Results are paginated with a default of 10 files per page. + +If no exact matches are found, falls back to semantic search to find relevant code. """ import os @@ -15,6 +17,7 @@ from codegen.sdk.core.codebase import Codebase from .observation import Observation +from .semantic_search import SearchResult, semantic_search class SearchMatch(Observation): @@ -125,7 +128,7 @@ def _search_with_ripgrep( This is faster than the Python implementation, especially for large codebases. """ # Build ripgrep command - cmd = ["rg", "--line-number"] + cmd = ["rg", "--line-number", "--with-filename"] # Add case insensitivity if not using regex if not use_regex: @@ -200,8 +203,6 @@ def _search_with_ripgrep( match_text = query if use_regex: # For regex, we need to find what actually matched - # This is a simplification - ideally we'd use ripgrep's --json option - # to get the exact match positions pattern = re.compile(query) match_obj = pattern.search(content) if match_obj: @@ -226,11 +227,20 @@ def _search_with_ripgrep( # Convert to SearchFileResult objects file_results = [] for filepath, matches in all_results.items(): + # Sort matches by line number and deduplicate + unique_matches = [] + seen = set() + for match in sorted(matches, key=lambda x: x.line_number): + key = (match.line_number, match.match) + if key not in seen: + seen.add(key) + unique_matches.append(match) + file_results.append( SearchFileResult( status="success", filepath=filepath, - matches=sorted(matches, key=lambda x: x.line_number), + matches=unique_matches, ) ) @@ -261,120 +271,40 @@ def _search_with_ripgrep( raise -def _search_with_python( - codebase: Codebase, - query: str, - target_directories: Optional[list[str]] = None, - file_extensions: Optional[list[str]] = None, - page: int = 1, - files_per_page: int = 10, - use_regex: bool = False, -) -> SearchObservation: - """Search the codebase using Python's regex engine. - - This is a fallback for when ripgrep is not available. - """ - # Validate pagination parameters - if page < 1: - page = 1 - if files_per_page < 1: - files_per_page = 10 - - # Prepare the search pattern - if use_regex: - try: - pattern = re.compile(query) - except re.error as e: - return SearchObservation( - status="error", - error=f"Invalid regex pattern: {e!s}", - query=query, - page=page, - total_pages=0, - total_files=0, - files_per_page=files_per_page, - results=[], - ) - else: - # For non-regex searches, escape special characters and make case-insensitive - pattern = re.compile(re.escape(query), re.IGNORECASE) - - # Handle file extensions - extensions = file_extensions if file_extensions is not None else "*" - - all_results = [] - for file in codebase.files(extensions=extensions): - # Skip if file doesn't match target directories - if target_directories and not any(file.filepath.startswith(d) for d in target_directories): - continue - - # Skip binary files - try: - content = file.content - except ValueError: # File is binary - continue - - file_matches = [] - # Split content into lines and store with line numbers (1-based) - lines = enumerate(content.splitlines(), 1) - - # Search each line for the pattern - for line_number, line in lines: - match = pattern.search(line) - if match: - file_matches.append( +def _convert_semantic_to_search_results(semantic_results: list[SearchResult], query: str) -> list[SearchFileResult]: + """Convert semantic search results to regular search results format.""" + file_results = [] + for result in semantic_results: + file_results.append( + SearchFileResult( + status="success", + filepath=result.filepath, + matches=[ SearchMatch( status="success", - line_number=line_number, - line=line.strip(), - match=match.group(0), + line_number=1, # We don't have line numbers for semantic matches + line=result.preview, + match=query, ) - ) - - if file_matches: - all_results.append( - SearchFileResult( - status="success", - filepath=file.filepath, - matches=sorted(file_matches, key=lambda x: x.line_number), - ) + ], ) - - # Sort all results by filepath - all_results.sort(key=lambda x: x.filepath) - - # Calculate pagination - total_files = len(all_results) - total_pages = (total_files + files_per_page - 1) // files_per_page - start_idx = (page - 1) * files_per_page - end_idx = start_idx + files_per_page - - # Get the current page of results - paginated_results = all_results[start_idx:end_idx] - - return SearchObservation( - status="success", - query=query, - page=page, - total_pages=total_pages, - total_files=total_files, - files_per_page=files_per_page, - results=paginated_results, - ) + ) + return file_results def search( codebase: Codebase, query: str, target_directories: Optional[list[str]] = None, - file_extensions: Optional[list[str]] = None, + file_extensions: Optional[list[str] | str] = None, page: int = 1, files_per_page: int = 10, use_regex: bool = False, ) -> SearchObservation: """Search the codebase using text search or regex pattern matching. - Uses ripgrep for performance when available, with fallback to Python's regex engine. + Uses ripgrep for performance when available. If no exact matches are found, + falls back to semantic search to find relevant code. If use_regex is True, performs a regex pattern match on each line. Otherwise, performs a case-insensitive text search. Returns matching lines with their line numbers, grouped by file. @@ -393,9 +323,52 @@ def search( Returns: SearchObservation containing search results with matches and their sources """ - # Try to use ripgrep first try: - return _search_with_ripgrep(codebase, query, target_directories, file_extensions, page, files_per_page, use_regex) + # Try ripgrep first + result = _search_with_ripgrep(codebase, query, target_directories, file_extensions, page, files_per_page, use_regex) + + # If no results found, try semantic search + if not result.results: + semantic_results = semantic_search(codebase, query, k=files_per_page) + if semantic_results.status == "success" and semantic_results.results: + # Convert semantic results to regular search results format + file_results = _convert_semantic_to_search_results(semantic_results.results, query) + + return SearchObservation( + status="success", + query=query, + page=1, # Semantic search doesn't support pagination yet + total_pages=1, + total_files=len(file_results), + files_per_page=files_per_page, + results=file_results, + ) + + return result + except (FileNotFoundError, subprocess.SubprocessError): - # Fall back to Python implementation if ripgrep fails or isn't available - return _search_with_python(codebase, query, target_directories, file_extensions, page, files_per_page, use_regex) + # If ripgrep fails, try semantic search directly + semantic_results = semantic_search(codebase, query, k=files_per_page) + if semantic_results.status == "success": + file_results = _convert_semantic_to_search_results(semantic_results.results, query) + + return SearchObservation( + status="success", + query=query, + page=1, + total_pages=1, + total_files=len(file_results), + files_per_page=files_per_page, + results=file_results, + ) + else: + return SearchObservation( + status="error", + error=f"Both text search and semantic search failed: {semantic_results.error}", + query=query, + page=page, + total_pages=0, + total_files=0, + files_per_page=files_per_page, + results=[], + ) diff --git a/tests/unit/codegen/extensions/test_tools.py b/tests/unit/codegen/extensions/test_tools.py index ec394312e..23c1ebe00 100644 --- a/tests/unit/codegen/extensions/test_tools.py +++ b/tests/unit/codegen/extensions/test_tools.py @@ -260,48 +260,6 @@ def test_search_regex(codebase): assert any("def greet" in match for match in matches) -def test_search_target_directories(codebase): - """Test searching with target directory filtering.""" - # First search without filter to ensure we have results - result_all = search(codebase, "hello") - assert result_all.status == "success" - assert len(result_all.results) > 0 - - # Now search with correct target directory - result_filtered = search(codebase, "hello", target_directories=["src"]) - assert result_filtered.status == "success" - assert len(result_filtered.results) > 0 - - # Search with non-existent directory - result_none = search(codebase, "hello", target_directories=["nonexistent"]) - assert result_none.status == "success" - assert len(result_none.results) == 0 - - -def test_search_file_extensions(codebase, tmpdir): - """Test searching with file extension filtering.""" - # Add a non-Python file - js_content = "function hello() { console.log('Hello from JS!'); }" - js_file = tmpdir / "src" / "script.js" - js_file.write_text(js_content, encoding="utf-8") - - # Search all files - result_all = search(codebase, "hello") - assert result_all.status == "success" - assert len(result_all.results) > 0 - - # Search only Python files - result_py = search(codebase, "hello", file_extensions=[".py"]) - assert result_py.status == "success" - assert all(file_result.filepath.endswith(".py") for file_result in result_py.results) - - # Search only JS files - result_js = search(codebase, "hello", file_extensions=[".js"]) - assert result_js.status == "success" - if len(result_js.results) > 0: # Only if JS file was properly added to codebase - assert all(file_result.filepath.endswith(".js") for file_result in result_js.results) - - def test_search_pagination(codebase, tmpdir): """Test search pagination.""" # Create multiple files to test pagination @@ -332,21 +290,6 @@ def test_search_pagination(codebase, tmpdir): assert not page1_files.intersection(page2_files) -def test_search_invalid_regex(codebase): - """Test search with invalid regex pattern.""" - result = search(codebase, "(unclosed", use_regex=True) - assert result.status == "error" - # Check for either Python's error message or ripgrep's error message - assert any( - error_msg in result.error - for error_msg in [ - "Invalid regex pattern", # Python error message - "regex parse error", # ripgrep error message - "unclosed group", # Common error description - ] - ) - - def test_search_fallback(codebase, monkeypatch): """Test fallback to Python implementation when ripgrep fails.""" @@ -409,52 +352,6 @@ def mock_subprocess_run(*args, **kwargs): assert ripgrep_called, "Ripgrep was not used for the search" -def test_search_implementation_consistency(codebase, monkeypatch): - """Test that ripgrep and Python implementations produce consistent results.""" - from codegen.extensions.tools.search import _search_with_python, _search_with_ripgrep - - # Skip test if ripgrep is not available - try: - subprocess.run(["rg", "--version"], capture_output=True, check=False) - except FileNotFoundError: - pytest.skip("Ripgrep not available, skipping consistency test") - - # Simple search that should work in both implementations - query = "hello" - - # Get results from both implementations - ripgrep_result = _search_with_ripgrep(codebase, query) - python_result = _search_with_python(codebase, query) - - # Compare basic metadata - assert ripgrep_result.status == python_result.status - assert ripgrep_result.query == python_result.query - - # Compare file paths found (order might differ) - ripgrep_files = {r.filepath for r in ripgrep_result.results} - python_files = {r.filepath for r in python_result.results} - - # There might be slight differences in which files are found due to how ripgrep handles - # certain files, so we'll check for substantial overlap rather than exact equality - common_files = ripgrep_files.intersection(python_files) - assert len(common_files) > 0, "No common files found between ripgrep and Python implementations" - - # For common files, compare the line numbers found - for filepath in common_files: - # Find the corresponding file results - ripgrep_file_result = next(r for r in ripgrep_result.results if r.filepath == filepath) - python_file_result = next(r for r in python_result.results if r.filepath == filepath) - - # Compare line numbers - there might be slight differences in how matches are found - ripgrep_lines = {m.line_number for m in ripgrep_file_result.matches} - python_lines = {m.line_number for m in python_file_result.matches} - - # Check for substantial overlap in line numbers - common_lines = ripgrep_lines.intersection(python_lines) - if ripgrep_lines and python_lines: # Only check if both found matches - assert len(common_lines) > 0, f"No common line matches found in {filepath}" - - def test_edit_file(codebase): """Test editing a file.""" result = edit_file(codebase, "src/main.py", "print('edited')") From b61ba9d167f1075b3e7b4ece5cd19e5231889f80 Mon Sep 17 00:00:00 2001 From: tomcodgen Date: Tue, 4 Mar 2025 23:35:18 +0100 Subject: [PATCH 22/66] [CG-10935] fix: issues with unpacking (#724) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --------- Co-authored-by: tomcodgen <191515280+tomcodgen@users.noreply.github.com> --- src/codegen/sdk/python/assignment.py | 6 ++++ .../sdk/python/expressions/test_unpacking.py | 30 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/codegen/sdk/python/assignment.py b/src/codegen/sdk/python/assignment.py index a85f57a82..2614b6d43 100644 --- a/src/codegen/sdk/python/assignment.py +++ b/src/codegen/sdk/python/assignment.py @@ -12,6 +12,7 @@ from codegen.sdk.python.symbol import PySymbol from codegen.sdk.python.symbol_groups.comment_group import PyCommentGroup from codegen.shared.decorators.docs import noapidoc, py_apidoc +from codegen.shared.logging.get_logger import get_logger if TYPE_CHECKING: from tree_sitter import Node as TSNode @@ -20,6 +21,8 @@ from codegen.sdk.core.node_id_factory import NodeId from codegen.sdk.python.statements.assignment_statement import PyAssignmentStatement +logger = get_logger(__name__) + @py_apidoc class PyAssignment(Assignment["PyAssignmentStatement"], PySymbol): @@ -152,6 +155,9 @@ def remove(self, delete_formatting: bool = True, priority: int = 0, dedupe: bool else: self.parent._values_scheduled_for_removal = [] else: + if name.source == "_": + logger.warning("Attempting to remove '_' in unpacking, command will be ignored. If you wish to remove the statement, remove the other remaining variable(s)!") + return transaction_count = self._active_transactions_on_assignment_names(TransactionPriority.Edit) throwaway = [asgnmt.name == "_" for asgnmt in self.parent.assignments].count(True) # Only edit if we didn't already omit all the other assignments, otherwise just remove the whole thing diff --git a/tests/unit/codegen/sdk/python/expressions/test_unpacking.py b/tests/unit/codegen/sdk/python/expressions/test_unpacking.py index cdf853e37..274329bea 100644 --- a/tests/unit/codegen/sdk/python/expressions/test_unpacking.py +++ b/tests/unit/codegen/sdk/python/expressions/test_unpacking.py @@ -1,5 +1,11 @@ +from typing import TYPE_CHECKING +from unittest.mock import patch + from codegen.sdk.codebase.factory.get_session import get_codebase_session +if TYPE_CHECKING: + from codegen.sdk.core.file import SourceFile + def test_remove_unpacking_assignment(tmpdir) -> None: # language=python @@ -155,3 +161,27 @@ def test_remove_unpacking_assignment_num(tmpdir) -> None: assert len(file2.symbols) == 0 assert file2.source == """""" + + +@patch("codegen.sdk.python.assignment.logger") +def test_unpacking_function_with_underscore_removal(mock_logger, tmpdir: str) -> None: + # language=python + content1 = """ + args, _ = parser.parse_known_args() ##args gets deleted + with open(args.template_path) as f: + print('test') + """ + with get_codebase_session( + tmpdir=tmpdir, + files={ + "file1.py": content1, + }, + ) as codebase: + file1: SourceFile = codebase.get_file("file1.py") + + for symbol in codebase.symbols: + if not symbol.usages: + symbol.remove() + codebase.commit() + assert len(file1.symbols) != 0 + assert mock_logger.warning.call_count == 1 From a8c10026c74b3fceba48772a2a4434583b964226 Mon Sep 17 00:00:00 2001 From: codegen-team Date: Tue, 4 Mar 2025 22:36:44 +0000 Subject: [PATCH 23/66] docs: updated API reference --- docs/api-reference/python/PyAssignment.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api-reference/python/PyAssignment.mdx b/docs/api-reference/python/PyAssignment.mdx index ad6fe66c4..074215c40 100644 --- a/docs/api-reference/python/PyAssignment.mdx +++ b/docs/api-reference/python/PyAssignment.mdx @@ -11,7 +11,7 @@ import {HorizontalDivider} from '/snippets/HorizontalDivider.mdx'; import {GithubLinkNote} from '/snippets/GithubLinkNote.mdx'; import {Attribute} from '/snippets/Attribute.mdx'; - + ### Inherits from [PySymbol](/api-reference/python/PySymbol), [Assignment](/api-reference/core/Assignment), [Symbol](/api-reference/core/Symbol), [HasValue](/api-reference/core/HasValue), [Typeable](/api-reference/core/Typeable), [Usable](/api-reference/core/Usable), [Importable](/api-reference/core/Importable), [Editable](/api-reference/core/Editable), [Expression](/api-reference/core/Expression), [HasName](/api-reference/core/HasName) @@ -291,7 +291,7 @@ Flags a Python symbol by adding a flag comment and returning a CodeFlag. ### from_named_expression Creates a MultiExpression from a Python named expression. - + remove Deletes this assignment and its related extended nodes (e.g. decorators, comments). - + Date: Tue, 4 Mar 2025 22:40:40 +0000 Subject: [PATCH 24/66] update changelog --- docs/changelog/changelog.mdx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 1cd40baab..f3ef3be22 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,14 @@ icon: "clock" iconType: "solid" --- + +### [Introduces a better search tool and dynamic scaling.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.46.0) +- Fix issues with unpacking functionality +- Implement dynamic scaling for asyncio requests +- Introduce a better search tool +- Enable evaluator to run on existing predictions + + ### [Improved bug fixes with updated dependency.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.45.1) - Update dependency to improve bug fixes From f64f45577cca20df39cfc9ef18c885059610d329 Mon Sep 17 00:00:00 2001 From: tomcodgen Date: Wed, 5 Mar 2025 19:29:53 +0100 Subject: [PATCH 25/66] [CG-10916] fix: WildcardImport error when trying to parse astropy (#754) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --------- Co-authored-by: tomcodgen <191515280+tomcodgen@users.noreply.github.com> --- src/codegen/sdk/core/import_resolution.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/codegen/sdk/core/import_resolution.py b/src/codegen/sdk/core/import_resolution.py index a824d8a72..c6d11af9d 100644 --- a/src/codegen/sdk/core/import_resolution.py +++ b/src/codegen/sdk/core/import_resolution.py @@ -706,6 +706,11 @@ def _resolved_types(self) -> Generator[ResolutionStack[Self], None, None]: def _compute_dependencies(self, usage_type: UsageKind, dest: HasName | None = None) -> None: pass + @property + @override + def filepath(self) -> str: + return self.imp.filepath + class ExternalImportResolver: def resolve(self, imp: Import) -> str | None: From 09b797a4b33634ac2f75e1f16411cf0b912b7cdb Mon Sep 17 00:00:00 2001 From: Vishal Shenoy Date: Wed, 5 Mar 2025 11:08:22 -0800 Subject: [PATCH 26/66] Github Checks (import) (#750) --- .../examples/github_checks/README.md | 106 ++++++++++++ .../examples/github_checks/app.py | 154 ++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 codegen-examples/examples/github_checks/README.md create mode 100644 codegen-examples/examples/github_checks/app.py diff --git a/codegen-examples/examples/github_checks/README.md b/codegen-examples/examples/github_checks/README.md new file mode 100644 index 000000000..cb0a87f94 --- /dev/null +++ b/codegen-examples/examples/github_checks/README.md @@ -0,0 +1,106 @@ +# Github Checks + +This application is a GitHub integration that analyzes import cycles in Python codebases. It automatically runs when a pull request is labeled and checks for potentially problematic import patterns in the modified codebase. + +## Features + +- Analyzes import relationships in Python codebases +- Detects circular import dependencies +- Identifies problematic cycles with mixed static and dynamic imports +- Automatically comments on pull requests with detailed analysis + +## How It Works + +1. The app creates a directed graph representing import relationships in the codebase + + ```python + for imp in codebase.imports: + if imp.from_file and imp.to_file: + G.add_edge( + imp.to_file.filepath, + imp.from_file.filepath, + color="red" if getattr(imp, "is_dynamic", False) else "black", + label="dynamic" if getattr(imp, "is_dynamic", False) else "static", + is_dynamic=getattr(imp, "is_dynamic", False), + ) + ``` + +1. It identifies strongly connected components (cycles) in the import graph + + ```python + cycles = [scc for scc in nx.strongly_connected_components(G) if len(scc) > 1] + ``` + +1. It specifically flags cycles that contain both static and dynamic imports + + ```python + dynamic_count = sum(1 for e in edges.values() if e["color"] == "red") + static_count = sum(1 for e in edges.values() if e["color"] == "black") + + if dynamic_count > 0 and static_count > 0: + mixed_imports[(from_file, to_file)] = { + "dynamic": dynamic_count, + "static": static_count, + "edges": edges, + } + ``` + +1. Results are posted as a comment on the pull request + + ```python + if problematic_loops: + message.append("\n### ⚠️ Problematic Import Cycles") + message.append("(Cycles with mixed static and dynamic imports)") + for i, cycle in enumerate(problematic_loops, 1): + message.append(f"\n#### Problematic Cycle #{i}") + message.append("Mixed imports:") + for (from_file, to_file), imports in cycle["mixed_imports"].items(): + message.append(f"\nFrom: `{from_file}`") + message.append(f"To: `{to_file}`") + message.append(f"- Static imports: {imports['static']}") + message.append(f"- Dynamic imports: {imports['dynamic']}") + + create_pr_comment(codebase, event.pull_request, number, "\n".join(message)) + ``` + +## Setup + +1. Ensure you have the following dependencies: + + - Python 3.13 + - Modal + - Codegen + - NetworkX + - python-dotenv + +1. Set up your environment variables in a `.env` file + + - `GITHUB_TOKEN`: Your GitHub token, configured with `repo` and `workflow` scopes + +1. Deploy the app using Modal: + + ```bash + modal deploy app.py + ``` + +## Technical Details + +The application uses Codegen to parse the codebase and a combination of NetworkX and Codegen to analyze the import relationships. The app is structured as a Modal App with a FastAPI server. +The analysis runs when a pull request is labeled (`pull_request:labeled` event). + +## Output Format + +The analysis results are posted as a markdown-formatted comment on the pull request, including: + +- Summary statistics +- Detailed cycle information +- Warning indicators for problematic import patterns + +## Learn More + +- [Codegen Documentation](https://docs.codegen.com) +- [Detecting Import Loops](https://docs.codegen.com/blog/fixing-import-loops) + +## Contributing + +Feel free to submit issues and enhancement requests! diff --git a/codegen-examples/examples/github_checks/app.py b/codegen-examples/examples/github_checks/app.py new file mode 100644 index 000000000..fe5097154 --- /dev/null +++ b/codegen-examples/examples/github_checks/app.py @@ -0,0 +1,154 @@ +import logging + +import modal +from codegen import CodegenApp, Codebase +from codegen.extensions.github.types.events.pull_request import PullRequestLabeledEvent +from codegen.extensions.tools.github.create_pr_comment import create_pr_comment +from dotenv import load_dotenv +import networkx as nx + +load_dotenv() + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +cg = CodegenApp(name="codegen-github-checks") + + +def create_graph_from_codebase(repo_path): + """Create a directed graph representing import relationships in a codebase.""" + codebase = Codebase.from_repo(repo_path) + G = nx.MultiDiGraph() + + for imp in codebase.imports: + if imp.from_file and imp.to_file: + G.add_edge( + imp.to_file.filepath, + imp.from_file.filepath, + color="red" if getattr(imp, "is_dynamic", False) else "black", + label="dynamic" if getattr(imp, "is_dynamic", False) else "static", + is_dynamic=getattr(imp, "is_dynamic", False), + ) + return G + + +def convert_all_calls_to_kwargs(codebase): + for file in codebase.files: + for function_call in file.function_calls: + function_call.convert_args_to_kwargs() + + print("All function calls have been converted to kwargs") + + +def find_import_cycles(G): + """Identify strongly connected components (cycles) in the import graph.""" + cycles = [scc for scc in nx.strongly_connected_components(G) if len(scc) > 1] + print(f"🔄 Found {len(cycles)} import cycles.") + + for i, cycle in enumerate(cycles, 1): + print(f"\nCycle #{i}: Size {len(cycle)} files") + print(f"Total number of imports in cycle: {G.subgraph(cycle).number_of_edges()}") + + print("\nFiles in this cycle:") + for file in cycle: + print(f" - {file}") + + return cycles + + +def find_problematic_import_loops(G, cycles): + """Identify cycles with both static and dynamic imports between files.""" + problematic_cycles = [] + + for i, scc in enumerate(cycles): + if i == 2: + continue + + mixed_imports = {} + for from_file in scc: + for to_file in scc: + if G.has_edge(from_file, to_file): + edges = G.get_edge_data(from_file, to_file) + dynamic_count = sum(1 for e in edges.values() if e["color"] == "red") + static_count = sum(1 for e in edges.values() if e["color"] == "black") + + if dynamic_count > 0 and static_count > 0: + mixed_imports[(from_file, to_file)] = { + "dynamic": dynamic_count, + "static": static_count, + "edges": edges, + } + + if mixed_imports: + problematic_cycles.append({"files": scc, "mixed_imports": mixed_imports, "index": i}) + + print(f"Found {len(problematic_cycles)} cycles with potentially problematic imports.") + + for i, cycle in enumerate(problematic_cycles): + print(f"\n⚠️ Problematic Cycle #{i + 1} (Index {cycle['index']}): Size {len(cycle['files'])} files") + print("\nFiles in cycle:") + for file in cycle["files"]: + print(f" - {file}") + print("\nMixed imports:") + for (from_file, to_file), imports in cycle["mixed_imports"].items(): + print(f"\n From: {from_file}") + print(f" To: {to_file}") + print(f" Static imports: {imports['static']}") + print(f" Dynamic imports: {imports['dynamic']}") + + return problematic_cycles + + +@cg.github.event("pull_request:labeled") +def handle_pr(event: PullRequestLabeledEvent): + codebase = Codebase.from_repo(event.repository.get("full_name"), commit=event.pull_request.head.sha) + + G = create_graph_from_codebase(event.repository.get("full_name")) + cycles = find_import_cycles(G) + problematic_loops = find_problematic_import_loops(G, cycles) + + # Build comment message + message = ["### Import Cycle Analysis - GitHub Check\n"] + + if problematic_loops: + message.append("\n### ⚠️ Potentially Problematic Import Cycles") + message.append("Cycles with mixed static and dynamic imports, which might recquire attention.") + for i, cycle in enumerate(problematic_loops, 1): + message.append(f"\n#### Problematic Cycle {i}") + for (from_file, to_file), imports in cycle["mixed_imports"].items(): + message.append(f"\nFrom: `{from_file}`") + message.append(f"To: `{to_file}`") + message.append(f"- Static imports: {imports['static']}") + message.append(f"- Dynamic imports: {imports['dynamic']}") + else: + message.append("\nNo problematic import cycles found! 🎉") + + create_pr_comment( + codebase, + event.pull_request.number, + "\n".join(message), + ) + + return { + "message": "PR event handled", + "num_files": len(codebase.files), + "num_functions": len(codebase.functions), + } + + +base_image = ( + modal.Image.debian_slim(python_version="3.13") + .apt_install("git") + .pip_install( + "codegen", + ) +) + +app = modal.App("codegen-test") + + +@app.function(image=base_image, secrets=[modal.Secret.from_dotenv()]) +@modal.asgi_app() +def fastapi_app(): + print("Starting codegen fastapi app") + return cg.app From 16a114b45679fe08830129a96007fc70d3e82115 Mon Sep 17 00:00:00 2001 From: Edo Pujol Date: Wed, 5 Mar 2025 17:21:12 -0500 Subject: [PATCH 27/66] fix tests (#763) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --------- Co-authored-by: kopekC <28070492+kopekC@users.noreply.github.com> --- tests/unit/codegen/extensions/test_tools.py | 135 ++------------------ 1 file changed, 8 insertions(+), 127 deletions(-) diff --git a/tests/unit/codegen/extensions/test_tools.py b/tests/unit/codegen/extensions/test_tools.py index 23c1ebe00..70bf68512 100644 --- a/tests/unit/codegen/extensions/test_tools.py +++ b/tests/unit/codegen/extensions/test_tools.py @@ -1,7 +1,5 @@ """Tests for codebase tools.""" -import subprocess - import pytest from codegen.extensions.tools import ( @@ -17,7 +15,6 @@ replacement_edit, reveal_symbol, run_codemod, - search, semantic_edit, semantic_search, view_file, @@ -138,10 +135,12 @@ def test_view_file_pagination(large_codebase): result = view_file(large_codebase, "src/large_file.py", start_line=350) assert result.status == "success" assert result.start_line == 350 - assert result.has_more is True # File has 2010 lines, so there should be more content + # File has 2010 lines, so there should be more content + assert result.has_more is True assert "def method_69" in result.content # Regular method assert "def class_method_80" in result.content # Class method at 80 - assert result.end_line == 599 # Should show 250 lines from start (350 to 599) + # Should show 250 lines from start (350 to 599) + assert result.end_line == 599 # Test custom max_lines result = view_file(large_codebase, "src/large_file.py", max_lines=100) @@ -189,7 +188,8 @@ def test_view_file_pagination_edge_cases(large_codebase): result = view_file(large_codebase, "src/large_file.py", start_line=200, end_line=2000) assert result.status == "success" assert result.start_line == 200 - assert result.end_line == min(200 + 250 - 1, 2010) # Should respect max_lines and file length + # Should respect max_lines and file length + assert result.end_line == min(200 + 250 - 1, 2010) # Test negative start_line (should default to 1) result = view_file(large_codebase, "src/large_file.py", start_line=-10) @@ -205,7 +205,8 @@ def test_list_directory(codebase): create_file(codebase, "src/core/models.py", "") create_file(codebase, "src/utils.py", "") - result = list_directory(codebase, "./", depth=2) # Ensure we get nested structure + # Ensure we get nested structure + result = list_directory(codebase, "./", depth=2) assert result.status == "success" # Check directory structure @@ -232,126 +233,6 @@ def test_list_directory(codebase): assert expected_tree in rendered.strip() -def test_search(codebase): - """Test searching the codebase.""" - result = search(codebase, "hello") - assert result.status == "success" - assert len(result.results) > 0 - - # Check that we found the right content - assert any("hello" in match.match.lower() for file_result in result.results for match in file_result.matches) - - # Check pagination info - assert result.page == 1 - assert result.total_pages >= 1 - assert result.files_per_page == 10 - - -def test_search_regex(codebase): - """Test searching with regex.""" - # Search for function definitions - result = search(codebase, r"def\s+\w+", use_regex=True) - assert result.status == "success" - assert len(result.results) > 0 - - # Should find both 'def hello' and 'def greet' - matches = [match.line for file_result in result.results for match in file_result.matches] - assert any("def hello" in match for match in matches) - assert any("def greet" in match for match in matches) - - -def test_search_pagination(codebase, tmpdir): - """Test search pagination.""" - # Create multiple files to test pagination - files_dict = {} - for i in range(15): # Create enough files to span multiple pages - content = f"def function_{i}():\n print('Hello from function {i}!')" - files_dict[f"src/file_{i}.py"] = content - - # Create a new codebase with all the files - with get_codebase_session(tmpdir=tmpdir, files=files_dict) as pagination_codebase: - # Search with default pagination (page 1) - result_page1 = search(pagination_codebase, "Hello", files_per_page=5) - assert result_page1.status == "success" - assert result_page1.page == 1 - assert len(result_page1.results) <= 5 - - # If we have enough results for multiple pages - if result_page1.total_pages > 1: - # Get page 2 - result_page2 = search(pagination_codebase, "Hello", page=2, files_per_page=5) - assert result_page2.status == "success" - assert result_page2.page == 2 - assert len(result_page2.results) <= 5 - - # Ensure different files on different pages - page1_files = {r.filepath for r in result_page1.results} - page2_files = {r.filepath for r in result_page2.results} - assert not page1_files.intersection(page2_files) - - -def test_search_fallback(codebase, monkeypatch): - """Test fallback to Python implementation when ripgrep fails.""" - - # Mock subprocess.run to simulate ripgrep failure - def mock_subprocess_run(*args, **kwargs): - msg = "Simulated ripgrep failure" - raise subprocess.SubprocessError(msg) - - # Apply the mock - monkeypatch.setattr(subprocess, "run", mock_subprocess_run) - - # Search should still work using Python fallback - result = search(codebase, "hello") - assert result.status == "success" - assert len(result.results) > 0 - - -def test_search_ripgrep_not_found(codebase, monkeypatch): - """Test fallback to Python implementation when ripgrep is not installed.""" - - # Mock subprocess.run to simulate ripgrep not found - def mock_subprocess_run(*args, **kwargs): - msg = "Simulated ripgrep not found" - raise FileNotFoundError(msg) - - # Apply the mock - monkeypatch.setattr(subprocess, "run", mock_subprocess_run) - - # Search should still work using Python fallback - result = search(codebase, "hello") - assert result.status == "success" - assert len(result.results) > 0 - - -def test_search_uses_ripgrep(codebase, monkeypatch): - """Test that ripgrep is used when available.""" - # Track if ripgrep was called - ripgrep_called = False - - # Store original subprocess.run - original_run = subprocess.run - - # Mock subprocess.run to track calls and then call the original - def mock_subprocess_run(*args, **kwargs): - nonlocal ripgrep_called - # Check if this is a ripgrep call - if args and args[0] and isinstance(args[0], list) and args[0][0] == "rg": - ripgrep_called = True - # Call the original implementation - return original_run(*args, **kwargs) - - # Apply the mock - monkeypatch.setattr(subprocess, "run", mock_subprocess_run) - - # Perform a search - result = search(codebase, "hello") - assert result.status == "success" - - # Verify ripgrep was called - assert ripgrep_called, "Ripgrep was not used for the search" - - def test_edit_file(codebase): """Test editing a file.""" result = edit_file(codebase, "src/main.py", "print('edited')") From 0af487f15bb0a40d45b30a1272f09aca7bdef99c Mon Sep 17 00:00:00 2001 From: jemeza-codegen <165736868+jemeza-codegen@users.noreply.github.com> Date: Wed, 5 Mar 2025 14:31:35 -0800 Subject: [PATCH 28/66] chore: better linking between a swebench run and its langsmith trace (#761) # Motivation Currently there isn't a good way to find a langsmith trace given a run_id and instance_id # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- .../swebench_agent_run/entry_point.py | 4 +-- .../examples/swebench_agent_run/run_eval.py | 14 ++++----- src/codegen/agents/code_agent.py | 30 +++++++++++++++++-- src/codegen/extensions/swebench/harness.py | 4 +-- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/codegen-examples/examples/swebench_agent_run/entry_point.py b/codegen-examples/examples/swebench_agent_run/entry_point.py index 79fd19575..bd7b6ec2b 100644 --- a/codegen-examples/examples/swebench_agent_run/entry_point.py +++ b/codegen-examples/examples/swebench_agent_run/entry_point.py @@ -14,6 +14,6 @@ @app.function(timeout=43200) -async def run_agent_modal(entry: SweBenchExample): +async def run_agent_modal(entry: SweBenchExample, run_id: str): """Modal function to process a single example from the SWE-bench dataset.""" - return run_agent_on_entry(entry) + return run_agent_on_entry(entry, run_id=run_id) diff --git a/codegen-examples/examples/swebench_agent_run/run_eval.py b/codegen-examples/examples/swebench_agent_run/run_eval.py index 92752d976..0c0e04f65 100644 --- a/codegen-examples/examples/swebench_agent_run/run_eval.py +++ b/codegen-examples/examples/swebench_agent_run/run_eval.py @@ -17,7 +17,7 @@ run_agent_modal = modal.Function.from_name(app_name="swebench-agent-run", name="run_agent_modal") -async def process_batch_modal(examples: list[SweBenchExample], num_workers=5, min_workers=1, max_retries=3): +async def process_batch_modal(examples: list[SweBenchExample], run_id: str, num_workers=5, min_workers=1, max_retries=3): """Process a batch of examples concurrently using a queue system with incremental worker scaling. Args: @@ -110,7 +110,7 @@ async def is_rate_limit_error(error): async def process_example(example, attempt, current_task): try: - result = await run_agent_modal.remote.aio(example) + result = await run_agent_modal.remote.aio(example, run_id=run_id) if result is None: print(f"Warning: Null result for {example.instance_id}") @@ -222,7 +222,7 @@ async def worker(): return [results.get(example.instance_id, {"instance_id": example.instance_id, "status": "missing"}) for example in examples] -def process_batch_local(examples: list[SweBenchExample], num_workers=5, codebases: dict[str, Codebase] = {}): +def process_batch_local(examples: list[SweBenchExample], num_workers=5, codebases: dict[str, Codebase] = {}, run_id: str | None = None): """Process a batch of examples synchronously. Args: @@ -242,9 +242,9 @@ def process_batch_local(examples: list[SweBenchExample], num_workers=5, codebase try: # Run the agent locally instead of using modal if codebases and example.instance_id in codebases: - result = run_agent_on_entry(example, codebase=codebases[example.instance_id]) + result = run_agent_on_entry(example, codebase=codebases[example.instance_id], run_id=run_id) else: - result = run_agent_on_entry(example) + result = run_agent_on_entry(example, run_id=run_id) results.append(result) except Exception as e: @@ -294,9 +294,9 @@ async def run_eval( # Process all examples in parallel batches if local: - results = process_batch_local(examples, codebases=codebases) + results = process_batch_local(examples, codebases=codebases, run_id=run_id) else: - results = await process_batch_modal(examples, num_workers=num_workers) + results = await process_batch_modal(examples, num_workers=num_workers, run_id=run_id) # Save individual results for result in results: diff --git a/src/codegen/agents/code_agent.py b/src/codegen/agents/code_agent.py index cb7be3ffa..a7c500c90 100644 --- a/src/codegen/agents/code_agent.py +++ b/src/codegen/agents/code_agent.py @@ -4,6 +4,7 @@ from langchain.tools import BaseTool from langchain_core.messages import AIMessage +from langchain_core.runnables.config import RunnableConfig from langsmith import Client from codegen.extensions.langchain.agent import create_codebase_agent @@ -16,7 +17,17 @@ class CodeAgent: """Agent for interacting with a codebase.""" - def __init__(self, codebase: "Codebase", model_provider: str = "anthropic", model_name: str = "claude-3-5-sonnet-latest", memory: bool = True, tools: Optional[list[BaseTool]] = None, **kwargs): + def __init__( + self, + codebase: "Codebase", + model_provider: str = "anthropic", + model_name: str = "claude-3-7-sonnet-latest", + memory: bool = True, + tools: Optional[list[BaseTool]] = None, + run_id: Optional[str] = None, + instance_id: Optional[str] = None, + **kwargs, + ): """Initialize a CodeAgent. Args: @@ -34,6 +45,8 @@ def __init__(self, codebase: "Codebase", model_provider: str = "anthropic", mode self.codebase = codebase self.agent = create_codebase_agent(self.codebase, model_provider=model_provider, model_name=model_name, memory=memory, additional_tools=tools, **kwargs) self.langsmith_client = Client() + self.run_id = run_id + self.instance_id = instance_id # Get project name from environment variable or use a default self.project_name = os.environ.get("LANGCHAIN_PROJECT", "RELACE") @@ -55,9 +68,20 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str: # this message has a reducer which appends the current message to the existing history # see more https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers input = {"messages": [("user", prompt)]} - + metadata = {"project": self.project_name} + tags = [] + # Add SWEBench run ID and instance ID to the metadata and tags for filtering + if self.run_id is not None: + metadata["swebench_run_id"] = self.run_id + tags.append(self.run_id) + + if self.instance_id is not None: + metadata["swebench_instance_id"] = self.instance_id + tags.append(self.instance_id) + + config = RunnableConfig(configurable={"thread_id": thread_id}, tags=tags, metadata=metadata, recursion_limit=100) # we stream the steps instead of invoke because it allows us to access intermediate nodes - stream = self.agent.stream(input, config={"configurable": {"thread_id": thread_id, "metadata": {"project": self.project_name}}, "recursion_limit": 100}, stream_mode="values") + stream = self.agent.stream(input, config=config, stream_mode="values") # Keep track of run IDs from the stream run_ids = [] diff --git a/src/codegen/extensions/swebench/harness.py b/src/codegen/extensions/swebench/harness.py index 5f4055d9c..5316b109a 100644 --- a/src/codegen/extensions/swebench/harness.py +++ b/src/codegen/extensions/swebench/harness.py @@ -49,7 +49,7 @@ def show_problems(dataset): print(f"{inst}: {problem}") -def run_agent_on_entry(entry: SweBenchExample, codebase: Codebase | None = None): +def run_agent_on_entry(entry: SweBenchExample, codebase: Codebase | None = None, run_id: str | None = None): """Process one `entry` from SWE Bench using the LLM `models` at the given `temperature`. Set `model_name_or_path` in the result json. """ @@ -70,7 +70,7 @@ def run_agent_on_entry(entry: SweBenchExample, codebase: Codebase | None = None) ) codebase = Codebase.from_repo(repo_full_name=entry.repo, commit=base_commit, language="python", config=config) # check out the repo - agent = CodeAgent(codebase=codebase) + agent = CodeAgent(codebase=codebase, run_id=run_id, instance_id=instance_id) pprint.pprint(instance_id) pprint.pprint(gold_files) From cb2329e5ac1ed9a8271849998c13bdf0b73d0787 Mon Sep 17 00:00:00 2001 From: Edward Li Date: Wed, 5 Mar 2025 15:03:32 -0800 Subject: [PATCH 29/66] Fix invalid file bug with `iter_files` (#764) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- src/codegen/extensions/tools/semantic_edit.py | 2 +- src/codegen/git/repo_operator/repo_operator.py | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/codegen/extensions/tools/semantic_edit.py b/src/codegen/extensions/tools/semantic_edit.py index 80099830e..91f35083d 100644 --- a/src/codegen/extensions/tools/semantic_edit.py +++ b/src/codegen/extensions/tools/semantic_edit.py @@ -109,7 +109,7 @@ def get_llm_edit(original_file_section: str, edit_content: str) -> str: def _validate_edit_boundaries(original_lines: list[str], modified_lines: list[str], start_idx: int, end_idx: int) -> None: - """Validate that the edit only modified lines within the specified boundaries. + """Validate` that the edit only modified lines within the specified boundaries. Args: original_lines: Original file lines diff --git a/src/codegen/git/repo_operator/repo_operator.py b/src/codegen/git/repo_operator/repo_operator.py index 9f1f58007..24db86ede 100644 --- a/src/codegen/git/repo_operator/repo_operator.py +++ b/src/codegen/git/repo_operator/repo_operator.py @@ -643,13 +643,14 @@ def iter_files( if extensions is None or any(filepath.endswith(e) for e in extensions): try: - if not skip_content: - content = self.get_file(filepath) - yield rel_filepath, content + if os.path.isfile(filepath): + if not skip_content: + content = self.get_file(filepath) + yield rel_filepath, content + else: + yield rel_filepath, "" else: - # WTF??? A no-op file read here fixes file parsing somehow? - open(filepath).close() - yield rel_filepath, "" + logger.warning(f"Skipping {filepath} because it does not exist or is not a valid file.") except Exception as e: logger.warning(f"Error reading file {filepath}: {e}") From 7903a9e2f940365524e5cc61f88997b60d968981 Mon Sep 17 00:00:00 2001 From: Vishal Shenoy Date: Wed, 5 Mar 2025 16:56:58 -0800 Subject: [PATCH 30/66] GitHub Webhook Fix (#765) --- .../examples/github_checks/README.md | 34 +++++++++++-------- .../examples/github_checks/app.py | 2 +- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/codegen-examples/examples/github_checks/README.md b/codegen-examples/examples/github_checks/README.md index cb0a87f94..605532669 100644 --- a/codegen-examples/examples/github_checks/README.md +++ b/codegen-examples/examples/github_checks/README.md @@ -1,10 +1,10 @@ # Github Checks -This application is a GitHub integration that analyzes import cycles in Python codebases. It automatically runs when a pull request is labeled and checks for potentially problematic import patterns in the modified codebase. +This application is a GitHub integration that analyzes import cycles in codebases. It automatically runs when a pull request is labeled and checks for potentially problematic import patterns in the modified codebase. ## Features -- Analyzes import relationships in Python codebases +- Analyzes import relationships in codebases - Detects circular import dependencies - Identifies problematic cycles with mixed static and dynamic imports - Automatically comments on pull requests with detailed analysis @@ -48,19 +48,20 @@ This application is a GitHub integration that analyzes import cycles in Python c 1. Results are posted as a comment on the pull request ```python + message = ["### Import Cycle Analysis - GitHub Check\n"] + if problematic_loops: - message.append("\n### ⚠️ Problematic Import Cycles") - message.append("(Cycles with mixed static and dynamic imports)") - for i, cycle in enumerate(problematic_loops, 1): - message.append(f"\n#### Problematic Cycle #{i}") - message.append("Mixed imports:") - for (from_file, to_file), imports in cycle["mixed_imports"].items(): - message.append(f"\nFrom: `{from_file}`") - message.append(f"To: `{to_file}`") - message.append(f"- Static imports: {imports['static']}") - message.append(f"- Dynamic imports: {imports['dynamic']}") - - create_pr_comment(codebase, event.pull_request, number, "\n".join(message)) + message.append("\n### ⚠️ Potentially Problematic Import Cycles") + message.append("Cycles with mixed static and dynamic imports, which might recquire attention.") + for i, cycle in enumerate(problematic_loops, 1): + message.append(f"\n#### Problematic Cycle {i}") + for (from_file, to_file), imports in cycle["mixed_imports"].items(): + message.append(f"\nFrom: `{from_file}`") + message.append(f"To: `{to_file}`") + message.append(f"- Static imports: {imports['static']}") + message.append(f"- Dynamic imports: {imports['dynamic']}") + else: + message.append("\nNo problematic import cycles found! 🎉") ``` ## Setup @@ -75,7 +76,7 @@ This application is a GitHub integration that analyzes import cycles in Python c 1. Set up your environment variables in a `.env` file - - `GITHUB_TOKEN`: Your GitHub token, configured with `repo` and `workflow` scopes + - `GITHUB_TOKEN`: Your GitHub token, configured with `repo` and `workflow` scopes. 1. Deploy the app using Modal: @@ -83,6 +84,9 @@ This application is a GitHub integration that analyzes import cycles in Python c modal deploy app.py ``` + - After deployment, configure your GitHub App's webhook URL in its developer settings to point to your Modal endpoint with the endpoint `/github/events` + - The app will analyze imports via the Modal deployment whenever a pull request receives a `Codegen` label + ## Technical Details The application uses Codegen to parse the codebase and a combination of NetworkX and Codegen to analyze the import relationships. The app is structured as a Modal App with a FastAPI server. diff --git a/codegen-examples/examples/github_checks/app.py b/codegen-examples/examples/github_checks/app.py index fe5097154..8166e5d31 100644 --- a/codegen-examples/examples/github_checks/app.py +++ b/codegen-examples/examples/github_checks/app.py @@ -144,7 +144,7 @@ def handle_pr(event: PullRequestLabeledEvent): ) ) -app = modal.App("codegen-test") +app = modal.App("codegen-import-cycles-github-check") @app.function(image=base_image, secrets=[modal.Secret.from_dotenv()]) From a2c6a5322dddd3b0660ddf661934aadfc1af9ab9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 00:59:39 +0000 Subject: [PATCH 31/66] fix(deps): update dependency openai to v1.65.4 (#766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [openai](https://redirect.github.com/openai/openai-python) | `==1.65.3` -> `==1.65.4` | [![age](https://developer.mend.io/api/mc/badges/age/pypi/openai/1.65.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/openai/1.65.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/openai/1.65.3/1.65.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/openai/1.65.3/1.65.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
openai/openai-python (openai) ### [`v1.65.4`](https://redirect.github.com/openai/openai-python/blob/HEAD/CHANGELOG.md#1654-2025-03-05) Full Changelog: [v1.65.3...v1.65.4](https://redirect.github.com/openai/openai-python/compare/v1.65.3...v1.65.4) ##### Bug Fixes - **api:** add missing file rank enum + more metadata ([#​2164](https://redirect.github.com/openai/openai-python/issues/2164)) ([0387e48](https://redirect.github.com/openai/openai-python/commit/0387e48e0880e496eb74b60eec9ed76a3171f14d))
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - "* 0-3 * * 1" (UTC). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/codegen-sh/codegen). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- uv.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 93d695eb8..ea7fa4ae1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" # renovate: datasource=python-version depName=python requires-python = ">=3.12, <3.14" dependencies = [ - "openai==1.65.3", + "openai==1.65.4", "tiktoken<1.0.0,>=0.5.1", "tabulate>=0.9.0,<1.0.0", "codeowners<1.0.0,>=0.6.0", diff --git a/uv.lock b/uv.lock index 5340f0dad..86bc5b166 100644 --- a/uv.lock +++ b/uv.lock @@ -701,7 +701,7 @@ requires-dist = [ { name = "neo4j" }, { name = "networkx", specifier = ">=3.4.1" }, { name = "numpy", specifier = ">=2.2.2" }, - { name = "openai", specifier = "==1.65.3" }, + { name = "openai", specifier = "==1.65.4" }, { name = "packaging", specifier = ">=24.2" }, { name = "pip", specifier = ">=24.3.1" }, { name = "plotly", specifier = ">=5.24.0,<7.0.0" }, @@ -2716,7 +2716,7 @@ wheels = [ [[package]] name = "openai" -version = "1.65.3" +version = "1.65.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2728,9 +2728,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/32/4f/b34b6fad12e1f6b3f42922214c161d5ef74a50fa97d9ae7d680db0958ff4/openai-1.65.3.tar.gz", hash = "sha256:9b7cd8f79140d03d77f4ed8aeec6009be5dcd79bbc02f03b0e8cd83356004f71", size = 358821 } +sdist = { url = "https://files.pythonhosted.org/packages/fa/8d/1f7aace801afbbe4d6b8c7fa89b76eb9a3a8eeff38b84d4005d47b226b30/openai-1.65.4.tar.gz", hash = "sha256:0b08c58625d556f5c6654701af1023689c173eb0989ce8f73c7fd0eb22203c76", size = 359365 } wheels = [ - { url = "https://files.pythonhosted.org/packages/86/d5/b8378be0f4cf192992aa3080eb9ddcdca3109b399be61984424aaa79f847/openai-1.65.3-py3-none-any.whl", hash = "sha256:a155fa5d60eccda516384d3d60d923e083909cc126f383fe4a350f79185c232a", size = 472758 }, + { url = "https://files.pythonhosted.org/packages/ba/db/7bab832be24631a793492c1c61ecbf029018b99696f435db3b63d690bf1c/openai-1.65.4-py3-none-any.whl", hash = "sha256:15566d46574b94eae3d18efc2f9a4ebd1366d1d44bfc1bdafeea7a5cf8271bcb", size = 473523 }, ] [[package]] From 5515372e5e7cec74ce04af517dd3db0a76236ea8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 6 Mar 2025 01:01:38 +0000 Subject: [PATCH 32/66] update changelog --- docs/changelog/changelog.mdx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index f3ef3be22..a3efe5e36 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,13 @@ icon: "clock" iconType: "solid" --- + +### [Bug fixes and GitHub Webhook functionality improvements.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.46.1) +- Fix invalid file handling bug +- Improve GitHub Webhook functionality +- Enhance testing and documentation updates + + ### [Introduces a better search tool and dynamic scaling.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.46.0) - Fix issues with unpacking functionality From 26b5ca444de9ca4e36e6e48ac6dddedc36ddf9ea Mon Sep 17 00:00:00 2001 From: jemeza-codegen <165736868+jemeza-codegen@users.noreply.github.com> Date: Wed, 5 Mar 2025 17:13:00 -0800 Subject: [PATCH 33/66] chore: model is now a parameter for the run eval command (#767) # Motivation Currently there is no way to specify which model to use from the command line when running the swe bench eval. # Content Passes model name through the functions # Testing This is a test # Please check the following before marking your PR as ready for review - [x] I have added tests for my changes - [x] I have updated the documentation or added new documentation as needed --- .../swebench_agent_run/entry_point.py | 4 +-- .../examples/swebench_agent_run/run_eval.py | 30 ++++++++++++------- src/codegen/extensions/swebench/harness.py | 4 +-- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/codegen-examples/examples/swebench_agent_run/entry_point.py b/codegen-examples/examples/swebench_agent_run/entry_point.py index bd7b6ec2b..a364aaa19 100644 --- a/codegen-examples/examples/swebench_agent_run/entry_point.py +++ b/codegen-examples/examples/swebench_agent_run/entry_point.py @@ -14,6 +14,6 @@ @app.function(timeout=43200) -async def run_agent_modal(entry: SweBenchExample, run_id: str): +async def run_agent_modal(entry: SweBenchExample, run_id: str, model: str): """Modal function to process a single example from the SWE-bench dataset.""" - return run_agent_on_entry(entry, run_id=run_id) + return run_agent_on_entry(entry, run_id=run_id, model=model) diff --git a/codegen-examples/examples/swebench_agent_run/run_eval.py b/codegen-examples/examples/swebench_agent_run/run_eval.py index 0c0e04f65..9a86135d8 100644 --- a/codegen-examples/examples/swebench_agent_run/run_eval.py +++ b/codegen-examples/examples/swebench_agent_run/run_eval.py @@ -17,7 +17,7 @@ run_agent_modal = modal.Function.from_name(app_name="swebench-agent-run", name="run_agent_modal") -async def process_batch_modal(examples: list[SweBenchExample], run_id: str, num_workers=5, min_workers=1, max_retries=3): +async def process_batch_modal(examples: list[SweBenchExample], run_id: str, model: str, num_workers=5, min_workers=1, max_retries=3): """Process a batch of examples concurrently using a queue system with incremental worker scaling. Args: @@ -110,7 +110,7 @@ async def is_rate_limit_error(error): async def process_example(example, attempt, current_task): try: - result = await run_agent_modal.remote.aio(example, run_id=run_id) + result = await run_agent_modal.remote.aio(example, run_id=run_id, model=model) if result is None: print(f"Warning: Null result for {example.instance_id}") @@ -222,7 +222,7 @@ async def worker(): return [results.get(example.instance_id, {"instance_id": example.instance_id, "status": "missing"}) for example in examples] -def process_batch_local(examples: list[SweBenchExample], num_workers=5, codebases: dict[str, Codebase] = {}, run_id: str | None = None): +def process_batch_local(examples: list[SweBenchExample], model: str, num_workers=5, codebases: dict[str, Codebase] = {}, run_id: str | None = None): """Process a batch of examples synchronously. Args: @@ -242,9 +242,9 @@ def process_batch_local(examples: list[SweBenchExample], num_workers=5, codebase try: # Run the agent locally instead of using modal if codebases and example.instance_id in codebases: - result = run_agent_on_entry(example, codebase=codebases[example.instance_id], run_id=run_id) + result = run_agent_on_entry(example, model=model, codebase=codebases[example.instance_id], run_id=run_id) else: - result = run_agent_on_entry(example, run_id=run_id) + result = run_agent_on_entry(example, model=model, run_id=run_id) results.append(result) except Exception as e: @@ -267,7 +267,15 @@ def process_batch_local(examples: list[SweBenchExample], num_workers=5, codebase async def run_eval( - use_existing_preds: str | None, dataset: str, length: int, instance_id: str | None = None, local: bool = False, codebases: dict[str, Codebase] = {}, repo: str | None = None, num_workers: int = 5 + use_existing_preds: str | None, + dataset: str, + length: int, + instance_id: str | None = None, + local: bool = False, + codebases: dict[str, Codebase] = {}, + repo: str | None = None, + num_workers: int = 5, + model: str = "claude-3-7-sonnet-latest", ): run_id = use_existing_preds or str(uuid.uuid4()) print(f"Run ID: {run_id}") @@ -294,9 +302,9 @@ async def run_eval( # Process all examples in parallel batches if local: - results = process_batch_local(examples, codebases=codebases, run_id=run_id) + results = process_batch_local(examples, model=model, codebases=codebases, run_id=run_id) else: - results = await process_batch_modal(examples, num_workers=num_workers, run_id=run_id) + results = await process_batch_modal(examples, model=model, run_id=run_id, num_workers=num_workers) # Save individual results for result in results: @@ -355,9 +363,11 @@ async def run_eval( @click.option( "--num-workers", help="The number of workers to use. This is the number of examples that will be processed concurrently. A large number may lead to rate limiting issues.", type=int, default=5 ) -def run_eval_command(use_existing_preds, dataset, length, instance_id, local, repo, num_workers): +@click.option("--model", help="The model to use.", type=str, default="claude-3-7-sonnet-latest") +def run_eval_command(use_existing_preds, dataset, length, instance_id, local, repo, num_workers, model): print(f"Repo: {repo}") - asyncio.run(run_eval(use_existing_preds=use_existing_preds, dataset=dataset, length=length, instance_id=instance_id, codebases=None, local=local, repo=repo, num_workers=num_workers)) + print(f"Model: {model}") + asyncio.run(run_eval(use_existing_preds=use_existing_preds, dataset=dataset, length=length, instance_id=instance_id, codebases=None, local=local, repo=repo, num_workers=num_workers, model=model)) if __name__ == "__main__": diff --git a/src/codegen/extensions/swebench/harness.py b/src/codegen/extensions/swebench/harness.py index 5316b109a..90cc9e017 100644 --- a/src/codegen/extensions/swebench/harness.py +++ b/src/codegen/extensions/swebench/harness.py @@ -49,7 +49,7 @@ def show_problems(dataset): print(f"{inst}: {problem}") -def run_agent_on_entry(entry: SweBenchExample, codebase: Codebase | None = None, run_id: str | None = None): +def run_agent_on_entry(entry: SweBenchExample, model: str, codebase: Codebase | None = None, run_id: str | None = None): """Process one `entry` from SWE Bench using the LLM `models` at the given `temperature`. Set `model_name_or_path` in the result json. """ @@ -70,7 +70,7 @@ def run_agent_on_entry(entry: SweBenchExample, codebase: Codebase | None = None, ) codebase = Codebase.from_repo(repo_full_name=entry.repo, commit=base_commit, language="python", config=config) # check out the repo - agent = CodeAgent(codebase=codebase, run_id=run_id, instance_id=instance_id) + agent = CodeAgent(codebase=codebase, run_id=run_id, instance_id=instance_id, model_name=model) pprint.pprint(instance_id) pprint.pprint(gold_files) From c44d98e07788d3a0c229017d075696c4e679230c Mon Sep 17 00:00:00 2001 From: Jay Hack Date: Thu, 6 Mar 2025 08:44:57 -0800 Subject: [PATCH 34/66] feat: adds SearchGithubIssuesTool (#747) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- src/codegen/agents/code_agent.py | 34 +++++++- src/codegen/extensions/langchain/tools.py | 41 ++++++++-- .../extensions/tools/github/__init__.py | 2 + src/codegen/extensions/tools/github/search.py | 77 +++++++++++++++++++ src/codegen/git/clients/git_repo_client.py | 11 +++ tests/integration/extension/test_github.py | 51 ++++++++++-- 6 files changed, 200 insertions(+), 16 deletions(-) create mode 100644 src/codegen/extensions/tools/github/search.py diff --git a/src/codegen/agents/code_agent.py b/src/codegen/agents/code_agent.py index a7c500c90..3c3cc9b88 100644 --- a/src/codegen/agents/code_agent.py +++ b/src/codegen/agents/code_agent.py @@ -8,7 +8,9 @@ from langsmith import Client from codegen.extensions.langchain.agent import create_codebase_agent -from codegen.extensions.langchain.utils.get_langsmith_url import find_and_print_langsmith_run_url +from codegen.extensions.langchain.utils.get_langsmith_url import ( + find_and_print_langsmith_run_url, +) if TYPE_CHECKING: from codegen import Codebase @@ -17,6 +19,13 @@ class CodeAgent: """Agent for interacting with a codebase.""" + codebase: "Codebase" + agent: any + langsmith_client: Client + project_name: str + thread_id: str | None = None + config: dict = {} + def __init__( self, codebase: "Codebase", @@ -43,7 +52,14 @@ def __init__( - max_tokens: Maximum number of tokens to generate """ self.codebase = codebase - self.agent = create_codebase_agent(self.codebase, model_provider=model_provider, model_name=model_name, memory=memory, additional_tools=tools, **kwargs) + self.agent = create_codebase_agent( + self.codebase, + model_provider=model_provider, + model_name=model_name, + memory=memory, + additional_tools=tools, + **kwargs, + ) self.langsmith_client = Client() self.run_id = run_id self.instance_id = instance_id @@ -64,6 +80,14 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str: """ if thread_id is None: thread_id = str(uuid4()) + self.thread_id = thread_id + self.config = { + "configurable": { + "thread_id": thread_id, + "metadata": {"project": self.project_name}, + }, + "recursion_limit": 100, + } # this message has a reducer which appends the current message to the existing history # see more https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers @@ -134,3 +158,9 @@ def get_agent_trace_url(self) -> str | None: print(traceback.format_exc()) print(separator) return None + + def get_tools(self) -> list[BaseTool]: + return list(self.agent.get_graph().nodes["tools"].data.tools_by_name.values()) + + def get_state(self) -> dict: + return self.agent.get_state(self.config) diff --git a/src/codegen/extensions/langchain/tools.py b/src/codegen/extensions/langchain/tools.py index acfbdaf59..c63843738 100644 --- a/src/codegen/extensions/langchain/tools.py +++ b/src/codegen/extensions/langchain/tools.py @@ -7,6 +7,7 @@ from codegen.extensions.linear.linear_client import LinearClient from codegen.extensions.tools.bash import run_bash_command +from codegen.extensions.tools.github.search import search from codegen.extensions.tools.linear.linear import ( linear_comment_on_issue_tool, linear_create_issue_tool, @@ -20,7 +21,6 @@ from codegen.extensions.tools.relace_edit import relace_edit from codegen.extensions.tools.replacement_edit import replacement_edit from codegen.extensions.tools.reveal_symbol import reveal_symbol -from codegen.extensions.tools.search import search from codegen.extensions.tools.semantic_edit import semantic_edit from codegen.extensions.tools.semantic_search import semantic_search from codegen.sdk.core.codebase import Codebase @@ -560,6 +560,28 @@ def _run(self, title: str, body: str) -> str: return result.render() +class GithubSearchIssuesInput(BaseModel): + """Input for searching GitHub issues.""" + + query: str = Field(..., description="Search query string to find issues") + + +class GithubSearchIssuesTool(BaseTool): + """Tool for searching GitHub issues.""" + + name: ClassVar[str] = "search_issues" + description: ClassVar[str] = "Search for GitHub issues/PRs using a query string from pygithub, e.g. 'is:pr is:open test_query'" + args_schema: ClassVar[type[BaseModel]] = GithubSearchIssuesInput + codebase: Codebase = Field(exclude=True) + + def __init__(self, codebase: Codebase) -> None: + super().__init__(codebase=codebase) + + def _run(self, query: str) -> str: + result = search(self.codebase, query) + return result.render() + + class GithubViewPRInput(BaseModel): """Input for getting PR contents.""" @@ -856,6 +878,7 @@ def get_workspace_tools(codebase: Codebase) -> list["BaseTool"]: GithubCreatePRCommentTool(codebase), GithubCreatePRReviewCommentTool(codebase), GithubViewPRTool(codebase), + GithubSearchIssuesTool(codebase), # Linear LinearGetIssueTool(codebase), LinearGetIssueCommentsTool(codebase), @@ -870,22 +893,28 @@ class ReplacementEditInput(BaseModel): filepath: str = Field(..., description="Path to the file to edit relative to the workspace root. The file must exist and be a text file.") pattern: str = Field( ..., - description="Regular expression pattern to match text that should be replaced. Supports all Python regex syntax including capture groups (\1, \2, etc). The pattern is compiled with re.MULTILINE flag by default.", + description="""Regular expression pattern to match text that should be replaced. +Supports all Python regex syntax including capture groups (\1, \2, etc). The pattern is compiled with re.MULTILINE flag by default.""", ) replacement: str = Field( ..., - description="Text to replace matched patterns with. Can reference regex capture groups using \1, \2, etc. If using regex groups in pattern, make sure to preserve them in replacement if needed.", + description="""Text to replace matched patterns with. +Can reference regex capture groups using \1, \2, etc. If using regex groups in pattern, make sure to preserve them in replacement if needed.""", ) start: int = Field( - default=1, description="Starting line number (1-indexed, inclusive) to begin replacements from. Use this with 'end' to limit changes to a specific region. Default is 1 (start of file)." + default=1, + description="""Starting line number (1-indexed, inclusive) to begin replacements from. +Use this with 'end' to limit changes to a specific region. Default is 1 (start of file).""", ) end: int = Field( default=-1, - description="Ending line number (1-indexed, inclusive) to stop replacements at. Use -1 to indicate end of file. Use this with 'start' to limit changes to a specific region. Default is -1 (end of file).", + description="""Ending line number (1-indexed, inclusive) to stop replacements at. +Use -1 to indicate end of file. Use this with 'start' to limit changes to a specific region. Default is -1 (end of file).""", ) count: Optional[int] = Field( default=None, - description="Maximum number of replacements to make. Use None to replace all occurrences (default), or specify a number to limit replacements. Useful when you only want to replace the first N occurrences.", + description="""Maximum number of replacements to make. Use None to replace all occurrences (default), or specify a number to limit replacements. +Useful when you only want to replace the first N occurrences.""", ) diff --git a/src/codegen/extensions/tools/github/__init__.py b/src/codegen/extensions/tools/github/__init__.py index a59669dd2..f5f9761f3 100644 --- a/src/codegen/extensions/tools/github/__init__.py +++ b/src/codegen/extensions/tools/github/__init__.py @@ -1,11 +1,13 @@ from .create_pr import create_pr from .create_pr_comment import create_pr_comment from .create_pr_review_comment import create_pr_review_comment +from .search import search from .view_pr import view_pr __all__ = [ "create_pr", "create_pr_comment", "create_pr_review_comment", + "search", "view_pr", ] diff --git a/src/codegen/extensions/tools/github/search.py b/src/codegen/extensions/tools/github/search.py new file mode 100644 index 000000000..b83504937 --- /dev/null +++ b/src/codegen/extensions/tools/github/search.py @@ -0,0 +1,77 @@ +"""Tools for searching GitHub issues and pull requests.""" + +from typing import ClassVar + +from pydantic import Field + +from codegen.sdk.core.codebase import Codebase + +from ..observation import Observation + + +class SearchResultObservation(Observation): + """Response from searching issues and pull requests.""" + + query: str = Field( + description="The search query that was used", + ) + results: list[dict] = Field( + description="List of matching issues/PRs with their details. Use is:pr in query to search for PRs, is:issue for issues.", + ) + + str_template: ClassVar[str] = "Found {total} results matching query: {query}" + + @property + def total(self) -> int: + return len(self.results) + + +def search( + codebase: Codebase, + query: str, + max_results: int = 20, +) -> SearchResultObservation: + """Search for GitHub issues and pull requests using the provided query. + + To search for pull requests specifically, include 'is:pr' in your query. + To search for issues specifically, include 'is:issue' in your query. + If neither is specified, both issues and PRs will be included in results. + + Args: + codebase: The codebase to operate on + query: Search query string (e.g. "is:pr label:bug", "is:issue is:open") + state: Filter by state ("open", "closed", or "all") + max_results: Maximum number of results to return + """ + try: + # Get the GitHub repo object + repo = codebase._op.remote_git_repo + + # Search using PyGitHub's search_issues (which searches both issues and PRs) + results = [] + for item in repo.search_issues(query)[:max_results]: + result = { + "title": item.title, + "number": item.number, + "state": item.state, + "labels": [label.name for label in item.labels], + "created_at": item.created_at.isoformat(), + "updated_at": item.updated_at.isoformat(), + "url": item.html_url, + "is_pr": item.pull_request is not None, + } + results.append(result) + + return SearchResultObservation( + status="success", + query=query, + results=results, + ) + + except Exception as e: + return SearchResultObservation( + status="error", + error=f"Failed to search: {e!s}", + query=query, + results=[], + ) diff --git a/src/codegen/git/clients/git_repo_client.py b/src/codegen/git/clients/git_repo_client.py index 79c8df2a4..e90735639 100644 --- a/src/codegen/git/clients/git_repo_client.py +++ b/src/codegen/git/clients/git_repo_client.py @@ -7,6 +7,7 @@ from github.Commit import Commit from github.GithubException import GithubException, UnknownObjectException from github.GithubObject import NotSet, Opt +from github.Issue import Issue from github.IssueComment import IssueComment from github.Label import Label from github.PullRequest import PullRequest @@ -431,3 +432,13 @@ def merge_upstream(self, branch_name: str) -> bool: post_parameters = {"branch": branch_name} status, _, _ = self.repo._requester.requestJson("POST", f"{self.repo.url}/merge-upstream", input=post_parameters) return status == 200 + + #################################################################################################################### + # SEARCH + #################################################################################################################### + + def search_issues(self, query: str, **kwargs) -> list[Issue]: + return self.gh_client.client.search_issues(query, **kwargs) + + def search_prs(self, query: str, **kwargs) -> list[PullRequest]: + return self.gh_client.client.search_issues(query, **kwargs) diff --git a/tests/integration/extension/test_github.py b/tests/integration/extension/test_github.py index 7f050bba7..4b6b82693 100644 --- a/tests/integration/extension/test_github.py +++ b/tests/integration/extension/test_github.py @@ -1,17 +1,16 @@ -"""Tests for Linear tools.""" +"""Tests for GitHub tools.""" import os import pytest -from codegen.extensions.linear.linear_client import LinearClient -from codegen.extensions.tools.github import view_pr +from codegen.extensions.tools.github import search, view_pr from codegen.sdk.core.codebase import Codebase @pytest.fixture -def client() -> LinearClient: - """Create a Linear client for testing.""" +def codebase() -> Codebase: + """Create a Codebase instance for testing.""" token = os.getenv("GITHUB_TOKEN") if not token: pytest.skip("GITHUB_TOKEN environment variable not set") @@ -19,8 +18,44 @@ def client() -> LinearClient: return codebase -def test_github_view_pr(client: LinearClient) -> None: - """Test getting an issue from Linear.""" +def test_github_view_pr(codebase: Codebase) -> None: + """Test viewing a PR from GitHub.""" # Link to PR: https://github.com/codegen-sh/Kevin-s-Adventure-Game/pull/419 - pr = view_pr(client, 419) + pr = view_pr(codebase, 419) print(pr) + + +def test_github_search_issues(codebase: Codebase) -> None: + """Test searching GitHub issues.""" + # Search for closed issues with the 'bug' label + result = search(codebase, query="is:issue is:closed") + assert result.status == "success" + assert len(result.results) > 0 + assert "is:issue is:closed" in result.query + + # Verify issue structure + if result.results: + issue = result.results[0] + assert "title" in issue + assert "number" in issue + assert "state" in issue + assert issue["state"] == "closed" + assert not issue["is_pr"] # Should be an issue, not a PR + + +def test_github_search_prs(codebase: Codebase) -> None: + """Test searching GitHub pull requests.""" + # Search for merged PRs + result = search(codebase, query="is:pr is:merged") + assert result.status == "success" + assert len(result.results) > 0 + assert "is:pr is:merged" in result.query + + # Verify PR structure + if result.results: + pr = result.results[0] + assert "title" in pr + assert "number" in pr + assert "state" in pr + assert pr["state"] == "closed" + assert pr["is_pr"] # Should be a PR From 0dc997421000df20e627b09e8dd4a76dd68f802e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 6 Mar 2025 16:48:18 +0000 Subject: [PATCH 35/66] update changelog --- docs/changelog/changelog.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index a3efe5e36..3b41df491 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,12 @@ icon: "clock" iconType: "solid" --- + +### [Adds GitHub issues search tool and eval command update.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.47.0) +- Adds a new tool for searching GitHub issues +- Makes model a parameter for the run eval command + + ### [Bug fixes and GitHub Webhook functionality improvements.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.46.1) - Fix invalid file handling bug From 074e761a38a870b17b4c97e51d205bc98cfd3126 Mon Sep 17 00:00:00 2001 From: Christine Wang Date: Thu, 6 Mar 2025 09:29:18 -0800 Subject: [PATCH 36/66] feat: add view PR checks tool (#768) --- src/codegen/extensions/langchain/tools.py | 23 ++++++++ .../extensions/tools/github/view_pr_checks.py | 54 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 src/codegen/extensions/tools/github/view_pr_checks.py diff --git a/src/codegen/extensions/langchain/tools.py b/src/codegen/extensions/langchain/tools.py index c63843738..5e78db2d1 100644 --- a/src/codegen/extensions/langchain/tools.py +++ b/src/codegen/extensions/langchain/tools.py @@ -8,6 +8,7 @@ from codegen.extensions.linear.linear_client import LinearClient from codegen.extensions.tools.bash import run_bash_command from codegen.extensions.tools.github.search import search +from codegen.extensions.tools.github.view_pr_checks import view_pr_checks from codegen.extensions.tools.linear.linear import ( linear_comment_on_issue_tool, linear_create_issue_tool, @@ -669,6 +670,28 @@ def _run( return result.render() +class GithubViewPRCheckInput(BaseModel): + """Input for viewing PR checks""" + + pr_number: int = Field(..., description="The PR number to view checks for") + + +class GithubViewPRCheckTool(BaseTool): + """Tool for viewing PR checks.""" + + name: ClassVar[str] = "view_pr_checks" + description: ClassVar[str] = "View the check suites for a PR" + args_schema: ClassVar[type[BaseModel]] = GithubCreatePRReviewCommentInput + codebase: Codebase = Field(exclude=True) + + def __init__(self, codebase: Codebase) -> None: + super().__init__(codebase=codebase) + + def _run(self, pr_number: int) -> str: + result = view_pr_checks(self.codebase, pr_number=pr_number) + return result.render() + + ######################################################################################################################## # LINEAR ######################################################################################################################## diff --git a/src/codegen/extensions/tools/github/view_pr_checks.py b/src/codegen/extensions/tools/github/view_pr_checks.py new file mode 100644 index 000000000..9f17edaa2 --- /dev/null +++ b/src/codegen/extensions/tools/github/view_pr_checks.py @@ -0,0 +1,54 @@ +"""Tool for creating PR review comments.""" + +import json + +from pydantic import Field + +from codegen.sdk.core.codebase import Codebase + +from ..observation import Observation + + +class PRCheckObservation(Observation): + """Response from retrieving PR checks.""" + + pr_number: int = Field( + description="PR number that was viewed", + ) + head_sha: str | None = Field( + description="SHA of the head commit", + ) + summary: str | None = Field( + description="Summary of the checks", + ) + + +def view_pr_checks(codebase: Codebase, pr_number: int) -> PRCheckObservation: + """Retrieve check information from a Github PR . + + Args: + codebase: The codebase to operate on + pr_number: The PR number to view checks on + """ + try: + pr = codebase.op.remote_git_repo.get_pull_safe(pr_number) + if not pr: + return PRCheckObservation( + pr_number=pr_number, + head_sha=None, + summary=None, + ) + commit = codebase.op.remote_git_repo.get_commit_safe(pr.head.sha) + all_check_suites = commit.get_check_suites() + return PRCheckObservation( + pr_number=pr_number, + head_sha=pr.head.sha, + summary="\n".join([json.dumps(check_suite.raw_data) for check_suite in all_check_suites]), + ) + + except Exception as e: + return PRCheckObservation( + pr_number=pr_number, + head_sha=None, + summary=None, + ) From 3eb3324e004f7b2e61beaebc412a3fa0acfd4570 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 6 Mar 2025 17:32:46 +0000 Subject: [PATCH 37/66] update changelog --- docs/changelog/changelog.mdx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 3b41df491..4353d52bf 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,11 @@ icon: "clock" iconType: "solid" --- + +### [adds view PR checks tool.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.0) +- Add view PR checks tool + + ### [Adds GitHub issues search tool and eval command update.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.47.0) - Adds a new tool for searching GitHub issues From 30c016e618b3eb6f056ed51cf2bd6d9e9bd5c1de Mon Sep 17 00:00:00 2001 From: Christine Wang Date: Thu, 6 Mar 2025 10:18:31 -0800 Subject: [PATCH 38/66] chore: CG-10986 checkout pr tool (#769) --- src/codegen/extensions/langchain/tools.py | 23 +++++++++ .../extensions/tools/github/checkout_pr.py | 47 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/codegen/extensions/tools/github/checkout_pr.py diff --git a/src/codegen/extensions/langchain/tools.py b/src/codegen/extensions/langchain/tools.py index 5e78db2d1..e191ca7f8 100644 --- a/src/codegen/extensions/langchain/tools.py +++ b/src/codegen/extensions/langchain/tools.py @@ -7,6 +7,7 @@ from codegen.extensions.linear.linear_client import LinearClient from codegen.extensions.tools.bash import run_bash_command +from codegen.extensions.tools.github.checkout_pr import checkout_pr from codegen.extensions.tools.github.search import search from codegen.extensions.tools.github.view_pr_checks import view_pr_checks from codegen.extensions.tools.linear.linear import ( @@ -605,6 +606,28 @@ def _run(self, pr_id: int) -> str: return result.render() +class GithubCheckoutPRInput(BaseModel): + """Input for checkout out a PR head branch.""" + + pr_number: int = Field(..., description="Number of the PR to checkout") + + +class GithubCheckoutPRTool(BaseTool): + """Tool for checking out a PR head branch.""" + + name: ClassVar[str] = "checkout_pr" + description: ClassVar[str] = "Checkout out a PR head branch" + args_schema: ClassVar[type[BaseModel]] = GithubCheckoutPRInput + codebase: Codebase = Field(exclude=True) + + def __init__(self, codebase: Codebase) -> None: + super().__init__(codebase=codebase) + + def _run(self, pr_number: int) -> str: + result = checkout_pr(self.codebase, pr_number) + return result.render() + + class GithubCreatePRCommentInput(BaseModel): """Input for creating a PR comment""" diff --git a/src/codegen/extensions/tools/github/checkout_pr.py b/src/codegen/extensions/tools/github/checkout_pr.py new file mode 100644 index 000000000..1b4b6d769 --- /dev/null +++ b/src/codegen/extensions/tools/github/checkout_pr.py @@ -0,0 +1,47 @@ +"""Tool for viewing PR contents and modified symbols.""" + +from pydantic import Field + +from codegen.sdk.core.codebase import Codebase + +from ..observation import Observation + + +class CheckoutPRObservation(Observation): + """Response from checking out a PR.""" + + pr_number: int = Field( + description="PR number", + ) + success: bool = Field( + description="Whether the checkout was successful", + default=False, + ) + + +def checkout_pr(codebase: Codebase, pr_number: int) -> CheckoutPRObservation: + """Checkout a PR. + + Args: + codebase: The codebase to operate on + pr_number: Number of the PR to get the contents for + """ + try: + pr = codebase.op.remote_git_repo.get_pull_safe(pr_number) + if not pr: + return CheckoutPRObservation( + pr_number=pr_number, + success=False, + ) + + codebase.checkout(branch=pr.head.ref) + return CheckoutPRObservation( + pr_number=pr_number, + success=True, + ) + except Exception as e: + return CheckoutPRObservation( + pr_number=pr_number, + success=False, + error=f"Failed to checkout PR: {e!s}", + ) From 0127d2bbe941dd23a41ea795f0136f158effbd23 Mon Sep 17 00:00:00 2001 From: jemeza-codegen <165736868+jemeza-codegen@users.noreply.github.com> Date: Thu, 6 Mar 2025 11:00:05 -0800 Subject: [PATCH 39/66] Model name is a tag for langsmith traces (#770) # Motivation We need a quick way to filter langsmith traces by model name. # Content Model name is now an attribute of CodeAgent and is added to the list of tags on the langsmith trace. # Testing Tested by running locally # Please check the following before marking your PR as ready for review --- src/codegen/agents/code_agent.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/codegen/agents/code_agent.py b/src/codegen/agents/code_agent.py index 3c3cc9b88..157df294d 100644 --- a/src/codegen/agents/code_agent.py +++ b/src/codegen/agents/code_agent.py @@ -60,6 +60,7 @@ def __init__( additional_tools=tools, **kwargs, ) + self.model_name = model_name self.langsmith_client = Client() self.run_id = run_id self.instance_id = instance_id @@ -92,8 +93,8 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str: # this message has a reducer which appends the current message to the existing history # see more https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers input = {"messages": [("user", prompt)]} - metadata = {"project": self.project_name} - tags = [] + metadata = {"project": self.project_name, "model": self.model_name} + tags = [self.model_name] # Add SWEBench run ID and instance ID to the metadata and tags for filtering if self.run_id is not None: metadata["swebench_run_id"] = self.run_id From 6616219965e8987c44b3071926aef9e81b3a7951 Mon Sep 17 00:00:00 2001 From: Carol Jung <165736129+caroljung-cg@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:33:49 -0800 Subject: [PATCH 40/66] fix: fix Codebase.from_repo (#771) --- src/codegen/sdk/core/codebase.py | 7 +++++-- tests/integration/codegen/git/codebase/conftest.py | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/codegen/sdk/core/codebase.py b/src/codegen/sdk/core/codebase.py index 735a8b5ea..2c641e655 100644 --- a/src/codegen/sdk/core/codebase.py +++ b/src/codegen/sdk/core/codebase.py @@ -26,6 +26,7 @@ from codegen.configs.models.secrets import SecretsConfig from codegen.git.repo_operator.repo_operator import RepoOperator from codegen.git.schemas.enums import CheckoutResult, SetupOption +from codegen.git.schemas.repo_config import RepoConfig from codegen.git.utils.pr_review import CodegenPR from codegen.sdk._proxy import proxy_property from codegen.sdk.ai.client import get_openai_client @@ -1343,15 +1344,17 @@ def from_repo( repo_path = os.path.join(tmp_dir, repo) repo_url = f"https://github.com/{repo_full_name}.git" logger.info(f"Will clone {repo_url} to {repo_path}") + access_token = secrets.github_token if secrets else None try: # Use RepoOperator to fetch the repository logger.info("Cloning repository...") if commit is None: - repo_operator = RepoOperator.create_from_repo(repo_path=repo_path, url=repo_url) + repo_config = RepoConfig.from_repo_path(repo_path) + repo_config.full_name = repo_full_name + repo_operator = RepoOperator(repo_config=repo_config, access_token=access_token, setup_option=setup_option) else: # Ensure the operator can handle remote operations - access_token = secrets.github_token if secrets else None repo_operator = RepoOperator.create_from_commit(repo_path=repo_path, commit=commit, url=repo_url, full_name=repo_full_name, access_token=access_token) logger.info("Clone completed successfully") diff --git a/tests/integration/codegen/git/codebase/conftest.py b/tests/integration/codegen/git/codebase/conftest.py index a8ab00e4f..4e163c87d 100644 --- a/tests/integration/codegen/git/codebase/conftest.py +++ b/tests/integration/codegen/git/codebase/conftest.py @@ -2,11 +2,12 @@ import pytest +from codegen.git.schemas.enums import SetupOption from codegen.sdk.core.codebase import Codebase @pytest.fixture def codebase(tmpdir): os.chdir(tmpdir) - codebase = Codebase.from_repo(repo_full_name="codegen-sh/Kevin-s-Adventure-Game", tmp_dir=tmpdir, language="python") + codebase = Codebase.from_repo(repo_full_name="codegen-sh/Kevin-s-Adventure-Game", tmp_dir=tmpdir, language="python", setup_option=SetupOption.PULL_OR_CLONE) yield codebase From 42b053741be5e6c948db19825dd81d8b478a8d28 Mon Sep 17 00:00:00 2001 From: codegen-team Date: Thu, 6 Mar 2025 20:35:17 +0000 Subject: [PATCH 41/66] docs: updated API reference --- docs/api-reference/core/Codebase.mdx | 62 ++++++++++++++-------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/api-reference/core/Codebase.mdx b/docs/api-reference/core/Codebase.mdx index bd47e4dd6..bcfbc0c38 100644 --- a/docs/api-reference/core/Codebase.mdx +++ b/docs/api-reference/core/Codebase.mdx @@ -11,7 +11,7 @@ import {HorizontalDivider} from '/snippets/HorizontalDivider.mdx'; import {GithubLinkNote} from '/snippets/GithubLinkNote.mdx'; import {Attribute} from '/snippets/Attribute.mdx'; - + ## Attributes @@ -89,7 +89,7 @@ import {Attribute} from '/snippets/Attribute.mdx'; ### ai Generates a response from the AI based on the provided prompt, target, and context. - + checkout Checks out a git branch or commit and syncs the codebase graph to the new state. - + commit Commits all staged changes to the codebase graph and synchronizes the graph with the filesystem if specified. - + create_directory Creates a directory at the specified path. - + create_file Creates a new file in the codebase with specified content. - + create_pr Creates a pull request from the current branch to the repository's default branch. - + create_pr_comment Create a comment on a pull request - + None } description=""/> @@ -265,7 +265,7 @@ Create a comment on a pull request ### create_pr_review_comment Create a review comment on a pull request. - + None } description=""/> @@ -273,7 +273,7 @@ Create a review comment on a pull request. ### files A list property that returns all files in the codebase. - + list[
SourceFile ] | list[ File ] } description="A sorted list of source files in the codebase."/> @@ -281,7 +281,7 @@ A list property that returns all files in the codebase. ### find_by_span Finds editable objects that overlap with the given source code span. - + from_files Creates a Codebase instance from multiple files. - + Codebase } description="A Codebase instance initialized with the provided files"/> @@ -306,7 +306,7 @@ Creates a Codebase instance from multiple files. ### from_repo Fetches a codebase from GitHub and returns a Codebase instance. - + from_string Creates a Codebase instance from a string of code. - + Codebase } description="A Codebase instance initialized with the provided code Example: >>> # Python code >>> code = "def add(a, b): return a + b" >>> codebase = Codebase.from_string(code, language="python") >>> # TypeScript code >>> code = "function add(a: number, b: number): number { return a + b; }" >>> codebase = Codebase.from_string(code, language="typescript")"/> @@ -367,7 +367,7 @@ Creates a Codebase instance from a string of code. ### get_class Returns a class that matches the given name. - + get_directory Returns Directory by `dir_path`, or full path to the directory from codebase root. - + get_file Retrieves a file from the codebase by its filepath. - + get_function Retrieves a function from the codebase by its name. - + get_modified_symbols_in_pr Get all modified symbols in a pull request - + tuple[str, dict[str, str], list[str]] } description=""/> @@ -473,7 +473,7 @@ Get all modified symbols in a pull request ### get_relative_path Calculates a relative path from one file to another, removing the extension from the target file. - + get_symbol Returns a Symbol by name from the codebase. - + get_symbols Retrieves all symbols in the codebase that match the given symbol name. - + git_commit Stages + commits all changes to the codebase and git. - + has_directory Returns a boolean indicating if a directory exists in the codebase. - + has_file Determines if a file exists in the codebase. - + has_symbol Returns whether a symbol exists in the codebase. - + reset Resets the codebase by - + None } description=""/> @@ -624,7 +624,7 @@ Resets the codebase by ### set_ai_key Sets the OpenAI key for the current Codebase instance. - + None } description=""/> @@ -632,7 +632,7 @@ Sets the OpenAI key for the current Codebase instance. ### set_session_options Sets the session options for the current codebase. - + should_fix Returns True if the flag should be fixed based on the current mode and active group. - + visualize Visualizes a NetworkX graph or Plotly figure. - + Date: Thu, 6 Mar 2025 20:38:31 +0000 Subject: [PATCH 42/66] update changelog --- docs/changelog/changelog.mdx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 4353d52bf..0746ef142 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,13 @@ icon: "clock" iconType: "solid" --- + +### [Fixes and documentation update with langsmith tagging.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.1) +- Updated API reference +- Fixed issue with Codebase.from_repo +- Enabled model name tagging for langsmith traces + + ### [adds view PR checks tool.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.0) - Add view PR checks tool From 997bcb5b6b1ed5cec086a5ecb58d5498abd94913 Mon Sep 17 00:00:00 2001 From: Christine Wang Date: Thu, 6 Mar 2025 13:04:42 -0800 Subject: [PATCH 43/66] fix: CG-10985 view PR returning 404 (#772) --- src/codegen/git/utils/pr_review.py | 44 ++++++++---------------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/src/codegen/git/utils/pr_review.py b/src/codegen/git/utils/pr_review.py index 4ebdc204a..ffb3f52f0 100644 --- a/src/codegen/git/utils/pr_review.py +++ b/src/codegen/git/utils/pr_review.py @@ -1,6 +1,5 @@ from typing import TYPE_CHECKING -import requests from github import Repository from github.PullRequest import PullRequest from unidiff import PatchSet @@ -39,28 +38,6 @@ def get_file_to_changed_ranges(pull_patch_set: PatchSet) -> dict[str, list]: return file_to_changed_ranges -def get_pull_patch_set(op: RepoOperator, pull: PullRequestContext) -> PatchSet: - # Get the diff directly from GitHub's API - if not op.remote_git_repo: - msg = "GitHub API client is required to get PR diffs" - raise ValueError(msg) - - # Get the diff directly from the PR - diff_url = pull.raw_data.get("diff_url") - if diff_url: - # Fetch the diff content from the URL - response = requests.get(diff_url) - response.raise_for_status() - diff = response.text - else: - # If diff_url not available, get the patch directly - diff = pull.get_patch() - - # Parse the diff into a PatchSet - pull_patch_set = PatchSet(diff) - return pull_patch_set - - def to_1_indexed(zero_indexed_range: range) -> range: """Converts a n-indexed range to n+1-indexed. Primarily to convert 0-indexed ranges to 1 indexed @@ -131,7 +108,7 @@ def __init__(self, op: RepoOperator, codebase: "Codebase", pr: PullRequest): def modified_file_ranges(self) -> dict[str, list[tuple[int, int]]]: """Files and the ranges within that are modified""" if not self._modified_file_ranges: - pull_patch_set = get_pull_patch_set(op=self._op, pull=self._gh_pr) + pull_patch_set = self.get_pull_patch_set() self._modified_file_ranges = get_file_to_changed_ranges(pull_patch_set) return self._modified_file_ranges @@ -174,15 +151,16 @@ def get_pr_diff(self) -> str: raise ValueError(msg) # Get the diff directly from the PR - diff_url = self._gh_pr.raw_data.get("diff_url") - if diff_url: - # Fetch the diff content from the URL - response = requests.get(diff_url) - response.raise_for_status() - return response.text - else: - # If diff_url not available, get the patch directly - return self._gh_pr.get_patch() + status, _, res = self._op.remote_git_repo.repo._requester.requestJson("GET", self._gh_pr.url, headers={"Accept": "application/vnd.github.v3.diff"}) + if status != 200: + msg = f"Failed to get PR diff: {res}" + raise Exception(msg) + return res + + def get_pull_patch_set(self) -> PatchSet: + diff = self.get_pr_diff() + pull_patch_set = PatchSet(diff) + return pull_patch_set def get_commit_sha(self) -> str: """Get the commit SHA of the PR""" From 66f33f5c1157725f3bdbb1c6ea281b89154f6609 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 6 Mar 2025 21:08:08 +0000 Subject: [PATCH 44/66] update changelog --- docs/changelog/changelog.mdx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 0746ef142..e84e789dc 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,11 @@ icon: "clock" iconType: "solid" --- + +### [Fixes PR viewing issue returning 404 error.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.2) +- Fix issue with viewing PR returning 404 + + ### [Fixes and documentation update with langsmith tagging.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.1) - Updated API reference From 5e8f95fee499e80aac17c0bfbdb670eb7478270f Mon Sep 17 00:00:00 2001 From: Edward Li Date: Thu, 6 Mar 2025 14:27:12 -0800 Subject: [PATCH 45/66] Add docs for Advanced Settings (#774) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- .../examples/sqlalchemy_soft_delete/README.md | 4 + docs/introduction/advanced-settings.mdx | 391 +++++++++ docs/introduction/getting-started.mdx | 33 + docs/mint.json | 757 +++++++++--------- 4 files changed, 806 insertions(+), 379 deletions(-) create mode 100644 docs/introduction/advanced-settings.mdx diff --git a/codegen-examples/examples/sqlalchemy_soft_delete/README.md b/codegen-examples/examples/sqlalchemy_soft_delete/README.md index b8c9a22db..52087e2e0 100644 --- a/codegen-examples/examples/sqlalchemy_soft_delete/README.md +++ b/codegen-examples/examples/sqlalchemy_soft_delete/README.md @@ -130,6 +130,10 @@ To run in no-graph mode: codebase = Codebase(str(repo_path), language="python", config=CodebaseConfig(disable_graph=True)) ``` + +To learn more about no-graph mode, see the [Advanced Settings](/introduction/advanced-settings) page. + + ## Running the Conversion ```bash diff --git a/docs/introduction/advanced-settings.mdx b/docs/introduction/advanced-settings.mdx new file mode 100644 index 000000000..e7297bd38 --- /dev/null +++ b/docs/introduction/advanced-settings.mdx @@ -0,0 +1,391 @@ +--- +title: "Advanced Settings" +sidebarTitle: "Advanced Settings" +icon: "memory" +iconType: "solid" +--- + +Codegen's [Codebase](/api-reference/core/Codebase) constructor accepts a `CodebaseConfig` object which is used to configure more advanced behaviors of the graph construction process. + +These flags are helpful for debugging problematic repos, optimizing Codegen's performance, or testing unreleased or experimental (potentially backwards-breaking) features. + + +**These are considered experimental features and may change in the future!** + +As such, they may have little to no testing or documentation. Many of these flags may also be unsupported in the future! + +If you need help, please visit our [community](/introduction/community). + + + +These configuration options are defined in [src/codegen/configs/models/codebase.py](https://github.com/codegen-sh/codegen/blob/develop/src/codegen/configs/models/codebase.py). + + +# Usage + +You can customize the behavior of the graph construction process when initializing a [Codebase](/api-reference/core/Codebase) by passing a `CodebaseConfig` object with the desired configuration flags. + +```python +from codegen import Codebase +from codegen.configs import CodebaseConfig + +# Initialize a Codebase with custom configuration +codebase = Codebase( + "", + config=CodebaseConfig( + flag1=..., + flag2=..., + ... + ) +) +``` + +# Table of Contents + +- [debug](#flag-debug) +- [verify-graph](#flag-verify-graph) +- [track-graph](#flag-track-graph) +- [method-usages](#flag-method-usages) +- [sync-enabled](#flag-sync-enabled) +- [full-range-index](#flag-full-range-index) +- [ignore-process-errors](#flag-ignore-process-errors) +- [disable-graph](#flag-disable-graph) +- [disable-file-parse](#flag-disable-file-parse) +- [exp-lazy-graph](#flag-exp-lazy-graph) +- [generics](#flag-generics) +- [import-resolution-paths](#flag-import-resolution-paths) +- [import-resolution-overrides](#flag-import-resolution-overrides) +- [py-resolve-syspath](#flag-py-resolve-syspath) +- [ts-dependency-manager](#flag-ts-dependency-manager) +- [ts-language-engine](#flag-ts-language-engine) +- [v8-ts-engine](#flag-v8-ts-engine) +- [unpacking-assignment-partial-removal](#flag-unpacking-assignment-partial-removal) + +# Configuration Flags + +## Flag: `debug` +> **Default: `False`** + +Enables verbose logging for debugging purposes. In its current form, it enables: +- Verbose logging when adding nodes to the graph +- Verbose logging during initial file parsing +- Additional assertions on graph creation +- Additional (costly) debug metrics on codebase construction +- etc. + + +This flag may be very noisy and significantly impact performance. It is generally not recommended to use. + + +## Flag: `verify_graph` +> **Default: `False`** + +Adds assertions for graph state during reset resync. Used to test and debug graph desyncs after a codebase reset. + +Runs `post_reset_validation` after a reset resync. + + +This is an internal debug flag. + + +## Flag: `track_graph` +> **Default: `False`** + +Keeps a copy of the original graph before a resync. Used in conjunction with `verify_graph` to test and debug graph desyncs. + +Original graph is saved as `ctx.old_graph`. + + +This is an internal debug flag. + + +## Flag: `method_usages` +> **Default: `True`** + +Enables and disables resolving method usages. + +**Example Codebase:** +```python +class Foo: + def bar(): + ... + +obj = Foo() +obj.bar() # Method Usage +``` + +**Codemod with `method_usages` on:** +```python +bar_func = codebase.get_class("Foo").get_method("bar") +len(bar_func.usages) # 1 +bar_func.usages # [obj.bar()] +``` + +**Codemod with `method_usages` off:** +```python +bar_func = codebase.get_class("Foo").get_method("bar") +len(bar_func.usages) # 0 +bar_func.usages # [] +``` + +Method usage resolution could be disabled for a marginal performance boost. However, it is generally recommended to leave it enabled. + +## Flag: `sync_enabled` +> **Default: `False`** + +Enables or disables graph sync during `codebase.commit`. + + +Implementation-specific details on sync graph can be found [here](https://github.com/codegen-sh/codegen/blob/develop/architecture/6.%20incremental-computation/C.%20Graph%20Recomputation.md). + + +This section won't go into the specific details of sync graph, but the general idea is that enabling sync graph will update the Codebase object to whatever new changes were made. + +**Example with `sync_enabled` on:** +```python +file = codebase.get_file(...) +file.insert_after("foobar = 1") +codebase.commit() + +foobar = codebase.get_symbol("foobar") +assert foobar # foobar is available after commit / graph sync +``` + +**Example with `sync_enabled` disabled:** +```python +file = codebase.get_file(...) +file.insert_after("foobar = 1") + +foobar = codebase.get_symbol("foobar", optional=True) +assert not foobar # foobar is not available after commit +``` + + +Enabling sync graph will have a performance impact on codebase commit, but will also unlock a bunch of operations that were previously not possible. + + +## Flag: `full_range_index` +> **Default: `False`** + +By default, Codebase maintains an internal range-to-node index for fast lookups. (i.e. `bytes 120 to 130 maps to node X`). +For optimization purposes, this only applies to nodes defined and handled by `parser.py`. + +Enabling `full_range_index` will create an additional index that maps **all** tree-sitter ranges to nodes. +This can be useful for debugging or when you need to build any applications that require a full range-to-node index (i.e. a codebase tree lookup). + + +This flag **significantly** increases memory usage! + + +## Flag: `ignore_process_errors` +> **Default: `True`** + +Controls whether to ignore errors that occur during external process execution (such as dependency manager or language engine). + +Disabling `ignore_process_errors` would make Codegen fail on errors that would otherwise be logged then ignored. + +## Flag: `disable_graph` +> **Default: `False`** + +Disables the graph construction process. Any operations that require the graph will no longer work. (In other words, this turns off import resolution and usage/dependency resolution) + +Functions that operate purely on AST such as getting and editing parameters or modifying function and class definitions will still work. + + +For codemods that do not require the graph (aka only AST/Syntax-level changes), **disabling graph parse could yield a 30%-40% decrease in parse time and memory usage**! + + +## Flag: `disable_file_parse` +> **Default: `False`** + +Disables **ALL** parsing, including file and graph parsing. This essentially treats all codebases as the "UNSUPPORTED" language mode. + +Nearly all functions except for editing primitives like `codebase.get_file` and `file.edit` will no longer work. + + +This flag is useful for any usages of Codegen that do **NOT** require any AST/CST/Graph parsing. (i.e. using Codegen purely as a file editing harness) + +If this is your use case, this **could decrease parse and memory usage by 95%.** + + +## Flag: `exp_lazy_graph` +> **Default: `False`** + +This experimental flag pushes the graph creation back until the graph is needed. This is an experimental feature and may have some unintended consequences. + +**Example Codemod:** +```python +from codegen import Codebase +from codegen.configs import CodebaseConfig + +# Enable lazy graph parsing +codebase = Codebase("", config=CodebaseConfig(exp_lazy_graph=True)) + +# The codebase object will be created immediately with no parsing done +# These all do not require graph parsing +codebase.files +codebase.directories +codebase.get_file("...") + +# These do require graph parsing, and will create the graph only if called +codebase.get_function("...") +codebase.get_class("...") +codebase.imports +``` + + +This may have a very slight performance boost. Use at your own risk! + + +## Flag: `generics` +> **Default: `True`** + +Enables and disables generic type resolution. + +**Example Codebase:** +```python +class Point: + def scale(cls, n: int): + pass + +class List[T](): + def pop(self) -> T: + ... + +l: List[Point] = [] +l.pop().scale(1) # Generic Usage +``` + +**Codemod with `generics` on:** +```python +bar_func = codebase.get_class("Point").get_method("scale") +len(bar_func.usages) # 1 +bar_func.usages # [l.pop().scale(1)] +``` + +**Codemod with `generics` off:** +```python +bar_func = codebase.get_class("Point").get_method("scale") +len(bar_func.usages) # 0 +bar_func.usages # [] +``` + + +Generic resolution is still largely WIP and experimental, and may not work in all cases. In some rare circumstances, disabling generics may result in a significant performance boost. + + +## Flag: `import_resolution_paths` +> **Default: `[]`** + +Controls alternative paths to resolve imports from. + +**Example Codebase:** +```python +# a/b/c/src.py +def update(): + pass + +# consumer.py +from c import src as operations + +operations.update() +``` + +**Codemod:** +```python +codebase.ctx.config.import_resolution_paths = ["a/b"] +``` + +## Flag: `import_resolution_overrides` +> **Default: `{}`** + +Controls import path overrides during import resolution. + +**Example** +`from a.b.c import d` with the override `a/b` -> `foo/bar` will internally resolve the import as `from foo.bar.c import d`. + +## Flag: `py_resolve_syspath` +> **Default: `False`** + +Enables and disables resolution of imports from `sys.path`. + +## Flag: `ts_dependency_manager` +> **Default: `False`** + + +**This is an internal flag used for Codegen Cloud and should not be used externally!** + +This flag **WILL** nuke any existing `node_modules` folder! + + + +This flag also assumes many constants for Codegen Cloud. Very likely this will not work if run locally. + +Instead, just install `node_modules` as normal (either through `npm`, `pnpm`, or `yarn`) and skip this setting! + + +Enables Codegen's internal dependency installer for TypeScript. This will modify `package.json` and install the bare minimum set of installable dependencies. + + +More documentation on TypeScript dependency manager can be found [here](https://github.com/codegen-sh/codegen/blob/develop/architecture/external/dependency-manager.md) + + +## Flag: `ts_language_engine` +> **Default: `False`** + + +This feature was built primarily with Codegen Cloud in mind. As such, this assumes a valid NodeJS and TypeScript environment. + + +Enables using the TypeScript compiler to extract information from the codebase. Enables commands such as `inferred_return_type`. + + +This will increase memory usage and parsing time. Larger repos may even hit resource constraints with the bundled TypeScript compiler integration. + + +## Flag: `v8_ts_engine` +> **Default: `False`** + + +This feature flag requires `ts_language_engine` to be enabled as well. + + +Enables using the **V8-based TypeScript compiler** to extract information from the codebase. Enables commands such as `inferred_return_type`. + +The V8 implementation (as opposed to the default external-process based implementation) is less stable, but provides the entire TypeScript API to be used from within Codegen. + + +This will increase memory usage and parsing time. Larger repos may even hit resource constraints with the V8-based TypeScript compiler integration. + + +## Flag: `unpacking_assignment_partial_removal` +> **Default: `False`** + +Enables smarter removal of unpacking assignments. + +**Example Codebase:** +```python +a, b, c = (1, 2, 3) +``` + +**Codemod with `unpacking_assignment_partial_removal` on:** +```python +file = codebase.get_file(...) +b = file.get_symbol("b") +b.remove() +codebase.commit() + +file.symbols # [a, c] +file.source # "a, c = (1, 3)" +``` + +**Codemod with `unpacking_assignment_partial_removal` off:** +```python +file = codebase.get_file(...) +b = file.get_symbol("b") +b.remove() +codebase.commit() + +file.symbols # [] +file.source # "" +``` diff --git a/docs/introduction/getting-started.mdx b/docs/introduction/getting-started.mdx index 50fd04e4d..ad9e2c5f2 100644 --- a/docs/introduction/getting-started.mdx +++ b/docs/introduction/getting-started.mdx @@ -276,6 +276,39 @@ if base_class: references](/building-with-codegen/dependencies-and-usages) or [imports](/building-with-codegen/imports) and [exports](/building-with-codegen/exports). +## Advanced Settings + +Codegen also supports a number of advanced settings that can be used to customize the behavior of the graph construction process. + +These flags are helpful for debugging problematic repos, optimizing Codegen’s performance, or testing unreleased or experimental (potentially backwards-breaking) features. + +```python +from codegen import Codebase +from codegen.configs import CodebaseConfig + +# Initialize a Codebase with custom configuration +codebase = Codebase( + "path/to/git/repo"", + config=CodebaseConfig( + verify_graph=True, + method_usages=False, + sync_enabled=True, + generics=False, + import_resolution_overrides={ + "old_module": "new_module" + }, + ts_language_engine=True, + v8_ts_engine=True + ) +) +``` + +To learn more about available settings, see the [Advanced Settings](/introduction/advanced-settings) page. + + +These are considered experimental and unstable features that may be removed or changed in the future. + + ## What's Next? diff --git a/docs/mint.json b/docs/mint.json index d0bb0c07b..cec15a787 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -1,380 +1,379 @@ { - "$schema": "https://mintlify.com/schema.json", - "name": "Codegen", - "logo": { - "dark": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45a3e32761c42b324b_Codegen_Logomark_Dark.svg", - "light": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45bf55446746125835_Codegen_Logomark_Light.svg" - }, - "modeToggle": { - "default": "dark" - }, - "metadata": { - "og:site_name": "Codegen", - "og:title": "Codegen - Manipulate Code at Scale", - "og:description": "A scriptable interface to a powerful, multi-lingual language server built on top of Tree-sitter.", - "og:url": "https://docs.codegen.com", - "og:locale": "en_US", - "og:logo": "https://i.imgur.com/f4OVOqI.png", - "article:publisher": "Codegen, Inc.", - "twitter:site": "@codegen" - }, - "favicon": "/favicon.svg", - "colors": { - "primary": "#a277ff", - "light": "#a277ff", - "dark": "#a277ff", - "anchors": { - "from": "#61ffca", - "to": "#61ffca" - } - }, - "theme": "prism", - "background": { - "style": "gradient" - }, - "analytics": { - "posthog": { - "apiKey": "phc_GLxaINoQJnuyCyxDmTciQqzdKBYFVDkY7bRBO4bDdso" - } - }, - "feedback": { - "thumbsRating": true - }, - "topbarCtaButton": { - "name": "GitHub", - "url": "https://github.com/codegen-sh/codegen-sdk" - }, - "tabs": [ - { - "name": "API Reference", - "url": "/api-reference" - }, - { - "name": "CLI", - "url": "/cli" - }, - { - "name": "Blog", - "url": "/blog" - }, - { - "name": "Changelog", - "url": "/changelog" - } - ], - "navigation": [ - { - "group": "Introduction", - "pages": [ - "introduction/overview", - "introduction/getting-started", - "introduction/installation", - "introduction/ide-usage", - "introduction/work-with-ai", - "introduction/how-it-works", - "introduction/guiding-principles", - "introduction/community", - "introduction/about", - "introduction/faq" - ] - }, - { - "group": "Tutorials", - "pages": [ - "tutorials/at-a-glance", - "tutorials/build-code-agent", - "tutorials/slack-bot", - "tutorials/github-review-bot", - "tutorials/deep-code-research", - "tutorials/training-data", - "tutorials/codebase-visualization", - "tutorials/migrating-apis", - "tutorials/organize-your-codebase", - "tutorials/promise-to-async-await", - "tutorials/modularity", - "tutorials/manage-feature-flags", - "tutorials/deleting-dead-code", - "tutorials/increase-type-coverage", - "tutorials/managing-typescript-exports", - "tutorials/converting-default-exports", - "tutorials/creating-documentation", - "tutorials/react-modernization", - "tutorials/unittest-to-pytest", - "tutorials/sqlalchemy-1.6-to-2.0", - "tutorials/fixing-import-loops-in-pytorch", - "tutorials/python2-to-python3", - "tutorials/flask-to-fastapi", - "tutorials/build-mcp", - "tutorials/neo4j-graph" - ] - }, - { - "group": "Building with Codegen", - "pages": [ - "building-with-codegen/at-a-glance", - "building-with-codegen/parsing-codebases", - "building-with-codegen/reusable-codemods", - "building-with-codegen/dot-codegen", - "building-with-codegen/function-decorator", - "building-with-codegen/language-support", - "building-with-codegen/commit-and-reset", - "building-with-codegen/git-operations", - "building-with-codegen/files-and-directories", - "building-with-codegen/the-editable-api", - "building-with-codegen/symbol-api", - "building-with-codegen/class-api", - "building-with-codegen/imports", - "building-with-codegen/exports", - "building-with-codegen/inheritable-behaviors", - "building-with-codegen/statements-and-code-blocks", - "building-with-codegen/dependencies-and-usages", - "building-with-codegen/function-calls-and-callsites", - "building-with-codegen/variable-assignments", - "building-with-codegen/local-variables", - "building-with-codegen/comments-and-docstrings", - "building-with-codegen/external-modules", - "building-with-codegen/type-annotations", - "building-with-codegen/moving-symbols", - "building-with-codegen/collections", - "building-with-codegen/traversing-the-call-graph", - "building-with-codegen/react-and-jsx", - "building-with-codegen/codebase-visualization", - "building-with-codegen/flagging-symbols", - "building-with-codegen/calling-out-to-llms", - "building-with-codegen/semantic-code-search", - "building-with-codegen/reducing-conditions" - ] - }, - { - "group": "CLI", - "pages": [ - "cli/about", - "cli/init", - "cli/notebook", - "cli/create", - "cli/run", - "cli/reset", - "cli/expert" - ] - }, - { - "group": "Changelog", - "pages": [ - "changelog/changelog" - ] - }, - { - "group": "Blog", - "pages": [ - "blog/posts", - "blog/devin", - "blog/act-via-code", - "blog/promise-to-async-await-twilio", - "blog/fixing-import-loops" - ] - }, - { - "group": "API Reference", - "pages": [ - "api-reference/index", - { - "group": "Core", - "icon": "code", - "pages": [ - "api-reference/core/Argument", - "api-reference/core/Assignment", - "api-reference/core/AssignmentStatement", - "api-reference/core/Attribute", - "api-reference/core/AwaitExpression", - "api-reference/core/BinaryExpression", - "api-reference/core/BlockStatement", - "api-reference/core/Boolean", - "api-reference/core/Callable", - "api-reference/core/CatchStatement", - "api-reference/core/ChainedAttribute", - "api-reference/core/Class", - "api-reference/core/CodeBlock", - "api-reference/core/CodeOwner", - "api-reference/core/Codebase", - "api-reference/core/Comment", - "api-reference/core/CommentGroup", - "api-reference/core/ComparisonExpression", - "api-reference/core/Decorator", - "api-reference/core/Dict", - "api-reference/core/Directory", - "api-reference/core/Editable", - "api-reference/core/Export", - "api-reference/core/ExportStatement", - "api-reference/core/Exportable", - "api-reference/core/Expression", - "api-reference/core/ExpressionGroup", - "api-reference/core/ExpressionStatement", - "api-reference/core/ExternalModule", - "api-reference/core/File", - "api-reference/core/FlagKwargs", - "api-reference/core/ForLoopStatement", - "api-reference/core/Function", - "api-reference/core/FunctionCall", - "api-reference/core/GenericType", - "api-reference/core/HasBlock", - "api-reference/core/HasName", - "api-reference/core/HasValue", - "api-reference/core/IfBlockStatement", - "api-reference/core/Import", - "api-reference/core/ImportStatement", - "api-reference/core/ImportType", - "api-reference/core/Importable", - "api-reference/core/Interface", - "api-reference/core/List", - "api-reference/core/MessageType", - "api-reference/core/MultiExpression", - "api-reference/core/MultiLineCollection", - "api-reference/core/Name", - "api-reference/core/NamedType", - "api-reference/core/NoneType", - "api-reference/core/Number", - "api-reference/core/Pair", - "api-reference/core/Parameter", - "api-reference/core/ParenthesizedExpression", - "api-reference/core/Placeholder", - "api-reference/core/PlaceholderType", - "api-reference/core/RaiseStatement", - "api-reference/core/ReturnStatement", - "api-reference/core/SourceFile", - "api-reference/core/Span", - "api-reference/core/Statement", - "api-reference/core/StatementType", - "api-reference/core/String", - "api-reference/core/StubPlaceholder", - "api-reference/core/SubscriptExpression", - "api-reference/core/SwitchCase", - "api-reference/core/SwitchStatement", - "api-reference/core/Symbol", - "api-reference/core/SymbolGroup", - "api-reference/core/SymbolStatement", - "api-reference/core/TernaryExpression", - "api-reference/core/TryCatchStatement", - "api-reference/core/Tuple", - "api-reference/core/TupleType", - "api-reference/core/Type", - "api-reference/core/TypeAlias", - "api-reference/core/TypePlaceholder", - "api-reference/core/Typeable", - "api-reference/core/UnaryExpression", - "api-reference/core/UnionType", - "api-reference/core/Unpack", - "api-reference/core/Unwrappable", - "api-reference/core/Usable", - "api-reference/core/Usage", - "api-reference/core/UsageKind", - "api-reference/core/UsageType", - "api-reference/core/Value", - "api-reference/core/WhileStatement", - "api-reference/core/WithStatement" - ] - }, - { - "group": "Python", - "icon": "python", - "pages": [ - "api-reference/python/PyAssignment", - "api-reference/python/PyAssignmentStatement", - "api-reference/python/PyAttribute", - "api-reference/python/PyBlockStatement", - "api-reference/python/PyBreakStatement", - "api-reference/python/PyCatchStatement", - "api-reference/python/PyChainedAttribute", - "api-reference/python/PyClass", - "api-reference/python/PyCodeBlock", - "api-reference/python/PyComment", - "api-reference/python/PyCommentGroup", - "api-reference/python/PyCommentType", - "api-reference/python/PyConditionalExpression", - "api-reference/python/PyDecorator", - "api-reference/python/PyFile", - "api-reference/python/PyForLoopStatement", - "api-reference/python/PyFunction", - "api-reference/python/PyGenericType", - "api-reference/python/PyHasBlock", - "api-reference/python/PyIfBlockStatement", - "api-reference/python/PyImport", - "api-reference/python/PyImportStatement", - "api-reference/python/PyMatchCase", - "api-reference/python/PyMatchStatement", - "api-reference/python/PyNamedType", - "api-reference/python/PyParameter", - "api-reference/python/PyPassStatement", - "api-reference/python/PyReturnTypePlaceholder", - "api-reference/python/PyString", - "api-reference/python/PySymbol", - "api-reference/python/PyTryCatchStatement", - "api-reference/python/PyUnionType", - "api-reference/python/PyWhileStatement" - ] - }, - { - "group": "Typescript", - "icon": "js", - "pages": [ - "api-reference/typescript/JSXElement", - "api-reference/typescript/JSXExpression", - "api-reference/typescript/JSXProp", - "api-reference/typescript/TSArrayType", - "api-reference/typescript/TSAssignment", - "api-reference/typescript/TSAssignmentStatement", - "api-reference/typescript/TSAttribute", - "api-reference/typescript/TSBlockStatement", - "api-reference/typescript/TSCatchStatement", - "api-reference/typescript/TSChainedAttribute", - "api-reference/typescript/TSClass", - "api-reference/typescript/TSCodeBlock", - "api-reference/typescript/TSComment", - "api-reference/typescript/TSCommentGroup", - "api-reference/typescript/TSCommentType", - "api-reference/typescript/TSConditionalType", - "api-reference/typescript/TSConfig", - "api-reference/typescript/TSDecorator", - "api-reference/typescript/TSDict", - "api-reference/typescript/TSEnum", - "api-reference/typescript/TSExport", - "api-reference/typescript/TSExpressionType", - "api-reference/typescript/TSFile", - "api-reference/typescript/TSForLoopStatement", - "api-reference/typescript/TSFunction", - "api-reference/typescript/TSFunctionType", - "api-reference/typescript/TSGenericType", - "api-reference/typescript/TSHasBlock", - "api-reference/typescript/TSIfBlockStatement", - "api-reference/typescript/TSImport", - "api-reference/typescript/TSImportStatement", - "api-reference/typescript/TSInterface", - "api-reference/typescript/TSLabeledStatement", - "api-reference/typescript/TSLookupType", - "api-reference/typescript/TSNamedType", - "api-reference/typescript/TSNamespace", - "api-reference/typescript/TSObjectType", - "api-reference/typescript/TSPair", - "api-reference/typescript/TSParameter", - "api-reference/typescript/TSQueryType", - "api-reference/typescript/TSReadonlyType", - "api-reference/typescript/TSReturnTypePlaceholder", - "api-reference/typescript/TSString", - "api-reference/typescript/TSSwitchCase", - "api-reference/typescript/TSSwitchStatement", - "api-reference/typescript/TSSymbol", - "api-reference/typescript/TSTernaryExpression", - "api-reference/typescript/TSTryCatchStatement", - "api-reference/typescript/TSTypeAlias", - "api-reference/typescript/TSUndefinedType", - "api-reference/typescript/TSUnionType", - "api-reference/typescript/TSWhileStatement" - ] - } - ] - } - ], - "footerSocials": { - "x": "https://x.com/codegen", - "linkedin": "https://linkedin.com/company/codegen-dot-com" - } -} \ No newline at end of file + "$schema": "https://mintlify.com/schema.json", + "name": "Codegen", + "logo": { + "dark": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45a3e32761c42b324b_Codegen_Logomark_Dark.svg", + "light": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45bf55446746125835_Codegen_Logomark_Light.svg" + }, + "modeToggle": { + "default": "dark" + }, + "metadata": { + "og:site_name": "Codegen", + "og:title": "Codegen - Manipulate Code at Scale", + "og:description": "A scriptable interface to a powerful, multi-lingual language server built on top of Tree-sitter.", + "og:url": "https://docs.codegen.com", + "og:locale": "en_US", + "og:logo": "https://i.imgur.com/f4OVOqI.png", + "article:publisher": "Codegen, Inc.", + "twitter:site": "@codegen" + }, + "favicon": "/favicon.svg", + "colors": { + "primary": "#a277ff", + "light": "#a277ff", + "dark": "#a277ff", + "anchors": { + "from": "#61ffca", + "to": "#61ffca" + } + }, + "theme": "prism", + "background": { + "style": "gradient" + }, + "analytics": { + "posthog": { + "apiKey": "phc_GLxaINoQJnuyCyxDmTciQqzdKBYFVDkY7bRBO4bDdso" + } + }, + "feedback": { + "thumbsRating": true + }, + "topbarCtaButton": { + "name": "GitHub", + "url": "https://github.com/codegen-sh/codegen-sdk" + }, + "tabs": [ + { + "name": "API Reference", + "url": "/api-reference" + }, + { + "name": "CLI", + "url": "/cli" + }, + { + "name": "Blog", + "url": "/blog" + }, + { + "name": "Changelog", + "url": "/changelog" + } + ], + "navigation": [ + { + "group": "Introduction", + "pages": [ + "introduction/overview", + "introduction/getting-started", + "introduction/installation", + "introduction/ide-usage", + "introduction/work-with-ai", + "introduction/how-it-works", + "introduction/advanced-settings", + "introduction/guiding-principles", + "introduction/community", + "introduction/about", + "introduction/faq" + ] + }, + { + "group": "Tutorials", + "pages": [ + "tutorials/at-a-glance", + "tutorials/build-code-agent", + "tutorials/slack-bot", + "tutorials/github-review-bot", + "tutorials/deep-code-research", + "tutorials/training-data", + "tutorials/codebase-visualization", + "tutorials/migrating-apis", + "tutorials/organize-your-codebase", + "tutorials/promise-to-async-await", + "tutorials/modularity", + "tutorials/manage-feature-flags", + "tutorials/deleting-dead-code", + "tutorials/increase-type-coverage", + "tutorials/managing-typescript-exports", + "tutorials/converting-default-exports", + "tutorials/creating-documentation", + "tutorials/react-modernization", + "tutorials/unittest-to-pytest", + "tutorials/sqlalchemy-1.6-to-2.0", + "tutorials/fixing-import-loops-in-pytorch", + "tutorials/python2-to-python3", + "tutorials/flask-to-fastapi", + "tutorials/build-mcp", + "tutorials/neo4j-graph" + ] + }, + { + "group": "Building with Codegen", + "pages": [ + "building-with-codegen/at-a-glance", + "building-with-codegen/parsing-codebases", + "building-with-codegen/reusable-codemods", + "building-with-codegen/dot-codegen", + "building-with-codegen/function-decorator", + "building-with-codegen/language-support", + "building-with-codegen/commit-and-reset", + "building-with-codegen/git-operations", + "building-with-codegen/files-and-directories", + "building-with-codegen/the-editable-api", + "building-with-codegen/symbol-api", + "building-with-codegen/class-api", + "building-with-codegen/imports", + "building-with-codegen/exports", + "building-with-codegen/inheritable-behaviors", + "building-with-codegen/statements-and-code-blocks", + "building-with-codegen/dependencies-and-usages", + "building-with-codegen/function-calls-and-callsites", + "building-with-codegen/variable-assignments", + "building-with-codegen/local-variables", + "building-with-codegen/comments-and-docstrings", + "building-with-codegen/external-modules", + "building-with-codegen/type-annotations", + "building-with-codegen/moving-symbols", + "building-with-codegen/collections", + "building-with-codegen/traversing-the-call-graph", + "building-with-codegen/react-and-jsx", + "building-with-codegen/codebase-visualization", + "building-with-codegen/flagging-symbols", + "building-with-codegen/calling-out-to-llms", + "building-with-codegen/semantic-code-search", + "building-with-codegen/reducing-conditions" + ] + }, + { + "group": "CLI", + "pages": [ + "cli/about", + "cli/init", + "cli/notebook", + "cli/create", + "cli/run", + "cli/reset", + "cli/expert" + ] + }, + { + "group": "Changelog", + "pages": ["changelog/changelog"] + }, + { + "group": "Blog", + "pages": [ + "blog/posts", + "blog/devin", + "blog/act-via-code", + "blog/promise-to-async-await-twilio", + "blog/fixing-import-loops" + ] + }, + { + "group": "API Reference", + "pages": [ + "api-reference/index", + { + "group": "Core", + "icon": "code", + "pages": [ + "api-reference/core/Argument", + "api-reference/core/Assignment", + "api-reference/core/AssignmentStatement", + "api-reference/core/Attribute", + "api-reference/core/AwaitExpression", + "api-reference/core/BinaryExpression", + "api-reference/core/BlockStatement", + "api-reference/core/Boolean", + "api-reference/core/Callable", + "api-reference/core/CatchStatement", + "api-reference/core/ChainedAttribute", + "api-reference/core/Class", + "api-reference/core/CodeBlock", + "api-reference/core/CodeOwner", + "api-reference/core/Codebase", + "api-reference/core/Comment", + "api-reference/core/CommentGroup", + "api-reference/core/ComparisonExpression", + "api-reference/core/Decorator", + "api-reference/core/Dict", + "api-reference/core/Directory", + "api-reference/core/Editable", + "api-reference/core/Export", + "api-reference/core/ExportStatement", + "api-reference/core/Exportable", + "api-reference/core/Expression", + "api-reference/core/ExpressionGroup", + "api-reference/core/ExpressionStatement", + "api-reference/core/ExternalModule", + "api-reference/core/File", + "api-reference/core/FlagKwargs", + "api-reference/core/ForLoopStatement", + "api-reference/core/Function", + "api-reference/core/FunctionCall", + "api-reference/core/GenericType", + "api-reference/core/HasBlock", + "api-reference/core/HasName", + "api-reference/core/HasValue", + "api-reference/core/IfBlockStatement", + "api-reference/core/Import", + "api-reference/core/ImportStatement", + "api-reference/core/ImportType", + "api-reference/core/Importable", + "api-reference/core/Interface", + "api-reference/core/List", + "api-reference/core/MessageType", + "api-reference/core/MultiExpression", + "api-reference/core/MultiLineCollection", + "api-reference/core/Name", + "api-reference/core/NamedType", + "api-reference/core/NoneType", + "api-reference/core/Number", + "api-reference/core/Pair", + "api-reference/core/Parameter", + "api-reference/core/ParenthesizedExpression", + "api-reference/core/Placeholder", + "api-reference/core/PlaceholderType", + "api-reference/core/RaiseStatement", + "api-reference/core/ReturnStatement", + "api-reference/core/SourceFile", + "api-reference/core/Span", + "api-reference/core/Statement", + "api-reference/core/StatementType", + "api-reference/core/String", + "api-reference/core/StubPlaceholder", + "api-reference/core/SubscriptExpression", + "api-reference/core/SwitchCase", + "api-reference/core/SwitchStatement", + "api-reference/core/Symbol", + "api-reference/core/SymbolGroup", + "api-reference/core/SymbolStatement", + "api-reference/core/TernaryExpression", + "api-reference/core/TryCatchStatement", + "api-reference/core/Tuple", + "api-reference/core/TupleType", + "api-reference/core/Type", + "api-reference/core/TypeAlias", + "api-reference/core/TypePlaceholder", + "api-reference/core/Typeable", + "api-reference/core/UnaryExpression", + "api-reference/core/UnionType", + "api-reference/core/Unpack", + "api-reference/core/Unwrappable", + "api-reference/core/Usable", + "api-reference/core/Usage", + "api-reference/core/UsageKind", + "api-reference/core/UsageType", + "api-reference/core/Value", + "api-reference/core/WhileStatement", + "api-reference/core/WithStatement" + ] + }, + { + "group": "Python", + "icon": "python", + "pages": [ + "api-reference/python/PyAssignment", + "api-reference/python/PyAssignmentStatement", + "api-reference/python/PyAttribute", + "api-reference/python/PyBlockStatement", + "api-reference/python/PyBreakStatement", + "api-reference/python/PyCatchStatement", + "api-reference/python/PyChainedAttribute", + "api-reference/python/PyClass", + "api-reference/python/PyCodeBlock", + "api-reference/python/PyComment", + "api-reference/python/PyCommentGroup", + "api-reference/python/PyCommentType", + "api-reference/python/PyConditionalExpression", + "api-reference/python/PyDecorator", + "api-reference/python/PyFile", + "api-reference/python/PyForLoopStatement", + "api-reference/python/PyFunction", + "api-reference/python/PyGenericType", + "api-reference/python/PyHasBlock", + "api-reference/python/PyIfBlockStatement", + "api-reference/python/PyImport", + "api-reference/python/PyImportStatement", + "api-reference/python/PyMatchCase", + "api-reference/python/PyMatchStatement", + "api-reference/python/PyNamedType", + "api-reference/python/PyParameter", + "api-reference/python/PyPassStatement", + "api-reference/python/PyReturnTypePlaceholder", + "api-reference/python/PyString", + "api-reference/python/PySymbol", + "api-reference/python/PyTryCatchStatement", + "api-reference/python/PyUnionType", + "api-reference/python/PyWhileStatement" + ] + }, + { + "group": "Typescript", + "icon": "js", + "pages": [ + "api-reference/typescript/JSXElement", + "api-reference/typescript/JSXExpression", + "api-reference/typescript/JSXProp", + "api-reference/typescript/TSArrayType", + "api-reference/typescript/TSAssignment", + "api-reference/typescript/TSAssignmentStatement", + "api-reference/typescript/TSAttribute", + "api-reference/typescript/TSBlockStatement", + "api-reference/typescript/TSCatchStatement", + "api-reference/typescript/TSChainedAttribute", + "api-reference/typescript/TSClass", + "api-reference/typescript/TSCodeBlock", + "api-reference/typescript/TSComment", + "api-reference/typescript/TSCommentGroup", + "api-reference/typescript/TSCommentType", + "api-reference/typescript/TSConditionalType", + "api-reference/typescript/TSConfig", + "api-reference/typescript/TSDecorator", + "api-reference/typescript/TSDict", + "api-reference/typescript/TSEnum", + "api-reference/typescript/TSExport", + "api-reference/typescript/TSExpressionType", + "api-reference/typescript/TSFile", + "api-reference/typescript/TSForLoopStatement", + "api-reference/typescript/TSFunction", + "api-reference/typescript/TSFunctionType", + "api-reference/typescript/TSGenericType", + "api-reference/typescript/TSHasBlock", + "api-reference/typescript/TSIfBlockStatement", + "api-reference/typescript/TSImport", + "api-reference/typescript/TSImportStatement", + "api-reference/typescript/TSInterface", + "api-reference/typescript/TSLabeledStatement", + "api-reference/typescript/TSLookupType", + "api-reference/typescript/TSNamedType", + "api-reference/typescript/TSNamespace", + "api-reference/typescript/TSObjectType", + "api-reference/typescript/TSPair", + "api-reference/typescript/TSParameter", + "api-reference/typescript/TSQueryType", + "api-reference/typescript/TSReadonlyType", + "api-reference/typescript/TSReturnTypePlaceholder", + "api-reference/typescript/TSString", + "api-reference/typescript/TSSwitchCase", + "api-reference/typescript/TSSwitchStatement", + "api-reference/typescript/TSSymbol", + "api-reference/typescript/TSTernaryExpression", + "api-reference/typescript/TSTryCatchStatement", + "api-reference/typescript/TSTypeAlias", + "api-reference/typescript/TSUndefinedType", + "api-reference/typescript/TSUnionType", + "api-reference/typescript/TSWhileStatement" + ] + } + ] + } + ], + "footerSocials": { + "x": "https://x.com/codegen", + "linkedin": "https://linkedin.com/company/codegen-dot-com" + } +} From c6f2f5ad5b28a26bb59a7fa8d170f873ee3a1e96 Mon Sep 17 00:00:00 2001 From: codegen-team Date: Thu, 6 Mar 2025 22:28:40 +0000 Subject: [PATCH 46/66] docs: updated API reference --- docs/mint.json | 758 +++++++++++++++--------------- src/codegen/sdk/system-prompt.txt | 426 +++++++++++++++++ 2 files changed, 806 insertions(+), 378 deletions(-) diff --git a/docs/mint.json b/docs/mint.json index cec15a787..5a33f2590 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -1,379 +1,381 @@ { - "$schema": "https://mintlify.com/schema.json", - "name": "Codegen", - "logo": { - "dark": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45a3e32761c42b324b_Codegen_Logomark_Dark.svg", - "light": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45bf55446746125835_Codegen_Logomark_Light.svg" - }, - "modeToggle": { - "default": "dark" - }, - "metadata": { - "og:site_name": "Codegen", - "og:title": "Codegen - Manipulate Code at Scale", - "og:description": "A scriptable interface to a powerful, multi-lingual language server built on top of Tree-sitter.", - "og:url": "https://docs.codegen.com", - "og:locale": "en_US", - "og:logo": "https://i.imgur.com/f4OVOqI.png", - "article:publisher": "Codegen, Inc.", - "twitter:site": "@codegen" - }, - "favicon": "/favicon.svg", - "colors": { - "primary": "#a277ff", - "light": "#a277ff", - "dark": "#a277ff", - "anchors": { - "from": "#61ffca", - "to": "#61ffca" - } - }, - "theme": "prism", - "background": { - "style": "gradient" - }, - "analytics": { - "posthog": { - "apiKey": "phc_GLxaINoQJnuyCyxDmTciQqzdKBYFVDkY7bRBO4bDdso" - } - }, - "feedback": { - "thumbsRating": true - }, - "topbarCtaButton": { - "name": "GitHub", - "url": "https://github.com/codegen-sh/codegen-sdk" - }, - "tabs": [ - { - "name": "API Reference", - "url": "/api-reference" - }, - { - "name": "CLI", - "url": "/cli" - }, - { - "name": "Blog", - "url": "/blog" - }, - { - "name": "Changelog", - "url": "/changelog" - } - ], - "navigation": [ - { - "group": "Introduction", - "pages": [ - "introduction/overview", - "introduction/getting-started", - "introduction/installation", - "introduction/ide-usage", - "introduction/work-with-ai", - "introduction/how-it-works", - "introduction/advanced-settings", - "introduction/guiding-principles", - "introduction/community", - "introduction/about", - "introduction/faq" - ] - }, - { - "group": "Tutorials", - "pages": [ - "tutorials/at-a-glance", - "tutorials/build-code-agent", - "tutorials/slack-bot", - "tutorials/github-review-bot", - "tutorials/deep-code-research", - "tutorials/training-data", - "tutorials/codebase-visualization", - "tutorials/migrating-apis", - "tutorials/organize-your-codebase", - "tutorials/promise-to-async-await", - "tutorials/modularity", - "tutorials/manage-feature-flags", - "tutorials/deleting-dead-code", - "tutorials/increase-type-coverage", - "tutorials/managing-typescript-exports", - "tutorials/converting-default-exports", - "tutorials/creating-documentation", - "tutorials/react-modernization", - "tutorials/unittest-to-pytest", - "tutorials/sqlalchemy-1.6-to-2.0", - "tutorials/fixing-import-loops-in-pytorch", - "tutorials/python2-to-python3", - "tutorials/flask-to-fastapi", - "tutorials/build-mcp", - "tutorials/neo4j-graph" - ] - }, - { - "group": "Building with Codegen", - "pages": [ - "building-with-codegen/at-a-glance", - "building-with-codegen/parsing-codebases", - "building-with-codegen/reusable-codemods", - "building-with-codegen/dot-codegen", - "building-with-codegen/function-decorator", - "building-with-codegen/language-support", - "building-with-codegen/commit-and-reset", - "building-with-codegen/git-operations", - "building-with-codegen/files-and-directories", - "building-with-codegen/the-editable-api", - "building-with-codegen/symbol-api", - "building-with-codegen/class-api", - "building-with-codegen/imports", - "building-with-codegen/exports", - "building-with-codegen/inheritable-behaviors", - "building-with-codegen/statements-and-code-blocks", - "building-with-codegen/dependencies-and-usages", - "building-with-codegen/function-calls-and-callsites", - "building-with-codegen/variable-assignments", - "building-with-codegen/local-variables", - "building-with-codegen/comments-and-docstrings", - "building-with-codegen/external-modules", - "building-with-codegen/type-annotations", - "building-with-codegen/moving-symbols", - "building-with-codegen/collections", - "building-with-codegen/traversing-the-call-graph", - "building-with-codegen/react-and-jsx", - "building-with-codegen/codebase-visualization", - "building-with-codegen/flagging-symbols", - "building-with-codegen/calling-out-to-llms", - "building-with-codegen/semantic-code-search", - "building-with-codegen/reducing-conditions" - ] - }, - { - "group": "CLI", - "pages": [ - "cli/about", - "cli/init", - "cli/notebook", - "cli/create", - "cli/run", - "cli/reset", - "cli/expert" - ] - }, - { - "group": "Changelog", - "pages": ["changelog/changelog"] - }, - { - "group": "Blog", - "pages": [ - "blog/posts", - "blog/devin", - "blog/act-via-code", - "blog/promise-to-async-await-twilio", - "blog/fixing-import-loops" - ] - }, - { - "group": "API Reference", - "pages": [ - "api-reference/index", - { - "group": "Core", - "icon": "code", - "pages": [ - "api-reference/core/Argument", - "api-reference/core/Assignment", - "api-reference/core/AssignmentStatement", - "api-reference/core/Attribute", - "api-reference/core/AwaitExpression", - "api-reference/core/BinaryExpression", - "api-reference/core/BlockStatement", - "api-reference/core/Boolean", - "api-reference/core/Callable", - "api-reference/core/CatchStatement", - "api-reference/core/ChainedAttribute", - "api-reference/core/Class", - "api-reference/core/CodeBlock", - "api-reference/core/CodeOwner", - "api-reference/core/Codebase", - "api-reference/core/Comment", - "api-reference/core/CommentGroup", - "api-reference/core/ComparisonExpression", - "api-reference/core/Decorator", - "api-reference/core/Dict", - "api-reference/core/Directory", - "api-reference/core/Editable", - "api-reference/core/Export", - "api-reference/core/ExportStatement", - "api-reference/core/Exportable", - "api-reference/core/Expression", - "api-reference/core/ExpressionGroup", - "api-reference/core/ExpressionStatement", - "api-reference/core/ExternalModule", - "api-reference/core/File", - "api-reference/core/FlagKwargs", - "api-reference/core/ForLoopStatement", - "api-reference/core/Function", - "api-reference/core/FunctionCall", - "api-reference/core/GenericType", - "api-reference/core/HasBlock", - "api-reference/core/HasName", - "api-reference/core/HasValue", - "api-reference/core/IfBlockStatement", - "api-reference/core/Import", - "api-reference/core/ImportStatement", - "api-reference/core/ImportType", - "api-reference/core/Importable", - "api-reference/core/Interface", - "api-reference/core/List", - "api-reference/core/MessageType", - "api-reference/core/MultiExpression", - "api-reference/core/MultiLineCollection", - "api-reference/core/Name", - "api-reference/core/NamedType", - "api-reference/core/NoneType", - "api-reference/core/Number", - "api-reference/core/Pair", - "api-reference/core/Parameter", - "api-reference/core/ParenthesizedExpression", - "api-reference/core/Placeholder", - "api-reference/core/PlaceholderType", - "api-reference/core/RaiseStatement", - "api-reference/core/ReturnStatement", - "api-reference/core/SourceFile", - "api-reference/core/Span", - "api-reference/core/Statement", - "api-reference/core/StatementType", - "api-reference/core/String", - "api-reference/core/StubPlaceholder", - "api-reference/core/SubscriptExpression", - "api-reference/core/SwitchCase", - "api-reference/core/SwitchStatement", - "api-reference/core/Symbol", - "api-reference/core/SymbolGroup", - "api-reference/core/SymbolStatement", - "api-reference/core/TernaryExpression", - "api-reference/core/TryCatchStatement", - "api-reference/core/Tuple", - "api-reference/core/TupleType", - "api-reference/core/Type", - "api-reference/core/TypeAlias", - "api-reference/core/TypePlaceholder", - "api-reference/core/Typeable", - "api-reference/core/UnaryExpression", - "api-reference/core/UnionType", - "api-reference/core/Unpack", - "api-reference/core/Unwrappable", - "api-reference/core/Usable", - "api-reference/core/Usage", - "api-reference/core/UsageKind", - "api-reference/core/UsageType", - "api-reference/core/Value", - "api-reference/core/WhileStatement", - "api-reference/core/WithStatement" - ] - }, - { - "group": "Python", - "icon": "python", - "pages": [ - "api-reference/python/PyAssignment", - "api-reference/python/PyAssignmentStatement", - "api-reference/python/PyAttribute", - "api-reference/python/PyBlockStatement", - "api-reference/python/PyBreakStatement", - "api-reference/python/PyCatchStatement", - "api-reference/python/PyChainedAttribute", - "api-reference/python/PyClass", - "api-reference/python/PyCodeBlock", - "api-reference/python/PyComment", - "api-reference/python/PyCommentGroup", - "api-reference/python/PyCommentType", - "api-reference/python/PyConditionalExpression", - "api-reference/python/PyDecorator", - "api-reference/python/PyFile", - "api-reference/python/PyForLoopStatement", - "api-reference/python/PyFunction", - "api-reference/python/PyGenericType", - "api-reference/python/PyHasBlock", - "api-reference/python/PyIfBlockStatement", - "api-reference/python/PyImport", - "api-reference/python/PyImportStatement", - "api-reference/python/PyMatchCase", - "api-reference/python/PyMatchStatement", - "api-reference/python/PyNamedType", - "api-reference/python/PyParameter", - "api-reference/python/PyPassStatement", - "api-reference/python/PyReturnTypePlaceholder", - "api-reference/python/PyString", - "api-reference/python/PySymbol", - "api-reference/python/PyTryCatchStatement", - "api-reference/python/PyUnionType", - "api-reference/python/PyWhileStatement" - ] - }, - { - "group": "Typescript", - "icon": "js", - "pages": [ - "api-reference/typescript/JSXElement", - "api-reference/typescript/JSXExpression", - "api-reference/typescript/JSXProp", - "api-reference/typescript/TSArrayType", - "api-reference/typescript/TSAssignment", - "api-reference/typescript/TSAssignmentStatement", - "api-reference/typescript/TSAttribute", - "api-reference/typescript/TSBlockStatement", - "api-reference/typescript/TSCatchStatement", - "api-reference/typescript/TSChainedAttribute", - "api-reference/typescript/TSClass", - "api-reference/typescript/TSCodeBlock", - "api-reference/typescript/TSComment", - "api-reference/typescript/TSCommentGroup", - "api-reference/typescript/TSCommentType", - "api-reference/typescript/TSConditionalType", - "api-reference/typescript/TSConfig", - "api-reference/typescript/TSDecorator", - "api-reference/typescript/TSDict", - "api-reference/typescript/TSEnum", - "api-reference/typescript/TSExport", - "api-reference/typescript/TSExpressionType", - "api-reference/typescript/TSFile", - "api-reference/typescript/TSForLoopStatement", - "api-reference/typescript/TSFunction", - "api-reference/typescript/TSFunctionType", - "api-reference/typescript/TSGenericType", - "api-reference/typescript/TSHasBlock", - "api-reference/typescript/TSIfBlockStatement", - "api-reference/typescript/TSImport", - "api-reference/typescript/TSImportStatement", - "api-reference/typescript/TSInterface", - "api-reference/typescript/TSLabeledStatement", - "api-reference/typescript/TSLookupType", - "api-reference/typescript/TSNamedType", - "api-reference/typescript/TSNamespace", - "api-reference/typescript/TSObjectType", - "api-reference/typescript/TSPair", - "api-reference/typescript/TSParameter", - "api-reference/typescript/TSQueryType", - "api-reference/typescript/TSReadonlyType", - "api-reference/typescript/TSReturnTypePlaceholder", - "api-reference/typescript/TSString", - "api-reference/typescript/TSSwitchCase", - "api-reference/typescript/TSSwitchStatement", - "api-reference/typescript/TSSymbol", - "api-reference/typescript/TSTernaryExpression", - "api-reference/typescript/TSTryCatchStatement", - "api-reference/typescript/TSTypeAlias", - "api-reference/typescript/TSUndefinedType", - "api-reference/typescript/TSUnionType", - "api-reference/typescript/TSWhileStatement" - ] - } - ] - } - ], - "footerSocials": { - "x": "https://x.com/codegen", - "linkedin": "https://linkedin.com/company/codegen-dot-com" - } -} + "$schema": "https://mintlify.com/schema.json", + "name": "Codegen", + "logo": { + "dark": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45a3e32761c42b324b_Codegen_Logomark_Dark.svg", + "light": "https://cdn.prod.website-files.com/67070304751b9b01bf6a161c/679bcf45bf55446746125835_Codegen_Logomark_Light.svg" + }, + "modeToggle": { + "default": "dark" + }, + "metadata": { + "og:site_name": "Codegen", + "og:title": "Codegen - Manipulate Code at Scale", + "og:description": "A scriptable interface to a powerful, multi-lingual language server built on top of Tree-sitter.", + "og:url": "https://docs.codegen.com", + "og:locale": "en_US", + "og:logo": "https://i.imgur.com/f4OVOqI.png", + "article:publisher": "Codegen, Inc.", + "twitter:site": "@codegen" + }, + "favicon": "/favicon.svg", + "colors": { + "primary": "#a277ff", + "light": "#a277ff", + "dark": "#a277ff", + "anchors": { + "from": "#61ffca", + "to": "#61ffca" + } + }, + "theme": "prism", + "background": { + "style": "gradient" + }, + "analytics": { + "posthog": { + "apiKey": "phc_GLxaINoQJnuyCyxDmTciQqzdKBYFVDkY7bRBO4bDdso" + } + }, + "feedback": { + "thumbsRating": true + }, + "topbarCtaButton": { + "name": "GitHub", + "url": "https://github.com/codegen-sh/codegen-sdk" + }, + "tabs": [ + { + "name": "API Reference", + "url": "/api-reference" + }, + { + "name": "CLI", + "url": "/cli" + }, + { + "name": "Blog", + "url": "/blog" + }, + { + "name": "Changelog", + "url": "/changelog" + } + ], + "navigation": [ + { + "group": "Introduction", + "pages": [ + "introduction/overview", + "introduction/getting-started", + "introduction/installation", + "introduction/ide-usage", + "introduction/work-with-ai", + "introduction/how-it-works", + "introduction/advanced-settings", + "introduction/guiding-principles", + "introduction/community", + "introduction/about", + "introduction/faq" + ] + }, + { + "group": "Tutorials", + "pages": [ + "tutorials/at-a-glance", + "tutorials/build-code-agent", + "tutorials/slack-bot", + "tutorials/github-review-bot", + "tutorials/deep-code-research", + "tutorials/training-data", + "tutorials/codebase-visualization", + "tutorials/migrating-apis", + "tutorials/organize-your-codebase", + "tutorials/promise-to-async-await", + "tutorials/modularity", + "tutorials/manage-feature-flags", + "tutorials/deleting-dead-code", + "tutorials/increase-type-coverage", + "tutorials/managing-typescript-exports", + "tutorials/converting-default-exports", + "tutorials/creating-documentation", + "tutorials/react-modernization", + "tutorials/unittest-to-pytest", + "tutorials/sqlalchemy-1.6-to-2.0", + "tutorials/fixing-import-loops-in-pytorch", + "tutorials/python2-to-python3", + "tutorials/flask-to-fastapi", + "tutorials/build-mcp", + "tutorials/neo4j-graph" + ] + }, + { + "group": "Building with Codegen", + "pages": [ + "building-with-codegen/at-a-glance", + "building-with-codegen/parsing-codebases", + "building-with-codegen/reusable-codemods", + "building-with-codegen/dot-codegen", + "building-with-codegen/function-decorator", + "building-with-codegen/language-support", + "building-with-codegen/commit-and-reset", + "building-with-codegen/git-operations", + "building-with-codegen/files-and-directories", + "building-with-codegen/the-editable-api", + "building-with-codegen/symbol-api", + "building-with-codegen/class-api", + "building-with-codegen/imports", + "building-with-codegen/exports", + "building-with-codegen/inheritable-behaviors", + "building-with-codegen/statements-and-code-blocks", + "building-with-codegen/dependencies-and-usages", + "building-with-codegen/function-calls-and-callsites", + "building-with-codegen/variable-assignments", + "building-with-codegen/local-variables", + "building-with-codegen/comments-and-docstrings", + "building-with-codegen/external-modules", + "building-with-codegen/type-annotations", + "building-with-codegen/moving-symbols", + "building-with-codegen/collections", + "building-with-codegen/traversing-the-call-graph", + "building-with-codegen/react-and-jsx", + "building-with-codegen/codebase-visualization", + "building-with-codegen/flagging-symbols", + "building-with-codegen/calling-out-to-llms", + "building-with-codegen/semantic-code-search", + "building-with-codegen/reducing-conditions" + ] + }, + { + "group": "CLI", + "pages": [ + "cli/about", + "cli/init", + "cli/notebook", + "cli/create", + "cli/run", + "cli/reset", + "cli/expert" + ] + }, + { + "group": "Changelog", + "pages": [ + "changelog/changelog" + ] + }, + { + "group": "Blog", + "pages": [ + "blog/posts", + "blog/devin", + "blog/act-via-code", + "blog/promise-to-async-await-twilio", + "blog/fixing-import-loops" + ] + }, + { + "group": "API Reference", + "pages": [ + "api-reference/index", + { + "group": "Core", + "icon": "code", + "pages": [ + "api-reference/core/Argument", + "api-reference/core/Assignment", + "api-reference/core/AssignmentStatement", + "api-reference/core/Attribute", + "api-reference/core/AwaitExpression", + "api-reference/core/BinaryExpression", + "api-reference/core/BlockStatement", + "api-reference/core/Boolean", + "api-reference/core/Callable", + "api-reference/core/CatchStatement", + "api-reference/core/ChainedAttribute", + "api-reference/core/Class", + "api-reference/core/CodeBlock", + "api-reference/core/CodeOwner", + "api-reference/core/Codebase", + "api-reference/core/Comment", + "api-reference/core/CommentGroup", + "api-reference/core/ComparisonExpression", + "api-reference/core/Decorator", + "api-reference/core/Dict", + "api-reference/core/Directory", + "api-reference/core/Editable", + "api-reference/core/Export", + "api-reference/core/ExportStatement", + "api-reference/core/Exportable", + "api-reference/core/Expression", + "api-reference/core/ExpressionGroup", + "api-reference/core/ExpressionStatement", + "api-reference/core/ExternalModule", + "api-reference/core/File", + "api-reference/core/FlagKwargs", + "api-reference/core/ForLoopStatement", + "api-reference/core/Function", + "api-reference/core/FunctionCall", + "api-reference/core/GenericType", + "api-reference/core/HasBlock", + "api-reference/core/HasName", + "api-reference/core/HasValue", + "api-reference/core/IfBlockStatement", + "api-reference/core/Import", + "api-reference/core/ImportStatement", + "api-reference/core/ImportType", + "api-reference/core/Importable", + "api-reference/core/Interface", + "api-reference/core/List", + "api-reference/core/MessageType", + "api-reference/core/MultiExpression", + "api-reference/core/MultiLineCollection", + "api-reference/core/Name", + "api-reference/core/NamedType", + "api-reference/core/NoneType", + "api-reference/core/Number", + "api-reference/core/Pair", + "api-reference/core/Parameter", + "api-reference/core/ParenthesizedExpression", + "api-reference/core/Placeholder", + "api-reference/core/PlaceholderType", + "api-reference/core/RaiseStatement", + "api-reference/core/ReturnStatement", + "api-reference/core/SourceFile", + "api-reference/core/Span", + "api-reference/core/Statement", + "api-reference/core/StatementType", + "api-reference/core/String", + "api-reference/core/StubPlaceholder", + "api-reference/core/SubscriptExpression", + "api-reference/core/SwitchCase", + "api-reference/core/SwitchStatement", + "api-reference/core/Symbol", + "api-reference/core/SymbolGroup", + "api-reference/core/SymbolStatement", + "api-reference/core/TernaryExpression", + "api-reference/core/TryCatchStatement", + "api-reference/core/Tuple", + "api-reference/core/TupleType", + "api-reference/core/Type", + "api-reference/core/TypeAlias", + "api-reference/core/TypePlaceholder", + "api-reference/core/Typeable", + "api-reference/core/UnaryExpression", + "api-reference/core/UnionType", + "api-reference/core/Unpack", + "api-reference/core/Unwrappable", + "api-reference/core/Usable", + "api-reference/core/Usage", + "api-reference/core/UsageKind", + "api-reference/core/UsageType", + "api-reference/core/Value", + "api-reference/core/WhileStatement", + "api-reference/core/WithStatement" + ] + }, + { + "group": "Python", + "icon": "python", + "pages": [ + "api-reference/python/PyAssignment", + "api-reference/python/PyAssignmentStatement", + "api-reference/python/PyAttribute", + "api-reference/python/PyBlockStatement", + "api-reference/python/PyBreakStatement", + "api-reference/python/PyCatchStatement", + "api-reference/python/PyChainedAttribute", + "api-reference/python/PyClass", + "api-reference/python/PyCodeBlock", + "api-reference/python/PyComment", + "api-reference/python/PyCommentGroup", + "api-reference/python/PyCommentType", + "api-reference/python/PyConditionalExpression", + "api-reference/python/PyDecorator", + "api-reference/python/PyFile", + "api-reference/python/PyForLoopStatement", + "api-reference/python/PyFunction", + "api-reference/python/PyGenericType", + "api-reference/python/PyHasBlock", + "api-reference/python/PyIfBlockStatement", + "api-reference/python/PyImport", + "api-reference/python/PyImportStatement", + "api-reference/python/PyMatchCase", + "api-reference/python/PyMatchStatement", + "api-reference/python/PyNamedType", + "api-reference/python/PyParameter", + "api-reference/python/PyPassStatement", + "api-reference/python/PyReturnTypePlaceholder", + "api-reference/python/PyString", + "api-reference/python/PySymbol", + "api-reference/python/PyTryCatchStatement", + "api-reference/python/PyUnionType", + "api-reference/python/PyWhileStatement" + ] + }, + { + "group": "Typescript", + "icon": "js", + "pages": [ + "api-reference/typescript/JSXElement", + "api-reference/typescript/JSXExpression", + "api-reference/typescript/JSXProp", + "api-reference/typescript/TSArrayType", + "api-reference/typescript/TSAssignment", + "api-reference/typescript/TSAssignmentStatement", + "api-reference/typescript/TSAttribute", + "api-reference/typescript/TSBlockStatement", + "api-reference/typescript/TSCatchStatement", + "api-reference/typescript/TSChainedAttribute", + "api-reference/typescript/TSClass", + "api-reference/typescript/TSCodeBlock", + "api-reference/typescript/TSComment", + "api-reference/typescript/TSCommentGroup", + "api-reference/typescript/TSCommentType", + "api-reference/typescript/TSConditionalType", + "api-reference/typescript/TSConfig", + "api-reference/typescript/TSDecorator", + "api-reference/typescript/TSDict", + "api-reference/typescript/TSEnum", + "api-reference/typescript/TSExport", + "api-reference/typescript/TSExpressionType", + "api-reference/typescript/TSFile", + "api-reference/typescript/TSForLoopStatement", + "api-reference/typescript/TSFunction", + "api-reference/typescript/TSFunctionType", + "api-reference/typescript/TSGenericType", + "api-reference/typescript/TSHasBlock", + "api-reference/typescript/TSIfBlockStatement", + "api-reference/typescript/TSImport", + "api-reference/typescript/TSImportStatement", + "api-reference/typescript/TSInterface", + "api-reference/typescript/TSLabeledStatement", + "api-reference/typescript/TSLookupType", + "api-reference/typescript/TSNamedType", + "api-reference/typescript/TSNamespace", + "api-reference/typescript/TSObjectType", + "api-reference/typescript/TSPair", + "api-reference/typescript/TSParameter", + "api-reference/typescript/TSQueryType", + "api-reference/typescript/TSReadonlyType", + "api-reference/typescript/TSReturnTypePlaceholder", + "api-reference/typescript/TSString", + "api-reference/typescript/TSSwitchCase", + "api-reference/typescript/TSSwitchStatement", + "api-reference/typescript/TSSymbol", + "api-reference/typescript/TSTernaryExpression", + "api-reference/typescript/TSTryCatchStatement", + "api-reference/typescript/TSTypeAlias", + "api-reference/typescript/TSUndefinedType", + "api-reference/typescript/TSUnionType", + "api-reference/typescript/TSWhileStatement" + ] + } + ] + } + ], + "footerSocials": { + "x": "https://x.com/codegen", + "linkedin": "https://linkedin.com/company/codegen-dot-com" + } +} \ No newline at end of file diff --git a/src/codegen/sdk/system-prompt.txt b/src/codegen/sdk/system-prompt.txt index e5b616c1b..bcb57217d 100644 --- a/src/codegen/sdk/system-prompt.txt +++ b/src/codegen/sdk/system-prompt.txt @@ -437,6 +437,39 @@ if base_class: references](/building-with-codegen/dependencies-and-usages) or [imports](/building-with-codegen/imports) and [exports](/building-with-codegen/exports). +## Advanced Settings + +Codegen also supports a number of advanced settings that can be used to customize the behavior of the graph construction process. + +These flags are helpful for debugging problematic repos, optimizing Codegen’s performance, or testing unreleased or experimental (potentially backwards-breaking) features. + +```python +from codegen import Codebase +from codegen.configs import CodebaseConfig + +# Initialize a Codebase with custom configuration +codebase = Codebase( + "path/to/git/repo"", + config=CodebaseConfig( + verify_graph=True, + method_usages=False, + sync_enabled=True, + generics=False, + import_resolution_overrides={ + "old_module": "new_module" + }, + ts_language_engine=True, + v8_ts_engine=True + ) +) +``` + +To learn more about available settings, see the [Advanced Settings](/introduction/advanced-settings) page. + + +These are considered experimental and unstable features that may be removed or changed in the future. + + ## What's Next? @@ -956,6 +989,399 @@ Codegen is just getting started, and we're excited about the possibilities ahead Check out our [community guide](/introduction/community) to get involved! +--- +title: "Advanced Settings" +sidebarTitle: "Advanced Settings" +icon: "memory" +iconType: "solid" +--- + +Codegen's [Codebase](/api-reference/core/Codebase) constructor accepts a `CodebaseConfig` object which is used to configure more advanced behaviors of the graph construction process. + +These flags are helpful for debugging problematic repos, optimizing Codegen's performance, or testing unreleased or experimental (potentially backwards-breaking) features. + + +**These are considered experimental features and may change in the future!** + +As such, they may have little to no testing or documentation. Many of these flags may also be unsupported in the future! + +If you need help, please visit our [community](/introduction/community). + + + +These configuration options are defined in [src/codegen/configs/models/codebase.py](https://github.com/codegen-sh/codegen/blob/develop/src/codegen/configs/models/codebase.py). + + +# Usage + +You can customize the behavior of the graph construction process when initializing a [Codebase](/api-reference/core/Codebase) by passing a `CodebaseConfig` object with the desired configuration flags. + +```python +from codegen import Codebase +from codegen.configs import CodebaseConfig + +# Initialize a Codebase with custom configuration +codebase = Codebase( + "", + config=CodebaseConfig( + flag1=..., + flag2=..., + ... + ) +) +``` + +# Table of Contents + +- [debug](#flag-debug) +- [verify-graph](#flag-verify-graph) +- [track-graph](#flag-track-graph) +- [method-usages](#flag-method-usages) +- [sync-enabled](#flag-sync-enabled) +- [full-range-index](#flag-full-range-index) +- [ignore-process-errors](#flag-ignore-process-errors) +- [disable-graph](#flag-disable-graph) +- [disable-file-parse](#flag-disable-file-parse) +- [exp-lazy-graph](#flag-exp-lazy-graph) +- [generics](#flag-generics) +- [import-resolution-paths](#flag-import-resolution-paths) +- [import-resolution-overrides](#flag-import-resolution-overrides) +- [py-resolve-syspath](#flag-py-resolve-syspath) +- [ts-dependency-manager](#flag-ts-dependency-manager) +- [ts-language-engine](#flag-ts-language-engine) +- [v8-ts-engine](#flag-v8-ts-engine) +- [unpacking-assignment-partial-removal](#flag-unpacking-assignment-partial-removal) + +# Configuration Flags + +## Flag: `debug` +> **Default: `False`** + +Enables verbose logging for debugging purposes. In its current form, it enables: +- Verbose logging when adding nodes to the graph +- Verbose logging during initial file parsing +- Additional assertions on graph creation +- Additional (costly) debug metrics on codebase construction +- etc. + + +This flag may be very noisy and significantly impact performance. It is generally not recommended to use. + + +## Flag: `verify_graph` +> **Default: `False`** + +Adds assertions for graph state during reset resync. Used to test and debug graph desyncs after a codebase reset. + +Runs `post_reset_validation` after a reset resync. + + +This is an internal debug flag. + + +## Flag: `track_graph` +> **Default: `False`** + +Keeps a copy of the original graph before a resync. Used in conjunction with `verify_graph` to test and debug graph desyncs. + +Original graph is saved as `ctx.old_graph`. + + +This is an internal debug flag. + + +## Flag: `method_usages` +> **Default: `True`** + +Enables and disables resolving method usages. + +**Example Codebase:** +```python +class Foo: + def bar(): + ... + +obj = Foo() +obj.bar() # Method Usage +``` + +**Codemod with `method_usages` on:** +```python +bar_func = codebase.get_class("Foo").get_method("bar") +len(bar_func.usages) # 1 +bar_func.usages # [obj.bar()] +``` + +**Codemod with `method_usages` off:** +```python +bar_func = codebase.get_class("Foo").get_method("bar") +len(bar_func.usages) # 0 +bar_func.usages # [] +``` + +Method usage resolution could be disabled for a marginal performance boost. However, it is generally recommended to leave it enabled. + +## Flag: `sync_enabled` +> **Default: `False`** + +Enables or disables graph sync during `codebase.commit`. + + +Implementation-specific details on sync graph can be found [here](https://github.com/codegen-sh/codegen/blob/develop/architecture/6.%20incremental-computation/C.%20Graph%20Recomputation.md). + + +This section won't go into the specific details of sync graph, but the general idea is that enabling sync graph will update the Codebase object to whatever new changes were made. + +**Example with `sync_enabled` on:** +```python +file = codebase.get_file(...) +file.insert_after("foobar = 1") +codebase.commit() + +foobar = codebase.get_symbol("foobar") +assert foobar # foobar is available after commit / graph sync +``` + +**Example with `sync_enabled` disabled:** +```python +file = codebase.get_file(...) +file.insert_after("foobar = 1") + +foobar = codebase.get_symbol("foobar", optional=True) +assert not foobar # foobar is not available after commit +``` + + +Enabling sync graph will have a performance impact on codebase commit, but will also unlock a bunch of operations that were previously not possible. + + +## Flag: `full_range_index` +> **Default: `False`** + +By default, Codebase maintains an internal range-to-node index for fast lookups. (i.e. `bytes 120 to 130 maps to node X`). +For optimization purposes, this only applies to nodes defined and handled by `parser.py`. + +Enabling `full_range_index` will create an additional index that maps **all** tree-sitter ranges to nodes. +This can be useful for debugging or when you need to build any applications that require a full range-to-node index (i.e. a codebase tree lookup). + + +This flag **significantly** increases memory usage! + + +## Flag: `ignore_process_errors` +> **Default: `True`** + +Controls whether to ignore errors that occur during external process execution (such as dependency manager or language engine). + +Disabling `ignore_process_errors` would make Codegen fail on errors that would otherwise be logged then ignored. + +## Flag: `disable_graph` +> **Default: `False`** + +Disables the graph construction process. Any operations that require the graph will no longer work. (In other words, this turns off import resolution and usage/dependency resolution) + +Functions that operate purely on AST such as getting and editing parameters or modifying function and class definitions will still work. + + +For codemods that do not require the graph (aka only AST/Syntax-level changes), **disabling graph parse could yield a 30%-40% decrease in parse time and memory usage**! + + +## Flag: `disable_file_parse` +> **Default: `False`** + +Disables **ALL** parsing, including file and graph parsing. This essentially treats all codebases as the "UNSUPPORTED" language mode. + +Nearly all functions except for editing primitives like `codebase.get_file` and `file.edit` will no longer work. + + +This flag is useful for any usages of Codegen that do **NOT** require any AST/CST/Graph parsing. (i.e. using Codegen purely as a file editing harness) + +If this is your use case, this **could decrease parse and memory usage by 95%.** + + +## Flag: `exp_lazy_graph` +> **Default: `False`** + +This experimental flag pushes the graph creation back until the graph is needed. This is an experimental feature and may have some unintended consequences. + +**Example Codemod:** +```python +from codegen import Codebase +from codegen.configs import CodebaseConfig + +# Enable lazy graph parsing +codebase = Codebase("", config=CodebaseConfig(exp_lazy_graph=True)) + +# The codebase object will be created immediately with no parsing done +# These all do not require graph parsing +codebase.files +codebase.directories +codebase.get_file("...") + +# These do require graph parsing, and will create the graph only if called +codebase.get_function("...") +codebase.get_class("...") +codebase.imports +``` + + +This may have a very slight performance boost. Use at your own risk! + + +## Flag: `generics` +> **Default: `True`** + +Enables and disables generic type resolution. + +**Example Codebase:** +```python +class Point: + def scale(cls, n: int): + pass + +class List[T](): + def pop(self) -> T: + ... + +l: List[Point] = [] +l.pop().scale(1) # Generic Usage +``` + +**Codemod with `generics` on:** +```python +bar_func = codebase.get_class("Point").get_method("scale") +len(bar_func.usages) # 1 +bar_func.usages # [l.pop().scale(1)] +``` + +**Codemod with `generics` off:** +```python +bar_func = codebase.get_class("Point").get_method("scale") +len(bar_func.usages) # 0 +bar_func.usages # [] +``` + + +Generic resolution is still largely WIP and experimental, and may not work in all cases. In some rare circumstances, disabling generics may result in a significant performance boost. + + +## Flag: `import_resolution_paths` +> **Default: `[]`** + +Controls alternative paths to resolve imports from. + +**Example Codebase:** +```python +# a/b/c/src.py +def update(): + pass + +# consumer.py +from c import src as operations + +operations.update() +``` + +**Codemod:** +```python +codebase.ctx.config.import_resolution_paths = ["a/b"] +``` + +## Flag: `import_resolution_overrides` +> **Default: `{}`** + +Controls import path overrides during import resolution. + +**Example** +`from a.b.c import d` with the override `a/b` -> `foo/bar` will internally resolve the import as `from foo.bar.c import d`. + +## Flag: `py_resolve_syspath` +> **Default: `False`** + +Enables and disables resolution of imports from `sys.path`. + +## Flag: `ts_dependency_manager` +> **Default: `False`** + + +**This is an internal flag used for Codegen Cloud and should not be used externally!** + +This flag **WILL** nuke any existing `node_modules` folder! + + + +This flag also assumes many constants for Codegen Cloud. Very likely this will not work if run locally. + +Instead, just install `node_modules` as normal (either through `npm`, `pnpm`, or `yarn`) and skip this setting! + + +Enables Codegen's internal dependency installer for TypeScript. This will modify `package.json` and install the bare minimum set of installable dependencies. + + +More documentation on TypeScript dependency manager can be found [here](https://github.com/codegen-sh/codegen/blob/develop/architecture/external/dependency-manager.md) + + +## Flag: `ts_language_engine` +> **Default: `False`** + + +This feature was built primarily with Codegen Cloud in mind. As such, this assumes a valid NodeJS and TypeScript environment. + + +Enables using the TypeScript compiler to extract information from the codebase. Enables commands such as `inferred_return_type`. + + +This will increase memory usage and parsing time. Larger repos may even hit resource constraints with the bundled TypeScript compiler integration. + + +## Flag: `v8_ts_engine` +> **Default: `False`** + + +This feature flag requires `ts_language_engine` to be enabled as well. + + +Enables using the **V8-based TypeScript compiler** to extract information from the codebase. Enables commands such as `inferred_return_type`. + +The V8 implementation (as opposed to the default external-process based implementation) is less stable, but provides the entire TypeScript API to be used from within Codegen. + + +This will increase memory usage and parsing time. Larger repos may even hit resource constraints with the V8-based TypeScript compiler integration. + + +## Flag: `unpacking_assignment_partial_removal` +> **Default: `False`** + +Enables smarter removal of unpacking assignments. + +**Example Codebase:** +```python +a, b, c = (1, 2, 3) +``` + +**Codemod with `unpacking_assignment_partial_removal` on:** +```python +file = codebase.get_file(...) +b = file.get_symbol("b") +b.remove() +codebase.commit() + +file.symbols # [a, c] +file.source # "a, c = (1, 3)" +``` + +**Codemod with `unpacking_assignment_partial_removal` off:** +```python +file = codebase.get_file(...) +b = file.get_symbol("b") +b.remove() +codebase.commit() + +file.symbols # [] +file.source # "" +``` + + --- title: "Guiding Principles" sidebarTitle: "Principles" From 91d767e50978a47cb2500a1123e1ab4d1296c92e Mon Sep 17 00:00:00 2001 From: Edo Pujol Date: Thu, 6 Mar 2025 20:01:36 -0500 Subject: [PATCH 47/66] chore: Integrate xAI as provider (#773) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [x] I have added tests for my changes - [x] I have updated the documentation or added new documentation as needed --------- Co-authored-by: kopekC <28070492+kopekC@users.noreply.github.com> --- pyproject.toml | 1 + src/codegen/extensions/langchain/llm.py | 12 +++++++++++- uv.lock | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ea7fa4ae1..777d80ec1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,6 +78,7 @@ dependencies = [ "datasets", "colorlog>=6.9.0", "langsmith", + "langchain-xai>=0.2.1", ] license = { text = "Apache-2.0" } diff --git a/src/codegen/extensions/langchain/llm.py b/src/codegen/extensions/langchain/llm.py index 1aafce31c..d2cec02a3 100644 --- a/src/codegen/extensions/langchain/llm.py +++ b/src/codegen/extensions/langchain/llm.py @@ -13,6 +13,7 @@ from langchain_core.runnables import Runnable from langchain_core.tools import BaseTool from langchain_openai import ChatOpenAI +from langchain_xai import ChatXAI from pydantic import Field @@ -76,6 +77,9 @@ def _get_model_kwargs(self) -> dict[str, Any]: if self.model_provider == "anthropic": return {**base_kwargs, "model": self.model_name} + elif self.model_provider == "xai": + xai_api_base = os.getenv("XAI_API_BASE", "https://api.x.ai/v1/") + return {**base_kwargs, "model": self.model_name, "xai_api_base": xai_api_base} else: # openai return {**base_kwargs, "model": self.model_name} @@ -93,7 +97,13 @@ def _get_model(self) -> BaseChatModel: raise ValueError(msg) return ChatOpenAI(**self._get_model_kwargs()) - msg = f"Unknown model provider: {self.model_provider}. Must be one of: anthropic, openai" + elif self.model_provider == "xai": + if not os.getenv("XAI_API_KEY"): + msg = "XAI_API_KEY not found in environment. Please set it in your .env file or environment variables." + raise ValueError(msg) + return ChatXAI(**self._get_model_kwargs()) + + msg = f"Unknown model provider: {self.model_provider}. Must be one of: anthropic, openai, xai" raise ValueError(msg) def _generate( diff --git a/uv.lock b/uv.lock index 86bc5b166..9796f29bb 100644 --- a/uv.lock +++ b/uv.lock @@ -561,6 +561,7 @@ dependencies = [ { name = "langchain-anthropic" }, { name = "langchain-core" }, { name = "langchain-openai" }, + { name = "langchain-xai" }, { name = "langgraph" }, { name = "langgraph-prebuilt" }, { name = "langsmith" }, @@ -689,6 +690,7 @@ requires-dist = [ { name = "langchain-anthropic", specifier = ">=0.3.7" }, { name = "langchain-core" }, { name = "langchain-openai" }, + { name = "langchain-xai" }, { name = "langgraph" }, { name = "langgraph-prebuilt" }, { name = "langsmith" }, @@ -2109,6 +2111,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4c/f8/6b82af988e65af9697f6a2f25373fb173fd32d48b62772a8773c5184c870/langchain_text_splitters-0.3.6-py3-none-any.whl", hash = "sha256:e5d7b850f6c14259ea930be4a964a65fa95d9df7e1dbdd8bad8416db72292f4e", size = 31197 }, ] +[[package]] +name = "langchain-xai" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "langchain-core" }, + { name = "langchain-openai" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/94/a633bf1b4bbf66e4516f4188adc1174480c465ae12fb98f06c3e23c98519/langchain_xai-0.2.1.tar.gz", hash = "sha256:143a6f52be7617b5e5c68ab10c9b7df90914f54a6b3098566ce22b5d8fd89da5", size = 7788 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/88/d8050e610fadabf97c1745d24f0987b3e53b72fca63c8038ab1e0c103da9/langchain_xai-0.2.1-py3-none-any.whl", hash = "sha256:87228125cb15131663979d627210fca47dcd6b9a28462e8b5fee47f73bbed9f4", size = 6263 }, +] + [[package]] name = "langgraph" version = "0.3.2" From d435cc51c7d284c48d3db9c627168f67d4e7aa01 Mon Sep 17 00:00:00 2001 From: Christine Wang Date: Fri, 7 Mar 2025 09:30:44 -0800 Subject: [PATCH 48/66] fix: remote git repo doesn't need token if it's public repo (#775) --- .pre-commit-config.yaml | 16 +--------------- src/codegen/git/repo_operator/repo_operator.py | 4 ++-- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7f8f20c68..eeea3f677 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -80,27 +80,13 @@ repos: rev: 39.169.3 hooks: - id: renovate-config-validator + - repo: https://github.com/astral-sh/uv-pre-commit rev: "0.5.31" hooks: - id: uv-sync args: ["--frozen", "--all-packages", "--all-extras"] - - repo: "local" - hooks: - # Disabled as part of LFS removal. - # - id: disallowed-words-check - # name: Check for disallowed words - # entry: scripts/disallowed-words-check.sh - # language: script - # files: '' # Check all files - - id: generate-runner-imports - name: Generate Runner Imports - entry: bash -c "uv run --frozen python -m codegen.gscli.cli generate runner-imports src/codegen/shared/compilation/function_imports.py" - language: system - pass_filenames: false - always_run: true - - repo: https://github.com/hukkin/mdformat rev: 0.7.22 # Use the ref you want to point at hooks: diff --git a/src/codegen/git/repo_operator/repo_operator.py b/src/codegen/git/repo_operator/repo_operator.py index 24db86ede..b5febfe14 100644 --- a/src/codegen/git/repo_operator/repo_operator.py +++ b/src/codegen/git/repo_operator/repo_operator.py @@ -20,7 +20,7 @@ from codegen.git.clients.git_repo_client import GitRepoClient from codegen.git.configs.constants import CODEGEN_BOT_EMAIL, CODEGEN_BOT_NAME from codegen.git.repo_operator.local_git_repo import LocalGitRepo -from codegen.git.schemas.enums import CheckoutResult, FetchResult, SetupOption +from codegen.git.schemas.enums import CheckoutResult, FetchResult, RepoVisibility, SetupOption from codegen.git.schemas.repo_config import RepoConfig from codegen.git.utils.clone import clone_or_pull_repo, clone_repo, pull_repo from codegen.git.utils.clone_url import add_access_token_to_url, get_authenticated_clone_url_for_repo_config, get_clone_url_for_repo_config, url_to_github @@ -89,7 +89,7 @@ def repo_path(self) -> str: @property def remote_git_repo(self) -> GitRepoClient: - if not self.access_token: + if not self.access_token and self.repo_config.visibility != RepoVisibility.PUBLIC: msg = "Must initialize with access_token to get remote" raise ValueError(msg) From c61256a0d6adbfc772c6c4caf7c92a11f702ef29 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 7 Mar 2025 17:33:58 +0000 Subject: [PATCH 49/66] update changelog --- docs/changelog/changelog.mdx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index e84e789dc..b1a952693 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,13 @@ icon: "clock" iconType: "solid" --- + +### [Fixes git token issue and integrates xAI provider.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.3) +- Fix issue with remote git repo token requirement +- Integrate new xAI provider +- Update and expand API documentation + + ### [Fixes PR viewing issue returning 404 error.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.2) - Fix issue with viewing PR returning 404 From 3360eae60731d6326647531b311a2de5185f9d99 Mon Sep 17 00:00:00 2001 From: Vishal Shenoy Date: Fri, 7 Mar 2025 13:48:59 -0800 Subject: [PATCH 50/66] Delete Chat Agent (#777) This agent implementation is no longer needed, better to remove for the sake of clarity. --- src/codegen/agents/chat_agent.py | 95 -------------------------------- 1 file changed, 95 deletions(-) delete mode 100644 src/codegen/agents/chat_agent.py diff --git a/src/codegen/agents/chat_agent.py b/src/codegen/agents/chat_agent.py deleted file mode 100644 index 2ecae36fb..000000000 --- a/src/codegen/agents/chat_agent.py +++ /dev/null @@ -1,95 +0,0 @@ -from typing import TYPE_CHECKING, Optional -from uuid import uuid4 - -from langchain.tools import BaseTool -from langchain_core.messages import AIMessage - -from codegen.extensions.langchain.agent import create_chat_agent - -if TYPE_CHECKING: - from codegen import Codebase - - -class ChatAgent: - """Agent for interacting with a codebase.""" - - def __init__(self, codebase: "Codebase", model_provider: str = "anthropic", model_name: str = "claude-3-5-sonnet-latest", memory: bool = True, tools: Optional[list[BaseTool]] = None, **kwargs): - """Initialize a CodeAgent. - - Args: - codebase: The codebase to operate on - model_provider: The model provider to use ("anthropic" or "openai") - model_name: Name of the model to use - memory: Whether to let LLM keep track of the conversation history - tools: Additional tools to use - **kwargs: Additional LLM configuration options. Supported options: - - temperature: Temperature parameter (0-1) - - top_p: Top-p sampling parameter (0-1) - - top_k: Top-k sampling parameter (>= 1) - - max_tokens: Maximum number of tokens to generate - """ - self.codebase = codebase - self.agent = create_chat_agent(self.codebase, model_provider=model_provider, model_name=model_name, memory=memory, additional_tools=tools, **kwargs) - - def run(self, prompt: str, thread_id: Optional[str] = None) -> str: - """Run the agent with a prompt. - - Args: - prompt: The prompt to run - thread_id: Optional thread ID for message history. If None, a new thread is created. - - Returns: - The agent's response - """ - if thread_id is None: - thread_id = str(uuid4()) - - input = {"messages": [("user", prompt)]} - stream = self.agent.stream(input, config={"configurable": {"thread_id": thread_id}}, stream_mode="values") - - for s in stream: - message = s["messages"][-1] - if isinstance(message, tuple): - print(message) - else: - if isinstance(message, AIMessage) and isinstance(message.content, list) and "text" in message.content[0]: - AIMessage(message.content[0]["text"]).pretty_print() - else: - message.pretty_print() - - return s["messages"][-1].content - - def chat(self, prompt: str, thread_id: Optional[str] = None) -> tuple[str, str]: - """Chat with the agent, maintaining conversation history. - - Args: - prompt: The user message - thread_id: Optional thread ID for message history. If None, a new thread is created. - - Returns: - A tuple of (response_content, thread_id) to allow continued conversation - """ - if thread_id is None: - thread_id = str(uuid4()) - print(f"Starting new chat thread: {thread_id}") - else: - print(f"Continuing chat thread: {thread_id}") - - response = self.run(prompt, thread_id=thread_id) - return response, thread_id - - def get_chat_history(self, thread_id: str) -> list: - """Retrieve the chat history for a specific thread. - - Args: - thread_id: The thread ID to retrieve history for - - Returns: - List of messages in the conversation history - """ - # Access the agent's memory to get conversation history - if hasattr(self.agent, "get_state"): - state = self.agent.get_state({"configurable": {"thread_id": thread_id}}) - if state and "messages" in state: - return state["messages"] - return [] From 5472cad41598f6fc4fd69c02b9a015a0d25ace0c Mon Sep 17 00:00:00 2001 From: Carol Jung <165736129+caroljung-cg@users.noreply.github.com> Date: Fri, 7 Mar 2025 15:07:57 -0800 Subject: [PATCH 51/66] fix: fix search tool import (#778) --- src/codegen/extensions/langchain/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/extensions/langchain/tools.py b/src/codegen/extensions/langchain/tools.py index e191ca7f8..8551b68e6 100644 --- a/src/codegen/extensions/langchain/tools.py +++ b/src/codegen/extensions/langchain/tools.py @@ -8,7 +8,6 @@ from codegen.extensions.linear.linear_client import LinearClient from codegen.extensions.tools.bash import run_bash_command from codegen.extensions.tools.github.checkout_pr import checkout_pr -from codegen.extensions.tools.github.search import search from codegen.extensions.tools.github.view_pr_checks import view_pr_checks from codegen.extensions.tools.linear.linear import ( linear_comment_on_issue_tool, @@ -23,6 +22,7 @@ from codegen.extensions.tools.relace_edit import relace_edit from codegen.extensions.tools.replacement_edit import replacement_edit from codegen.extensions.tools.reveal_symbol import reveal_symbol +from codegen.extensions.tools.search import search from codegen.extensions.tools.semantic_edit import semantic_edit from codegen.extensions.tools.semantic_search import semantic_search from codegen.sdk.core.codebase import Codebase From 1d1a1c7bcd1947c9252e2add3cdfdeb957b209f5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 7 Mar 2025 23:11:27 +0000 Subject: [PATCH 52/66] update changelog --- docs/changelog/changelog.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index b1a952693..947a1a9ee 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,12 @@ icon: "clock" iconType: "solid" --- + +### [Fixes import issue and removes outdated Chat Agent.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.4) +- Fix search tool import issue +- Remove obsolete Chat Agent implementation + + ### [Fixes git token issue and integrates xAI provider.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.3) - Fix issue with remote git repo token requirement From b763d1fea2980b2543b9935d1e230c3bb3495da8 Mon Sep 17 00:00:00 2001 From: jemeza-codegen <165736868+jemeza-codegen@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:22:18 -0800 Subject: [PATCH 53/66] CG-10997: Added subsets of swe-bench lite (#779) Added subsets of swe-bench lite that are designed to match the distribution of the dataset. # Motivation We need quick and reliable methods to iterate on the agent. # Content - adds subsets of the lite dataset designed to match the distribution of the entire dataset. Three datasets were added of lengths 10, 20 and 100. - added command line support - the agent traces are tagged with the difficulty of the task # Testing This is a test. # Please check the following before marking your PR as ready for review - [x] I have added tests for my changes - [x] I have updated the documentation or added new documentation as needed --- .../examples/swebench_agent_run/README.md | 3 +- .../examples/swebench_agent_run/constants.py | 12 + .../examples/swebench_agent_run/run_eval.py | 15 +- src/codegen/agents/code_agent.py | 31 +- src/codegen/extensions/swebench/enums.py | 13 + src/codegen/extensions/swebench/harness.py | 2 +- src/codegen/extensions/swebench/report.py | 2 +- src/codegen/extensions/swebench/subsets.py | 146 +++++++++ .../extensions/swebench/success_rates.py | 302 ++++++++++++++++++ src/codegen/extensions/swebench/utils.py | 52 +-- 10 files changed, 532 insertions(+), 46 deletions(-) create mode 100644 codegen-examples/examples/swebench_agent_run/constants.py create mode 100644 src/codegen/extensions/swebench/enums.py create mode 100644 src/codegen/extensions/swebench/subsets.py create mode 100644 src/codegen/extensions/swebench/success_rates.py diff --git a/codegen-examples/examples/swebench_agent_run/README.md b/codegen-examples/examples/swebench_agent_run/README.md index c6dc48676..277578f16 100644 --- a/codegen-examples/examples/swebench_agent_run/README.md +++ b/codegen-examples/examples/swebench_agent_run/README.md @@ -27,7 +27,8 @@ Options: --use-existing-preds TEXT The run ID of the existing predictions to use. - --dataset [lite|full|verified] The dataset to use. + --dataset [lite|full|verified|lite_small|lite_medium|lite_large] + The dataset to use. --length INTEGER The number of examples to process. --instance-id TEXT The instance ID of the example to process. --repo TEXT The repo to use. diff --git a/codegen-examples/examples/swebench_agent_run/constants.py b/codegen-examples/examples/swebench_agent_run/constants.py new file mode 100644 index 000000000..138669e96 --- /dev/null +++ b/codegen-examples/examples/swebench_agent_run/constants.py @@ -0,0 +1,12 @@ +from codegen.extensions.swebench.enums import SWEBenchDataset +from codegen.extensions.swebench.enums import SWEBenchLiteSubset + + +DATASET_DICT = { + "lite": SWEBenchDataset.LITE, + "full": SWEBenchDataset.FULL, + "verified": SWEBenchDataset.VERIFIED, + "lite_small": SWEBenchLiteSubset.LITE_SMALL, + "lite_medium": SWEBenchLiteSubset.LITE_MEDIUM, + "lite_large": SWEBenchLiteSubset.LITE_LARGE, +} diff --git a/codegen-examples/examples/swebench_agent_run/run_eval.py b/codegen-examples/examples/swebench_agent_run/run_eval.py index 9a86135d8..b38041c88 100644 --- a/codegen-examples/examples/swebench_agent_run/run_eval.py +++ b/codegen-examples/examples/swebench_agent_run/run_eval.py @@ -6,8 +6,10 @@ import modal import click import time +from codegen.extensions.swebench.enums import SWEBenchDataset, SWEBenchLiteSubset +from constants import DATASET_DICT from codegen.extensions.swebench.harness import run_agent_on_entry -from codegen.extensions.swebench.utils import SWEBenchDataset, SweBenchExample, get_swe_bench_examples +from codegen.extensions.swebench.utils import SweBenchExample, get_swe_bench_examples from codegen.extensions.swebench.report import generate_report from codegen.sdk.core.codebase import Codebase @@ -280,13 +282,8 @@ async def run_eval( run_id = use_existing_preds or str(uuid.uuid4()) print(f"Run ID: {run_id}") predictions_dir = PREDS_DNAME / f"results_{run_id}" - dataset_dict = { - "lite": SWEBenchDataset.LITE, - "full": SWEBenchDataset.FULL, - "verified": SWEBenchDataset.VERIFIED, - } - dataset_enum = dataset_dict[dataset] + dataset_enum = DATASET_DICT[dataset] examples = get_swe_bench_examples(dataset=dataset_enum, length=length, instance_id=instance_id, repo=repo) try: @@ -345,6 +342,8 @@ async def run_eval( for error_type, count in summary["error_types"].items(): print(f" {error_type}: {count}") + if isinstance(dataset_enum, SWEBenchLiteSubset): + dataset_enum = SWEBenchDataset.LITE # Generate Report on Modal generate_report(predictions_dir, LOG_DIR, dataset_enum, run_id) except Exception: @@ -355,7 +354,7 @@ async def run_eval( @click.command() @click.option("--use-existing-preds", help="The run ID of the existing predictions to use.", type=str, default=None) -@click.option("--dataset", help="The dataset to use.", type=click.Choice(["lite", "full", "verified"]), default="lite") +@click.option("--dataset", help="The dataset to use.", type=click.Choice(["lite", "full", "verified", "lite_small", "lite_medium", "lite_large"]), default="lite") @click.option("--length", help="The number of examples to process.", type=int, default=10) @click.option("--instance-id", help="The instance ID of the example to process.", type=str, default=None) @click.option("--local", help="Run the evaluation locally.", is_flag=True, default=False) diff --git a/src/codegen/agents/code_agent.py b/src/codegen/agents/code_agent.py index 157df294d..d02cd08a2 100644 --- a/src/codegen/agents/code_agent.py +++ b/src/codegen/agents/code_agent.py @@ -35,6 +35,7 @@ def __init__( tools: Optional[list[BaseTool]] = None, run_id: Optional[str] = None, instance_id: Optional[str] = None, + difficulty: Optional[int] = None, **kwargs, ): """Initialize a CodeAgent. @@ -64,6 +65,7 @@ def __init__( self.langsmith_client = Client() self.run_id = run_id self.instance_id = instance_id + self.difficulty = difficulty # Get project name from environment variable or use a default self.project_name = os.environ.get("LANGCHAIN_PROJECT", "RELACE") @@ -93,16 +95,7 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str: # this message has a reducer which appends the current message to the existing history # see more https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers input = {"messages": [("user", prompt)]} - metadata = {"project": self.project_name, "model": self.model_name} - tags = [self.model_name] - # Add SWEBench run ID and instance ID to the metadata and tags for filtering - if self.run_id is not None: - metadata["swebench_run_id"] = self.run_id - tags.append(self.run_id) - - if self.instance_id is not None: - metadata["swebench_instance_id"] = self.instance_id - tags.append(self.instance_id) + tags, metadata = self.get_tags_metadata() config = RunnableConfig(configurable={"thread_id": thread_id}, tags=tags, metadata=metadata, recursion_limit=100) # we stream the steps instead of invoke because it allows us to access intermediate nodes @@ -165,3 +158,21 @@ def get_tools(self) -> list[BaseTool]: def get_state(self) -> dict: return self.agent.get_state(self.config) + + def get_tags_metadata(self) -> tuple[list[str], dict]: + tags = [self.model_name] + metadata = {"project": self.project_name, "model": self.model_name} + # Add SWEBench run ID and instance ID to the metadata and tags for filtering + if self.run_id is not None: + metadata["swebench_run_id"] = self.run_id + tags.append(self.run_id) + + if self.instance_id is not None: + metadata["swebench_instance_id"] = self.instance_id + tags.append(self.instance_id) + + if self.difficulty is not None: + metadata["swebench_difficulty"] = self.difficulty + tags.append(f"difficulty_{self.difficulty}") + + return tags, metadata diff --git a/src/codegen/extensions/swebench/enums.py b/src/codegen/extensions/swebench/enums.py new file mode 100644 index 000000000..0cf3a484a --- /dev/null +++ b/src/codegen/extensions/swebench/enums.py @@ -0,0 +1,13 @@ +from enum import Enum + + +class SWEBenchDataset(Enum): + LITE = "princeton-nlp/SWE-bench_Lite" + FULL = "princeton-nlp/SWE-bench" + VERIFIED = "princeton-nlp/SWE-bench-verified" + + +class SWEBenchLiteSubset(Enum): + LITE_SMALL = "lite_small" + LITE_MEDIUM = "lite_medium" + LITE_LARGE = "lite_large" diff --git a/src/codegen/extensions/swebench/harness.py b/src/codegen/extensions/swebench/harness.py index 90cc9e017..dbf9f6b9b 100644 --- a/src/codegen/extensions/swebench/harness.py +++ b/src/codegen/extensions/swebench/harness.py @@ -70,7 +70,7 @@ def run_agent_on_entry(entry: SweBenchExample, model: str, codebase: Codebase | ) codebase = Codebase.from_repo(repo_full_name=entry.repo, commit=base_commit, language="python", config=config) # check out the repo - agent = CodeAgent(codebase=codebase, run_id=run_id, instance_id=instance_id, model_name=model) + agent = CodeAgent(codebase=codebase, run_id=run_id, instance_id=instance_id, model_name=model, difficulty=entry.difficulty) pprint.pprint(instance_id) pprint.pprint(gold_files) diff --git a/src/codegen/extensions/swebench/report.py b/src/codegen/extensions/swebench/report.py index a373e87e1..f8100e36d 100755 --- a/src/codegen/extensions/swebench/report.py +++ b/src/codegen/extensions/swebench/report.py @@ -5,8 +5,8 @@ from collections import defaultdict from pathlib import Path +from codegen.extensions.swebench.enums import SWEBenchDataset from codegen.extensions.swebench.tests import remove_patches_to_tests -from codegen.extensions.swebench.utils import SWEBenchDataset NUM_EVAL_PROCS = 5 diff --git a/src/codegen/extensions/swebench/subsets.py b/src/codegen/extensions/swebench/subsets.py new file mode 100644 index 000000000..a2f522ffe --- /dev/null +++ b/src/codegen/extensions/swebench/subsets.py @@ -0,0 +1,146 @@ +from codegen.extensions.swebench.enums import SWEBenchLiteSubset + +SMALL_LITE_SUBSET = [ + "mwaskom__seaborn-2848", + "sphinx-doc__sphinx-8627", + "sphinx-doc__sphinx-7975", + "django__django-17087", + "sympy__sympy-17655", + "matplotlib__matplotlib-26020", + "sympy__sympy-20154", + "scikit-learn__scikit-learn-13439", + "pytest-dev__pytest-7373", + "django__django-16527", +] + +MEDIUM_LITE_SUBSET = [ + "sympy__sympy-15346", + "sympy__sympy-16281", + "sympy__sympy-22840", + "pytest-dev__pytest-7220", + "django__django-12284", + "pytest-dev__pytest-7490", + "matplotlib__matplotlib-25442", + "django__django-13757", + "django__django-15790", + "sympy__sympy-18532", + "sympy__sympy-13471", + "scikit-learn__scikit-learn-15535", + "django__django-13447", + "django__django-15789", + "scikit-learn__scikit-learn-14894", + "django__django-14238", + "django__django-10914", + "pytest-dev__pytest-11143", + "django__django-16255", + "django__django-13658", +] + +LARGE_LITE_SUBSET = [ + "pytest-dev__pytest-5495", + "django__django-11797", + "django__django-14730", + "scikit-learn__scikit-learn-25500", + "sphinx-doc__sphinx-8506", + "django__django-16408", + "django__django-16910", + "sympy__sympy-12236", + "matplotlib__matplotlib-24265", + "django__django-15320", + "matplotlib__matplotlib-25311", + "django__django-12125", + "django__django-12747", + "matplotlib__matplotlib-24334", + "scikit-learn__scikit-learn-14983", + "scikit-learn__scikit-learn-13497", + "django__django-14580", + "pylint-dev__pylint-6506", + "matplotlib__matplotlib-23987", + "scikit-learn__scikit-learn-13497", + "django__django-14017", + "django__django-15213", + "django__django-12284", + "pylint-dev__pylint-7114", + "django__django-11422", + "django__django-11620", + "django__django-12284", + "sympy__sympy-13971", + "django__django-12284", + "sphinx-doc__sphinx-7975", + "scikit-learn__scikit-learn-15512", + "scikit-learn__scikit-learn-15512", + "pylint-dev__pylint-7993", + "django__django-12184", + "django__django-13315", + "sympy__sympy-15609", + "pylint-dev__pylint-7993", + "sympy__sympy-17022", + "pylint-dev__pylint-7993", + "sympy__sympy-15678", + "sympy__sympy-18057", + "sympy__sympy-17655", + "sympy__sympy-17655", + "django__django-13028", + "sympy__sympy-17139", + "django__django-14999", + "django__django-15790", + "scikit-learn__scikit-learn-11281", + "astropy__astropy-12907", + "django__django-11815", + "sympy__sympy-18621", + "django__django-11999", + "sphinx-doc__sphinx-8721", + "matplotlib__matplotlib-23314", + "sphinx-doc__sphinx-8721", + "sympy__sympy-18621", + "django__django-12497", + "scikit-learn__scikit-learn-13584", + "matplotlib__matplotlib-24970", + "scikit-learn__scikit-learn-13584", + "django__django-12453", + "sympy__sympy-20154", + "django__django-13447", + "sphinx-doc__sphinx-8595", + "sympy__sympy-20154", + "sympy__sympy-20154", + "django__django-12700", + "psf__requests-2317", + "django__django-16046", + "sympy__sympy-20154", + "sympy__sympy-20212", + "django__django-13710", + "sympy__sympy-13647", + "django__django-15851", + "scikit-learn__scikit-learn-14894", + "sympy__sympy-24213", + "scikit-learn__scikit-learn-13779", + "django__django-13710", + "django__django-13933", + "sympy__sympy-20212", + "django__django-14855", + "django__django-11039", + "django__django-16379", + "pydata__xarray-5131", + "pytest-dev__pytest-7373", + "django__django-16139", + "django__django-14382", + "pytest-dev__pytest-5227", + "django__django-16595", + "django__django-16379", + "django__django-16527", + "django__django-13658", + "django__django-16255", + "django__django-16527", + "django__django-13658", + "django__django-13658", + "django__django-13658", + "django__django-11099", + "django__django-16527", + "django__django-11099", +] + +LITE_SUBSETS = { + SWEBenchLiteSubset.LITE_SMALL: SMALL_LITE_SUBSET, + SWEBenchLiteSubset.LITE_MEDIUM: MEDIUM_LITE_SUBSET, + SWEBenchLiteSubset.LITE_LARGE: LARGE_LITE_SUBSET, +} diff --git a/src/codegen/extensions/swebench/success_rates.py b/src/codegen/extensions/swebench/success_rates.py new file mode 100644 index 000000000..2d3cbbdf1 --- /dev/null +++ b/src/codegen/extensions/swebench/success_rates.py @@ -0,0 +1,302 @@ +LITE_SUCCESS_RATES = { + "pallets__flask-5063": 0.0, + "sphinx-doc__sphinx-8282": 0.0, + "django__django-14667": 0.0, + "sphinx-doc__sphinx-8474": 0.0, + "sympy__sympy-11400": 0.0, + "sympy__sympy-11870": 0.0, + "sympy__sympy-11897": 0.0, + "sympy__sympy-12171": 0.0, + "sympy__sympy-12236": 0.0, + "sympy__sympy-13146": 0.0, + "sympy__sympy-13773": 0.0, + "sympy__sympy-13895": 0.0, + "django__django-13220": 0.0, + "sympy__sympy-13915": 0.0, + "sympy__sympy-14024": 0.0, + "sympy__sympy-14308": 0.0, + "django__django-14730": 0.0, + "sphinx-doc__sphinx-7738": 0.0, + "sphinx-doc__sphinx-7686": 0.0, + "django__django-14997": 0.0, + "matplotlib__matplotlib-25079": 0.0, + "pydata__xarray-4493": 0.0, + "matplotlib__matplotlib-22835": 0.0, + "matplotlib__matplotlib-18869": 0.0, + "pylint-dev__pylint-7228": 0.0, + "pytest-dev__pytest-5103": 0.0, + "pytest-dev__pytest-5221": 0.0, + "sympy__sympy-14317": 0.0, + "django__django-16820": 0.0, + "django__django-16229": 0.0, + "pytest-dev__pytest-9359": 0.0, + "scikit-learn__scikit-learn-10508": 0.0, + "scikit-learn__scikit-learn-10949": 0.0, + "scikit-learn__scikit-learn-11040": 0.0, + "django__django-15695": 0.0, + "scikit-learn__scikit-learn-25638": 0.0, + "django__django-16816": 0.0, + "sympy__sympy-15308": 0.0, + "matplotlib__matplotlib-25433": 0.0, + "sympy__sympy-18087": 0.0, + "astropy__astropy-7746": 0.0, + "django__django-11630": 0.0, + "sympy__sympy-18199": 0.0, + "sympy__sympy-23191": 0.0, + "sympy__sympy-17630": 0.0, + "sympy__sympy-19254": 0.0, + "sympy__sympy-21627": 0.0, + "sympy__sympy-16281": 0.0, + "sympy__sympy-16106": 0.0, + "sympy__sympy-24102": 0.0, + "django__django-11905": 0.0, + "sympy__sympy-21171": 0.0, + "sympy__sympy-20639": 0.0, + "django__django-12589": 0.0, + "sympy__sympy-20322": 0.0, + "django__django-11564": 0.0, + "django__django-11019": 0.0, + "django__django-16910": 0.02, + "django__django-15252": 0.02, + "pytest-dev__pytest-5413": 0.02, + "django__django-11742": 0.02, + "sphinx-doc__sphinx-8273": 0.02, + "pytest-dev__pytest-8906": 0.02, + "django__django-15996": 0.02, + "sympy__sympy-19007": 0.02, + "django__django-11910": 0.02, + "matplotlib__matplotlib-22711": 0.02, + "django__django-13768": 0.02, + "astropy__astropy-14182": 0.02, + "mwaskom__seaborn-3407": 0.02, + "pallets__flask-4045": 0.02, + "django__django-12908": 0.02, + "pallets__flask-4992": 0.02, + "pydata__xarray-3364": 0.02, + "sympy__sympy-16503": 0.02, + "django__django-15738": 0.02, + "pydata__xarray-4248": 0.02, + "django__django-13265": 0.02, + "sympy__sympy-13177": 0.02, + "django__django-13448": 0.02, + "django__django-12113": 0.02, + "sympy__sympy-13043": 0.02, + "sympy__sympy-12454": 0.02, + "sympy__sympy-13437": 0.02, + "django__django-16408": 0.03, + "pytest-dev__pytest-6116": 0.03, + "pytest-dev__pytest-8365": 0.03, + "psf__requests-2148": 0.03, + "sympy__sympy-21612": 0.03, + "astropy__astropy-14365": 0.03, + "matplotlib__matplotlib-23299": 0.03, + "django__django-11283": 0.03, + "django__django-14155": 0.03, + "sphinx-doc__sphinx-8506": 0.03, + "django__django-11797": 0.03, + "sympy__sympy-18698": 0.03, + "django__django-15320": 0.03, + "sphinx-doc__sphinx-10451": 0.03, + "django__django-15388": 0.03, + "sympy__sympy-20049": 0.03, + "django__django-15781": 0.05, + "django__django-13321": 0.05, + "sympy__sympy-18835": 0.05, + "django__django-14534": 0.05, + "matplotlib__matplotlib-24265": 0.05, + "django__django-15202": 0.05, + "django__django-12856": 0.05, + "matplotlib__matplotlib-23476": 0.05, + "django__django-15061": 0.05, + "sphinx-doc__sphinx-11445": 0.06, + "django__django-12470": 0.06, + "django__django-16400": 0.06, + "sympy__sympy-15346": 0.06, + "pytest-dev__pytest-5495": 0.06, + "sphinx-doc__sphinx-8801": 0.08, + "matplotlib__matplotlib-23563": 0.08, + "sympy__sympy-21379": 0.08, + "django__django-15819": 0.08, + "mwaskom__seaborn-2848": 0.08, + "scikit-learn__scikit-learn-25500": 0.08, + "sympy__sympy-12419": 0.08, + "django__django-12308": 0.09, + "sympy__sympy-14396": 0.09, + "sympy__sympy-15345": 0.09, + "sympy__sympy-19487": 0.09, + "pytest-dev__pytest-7168": 0.09, + "scikit-learn__scikit-learn-25747": 0.09, + "matplotlib__matplotlib-25498": 0.11, + "sympy__sympy-22840": 0.11, + "sphinx-doc__sphinx-8627": 0.11, + "pydata__xarray-4094": 0.11, + "pytest-dev__pytest-7220": 0.11, + "django__django-12747": 0.11, + "sympy__sympy-13031": 0.12, + "django__django-13660": 0.12, + "scikit-learn__scikit-learn-14983": 0.12, + "sphinx-doc__sphinx-8435": 0.14, + "sympy__sympy-20590": 0.14, + "scikit-learn__scikit-learn-14087": 0.14, + "sympy__sympy-24909": 0.14, + "django__django-15400": 0.14, + "matplotlib__matplotlib-25311": 0.14, + "pylint-dev__pylint-6506": 0.15, + "django__django-12125": 0.15, + "matplotlib__matplotlib-24334": 0.15, + "scikit-learn__scikit-learn-13497": 0.17, + "sympy__sympy-16792": 0.17, + "django__django-14580": 0.17, + "pylint-dev__pylint-7080": 0.18, + "matplotlib__matplotlib-25332": 0.18, + "sympy__sympy-22005": 0.18, + "sympy__sympy-20442": 0.2, + "django__django-13551": 0.2, + "sympy__sympy-14817": 0.2, + "matplotlib__matplotlib-23987": 0.2, + "django__django-13033": 0.21, + "sphinx-doc__sphinx-7975": 0.21, + "django__django-13925": 0.23, + "sphinx-doc__sphinx-10325": 0.23, + "sympy__sympy-16988": 0.23, + "pytest-dev__pytest-7490": 0.24, + "django__django-15213": 0.24, + "django__django-12284": 0.24, + "pytest-dev__pytest-11148": 0.24, + "django__django-11964": 0.24, + "pylint-dev__pylint-7114": 0.26, + "django__django-11422": 0.26, + "django__django-14017": 0.27, + "django__django-15902": 0.27, + "django__django-10924": 0.27, + "django__django-13158": 0.29, + "django__django-11620": 0.29, + "sympy__sympy-13971": 0.29, + "django__django-15498": 0.3, + "django__django-12184": 0.3, + "django__django-13964": 0.3, + "psf__requests-1963": 0.3, + "matplotlib__matplotlib-25442": 0.3, + "django__django-13757": 0.32, + "scikit-learn__scikit-learn-15512": 0.32, + "sympy__sympy-21614": 0.33, + "sympy__sympy-15609": 0.33, + "matplotlib__matplotlib-23562": 0.33, + "django__django-13315": 0.33, + "django__django-11848": 0.35, + "django__django-17087": 0.35, + "matplotlib__matplotlib-26011": 0.36, + "sympy__sympy-21055": 0.36, + "sympy__sympy-17022": 0.36, + "pylint-dev__pylint-7993": 0.36, + "astropy__astropy-6938": 0.38, + "sympy__sympy-15678": 0.38, + "django__django-17051": 0.38, + "scikit-learn__scikit-learn-14092": 0.38, + "pylint-dev__pylint-5859": 0.39, + "django__django-14411": 0.39, + "django__django-11001": 0.41, + "astropy__astropy-12907": 0.41, + "sympy__sympy-18057": 0.42, + "sympy__sympy-23262": 0.44, + "sympy__sympy-18189": 0.44, + "sympy__sympy-17139": 0.45, + "django__django-15790": 0.45, + "django__django-14999": 0.45, + "sympy__sympy-18532": 0.47, + "scikit-learn__scikit-learn-11281": 0.47, + "django__django-12915": 0.47, + "sympy__sympy-12481": 0.47, + "sympy__sympy-24066": 0.48, + "django__django-11815": 0.48, + "django__django-13028": 0.48, + "sympy__sympy-17655": 0.48, + "django__django-12708": 0.48, + "matplotlib__matplotlib-24970": 0.5, + "mwaskom__seaborn-3190": 0.52, + "scikit-learn__scikit-learn-13142": 0.52, + "matplotlib__matplotlib-26020": 0.53, + "scikit-learn__scikit-learn-15535": 0.53, + "sympy__sympy-13471": 0.53, + "sympy__sympy-15011": 0.53, + "psf__requests-3362": 0.55, + "matplotlib__matplotlib-24149": 0.55, + "matplotlib__matplotlib-23314": 0.55, + "django__django-14608": 0.56, + "scikit-learn__scikit-learn-13241": 0.56, + "scikit-learn__scikit-learn-25570": 0.56, + "sympy__sympy-18621": 0.56, + "scikit-learn__scikit-learn-13584": 0.56, + "django__django-13401": 0.58, + "pytest-dev__pytest-5692": 0.58, + "django__django-14787": 0.58, + "django__django-15814": 0.58, + "sphinx-doc__sphinx-8721": 0.58, + "django__django-14016": 0.58, + "django__django-11999": 0.59, + "django__django-12497": 0.59, + "psf__requests-2674": 0.59, + "matplotlib__matplotlib-23913": 0.59, + "pytest-dev__pytest-7432": 0.59, + "django__django-11049": 0.59, + "sympy__sympy-22714": 0.62, + "scikit-learn__scikit-learn-12471": 0.62, + "psf__requests-863": 0.62, + "django__django-14672": 0.62, + "sympy__sympy-20154": 0.62, + "django__django-13590": 0.64, + "django__django-12700": 0.64, + "sphinx-doc__sphinx-8595": 0.64, + "django__django-15789": 0.65, + "django__django-12453": 0.68, + "django__django-13447": 0.68, + "psf__requests-2317": 0.7, + "django__django-11583": 0.7, + "django__django-16046": 0.7, + "django__django-14238": 0.71, + "django__django-15851": 0.71, + "django__django-13710": 0.73, + "sympy__sympy-21847": 0.73, + "sympy__sympy-23117": 0.73, + "django__django-12983": 0.73, + "scikit-learn__scikit-learn-13779": 0.74, + "sympy__sympy-13647": 0.74, + "django__django-16041": 0.74, + "scikit-learn__scikit-learn-10297": 0.74, + "django__django-15347": 0.74, + "scikit-learn__scikit-learn-13496": 0.74, + "sympy__sympy-20212": 0.76, + "scikit-learn__scikit-learn-13439": 0.76, + "django__django-13933": 0.76, + "django__django-12286": 0.76, + "django__django-13230": 0.77, + "astropy__astropy-14995": 0.77, + "django__django-11179": 0.77, + "sphinx-doc__sphinx-8713": 0.77, + "sympy__sympy-24213": 0.77, + "matplotlib__matplotlib-23964": 0.79, + "scikit-learn__scikit-learn-14894": 0.79, + "django__django-10914": 0.8, + "pydata__xarray-5131": 0.8, + "django__django-11039": 0.82, + "pytest-dev__pytest-7373": 0.82, + "django__django-14915": 0.82, + "django__django-16595": 0.83, + "pytest-dev__pytest-11143": 0.85, + "sympy__sympy-14774": 0.85, + "pytest-dev__pytest-5227": 0.85, + "django__django-16873": 0.85, + "django__django-16139": 0.85, + "mwaskom__seaborn-3010": 0.86, + "django__django-14382": 0.86, + "django__django-14752": 0.86, + "sympy__sympy-13480": 0.86, + "django__django-16379": 0.86, + "sympy__sympy-24152": 0.88, + "django__django-14855": 0.88, + "django__django-11133": 0.88, + "django__django-11099": 0.91, + "django__django-13658": 0.91, + "django__django-16255": 0.91, + "django__django-16527": 0.91, +} diff --git a/src/codegen/extensions/swebench/utils.py b/src/codegen/extensions/swebench/utils.py index cd1ded36e..d977dce4e 100644 --- a/src/codegen/extensions/swebench/utils.py +++ b/src/codegen/extensions/swebench/utils.py @@ -1,17 +1,14 @@ import json from dataclasses import dataclass -from enum import Enum from pathlib import Path from pprint import pprint from typing import Literal, Optional from datasets import load_dataset - -class SWEBenchDataset(Enum): - LITE = "princeton-nlp/SWE-bench_Lite" - FULL = "princeton-nlp/SWE-bench" - VERIFIED = "princeton-nlp/SWE-bench-verified" +from codegen.extensions.swebench.enums import SWEBenchDataset, SWEBenchLiteSubset +from codegen.extensions.swebench.subsets import LITE_SUBSETS +from codegen.extensions.swebench.success_rates import LITE_SUCCESS_RATES @dataclass @@ -30,6 +27,7 @@ class SweBenchExample: fail_to_pass: str pass_to_pass: Optional[str] environment_setup_commit: Optional[str] + difficulty: Optional[int] def load_predictions(paths): @@ -64,11 +62,16 @@ def load_predictions(paths): return predictions +def get_difficulty(instance_id: str) -> int | None: + if instance_id in LITE_SUCCESS_RATES: + return 10 - int(LITE_SUCCESS_RATES[instance_id] * 10) + return None + + def get_swe_bench_examples( - dataset: SWEBenchDataset = SWEBenchDataset.LITE, + dataset: SWEBenchDataset | SWEBenchLiteSubset = SWEBenchLiteSubset.LITE_SMALL, split: Literal["train", "dev", "test"] = "test", - offset: int = 0, - length: int = 100, + length: int | None = None, instance_id: str | None = None, repo: str | None = None, ) -> list[SweBenchExample]: @@ -87,31 +90,26 @@ def get_swe_bench_examples( # Convert string dataset name to enum # Load the dataset with caching enabled - swe_bench_dataset = load_dataset(dataset.value, download_mode="reuse_dataset_if_exists") + instance_ids = [] + if isinstance(dataset, SWEBenchLiteSubset): + swe_bench_dataset = load_dataset(SWEBenchDataset.LITE.value, download_mode="reuse_dataset_if_exists") + instance_ids = LITE_SUBSETS[dataset] + else: + swe_bench_dataset = load_dataset(dataset.value, download_mode="reuse_dataset_if_exists") # Get the requested split split_data = swe_bench_dataset[split] - # Apply offset and length - if instance_id or repo: - offset = 0 - end_idx = len(split_data) - else: - end_idx = min(offset + length, len(split_data)) - if offset >= len(split_data): - return [] - - # Use the select method instead of slicing - # This ensures we get dictionary-like objects - selected_rows = split_data.select(range(offset, end_idx)) - # Convert to SweBenchExample objects examples = [] - for row in selected_rows: + for row in split_data: if instance_id and row["instance_id"] != instance_id: continue if repo and row["repo"] != repo: continue + if instance_ids and row["instance_id"] not in instance_ids: + continue + example = SweBenchExample( repo=row["repo"], instance_id=row["instance_id"], @@ -125,7 +123,11 @@ def get_swe_bench_examples( fail_to_pass=row["FAIL_TO_PASS"], pass_to_pass=row.get("PASS_TO_PASS"), environment_setup_commit=row.get("environment_setup_commit"), + difficulty=get_difficulty(row["instance_id"]), ) examples.append(example) - return examples[:length] + if length: + examples = examples[:length] + + return examples From 0d600cf625287485a0fe72cc948d5b940def07d3 Mon Sep 17 00:00:00 2001 From: Edo Pujol Date: Fri, 7 Mar 2025 20:01:07 -0500 Subject: [PATCH 54/66] chore: reverts to clasic regex + ripgrep search (#776) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- src/codegen/extensions/langchain/tools.py | 105 ++---------- src/codegen/extensions/tools/search.py | 185 +++++++++++++--------- 2 files changed, 115 insertions(+), 175 deletions(-) diff --git a/src/codegen/extensions/langchain/tools.py b/src/codegen/extensions/langchain/tools.py index 8551b68e6..7cda6d7f9 100644 --- a/src/codegen/extensions/langchain/tools.py +++ b/src/codegen/extensions/langchain/tools.py @@ -112,111 +112,24 @@ def _run(self, dirpath: str = "./", depth: int = 1) -> str: class SearchInput(BaseModel): + """Input for searching the codebase.""" + query: str = Field( ..., - description="""The text or pattern to search for in the codebase. - - For simple text search (use_regex=False): - - Uses ripgrep's fixed-strings mode (--fixed-strings) - - Case-insensitive matching (--ignore-case) - - All characters are treated literally, including special regex characters - - Exact string matching (no regex interpretation) - - For regex search (use_regex=True): - - Full regex pattern support - - Case-sensitive by default - - Special characters have regex meaning and need proper escaping - - Uses ripgrep's default regex mode - - If no exact matches are found, automatically falls back to semantic search - to find relevant code even without exact text matches.""", - ) - - target_directories: Optional[list[str]] = Field( - default=None, - description="""Optional list of directories to limit the search scope. - - - Paths should be relative to the workspace root - - Multiple directories are searched in parallel - - If None, searches the entire codebase - - Example: ["src/frontend", "tests/unit"]""", - ) - - file_extensions: Optional[list[str]] = Field( - default=None, - description="""Optional list of file extensions to filter the search. - - - Include the dot in extensions (e.g. ['.py', '.ts']) - - Multiple extensions are combined with OR logic - - If None, searches all file types - - Binary files are automatically excluded - - Example: [".py", ".tsx", ".md"]""", - ) - - page: int = Field( - default=1, - description="""Page number for paginated results (1-based indexing). - - - Use with files_per_page to navigate large result sets - - If page exceeds available pages, returns last available page - - Note: When falling back to semantic search, pagination is not supported - - Example: page=2 with files_per_page=10 shows files 11-20""", - ) - - files_per_page: int = Field( - default=10, - description="""Number of files to show per page. - - - Each file can contain multiple matching lines - - Reasonable values are between 5 and 50 - - Larger values may impact performance - - When falling back to semantic search, this becomes the number of semantic results - - Example: files_per_page=20 shows up to 20 files with matches""", - ) - - use_regex: bool = Field( - default=False, - description="""Whether to treat the query as a regex pattern. - - - False (default): Simple text search, case-insensitive - - True: Full regex syntax, case-sensitive - - Invalid regex patterns will return an error - - Note: Semantic fallback is used regardless of this setting when no matches found - - Example: Set to True to use patterns like "test_.*_func.*" """, + description="The search query to find in the codebase. When ripgrep is available, this will be passed as a ripgrep pattern. For regex searches, set use_regex=True. Ripgrep is the preferred method.", ) + target_directories: Optional[list[str]] = Field(default=None, description="Optional list of directories to search in") + file_extensions: Optional[list[str]] = Field(default=None, description="Optional list of file extensions to search (e.g. ['.py', '.ts'])") + page: int = Field(default=1, description="Page number to return (1-based, default: 1)") + files_per_page: int = Field(default=10, description="Number of files to return per page (default: 10)") + use_regex: bool = Field(default=False, description="Whether to treat query as a regex pattern (default: False)") class SearchTool(BaseTool): """Tool for searching the codebase.""" name: ClassVar[str] = "search" - description: ClassVar[str] = r"""Search the codebase using text search or regex pattern matching. - - This tool provides powerful text-based search capabilities across your codebase, - with support for both simple text matching and regular expressions. It uses ripgrep - when available for high-performance searches. - - If no exact matches are found, automatically falls back to semantic search to find - relevant code even without exact text matches. - - Features: - - Plain text or regex pattern matching - - Directory and file type filtering - - Paginated results for large codebases - - Case-insensitive by default for simple text searches - - Semantic fallback for finding related code - - Example queries: - 1. Simple text: "function calculateTotal" (matches exactly, case-insensitive) - 2. Regex: "def.*calculate.*\(.*\)" (with use_regex=True) - 3. File-specific: "TODO" with file_extensions=[".py", ".ts"] - 4. Directory-specific: "api" with target_directories=["src/backend"] - """ + description: ClassVar[str] = "Search the codebase using text search or regex pattern matching" args_schema: ClassVar[type[BaseModel]] = SearchInput codebase: Codebase = Field(exclude=True) diff --git a/src/codegen/extensions/tools/search.py b/src/codegen/extensions/tools/search.py index 8083e7db8..4bcdfb74e 100644 --- a/src/codegen/extensions/tools/search.py +++ b/src/codegen/extensions/tools/search.py @@ -3,8 +3,6 @@ This performs either a regex pattern match or simple text search across all files in the codebase. Each matching line will be returned with its line number. Results are paginated with a default of 10 files per page. - -If no exact matches are found, falls back to semantic search to find relevant code. """ import os @@ -17,7 +15,6 @@ from codegen.sdk.core.codebase import Codebase from .observation import Observation -from .semantic_search import SearchResult, semantic_search class SearchMatch(Observation): @@ -128,7 +125,7 @@ def _search_with_ripgrep( This is faster than the Python implementation, especially for large codebases. """ # Build ripgrep command - cmd = ["rg", "--line-number", "--with-filename"] + cmd = ["rg", "--line-number"] # Add case insensitivity if not using regex if not use_regex: @@ -203,6 +200,8 @@ def _search_with_ripgrep( match_text = query if use_regex: # For regex, we need to find what actually matched + # This is a simplification - ideally we'd use ripgrep's --json option + # to get the exact match positions pattern = re.compile(query) match_obj = pattern.search(content) if match_obj: @@ -227,20 +226,11 @@ def _search_with_ripgrep( # Convert to SearchFileResult objects file_results = [] for filepath, matches in all_results.items(): - # Sort matches by line number and deduplicate - unique_matches = [] - seen = set() - for match in sorted(matches, key=lambda x: x.line_number): - key = (match.line_number, match.match) - if key not in seen: - seen.add(key) - unique_matches.append(match) - file_results.append( SearchFileResult( status="success", filepath=filepath, - matches=unique_matches, + matches=sorted(matches, key=lambda x: x.line_number), ) ) @@ -271,40 +261,120 @@ def _search_with_ripgrep( raise -def _convert_semantic_to_search_results(semantic_results: list[SearchResult], query: str) -> list[SearchFileResult]: - """Convert semantic search results to regular search results format.""" - file_results = [] - for result in semantic_results: - file_results.append( - SearchFileResult( - status="success", - filepath=result.filepath, - matches=[ +def _search_with_python( + codebase: Codebase, + query: str, + target_directories: Optional[list[str]] = None, + file_extensions: Optional[list[str]] = None, + page: int = 1, + files_per_page: int = 10, + use_regex: bool = False, +) -> SearchObservation: + """Search the codebase using Python's regex engine. + + This is a fallback for when ripgrep is not available. + """ + # Validate pagination parameters + if page < 1: + page = 1 + if files_per_page < 1: + files_per_page = 10 + + # Prepare the search pattern + if use_regex: + try: + pattern = re.compile(query) + except re.error as e: + return SearchObservation( + status="error", + error=f"Invalid regex pattern: {e!s}", + query=query, + page=page, + total_pages=0, + total_files=0, + files_per_page=files_per_page, + results=[], + ) + else: + # For non-regex searches, escape special characters and make case-insensitive + pattern = re.compile(re.escape(query), re.IGNORECASE) + + # Handle file extensions + extensions = file_extensions if file_extensions is not None else "*" + + all_results = [] + for file in codebase.files(extensions=extensions): + # Skip if file doesn't match target directories + if target_directories and not any(file.filepath.startswith(d) for d in target_directories): + continue + + # Skip binary files + try: + content = file.content + except ValueError: # File is binary + continue + + file_matches = [] + # Split content into lines and store with line numbers (1-based) + lines = enumerate(content.splitlines(), 1) + + # Search each line for the pattern + for line_number, line in lines: + match = pattern.search(line) + if match: + file_matches.append( SearchMatch( status="success", - line_number=1, # We don't have line numbers for semantic matches - line=result.preview, - match=query, + line_number=line_number, + line=line.strip(), + match=match.group(0), ) - ], + ) + + if file_matches: + all_results.append( + SearchFileResult( + status="success", + filepath=file.filepath, + matches=sorted(file_matches, key=lambda x: x.line_number), + ) ) - ) - return file_results + + # Sort all results by filepath + all_results.sort(key=lambda x: x.filepath) + + # Calculate pagination + total_files = len(all_results) + total_pages = (total_files + files_per_page - 1) // files_per_page + start_idx = (page - 1) * files_per_page + end_idx = start_idx + files_per_page + + # Get the current page of results + paginated_results = all_results[start_idx:end_idx] + + return SearchObservation( + status="success", + query=query, + page=page, + total_pages=total_pages, + total_files=total_files, + files_per_page=files_per_page, + results=paginated_results, + ) def search( codebase: Codebase, query: str, target_directories: Optional[list[str]] = None, - file_extensions: Optional[list[str] | str] = None, + file_extensions: Optional[list[str]] = None, page: int = 1, files_per_page: int = 10, use_regex: bool = False, ) -> SearchObservation: """Search the codebase using text search or regex pattern matching. - Uses ripgrep for performance when available. If no exact matches are found, - falls back to semantic search to find relevant code. + Uses ripgrep for performance when available, with fallback to Python's regex engine. If use_regex is True, performs a regex pattern match on each line. Otherwise, performs a case-insensitive text search. Returns matching lines with their line numbers, grouped by file. @@ -323,52 +393,9 @@ def search( Returns: SearchObservation containing search results with matches and their sources """ + # Try to use ripgrep first try: - # Try ripgrep first - result = _search_with_ripgrep(codebase, query, target_directories, file_extensions, page, files_per_page, use_regex) - - # If no results found, try semantic search - if not result.results: - semantic_results = semantic_search(codebase, query, k=files_per_page) - if semantic_results.status == "success" and semantic_results.results: - # Convert semantic results to regular search results format - file_results = _convert_semantic_to_search_results(semantic_results.results, query) - - return SearchObservation( - status="success", - query=query, - page=1, # Semantic search doesn't support pagination yet - total_pages=1, - total_files=len(file_results), - files_per_page=files_per_page, - results=file_results, - ) - - return result - + return _search_with_ripgrep(codebase, query, target_directories, file_extensions, page, files_per_page, use_regex) except (FileNotFoundError, subprocess.SubprocessError): - # If ripgrep fails, try semantic search directly - semantic_results = semantic_search(codebase, query, k=files_per_page) - if semantic_results.status == "success": - file_results = _convert_semantic_to_search_results(semantic_results.results, query) - - return SearchObservation( - status="success", - query=query, - page=1, - total_pages=1, - total_files=len(file_results), - files_per_page=files_per_page, - results=file_results, - ) - else: - return SearchObservation( - status="error", - error=f"Both text search and semantic search failed: {semantic_results.error}", - query=query, - page=page, - total_pages=0, - total_files=0, - files_per_page=files_per_page, - results=[], - ) + # Fall back to Python implementation if ripgrep fails or isn't available + return _search_with_python(codebase, query, target_directories, file_extensions, page, files_per_page, use_regex) From e8783f6f1dd6a5a926d19683b792824543a2db08 Mon Sep 17 00:00:00 2001 From: jemeza-codegen <165736868+jemeza-codegen@users.noreply.github.com> Date: Fri, 7 Mar 2025 17:45:52 -0800 Subject: [PATCH 55/66] chore: improvements to command line arguments (#781) # Motivation Makes `run_eval` command require explicit arguments # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- .../examples/swebench_agent_run/run_eval.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/codegen-examples/examples/swebench_agent_run/run_eval.py b/codegen-examples/examples/swebench_agent_run/run_eval.py index b38041c88..b1567f8f6 100644 --- a/codegen-examples/examples/swebench_agent_run/run_eval.py +++ b/codegen-examples/examples/swebench_agent_run/run_eval.py @@ -269,14 +269,14 @@ def process_batch_local(examples: list[SweBenchExample], model: str, num_workers async def run_eval( - use_existing_preds: str | None, dataset: str, - length: int, + use_existing_preds: str | None = None, + length: int | None = None, instance_id: str | None = None, local: bool = False, codebases: dict[str, Codebase] = {}, repo: str | None = None, - num_workers: int = 5, + num_workers: int = 2, model: str = "claude-3-7-sonnet-latest", ): run_id = use_existing_preds or str(uuid.uuid4()) @@ -353,9 +353,9 @@ async def run_eval( @click.command() -@click.option("--use-existing-preds", help="The run ID of the existing predictions to use.", type=str, default=None) @click.option("--dataset", help="The dataset to use.", type=click.Choice(["lite", "full", "verified", "lite_small", "lite_medium", "lite_large"]), default="lite") -@click.option("--length", help="The number of examples to process.", type=int, default=10) +@click.option("--use-existing-preds", help="The run ID of the existing predictions to use.", type=str, default=None) +@click.option("--length", help="The number of examples to process.", type=int, default=None) @click.option("--instance-id", help="The instance ID of the example to process.", type=str, default=None) @click.option("--local", help="Run the evaluation locally.", is_flag=True, default=False) @click.option("--repo", help="The repo to use.", type=str, default=None) @@ -363,10 +363,10 @@ async def run_eval( "--num-workers", help="The number of workers to use. This is the number of examples that will be processed concurrently. A large number may lead to rate limiting issues.", type=int, default=5 ) @click.option("--model", help="The model to use.", type=str, default="claude-3-7-sonnet-latest") -def run_eval_command(use_existing_preds, dataset, length, instance_id, local, repo, num_workers, model): +def run_eval_command(dataset, use_existing_preds, length, instance_id, local, repo, num_workers, model): print(f"Repo: {repo}") print(f"Model: {model}") - asyncio.run(run_eval(use_existing_preds=use_existing_preds, dataset=dataset, length=length, instance_id=instance_id, codebases=None, local=local, repo=repo, num_workers=num_workers, model=model)) + asyncio.run(run_eval(dataset=dataset, use_existing_preds=use_existing_preds, length=length, instance_id=instance_id, local=local, repo=repo, num_workers=num_workers, model=model)) if __name__ == "__main__": From 8a5818ead966118b068771085e1e6c93206fc149 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 9 Mar 2025 14:49:59 +0000 Subject: [PATCH 56/66] fix(deps): update dependency openai to v1.65.5 (#782) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [openai](https://redirect.github.com/openai/openai-python) | `==1.65.4` -> `==1.65.5` | [![age](https://developer.mend.io/api/mc/badges/age/pypi/openai/1.65.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/openai/1.65.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/openai/1.65.4/1.65.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/openai/1.65.4/1.65.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
openai/openai-python (openai) ### [`v1.65.5`](https://redirect.github.com/openai/openai-python/blob/HEAD/CHANGELOG.md#1655-2025-03-09) Full Changelog: [v1.65.4...v1.65.5](https://redirect.github.com/openai/openai-python/compare/v1.65.4...v1.65.5) ##### Chores - move ChatModel type to shared ([#​2167](https://redirect.github.com/openai/openai-python/issues/2167)) ([104f02a](https://redirect.github.com/openai/openai-python/commit/104f02af371076d5d2498e48ae14d2eacc7df8bd))
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - "* 0-3 * * 1" (UTC). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/codegen-sh/codegen). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- uv.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 777d80ec1..bbbb9ccde 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" # renovate: datasource=python-version depName=python requires-python = ">=3.12, <3.14" dependencies = [ - "openai==1.65.4", + "openai==1.65.5", "tiktoken<1.0.0,>=0.5.1", "tabulate>=0.9.0,<1.0.0", "codeowners<1.0.0,>=0.6.0", diff --git a/uv.lock b/uv.lock index 9796f29bb..27f9fed2e 100644 --- a/uv.lock +++ b/uv.lock @@ -690,7 +690,7 @@ requires-dist = [ { name = "langchain-anthropic", specifier = ">=0.3.7" }, { name = "langchain-core" }, { name = "langchain-openai" }, - { name = "langchain-xai" }, + { name = "langchain-xai", specifier = ">=0.2.1" }, { name = "langgraph" }, { name = "langgraph-prebuilt" }, { name = "langsmith" }, @@ -703,7 +703,7 @@ requires-dist = [ { name = "neo4j" }, { name = "networkx", specifier = ">=3.4.1" }, { name = "numpy", specifier = ">=2.2.2" }, - { name = "openai", specifier = "==1.65.4" }, + { name = "openai", specifier = "==1.65.5" }, { name = "packaging", specifier = ">=24.2" }, { name = "pip", specifier = ">=24.3.1" }, { name = "plotly", specifier = ">=5.24.0,<7.0.0" }, @@ -2733,7 +2733,7 @@ wheels = [ [[package]] name = "openai" -version = "1.65.4" +version = "1.65.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2745,9 +2745,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fa/8d/1f7aace801afbbe4d6b8c7fa89b76eb9a3a8eeff38b84d4005d47b226b30/openai-1.65.4.tar.gz", hash = "sha256:0b08c58625d556f5c6654701af1023689c173eb0989ce8f73c7fd0eb22203c76", size = 359365 } +sdist = { url = "https://files.pythonhosted.org/packages/56/cf/e02fb2c5a834803e6f29f43fd3dfe010303282d1ea450a5b95e28608860a/openai-1.65.5.tar.gz", hash = "sha256:17d39096bbcaf6c86580244b493a59e16613460147f0ba5ab6e608cdb6628149", size = 359548 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/db/7bab832be24631a793492c1c61ecbf029018b99696f435db3b63d690bf1c/openai-1.65.4-py3-none-any.whl", hash = "sha256:15566d46574b94eae3d18efc2f9a4ebd1366d1d44bfc1bdafeea7a5cf8271bcb", size = 473523 }, + { url = "https://files.pythonhosted.org/packages/fc/8f/a178d73277bf2d838617fa20ba4ae6952e26074664aacb53ae4532a69588/openai-1.65.5-py3-none-any.whl", hash = "sha256:5948a504e7b4003d921cfab81273813793a31c25b1d7b605797c01757e0141f1", size = 474468 }, ] [[package]] From d53181c1214035fb46ae9212f32f79c41e080532 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 9 Mar 2025 14:51:50 +0000 Subject: [PATCH 57/66] update changelog --- docs/changelog/changelog.mdx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 947a1a9ee..9cd4834aa 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,13 @@ icon: "clock" iconType: "solid" --- + +### [Adds dataset subsets and improves CLI arguments.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.5) +- Updated OpenAI dependency +- Improved command line arguments +- Added subsets of swe-bench lite dataset + + ### [Fixes import issue and removes outdated Chat Agent.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.4) - Fix search tool import issue From d9cb6d94124c07567f7c9d9c4553a3a9a408b75d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 02:31:21 +0000 Subject: [PATCH 58/66] chore(deps): lock file maintenance (#784) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "* 0-3 * * 1" (UTC), Automerge - "* 0-3 * * 1" (UTC). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/codegen-sh/codegen). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- codegen-examples/uv.lock | 482 ++++++++++++++----------------------- uv.lock | 496 ++++++++++++++------------------------- 2 files changed, 343 insertions(+), 635 deletions(-) diff --git a/codegen-examples/uv.lock b/codegen-examples/uv.lock index d34fae7ac..268c77f50 100644 --- a/codegen-examples/uv.lock +++ b/codegen-examples/uv.lock @@ -14,11 +14,11 @@ members = [ [[package]] name = "aiohappyeyeballs" -version = "2.4.6" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/08/07/508f9ebba367fc3370162e53a3cfd12f5652ad79f0e0bfdf9f9847c6f159/aiohappyeyeballs-2.4.6.tar.gz", hash = "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0", size = 21726 } +sdist = { url = "https://files.pythonhosted.org/packages/a2/0c/458958007041f4b4de2d307e6b75d9e7554dad0baf26fe7a48b741aac126/aiohappyeyeballs-2.5.0.tar.gz", hash = "sha256:18fde6204a76deeabc97c48bdd01d5801cfda5d6b9c8bbeb1aaaee9d648ca191", size = 22494 } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/4c/03fb05f56551828ec67ceb3665e5dc51638042d204983a03b0a1541475b6/aiohappyeyeballs-2.4.6-py3-none-any.whl", hash = "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1", size = 14543 }, + { url = "https://files.pythonhosted.org/packages/1b/9a/e4886864ce06e1579bd428208127fbdc0d62049c751e4e9e3b509c0059dc/aiohappyeyeballs-2.5.0-py3-none-any.whl", hash = "sha256:0850b580748c7071db98bffff6d4c94028d0d3035acc20fd721a0ce7e8cac35d", size = 15128 }, ] [[package]] @@ -82,15 +82,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", size = 7597 }, ] -[[package]] -name = "alabaster" -version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929 }, -] - [[package]] name = "annotated-types" version = "0.7.0" @@ -143,11 +134,11 @@ wheels = [ [[package]] name = "argcomplete" -version = "3.5.3" +version = "3.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0c/be/6c23d80cb966fb8f83fb1ebfb988351ae6b0554d0c3a613ee4531c026597/argcomplete-3.5.3.tar.gz", hash = "sha256:c12bf50eded8aebb298c7b7da7a5ff3ee24dffd9f5281867dfe1424b58c55392", size = 72999 } +sdist = { url = "https://files.pythonhosted.org/packages/ee/be/29abccb5d9f61a92886a2fba2ac22bf74326b5c4f55d36d0a56094630589/argcomplete-3.6.0.tar.gz", hash = "sha256:2e4e42ec0ba2fff54b0d244d0b1623e86057673e57bafe72dda59c64bd5dee8b", size = 73135 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c4/08/2a4db06ec3d203124c967fc89295e85a202e5cbbcdc08fd6a64b65217d1e/argcomplete-3.5.3-py3-none-any.whl", hash = "sha256:2ab2c4a215c59fd6caaff41a869480a23e8f6a5f910b266c1808037f4e375b61", size = 43569 }, + { url = "https://files.pythonhosted.org/packages/08/94/e786d91ccc3a1fc664c20332825b73da20928eb067cdc984b821948a1acc/argcomplete-3.6.0-py3-none-any.whl", hash = "sha256:4e3e4e10beb20e06444dbac0ac8dda650cb6349caeefe980208d3c548708bedd", size = 43769 }, ] [[package]] @@ -407,7 +398,7 @@ wheels = [ [[package]] name = "codegen" -version = "0.43.2" +version = "0.48.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astor" }, @@ -431,6 +422,7 @@ dependencies = [ { name = "langchain-anthropic" }, { name = "langchain-core" }, { name = "langchain-openai" }, + { name = "langchain-xai" }, { name = "langgraph" }, { name = "langgraph-prebuilt" }, { name = "langsmith" }, @@ -484,14 +476,14 @@ dependencies = [ { name = "xmltodict" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/e1/ff1a5bc1c5e4e030e176eb37c3e480395a38e0ce613cc7c9af0ccb378f15/codegen-0.43.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:936004461a5bf014ae887e200a235ad7731d54057a7ba148c3224b5a6f1a8b96", size = 1146690 }, - { url = "https://files.pythonhosted.org/packages/4c/4e/d4f7043fadd416dc5b0d9ec9a11aa86d0d11d4d9f130e9c862b756cf481a/codegen-0.43.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:36533914fbb78e16708c280320e2fa65bfff404dc3b7fb276b4f02a899f1b793", size = 1137829 }, - { url = "https://files.pythonhosted.org/packages/3a/04/0436ff5617313570523663bbad46d11f1827b7cfcc70c1a896ebb60a7256/codegen-0.43.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_34_aarch64.whl", hash = "sha256:ccc83c2542b2843a75fd12327621639afdc9b009338231bc83bea14d44656c7f", size = 2142117 }, - { url = "https://files.pythonhosted.org/packages/51/ed/24a7e6a3c44264849256e784d0a3ffe30e83407ee3b3d24dbaae20d43c97/codegen-0.43.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_34_x86_64.whl", hash = "sha256:1010714abf56c9e252647c1a961a438e65fcb5f65169493d4c4fda0da36bd0cd", size = 2191390 }, - { url = "https://files.pythonhosted.org/packages/15/cd/63808926dbfb46b48786242c7680fdfd69357a848ca08fbb2c88b6d93b47/codegen-0.43.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:388bc76c57c93ccede4af4cec535083135079990f960719309ce331b8bb154b3", size = 1142110 }, - { url = "https://files.pythonhosted.org/packages/3b/8a/72fff90bdc517143fc0a17b31cd09360705a7549cdf299f4230f67b9d88c/codegen-0.43.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:24ae5b7f540e6e9ff55ade1171e3d1e718312bcc2589650436407059f334ffe0", size = 1133994 }, - { url = "https://files.pythonhosted.org/packages/9c/6e/7b9bcd9385ec35db07c08e234bacaac445cab9fdf0801535f1343d55f9a2/codegen-0.43.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_34_aarch64.whl", hash = "sha256:aaccab5b2063bf74c6c2125fb5a4ff65fd6792c24876c60f3f79ef16c82263b5", size = 2134861 }, - { url = "https://files.pythonhosted.org/packages/e9/36/e991085e3e7a1c369a2d1deb75fc7e9dba855dcbccdd437ef404cd40fd8a/codegen-0.43.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_34_x86_64.whl", hash = "sha256:1f2aa88e0e2ecae0883798656e38ce300cbeabc20dced33a1fbfca8271ac068f", size = 2181238 }, + { url = "https://files.pythonhosted.org/packages/b8/a1/2e79373ece8044ff60975dd0f64c7782059e75767b5551541bfe03e8235c/codegen-0.48.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:92379780a883a87a18d2016eac6fba94fd6ea1e6ae8d5a4f2bf2bea619798421", size = 1158326 }, + { url = "https://files.pythonhosted.org/packages/bc/15/79f6870fa73f4d31726b6a2ad04261c6f5a4ff64fa5acc59425222cc621c/codegen-0.48.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d0de392531421fc8bd7ea49efe9d7f2e6b621d26dcb108be409511edcb5ad0a", size = 1149461 }, + { url = "https://files.pythonhosted.org/packages/b8/5c/f8e35680b1b4d2f6bed47f87ed1ecd7221f292c480e6136550fb1ea286b2/codegen-0.48.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_34_aarch64.whl", hash = "sha256:433de2e2619df3ae2674c5e6b0e67d9e167353e7cc0509eb52e214af93a77349", size = 2153759 }, + { url = "https://files.pythonhosted.org/packages/c0/94/3aaad37d7686850cf9e63d6cb4410144ac54a0d1d33c1f9f0cb51832c99f/codegen-0.48.5-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_34_x86_64.whl", hash = "sha256:a69764e76a0bee45851416da955a9f69919323490e3328c45a59360b59381d7f", size = 2203035 }, + { url = "https://files.pythonhosted.org/packages/78/a3/eb1f4c0f07d1732b887ee75c4077f966546d976cb4bed6446625e5502d94/codegen-0.48.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:faf7768cab6e2ebb990cce9ef37272b98fe12a8fcad5435c080656911d6bb5f9", size = 1153747 }, + { url = "https://files.pythonhosted.org/packages/e9/0a/63a808ebe700c01f63618efb68749321f0d5d81394461f1e697666081a1c/codegen-0.48.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3a32bf053e699ca380752d7440cac01e6f50f2558451b503dfac3f2f3db42ac8", size = 1145635 }, + { url = "https://files.pythonhosted.org/packages/f4/98/9f835f7cd40564eef0b65b12a6b063d2ce305ee5e1416a28466b5a75b062/codegen-0.48.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_34_aarch64.whl", hash = "sha256:c8d0d5eb92573c81c0fa8309c11fe1c840da7aaf730200c42f31dd59dafcb7ee", size = 2146504 }, + { url = "https://files.pythonhosted.org/packages/a5/5a/7b48ed2441d401b844793bd1b8c3c2f86066944166d24a1cb3208885a145/codegen-0.48.5-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_34_x86_64.whl", hash = "sha256:2d4dce804a3de5b92e32dd60c8623184381a8f2f856cc625ddffca2f152792cb", size = 2192882 }, ] [[package]] @@ -663,19 +655,19 @@ wheels = [ [[package]] name = "debugpy" -version = "1.8.12" +version = "1.8.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/68/25/c74e337134edf55c4dfc9af579eccb45af2393c40960e2795a94351e8140/debugpy-1.8.12.tar.gz", hash = "sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce", size = 1641122 } +sdist = { url = "https://files.pythonhosted.org/packages/51/d4/f35f539e11c9344652f362c22413ec5078f677ac71229dc9b4f6f85ccaa3/debugpy-1.8.13.tar.gz", hash = "sha256:837e7bef95bdefba426ae38b9a94821ebdc5bea55627879cd48165c90b9e50ce", size = 1641193 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/e6/0f876ecfe5831ebe4762b19214364753c8bc2b357d28c5d739a1e88325c7/debugpy-1.8.12-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498", size = 2500846 }, - { url = "https://files.pythonhosted.org/packages/19/64/33f41653a701f3cd2cbff8b41ebaad59885b3428b5afd0d93d16012ecf17/debugpy-1.8.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06", size = 4222181 }, - { url = "https://files.pythonhosted.org/packages/32/a6/02646cfe50bfacc9b71321c47dc19a46e35f4e0aceea227b6d205e900e34/debugpy-1.8.12-cp312-cp312-win32.whl", hash = "sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d", size = 5227017 }, - { url = "https://files.pythonhosted.org/packages/da/a6/10056431b5c47103474312cf4a2ec1001f73e0b63b1216706d5fef2531eb/debugpy-1.8.12-cp312-cp312-win_amd64.whl", hash = "sha256:39dfbb6fa09f12fae32639e3286112fc35ae976114f1f3d37375f3130a820969", size = 5267555 }, - { url = "https://files.pythonhosted.org/packages/cf/4d/7c3896619a8791effd5d8c31f0834471fc8f8fb3047ec4f5fc69dd1393dd/debugpy-1.8.12-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:696d8ae4dff4cbd06bf6b10d671e088b66669f110c7c4e18a44c43cf75ce966f", size = 2485246 }, - { url = "https://files.pythonhosted.org/packages/99/46/bc6dcfd7eb8cc969a5716d858e32485eb40c72c6a8dc88d1e3a4d5e95813/debugpy-1.8.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:898fba72b81a654e74412a67c7e0a81e89723cfe2a3ea6fcd3feaa3395138ca9", size = 4218616 }, - { url = "https://files.pythonhosted.org/packages/03/dd/d7fcdf0381a9b8094da1f6a1c9f19fed493a4f8576a2682349b3a8b20ec7/debugpy-1.8.12-cp313-cp313-win32.whl", hash = "sha256:22a11c493c70413a01ed03f01c3c3a2fc4478fc6ee186e340487b2edcd6f4180", size = 5226540 }, - { url = "https://files.pythonhosted.org/packages/25/bd/ecb98f5b5fc7ea0bfbb3c355bc1dd57c198a28780beadd1e19915bf7b4d9/debugpy-1.8.12-cp313-cp313-win_amd64.whl", hash = "sha256:fdb3c6d342825ea10b90e43d7f20f01535a72b3a1997850c0c3cefa5c27a4a2c", size = 5267134 }, - { url = "https://files.pythonhosted.org/packages/38/c4/5120ad36405c3008f451f94b8f92ef1805b1e516f6ff870f331ccb3c4cc0/debugpy-1.8.12-py2.py3-none-any.whl", hash = "sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6", size = 5229490 }, + { url = "https://files.pythonhosted.org/packages/79/ad/dff929b6b5403feaab0af0e5bb460fd723f9c62538b718a9af819b8fff20/debugpy-1.8.13-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:2b8de94c5c78aa0d0ed79023eb27c7c56a64c68217d881bee2ffbcb13951d0c1", size = 2501004 }, + { url = "https://files.pythonhosted.org/packages/d6/4f/b7d42e6679f0bb525888c278b0c0d2b6dff26ed42795230bb46eaae4f9b3/debugpy-1.8.13-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887d54276cefbe7290a754424b077e41efa405a3e07122d8897de54709dbe522", size = 4222346 }, + { url = "https://files.pythonhosted.org/packages/ec/18/d9b3e88e85d41f68f77235112adc31012a784e45a3fcdbb039777d570a0f/debugpy-1.8.13-cp312-cp312-win32.whl", hash = "sha256:3872ce5453b17837ef47fb9f3edc25085ff998ce63543f45ba7af41e7f7d370f", size = 5226639 }, + { url = "https://files.pythonhosted.org/packages/c9/f7/0df18a4f530ed3cc06f0060f548efe9e3316102101e311739d906f5650be/debugpy-1.8.13-cp312-cp312-win_amd64.whl", hash = "sha256:63ca7670563c320503fea26ac688988d9d6b9c6a12abc8a8cf2e7dd8e5f6b6ea", size = 5268735 }, + { url = "https://files.pythonhosted.org/packages/b1/db/ae7cd645c1826aae557cebccbc448f0cc9a818d364efb88f8d80e7a03f41/debugpy-1.8.13-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:31abc9618be4edad0b3e3a85277bc9ab51a2d9f708ead0d99ffb5bb750e18503", size = 2485416 }, + { url = "https://files.pythonhosted.org/packages/ec/ed/db4b10ff3b5bb30fe41d9e86444a08bb6448e4d8265e7768450b8408dd36/debugpy-1.8.13-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0bd87557f97bced5513a74088af0b84982b6ccb2e254b9312e29e8a5c4270eb", size = 4218784 }, + { url = "https://files.pythonhosted.org/packages/82/82/ed81852a8d94086f51664d032d83c7f87cd2b087c6ea70dabec7c1ba813d/debugpy-1.8.13-cp313-cp313-win32.whl", hash = "sha256:5268ae7fdca75f526d04465931cb0bd24577477ff50e8bb03dab90983f4ebd02", size = 5226270 }, + { url = "https://files.pythonhosted.org/packages/15/63/aa92fb341a78ec40f1c414ec7a7885c2ee17032eee00d12cee0cdc502af4/debugpy-1.8.13-cp313-cp313-win_amd64.whl", hash = "sha256:79ce4ed40966c4c1631d0131606b055a5a2f8e430e3f7bf8fd3744b09943e8e8", size = 5268621 }, + { url = "https://files.pythonhosted.org/packages/37/4f/0b65410a08b6452bfd3f7ed6f3610f1a31fb127f46836e82d31797065dcb/debugpy-1.8.13-py2.py3-none-any.whl", hash = "sha256:d4ba115cdd0e3a70942bd562adba9ec8c651fe69ddde2298a1be296fc331906f", size = 5229306 }, ] [[package]] @@ -798,15 +790,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d5/7c/e9fcff7623954d86bdc17782036cbf715ecab1bec4847c008557affe1ca8/docstring_parser-0.16-py3-none-any.whl", hash = "sha256:bf0a1387354d3691d102edef7ec124f219ef639982d096e26e3b60aeffa90637", size = 36533 }, ] -[[package]] -name = "docutils" -version = "0.21.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408 }, -] - [[package]] name = "dotty-dict" version = "1.3.1" @@ -1166,7 +1149,7 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "0.29.1" +version = "0.29.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, @@ -1177,9 +1160,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/37/797d6476f13e5ef6af5fc48a5d641d32b39c37e166ccf40c3714c5854a85/huggingface_hub-0.29.1.tar.gz", hash = "sha256:9524eae42077b8ff4fc459ceb7a514eca1c1232b775276b009709fe2a084f250", size = 389776 } +sdist = { url = "https://files.pythonhosted.org/packages/58/b2/f8b3c9842a794e8203448725aefa02d7c9e0da42d5f22f4ed806057cc36e/huggingface_hub-0.29.2.tar.gz", hash = "sha256:590b29c0dcbd0ee4b7b023714dc1ad8563fe4a68a91463438b74e980d28afaf3", size = 389816 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/05/75b90de9093de0aadafc868bb2fa7c57651fd8f45384adf39bd77f63980d/huggingface_hub-0.29.1-py3-none-any.whl", hash = "sha256:352f69caf16566c7b6de84b54a822f6238e17ddd8ae3da4f8f2272aea5b198d5", size = 468049 }, + { url = "https://files.pythonhosted.org/packages/13/5f/088ff08dc41808fcd99d9972b9bcfa7e3a35e30e8b0a3155b57938f1611c/huggingface_hub-0.29.2-py3-none-any.whl", hash = "sha256:c56f20fca09ef19da84dcde2b76379ecdaddf390b083f59f166715584953307d", size = 468087 }, ] [[package]] @@ -1202,11 +1185,11 @@ wheels = [ [[package]] name = "identify" -version = "2.6.8" +version = "2.6.9" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/fa/5eb460539e6f5252a7c5a931b53426e49258cde17e3d50685031c300a8fd/identify-2.6.8.tar.gz", hash = "sha256:61491417ea2c0c5c670484fd8abbb34de34cdae1e5f39a73ee65e48e4bb663fc", size = 99249 } +sdist = { url = "https://files.pythonhosted.org/packages/9b/98/a71ab060daec766acc30fb47dfca219d03de34a70d616a79a38c6066c5bf/identify-2.6.9.tar.gz", hash = "sha256:d40dfe3142a1421d8518e3d3985ef5ac42890683e32306ad614a29490abeb6bf", size = 99249 } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/8c/4bfcab2d8286473b8d83ea742716f4b79290172e75f91142bc1534b05b9a/identify-2.6.8-py2.py3-none-any.whl", hash = "sha256:83657f0f766a3c8d0eaea16d4ef42494b39b34629a4b3192a9d020d349b3e255", size = 99109 }, + { url = "https://files.pythonhosted.org/packages/07/ce/0845144ed1f0e25db5e7a79c2354c1da4b5ce392b8966449d5db8dca18f1/identify-2.6.9-py2.py3-none-any.whl", hash = "sha256:c98b4322da415a8e5a70ff6e51fbc2d2932c015532d77e9f8537b4ba7813b150", size = 99101 }, ] [[package]] @@ -1218,15 +1201,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] -[[package]] -name = "imagesize" -version = "1.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769 }, -] - [[package]] name = "importlib-resources" version = "6.5.2" @@ -1280,7 +1254,7 @@ wheels = [ [[package]] name = "ipython" -version = "9.0.0" +version = "9.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -1294,9 +1268,9 @@ dependencies = [ { name = "stack-data" }, { name = "traitlets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/de/39/264894738a202ddaf6abae39b3f84671ddee23fd292dbb3e10039e70300c/ipython-9.0.0.tar.gz", hash = "sha256:9368d65b3d4a471e9a698fed3ea486bbf6737e45111e915279c971b77f974397", size = 4364165 } +sdist = { url = "https://files.pythonhosted.org/packages/7d/ce/012a0f40ca58a966f87a6e894d6828e2817657cbdf522b02a5d3a87d92ce/ipython-9.0.2.tar.gz", hash = "sha256:ec7b479e3e5656bf4f58c652c120494df1820f4f28f522fb7ca09e213c2aab52", size = 4366102 } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/a1/894e4c0b6ac994045c6edeb2b6fdf69c59f20fcd2e348a42f4e40889181c/ipython-9.0.0-py3-none-any.whl", hash = "sha256:2cce23069b830a54a5b9d3d66ccd6433047c1503a7b9a3b34593c0b5c2c08477", size = 592040 }, + { url = "https://files.pythonhosted.org/packages/20/3a/917cb9e72f4e1a4ea13c862533205ae1319bd664119189ee5cc9e4e95ebf/ipython-9.0.2-py3-none-any.whl", hash = "sha256:143ef3ea6fb1e1bffb4c74b114051de653ffb7737a3f7ab1670e657ca6ae8c44", size = 600524 }, ] [[package]] @@ -1346,14 +1320,14 @@ wheels = [ [[package]] name = "jinja2" -version = "3.1.5" +version = "3.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/af/92/b3130cbbf5591acf9ade8708c365f3238046ac7cb8ccba6e81abccb0ccff/jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", size = 244674 } +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596 }, + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 }, ] [[package]] @@ -1617,23 +1591,20 @@ wheels = [ [[package]] name = "langchain" -version = "0.3.19" +version = "0.3.20" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aiohttp" }, { name = "langchain-core" }, { name = "langchain-text-splitters" }, { name = "langsmith" }, - { name = "numpy" }, { name = "pydantic" }, { name = "pyyaml" }, { name = "requests" }, { name = "sqlalchemy" }, - { name = "tenacity" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a2/cf/a064ef27d5f3154491c85783590a25d7ae22340cddedf9bf47496044e4eb/langchain-0.3.19.tar.gz", hash = "sha256:b96f8a445f01d15d522129ffe77cc89c8468dbd65830d153a676de8f6b899e7b", size = 10224228 } +sdist = { url = "https://files.pythonhosted.org/packages/2a/b0/5121cdd19cf99e684043f4eae528c893f56bd25e7711d4de89f27832a5f3/langchain-0.3.20.tar.gz", hash = "sha256:edcc3241703e1f6557ef5a5c35cd56f9ccc25ff12e38b4829c66d94971737a93", size = 10225276 } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/7d/0f4cc3317634195381f87c5d90268f29b9a31fda62aa7a7f36a1c27b06f3/langchain-0.3.19-py3-none-any.whl", hash = "sha256:1e16d97db9106640b7de4c69f8f5ed22eeda56b45b9241279e83f111640eff16", size = 1010630 }, + { url = "https://files.pythonhosted.org/packages/b5/d4/afe8174838bdd3baba5d6a19e9f3af4c54c5db1ab4d66ef0b650c6157919/langchain-0.3.20-py3-none-any.whl", hash = "sha256:273287f8e61ffdf7e811cf8799e6a71e9381325b8625fd6618900faba79cfdd0", size = 1011577 }, ] [package.optional-dependencies] @@ -1643,21 +1614,21 @@ openai = [ [[package]] name = "langchain-anthropic" -version = "0.3.8" +version = "0.3.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anthropic" }, { name = "langchain-core" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/2f/6ec88725da9cbb1c2b1295f6903faa2fa87fda07c87f8f0dfdec85f687dc/langchain_anthropic-0.3.8.tar.gz", hash = "sha256:1932977b8105744739ffdcb39861b041b73ae93846d0896a775fcea9a29e4b2b", size = 40585 } +sdist = { url = "https://files.pythonhosted.org/packages/be/0a/7ccb79c41575b04266fc4def50f41d0a4689361421d82a14350d9d5e783e/langchain_anthropic-0.3.9.tar.gz", hash = "sha256:e8012d7986ad1d8412df6914c56f3c0d2797f231766a03bb1ad22cc7023e6e1d", size = 42205 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/b1/9f3f1b94c8770b2745c6cb950ef0f3299c2178ed3f9d73d61ccf3215390c/langchain_anthropic-0.3.8-py3-none-any.whl", hash = "sha256:05a70f51500d3c4e0f3e463730e193a25b6244e06b3bda3d7b2ec21d83d081ae", size = 23266 }, + { url = "https://files.pythonhosted.org/packages/b9/27/258565b4a487fca7db363ea95765e6f1f00c23baa83dc4ec19a009213658/langchain_anthropic-0.3.9-py3-none-any.whl", hash = "sha256:adbbfaf3ce9798d46fb43d6fc01105630238f375dc6043d35d0aafab61fdbb71", size = 24414 }, ] [[package]] name = "langchain-core" -version = "0.3.40" +version = "0.3.43" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -1668,23 +1639,23 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4f/6b/7c3f5fa60639b885d8dbc932c37f0b0584ac5151ac6bdcd00b67b591e5e9/langchain_core-0.3.40.tar.gz", hash = "sha256:893a238b38491967c804662c1ec7c3e6ebaf223d1125331249c3cf3862ff2746", size = 528341 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/18/26255368f56d2749709fc2884c521d64471f32118ce09dfc677e0596be20/langchain_core-0.3.43.tar.gz", hash = "sha256:bec60f4f5665b536434ff747b8f23375a812e82cfa529f519b54cc1e7a94a875", size = 529403 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/01/b52e43f63261b5aae016cbe170bb5d8e8899770530075d11c1e45a07b97b/langchain_core-0.3.40-py3-none-any.whl", hash = "sha256:9f31358741f10a13db8531e8288b8a5ae91904018c5c2e6f739d6645a98fca03", size = 414346 }, + { url = "https://files.pythonhosted.org/packages/20/0e/ddf9f5dc46b178df5c101666bb3bc7fc526d68cd81cdd60cbe1b6b438b30/langchain_core-0.3.43-py3-none-any.whl", hash = "sha256:caa6bc1f4c6ab71d3c2e400f8b62e1cd6dc5ac2c37e03f12f3e2c60befd5b273", size = 415421 }, ] [[package]] name = "langchain-openai" -version = "0.3.7" +version = "0.3.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "openai" }, { name = "tiktoken" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/3c/08add067e46409d3e881933155f546edb08644e5e4e2360ff22c6a2104a8/langchain_openai-0.3.7.tar.gz", hash = "sha256:b8b51a3aaa1cc3bda060651ea41145f7728219e8a7150b5404fb1e8446de9cef", size = 256488 } +sdist = { url = "https://files.pythonhosted.org/packages/2e/04/ae071af0b04d1c3a8040498714091afd21149f6f8ae1dbab584317d9dfd7/langchain_openai-0.3.8.tar.gz", hash = "sha256:4d73727eda8102d1d07a2ca036278fccab0bb5e0abf353cec9c3973eb72550ec", size = 256898 } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/0e/816c5293eda67600d374bb8484a9adab873c9096489f6f91634581919f35/langchain_openai-0.3.7-py3-none-any.whl", hash = "sha256:0aefc7bdf8e7398d41e09c4313cace816df6438f2aa93d34f79523487310f0da", size = 55254 }, + { url = "https://files.pythonhosted.org/packages/a5/43/9c6a1101bcd751d52a3328a06956f85122f9aaa31da1b15a8e0f99a70317/langchain_openai-0.3.8-py3-none-any.whl", hash = "sha256:9004dc8ef853aece0d8f0feca7753dc97f710fa3e53874c8db66466520436dbb", size = 55446 }, ] [[package]] @@ -1699,9 +1670,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4c/f8/6b82af988e65af9697f6a2f25373fb173fd32d48b62772a8773c5184c870/langchain_text_splitters-0.3.6-py3-none-any.whl", hash = "sha256:e5d7b850f6c14259ea930be4a964a65fa95d9df7e1dbdd8bad8416db72292f4e", size = 31197 }, ] +[[package]] +name = "langchain-xai" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "langchain-core" }, + { name = "langchain-openai" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/94/a633bf1b4bbf66e4516f4188adc1174480c465ae12fb98f06c3e23c98519/langchain_xai-0.2.1.tar.gz", hash = "sha256:143a6f52be7617b5e5c68ab10c9b7df90914f54a6b3098566ce22b5d8fd89da5", size = 7788 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/88/d8050e610fadabf97c1745d24f0987b3e53b72fca63c8038ab1e0c103da9/langchain_xai-0.2.1-py3-none-any.whl", hash = "sha256:87228125cb15131663979d627210fca47dcd6b9a28462e8b5fee47f73bbed9f4", size = 6263 }, +] + [[package]] name = "langgraph" -version = "0.3.2" +version = "0.3.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, @@ -1709,53 +1695,53 @@ dependencies = [ { name = "langgraph-prebuilt" }, { name = "langgraph-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/21/83cc5f941da39ba31b8ff07e5e55b3112839f0bf332d52e6b405ad365ae5/langgraph-0.3.2.tar.gz", hash = "sha256:4712c11a9355e5d15126e15a166807a1d6275d72cf74fd2303609ffc2505e7a8", size = 113460 } +sdist = { url = "https://files.pythonhosted.org/packages/4e/fa/b1ecc95a2464bc7dbe5e67fbd21096013829119899c33236090b98c75508/langgraph-0.3.5.tar.gz", hash = "sha256:7c0d8e61aa02578b41036c9f7a599ccba2562d269f66ef76bacbba47a99a7eca", size = 114020 } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/1c/c50719e89442094bace035e632da7be161e5389974f2b805b75fef7aab8f/langgraph-0.3.2-py3-none-any.whl", hash = "sha256:1e17f85e225bf4fc5f0f70bce89d8bc5d1536b7993e39e2e47baa1b1a17a439c", size = 130875 }, + { url = "https://files.pythonhosted.org/packages/a4/5f/1e1d9173b5c41eff54f88d9f4ee82c38eb4928120ab6a21a68a78d1c499e/langgraph-0.3.5-py3-none-any.whl", hash = "sha256:be313ec300633c857873ea3e44aece4dd7d0b11f131d385108b359d377a85bf7", size = 131527 }, ] [[package]] name = "langgraph-checkpoint" -version = "2.0.16" +version = "2.0.18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "msgpack" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/01/66/5d4a2013a84c511be289bb4a5ef91cbaad28c091b6b366fdb79710a1458b/langgraph_checkpoint-2.0.16.tar.gz", hash = "sha256:49ba8cfa12b2aae845ccc3b1fbd1d7a8d3a6c4a2e387ab3a92fca40dd3d4baa5", size = 34206 } +sdist = { url = "https://files.pythonhosted.org/packages/76/1d/27a178de8a40c0cd53671f6a7e9aa21967a17672fdc774e5c0ae6cc406a4/langgraph_checkpoint-2.0.18.tar.gz", hash = "sha256:2822eedd028b454b7bfebfb7e04347aed1b64db97dedb7eb68ef0fb42641606d", size = 34947 } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/63/03bc3dd304ead45b53313cab8727329e1d139a2d220f2d030c72242c860e/langgraph_checkpoint-2.0.16-py3-none-any.whl", hash = "sha256:dfab51076a6eddb5f9e146cfe1b977e3dd6419168b2afa23ff3f4e47973bf06f", size = 38291 }, + { url = "https://files.pythonhosted.org/packages/21/11/91062b03b22b9ce6474df7c3e056417a4c2b029f9cc71829dd6f62479dd0/langgraph_checkpoint-2.0.18-py3-none-any.whl", hash = "sha256:941de442e5a893a6cabb8c3845f03159301b85f63ff4e8f2b308f7dfd96a3f59", size = 39106 }, ] [[package]] name = "langgraph-prebuilt" -version = "0.1.1" +version = "0.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/15/848593ccace12e4f8b80cc0b159b0ba1da17605e1eecbda5f37d891748a3/langgraph_prebuilt-0.1.1.tar.gz", hash = "sha256:420a748ff93842f2b1a345a0c1ca3939d2bc7a2d46c20e9a9a0d8f148152cc47", size = 23257 } +sdist = { url = "https://files.pythonhosted.org/packages/99/68/e1e692dbaeb4e9159b60a585fbfc26fbf073b3bb061caa2ff3153f85121a/langgraph_prebuilt-0.1.2.tar.gz", hash = "sha256:cfa7e54006d45e8f3d034ee88fa1d457c381bf6a2a0de0e64c5d3a776659e6d0", size = 23310 } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/62/a424fdb892f578fa88b2ff4df0bfdebdc8b89501dacb8ca3b480305cbfef/langgraph_prebuilt-0.1.1-py3-none-any.whl", hash = "sha256:148a9558a36ec7e83cc6512f3521425c862b0463251ae0242ade52a448c54e78", size = 24622 }, + { url = "https://files.pythonhosted.org/packages/73/2c/2fd70d557b7343f766f79dc8184b391f3417fc85b34dd04439cdd12dc2e1/langgraph_prebuilt-0.1.2-py3-none-any.whl", hash = "sha256:32028c4c4370576748e6c2e075cab1e13b5e3f2c196a390d71cacfb455212311", size = 24684 }, ] [[package]] name = "langgraph-sdk" -version = "0.1.53" +version = "0.1.55" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "orjson" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/b2/a261cfbf91a4499396ba0993cf5601076301dd22883d3c0901e905253917/langgraph_sdk-0.1.53.tar.gz", hash = "sha256:12906ed965905fa27e0c28d9fa07dc6fd89e6895ff321ff049fdf3965d057cc4", size = 42369 } +sdist = { url = "https://files.pythonhosted.org/packages/7a/6c/8286151a21124dc0189b57495541c2e3cace317056f60feb04076b438f82/langgraph_sdk-0.1.55.tar.gz", hash = "sha256:89a0240157a27822cc4edd1c9e72bc852e20f5c71165a4c9b91eeffa11fd6a6b", size = 42690 } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/97/3492a07b454cc74bf49938e83f0a95c608a8bc5c3dda338091d3c66e3ec5/langgraph_sdk-0.1.53-py3-none-any.whl", hash = "sha256:4fab62caad73661ffe4c3ababedcd0d7bfaaba986bee4416b9c28948458a3af5", size = 45441 }, + { url = "https://files.pythonhosted.org/packages/4e/64/4b75f4b57f0c8f39bdb43aa74b1d2edcdb604b5baa58465ccc54b8b906c5/langgraph_sdk-0.1.55-py3-none-any.whl", hash = "sha256:266e92a558eb738da1ef04c29fbfc2157cd3a977b80905d9509a2cb79331f8fc", size = 45785 }, ] [[package]] name = "langsmith" -version = "0.3.11" +version = "0.3.13" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -1766,9 +1752,9 @@ dependencies = [ { name = "requests-toolbelt" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/34/c4c0eddad03e00457cd6be1a88c288cd4419da8d368d8f519a29abe5392c/langsmith-0.3.11.tar.gz", hash = "sha256:ddf29d24352e99de79c9618aaf95679214324e146c5d3d9475a7ddd2870018b1", size = 323815 } +sdist = { url = "https://files.pythonhosted.org/packages/2a/18/14b2427d627bba44abc613dc78cbd395580310856774ce8c555bd58308dd/langsmith-0.3.13.tar.gz", hash = "sha256:14014058cff408772acb93344e03cb64174837292d5f1ae09b2c8c1d8df45e92", size = 326588 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/68/514ffa62860202a5a0a3acbf5c05017ef9df38d4437d2cb44a3cf93d617b/langsmith-0.3.11-py3-none-any.whl", hash = "sha256:0cca22737ef07d3b038a437c141deda37e00add56022582680188b681bec095e", size = 335265 }, + { url = "https://files.pythonhosted.org/packages/e0/09/3f909694aa0b104a611444959227832206864d92703e191a0f4b2a27d55b/langsmith-0.3.13-py3-none-any.whl", hash = "sha256:73aaf52bbc293b9415fff4f6dad68df40658081eb26c9cb2c7bd1ff57cedd695", size = 339683 }, ] [[package]] @@ -1830,15 +1816,14 @@ wheels = [ [[package]] name = "lox" -version = "0.12.0" +version = "0.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pathos" }, - { name = "sphinx-rtd-theme" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0f/b5/2bfa8da2a1dd6647c3ea0b8d7ae366bbb36b49f9f3858a253199daacb860/lox-0.12.0.tar.gz", hash = "sha256:cc7d5f867afb4dc7c2bce7bd6e90f4665c6df492863f35ff63229300b7219977", size = 37579 } +sdist = { url = "https://files.pythonhosted.org/packages/95/85/923891e93122afcd724241a2bca01331ac2b956cde021445f51cf223e642/lox-0.13.0.tar.gz", hash = "sha256:f27b17e01d8ae92eec5e6e782477e0fb78ab8ceccec0a64385e50f5b7211bb34", size = 37565 } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/9a/cc790ca4b853821b76acb5944d32036590a789e5f3b9e4f10a8962bcfda5/lox-0.12.0-py2.py3-none-any.whl", hash = "sha256:ac0a392662f3a75cc9097655d26169d5e3564e2670431fd9884a7a09a09f6921", size = 25372 }, + { url = "https://files.pythonhosted.org/packages/70/d5/eca08aa7cd286c2dacd0c39c1dd9828e537b000a1ca246af0bdafae56340/lox-0.13.0-py2.py3-none-any.whl", hash = "sha256:37e1a206b7ac932082e7bdc49c4c26f1b9be1a737010db5b6cff8c707714fe67", size = 25363 }, ] [[package]] @@ -1975,7 +1960,7 @@ wheels = [ [[package]] name = "modal" -version = "0.73.78" +version = "0.73.91" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -1993,9 +1978,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "watchfiles" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f6/68/90f2ef2ad678faa7bfd750f4c2bc16c363b11970825779df86fffe939a1d/modal-0.73.78.tar.gz", hash = "sha256:dcb3535549e47ba519ed927635a424e4b73e45afa942b002d5cbc8d3f78479f0", size = 469597 } +sdist = { url = "https://files.pythonhosted.org/packages/d0/b6/c44d67b8468f86e2cad6c6f61afdc4021c97adabcc826d465eb45bd1b139/modal-0.73.91.tar.gz", hash = "sha256:77d8c556f9be37298e042ea0ea1602f5de3261ef1e3c4135f63a6f758be9c06d", size = 469844 } wheels = [ - { url = "https://files.pythonhosted.org/packages/97/1f/08178134de7c7bcdb3b8777193ed008188c305edfa7f8e58a6f1bda4ce8b/modal-0.73.78-py3-none-any.whl", hash = "sha256:602edf2ec8877078d5a8d9a0956baf085d59f3431aa654b1302130e9fbde39f2", size = 535815 }, + { url = "https://files.pythonhosted.org/packages/1b/a9/8bf787c9dde7e0ae5d5c33ba9a75e5b67aadd90fd6046441c88024f651c7/modal-0.73.91-py3-none-any.whl", hash = "sha256:5d47a250dc8af992934359ffe9ee7c0cb1a1b7a732f47651750a982ed6b9a214", size = 536057 }, ] [[package]] @@ -2094,11 +2079,11 @@ wheels = [ [[package]] name = "narwhals" -version = "1.28.0" +version = "1.29.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/65/cc4f1d02d418e587fc5b9b31f3cbb8db83f4b35f91d7b59adfa8d947f644/narwhals-1.28.0.tar.gz", hash = "sha256:a2213fa44a039f724278fb15609889319e7c240403413f2606cc856c8d8f708d", size = 252143 } +sdist = { url = "https://files.pythonhosted.org/packages/a7/17/7d35094da0820ae941d8ce51842f253da36c6f95360ea0afabfc18bc02c6/narwhals-1.29.1.tar.gz", hash = "sha256:c408acf09e90c116f247cf34f24a3a89d147e3e235b1d3c708cfd1960baf320a", size = 251464 } wheels = [ - { url = "https://files.pythonhosted.org/packages/73/aa/eedf2ade0c16a60541ca7acd48665c62dc0d11e1e910467b6c7e6b1eda34/narwhals-1.28.0-py3-none-any.whl", hash = "sha256:45d909ad6240944d447b0dae38074c5a919830dff3868d57b05a5526c1f06fe4", size = 308950 }, + { url = "https://files.pythonhosted.org/packages/f1/22/380df533b08a57bc9013bb5714f33c571e1447828d83213a66adaefc0a04/narwhals-1.29.1-py3-none-any.whl", hash = "sha256:2f68cfbb2562672c4dfa54f158ed8c2828e9920ef784981cd9114e419c444216", size = 308220 }, ] [[package]] @@ -2247,7 +2232,7 @@ wheels = [ [[package]] name = "openai" -version = "1.65.2" +version = "1.65.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2259,9 +2244,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f6/03/0bbf201a7e44920d892db0445874c8111be4255cb9495379df18d6d36ea1/openai-1.65.2.tar.gz", hash = "sha256:729623efc3fd91c956f35dd387fa5c718edd528c4bed9f00b40ef290200fb2ce", size = 359185 } +sdist = { url = "https://files.pythonhosted.org/packages/56/cf/e02fb2c5a834803e6f29f43fd3dfe010303282d1ea450a5b95e28608860a/openai-1.65.5.tar.gz", hash = "sha256:17d39096bbcaf6c86580244b493a59e16613460147f0ba5ab6e608cdb6628149", size = 359548 } wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/3b/722ed868cb56f70264190ed479b38b3e46d14daa267d559a3fe3bd9061cf/openai-1.65.2-py3-none-any.whl", hash = "sha256:27d9fe8de876e31394c2553c4e6226378b6ed85e480f586ccfe25b7193fb1750", size = 473206 }, + { url = "https://files.pythonhosted.org/packages/fc/8f/a178d73277bf2d838617fa20ba4ae6952e26074664aacb53ae4532a69588/openai-1.65.5-py3-none-any.whl", hash = "sha256:5948a504e7b4003d921cfab81273813793a31c25b1d7b605797c01757e0141f1", size = 474468 }, ] [[package]] @@ -2952,11 +2937,11 @@ wheels = [ [[package]] name = "python-json-logger" -version = "3.2.1" +version = "3.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/c4/358cd13daa1d912ef795010897a483ab2f0b41c9ea1b35235a8b2f7d15a7/python_json_logger-3.2.1.tar.gz", hash = "sha256:8eb0554ea17cb75b05d2848bc14fb02fbdbd9d6972120781b974380bfa162008", size = 16287 } +sdist = { url = "https://files.pythonhosted.org/packages/9e/de/d3144a0bceede957f961e975f3752760fbe390d57fbe194baf709d8f1f7b/python_json_logger-3.3.0.tar.gz", hash = "sha256:12b7e74b17775e7d565129296105bbe3910842d9d0eb083fc83a6a617aa8df84", size = 16642 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/72/2f30cf26664fcfa0bd8ec5ee62ec90c03bd485e4a294d92aabc76c5203a5/python_json_logger-3.2.1-py3-none-any.whl", hash = "sha256:cdc17047eb5374bd311e748b42f99d71223f3b0e186f4206cc5d52aefe85b090", size = 14924 }, + { url = "https://files.pythonhosted.org/packages/08/20/0f2523b9e50a8052bc6a8b732dfc8568abbdc42010aef03a2d750bdab3b2/python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7", size = 15163 }, ] [[package]] @@ -3015,15 +3000,15 @@ wheels = [ [[package]] name = "pywin32" -version = "308" +version = "309" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/7c/d00d6bdd96de4344e06c4afbf218bc86b54436a94c01c71a8701f613aa56/pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897", size = 5939729 }, - { url = "https://files.pythonhosted.org/packages/21/27/0c8811fbc3ca188f93b5354e7c286eb91f80a53afa4e11007ef661afa746/pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47", size = 6543015 }, - { url = "https://files.pythonhosted.org/packages/9d/0f/d40f8373608caed2255781a3ad9a51d03a594a1248cd632d6a298daca693/pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091", size = 7976033 }, - { url = "https://files.pythonhosted.org/packages/a9/a4/aa562d8935e3df5e49c161b427a3a2efad2ed4e9cf81c3de636f1fdddfd0/pywin32-308-cp313-cp313-win32.whl", hash = "sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed", size = 5938579 }, - { url = "https://files.pythonhosted.org/packages/c7/50/b0efb8bb66210da67a53ab95fd7a98826a97ee21f1d22949863e6d588b22/pywin32-308-cp313-cp313-win_amd64.whl", hash = "sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4", size = 6542056 }, - { url = "https://files.pythonhosted.org/packages/26/df/2b63e3e4f2df0224f8aaf6d131f54fe4e8c96400eb9df563e2aae2e1a1f9/pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd", size = 7974986 }, + { url = "https://files.pythonhosted.org/packages/20/2c/b0240b14ff3dba7a8a7122dc9bbf7fbd21ed0e8b57c109633675b5d1761f/pywin32-309-cp312-cp312-win32.whl", hash = "sha256:de9acacced5fa82f557298b1fed5fef7bd49beee04190f68e1e4783fbdc19926", size = 8790648 }, + { url = "https://files.pythonhosted.org/packages/dd/11/c36884c732e2b3397deee808b5dac1abbb170ec37f94c6606fcb04d1e9d7/pywin32-309-cp312-cp312-win_amd64.whl", hash = "sha256:6ff9eebb77ffc3d59812c68db33c0a7817e1337e3537859499bd27586330fc9e", size = 9497399 }, + { url = "https://files.pythonhosted.org/packages/18/9f/79703972958f8ba3fd38bc9bf1165810bd75124982419b0cc433a2894d46/pywin32-309-cp312-cp312-win_arm64.whl", hash = "sha256:619f3e0a327b5418d833f44dc87859523635cf339f86071cc65a13c07be3110f", size = 8454122 }, + { url = "https://files.pythonhosted.org/packages/6c/c3/51aca6887cc5e410aa4cdc55662cf8438212440c67335c3f141b02eb8d52/pywin32-309-cp313-cp313-win32.whl", hash = "sha256:008bffd4afd6de8ca46c6486085414cc898263a21a63c7f860d54c9d02b45c8d", size = 8789700 }, + { url = "https://files.pythonhosted.org/packages/dd/66/330f265140fa814b4ed1bf16aea701f9d005f8f4ab57a54feb17f53afe7e/pywin32-309-cp313-cp313-win_amd64.whl", hash = "sha256:bd0724f58492db4cbfbeb1fcd606495205aa119370c0ddc4f70e5771a3ab768d", size = 9496714 }, + { url = "https://files.pythonhosted.org/packages/2c/84/9a51e6949a03f25cd329ece54dbf0846d57fadd2e79046c3b8d140aaa132/pywin32-309-cp313-cp313-win_arm64.whl", hash = "sha256:8fd9669cfd41863b688a1bc9b1d4d2d76fd4ba2128be50a70b0ea66b8d37953b", size = 8453052 }, ] [[package]] @@ -3273,16 +3258,16 @@ wheels = [ [[package]] name = "rich-click" -version = "1.8.6" +version = "1.8.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "rich" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/e3/ff1c715b673ec9e01f4482d8d0edfd9adf891f3630d83e695b38337a3889/rich_click-1.8.6.tar.gz", hash = "sha256:8a2448fd80e3d4e16fcb3815bfbc19be9bae75c9bb6aedf637901e45f3555752", size = 38247 } +sdist = { url = "https://files.pythonhosted.org/packages/a6/7a/4b78c5997f2a799a8c5c07f3b2145bbcda40115c4d35c76fbadd418a3c89/rich_click-1.8.8.tar.gz", hash = "sha256:547c618dea916620af05d4a6456da797fbde904c97901f44d2f32f89d85d6c84", size = 39066 } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/09/c20b04b6c9cf273995753f226ca51656e00f8a37f1e723f8c713b93b2ad4/rich_click-1.8.6-py3-none-any.whl", hash = "sha256:55fb571bad7d3d69ac43ca45f05b44616fd019616161b1815ff053567b9a8e22", size = 35076 }, + { url = "https://files.pythonhosted.org/packages/fa/69/963f0bf44a654f6465bdb66fb5a91051b0d7af9f742b5bd7202607165036/rich_click-1.8.8-py3-none-any.whl", hash = "sha256:205aabd5a98e64ab2c105dee9e368be27480ba004c7dfa2accd0ed44f9f1550e", size = 35747 }, ] [[package]] @@ -3299,15 +3284,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/1b/1c2f43af46456050b27810a7a013af8a7e12bc545a0cdc00eb0df55eb769/rich_toolkit-0.13.2-py3-none-any.whl", hash = "sha256:f3f6c583e5283298a2f7dbd3c65aca18b7f818ad96174113ab5bec0b0e35ed61", size = 13566 }, ] -[[package]] -name = "roman-numerals-py" -version = "3.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742 }, -] - [[package]] name = "rpds-py" version = "0.23.1" @@ -3400,11 +3376,11 @@ wheels = [ [[package]] name = "setuptools" -version = "75.8.2" +version = "76.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d1/53/43d99d7687e8cdef5ab5f9ec5eaf2c0423c2b35133a2b7e7bc276fc32b21/setuptools-75.8.2.tar.gz", hash = "sha256:4880473a969e5f23f2a2be3646b2dfd84af9028716d398e46192f84bc36900d2", size = 1344083 } +sdist = { url = "https://files.pythonhosted.org/packages/32/d2/7b171caf085ba0d40d8391f54e1c75a1cda9255f542becf84575cfd8a732/setuptools-76.0.0.tar.gz", hash = "sha256:43b4ee60e10b0d0ee98ad11918e114c70701bc6051662a9a675a0496c1a158f4", size = 1349387 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/38/7d7362e031bd6dc121e5081d8cb6aa6f6fedf2b67bf889962134c6da4705/setuptools-75.8.2-py3-none-any.whl", hash = "sha256:558e47c15f1811c1fa7adbd0096669bf76c1d3f433f58324df69f3f5ecac4e8f", size = 1229385 }, + { url = "https://files.pythonhosted.org/packages/37/66/d2d7e6ad554f3a7c7297c3f8ef6e22643ad3d35ef5c63bf488bc89f32f31/setuptools-76.0.0-py3-none-any.whl", hash = "sha256:199466a166ff664970d0ee145839f5582cb9bca7a0a3a2e795b6a9cb2308e9c6", size = 1236106 }, ] [[package]] @@ -3477,15 +3453,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, ] -[[package]] -name = "snowballstemmer" -version = "2.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002 }, -] - [[package]] name = "soupsieve" version = "2.6" @@ -3495,114 +3462,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 }, ] -[[package]] -name = "sphinx" -version = "8.2.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "alabaster" }, - { name = "babel" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "docutils" }, - { name = "imagesize" }, - { name = "jinja2" }, - { name = "packaging" }, - { name = "pygments" }, - { name = "requests" }, - { name = "roman-numerals-py" }, - { name = "snowballstemmer" }, - { name = "sphinxcontrib-applehelp" }, - { name = "sphinxcontrib-devhelp" }, - { name = "sphinxcontrib-htmlhelp" }, - { name = "sphinxcontrib-jsmath" }, - { name = "sphinxcontrib-qthelp" }, - { name = "sphinxcontrib-serializinghtml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741 }, -] - -[[package]] -name = "sphinx-rtd-theme" -version = "3.0.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "docutils" }, - { name = "sphinx" }, - { name = "sphinxcontrib-jquery" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/91/44/c97faec644d29a5ceddd3020ae2edffa69e7d00054a8c7a6021e82f20335/sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85", size = 7620463 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/85/77/46e3bac77b82b4df5bb5b61f2de98637724f246b4966cfc34bc5895d852a/sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13", size = 7655561 }, -] - -[[package]] -name = "sphinxcontrib-applehelp" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300 }, -] - -[[package]] -name = "sphinxcontrib-devhelp" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530 }, -] - -[[package]] -name = "sphinxcontrib-htmlhelp" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705 }, -] - -[[package]] -name = "sphinxcontrib-jquery" -version = "4.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/de/f3/aa67467e051df70a6330fe7770894b3e4f09436dea6881ae0b4f3d87cad8/sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", size = 122331 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/85/749bd22d1a68db7291c89e2ebca53f4306c3f205853cf31e9de279034c3c/sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae", size = 121104 }, -] - -[[package]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071 }, -] - -[[package]] -name = "sphinxcontrib-qthelp" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743 }, -] - -[[package]] -name = "sphinxcontrib-serializinghtml" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072 }, -] - [[package]] name = "sqlalchemy" version = "2.0.38" @@ -3661,14 +3520,14 @@ wheels = [ [[package]] name = "starlette" -version = "0.46.0" +version = "0.46.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/44/b6/fb9a32e3c5d59b1e383c357534c63c2d3caa6f25bf3c59dd89d296ecbaec/starlette-0.46.0.tar.gz", hash = "sha256:b359e4567456b28d473d0193f34c0de0ed49710d75ef183a74a5ce0499324f50", size = 2575568 } +sdist = { url = "https://files.pythonhosted.org/packages/04/1b/52b27f2e13ceedc79a908e29eac426a63465a1a01248e5f24aa36a62aeb3/starlette-0.46.1.tar.gz", hash = "sha256:3c88d58ee4bd1bb807c0d1acb381838afc7752f9ddaec81bbe4383611d833230", size = 2580102 } wheels = [ - { url = "https://files.pythonhosted.org/packages/41/94/8af675a62e3c91c2dee47cf92e602cfac86e8767b1a1ac3caf1b327c2ab0/starlette-0.46.0-py3-none-any.whl", hash = "sha256:913f0798bd90ba90a9156383bcf1350a17d6259451d0d8ee27fc0cf2db609038", size = 71991 }, + { url = "https://files.pythonhosted.org/packages/a0/4b/528ccf7a982216885a1ff4908e886b8fb5f19862d1962f56a3fce2435a70/starlette-0.46.1-py3-none-any.whl", hash = "sha256:77c74ed9d2720138b25875133f3a2dae6d854af2ec37dceb56aef370c1d8a227", size = 71995 }, ] [[package]] @@ -3898,11 +3757,11 @@ wheels = [ [[package]] name = "trove-classifiers" -version = "2025.2.18.16" +version = "2025.3.3.18" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/13/8e/15ba2980e2704edecc53d15506a5bfa6efb3b1cadc5e4df7dc277bc199f8/trove_classifiers-2025.2.18.16.tar.gz", hash = "sha256:b1ee2e1668589217d4edf506743e28b1834da128f8a122bad522c02d837006e1", size = 16271 } +sdist = { url = "https://files.pythonhosted.org/packages/08/e9/eb59303bac7aca949c4a4b0fa03a9b270be165d303a84cf2733d35a840ce/trove_classifiers-2025.3.3.18.tar.gz", hash = "sha256:3ffcfa90a428adfde1a5d90e3aa1b87fe474c5dbdbf5ccbca74ed69ba83c5ca7", size = 16239 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/67/038a8c7f60ffd6037374649826dbaa221e4b17755016b71a581162a15ce1/trove_classifiers-2025.2.18.16-py3-none-any.whl", hash = "sha256:7f6dfae899f23f04b73bc09e0754d9219a6fc4d6cca6acd62f1850a87ea92262", size = 13616 }, + { url = "https://files.pythonhosted.org/packages/ef/bf/44195f3d9c3c4fe4cccf1c261c80d50781b9e8a0a6febf084c09c66740ff/trove_classifiers-2025.3.3.18-py3-none-any.whl", hash = "sha256:215630da61cf8757c373f81b602fc1283ec5a691cf12c5f9f96f11d6ad5fc7f2", size = 13629 }, ] [[package]] @@ -3940,11 +3799,14 @@ wheels = [ [[package]] name = "types-setuptools" -version = "75.8.2.20250301" +version = "75.8.2.20250305" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/02/5f476d1a4f2bb23ba47c3aac6246cae1159d430937171e58860a9f1f47f8/types_setuptools-75.8.2.20250301.tar.gz", hash = "sha256:c900bceebfffc92a4abc3cfd4b3c39ead1a2298a73dae37e6bc09da7baf797a0", size = 48468 } +dependencies = [ + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/18/a996861f5225e7d533a8d8b6aa61bcc9183429a6b8bc93b850aa2e22974d/types_setuptools-75.8.2.20250305.tar.gz", hash = "sha256:a987269b49488f21961a1d99aa8d281b611625883def6392a93855b31544e405", size = 42609 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/d8/aba63d60951fbec2917a9d2c8673605a57fdbfc9134268802988c99c7a4c/types_setuptools-75.8.2.20250301-py3-none-any.whl", hash = "sha256:3cc3e751db9e84eddf1e6d4f8c46bef2c77e6c25b0cd096f729ffa57d3d6a83a", size = 71841 }, + { url = "https://files.pythonhosted.org/packages/d9/5b/bb33f99239a6d54ed1d8220a088d96d2ccacac7abb317df0d68d2500f3be/types_setuptools-75.8.2.20250305-py3-none-any.whl", hash = "sha256:ba80953fd1f5f49e552285c024f75b5223096a38a5138a54d18ddd3fa8f6a2d4", size = 63727 }, ] [[package]] @@ -4016,27 +3878,27 @@ wheels = [ [[package]] name = "uv" -version = "0.6.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4e/31/8f354a0b1df7ef4cb42da118dfae046d49f2c57ae427eb948a48a236c37d/uv-0.6.3.tar.gz", hash = "sha256:73587a192f2ebb8a25431d01037fe19f713fa99ff3b9fdf6e7a121131c6c5649", size = 3081857 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bb/c2/5a4138f1c615c7702943ce94155349943b5813e51faa38b6876a2ab86033/uv-0.6.3-py3-none-linux_armv6l.whl", hash = "sha256:facfec798eaddd07615b3a52973e38f2c8862ceb1bc685a5091891cd6c0c2a21", size = 15524019 }, - { url = "https://files.pythonhosted.org/packages/02/1d/abf01aa5e02b0a066f77b69a4f2f771c2ccd5424cd553e218afb026c65b9/uv-0.6.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b261895497f3c55a8a8917db0a1daeba1a9988ba487b068198d6cc4e8c13e769", size = 15537243 }, - { url = "https://files.pythonhosted.org/packages/ea/ac/4c1d5e04868051874dce74333fbe98e1f61e40a1522a9258a998775f2fab/uv-0.6.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:08e3f71a39c76c5b9ab63f9341b433a4ab8a1cc4e29d34ce81bd3b6f5bd642d8", size = 14450283 }, - { url = "https://files.pythonhosted.org/packages/00/8b/6cdb9a8cb4a5579d8b22d632e98d01f7c3695066ce1a2e33036edba2413a/uv-0.6.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:ebd4d1012c5043fe507f1f4477e7a54ec81e939e2a6e0229f23abb242f1622f5", size = 14909401 }, - { url = "https://files.pythonhosted.org/packages/51/8e/4d8c31250c7440a4c3704e81dab39f7f75db046e8b23f5322c3e47549557/uv-0.6.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f63b659a5ccbbd8c0ca5200c83ada6d19e73c0f1cafb8f4d9a7ef32544beb06d", size = 15245520 }, - { url = "https://files.pythonhosted.org/packages/4b/29/52976b3f7a79e4293763823e59d4de3b77506a1b9d298df0285be4879026/uv-0.6.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c23948f242a6bcbd274fa18387a608a52b21a3dfed18d324641964e305c348e9", size = 15890146 }, - { url = "https://files.pythonhosted.org/packages/54/38/a3c37aaf02b890d908edfec32e7a9b86e0df819df6443837929e40ac8d7e/uv-0.6.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0445ce49229001cec0a0b1240c6135e2252a3b8017ae878b0559411688a3e12a", size = 16817703 }, - { url = "https://files.pythonhosted.org/packages/df/0b/cd75c692266eb1cdea6764f9fb14d88babfa8d8433c414ac18623777760d/uv-0.6.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95ab9e9194046f4fb50daec6293e471fc18b6e1d350dba4f5328d0f19f6ec183", size = 16509829 }, - { url = "https://files.pythonhosted.org/packages/1c/5c/35747d595bf13f5b495a29ec9bb6212fd2fad7d8c32324a7faaeb6a643d0/uv-0.6.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af417925d7af00be949ebcab1bf187540bea235e9454aa2193ffae5b7ecc75cf", size = 20477063 }, - { url = "https://files.pythonhosted.org/packages/23/c7/4ea3d3f23d24240c54deee0248766c320163eef8b0117310f0be168fe0f0/uv-0.6.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed2d4e3c6e041bc8b55f931a58d758220e46e828b983967fbb318a117d879351", size = 16190208 }, - { url = "https://files.pythonhosted.org/packages/83/f2/96d4981c3490fabc5ba787703951124969f5b6dc8e3166543e7534de2dea/uv-0.6.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:a936275590f3091b05c03ad3ce69e2f8a4c964e80ae44ce0cf13cc3b412352f1", size = 15145146 }, - { url = "https://files.pythonhosted.org/packages/2b/62/1be7fb8b97fd057460b733bbdf30e71e771dcfbfab27b7db552fa4e219e6/uv-0.6.3-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:e842e96b941832cd95cb2fce90c5626b33e477773f425005e9237f8fd9ef5696", size = 15245907 }, - { url = "https://files.pythonhosted.org/packages/e0/1b/5849046e11f8154567b235fc8097ebb6a0d6416b3ce317300d9b06470481/uv-0.6.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:cd51af332fb0f6362cc44e4cca22c2d12c31dd52352c6259cae0e3570ce79da4", size = 15504955 }, - { url = "https://files.pythonhosted.org/packages/ec/46/d4fa9bd06f84bb83e452f3f201b058cd13969cb979402ff000c2e4c77a1e/uv-0.6.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:328677a74c7d998b654e4bfd50ba4347d0f3deed85284dbd041004a184353806", size = 16317436 }, - { url = "https://files.pythonhosted.org/packages/0b/d9/f93e4522cf1de51ff1a985ead75df85523cd1b689128b1b033c9e31204b8/uv-0.6.3-py3-none-win32.whl", hash = "sha256:dc2d965481bba716a0cf9d0f81896a70c341a854f0e4273f1887f22e52e5c9fb", size = 15545377 }, - { url = "https://files.pythonhosted.org/packages/91/ea/27dd790ec0d1f8c4ced06e27a409522bd157ed295a1140b3fb6cac3cd39a/uv-0.6.3-py3-none-win_amd64.whl", hash = "sha256:8fc19471fd4cfde1b31a47c239591d7c6dc0a31213f206d3953c528f9f3b406c", size = 16860609 }, - { url = "https://files.pythonhosted.org/packages/97/0f/01e48493264d75cfac6c953809e11c8356c77fb6be32dfce831bcf481ab2/uv-0.6.3-py3-none-win_arm64.whl", hash = "sha256:94a9d59c05f22829388e51a62a9cfddef4000a112e1c561bb5bd5761d4d672f1", size = 15697009 }, +version = "0.6.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/3b/9a699194b132948b377272f06f2218d6453d440c8bae77275cd7d21e64dc/uv-0.6.5.tar.gz", hash = "sha256:70ad4cc5f2b636edbeeebb3aee0a7daa66b17457038088be870ac7adc5a9842d", size = 3093602 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/40/ac0b8050e145ae7dab029e8590046f9f96af4c6a36a4c4ee328a81e56062/uv-0.6.5-py3-none-linux_armv6l.whl", hash = "sha256:c5676fc7cdd088e2c3342593c1d2dc379bf86a83301af7b0dfe8d45801a50d85", size = 15517362 }, + { url = "https://files.pythonhosted.org/packages/3c/f8/c0c2a2d5021904830d0d9fac4885819d731af2ed8e4ec11d80751420c646/uv-0.6.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6e82de1cb6a116f7736de9542430d78c210d152c80723db8beffc14e5b4e4b40", size = 15606625 }, + { url = "https://files.pythonhosted.org/packages/c6/f7/1c5a44233ba80938b316eb67b6f3087a5cdc032882fbb86abfb7b8d14f3a/uv-0.6.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:442639a874f6bb6864279f099c97739287d7e244bc25d0f791345cc69f46c940", size = 14483413 }, + { url = "https://files.pythonhosted.org/packages/c9/15/68beb9094e976c9403d8b79de76601f793250d0ecb84cb69d5940ba36729/uv-0.6.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:b5445a509f500bbf18faba4e7cf5cc9763617c335d58afaa5f3e5a6e388dd4ee", size = 14914536 }, + { url = "https://files.pythonhosted.org/packages/1c/49/42d917ec3a6d79751d54862ac8d5170b1f509680bcad506d949f5d365aaa/uv-0.6.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c5683bccfc2b92cdc2f91e2904baa8ee2b5893b33ac8acac25e702ce7d3e5415", size = 15264210 }, + { url = "https://files.pythonhosted.org/packages/ad/4c/446c039726dc6f04cd963f2a0813ec4e35c57d3566a9daf0272e2c5e311d/uv-0.6.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43847ef95d56c239de940339e5cfc2ade58249005e8ab97244fdb69fb9761572", size = 15974263 }, + { url = "https://files.pythonhosted.org/packages/8b/c6/46f5334c73846bb9afd883ca9a1f41262d677a3ee0e3ff0063acef5a8a05/uv-0.6.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ef0b2f810d87aa9bbad15c3ab113e555871f14c9cd8ad2205338fb0358aaf52d", size = 16842142 }, + { url = "https://files.pythonhosted.org/packages/a3/b4/b01cfa179b6e65aeb58eaf89bd3a6880082ec0fa391f93cc786db65ace03/uv-0.6.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b56fa88951fab3bc7164255d844de9ad048e6a04a95f1c2774637e06889efe6", size = 16539261 }, + { url = "https://files.pythonhosted.org/packages/cb/cc/1e00721e749ecc4d2cf8d233a9f9585108afcd62e3da4a2784f15d1f3a65/uv-0.6.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f3b3f21b2385545f499f6cc21f44eac3bbb0f6cb98fbf9c6d3e58db186c8a41", size = 20699878 }, + { url = "https://files.pythonhosted.org/packages/66/32/ad9944c9716360c82fb62516aca72bdeaedf7991483383f3a06734cb2cf4/uv-0.6.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15dae245979add192c4845947da1a9141f95c19403d1c0d75019182e6882e7d4", size = 16249288 }, + { url = "https://files.pythonhosted.org/packages/80/7a/cad1a0382182b923f881ec9b592106abb0df55be42384bfbe3694fb5b243/uv-0.6.5-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:26a90e69d6438de2ec03ab452cc48d1cb375249c6b6980f4ed177f324a5ad8b3", size = 15156024 }, + { url = "https://files.pythonhosted.org/packages/f5/f1/a9721cf48232ee4d0871c74dbc7ff5e2e90fb79aab4096c76f12eb3ba453/uv-0.6.5-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:776500595ff7cda1ffa5a76dd3ff9de3819f1e26c493938cbdc20c1ab766b2eb", size = 15213625 }, + { url = "https://files.pythonhosted.org/packages/cc/a4/02a2e4eb1a09b87086c92ebeb9953dca427b54ec113be2e0445abc850b3c/uv-0.6.5-py3-none-musllinux_1_1_i686.whl", hash = "sha256:6210fe6ef6a0ae3dc618611fcc8ada4e620fea5172fb8a9c50d3a59b6915b023", size = 15558969 }, + { url = "https://files.pythonhosted.org/packages/78/c1/5a3a0905a630a5b99b7b3cc1a400bcb65401e1a325bf43ced50e8bd007a2/uv-0.6.5-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:d47b4adffcdbe30bd678c7670e63c671b8b34a667898501e588f2e7cbce34656", size = 16345448 }, + { url = "https://files.pythonhosted.org/packages/36/80/721c0621f14071462bc8420b16c4cba3c9c066f5775eab7dc56d9b559c30/uv-0.6.5-py3-none-win32.whl", hash = "sha256:23aa8e8ca7795f54f6cf0f0fbd0aaf7b26bf4aae42f8c10643bcba6d42485a3f", size = 15657842 }, + { url = "https://files.pythonhosted.org/packages/09/d1/751610f12b99ab6166887554cd98d376f22ffb6fdc69e57676735e781ccc/uv-0.6.5-py3-none-win_amd64.whl", hash = "sha256:5323e9219a519c6553111820a8c54588d426380404a208b23cf4c3265bc87ec6", size = 16958031 }, + { url = "https://files.pythonhosted.org/packages/0d/63/0080e1618c936297001a3da462dd83f73391bacf7857ed7b327518d57f93/uv-0.6.5-py3-none-win_arm64.whl", hash = "sha256:a481254f63240023239ecec80cd690dec05875e248eb4b9d7f66957b017798b1", size = 15811982 }, ] [[package]] @@ -4085,16 +3947,16 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.29.2" +version = "20.29.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/88/dacc875dd54a8acadb4bcbfd4e3e86df8be75527116c91d8f9784f5e9cab/virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728", size = 4320272 } +sdist = { url = "https://files.pythonhosted.org/packages/c7/9c/57d19fa093bcf5ac61a48087dd44d00655f85421d1aa9722f8befbf3f40a/virtualenv-20.29.3.tar.gz", hash = "sha256:95e39403fcf3940ac45bc717597dba16110b74506131845d9b687d5e73d947ac", size = 4320280 } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/fa/849483d56773ae29740ae70043ad88e068f98a6401aa819b5d6bee604683/virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a", size = 4301478 }, + { url = "https://files.pythonhosted.org/packages/c2/eb/c6db6e3001d58c6a9e67c74bb7b4206767caa3ccc28c6b9eaf4c23fb4e34/virtualenv-20.29.3-py3-none-any.whl", hash = "sha256:3e3d00f5807e83b234dfb6122bf37cfadf4be216c53a49ac059d02414f819170", size = 4301458 }, ] [[package]] @@ -4171,33 +4033,33 @@ wheels = [ [[package]] name = "websockets" -version = "15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2e/7a/8bc4d15af7ff30f7ba34f9a172063bfcee9f5001d7cef04bee800a658f33/websockets-15.0.tar.gz", hash = "sha256:ca36151289a15b39d8d683fd8b7abbe26fc50be311066c5f8dcf3cb8cee107ab", size = 175574 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/1e/92c4547d7b2a93f848aedaf37e9054111bc00dc11bff4385ca3f80dbb412/websockets-15.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:cccc18077acd34c8072578394ec79563664b1c205f7a86a62e94fafc7b59001f", size = 174709 }, - { url = "https://files.pythonhosted.org/packages/9f/37/eae4830a28061ba552516d84478686b637cd9e57d6a90b45ad69e89cb0af/websockets-15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d4c22992e24f12de340ca5f824121a5b3e1a37ad4360b4e1aaf15e9d1c42582d", size = 172372 }, - { url = "https://files.pythonhosted.org/packages/46/2f/b409f8b8aa9328d5a47f7a301a43319d540d70cf036d1e6443675978a988/websockets-15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1206432cc6c644f6fc03374b264c5ff805d980311563202ed7fef91a38906276", size = 172607 }, - { url = "https://files.pythonhosted.org/packages/d6/81/d7e2e4542d4b4df849b0110df1b1f94f2647b71ab4b65d672090931ad2bb/websockets-15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d3cc75ef3e17490042c47e0523aee1bcc4eacd2482796107fd59dd1100a44bc", size = 182422 }, - { url = "https://files.pythonhosted.org/packages/b6/91/3b303160938d123eea97f58be363f7dbec76e8c59d587e07b5bc257dd584/websockets-15.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b89504227a5311610e4be16071465885a0a3d6b0e82e305ef46d9b064ce5fb72", size = 181362 }, - { url = "https://files.pythonhosted.org/packages/f2/8b/df6807f1ca339c567aba9a7ab03bfdb9a833f625e8d2b4fc7529e4c701de/websockets-15.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56e3efe356416bc67a8e093607315951d76910f03d2b3ad49c4ade9207bf710d", size = 181787 }, - { url = "https://files.pythonhosted.org/packages/21/37/e6d3d5ebb0ebcaf98ae84904205c9dcaf3e0fe93e65000b9f08631ed7309/websockets-15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0f2205cdb444a42a7919690238fb5979a05439b9dbb73dd47c863d39640d85ab", size = 182058 }, - { url = "https://files.pythonhosted.org/packages/c9/df/6aca296f2be4c638ad20908bb3d7c94ce7afc8d9b4b2b0780d1fc59b359c/websockets-15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aea01f40995fa0945c020228ab919b8dfc93fc8a9f2d3d705ab5b793f32d9e99", size = 181434 }, - { url = "https://files.pythonhosted.org/packages/88/f1/75717a982bab39bbe63c83f9df0e7753e5c98bab907eb4fb5d97fe5c8c11/websockets-15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9f8e33747b1332db11cf7fcf4a9512bef9748cb5eb4d3f7fbc8c30d75dc6ffc", size = 181431 }, - { url = "https://files.pythonhosted.org/packages/e7/15/cee9e63ed9ac5bfc1a3ae8fc6c02c41745023c21eed622eef142d8fdd749/websockets-15.0-cp312-cp312-win32.whl", hash = "sha256:32e02a2d83f4954aa8c17e03fe8ec6962432c39aca4be7e8ee346b05a3476904", size = 175678 }, - { url = "https://files.pythonhosted.org/packages/4e/00/993974c60f40faabb725d4dbae8b072ef73b4c4454bd261d3b1d34ace41f/websockets-15.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc02b159b65c05f2ed9ec176b715b66918a674bd4daed48a9a7a590dd4be1aa", size = 176119 }, - { url = "https://files.pythonhosted.org/packages/12/23/be28dc1023707ac51768f848d28a946443041a348ee3a54abdf9f6283372/websockets-15.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d2244d8ab24374bed366f9ff206e2619345f9cd7fe79aad5225f53faac28b6b1", size = 174714 }, - { url = "https://files.pythonhosted.org/packages/8f/ff/02b5e9fbb078e7666bf3d25c18c69b499747a12f3e7f2776063ef3fb7061/websockets-15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3a302241fbe825a3e4fe07666a2ab513edfdc6d43ce24b79691b45115273b5e7", size = 172374 }, - { url = "https://files.pythonhosted.org/packages/8e/61/901c8d4698e0477eff4c3c664d53f898b601fa83af4ce81946650ec2a4cb/websockets-15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:10552fed076757a70ba2c18edcbc601c7637b30cdfe8c24b65171e824c7d6081", size = 172605 }, - { url = "https://files.pythonhosted.org/packages/d2/4b/dc47601a80dff317aecf8da7b4ab278d11d3494b2c373b493e4887561f90/websockets-15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c53f97032b87a406044a1c33d1e9290cc38b117a8062e8a8b285175d7e2f99c9", size = 182380 }, - { url = "https://files.pythonhosted.org/packages/83/f7/b155d2b38f05ed47a0b8de1c9ea245fcd7fc625d89f35a37eccba34b42de/websockets-15.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1caf951110ca757b8ad9c4974f5cac7b8413004d2f29707e4d03a65d54cedf2b", size = 181325 }, - { url = "https://files.pythonhosted.org/packages/d3/ff/040a20c01c294695cac0e361caf86f33347acc38f164f6d2be1d3e007d9f/websockets-15.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bf1ab71f9f23b0a1d52ec1682a3907e0c208c12fef9c3e99d2b80166b17905f", size = 181763 }, - { url = "https://files.pythonhosted.org/packages/cb/6a/af23e93678fda8341ac8775e85123425e45c608389d3514863c702896ea5/websockets-15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bfcd3acc1a81f106abac6afd42327d2cf1e77ec905ae11dc1d9142a006a496b6", size = 182097 }, - { url = "https://files.pythonhosted.org/packages/7e/3e/1069e159c30129dc03c01513b5830237e576f47cedb888777dd885cae583/websockets-15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c8c5c8e1bac05ef3c23722e591ef4f688f528235e2480f157a9cfe0a19081375", size = 181485 }, - { url = "https://files.pythonhosted.org/packages/9a/a7/c91c47103f1cd941b576bbc452601e9e01f67d5c9be3e0a9abe726491ab5/websockets-15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:86bfb52a9cfbcc09aba2b71388b0a20ea5c52b6517c0b2e316222435a8cdab72", size = 181466 }, - { url = "https://files.pythonhosted.org/packages/16/32/a4ca6e3d56c24aac46b0cf5c03b841379f6409d07fc2044b244f90f54105/websockets-15.0-cp313-cp313-win32.whl", hash = "sha256:26ba70fed190708551c19a360f9d7eca8e8c0f615d19a574292b7229e0ae324c", size = 175673 }, - { url = "https://files.pythonhosted.org/packages/c0/31/25a417a23e985b61ffa5544f9facfe4a118cb64d664c886f1244a8baeca5/websockets-15.0-cp313-cp313-win_amd64.whl", hash = "sha256:ae721bcc8e69846af00b7a77a220614d9b2ec57d25017a6bbde3a99473e41ce8", size = 176115 }, - { url = "https://files.pythonhosted.org/packages/e8/b2/31eec524b53f01cd8343f10a8e429730c52c1849941d1f530f8253b6d934/websockets-15.0-py3-none-any.whl", hash = "sha256:51ffd53c53c4442415b613497a34ba0aa7b99ac07f1e4a62db5dcd640ae6c3c3", size = 169023 }, +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437 }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096 }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332 }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152 }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096 }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523 }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790 }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165 }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160 }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395 }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841 }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440 }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098 }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329 }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111 }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054 }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496 }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829 }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217 }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195 }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393 }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837 }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743 }, ] [[package]] diff --git a/uv.lock b/uv.lock index 27f9fed2e..8e0364f57 100644 --- a/uv.lock +++ b/uv.lock @@ -8,11 +8,11 @@ resolution-markers = [ [[package]] name = "aiohappyeyeballs" -version = "2.4.6" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/08/07/508f9ebba367fc3370162e53a3cfd12f5652ad79f0e0bfdf9f9847c6f159/aiohappyeyeballs-2.4.6.tar.gz", hash = "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0", size = 21726 } +sdist = { url = "https://files.pythonhosted.org/packages/a2/0c/458958007041f4b4de2d307e6b75d9e7554dad0baf26fe7a48b741aac126/aiohappyeyeballs-2.5.0.tar.gz", hash = "sha256:18fde6204a76deeabc97c48bdd01d5801cfda5d6b9c8bbeb1aaaee9d648ca191", size = 22494 } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/4c/03fb05f56551828ec67ceb3665e5dc51638042d204983a03b0a1541475b6/aiohappyeyeballs-2.4.6-py3-none-any.whl", hash = "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1", size = 14543 }, + { url = "https://files.pythonhosted.org/packages/1b/9a/e4886864ce06e1579bd428208127fbdc0d62049c751e4e9e3b509c0059dc/aiohappyeyeballs-2.5.0-py3-none-any.whl", hash = "sha256:0850b580748c7071db98bffff6d4c94028d0d3035acc20fd721a0ce7e8cac35d", size = 15128 }, ] [[package]] @@ -76,15 +76,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", size = 7597 }, ] -[[package]] -name = "alabaster" -version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929 }, -] - [[package]] name = "annotated-types" version = "0.7.0" @@ -137,11 +128,11 @@ wheels = [ [[package]] name = "argcomplete" -version = "3.5.3" +version = "3.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0c/be/6c23d80cb966fb8f83fb1ebfb988351ae6b0554d0c3a613ee4531c026597/argcomplete-3.5.3.tar.gz", hash = "sha256:c12bf50eded8aebb298c7b7da7a5ff3ee24dffd9f5281867dfe1424b58c55392", size = 72999 } +sdist = { url = "https://files.pythonhosted.org/packages/ee/be/29abccb5d9f61a92886a2fba2ac22bf74326b5c4f55d36d0a56094630589/argcomplete-3.6.0.tar.gz", hash = "sha256:2e4e42ec0ba2fff54b0d244d0b1623e86057673e57bafe72dda59c64bd5dee8b", size = 73135 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c4/08/2a4db06ec3d203124c967fc89295e85a202e5cbbcdc08fd6a64b65217d1e/argcomplete-3.5.3-py3-none-any.whl", hash = "sha256:2ab2c4a215c59fd6caaff41a869480a23e8f6a5f910b266c1808037f4e375b61", size = 43569 }, + { url = "https://files.pythonhosted.org/packages/08/94/e786d91ccc3a1fc664c20332825b73da20928eb067cdc984b821948a1acc/argcomplete-3.6.0-py3-none-any.whl", hash = "sha256:4e3e4e10beb20e06444dbac0ac8dda650cb6349caeefe980208d3c548708bedd", size = 43769 }, ] [[package]] @@ -354,7 +345,7 @@ wheels = [ [[package]] name = "braintrust" -version = "0.0.185" +version = "0.0.187" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "braintrust-core" }, @@ -368,9 +359,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3d/22/1d0cd915b5455f3cfcf6167ece3c98850c297d507979bdc46d0b62e84dbb/braintrust-0.0.185.tar.gz", hash = "sha256:20712119928bb555cdf0ff8a8158a18b53d9b93909fdaefb3321252dcb97200c", size = 102666 } +sdist = { url = "https://files.pythonhosted.org/packages/3a/2c/04494d3ffaf4f21518d026c7d033a5d0330459643539eee44fda21e8f5de/braintrust-0.0.187.tar.gz", hash = "sha256:8189eee23ba709db249260ad8fe75eecd5e8e9792ada77be3d2f55719ea00f68", size = 102881 } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/d7/8ca9e03e4d76766b8985b02d8bf886727f845df072187d942e9d2d0e745b/braintrust-0.0.185-py3-none-any.whl", hash = "sha256:ec83f2e5ff87a56a9268c176ab83470ba0a1944ccf96081163c38631907f5d4d", size = 119452 }, + { url = "https://files.pythonhosted.org/packages/50/d6/bc4288ebaea1f96183210c608d3bdd072cfa60cd54dfe573da7b6d8533d9/braintrust-0.0.187-py3-none-any.whl", hash = "sha256:0b628f27497ca30ea34e30606d834a7a9ff8a10203049b7e59cacdd5b8ec0ebc", size = 119629 }, ] [[package]] @@ -993,19 +984,19 @@ wheels = [ [[package]] name = "debugpy" -version = "1.8.12" +version = "1.8.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/68/25/c74e337134edf55c4dfc9af579eccb45af2393c40960e2795a94351e8140/debugpy-1.8.12.tar.gz", hash = "sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce", size = 1641122 } +sdist = { url = "https://files.pythonhosted.org/packages/51/d4/f35f539e11c9344652f362c22413ec5078f677ac71229dc9b4f6f85ccaa3/debugpy-1.8.13.tar.gz", hash = "sha256:837e7bef95bdefba426ae38b9a94821ebdc5bea55627879cd48165c90b9e50ce", size = 1641193 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/e6/0f876ecfe5831ebe4762b19214364753c8bc2b357d28c5d739a1e88325c7/debugpy-1.8.12-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498", size = 2500846 }, - { url = "https://files.pythonhosted.org/packages/19/64/33f41653a701f3cd2cbff8b41ebaad59885b3428b5afd0d93d16012ecf17/debugpy-1.8.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06", size = 4222181 }, - { url = "https://files.pythonhosted.org/packages/32/a6/02646cfe50bfacc9b71321c47dc19a46e35f4e0aceea227b6d205e900e34/debugpy-1.8.12-cp312-cp312-win32.whl", hash = "sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d", size = 5227017 }, - { url = "https://files.pythonhosted.org/packages/da/a6/10056431b5c47103474312cf4a2ec1001f73e0b63b1216706d5fef2531eb/debugpy-1.8.12-cp312-cp312-win_amd64.whl", hash = "sha256:39dfbb6fa09f12fae32639e3286112fc35ae976114f1f3d37375f3130a820969", size = 5267555 }, - { url = "https://files.pythonhosted.org/packages/cf/4d/7c3896619a8791effd5d8c31f0834471fc8f8fb3047ec4f5fc69dd1393dd/debugpy-1.8.12-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:696d8ae4dff4cbd06bf6b10d671e088b66669f110c7c4e18a44c43cf75ce966f", size = 2485246 }, - { url = "https://files.pythonhosted.org/packages/99/46/bc6dcfd7eb8cc969a5716d858e32485eb40c72c6a8dc88d1e3a4d5e95813/debugpy-1.8.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:898fba72b81a654e74412a67c7e0a81e89723cfe2a3ea6fcd3feaa3395138ca9", size = 4218616 }, - { url = "https://files.pythonhosted.org/packages/03/dd/d7fcdf0381a9b8094da1f6a1c9f19fed493a4f8576a2682349b3a8b20ec7/debugpy-1.8.12-cp313-cp313-win32.whl", hash = "sha256:22a11c493c70413a01ed03f01c3c3a2fc4478fc6ee186e340487b2edcd6f4180", size = 5226540 }, - { url = "https://files.pythonhosted.org/packages/25/bd/ecb98f5b5fc7ea0bfbb3c355bc1dd57c198a28780beadd1e19915bf7b4d9/debugpy-1.8.12-cp313-cp313-win_amd64.whl", hash = "sha256:fdb3c6d342825ea10b90e43d7f20f01535a72b3a1997850c0c3cefa5c27a4a2c", size = 5267134 }, - { url = "https://files.pythonhosted.org/packages/38/c4/5120ad36405c3008f451f94b8f92ef1805b1e516f6ff870f331ccb3c4cc0/debugpy-1.8.12-py2.py3-none-any.whl", hash = "sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6", size = 5229490 }, + { url = "https://files.pythonhosted.org/packages/79/ad/dff929b6b5403feaab0af0e5bb460fd723f9c62538b718a9af819b8fff20/debugpy-1.8.13-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:2b8de94c5c78aa0d0ed79023eb27c7c56a64c68217d881bee2ffbcb13951d0c1", size = 2501004 }, + { url = "https://files.pythonhosted.org/packages/d6/4f/b7d42e6679f0bb525888c278b0c0d2b6dff26ed42795230bb46eaae4f9b3/debugpy-1.8.13-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887d54276cefbe7290a754424b077e41efa405a3e07122d8897de54709dbe522", size = 4222346 }, + { url = "https://files.pythonhosted.org/packages/ec/18/d9b3e88e85d41f68f77235112adc31012a784e45a3fcdbb039777d570a0f/debugpy-1.8.13-cp312-cp312-win32.whl", hash = "sha256:3872ce5453b17837ef47fb9f3edc25085ff998ce63543f45ba7af41e7f7d370f", size = 5226639 }, + { url = "https://files.pythonhosted.org/packages/c9/f7/0df18a4f530ed3cc06f0060f548efe9e3316102101e311739d906f5650be/debugpy-1.8.13-cp312-cp312-win_amd64.whl", hash = "sha256:63ca7670563c320503fea26ac688988d9d6b9c6a12abc8a8cf2e7dd8e5f6b6ea", size = 5268735 }, + { url = "https://files.pythonhosted.org/packages/b1/db/ae7cd645c1826aae557cebccbc448f0cc9a818d364efb88f8d80e7a03f41/debugpy-1.8.13-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:31abc9618be4edad0b3e3a85277bc9ab51a2d9f708ead0d99ffb5bb750e18503", size = 2485416 }, + { url = "https://files.pythonhosted.org/packages/ec/ed/db4b10ff3b5bb30fe41d9e86444a08bb6448e4d8265e7768450b8408dd36/debugpy-1.8.13-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0bd87557f97bced5513a74088af0b84982b6ccb2e254b9312e29e8a5c4270eb", size = 4218784 }, + { url = "https://files.pythonhosted.org/packages/82/82/ed81852a8d94086f51664d032d83c7f87cd2b087c6ea70dabec7c1ba813d/debugpy-1.8.13-cp313-cp313-win32.whl", hash = "sha256:5268ae7fdca75f526d04465931cb0bd24577477ff50e8bb03dab90983f4ebd02", size = 5226270 }, + { url = "https://files.pythonhosted.org/packages/15/63/aa92fb341a78ec40f1c414ec7a7885c2ee17032eee00d12cee0cdc502af4/debugpy-1.8.13-cp313-cp313-win_amd64.whl", hash = "sha256:79ce4ed40966c4c1631d0131606b055a5a2f8e430e3f7bf8fd3744b09943e8e8", size = 5268621 }, + { url = "https://files.pythonhosted.org/packages/37/4f/0b65410a08b6452bfd3f7ed6f3610f1a31fb127f46836e82d31797065dcb/debugpy-1.8.13-py2.py3-none-any.whl", hash = "sha256:d4ba115cdd0e3a70942bd562adba9ec8c651fe69ddde2298a1be296fc331906f", size = 5229306 }, ] [[package]] @@ -1140,15 +1131,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d5/7c/e9fcff7623954d86bdc17782036cbf715ecab1bec4847c008557affe1ca8/docstring_parser-0.16-py3-none-any.whl", hash = "sha256:bf0a1387354d3691d102edef7ec124f219ef639982d096e26e3b60aeffa90637", size = 36533 }, ] -[[package]] -name = "docutils" -version = "0.21.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408 }, -] - [[package]] name = "dotty-dict" version = "1.3.1" @@ -1544,7 +1526,7 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "0.29.1" +version = "0.29.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, @@ -1555,9 +1537,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/37/797d6476f13e5ef6af5fc48a5d641d32b39c37e166ccf40c3714c5854a85/huggingface_hub-0.29.1.tar.gz", hash = "sha256:9524eae42077b8ff4fc459ceb7a514eca1c1232b775276b009709fe2a084f250", size = 389776 } +sdist = { url = "https://files.pythonhosted.org/packages/58/b2/f8b3c9842a794e8203448725aefa02d7c9e0da42d5f22f4ed806057cc36e/huggingface_hub-0.29.2.tar.gz", hash = "sha256:590b29c0dcbd0ee4b7b023714dc1ad8563fe4a68a91463438b74e980d28afaf3", size = 389816 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/05/75b90de9093de0aadafc868bb2fa7c57651fd8f45384adf39bd77f63980d/huggingface_hub-0.29.1-py3-none-any.whl", hash = "sha256:352f69caf16566c7b6de84b54a822f6238e17ddd8ae3da4f8f2272aea5b198d5", size = 468049 }, + { url = "https://files.pythonhosted.org/packages/13/5f/088ff08dc41808fcd99d9972b9bcfa7e3a35e30e8b0a3155b57938f1611c/huggingface_hub-0.29.2-py3-none-any.whl", hash = "sha256:c56f20fca09ef19da84dcde2b76379ecdaddf390b083f59f166715584953307d", size = 468087 }, ] [[package]] @@ -1580,11 +1562,11 @@ wheels = [ [[package]] name = "identify" -version = "2.6.8" +version = "2.6.9" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/fa/5eb460539e6f5252a7c5a931b53426e49258cde17e3d50685031c300a8fd/identify-2.6.8.tar.gz", hash = "sha256:61491417ea2c0c5c670484fd8abbb34de34cdae1e5f39a73ee65e48e4bb663fc", size = 99249 } +sdist = { url = "https://files.pythonhosted.org/packages/9b/98/a71ab060daec766acc30fb47dfca219d03de34a70d616a79a38c6066c5bf/identify-2.6.9.tar.gz", hash = "sha256:d40dfe3142a1421d8518e3d3985ef5ac42890683e32306ad614a29490abeb6bf", size = 99249 } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/8c/4bfcab2d8286473b8d83ea742716f4b79290172e75f91142bc1534b05b9a/identify-2.6.8-py2.py3-none-any.whl", hash = "sha256:83657f0f766a3c8d0eaea16d4ef42494b39b34629a4b3192a9d020d349b3e255", size = 99109 }, + { url = "https://files.pythonhosted.org/packages/07/ce/0845144ed1f0e25db5e7a79c2354c1da4b5ce392b8966449d5db8dca18f1/identify-2.6.9-py2.py3-none-any.whl", hash = "sha256:c98b4322da415a8e5a70ff6e51fbc2d2932c015532d77e9f8537b4ba7813b150", size = 99101 }, ] [[package]] @@ -1596,15 +1578,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] -[[package]] -name = "imagesize" -version = "1.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769 }, -] - [[package]] name = "importlib-metadata" version = "8.6.1" @@ -1679,7 +1652,7 @@ wheels = [ [[package]] name = "ipython" -version = "9.0.1" +version = "9.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -1693,9 +1666,9 @@ dependencies = [ { name = "stack-data" }, { name = "traitlets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/33/1901c9a842b301d8674f367dee597e654e402548a903faf7280aae8fc2d4/ipython-9.0.1.tar.gz", hash = "sha256:377ea91c8226b48dc9021ac9846a64761abc7ddf74c5efe38e6eb06f6e052f3a", size = 4365847 } +sdist = { url = "https://files.pythonhosted.org/packages/7d/ce/012a0f40ca58a966f87a6e894d6828e2817657cbdf522b02a5d3a87d92ce/ipython-9.0.2.tar.gz", hash = "sha256:ec7b479e3e5656bf4f58c652c120494df1820f4f28f522fb7ca09e213c2aab52", size = 4366102 } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/39/fda74f8215ef94a812dd780073c61a826a88a01e51f627a3454f7ae6951d/ipython-9.0.1-py3-none-any.whl", hash = "sha256:3e878273824b52e0a2280ed84f8193aba8c4ba9a6f45a438348a3d5ef1a34bd0", size = 600186 }, + { url = "https://files.pythonhosted.org/packages/20/3a/917cb9e72f4e1a4ea13c862533205ae1319bd664119189ee5cc9e4e95ebf/ipython-9.0.2-py3-none-any.whl", hash = "sha256:143ef3ea6fb1e1bffb4c74b114051de653ffb7737a3f7ab1670e657ca6ae8c44", size = 600524 }, ] [[package]] @@ -1745,14 +1718,14 @@ wheels = [ [[package]] name = "jinja2" -version = "3.1.5" +version = "3.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/af/92/b3130cbbf5591acf9ade8708c365f3238046ac7cb8ccba6e81abccb0ccff/jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", size = 244674 } +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596 }, + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 }, ] [[package]] @@ -2029,23 +2002,20 @@ wheels = [ [[package]] name = "langchain" -version = "0.3.19" +version = "0.3.20" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aiohttp" }, { name = "langchain-core" }, { name = "langchain-text-splitters" }, { name = "langsmith" }, - { name = "numpy" }, { name = "pydantic" }, { name = "pyyaml" }, { name = "requests" }, { name = "sqlalchemy" }, - { name = "tenacity" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a2/cf/a064ef27d5f3154491c85783590a25d7ae22340cddedf9bf47496044e4eb/langchain-0.3.19.tar.gz", hash = "sha256:b96f8a445f01d15d522129ffe77cc89c8468dbd65830d153a676de8f6b899e7b", size = 10224228 } +sdist = { url = "https://files.pythonhosted.org/packages/2a/b0/5121cdd19cf99e684043f4eae528c893f56bd25e7711d4de89f27832a5f3/langchain-0.3.20.tar.gz", hash = "sha256:edcc3241703e1f6557ef5a5c35cd56f9ccc25ff12e38b4829c66d94971737a93", size = 10225276 } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/7d/0f4cc3317634195381f87c5d90268f29b9a31fda62aa7a7f36a1c27b06f3/langchain-0.3.19-py3-none-any.whl", hash = "sha256:1e16d97db9106640b7de4c69f8f5ed22eeda56b45b9241279e83f111640eff16", size = 1010630 }, + { url = "https://files.pythonhosted.org/packages/b5/d4/afe8174838bdd3baba5d6a19e9f3af4c54c5db1ab4d66ef0b650c6157919/langchain-0.3.20-py3-none-any.whl", hash = "sha256:273287f8e61ffdf7e811cf8799e6a71e9381325b8625fd6618900faba79cfdd0", size = 1011577 }, ] [package.optional-dependencies] @@ -2055,21 +2025,21 @@ openai = [ [[package]] name = "langchain-anthropic" -version = "0.3.8" +version = "0.3.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anthropic" }, { name = "langchain-core" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/2f/6ec88725da9cbb1c2b1295f6903faa2fa87fda07c87f8f0dfdec85f687dc/langchain_anthropic-0.3.8.tar.gz", hash = "sha256:1932977b8105744739ffdcb39861b041b73ae93846d0896a775fcea9a29e4b2b", size = 40585 } +sdist = { url = "https://files.pythonhosted.org/packages/be/0a/7ccb79c41575b04266fc4def50f41d0a4689361421d82a14350d9d5e783e/langchain_anthropic-0.3.9.tar.gz", hash = "sha256:e8012d7986ad1d8412df6914c56f3c0d2797f231766a03bb1ad22cc7023e6e1d", size = 42205 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/b1/9f3f1b94c8770b2745c6cb950ef0f3299c2178ed3f9d73d61ccf3215390c/langchain_anthropic-0.3.8-py3-none-any.whl", hash = "sha256:05a70f51500d3c4e0f3e463730e193a25b6244e06b3bda3d7b2ec21d83d081ae", size = 23266 }, + { url = "https://files.pythonhosted.org/packages/b9/27/258565b4a487fca7db363ea95765e6f1f00c23baa83dc4ec19a009213658/langchain_anthropic-0.3.9-py3-none-any.whl", hash = "sha256:adbbfaf3ce9798d46fb43d6fc01105630238f375dc6043d35d0aafab61fdbb71", size = 24414 }, ] [[package]] name = "langchain-core" -version = "0.3.40" +version = "0.3.43" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -2080,23 +2050,23 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4f/6b/7c3f5fa60639b885d8dbc932c37f0b0584ac5151ac6bdcd00b67b591e5e9/langchain_core-0.3.40.tar.gz", hash = "sha256:893a238b38491967c804662c1ec7c3e6ebaf223d1125331249c3cf3862ff2746", size = 528341 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/18/26255368f56d2749709fc2884c521d64471f32118ce09dfc677e0596be20/langchain_core-0.3.43.tar.gz", hash = "sha256:bec60f4f5665b536434ff747b8f23375a812e82cfa529f519b54cc1e7a94a875", size = 529403 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/01/b52e43f63261b5aae016cbe170bb5d8e8899770530075d11c1e45a07b97b/langchain_core-0.3.40-py3-none-any.whl", hash = "sha256:9f31358741f10a13db8531e8288b8a5ae91904018c5c2e6f739d6645a98fca03", size = 414346 }, + { url = "https://files.pythonhosted.org/packages/20/0e/ddf9f5dc46b178df5c101666bb3bc7fc526d68cd81cdd60cbe1b6b438b30/langchain_core-0.3.43-py3-none-any.whl", hash = "sha256:caa6bc1f4c6ab71d3c2e400f8b62e1cd6dc5ac2c37e03f12f3e2c60befd5b273", size = 415421 }, ] [[package]] name = "langchain-openai" -version = "0.3.7" +version = "0.3.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "openai" }, { name = "tiktoken" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/3c/08add067e46409d3e881933155f546edb08644e5e4e2360ff22c6a2104a8/langchain_openai-0.3.7.tar.gz", hash = "sha256:b8b51a3aaa1cc3bda060651ea41145f7728219e8a7150b5404fb1e8446de9cef", size = 256488 } +sdist = { url = "https://files.pythonhosted.org/packages/2e/04/ae071af0b04d1c3a8040498714091afd21149f6f8ae1dbab584317d9dfd7/langchain_openai-0.3.8.tar.gz", hash = "sha256:4d73727eda8102d1d07a2ca036278fccab0bb5e0abf353cec9c3973eb72550ec", size = 256898 } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/0e/816c5293eda67600d374bb8484a9adab873c9096489f6f91634581919f35/langchain_openai-0.3.7-py3-none-any.whl", hash = "sha256:0aefc7bdf8e7398d41e09c4313cace816df6438f2aa93d34f79523487310f0da", size = 55254 }, + { url = "https://files.pythonhosted.org/packages/a5/43/9c6a1101bcd751d52a3328a06956f85122f9aaa31da1b15a8e0f99a70317/langchain_openai-0.3.8-py3-none-any.whl", hash = "sha256:9004dc8ef853aece0d8f0feca7753dc97f710fa3e53874c8db66466520436dbb", size = 55446 }, ] [[package]] @@ -2128,7 +2098,7 @@ wheels = [ [[package]] name = "langgraph" -version = "0.3.2" +version = "0.3.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, @@ -2136,53 +2106,53 @@ dependencies = [ { name = "langgraph-prebuilt" }, { name = "langgraph-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/21/83cc5f941da39ba31b8ff07e5e55b3112839f0bf332d52e6b405ad365ae5/langgraph-0.3.2.tar.gz", hash = "sha256:4712c11a9355e5d15126e15a166807a1d6275d72cf74fd2303609ffc2505e7a8", size = 113460 } +sdist = { url = "https://files.pythonhosted.org/packages/4e/fa/b1ecc95a2464bc7dbe5e67fbd21096013829119899c33236090b98c75508/langgraph-0.3.5.tar.gz", hash = "sha256:7c0d8e61aa02578b41036c9f7a599ccba2562d269f66ef76bacbba47a99a7eca", size = 114020 } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/1c/c50719e89442094bace035e632da7be161e5389974f2b805b75fef7aab8f/langgraph-0.3.2-py3-none-any.whl", hash = "sha256:1e17f85e225bf4fc5f0f70bce89d8bc5d1536b7993e39e2e47baa1b1a17a439c", size = 130875 }, + { url = "https://files.pythonhosted.org/packages/a4/5f/1e1d9173b5c41eff54f88d9f4ee82c38eb4928120ab6a21a68a78d1c499e/langgraph-0.3.5-py3-none-any.whl", hash = "sha256:be313ec300633c857873ea3e44aece4dd7d0b11f131d385108b359d377a85bf7", size = 131527 }, ] [[package]] name = "langgraph-checkpoint" -version = "2.0.16" +version = "2.0.18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "msgpack" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/01/66/5d4a2013a84c511be289bb4a5ef91cbaad28c091b6b366fdb79710a1458b/langgraph_checkpoint-2.0.16.tar.gz", hash = "sha256:49ba8cfa12b2aae845ccc3b1fbd1d7a8d3a6c4a2e387ab3a92fca40dd3d4baa5", size = 34206 } +sdist = { url = "https://files.pythonhosted.org/packages/76/1d/27a178de8a40c0cd53671f6a7e9aa21967a17672fdc774e5c0ae6cc406a4/langgraph_checkpoint-2.0.18.tar.gz", hash = "sha256:2822eedd028b454b7bfebfb7e04347aed1b64db97dedb7eb68ef0fb42641606d", size = 34947 } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/63/03bc3dd304ead45b53313cab8727329e1d139a2d220f2d030c72242c860e/langgraph_checkpoint-2.0.16-py3-none-any.whl", hash = "sha256:dfab51076a6eddb5f9e146cfe1b977e3dd6419168b2afa23ff3f4e47973bf06f", size = 38291 }, + { url = "https://files.pythonhosted.org/packages/21/11/91062b03b22b9ce6474df7c3e056417a4c2b029f9cc71829dd6f62479dd0/langgraph_checkpoint-2.0.18-py3-none-any.whl", hash = "sha256:941de442e5a893a6cabb8c3845f03159301b85f63ff4e8f2b308f7dfd96a3f59", size = 39106 }, ] [[package]] name = "langgraph-prebuilt" -version = "0.1.1" +version = "0.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/15/848593ccace12e4f8b80cc0b159b0ba1da17605e1eecbda5f37d891748a3/langgraph_prebuilt-0.1.1.tar.gz", hash = "sha256:420a748ff93842f2b1a345a0c1ca3939d2bc7a2d46c20e9a9a0d8f148152cc47", size = 23257 } +sdist = { url = "https://files.pythonhosted.org/packages/99/68/e1e692dbaeb4e9159b60a585fbfc26fbf073b3bb061caa2ff3153f85121a/langgraph_prebuilt-0.1.2.tar.gz", hash = "sha256:cfa7e54006d45e8f3d034ee88fa1d457c381bf6a2a0de0e64c5d3a776659e6d0", size = 23310 } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/62/a424fdb892f578fa88b2ff4df0bfdebdc8b89501dacb8ca3b480305cbfef/langgraph_prebuilt-0.1.1-py3-none-any.whl", hash = "sha256:148a9558a36ec7e83cc6512f3521425c862b0463251ae0242ade52a448c54e78", size = 24622 }, + { url = "https://files.pythonhosted.org/packages/73/2c/2fd70d557b7343f766f79dc8184b391f3417fc85b34dd04439cdd12dc2e1/langgraph_prebuilt-0.1.2-py3-none-any.whl", hash = "sha256:32028c4c4370576748e6c2e075cab1e13b5e3f2c196a390d71cacfb455212311", size = 24684 }, ] [[package]] name = "langgraph-sdk" -version = "0.1.53" +version = "0.1.55" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "orjson" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/b2/a261cfbf91a4499396ba0993cf5601076301dd22883d3c0901e905253917/langgraph_sdk-0.1.53.tar.gz", hash = "sha256:12906ed965905fa27e0c28d9fa07dc6fd89e6895ff321ff049fdf3965d057cc4", size = 42369 } +sdist = { url = "https://files.pythonhosted.org/packages/7a/6c/8286151a21124dc0189b57495541c2e3cace317056f60feb04076b438f82/langgraph_sdk-0.1.55.tar.gz", hash = "sha256:89a0240157a27822cc4edd1c9e72bc852e20f5c71165a4c9b91eeffa11fd6a6b", size = 42690 } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/97/3492a07b454cc74bf49938e83f0a95c608a8bc5c3dda338091d3c66e3ec5/langgraph_sdk-0.1.53-py3-none-any.whl", hash = "sha256:4fab62caad73661ffe4c3ababedcd0d7bfaaba986bee4416b9c28948458a3af5", size = 45441 }, + { url = "https://files.pythonhosted.org/packages/4e/64/4b75f4b57f0c8f39bdb43aa74b1d2edcdb604b5baa58465ccc54b8b906c5/langgraph_sdk-0.1.55-py3-none-any.whl", hash = "sha256:266e92a558eb738da1ef04c29fbfc2157cd3a977b80905d9509a2cb79331f8fc", size = 45785 }, ] [[package]] name = "langsmith" -version = "0.3.11" +version = "0.3.13" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -2193,9 +2163,9 @@ dependencies = [ { name = "requests-toolbelt" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/34/c4c0eddad03e00457cd6be1a88c288cd4419da8d368d8f519a29abe5392c/langsmith-0.3.11.tar.gz", hash = "sha256:ddf29d24352e99de79c9618aaf95679214324e146c5d3d9475a7ddd2870018b1", size = 323815 } +sdist = { url = "https://files.pythonhosted.org/packages/2a/18/14b2427d627bba44abc613dc78cbd395580310856774ce8c555bd58308dd/langsmith-0.3.13.tar.gz", hash = "sha256:14014058cff408772acb93344e03cb64174837292d5f1ae09b2c8c1d8df45e92", size = 326588 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/68/514ffa62860202a5a0a3acbf5c05017ef9df38d4437d2cb44a3cf93d617b/langsmith-0.3.11-py3-none-any.whl", hash = "sha256:0cca22737ef07d3b038a437c141deda37e00add56022582680188b681bec095e", size = 335265 }, + { url = "https://files.pythonhosted.org/packages/e0/09/3f909694aa0b104a611444959227832206864d92703e191a0f4b2a27d55b/langsmith-0.3.13-py3-none-any.whl", hash = "sha256:73aaf52bbc293b9415fff4f6dad68df40658081eb26c9cb2c7bd1ff57cedd695", size = 339683 }, ] [[package]] @@ -2270,15 +2240,14 @@ wheels = [ [[package]] name = "lox" -version = "0.12.0" +version = "0.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pathos" }, - { name = "sphinx-rtd-theme" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0f/b5/2bfa8da2a1dd6647c3ea0b8d7ae366bbb36b49f9f3858a253199daacb860/lox-0.12.0.tar.gz", hash = "sha256:cc7d5f867afb4dc7c2bce7bd6e90f4665c6df492863f35ff63229300b7219977", size = 37579 } +sdist = { url = "https://files.pythonhosted.org/packages/95/85/923891e93122afcd724241a2bca01331ac2b956cde021445f51cf223e642/lox-0.13.0.tar.gz", hash = "sha256:f27b17e01d8ae92eec5e6e782477e0fb78ab8ceccec0a64385e50f5b7211bb34", size = 37565 } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/9a/cc790ca4b853821b76acb5944d32036590a789e5f3b9e4f10a8962bcfda5/lox-0.12.0-py2.py3-none-any.whl", hash = "sha256:ac0a392662f3a75cc9097655d26169d5e3564e2670431fd9884a7a09a09f6921", size = 25372 }, + { url = "https://files.pythonhosted.org/packages/70/d5/eca08aa7cd286c2dacd0c39c1dd9828e537b000a1ca246af0bdafae56340/lox-0.13.0-py2.py3-none-any.whl", hash = "sha256:37e1a206b7ac932082e7bdc49c4c26f1b9be1a737010db5b6cff8c707714fe67", size = 25363 }, ] [[package]] @@ -2428,7 +2397,7 @@ wheels = [ [[package]] name = "modal" -version = "0.73.81" +version = "0.73.91" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -2446,9 +2415,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "watchfiles" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0c/d6/800423a59ea862f696804059e5fb49bbb8ca3884aecfc62b4af7cba8f1a8/modal-0.73.81.tar.gz", hash = "sha256:9404481b1dcd2b926597f87afb9e1729caac8f49b8dc58302ba8e6f138d1be56", size = 469407 } +sdist = { url = "https://files.pythonhosted.org/packages/d0/b6/c44d67b8468f86e2cad6c6f61afdc4021c97adabcc826d465eb45bd1b139/modal-0.73.91.tar.gz", hash = "sha256:77d8c556f9be37298e042ea0ea1602f5de3261ef1e3c4135f63a6f758be9c06d", size = 469844 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/a9/9dd0e5f58e0e7f37fee6761a4cdeb3352c2d32ee85a5022099e68f953224/modal-0.73.81-py3-none-any.whl", hash = "sha256:9c9ce548c1bde97aeba07904f6754910667a97250b5a44eb4dd9797bc387c969", size = 535608 }, + { url = "https://files.pythonhosted.org/packages/1b/a9/8bf787c9dde7e0ae5d5c33ba9a75e5b67aadd90fd6046441c88024f651c7/modal-0.73.91-py3-none-any.whl", hash = "sha256:5d47a250dc8af992934359ffe9ee7c0cb1a1b7a732f47651750a982ed6b9a214", size = 536057 }, ] [[package]] @@ -2580,11 +2549,11 @@ wheels = [ [[package]] name = "narwhals" -version = "1.29.0" +version = "1.29.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e6/f7/caa23ebc4aed3ef2314441c44e1d842e701adc6af57587ffda9263c03b6e/narwhals-1.29.0.tar.gz", hash = "sha256:1021c345d56c66ff0cc8e6d03ca8c543d01ffc411630973a5cb69ee86824d823", size = 248349 } +sdist = { url = "https://files.pythonhosted.org/packages/a7/17/7d35094da0820ae941d8ce51842f253da36c6f95360ea0afabfc18bc02c6/narwhals-1.29.1.tar.gz", hash = "sha256:c408acf09e90c116f247cf34f24a3a89d147e3e235b1d3c708cfd1960baf320a", size = 251464 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/f6/1fcd6b3d0e21d9b75e71ae68fbc92bbb9b9b1f4f33dd81c61d8f53378b30/narwhals-1.29.0-py3-none-any.whl", hash = "sha256:653aa8e5eb435816e7b50c8def17e7e5e3324c2ffd8a3eec03fef85792e9cf5e", size = 305214 }, + { url = "https://files.pythonhosted.org/packages/f1/22/380df533b08a57bc9013bb5714f33c571e1447828d83213a66adaefc0a04/narwhals-1.29.1-py3-none-any.whl", hash = "sha256:2f68cfbb2562672c4dfa54f158ed8c2828e9920ef784981cd9114e419c444216", size = 308220 }, ] [[package]] @@ -3582,11 +3551,11 @@ wheels = [ [[package]] name = "python-json-logger" -version = "3.2.1" +version = "3.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/c4/358cd13daa1d912ef795010897a483ab2f0b41c9ea1b35235a8b2f7d15a7/python_json_logger-3.2.1.tar.gz", hash = "sha256:8eb0554ea17cb75b05d2848bc14fb02fbdbd9d6972120781b974380bfa162008", size = 16287 } +sdist = { url = "https://files.pythonhosted.org/packages/9e/de/d3144a0bceede957f961e975f3752760fbe390d57fbe194baf709d8f1f7b/python_json_logger-3.3.0.tar.gz", hash = "sha256:12b7e74b17775e7d565129296105bbe3910842d9d0eb083fc83a6a617aa8df84", size = 16642 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/72/2f30cf26664fcfa0bd8ec5ee62ec90c03bd485e4a294d92aabc76c5203a5/python_json_logger-3.2.1-py3-none-any.whl", hash = "sha256:cdc17047eb5374bd311e748b42f99d71223f3b0e186f4206cc5d52aefe85b090", size = 14924 }, + { url = "https://files.pythonhosted.org/packages/08/20/0f2523b9e50a8052bc6a8b732dfc8568abbdc42010aef03a2d750bdab3b2/python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7", size = 15163 }, ] [[package]] @@ -3657,15 +3626,15 @@ wheels = [ [[package]] name = "pywin32" -version = "308" +version = "309" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/7c/d00d6bdd96de4344e06c4afbf218bc86b54436a94c01c71a8701f613aa56/pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897", size = 5939729 }, - { url = "https://files.pythonhosted.org/packages/21/27/0c8811fbc3ca188f93b5354e7c286eb91f80a53afa4e11007ef661afa746/pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47", size = 6543015 }, - { url = "https://files.pythonhosted.org/packages/9d/0f/d40f8373608caed2255781a3ad9a51d03a594a1248cd632d6a298daca693/pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091", size = 7976033 }, - { url = "https://files.pythonhosted.org/packages/a9/a4/aa562d8935e3df5e49c161b427a3a2efad2ed4e9cf81c3de636f1fdddfd0/pywin32-308-cp313-cp313-win32.whl", hash = "sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed", size = 5938579 }, - { url = "https://files.pythonhosted.org/packages/c7/50/b0efb8bb66210da67a53ab95fd7a98826a97ee21f1d22949863e6d588b22/pywin32-308-cp313-cp313-win_amd64.whl", hash = "sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4", size = 6542056 }, - { url = "https://files.pythonhosted.org/packages/26/df/2b63e3e4f2df0224f8aaf6d131f54fe4e8c96400eb9df563e2aae2e1a1f9/pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd", size = 7974986 }, + { url = "https://files.pythonhosted.org/packages/20/2c/b0240b14ff3dba7a8a7122dc9bbf7fbd21ed0e8b57c109633675b5d1761f/pywin32-309-cp312-cp312-win32.whl", hash = "sha256:de9acacced5fa82f557298b1fed5fef7bd49beee04190f68e1e4783fbdc19926", size = 8790648 }, + { url = "https://files.pythonhosted.org/packages/dd/11/c36884c732e2b3397deee808b5dac1abbb170ec37f94c6606fcb04d1e9d7/pywin32-309-cp312-cp312-win_amd64.whl", hash = "sha256:6ff9eebb77ffc3d59812c68db33c0a7817e1337e3537859499bd27586330fc9e", size = 9497399 }, + { url = "https://files.pythonhosted.org/packages/18/9f/79703972958f8ba3fd38bc9bf1165810bd75124982419b0cc433a2894d46/pywin32-309-cp312-cp312-win_arm64.whl", hash = "sha256:619f3e0a327b5418d833f44dc87859523635cf339f86071cc65a13c07be3110f", size = 8454122 }, + { url = "https://files.pythonhosted.org/packages/6c/c3/51aca6887cc5e410aa4cdc55662cf8438212440c67335c3f141b02eb8d52/pywin32-309-cp313-cp313-win32.whl", hash = "sha256:008bffd4afd6de8ca46c6486085414cc898263a21a63c7f860d54c9d02b45c8d", size = 8789700 }, + { url = "https://files.pythonhosted.org/packages/dd/66/330f265140fa814b4ed1bf16aea701f9d005f8f4ab57a54feb17f53afe7e/pywin32-309-cp313-cp313-win_amd64.whl", hash = "sha256:bd0724f58492db4cbfbeb1fcd606495205aa119370c0ddc4f70e5771a3ab768d", size = 9496714 }, + { url = "https://files.pythonhosted.org/packages/2c/84/9a51e6949a03f25cd329ece54dbf0846d57fadd2e79046c3b8d140aaa132/pywin32-309-cp313-cp313-win_arm64.whl", hash = "sha256:8fd9669cfd41863b688a1bc9b1d4d2d76fd4ba2128be50a70b0ea66b8d37953b", size = 8453052 }, ] [[package]] @@ -3915,16 +3884,16 @@ wheels = [ [[package]] name = "rich-click" -version = "1.8.6" +version = "1.8.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "rich" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/e3/ff1c715b673ec9e01f4482d8d0edfd9adf891f3630d83e695b38337a3889/rich_click-1.8.6.tar.gz", hash = "sha256:8a2448fd80e3d4e16fcb3815bfbc19be9bae75c9bb6aedf637901e45f3555752", size = 38247 } +sdist = { url = "https://files.pythonhosted.org/packages/a6/7a/4b78c5997f2a799a8c5c07f3b2145bbcda40115c4d35c76fbadd418a3c89/rich_click-1.8.8.tar.gz", hash = "sha256:547c618dea916620af05d4a6456da797fbde904c97901f44d2f32f89d85d6c84", size = 39066 } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/09/c20b04b6c9cf273995753f226ca51656e00f8a37f1e723f8c713b93b2ad4/rich_click-1.8.6-py3-none-any.whl", hash = "sha256:55fb571bad7d3d69ac43ca45f05b44616fd019616161b1815ff053567b9a8e22", size = 35076 }, + { url = "https://files.pythonhosted.org/packages/fa/69/963f0bf44a654f6465bdb66fb5a91051b0d7af9f742b5bd7202607165036/rich_click-1.8.8-py3-none-any.whl", hash = "sha256:205aabd5a98e64ab2c105dee9e368be27480ba004c7dfa2accd0ed44f9f1550e", size = 35747 }, ] [[package]] @@ -3941,15 +3910,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/1b/1c2f43af46456050b27810a7a013af8a7e12bc545a0cdc00eb0df55eb769/rich_toolkit-0.13.2-py3-none-any.whl", hash = "sha256:f3f6c583e5283298a2f7dbd3c65aca18b7f818ad96174113ab5bec0b0e35ed61", size = 13566 }, ] -[[package]] -name = "roman-numerals-py" -version = "3.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742 }, -] - [[package]] name = "rpds-py" version = "0.23.1" @@ -3999,27 +3959,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.9.9" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/c3/418441a8170e8d53d05c0b9dad69760dbc7b8a12c10dbe6db1e1205d2377/ruff-0.9.9.tar.gz", hash = "sha256:0062ed13f22173e85f8f7056f9a24016e692efeea8704d1a5e8011b8aa850933", size = 3717448 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/c3/2c4afa9ba467555d074b146d9aed0633a56ccdb900839fb008295d037b89/ruff-0.9.9-py3-none-linux_armv6l.whl", hash = "sha256:628abb5ea10345e53dff55b167595a159d3e174d6720bf19761f5e467e68d367", size = 10027252 }, - { url = "https://files.pythonhosted.org/packages/33/d1/439e58487cf9eac26378332e25e7d5ade4b800ce1eec7dc2cfc9b0d7ca96/ruff-0.9.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6cd1428e834b35d7493354723543b28cc11dc14d1ce19b685f6e68e07c05ec7", size = 10840721 }, - { url = "https://files.pythonhosted.org/packages/50/44/fead822c38281ba0122f1b76b460488a175a9bd48b130650a6fb6dbcbcf9/ruff-0.9.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5ee162652869120ad260670706f3cd36cd3f32b0c651f02b6da142652c54941d", size = 10161439 }, - { url = "https://files.pythonhosted.org/packages/11/ae/d404a2ab8e61ddf6342e09cc6b7f7846cce6b243e45c2007dbe0ca928a5d/ruff-0.9.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3aa0f6b75082c9be1ec5a1db78c6d4b02e2375c3068438241dc19c7c306cc61a", size = 10336264 }, - { url = "https://files.pythonhosted.org/packages/6a/4e/7c268aa7d84cd709fb6f046b8972313142cffb40dfff1d2515c5e6288d54/ruff-0.9.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:584cc66e89fb5f80f84b05133dd677a17cdd86901d6479712c96597a3f28e7fe", size = 9908774 }, - { url = "https://files.pythonhosted.org/packages/cc/26/c618a878367ef1b76270fd027ca93692657d3f6122b84ba48911ef5f2edc/ruff-0.9.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf3369325761a35aba75cd5c55ba1b5eb17d772f12ab168fbfac54be85cf18c", size = 11428127 }, - { url = "https://files.pythonhosted.org/packages/d7/9a/c5588a93d9bfed29f565baf193fe802fa676a0c837938137ea6cf0576d8c/ruff-0.9.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3403a53a32a90ce929aa2f758542aca9234befa133e29f4933dcef28a24317be", size = 12133187 }, - { url = "https://files.pythonhosted.org/packages/3e/ff/e7980a7704a60905ed7e156a8d73f604c846d9bd87deda9cabfa6cba073a/ruff-0.9.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18454e7fa4e4d72cffe28a37cf6a73cb2594f81ec9f4eca31a0aaa9ccdfb1590", size = 11602937 }, - { url = "https://files.pythonhosted.org/packages/24/78/3690444ad9e3cab5c11abe56554c35f005b51d1d118b429765249095269f/ruff-0.9.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fadfe2c88724c9617339f62319ed40dcdadadf2888d5afb88bf3adee7b35bfb", size = 13771698 }, - { url = "https://files.pythonhosted.org/packages/6e/bf/e477c2faf86abe3988e0b5fd22a7f3520e820b2ee335131aca2e16120038/ruff-0.9.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6df104d08c442a1aabcfd254279b8cc1e2cbf41a605aa3e26610ba1ec4acf0b0", size = 11249026 }, - { url = "https://files.pythonhosted.org/packages/f7/82/cdaffd59e5a8cb5b14c408c73d7a555a577cf6645faaf83e52fe99521715/ruff-0.9.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d7c62939daf5b2a15af48abbd23bea1efdd38c312d6e7c4cedf5a24e03207e17", size = 10220432 }, - { url = "https://files.pythonhosted.org/packages/fe/a4/2507d0026225efa5d4412b6e294dfe54725a78652a5c7e29e6bd0fc492f3/ruff-0.9.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9494ba82a37a4b81b6a798076e4a3251c13243fc37967e998efe4cce58c8a8d1", size = 9874602 }, - { url = "https://files.pythonhosted.org/packages/d5/be/f3aab1813846b476c4bcffe052d232244979c3cd99d751c17afb530ca8e4/ruff-0.9.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4efd7a96ed6d36ef011ae798bf794c5501a514be369296c672dab7921087fa57", size = 10851212 }, - { url = "https://files.pythonhosted.org/packages/8b/45/8e5fd559bea0d2f57c4e12bf197a2fade2fac465aa518284f157dfbca92b/ruff-0.9.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ab90a7944c5a1296f3ecb08d1cbf8c2da34c7e68114b1271a431a3ad30cb660e", size = 11327490 }, - { url = "https://files.pythonhosted.org/packages/42/55/e6c90f13880aeef327746052907e7e930681f26a164fe130ddac28b08269/ruff-0.9.9-py3-none-win32.whl", hash = "sha256:6b4c376d929c25ecd6d87e182a230fa4377b8e5125a4ff52d506ee8c087153c1", size = 10227912 }, - { url = "https://files.pythonhosted.org/packages/35/b2/da925693cb82a1208aa34966c0f36cb222baca94e729dd22a587bc22d0f3/ruff-0.9.9-py3-none-win_amd64.whl", hash = "sha256:837982ea24091d4c1700ddb2f63b7070e5baec508e43b01de013dc7eff974ff1", size = 11355632 }, - { url = "https://files.pythonhosted.org/packages/31/d8/de873d1c1b020d668d8ec9855d390764cb90cf8f6486c0983da52be8b7b7/ruff-0.9.9-py3-none-win_arm64.whl", hash = "sha256:3ac78f127517209fe6d96ab00f3ba97cafe38718b23b1db3e96d8b2d39e37ddf", size = 10435860 }, +version = "0.9.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/8e/fafaa6f15c332e73425d9c44ada85360501045d5ab0b81400076aff27cf6/ruff-0.9.10.tar.gz", hash = "sha256:9bacb735d7bada9cfb0f2c227d3658fc443d90a727b47f206fb33f52f3c0eac7", size = 3759776 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/b2/af7c2cc9e438cbc19fafeec4f20bfcd72165460fe75b2b6e9a0958c8c62b/ruff-0.9.10-py3-none-linux_armv6l.whl", hash = "sha256:eb4d25532cfd9fe461acc83498361ec2e2252795b4f40b17e80692814329e42d", size = 10049494 }, + { url = "https://files.pythonhosted.org/packages/6d/12/03f6dfa1b95ddd47e6969f0225d60d9d7437c91938a310835feb27927ca0/ruff-0.9.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:188a6638dab1aa9bb6228a7302387b2c9954e455fb25d6b4470cb0641d16759d", size = 10853584 }, + { url = "https://files.pythonhosted.org/packages/02/49/1c79e0906b6ff551fb0894168763f705bf980864739572b2815ecd3c9df0/ruff-0.9.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5284dcac6b9dbc2fcb71fdfc26a217b2ca4ede6ccd57476f52a587451ebe450d", size = 10155692 }, + { url = "https://files.pythonhosted.org/packages/5b/01/85e8082e41585e0e1ceb11e41c054e9e36fed45f4b210991052d8a75089f/ruff-0.9.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47678f39fa2a3da62724851107f438c8229a3470f533894b5568a39b40029c0c", size = 10369760 }, + { url = "https://files.pythonhosted.org/packages/a1/90/0bc60bd4e5db051f12445046d0c85cc2c617095c0904f1aa81067dc64aea/ruff-0.9.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99713a6e2766b7a17147b309e8c915b32b07a25c9efd12ada79f217c9c778b3e", size = 9912196 }, + { url = "https://files.pythonhosted.org/packages/66/ea/0b7e8c42b1ec608033c4d5a02939c82097ddcb0b3e393e4238584b7054ab/ruff-0.9.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524ee184d92f7c7304aa568e2db20f50c32d1d0caa235d8ddf10497566ea1a12", size = 11434985 }, + { url = "https://files.pythonhosted.org/packages/d5/86/3171d1eff893db4f91755175a6e1163c5887be1f1e2f4f6c0c59527c2bfd/ruff-0.9.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:df92aeac30af821f9acf819fc01b4afc3dfb829d2782884f8739fb52a8119a16", size = 12155842 }, + { url = "https://files.pythonhosted.org/packages/89/9e/700ca289f172a38eb0bca752056d0a42637fa17b81649b9331786cb791d7/ruff-0.9.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de42e4edc296f520bb84954eb992a07a0ec5a02fecb834498415908469854a52", size = 11613804 }, + { url = "https://files.pythonhosted.org/packages/f2/92/648020b3b5db180f41a931a68b1c8575cca3e63cec86fd26807422a0dbad/ruff-0.9.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d257f95b65806104b6b1ffca0ea53f4ef98454036df65b1eda3693534813ecd1", size = 13823776 }, + { url = "https://files.pythonhosted.org/packages/5e/a6/cc472161cd04d30a09d5c90698696b70c169eeba2c41030344194242db45/ruff-0.9.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60dec7201c0b10d6d11be00e8f2dbb6f40ef1828ee75ed739923799513db24c", size = 11302673 }, + { url = "https://files.pythonhosted.org/packages/6c/db/d31c361c4025b1b9102b4d032c70a69adb9ee6fde093f6c3bf29f831c85c/ruff-0.9.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d838b60007da7a39c046fcdd317293d10b845001f38bcb55ba766c3875b01e43", size = 10235358 }, + { url = "https://files.pythonhosted.org/packages/d1/86/d6374e24a14d4d93ebe120f45edd82ad7dcf3ef999ffc92b197d81cdc2a5/ruff-0.9.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ccaf903108b899beb8e09a63ffae5869057ab649c1e9231c05ae354ebc62066c", size = 9886177 }, + { url = "https://files.pythonhosted.org/packages/00/62/a61691f6eaaac1e945a1f3f59f1eea9a218513139d5b6c2b8f88b43b5b8f/ruff-0.9.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f9567d135265d46e59d62dc60c0bfad10e9a6822e231f5b24032dba5a55be6b5", size = 10864747 }, + { url = "https://files.pythonhosted.org/packages/ee/94/2c7065e1d92a8a8a46d46d9c3cf07b0aa7e0a1e0153d74baa5e6620b4102/ruff-0.9.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5f202f0d93738c28a89f8ed9eaba01b7be339e5d8d642c994347eaa81c6d75b8", size = 11360441 }, + { url = "https://files.pythonhosted.org/packages/a7/8f/1f545ea6f9fcd7bf4368551fb91d2064d8f0577b3079bb3f0ae5779fb773/ruff-0.9.10-py3-none-win32.whl", hash = "sha256:bfb834e87c916521ce46b1788fbb8484966e5113c02df216680102e9eb960029", size = 10247401 }, + { url = "https://files.pythonhosted.org/packages/4f/18/fb703603ab108e5c165f52f5b86ee2aa9be43bb781703ec87c66a5f5d604/ruff-0.9.10-py3-none-win_amd64.whl", hash = "sha256:f2160eeef3031bf4b17df74e307d4c5fb689a6f3a26a2de3f7ef4044e3c484f1", size = 11366360 }, + { url = "https://files.pythonhosted.org/packages/35/85/338e603dc68e7d9994d5d84f24adbf69bae760ba5efd3e20f5ff2cec18da/ruff-0.9.10-py3-none-win_arm64.whl", hash = "sha256:5fd804c0327a5e5ea26615550e706942f348b197d5475ff34c19733aee4b2e69", size = 10436892 }, ] [[package]] @@ -4083,11 +4043,11 @@ wheels = [ [[package]] name = "setuptools" -version = "75.8.2" +version = "76.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d1/53/43d99d7687e8cdef5ab5f9ec5eaf2c0423c2b35133a2b7e7bc276fc32b21/setuptools-75.8.2.tar.gz", hash = "sha256:4880473a969e5f23f2a2be3646b2dfd84af9028716d398e46192f84bc36900d2", size = 1344083 } +sdist = { url = "https://files.pythonhosted.org/packages/32/d2/7b171caf085ba0d40d8391f54e1c75a1cda9255f542becf84575cfd8a732/setuptools-76.0.0.tar.gz", hash = "sha256:43b4ee60e10b0d0ee98ad11918e114c70701bc6051662a9a675a0496c1a158f4", size = 1349387 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/38/7d7362e031bd6dc121e5081d8cb6aa6f6fedf2b67bf889962134c6da4705/setuptools-75.8.2-py3-none-any.whl", hash = "sha256:558e47c15f1811c1fa7adbd0096669bf76c1d3f433f58324df69f3f5ecac4e8f", size = 1229385 }, + { url = "https://files.pythonhosted.org/packages/37/66/d2d7e6ad554f3a7c7297c3f8ef6e22643ad3d35ef5c63bf488bc89f32f31/setuptools-76.0.0-py3-none-any.whl", hash = "sha256:199466a166ff664970d0ee145839f5582cb9bca7a0a3a2e795b6a9cb2308e9c6", size = 1236106 }, ] [[package]] @@ -4160,15 +4120,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, ] -[[package]] -name = "snowballstemmer" -version = "2.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002 }, -] - [[package]] name = "soupsieve" version = "2.6" @@ -4178,114 +4129,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 }, ] -[[package]] -name = "sphinx" -version = "8.2.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "alabaster" }, - { name = "babel" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "docutils" }, - { name = "imagesize" }, - { name = "jinja2" }, - { name = "packaging" }, - { name = "pygments" }, - { name = "requests" }, - { name = "roman-numerals-py" }, - { name = "snowballstemmer" }, - { name = "sphinxcontrib-applehelp" }, - { name = "sphinxcontrib-devhelp" }, - { name = "sphinxcontrib-htmlhelp" }, - { name = "sphinxcontrib-jsmath" }, - { name = "sphinxcontrib-qthelp" }, - { name = "sphinxcontrib-serializinghtml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741 }, -] - -[[package]] -name = "sphinx-rtd-theme" -version = "3.0.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "docutils" }, - { name = "sphinx" }, - { name = "sphinxcontrib-jquery" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/91/44/c97faec644d29a5ceddd3020ae2edffa69e7d00054a8c7a6021e82f20335/sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85", size = 7620463 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/85/77/46e3bac77b82b4df5bb5b61f2de98637724f246b4966cfc34bc5895d852a/sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13", size = 7655561 }, -] - -[[package]] -name = "sphinxcontrib-applehelp" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300 }, -] - -[[package]] -name = "sphinxcontrib-devhelp" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530 }, -] - -[[package]] -name = "sphinxcontrib-htmlhelp" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705 }, -] - -[[package]] -name = "sphinxcontrib-jquery" -version = "4.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/de/f3/aa67467e051df70a6330fe7770894b3e4f09436dea6881ae0b4f3d87cad8/sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", size = 122331 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/85/749bd22d1a68db7291c89e2ebca53f4306c3f205853cf31e9de279034c3c/sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae", size = 121104 }, -] - -[[package]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071 }, -] - -[[package]] -name = "sphinxcontrib-qthelp" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743 }, -] - -[[package]] -name = "sphinxcontrib-serializinghtml" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072 }, -] - [[package]] name = "sqlalchemy" version = "2.0.38" @@ -4353,14 +4196,14 @@ wheels = [ [[package]] name = "starlette" -version = "0.46.0" +version = "0.46.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/44/b6/fb9a32e3c5d59b1e383c357534c63c2d3caa6f25bf3c59dd89d296ecbaec/starlette-0.46.0.tar.gz", hash = "sha256:b359e4567456b28d473d0193f34c0de0ed49710d75ef183a74a5ce0499324f50", size = 2575568 } +sdist = { url = "https://files.pythonhosted.org/packages/04/1b/52b27f2e13ceedc79a908e29eac426a63465a1a01248e5f24aa36a62aeb3/starlette-0.46.1.tar.gz", hash = "sha256:3c88d58ee4bd1bb807c0d1acb381838afc7752f9ddaec81bbe4383611d833230", size = 2580102 } wheels = [ - { url = "https://files.pythonhosted.org/packages/41/94/8af675a62e3c91c2dee47cf92e602cfac86e8767b1a1ac3caf1b327c2ab0/starlette-0.46.0-py3-none-any.whl", hash = "sha256:913f0798bd90ba90a9156383bcf1350a17d6259451d0d8ee27fc0cf2db609038", size = 71991 }, + { url = "https://files.pythonhosted.org/packages/a0/4b/528ccf7a982216885a1ff4908e886b8fb5f19862d1962f56a3fce2435a70/starlette-0.46.1-py3-none-any.whl", hash = "sha256:77c74ed9d2720138b25875133f3a2dae6d854af2ec37dceb56aef370c1d8a227", size = 71995 }, ] [[package]] @@ -4635,14 +4478,14 @@ wheels = [ [[package]] name = "types-networkx" -version = "3.4.2.20250227" +version = "3.4.2.20250304" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d8/63/a6924a14d564bb7c7dd249007601b421a1d6f5e00e93cfd36eb8b6dce5fe/types_networkx-3.4.2.20250227.tar.gz", hash = "sha256:cf690e08ac91d40ab07983dd06928f2090b3b7f8ee99f53c865f77b605d8a690", size = 55016 } +sdist = { url = "https://files.pythonhosted.org/packages/ec/40/6dd15ecf27303c4c645e6e6f5ee60fc0d4b8edb4e859e72ac1e300eec471/types_networkx-3.4.2.20250304.tar.gz", hash = "sha256:249c74deeb6d64a360ce94fcbc6e4077d1bfd433b9186596f89b1146327cec1f", size = 55100 } wheels = [ - { url = "https://files.pythonhosted.org/packages/97/f0/f35c82ab5136d5e64c2c9662977bafda63189d092454704e85b2e3d6b112/types_networkx-3.4.2.20250227-py3-none-any.whl", hash = "sha256:9ef12b5e74efc3150772300a5b6cba2deff0d17895d46d227939dc490ec7527f", size = 137428 }, + { url = "https://files.pythonhosted.org/packages/d0/bf/c0b0edd702562de22994cd6643ae7c17250a2a666dc24f8b298ee3c1a43a/types_networkx-3.4.2.20250304-py3-none-any.whl", hash = "sha256:d578c3100d7cd066996c49da0274e8bd18a251cd0ae57cd2ca7bad0e9c41dc6a", size = 137452 }, ] [[package]] @@ -4656,23 +4499,26 @@ wheels = [ [[package]] name = "types-requests" -version = "2.32.0.20250301" +version = "2.32.0.20250306" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/87/88/365d6b46f1088ddeccbc89c26190c3180088ef6e7c8d162fc619496aab96/types_requests-2.32.0.20250301.tar.gz", hash = "sha256:3d909dc4eaab159c0d964ebe8bfa326a7afb4578d8706408d417e17d61b0c500", size = 22977 } +sdist = { url = "https://files.pythonhosted.org/packages/09/1a/beaeff79ef9efd186566ba5f0d95b44ae21f6d31e9413bcfbef3489b6ae3/types_requests-2.32.0.20250306.tar.gz", hash = "sha256:0962352694ec5b2f95fda877ee60a159abdf84a0fc6fdace599f20acb41a03d1", size = 23012 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/c2/e44564e8995dbc1738c2acacb8009d59c8cb19327da95a1b5c5d9cb68364/types_requests-2.32.0.20250301-py3-none-any.whl", hash = "sha256:0003e0124e2cbefefb88222ff822b48616af40c74df83350f599a650c8de483b", size = 20671 }, + { url = "https://files.pythonhosted.org/packages/99/26/645d89f56004aa0ba3b96fec27793e3c7e62b40982ee069e52568922b6db/types_requests-2.32.0.20250306-py3-none-any.whl", hash = "sha256:25f2cbb5c8710b2022f8bbee7b2b66f319ef14aeea2f35d80f18c9dbf3b60a0b", size = 20673 }, ] [[package]] name = "types-setuptools" -version = "75.8.2.20250301" +version = "75.8.2.20250305" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/02/5f476d1a4f2bb23ba47c3aac6246cae1159d430937171e58860a9f1f47f8/types_setuptools-75.8.2.20250301.tar.gz", hash = "sha256:c900bceebfffc92a4abc3cfd4b3c39ead1a2298a73dae37e6bc09da7baf797a0", size = 48468 } +dependencies = [ + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/18/a996861f5225e7d533a8d8b6aa61bcc9183429a6b8bc93b850aa2e22974d/types_setuptools-75.8.2.20250305.tar.gz", hash = "sha256:a987269b49488f21961a1d99aa8d281b611625883def6392a93855b31544e405", size = 42609 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/d8/aba63d60951fbec2917a9d2c8673605a57fdbfc9134268802988c99c7a4c/types_setuptools-75.8.2.20250301-py3-none-any.whl", hash = "sha256:3cc3e751db9e84eddf1e6d4f8c46bef2c77e6c25b0cd096f729ffa57d3d6a83a", size = 71841 }, + { url = "https://files.pythonhosted.org/packages/d9/5b/bb33f99239a6d54ed1d8220a088d96d2ccacac7abb317df0d68d2500f3be/types_setuptools-75.8.2.20250305-py3-none-any.whl", hash = "sha256:ba80953fd1f5f49e552285c024f75b5223096a38a5138a54d18ddd3fa8f6a2d4", size = 63727 }, ] [[package]] @@ -4753,27 +4599,27 @@ wheels = [ [[package]] name = "uv" -version = "0.6.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4e/31/8f354a0b1df7ef4cb42da118dfae046d49f2c57ae427eb948a48a236c37d/uv-0.6.3.tar.gz", hash = "sha256:73587a192f2ebb8a25431d01037fe19f713fa99ff3b9fdf6e7a121131c6c5649", size = 3081857 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bb/c2/5a4138f1c615c7702943ce94155349943b5813e51faa38b6876a2ab86033/uv-0.6.3-py3-none-linux_armv6l.whl", hash = "sha256:facfec798eaddd07615b3a52973e38f2c8862ceb1bc685a5091891cd6c0c2a21", size = 15524019 }, - { url = "https://files.pythonhosted.org/packages/02/1d/abf01aa5e02b0a066f77b69a4f2f771c2ccd5424cd553e218afb026c65b9/uv-0.6.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b261895497f3c55a8a8917db0a1daeba1a9988ba487b068198d6cc4e8c13e769", size = 15537243 }, - { url = "https://files.pythonhosted.org/packages/ea/ac/4c1d5e04868051874dce74333fbe98e1f61e40a1522a9258a998775f2fab/uv-0.6.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:08e3f71a39c76c5b9ab63f9341b433a4ab8a1cc4e29d34ce81bd3b6f5bd642d8", size = 14450283 }, - { url = "https://files.pythonhosted.org/packages/00/8b/6cdb9a8cb4a5579d8b22d632e98d01f7c3695066ce1a2e33036edba2413a/uv-0.6.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:ebd4d1012c5043fe507f1f4477e7a54ec81e939e2a6e0229f23abb242f1622f5", size = 14909401 }, - { url = "https://files.pythonhosted.org/packages/51/8e/4d8c31250c7440a4c3704e81dab39f7f75db046e8b23f5322c3e47549557/uv-0.6.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f63b659a5ccbbd8c0ca5200c83ada6d19e73c0f1cafb8f4d9a7ef32544beb06d", size = 15245520 }, - { url = "https://files.pythonhosted.org/packages/4b/29/52976b3f7a79e4293763823e59d4de3b77506a1b9d298df0285be4879026/uv-0.6.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c23948f242a6bcbd274fa18387a608a52b21a3dfed18d324641964e305c348e9", size = 15890146 }, - { url = "https://files.pythonhosted.org/packages/54/38/a3c37aaf02b890d908edfec32e7a9b86e0df819df6443837929e40ac8d7e/uv-0.6.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0445ce49229001cec0a0b1240c6135e2252a3b8017ae878b0559411688a3e12a", size = 16817703 }, - { url = "https://files.pythonhosted.org/packages/df/0b/cd75c692266eb1cdea6764f9fb14d88babfa8d8433c414ac18623777760d/uv-0.6.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95ab9e9194046f4fb50daec6293e471fc18b6e1d350dba4f5328d0f19f6ec183", size = 16509829 }, - { url = "https://files.pythonhosted.org/packages/1c/5c/35747d595bf13f5b495a29ec9bb6212fd2fad7d8c32324a7faaeb6a643d0/uv-0.6.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af417925d7af00be949ebcab1bf187540bea235e9454aa2193ffae5b7ecc75cf", size = 20477063 }, - { url = "https://files.pythonhosted.org/packages/23/c7/4ea3d3f23d24240c54deee0248766c320163eef8b0117310f0be168fe0f0/uv-0.6.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed2d4e3c6e041bc8b55f931a58d758220e46e828b983967fbb318a117d879351", size = 16190208 }, - { url = "https://files.pythonhosted.org/packages/83/f2/96d4981c3490fabc5ba787703951124969f5b6dc8e3166543e7534de2dea/uv-0.6.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:a936275590f3091b05c03ad3ce69e2f8a4c964e80ae44ce0cf13cc3b412352f1", size = 15145146 }, - { url = "https://files.pythonhosted.org/packages/2b/62/1be7fb8b97fd057460b733bbdf30e71e771dcfbfab27b7db552fa4e219e6/uv-0.6.3-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:e842e96b941832cd95cb2fce90c5626b33e477773f425005e9237f8fd9ef5696", size = 15245907 }, - { url = "https://files.pythonhosted.org/packages/e0/1b/5849046e11f8154567b235fc8097ebb6a0d6416b3ce317300d9b06470481/uv-0.6.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:cd51af332fb0f6362cc44e4cca22c2d12c31dd52352c6259cae0e3570ce79da4", size = 15504955 }, - { url = "https://files.pythonhosted.org/packages/ec/46/d4fa9bd06f84bb83e452f3f201b058cd13969cb979402ff000c2e4c77a1e/uv-0.6.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:328677a74c7d998b654e4bfd50ba4347d0f3deed85284dbd041004a184353806", size = 16317436 }, - { url = "https://files.pythonhosted.org/packages/0b/d9/f93e4522cf1de51ff1a985ead75df85523cd1b689128b1b033c9e31204b8/uv-0.6.3-py3-none-win32.whl", hash = "sha256:dc2d965481bba716a0cf9d0f81896a70c341a854f0e4273f1887f22e52e5c9fb", size = 15545377 }, - { url = "https://files.pythonhosted.org/packages/91/ea/27dd790ec0d1f8c4ced06e27a409522bd157ed295a1140b3fb6cac3cd39a/uv-0.6.3-py3-none-win_amd64.whl", hash = "sha256:8fc19471fd4cfde1b31a47c239591d7c6dc0a31213f206d3953c528f9f3b406c", size = 16860609 }, - { url = "https://files.pythonhosted.org/packages/97/0f/01e48493264d75cfac6c953809e11c8356c77fb6be32dfce831bcf481ab2/uv-0.6.3-py3-none-win_arm64.whl", hash = "sha256:94a9d59c05f22829388e51a62a9cfddef4000a112e1c561bb5bd5761d4d672f1", size = 15697009 }, +version = "0.6.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/3b/9a699194b132948b377272f06f2218d6453d440c8bae77275cd7d21e64dc/uv-0.6.5.tar.gz", hash = "sha256:70ad4cc5f2b636edbeeebb3aee0a7daa66b17457038088be870ac7adc5a9842d", size = 3093602 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/40/ac0b8050e145ae7dab029e8590046f9f96af4c6a36a4c4ee328a81e56062/uv-0.6.5-py3-none-linux_armv6l.whl", hash = "sha256:c5676fc7cdd088e2c3342593c1d2dc379bf86a83301af7b0dfe8d45801a50d85", size = 15517362 }, + { url = "https://files.pythonhosted.org/packages/3c/f8/c0c2a2d5021904830d0d9fac4885819d731af2ed8e4ec11d80751420c646/uv-0.6.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6e82de1cb6a116f7736de9542430d78c210d152c80723db8beffc14e5b4e4b40", size = 15606625 }, + { url = "https://files.pythonhosted.org/packages/c6/f7/1c5a44233ba80938b316eb67b6f3087a5cdc032882fbb86abfb7b8d14f3a/uv-0.6.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:442639a874f6bb6864279f099c97739287d7e244bc25d0f791345cc69f46c940", size = 14483413 }, + { url = "https://files.pythonhosted.org/packages/c9/15/68beb9094e976c9403d8b79de76601f793250d0ecb84cb69d5940ba36729/uv-0.6.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:b5445a509f500bbf18faba4e7cf5cc9763617c335d58afaa5f3e5a6e388dd4ee", size = 14914536 }, + { url = "https://files.pythonhosted.org/packages/1c/49/42d917ec3a6d79751d54862ac8d5170b1f509680bcad506d949f5d365aaa/uv-0.6.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c5683bccfc2b92cdc2f91e2904baa8ee2b5893b33ac8acac25e702ce7d3e5415", size = 15264210 }, + { url = "https://files.pythonhosted.org/packages/ad/4c/446c039726dc6f04cd963f2a0813ec4e35c57d3566a9daf0272e2c5e311d/uv-0.6.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43847ef95d56c239de940339e5cfc2ade58249005e8ab97244fdb69fb9761572", size = 15974263 }, + { url = "https://files.pythonhosted.org/packages/8b/c6/46f5334c73846bb9afd883ca9a1f41262d677a3ee0e3ff0063acef5a8a05/uv-0.6.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ef0b2f810d87aa9bbad15c3ab113e555871f14c9cd8ad2205338fb0358aaf52d", size = 16842142 }, + { url = "https://files.pythonhosted.org/packages/a3/b4/b01cfa179b6e65aeb58eaf89bd3a6880082ec0fa391f93cc786db65ace03/uv-0.6.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b56fa88951fab3bc7164255d844de9ad048e6a04a95f1c2774637e06889efe6", size = 16539261 }, + { url = "https://files.pythonhosted.org/packages/cb/cc/1e00721e749ecc4d2cf8d233a9f9585108afcd62e3da4a2784f15d1f3a65/uv-0.6.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f3b3f21b2385545f499f6cc21f44eac3bbb0f6cb98fbf9c6d3e58db186c8a41", size = 20699878 }, + { url = "https://files.pythonhosted.org/packages/66/32/ad9944c9716360c82fb62516aca72bdeaedf7991483383f3a06734cb2cf4/uv-0.6.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15dae245979add192c4845947da1a9141f95c19403d1c0d75019182e6882e7d4", size = 16249288 }, + { url = "https://files.pythonhosted.org/packages/80/7a/cad1a0382182b923f881ec9b592106abb0df55be42384bfbe3694fb5b243/uv-0.6.5-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:26a90e69d6438de2ec03ab452cc48d1cb375249c6b6980f4ed177f324a5ad8b3", size = 15156024 }, + { url = "https://files.pythonhosted.org/packages/f5/f1/a9721cf48232ee4d0871c74dbc7ff5e2e90fb79aab4096c76f12eb3ba453/uv-0.6.5-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:776500595ff7cda1ffa5a76dd3ff9de3819f1e26c493938cbdc20c1ab766b2eb", size = 15213625 }, + { url = "https://files.pythonhosted.org/packages/cc/a4/02a2e4eb1a09b87086c92ebeb9953dca427b54ec113be2e0445abc850b3c/uv-0.6.5-py3-none-musllinux_1_1_i686.whl", hash = "sha256:6210fe6ef6a0ae3dc618611fcc8ada4e620fea5172fb8a9c50d3a59b6915b023", size = 15558969 }, + { url = "https://files.pythonhosted.org/packages/78/c1/5a3a0905a630a5b99b7b3cc1a400bcb65401e1a325bf43ced50e8bd007a2/uv-0.6.5-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:d47b4adffcdbe30bd678c7670e63c671b8b34a667898501e588f2e7cbce34656", size = 16345448 }, + { url = "https://files.pythonhosted.org/packages/36/80/721c0621f14071462bc8420b16c4cba3c9c066f5775eab7dc56d9b559c30/uv-0.6.5-py3-none-win32.whl", hash = "sha256:23aa8e8ca7795f54f6cf0f0fbd0aaf7b26bf4aae42f8c10643bcba6d42485a3f", size = 15657842 }, + { url = "https://files.pythonhosted.org/packages/09/d1/751610f12b99ab6166887554cd98d376f22ffb6fdc69e57676735e781ccc/uv-0.6.5-py3-none-win_amd64.whl", hash = "sha256:5323e9219a519c6553111820a8c54588d426380404a208b23cf4c3265bc87ec6", size = 16958031 }, + { url = "https://files.pythonhosted.org/packages/0d/63/0080e1618c936297001a3da462dd83f73391bacf7857ed7b327518d57f93/uv-0.6.5-py3-none-win_arm64.whl", hash = "sha256:a481254f63240023239ecec80cd690dec05875e248eb4b9d7f66957b017798b1", size = 15811982 }, ] [[package]] @@ -4822,16 +4668,16 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.29.2" +version = "20.29.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/88/dacc875dd54a8acadb4bcbfd4e3e86df8be75527116c91d8f9784f5e9cab/virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728", size = 4320272 } +sdist = { url = "https://files.pythonhosted.org/packages/c7/9c/57d19fa093bcf5ac61a48087dd44d00655f85421d1aa9722f8befbf3f40a/virtualenv-20.29.3.tar.gz", hash = "sha256:95e39403fcf3940ac45bc717597dba16110b74506131845d9b687d5e73d947ac", size = 4320280 } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/fa/849483d56773ae29740ae70043ad88e068f98a6401aa819b5d6bee604683/virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a", size = 4301478 }, + { url = "https://files.pythonhosted.org/packages/c2/eb/c6db6e3001d58c6a9e67c74bb7b4206767caa3ccc28c6b9eaf4c23fb4e34/virtualenv-20.29.3-py3-none-any.whl", hash = "sha256:3e3d00f5807e83b234dfb6122bf37cfadf4be216c53a49ac059d02414f819170", size = 4301458 }, ] [[package]] @@ -4908,33 +4754,33 @@ wheels = [ [[package]] name = "websockets" -version = "15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2e/7a/8bc4d15af7ff30f7ba34f9a172063bfcee9f5001d7cef04bee800a658f33/websockets-15.0.tar.gz", hash = "sha256:ca36151289a15b39d8d683fd8b7abbe26fc50be311066c5f8dcf3cb8cee107ab", size = 175574 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/1e/92c4547d7b2a93f848aedaf37e9054111bc00dc11bff4385ca3f80dbb412/websockets-15.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:cccc18077acd34c8072578394ec79563664b1c205f7a86a62e94fafc7b59001f", size = 174709 }, - { url = "https://files.pythonhosted.org/packages/9f/37/eae4830a28061ba552516d84478686b637cd9e57d6a90b45ad69e89cb0af/websockets-15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d4c22992e24f12de340ca5f824121a5b3e1a37ad4360b4e1aaf15e9d1c42582d", size = 172372 }, - { url = "https://files.pythonhosted.org/packages/46/2f/b409f8b8aa9328d5a47f7a301a43319d540d70cf036d1e6443675978a988/websockets-15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1206432cc6c644f6fc03374b264c5ff805d980311563202ed7fef91a38906276", size = 172607 }, - { url = "https://files.pythonhosted.org/packages/d6/81/d7e2e4542d4b4df849b0110df1b1f94f2647b71ab4b65d672090931ad2bb/websockets-15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d3cc75ef3e17490042c47e0523aee1bcc4eacd2482796107fd59dd1100a44bc", size = 182422 }, - { url = "https://files.pythonhosted.org/packages/b6/91/3b303160938d123eea97f58be363f7dbec76e8c59d587e07b5bc257dd584/websockets-15.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b89504227a5311610e4be16071465885a0a3d6b0e82e305ef46d9b064ce5fb72", size = 181362 }, - { url = "https://files.pythonhosted.org/packages/f2/8b/df6807f1ca339c567aba9a7ab03bfdb9a833f625e8d2b4fc7529e4c701de/websockets-15.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56e3efe356416bc67a8e093607315951d76910f03d2b3ad49c4ade9207bf710d", size = 181787 }, - { url = "https://files.pythonhosted.org/packages/21/37/e6d3d5ebb0ebcaf98ae84904205c9dcaf3e0fe93e65000b9f08631ed7309/websockets-15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0f2205cdb444a42a7919690238fb5979a05439b9dbb73dd47c863d39640d85ab", size = 182058 }, - { url = "https://files.pythonhosted.org/packages/c9/df/6aca296f2be4c638ad20908bb3d7c94ce7afc8d9b4b2b0780d1fc59b359c/websockets-15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aea01f40995fa0945c020228ab919b8dfc93fc8a9f2d3d705ab5b793f32d9e99", size = 181434 }, - { url = "https://files.pythonhosted.org/packages/88/f1/75717a982bab39bbe63c83f9df0e7753e5c98bab907eb4fb5d97fe5c8c11/websockets-15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9f8e33747b1332db11cf7fcf4a9512bef9748cb5eb4d3f7fbc8c30d75dc6ffc", size = 181431 }, - { url = "https://files.pythonhosted.org/packages/e7/15/cee9e63ed9ac5bfc1a3ae8fc6c02c41745023c21eed622eef142d8fdd749/websockets-15.0-cp312-cp312-win32.whl", hash = "sha256:32e02a2d83f4954aa8c17e03fe8ec6962432c39aca4be7e8ee346b05a3476904", size = 175678 }, - { url = "https://files.pythonhosted.org/packages/4e/00/993974c60f40faabb725d4dbae8b072ef73b4c4454bd261d3b1d34ace41f/websockets-15.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc02b159b65c05f2ed9ec176b715b66918a674bd4daed48a9a7a590dd4be1aa", size = 176119 }, - { url = "https://files.pythonhosted.org/packages/12/23/be28dc1023707ac51768f848d28a946443041a348ee3a54abdf9f6283372/websockets-15.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d2244d8ab24374bed366f9ff206e2619345f9cd7fe79aad5225f53faac28b6b1", size = 174714 }, - { url = "https://files.pythonhosted.org/packages/8f/ff/02b5e9fbb078e7666bf3d25c18c69b499747a12f3e7f2776063ef3fb7061/websockets-15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3a302241fbe825a3e4fe07666a2ab513edfdc6d43ce24b79691b45115273b5e7", size = 172374 }, - { url = "https://files.pythonhosted.org/packages/8e/61/901c8d4698e0477eff4c3c664d53f898b601fa83af4ce81946650ec2a4cb/websockets-15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:10552fed076757a70ba2c18edcbc601c7637b30cdfe8c24b65171e824c7d6081", size = 172605 }, - { url = "https://files.pythonhosted.org/packages/d2/4b/dc47601a80dff317aecf8da7b4ab278d11d3494b2c373b493e4887561f90/websockets-15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c53f97032b87a406044a1c33d1e9290cc38b117a8062e8a8b285175d7e2f99c9", size = 182380 }, - { url = "https://files.pythonhosted.org/packages/83/f7/b155d2b38f05ed47a0b8de1c9ea245fcd7fc625d89f35a37eccba34b42de/websockets-15.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1caf951110ca757b8ad9c4974f5cac7b8413004d2f29707e4d03a65d54cedf2b", size = 181325 }, - { url = "https://files.pythonhosted.org/packages/d3/ff/040a20c01c294695cac0e361caf86f33347acc38f164f6d2be1d3e007d9f/websockets-15.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bf1ab71f9f23b0a1d52ec1682a3907e0c208c12fef9c3e99d2b80166b17905f", size = 181763 }, - { url = "https://files.pythonhosted.org/packages/cb/6a/af23e93678fda8341ac8775e85123425e45c608389d3514863c702896ea5/websockets-15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bfcd3acc1a81f106abac6afd42327d2cf1e77ec905ae11dc1d9142a006a496b6", size = 182097 }, - { url = "https://files.pythonhosted.org/packages/7e/3e/1069e159c30129dc03c01513b5830237e576f47cedb888777dd885cae583/websockets-15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c8c5c8e1bac05ef3c23722e591ef4f688f528235e2480f157a9cfe0a19081375", size = 181485 }, - { url = "https://files.pythonhosted.org/packages/9a/a7/c91c47103f1cd941b576bbc452601e9e01f67d5c9be3e0a9abe726491ab5/websockets-15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:86bfb52a9cfbcc09aba2b71388b0a20ea5c52b6517c0b2e316222435a8cdab72", size = 181466 }, - { url = "https://files.pythonhosted.org/packages/16/32/a4ca6e3d56c24aac46b0cf5c03b841379f6409d07fc2044b244f90f54105/websockets-15.0-cp313-cp313-win32.whl", hash = "sha256:26ba70fed190708551c19a360f9d7eca8e8c0f615d19a574292b7229e0ae324c", size = 175673 }, - { url = "https://files.pythonhosted.org/packages/c0/31/25a417a23e985b61ffa5544f9facfe4a118cb64d664c886f1244a8baeca5/websockets-15.0-cp313-cp313-win_amd64.whl", hash = "sha256:ae721bcc8e69846af00b7a77a220614d9b2ec57d25017a6bbde3a99473e41ce8", size = 176115 }, - { url = "https://files.pythonhosted.org/packages/e8/b2/31eec524b53f01cd8343f10a8e429730c52c1849941d1f530f8253b6d934/websockets-15.0-py3-none-any.whl", hash = "sha256:51ffd53c53c4442415b613497a34ba0aa7b99ac07f1e4a62db5dcd640ae6c3c3", size = 169023 }, +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437 }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096 }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332 }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152 }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096 }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523 }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790 }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165 }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160 }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395 }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841 }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440 }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098 }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329 }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111 }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054 }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496 }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829 }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217 }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195 }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393 }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837 }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743 }, ] [[package]] From 2f7d00257cc45380ebd805b5898b7c7eb9f141cf Mon Sep 17 00:00:00 2001 From: Christine Wang Date: Mon, 10 Mar 2025 09:11:20 -0700 Subject: [PATCH 59/66] fix: pull request context - body can be null (#787) --- src/codegen/git/models/pull_request_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/git/models/pull_request_context.py b/src/codegen/git/models/pull_request_context.py index 6729acf63..1f97afbd1 100644 --- a/src/codegen/git/models/pull_request_context.py +++ b/src/codegen/git/models/pull_request_context.py @@ -14,10 +14,10 @@ class PullRequestContext(BaseModel): state: str title: str user: GithubNamedUserContext - body: str draft: bool head: PRPartContext base: PRPartContext + body: str | None = None merged: bool | None = None merged_by: dict | None = None additions: int | None = None From 7de5af70de04c705c8bf45887d44a73bd2b8e4b8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 10 Mar 2025 16:14:40 +0000 Subject: [PATCH 60/66] update changelog --- docs/changelog/changelog.mdx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/changelog/changelog.mdx b/docs/changelog/changelog.mdx index 9cd4834aa..49e17df61 100644 --- a/docs/changelog/changelog.mdx +++ b/docs/changelog/changelog.mdx @@ -4,6 +4,11 @@ icon: "clock" iconType: "solid" --- + +### [Fixes null body issue in pull request context.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.6) +- Fix null body issue in pull request context + + ### [Adds dataset subsets and improves CLI arguments.](https://github.com/codegen-sh/codegen-sdk/releases/tag/v0.48.5) - Updated OpenAI dependency From 6629cd14369496d7be5a8237972751eff02f8ae0 Mon Sep 17 00:00:00 2001 From: Tawsif Kamal Date: Mon, 10 Mar 2025 11:48:27 -0700 Subject: [PATCH 61/66] CG-10967: Create Custom Langgraph Nodes + Retry Policy (#788) - No more `create_react_agent` from `langgraph.prebuilt` - In `graph.py` we now have our own nodes for langgraph - Retry policy with the following parameters `30s` for interval and back off factor `0.5`. so it will be 30s first wait, then `15s`, then `7.5s`, etc. --- .../examples/langchain_agent/run.py | 4 +- .../swebench_agent_run/local_run.ipynb | 52 ++------- pyproject.toml | 1 + src/codegen/agents/chat_agent.py | 95 ++++++++++++++++ src/codegen/agents/code_agent.py | 23 +++- src/codegen/extensions/langchain/agent.py | 17 +-- src/codegen/extensions/langchain/graph.py | 102 ++++++++++++++++++ src/codegen/extensions/langchain/llm.py | 4 +- src/codegen/extensions/langchain/tools.py | 39 ++++--- .../extensions/tools/replacement_edit.py | 17 ++- src/codegen/extensions/tools/search.py | 2 +- 11 files changed, 283 insertions(+), 73 deletions(-) create mode 100644 src/codegen/agents/chat_agent.py create mode 100644 src/codegen/extensions/langchain/graph.py diff --git a/codegen-examples/examples/langchain_agent/run.py b/codegen-examples/examples/langchain_agent/run.py index 0d4d4f837..5c6891889 100644 --- a/codegen-examples/examples/langchain_agent/run.py +++ b/codegen-examples/examples/langchain_agent/run.py @@ -20,7 +20,7 @@ from langgraph.checkpoint.memory import MemorySaver from langgraph.graph.graph import CompiledGraph -from langgraph.prebuilt import create_react_agent +from codegen.extensions.langchain.graph import create_react_agent from langchain_core.messages import SystemMessage @@ -70,7 +70,7 @@ def create_codebase_agent( memory = MemorySaver() if memory else None - return create_react_agent(model=llm, tools=tools, prompt=system_message, checkpointer=memory, debug=debug) + return create_react_agent(model=llm, tools=tools, system_message=system_message, checkpointer=memory, debug=debug) if __name__ == "__main__": diff --git a/codegen-examples/examples/swebench_agent_run/local_run.ipynb b/codegen-examples/examples/swebench_agent_run/local_run.ipynb index 1f27f470c..0b212fa40 100644 --- a/codegen-examples/examples/swebench_agent_run/local_run.ipynb +++ b/codegen-examples/examples/swebench_agent_run/local_run.ipynb @@ -7,7 +7,14 @@ "outputs": [], "source": [ "%load_ext autoreload\n", - "%autoreload 2" + "%autoreload 2\n", + "\n", + "from dotenv import load_dotenv # type: ignore\n", + "\n", + "load_dotenv()\n", + "\n", + "from codegen.extensions.swebench.utils import SWEBenchDataset, get_swe_bench_examples # noqa: E402\n", + "from run_eval import run_eval # noqa: E402" ] }, { @@ -16,9 +23,7 @@ "metadata": {}, "outputs": [], "source": [ - "from codegen.sdk.core.codebase import Codebase\n", - "from codegen.extensions.swebench.utils import SWEBenchDataset, get_swe_bench_examples\n", - "from run_eval import run_eval" + "examples = get_swe_bench_examples(dataset=SWEBenchDataset.LITE, split=\"test\", offset=0, length=10)" ] }, { @@ -27,43 +32,8 @@ "metadata": {}, "outputs": [], "source": [ - "examples = get_swe_bench_examples(dataset=SWEBenchDataset.LITE, split=\"test\", offset=0, length=1)" + "await run_eval(use_existing_preds=None, dataset=\"lite\", length=20, repo=\"django/django\", num_workers=10, model=\"claude-3-7-sonnet-latest\")" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "codebase = Codebase.from_repo(examples[0].repo, commit=examples[0].base_commit, tmp_dir=f\"/tmp/{examples[0].instance_id}\")\n", - "# this will allow us to reuse the codebase for multiple examples\n", - "codebases = {examples[0].instance_id: codebase}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "await run_eval(use_existing_preds=None, dataset=\"lite\", length=None, instance_id=examples[0].instance_id, local=True, codebases=codebases)\n", - "codebases[examples[0].instance_id].reset()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -82,7 +52,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.13.1" + "version": "3.13.0" } }, "nbformat": 4, diff --git a/pyproject.toml b/pyproject.toml index bbbb9ccde..3f30ba581 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ dependencies = [ "tiktoken<1.0.0,>=0.5.1", "tabulate>=0.9.0,<1.0.0", "codeowners<1.0.0,>=0.6.0", + "anthropic", "dataclasses-json<1.0.0,>=0.6.4", "dicttoxml<2.0.0,>=1.7.16", "xmltodict<1.0.0,>=0.13.0", diff --git a/src/codegen/agents/chat_agent.py b/src/codegen/agents/chat_agent.py new file mode 100644 index 000000000..24ecada26 --- /dev/null +++ b/src/codegen/agents/chat_agent.py @@ -0,0 +1,95 @@ +from typing import TYPE_CHECKING, Optional +from uuid import uuid4 + +from langchain.tools import BaseTool +from langchain_core.messages import AIMessage + +from codegen.extensions.langchain.agent import create_chat_agent + +if TYPE_CHECKING: + from codegen import Codebase + + +class ChatAgent: + """Agent for interacting with a codebase.""" + + def __init__(self, codebase: "Codebase", model_provider: str = "anthropic", model_name: str = "claude-3-5-sonnet-latest", memory: bool = True, tools: Optional[list[BaseTool]] = None, **kwargs): + """Initialize a CodeAgent. + + Args: + codebase: The codebase to operate on + model_provider: The model provider to use ("anthropic" or "openai") + model_name: Name of the model to use + memory: Whether to let LLM keep track of the conversation history + tools: Additional tools to use + **kwargs: Additional LLM configuration options. Supported options: + - temperature: Temperature parameter (0-1) + - top_p: Top-p sampling parameter (0-1) + - top_k: Top-k sampling parameter (>= 1) + - max_tokens: Maximum number of tokens to generate + """ + self.codebase = codebase + self.agent = create_chat_agent(self.codebase, model_provider=model_provider, model_name=model_name, memory=memory, additional_tools=tools, **kwargs) + + def run(self, prompt: str, thread_id: Optional[str] = None) -> str: + """Run the agent with a prompt. + + Args: + prompt: The prompt to run + thread_id: Optional thread ID for message history. If None, a new thread is created. + + Returns: + The agent's response + """ + if thread_id is None: + thread_id = str(uuid4()) + + input = {"query": prompt} + stream = self.agent.stream(input, config={"configurable": {"thread_id": thread_id}}, stream_mode="values") + + for s in stream: + message = s["messages"][-1] + if isinstance(message, tuple): + print(message) + else: + if isinstance(message, AIMessage) and isinstance(message.content, list) and "text" in message.content[0]: + AIMessage(message.content[0]["text"]).pretty_print() + else: + message.pretty_print() + + return s["final_answer"] + + def chat(self, prompt: str, thread_id: Optional[str] = None) -> tuple[str, str]: + """Chat with the agent, maintaining conversation history. + + Args: + prompt: The user message + thread_id: Optional thread ID for message history. If None, a new thread is created. + + Returns: + A tuple of (response_content, thread_id) to allow continued conversation + """ + if thread_id is None: + thread_id = str(uuid4()) + print(f"Starting new chat thread: {thread_id}") + else: + print(f"Continuing chat thread: {thread_id}") + + response = self.run(prompt, thread_id=thread_id) + return response, thread_id + + def get_chat_history(self, thread_id: str) -> list: + """Retrieve the chat history for a specific thread. + + Args: + thread_id: The thread ID to retrieve history for + + Returns: + List of messages in the conversation history + """ + # Access the agent's memory to get conversation history + if hasattr(self.agent, "get_state"): + state = self.agent.get_state({"configurable": {"thread_id": thread_id}}) + if state and "messages" in state: + return state["messages"] + return [] diff --git a/src/codegen/agents/code_agent.py b/src/codegen/agents/code_agent.py index d02cd08a2..03f061cab 100644 --- a/src/codegen/agents/code_agent.py +++ b/src/codegen/agents/code_agent.py @@ -3,7 +3,7 @@ from uuid import uuid4 from langchain.tools import BaseTool -from langchain_core.messages import AIMessage +from langchain_core.messages import AIMessage, HumanMessage from langchain_core.runnables.config import RunnableConfig from langsmith import Client @@ -94,8 +94,17 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str: # this message has a reducer which appends the current message to the existing history # see more https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers - input = {"messages": [("user", prompt)]} - tags, metadata = self.get_tags_metadata() + input = {"query": prompt} + metadata = {"project": self.project_name} + tags = [] + # Add SWEBench run ID and instance ID to the metadata and tags for filtering + if self.run_id is not None: + metadata["swebench_run_id"] = self.run_id + tags.append(self.run_id) + + if self.instance_id is not None: + metadata["swebench_instance_id"] = self.instance_id + tags.append(self.instance_id) config = RunnableConfig(configurable={"thread_id": thread_id}, tags=tags, metadata=metadata, recursion_limit=100) # we stream the steps instead of invoke because it allows us to access intermediate nodes @@ -105,7 +114,11 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str: run_ids = [] for s in stream: - message = s["messages"][-1] + if len(s["messages"]) == 0: + message = HumanMessage(content=prompt) + else: + message = s["messages"][-1] + if isinstance(message, tuple): print(message) else: @@ -119,7 +132,7 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str: run_ids.append(message.additional_kwargs["run_id"]) # Get the last message content - result = s["messages"][-1].content + result = s["final_answer"] # Try to find run IDs in the LangSmith client's recent runs try: diff --git a/src/codegen/extensions/langchain/agent.py b/src/codegen/extensions/langchain/agent.py index aabc57847..fe44594b1 100644 --- a/src/codegen/extensions/langchain/agent.py +++ b/src/codegen/extensions/langchain/agent.py @@ -6,11 +6,10 @@ from langchain_core.messages import SystemMessage from langgraph.checkpoint.memory import MemorySaver from langgraph.graph.graph import CompiledGraph -from langgraph.prebuilt import create_react_agent -from .llm import LLM -from .prompts import REASONER_SYSTEM_MESSAGE -from .tools import ( +from codegen.extensions.langchain.llm import LLM +from codegen.extensions.langchain.prompts import REASONER_SYSTEM_MESSAGE +from codegen.extensions.langchain.tools import ( CreateFileTool, DeleteFileTool, ListDirectoryTool, @@ -25,6 +24,8 @@ ViewFileTool, ) +from .graph import create_react_agent + if TYPE_CHECKING: from codegen import Codebase @@ -88,7 +89,7 @@ def create_codebase_agent( memory = MemorySaver() if memory else None - return create_react_agent(model=llm, tools=tools, prompt=system_message, checkpointer=memory, debug=debug) + return create_react_agent(model=llm, tools=tools, system_message=system_message, checkpointer=memory, debug=debug) def create_chat_agent( @@ -137,7 +138,7 @@ def create_chat_agent( memory = MemorySaver() if memory else None - return create_react_agent(model=llm, tools=tools, prompt=system_message, checkpointer=memory, debug=debug) + return create_react_agent(model=llm, tools=tools, system_message=system_message, checkpointer=memory, debug=debug) def create_codebase_inspector_agent( @@ -174,7 +175,7 @@ def create_codebase_inspector_agent( ] memory = MemorySaver() if memory else None - return create_react_agent(model=llm, tools=tools, prompt=system_message, checkpointer=memory, debug=debug) + return create_react_agent(model=llm, tools=tools, system_message=system_message, checkpointer=memory, debug=debug) def create_agent_with_tools( @@ -208,4 +209,4 @@ def create_agent_with_tools( memory = MemorySaver() if memory else None - return create_react_agent(model=llm, tools=tools, prompt=system_message, checkpointer=memory, debug=debug) + return create_react_agent(model=llm, tools=tools, system_message=system_message, checkpointer=memory, debug=debug) diff --git a/src/codegen/extensions/langchain/graph.py b/src/codegen/extensions/langchain/graph.py new file mode 100644 index 000000000..3685ea322 --- /dev/null +++ b/src/codegen/extensions/langchain/graph.py @@ -0,0 +1,102 @@ +"""Demo implementation of an agent with Codegen tools.""" + +from typing import TYPE_CHECKING, Annotated, Any, Literal, Optional + +import anthropic +import openai +from langchain.tools import BaseTool +from langchain_core.messages import AIMessage, AnyMessage, HumanMessage, SystemMessage +from langgraph.checkpoint.memory import MemorySaver +from langgraph.graph import END, START +from langgraph.graph.message import add_messages +from langgraph.graph.state import CompiledGraph, StateGraph +from langgraph.prebuilt import ToolNode +from langgraph.pregel import RetryPolicy + + +class GraphState(dict[str, Any]): + """State of the graph.""" + + query: str + final_answer: str + messages: Annotated[list[AnyMessage], add_messages] + + +class AgentGraph: + """Main graph class for the agent.""" + + def __init__(self, model: "LLM", tools: list[BaseTool], system_message: SystemMessage): + self.model = model.bind_tools(tools) + self.tools = tools + self.system_message = system_message + + # =================================== NODES ==================================== + + # Reasoner node + def reasoner(self, state: GraphState) -> dict[str, Any]: + new_turn = len(state["messages"]) == 0 or isinstance(state["messages"][-1], AIMessage) + messages = state["messages"] + if new_turn: + query = state["query"] + messages.append(HumanMessage(content=query)) + + result = self.model.invoke([self.system_message, *messages]) + + if isinstance(result, AIMessage): + return {"messages": [*messages, result], "final_answer": result.content} + + return {"messages": [*messages, result]} + + # =================================== EDGE CONDITIONS ==================================== + def should_continue(self, state: GraphState) -> Literal["tools", END]: + messages = state["messages"] + last_message = messages[-1] + if hasattr(last_message, "tool_calls") and last_message.tool_calls: + return "tools" + return END + + # =================================== COMPILE GRAPH ==================================== + def create(self, checkpointer: Optional[MemorySaver] = None, debug: bool = False) -> CompiledGraph: + """Create and compile the graph.""" + builder = StateGraph(GraphState) + + # the retry policy has an initial interval, a backoff factor, and a max interval of controlling the + # amount of time between retries + retry_policy = RetryPolicy( + retry_on=[anthropic.RateLimitError, openai.RateLimitError], + max_attempts=10, + initial_interval=30.0, # Start with 30 second wait + backoff_factor=2, # Double the wait time each retry + max_interval=1000.0, # Cap at 1000 second max wait + jitter=True, + ) + + # Add nodes + builder.add_node("reasoner", self.reasoner, retry=retry_policy) + builder.add_node("tools", ToolNode(self.tools), retry=retry_policy) + + # Add edges + builder.add_edge(START, "reasoner") + builder.add_edge("tools", "reasoner") + builder.add_conditional_edges( + "reasoner", + self.should_continue, + ) + + return builder.compile(checkpointer=checkpointer, debug=debug) + + +def create_react_agent( + model: "LLM", + tools: list[BaseTool], + system_message: SystemMessage, + checkpointer: Optional[MemorySaver] = None, + debug: bool = False, +) -> CompiledGraph: + """Create a reactive agent graph.""" + graph = AgentGraph(model, tools, system_message) + return graph.create(checkpointer=checkpointer, debug=debug) + + +if TYPE_CHECKING: + from codegen.extensions.langchain.llm import LLM diff --git a/src/codegen/extensions/langchain/llm.py b/src/codegen/extensions/langchain/llm.py index d2cec02a3..54b9a91a2 100644 --- a/src/codegen/extensions/langchain/llm.py +++ b/src/codegen/extensions/langchain/llm.py @@ -89,13 +89,13 @@ def _get_model(self) -> BaseChatModel: if not os.getenv("ANTHROPIC_API_KEY"): msg = "ANTHROPIC_API_KEY not found in environment. Please set it in your .env file or environment variables." raise ValueError(msg) - return ChatAnthropic(**self._get_model_kwargs()) + return ChatAnthropic(**self._get_model_kwargs(), max_retries=10, timeout=1000) elif self.model_provider == "openai": if not os.getenv("OPENAI_API_KEY"): msg = "OPENAI_API_KEY not found in environment. Please set it in your .env file or environment variables." raise ValueError(msg) - return ChatOpenAI(**self._get_model_kwargs()) + return ChatOpenAI(**self._get_model_kwargs(), max_retries=10, timeout=1000) elif self.model_provider == "xai": if not os.getenv("XAI_API_KEY"): diff --git a/src/codegen/extensions/langchain/tools.py b/src/codegen/extensions/langchain/tools.py index 7cda6d7f9..2ab5b0179 100644 --- a/src/codegen/extensions/langchain/tools.py +++ b/src/codegen/extensions/langchain/tools.py @@ -116,7 +116,8 @@ class SearchInput(BaseModel): query: str = Field( ..., - description="The search query to find in the codebase. When ripgrep is available, this will be passed as a ripgrep pattern. For regex searches, set use_regex=True. Ripgrep is the preferred method.", + description="""The search query to find in the codebase. When ripgrep is available, this will be passed as a ripgrep pattern. For regex searches, set use_regex=True. + Ripgrep is the preferred method.""", ) target_directories: Optional[list[str]] = Field(default=None, description="Optional list of directories to search in") file_extensions: Optional[list[str]] = Field(default=None, description="Optional list of file extensions to search (e.g. ['.py', '.ts'])") @@ -849,31 +850,45 @@ def get_workspace_tools(codebase: Codebase) -> list["BaseTool"]: class ReplacementEditInput(BaseModel): - filepath: str = Field(..., description="Path to the file to edit relative to the workspace root. The file must exist and be a text file.") + """Input for replacement editing.""" + + filepath: str = Field( + ..., + description=("Path to the file to edit relative to the workspace root. The file must exist and be a text file."), + ) pattern: str = Field( ..., - description="""Regular expression pattern to match text that should be replaced. -Supports all Python regex syntax including capture groups (\1, \2, etc). The pattern is compiled with re.MULTILINE flag by default.""", + description=( + "Regular expression pattern to match text that should be replaced. " + "Supports all Python regex syntax including capture groups (\\1, \\2, etc). " + "The pattern is compiled with re.MULTILINE flag by default." + ), ) replacement: str = Field( ..., - description="""Text to replace matched patterns with. -Can reference regex capture groups using \1, \2, etc. If using regex groups in pattern, make sure to preserve them in replacement if needed.""", + description=( + "Text to replace matched patterns with. Can reference regex capture groups using \\1, \\2, etc. If using regex groups in pattern, make sure to preserve them in replacement if needed." + ), ) start: int = Field( default=1, - description="""Starting line number (1-indexed, inclusive) to begin replacements from. -Use this with 'end' to limit changes to a specific region. Default is 1 (start of file).""", + description=("Starting line number (1-indexed, inclusive) to begin replacements from. Use this with 'end' to limit changes to a specific region. Default is 1 (start of file)."), ) end: int = Field( default=-1, - description="""Ending line number (1-indexed, inclusive) to stop replacements at. -Use -1 to indicate end of file. Use this with 'start' to limit changes to a specific region. Default is -1 (end of file).""", + description=( + "Ending line number (1-indexed, inclusive) to stop replacements at. " + "Use -1 to indicate end of file. Use this with 'start' to limit changes to a specific region. " + "Default is -1 (end of file)." + ), ) count: Optional[int] = Field( default=None, - description="""Maximum number of replacements to make. Use None to replace all occurrences (default), or specify a number to limit replacements. -Useful when you only want to replace the first N occurrences.""", + description=( + "Maximum number of replacements to make. " + "Use None to replace all occurrences (default), or specify a number to limit replacements. " + "Useful when you only want to replace the first N occurrences." + ), ) diff --git a/src/codegen/extensions/tools/replacement_edit.py b/src/codegen/extensions/tools/replacement_edit.py index 0c61c8f96..aa5cd98be 100644 --- a/src/codegen/extensions/tools/replacement_edit.py +++ b/src/codegen/extensions/tools/replacement_edit.py @@ -30,6 +30,14 @@ class ReplacementEditObservation(Observation): default=None, description="Message describing the result", ) + error: Optional[str] = Field( + default=None, + description="Error message if an error occurred", + ) + error_pattern: Optional[str] = Field( + default=None, + description="Regex pattern that failed to compile", + ) str_template: ClassVar[str] = "{message}" if "{message}" else "Edited file {filepath}" @@ -138,8 +146,13 @@ def replacement_edit( # Compile pattern for better error messages regex = re.compile(pattern, flags) except re.error as e: - msg = f"Invalid regex pattern: {e}" - raise ValueError(msg) + return ReplacementEditObservation( + status="error", + error=f"Invalid regex pattern: {e!s}", + error_pattern=pattern, + filepath=filepath, + message="Invalid regex pattern", + ) # Perform the replacement if count is None: diff --git a/src/codegen/extensions/tools/search.py b/src/codegen/extensions/tools/search.py index 4bcdfb74e..08a52c48b 100644 --- a/src/codegen/extensions/tools/search.py +++ b/src/codegen/extensions/tools/search.py @@ -146,7 +146,7 @@ def _search_with_ripgrep( pass # Add the query and path - cmd.append(query) + cmd.append(f"{query}") cmd.append(search_path) # Run ripgrep From 6da11739724648e3720fca2fbaad2fea9cba3d0a Mon Sep 17 00:00:00 2001 From: Tawsif Kamal Date: Mon, 10 Mar 2025 12:04:10 -0700 Subject: [PATCH 62/66] 500 Error Anthropic Retry Policy (#789) added `anthropic.InternalServerError` in the retry policy --- src/codegen/extensions/langchain/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/extensions/langchain/graph.py b/src/codegen/extensions/langchain/graph.py index 3685ea322..e5116630f 100644 --- a/src/codegen/extensions/langchain/graph.py +++ b/src/codegen/extensions/langchain/graph.py @@ -63,7 +63,7 @@ def create(self, checkpointer: Optional[MemorySaver] = None, debug: bool = False # the retry policy has an initial interval, a backoff factor, and a max interval of controlling the # amount of time between retries retry_policy = RetryPolicy( - retry_on=[anthropic.RateLimitError, openai.RateLimitError], + retry_on=[anthropic.RateLimitError, openai.RateLimitError, anthropic.InternalServerError], max_attempts=10, initial_interval=30.0, # Start with 30 second wait backoff_factor=2, # Double the wait time each retry From a652487d94e5ea2a2da66e95c15da67cab1cc1a3 Mon Sep 17 00:00:00 2001 From: jemeza-codegen <165736868+jemeza-codegen@users.noreply.github.com> Date: Mon, 10 Mar 2025 12:05:54 -0700 Subject: [PATCH 63/66] chore: minor tag and metadata refactor (#780) # Motivation Tags and Metadata are now optional parameters to the CodeAgent class. These will be added to the agent trace # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- src/codegen/agents/code_agent.py | 32 ++++++++++------------ src/codegen/extensions/swebench/harness.py | 4 ++- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/codegen/agents/code_agent.py b/src/codegen/agents/code_agent.py index 03f061cab..99c01a874 100644 --- a/src/codegen/agents/code_agent.py +++ b/src/codegen/agents/code_agent.py @@ -33,9 +33,8 @@ def __init__( model_name: str = "claude-3-7-sonnet-latest", memory: bool = True, tools: Optional[list[BaseTool]] = None, - run_id: Optional[str] = None, - instance_id: Optional[str] = None, - difficulty: Optional[int] = None, + tags: Optional[list[str]] = [], + metadata: Optional[dict] = {}, **kwargs, ): """Initialize a CodeAgent. @@ -46,6 +45,8 @@ def __init__( model_name: Name of the model to use memory: Whether to let LLM keep track of the conversation history tools: Additional tools to use + tags: Tags to add to the agent trace. Must be of the same type. + metadata: Metadata to use for the agent. Must be a dictionary. **kwargs: Additional LLM configuration options. Supported options: - temperature: Temperature parameter (0-1) - top_p: Top-p sampling parameter (0-1) @@ -63,14 +64,21 @@ def __init__( ) self.model_name = model_name self.langsmith_client = Client() - self.run_id = run_id - self.instance_id = instance_id - self.difficulty = difficulty # Get project name from environment variable or use a default self.project_name = os.environ.get("LANGCHAIN_PROJECT", "RELACE") print(f"Using LangSmith project: {self.project_name}") + # Initialize tags for agent trace + self.tags = [*tags, self.model_name] + + # Initialize metadata for agent trace + self.metadata = { + "project": self.project_name, + "model": self.model_name, + **metadata, + } + def run(self, prompt: str, thread_id: Optional[str] = None) -> str: """Run the agent with a prompt. @@ -95,18 +103,8 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str: # this message has a reducer which appends the current message to the existing history # see more https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers input = {"query": prompt} - metadata = {"project": self.project_name} - tags = [] - # Add SWEBench run ID and instance ID to the metadata and tags for filtering - if self.run_id is not None: - metadata["swebench_run_id"] = self.run_id - tags.append(self.run_id) - - if self.instance_id is not None: - metadata["swebench_instance_id"] = self.instance_id - tags.append(self.instance_id) - config = RunnableConfig(configurable={"thread_id": thread_id}, tags=tags, metadata=metadata, recursion_limit=100) + config = RunnableConfig(configurable={"thread_id": thread_id}, tags=self.tags, metadata=self.metadata, recursion_limit=100) # we stream the steps instead of invoke because it allows us to access intermediate nodes stream = self.agent.stream(input, config=config, stream_mode="values") diff --git a/src/codegen/extensions/swebench/harness.py b/src/codegen/extensions/swebench/harness.py index dbf9f6b9b..7eaacd5ad 100644 --- a/src/codegen/extensions/swebench/harness.py +++ b/src/codegen/extensions/swebench/harness.py @@ -70,7 +70,9 @@ def run_agent_on_entry(entry: SweBenchExample, model: str, codebase: Codebase | ) codebase = Codebase.from_repo(repo_full_name=entry.repo, commit=base_commit, language="python", config=config) # check out the repo - agent = CodeAgent(codebase=codebase, run_id=run_id, instance_id=instance_id, model_name=model, difficulty=entry.difficulty) + metadata = {"run_id": run_id, "instance_id": instance_id, "difficulty": f"difficulty_{entry.difficulty}"} + tags = [str(value) for value in metadata.values()] + agent = CodeAgent(codebase=codebase, tags=tags, metadata=metadata) pprint.pprint(instance_id) pprint.pprint(gold_files) From ef1dba8a82331685d642d014238a671ba0a48ae3 Mon Sep 17 00:00:00 2001 From: Vishal Shenoy Date: Mon, 10 Mar 2025 16:06:23 -0700 Subject: [PATCH 64/66] From repo with full history (#790) Add optional full_history argument to from_repo to get all commit history. --- docs/api-reference/core/Codebase.mdx | 6 +++--- src/codegen/git/repo_operator/repo_operator.py | 11 ++++++++--- src/codegen/sdk/core/codebase.py | 3 ++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/api-reference/core/Codebase.mdx b/docs/api-reference/core/Codebase.mdx index bcfbc0c38..529d9eb13 100644 --- a/docs/api-reference/core/Codebase.mdx +++ b/docs/api-reference/core/Codebase.mdx @@ -328,10 +328,10 @@ Fetches a codebase from GitHub and returns a Codebase instance. defaultValue="None" /> bool } - description="Whether to do a shallow clone. Defaults to True" - defaultValue="" + description="Whether to clone the full git history. Defaults to False" + defaultValue="False" /> Self | None: + def create_from_repo(cls, repo_path: str, url: str, access_token: str | None = None, full_history: bool = False) -> Self | None: """Create a fresh clone of a repository or use existing one if up to date. Args: repo_path (str): Path where the repo should be cloned url (str): Git URL of the repository access_token (str | None): Optional GitHub API key for operations that need GitHub access + full_history (bool): If True, clones the complete repository history. If False, performs a shallow clone. Defaults to False. """ access_token = access_token or SecretsConfig().github_token if access_token: @@ -886,9 +887,13 @@ def create_from_repo(cls, repo_path: str, url: str, access_token: str | None = N import shutil shutil.rmtree(repo_path) + try: - # Clone the repository - GitCLI.clone_from(url=url, to_path=repo_path, depth=1) + # Clone the repository with or without full history + if full_history: + GitCLI.clone_from(url=url, to_path=repo_path) + else: + GitCLI.clone_from(url=url, to_path=repo_path, depth=1) # Initialize with the cloned repo git_cli = GitCLI(repo_path) diff --git a/src/codegen/sdk/core/codebase.py b/src/codegen/sdk/core/codebase.py index 2c641e655..d9a6e6960 100644 --- a/src/codegen/sdk/core/codebase.py +++ b/src/codegen/sdk/core/codebase.py @@ -1313,6 +1313,7 @@ def from_repo( config: CodebaseConfig | None = None, secrets: SecretsConfig | None = None, setup_option: SetupOption | None = None, + full_history: bool = False, ) -> "Codebase": """Fetches a codebase from GitHub and returns a Codebase instance. @@ -1352,7 +1353,7 @@ def from_repo( if commit is None: repo_config = RepoConfig.from_repo_path(repo_path) repo_config.full_name = repo_full_name - repo_operator = RepoOperator(repo_config=repo_config, access_token=access_token, setup_option=setup_option) + repo_operator = RepoOperator.create_from_repo(repo_config=repo_config, access_token=access_token, setup_option=setup_option, full_history=full_history) else: # Ensure the operator can handle remote operations repo_operator = RepoOperator.create_from_commit(repo_path=repo_path, commit=commit, url=repo_url, full_name=repo_full_name, access_token=access_token) From 35537882c947dc19b083f951bfdd8221e6c753a8 Mon Sep 17 00:00:00 2001 From: codegen-team Date: Mon, 10 Mar 2025 23:08:03 +0000 Subject: [PATCH 65/66] docs: updated API reference --- docs/api-reference/core/Codebase.mdx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/api-reference/core/Codebase.mdx b/docs/api-reference/core/Codebase.mdx index 529d9eb13..963ee95db 100644 --- a/docs/api-reference/core/Codebase.mdx +++ b/docs/api-reference/core/Codebase.mdx @@ -11,7 +11,7 @@ import {HorizontalDivider} from '/snippets/HorizontalDivider.mdx'; import {GithubLinkNote} from '/snippets/GithubLinkNote.mdx'; import {Attribute} from '/snippets/Attribute.mdx'; - + ## Attributes @@ -257,7 +257,7 @@ Creates a pull request from the current branch to the repository's default branc ### create_pr_comment Create a comment on a pull request - + None } description=""/> @@ -265,7 +265,7 @@ Create a comment on a pull request ### create_pr_review_comment Create a review comment on a pull request. - + None } description=""/> @@ -298,7 +298,7 @@ Finds editable objects that overlap with the given source code span. ### from_files Creates a Codebase instance from multiple files. - + Codebase } description="A Codebase instance initialized with the provided files"/> @@ -306,7 +306,7 @@ Creates a Codebase instance from multiple files. ### from_repo Fetches a codebase from GitHub and returns a Codebase instance. - + bool } - description="Whether to clone the full git history. Defaults to False" - defaultValue="False" + description="Whether to do a shallow clone. Defaults to True" + defaultValue="" /> from_string Creates a Codebase instance from a string of code. - + Codebase } description="A Codebase instance initialized with the provided code Example: >>> # Python code >>> code = "def add(a, b): return a + b" >>> codebase = Codebase.from_string(code, language="python") >>> # TypeScript code >>> code = "function add(a: number, b: number): number { return a + b; }" >>> codebase = Codebase.from_string(code, language="typescript")"/> @@ -465,7 +465,7 @@ Retrieves a function from the codebase by its name. ### get_modified_symbols_in_pr Get all modified symbols in a pull request - + tuple[str, dict[str, str], list[str]] } description=""/> From 8490b3098f98340e672aa26f793a68e84acdb89f Mon Sep 17 00:00:00 2001 From: Edward Li Date: Mon, 10 Mar 2025 16:23:22 -0700 Subject: [PATCH 66/66] Architecture Docs V1 (#792) # Motivation # Content # Testing # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --- .../2. parsing/B. AST Construction.md | 2 +- .../2. parsing/C. Directory Parsing.md | 50 ++++++++++ architecture/3. imports-exports/A. Imports.md | 57 ++++++++++- architecture/3. imports-exports/B. Exports.md | 70 +++++++++++++- .../3. imports-exports/C. TSConfig.md | 76 ++++++++++++++- .../5. performing-edits/A. Edit Operations.md | 7 -- .../5. performing-edits/A. Transactions.md | 54 +++++++++++ .../B. Transaction Manager.md | 88 ++++++++++++++++- architecture/external/dependency-manager.md | 95 ++++++++++++++++++- architecture/external/type-engine.md | 20 +++- 10 files changed, 504 insertions(+), 15 deletions(-) create mode 100644 architecture/2. parsing/C. Directory Parsing.md delete mode 100644 architecture/5. performing-edits/A. Edit Operations.md create mode 100644 architecture/5. performing-edits/A. Transactions.md diff --git a/architecture/2. parsing/B. AST Construction.md b/architecture/2. parsing/B. AST Construction.md index c6484aaba..06a1cd48c 100644 --- a/architecture/2. parsing/B. AST Construction.md +++ b/architecture/2. parsing/B. AST Construction.md @@ -74,4 +74,4 @@ Statements have another layer of complexity. They are essentially pattern based ## Next Step -After the AST is constructed, the system moves on to [Import Resolution](../3.%20imports-exports/A.%20Imports.md) to analyze module dependencies and resolve symbols across files. +After the AST is constructed, the system moves on to [Directory Parsing](./C.%20Directory%20Parsing.md) to build a hierarchical representation of the codebase's directory structure. diff --git a/architecture/2. parsing/C. Directory Parsing.md b/architecture/2. parsing/C. Directory Parsing.md new file mode 100644 index 000000000..f25de2e29 --- /dev/null +++ b/architecture/2. parsing/C. Directory Parsing.md @@ -0,0 +1,50 @@ +# Directory Parsing + +The Directory Parsing system is responsible for creating and maintaining a hierarchical representation of the codebase's directory structure in memory. Directories do not hold references to the file itself, but instead holds the names to the files and does a dynamic lookup when needed. + +In addition to providing a more cohesive API for listing directory files, the Directory API is also used for [TSConfig](../3.%20imports-exports/C.%20TSConfig.md)-based (Import Resolution)[../3.%20imports-exports/A.%20Imports.md]. + +## Core Components + +The Directory Tree is constructed during the initial build_graph step in codebase_context.py, and is recreated from scratch on every re-sync. More details are below: + +## Directory Tree Construction + +The directory tree is built through the following process: + +1. The `build_directory_tree` method in `CodebaseContext` is called during graph initialization or when the codebase structure changes. +1. The method iterates through all files in the repository, creating directory objects for each directory path encountered. +1. For each file, it adds the file to its parent directory using the `_add_file` method. +1. Directories are created recursively as needed using the `get_directory` method with create_on_missing=True\`. + +## Directory Representation + +The `Directory` class provides a rich interface for working with directories: + +- **Hierarchy Navigation**: Access parent directories and subdirectories +- **File Access**: Retrieve files by name or extension +- **Symbol Access**: Find symbols (classes, functions, etc.) within files in the directory +- **Directory Operations**: Rename, remove, or update directories + +Each `Directory` instance maintains: + +- A reference to its parent directory +- Lists of files and subdirectories +- Methods to recursively traverse the directory tree + +## File Representation + +Files are represented by the `File` class and its subclasses: + +- `File`: Base class for all files, supporting basic operations like reading and writing content +- `SourceFile`: Specialized class for source code files that can be parsed into an AST + +Files maintain references to: + +- Their parent directory +- Their content (loaded dynamically to preserve the source of truth) +- For source files, the parsed AST and symbols + +## Next Step + +After the directory structure is parsed, the system can perform [Import Resolution](../3.%20imports-exports/A.%20Imports.md) to analyze module dependencies and resolve symbols across files. diff --git a/architecture/3. imports-exports/A. Imports.md b/architecture/3. imports-exports/A. Imports.md index 09d70d902..cca5951ab 100644 --- a/architecture/3. imports-exports/A. Imports.md +++ b/architecture/3. imports-exports/A. Imports.md @@ -1,7 +1,60 @@ # Import Resolution -TODO +Import resolution follows AST construction in the code analysis pipeline. It identifies dependencies between modules and builds a graph of relationships across the codebase. + +> NOTE: This is an actively evolving part of Codegen SDK, so some details here may be imcomplete, outdated, or incorrect. + +## Purpose + +The import resolution system serves these purposes: + +1. **Dependency Tracking**: Maps relationships between files by resolving import statements. +1. **Symbol Resolution**: Connects imported symbols to their definitions. +1. **Module Graph Construction**: Builds a directed graph of module dependencies. +1. **(WIP) Cross-Language Support**: Provides implementations for different programming languages. + +## Core Components + +### ImportResolution Class + +The `ImportResolution` class represents the outcome of resolving an import statement. It contains: + +- The source file containing the imported symbol +- The specific symbol being imported (if applicable) +- Whether the import references an entire file/module + +### Import Base Class + +The `Import` class is the foundation for language-specific import implementations. It: + +- Stores metadata about the import (module path, symbol name, alias) +- Provides the abstract `resolve_import()` method +- Adds symbol resolution edges to the codebase graph + +### Language-Specific Implementations + +#### Python Import Resolution + +The `PyImport` class extends the base `Import` class with Python-specific logic: + +- Handles relative imports +- Supports module imports, named imports, and wildcard imports +- Resolves imports using configurable resolution paths and `sys.path` +- Handles special cases like `__init__.py` files + +#### TypeScript Import Resolution + +The `TSImport` class implements TypeScript-specific resolution: + +- Supports named imports, default imports, and namespace imports +- Handles type imports and dynamic imports +- Resolves imports using TSConfig path mappings +- Supports file extension resolution + +## Implementation + +After file and directory parse, we loop through all import nodes and perform `add_symbol_resolution_edge`. This then invokes the language-specific `resolve_import` method that converts the import statement into a resolvable `ImportResolution` object (or None if the import cannot be resolved). This import symbol and the `ImportResolution` object are then used to add a symbol resolution edge to the graph, where it can then be used in future steps to resolve symbols. ## Next Step -After import resolution, the system analyzes [Export Analysis](./B.%20Exports.md) and handles [TSConfig Support](./C.%20TSConfig.md) for TypeScript projects. This is followed by comprehensive [Type Analysis](../4.%20type-analysis/A.%20Type%20Analysis.md). +After import resolution, the system analyzes [Export Analysis](./B.%20Exports.md) and handles [TSConfig Support](./C.%20TSConfig.md) for TypeScript projects. This is followed by [Type Analysis](../4.%20type-analysis/A.%20Type%20Analysis.md). diff --git a/architecture/3. imports-exports/B. Exports.md b/architecture/3. imports-exports/B. Exports.md index 9da67fcb4..0e42c98c4 100644 --- a/architecture/3. imports-exports/B. Exports.md +++ b/architecture/3. imports-exports/B. Exports.md @@ -1,6 +1,74 @@ # Export Analysis -TODO +Some languages contain additional metadata on "exported" symbols, specifying which symbols are made available to other modules. Export analysis follows import resolution in the code analysis pipeline. It identifies and processes exported symbols from modules, enabling the system to track what each module makes available to others. + +## Core Components + +### Export Base Class + +The `Export` class serves as the foundation for language-specific export implementations. It: + +- Stores metadata about the export (symbol name, is default, etc.) +- Tracks the relationship between the export and its declared symbol +- Adds export edges to the codebase graph + +### TypeScript Export Implementation + +The `TSExport` class implements TypeScript-specific export handling: + +- Supports various export styles (named exports, default exports, re-exports) +- Handles export declarations with and without values +- Processes wildcard exports (`export * from 'module'`) +- Manages export statements with multiple exports + +#### Export Types and Symbol Resolution + +The TypeScript implementation handles several types of exports: + +1. **Declaration Exports** + + - Function declarations (including generators) + - Class declarations + - Interface declarations + - Type alias declarations + - Enum declarations + - Namespace declarations + - Variable/constant declarations + +1. **Value Exports** + + - Object literals with property exports + - Arrow functions and function expressions + - Classes and class expressions + - Assignment expressions + - Primitive values and expressions + +1. **Special Export Forms** + + - Wildcard exports (`export * from 'module'`) + - Named re-exports (`export { name as alias } from 'module'`) + - Default exports with various value types + +#### Symbol Tracking and Dependencies + +The export system: + +- Maintains relationships between exported symbols and their declarations +- Validates export names match their declared symbols +- Tracks dependencies through the codebase graph +- Handles complex scenarios like: + - Shorthand property exports in objects + - Nested function and class declarations + - Re-exports from other modules + +#### Integration with Type System + +Exports are tightly integrated with the type system: + +- Exported type declarations are properly tracked +- Symbol resolution considers both value and type exports +- Re-exports preserve type information +- Export edges in the codebase graph maintain type relationships ## Next Step diff --git a/architecture/3. imports-exports/C. TSConfig.md b/architecture/3. imports-exports/C. TSConfig.md index e9c77ae0c..b2362a7c8 100644 --- a/architecture/3. imports-exports/C. TSConfig.md +++ b/architecture/3. imports-exports/C. TSConfig.md @@ -1,6 +1,80 @@ # TSConfig Support -TODO +TSConfig support is a critical component for TypeScript projects in the import resolution system. It processes TypeScript configuration files (tsconfig.json) to correctly resolve module paths and dependencies. + +## Purpose + +The TSConfig support system serves these purposes: + +1. **Path Mapping**: Resolves custom module path aliases defined in the tsconfig.json file. +1. **Base URL Resolution**: Handles non-relative module imports using the baseUrl configuration. +1. **Project References**: Manages dependencies between TypeScript projects using the references field. +1. **Directory Structure**: Respects rootDir and outDir settings for maintaining proper directory structures. + +## Core Components + +### TSConfig Class + +The `TSConfig` class represents a parsed TypeScript configuration file. It: + +- Parses and stores the configuration settings from tsconfig.json +- Handles inheritance through the "extends" field +- Provides methods for translating between import paths and absolute file paths +- Caches computed values for performance optimization + +## Configuration Processing + +### Configuration Inheritance + +TSConfig files can extend other configuration files through the "extends" field: + +1. Base configurations are loaded and parsed first +1. Child configurations inherit and can override settings from their parent +1. Path mappings, base URLs, and other settings are merged appropriately + +### Path Mapping Resolution + +The system processes the "paths" field in tsconfig.json to create a mapping between import aliases and file paths: + +1. Path patterns are normalized (removing wildcards, trailing slashes) +1. Relative paths are converted to absolute paths +1. Mappings are stored for efficient lookup during import resolution + +### Project References + +The "references" field defines dependencies between TypeScript projects: + +1. Referenced projects are identified and loaded +1. Their configurations are analyzed to determine import paths +1. Import resolution can cross project boundaries using these references + +## Import Resolution Process + +### Path Translation + +When resolving an import path in TypeScript: + +1. Check if the path matches any path alias in the tsconfig.json +1. If a match is found, translate the path according to the mapping +1. Apply baseUrl resolution for non-relative imports +1. Handle project references for cross-project imports + +### Optimization Techniques + +The system employs several optimizations: + +1. Caching computed values to avoid redundant processing +1. Early path checking for common patterns (e.g., paths starting with "@" or "~") +1. Hierarchical resolution that respects the configuration inheritance chain + +## Integration with Import Resolution + +The TSConfig support integrates with the broader import resolution system: + +1. Each TypeScript file is associated with its nearest tsconfig.json +1. Import statements are processed using the file's associated configuration +1. Path mappings are applied during the module resolution process +1. Project references are considered when resolving imports across project boundaries ## Next Step diff --git a/architecture/5. performing-edits/A. Edit Operations.md b/architecture/5. performing-edits/A. Edit Operations.md deleted file mode 100644 index 850b8e103..000000000 --- a/architecture/5. performing-edits/A. Edit Operations.md +++ /dev/null @@ -1,7 +0,0 @@ -# Edit Operations - -TODO - -## Next Step - -After preparing edits, they are managed by the [Transaction Manager](./B.%20Transaction%20Manager.md) to ensure consistency and atomicity. diff --git a/architecture/5. performing-edits/A. Transactions.md b/architecture/5. performing-edits/A. Transactions.md new file mode 100644 index 000000000..c27c7e65f --- /dev/null +++ b/architecture/5. performing-edits/A. Transactions.md @@ -0,0 +1,54 @@ +# Transactions + +Transactions represent atomic changes to files in the codebase. Each transaction defines a specific modification that can be queued, validated, and executed. + +## Transaction Types + +The transaction system is built around a base `Transaction` class with specialized subclasses: + +### Content Transactions + +- **RemoveTransaction**: Removes content between specified byte positions +- **InsertTransaction**: Inserts new content at a specified byte position +- **EditTransaction**: Replaces content between specified byte positions + +### File Transactions + +- **FileAddTransaction**: Creates a new file +- **FileRenameTransaction**: Renames an existing file +- **FileRemoveTransaction**: Deletes a file + +## Transaction Priority + +Transactions are executed in a specific order defined by the `TransactionPriority` enum: + +1. **Remove** (highest priority) +1. **Edit** +1. **Insert** +1. **FileAdd** +1. **FileRename** +1. **FileRemove** + +This ordering ensures that content is removed before editing or inserting, and that all content operations happen before file operations. + +## Key Concepts + +### Byte-Level Operations + +All content transactions operate at the byte level rather than on lines or characters. This provides precise control over modifications and allows transactions to work with any file type, regardless of encoding or line ending conventions. + +### Content Generation + +Transactions support both static content (direct strings) and dynamic content (generated at execution time). This flexibility allows for complex transformations where the new content depends on the state of the codebase at execution time. + +Most content transactions use static content, but dynamic content is supported for rare cases where the new content depends on the state of other transactions. One common example is handling whitespace during add and remove transactions. + +### File Operations + +File transactions are used to create, rename, and delete files. + +> NOTE: It is important to note that most file transactions such as `FileAddTransaction` are no-ops (AKA skiping Transaction Manager) and instead applied immediately once the `create_file` API is called. This allows for created files to be immediately available for edit and use. The reason file operations are still added to Transaction Manager is to help with optimizing graph re-parse and diff generation. (Keeping track of which files exist and don't exist anymore). + +## Next Step + +After understanding the transaction system, they are managed by the [Transaction Manager](./B.%20Transaction%20Manager.md) to ensure consistency and atomicity. diff --git a/architecture/5. performing-edits/B. Transaction Manager.md b/architecture/5. performing-edits/B. Transaction Manager.md index a41d91270..4ed78a750 100644 --- a/architecture/5. performing-edits/B. Transaction Manager.md +++ b/architecture/5. performing-edits/B. Transaction Manager.md @@ -1,6 +1,92 @@ # Transaction Manager -TODO +The Transaction Manager coordinates the execution of transactions across multiple files, handling conflict resolution, and enforcing resource limits. + +## High-level Concept + +Since all node operations are on byte positions of the original file, multiple operations that change the total byte length of the file will result in offset errors and broken code. + +Give this example over here: + +``` +Original: FooBar +Operations: Remove "Foo" (bytes 0-3), Insert "Hello" (bytes 0-5) + Remove "Bar" (bytes 3-6), Insert "World" (bytes 3-7) +``` + +If these operations were applied in order, the result would be: + +``` +Result: FooBar +Operation: Remove "Foo" (bytes 0-3), Insert "Hello" (bytes 0-5) +Result: HelloBar +Operation: Remove "Bar" (bytes 3-6), Insert "World" (bytes 3-7) +Result: HelWorldar +``` + +Resulting in an invalid output. + +⭐ The key with TransactionManager is that it queues up all transactions in a given Codemod run, the applies all of the ***backwards*** from the last byte range to the first. Given the same example as above but applied backwards: + +``` +Result: FooBar +Operation: Remove "Bar" (bytes 3-6), Insert "World" (bytes 3-7) +Result: FooWorld +Operation: Remove "Foo" (bytes 0-3), Insert "Hello" (bytes 0-5) +Result: HelloWorld +``` + +TransactionManager also performs some additional operations such detecting conflicts and coordinating (some basic) conflict resolutions. Overall, the core responsibilities are as follows: + +1. **Transaction Queueing**: Maintains a queue of pending transactions organized by file +1. **Conflict Resolution**: Detects and resolves conflicts between transactions +1. **Transaction Execution**: Applies transactions in the correct order +1. **Resource Management**: Enforces limits on transaction count and execution time +1. **Change Tracking**: Generates diffs for applied changes + +## Sorting Transactions + +Before execution, transactions are sorted based on (in this priority): + +1. Position in the file (higher byte positions first) +1. Transaction type (following the priority order) +1. User-defined priority +1. Creation order + +This sorting ensures that transactions are applied in a deterministic order that minimizes conflicts. Larger byte ranges are always edited first, removals happen before insertions, and older transactions are applied before newer ones. + +## Conflict Resolution + +### Conflict Types + +The manager identifies several types of conflicts: + +1. **Overlapping Transactions**: Multiple transactions affecting the same byte range +1. **Contained Transactions**: One transaction completely contained within another +1. **Adjacent Transactions**: Transactions affecting adjacent byte ranges + +In it's current implementation, TransactionManager only handles Contained Transactions that are trivially sovable. (If a remove transaction completely overlaps with another remove transaction, only the larger one will be kept) + +## Resource Management + +The Transaction Manager enforces two types of limits: + +1. **Transaction Count**: Optional maximum number of transactions +1. **Execution Time**: Optional time limit for transaction processing + +These limits prevent excessive resource usage and allow for early termination of long-running operations. + +## Commit Process + +The commit process applies queued transactions to the codebase: + +1. Transactions are sorted according to priority rules +1. Files are processed one by one +1. For each file, transactions are executed in order +1. Diffs are collected for each modified file +1. The queue is cleared after successful commit + +The diff's are later used during resyc to efficiently update the codebase graph as changes occur. See [Incremental Computation](../6.%20incremental-computation/A.%20Overview.md) for more details. ## Next Step diff --git a/architecture/external/dependency-manager.md b/architecture/external/dependency-manager.md index 071a10526..ed8e42a3d 100644 --- a/architecture/external/dependency-manager.md +++ b/architecture/external/dependency-manager.md @@ -1,6 +1,99 @@ # Dependency Manager -TODO +> WARNING: Dependency manager is an experimental feature designed for Codegen Cloud! The current implementation WILL delete any existing `node_modules` folder! + +## Motivation + +A future goal of Codegen is to support resolving symbols directly from dependencies, instead of falling back to `ExternalModule`s. (In fact, some experimental Codegen features such as [Type Engine](./type-engine.md) already parse and use 3rd party dependencies from `node_modules`) + +This requires us to pull and install dependencies from a repository's `package.json`. However, simply installing dependencies from `package.json` is not enough, as many projects require internal dependencies that use custom NPM registries. Others require custom post-install scripts that may not run on our codemod environments. + +Dependency Manager is an experimental solution to this problem. It creates a shadow tree of `package.json` files that includes all core dependencies and settings from the repository's original `package.json` without any custom registries or potentially problematic settings. + +> NOTE: Currently, this is only implemented for TypeScript projects. + +## Implementation + +Given this example codebase structure: + +``` +repo/ +├── package.json +├── node_modules/ +├── src/ +│ ├── frontend/ +│ │ └── package.json +│ └── backend/ +│ └── package.json +└── tests/ + └── package.json +``` + +Dependency Manager first deletes any existing `node_modules` folder in the user's repository. After this step, Dependency Manager initializes itself to use the correct version of NPM, Yarn, or PNPM for the user's repository. + +Dependency Manager then creates a "shadow copy" of the repository's original `package.json` file. This shadow copy is used to later revert any changes made by Codegen before running codemods. With these steps, the codebase structure now looks like this: + +``` +repo/ +├── package.json +├── package.json.gs_internal.bak +├── src/ +│ ├── frontend/ +│ │ └── package.json +│ │ └── package.json.gs_internal.bak +│ └── backend/ +│ └── package.json +│ └── package.json.gs_internal.bak +└── tests/ + └── package.json + └── package.json.gs_internal.bak +``` + +Next, Dependency Manager iterates through all the `package.json` files and creates a "clean" version of each file. This "clean" version only includes a subset of information from the original, including: + +- Name +- Version +- Package Manager Details +- Workspaces + +Most importantly, this step iterates through `dependencies` and `devDependencies` of each `package.json` file and validates them against the npm registry. If a package is not found, it is added to a list of invalid dependencies and removed from the `package.json` file. + +After this step, the codebase structure now looks like this: + +``` +repo/ +├── package.json (modified) +├── package.json.gs_internal.bak +├── src/ +│ ├── frontend/ +│ │ └── package.json (modified) +│ │ └── package.json.gs_internal.bak +│ └── backend/ +│ └── package.json (modified) +│ └── package.json.gs_internal.bak +└── tests/ + └── package.json (modified) + └── package.json.gs_internal.bak +``` + +After the shadow and cleaning steps, Dependency Manager proceeds to install the user's dependencies through NPM, Yarn, or PNPM, depending on the detected installer type. Finally, Dependency Manager restores the original `package.json` files and removes the shadow copies. + +The final codebase structure looks like this: + +``` +repo/ +├── package.json +├── node_modules/ +├── src/ +│ ├── frontend/ +│ │ └── package.json +│ └── backend/ +│ └── package.json +└── tests/ + └── package.json +``` + +If all goes well, Dependency Manager will have successfully installed the user's dependencies and prepared the codebase for codemods. ## Next Step diff --git a/architecture/external/type-engine.md b/architecture/external/type-engine.md index 54313a82b..42b96f643 100644 --- a/architecture/external/type-engine.md +++ b/architecture/external/type-engine.md @@ -1,6 +1,24 @@ # Type Engine -TODO +Type Engine is an experimental feature of Codegen that leverages the [TypeScript Compiler API](https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API) to provide deeper insight into a user's codebase (such as resolving return types). + +> NOTE: Currently, this is only implemented for TypeScript projects. + +There are currently two experimental implementations of TypeScript's Type Engine: an external process-based implementation and a V8-based implementation. + +## Implementation (External Process) + +During codebase parsing, the Type Engine spawns a type inference subprocess (defined in `src/codegen/sdk/typescript/external/typescript_analyzer/run_full.ts`) that concurrently parses the codebase with the TypeScript API to resolve return types. The final analyzer output is placed in `/tmp/typescript-analysis.json` and is read in by Codegen to resolve return types. + +## Implementation (V8) + +The V8-based implementation is much more flexible and powerful in comparison but is currently not as stable. It uses the [PyMiniRacer](https://github.com/sqreen/py_mini_racer) package to spawn a V8-based JavaScript engine that can parse the codebase with the TypeScript API to resolve return types. + +The entirety of `src/codegen/sdk/typescript/external/typescript_analyzer` is compiled down using [Rollup.js](https://rollupjs.org/) into a single `index.js` file. A couple of patches are applied to the engine source to remove `require` and `export` statements, which are not supported by MiniRacer. + +Then, the entire `index.js` file is loaded into the MiniRacer context. To work around file read limitations with V8, an in-memory shadow filesystem is created that mimics the user's repository's filesystem. These are defined in `fsi.ts` (`FileSystemInterface`) and `fs_proxy.ts` (`ProxyFileSystem`). The TypeScript Compiler then uses the custom `ProxyFileSystem.readFile` function instead of the traditional `fs.readFile`. + +Once the analyzer is initialized and the codebase is parsed, the entire TypeScript Compiler API is available in the MiniRacer context. The analyzer can then be used to resolve return types for any function in the codebase or to parse the codebase and generate a full type analysis. ## Next Step

t-A#t(0L^)UZI|6c9!$m3ny74Alvr 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