diff --git a/typescript-sdk/.gitignore b/typescript-sdk/.gitignore index a581572e3..5c8126db7 100644 --- a/typescript-sdk/.gitignore +++ b/typescript-sdk/.gitignore @@ -41,4 +41,7 @@ yarn-error.log* packages/proto/src/generated # LangGraph API -**/**/.langgraph_api \ No newline at end of file +**/**/.langgraph_api + +# Python +__pycache__/ diff --git a/typescript-sdk/apps/dojo/package.json b/typescript-sdk/apps/dojo/package.json index 61a38af2f..4c47082c7 100644 --- a/typescript-sdk/apps/dojo/package.json +++ b/typescript-sdk/apps/dojo/package.json @@ -16,6 +16,7 @@ "@ag-ui/llamaindex": "workspace:*", "@ag-ui/mastra": "workspace:*", "@ag-ui/middleware-starter": "workspace:*", + "@ag-ui/pydantic-ai": "workspace:*", "@ag-ui/server-starter": "workspace:*", "@ag-ui/server-starter-all-features": "workspace:*", "@ag-ui/vercel-ai-sdk": "workspace:*", diff --git a/typescript-sdk/apps/dojo/src/agents.ts b/typescript-sdk/apps/dojo/src/agents.ts index 859794523..a3bfee205 100644 --- a/typescript-sdk/apps/dojo/src/agents.ts +++ b/typescript-sdk/apps/dojo/src/agents.ts @@ -13,6 +13,7 @@ import { AgnoAgent } from "@ag-ui/agno"; import { LlamaIndexAgent } from "@ag-ui/llamaindex"; import { CrewAIAgent } from "@ag-ui/crewai"; import { mastra } from "./mastra"; +import { PydanticAIAgent } from "@ag-ui/pydantic-ai"; export const agentsIntegrations: AgentIntegrationConfig[] = [ { @@ -23,6 +24,31 @@ export const agentsIntegrations: AgentIntegrationConfig[] = [ }; }, }, + { + id: "pydantic-ai", + agents: async () => { + return { + agentic_chat: new PydanticAIAgent({ + url: "http://localhost:9000/agentic_chat/", + }), + agentic_generative_ui: new PydanticAIAgent({ + url: "http://localhost:9000/agentic_generative_ui/", + }), + human_in_the_loop: new PydanticAIAgent({ + url: "http://localhost:9000/human_in_the_loop/", + }), + predictive_state_updates: new PydanticAIAgent({ + url: "http://localhost:9000/predictive_state_updates/", + }), + shared_state: new PydanticAIAgent({ + url: "http://localhost:9000/shared_state/", + }), + tool_based_generative_ui: new PydanticAIAgent({ + url: "http://localhost:9000/tool_based_generative_ui/", + }), + }; + }, + }, { id: "server-starter", agents: async () => { diff --git a/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/agentic_chat/page.tsx b/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/agentic_chat/page.tsx index 2a9ad9440..dc53a6bd3 100644 --- a/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/agentic_chat/page.tsx +++ b/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/agentic_chat/page.tsx @@ -42,6 +42,10 @@ const Chat = () => { ], handler: ({ background }) => { setBackground(background); + return { + status: "success", + message: `Background changed to ${background}`, + }; }, }); diff --git a/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/agentic_generative_ui/page.tsx b/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/agentic_generative_ui/page.tsx index 120e72231..c44cd0b1f 100644 --- a/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/agentic_generative_ui/page.tsx +++ b/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/agentic_generative_ui/page.tsx @@ -42,7 +42,7 @@ const Chat = () => { return (
-
+
{state.steps.map((step, index) => { if (step.status === "completed") { return ( @@ -55,7 +55,7 @@ const Chat = () => { index === state.steps.findIndex((s) => s.status === "pending") ) { return ( -
+
{step.description}
diff --git a/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/human_in_the_loop/page.tsx b/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/human_in_the_loop/page.tsx index 5b88a1307..0b674d10b 100644 --- a/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/human_in_the_loop/page.tsx +++ b/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/human_in_the_loop/page.tsx @@ -99,6 +99,7 @@ const Chat = () => { }); useCopilotAction({ name: "generate_task_steps", + description: "Generates a list of steps for the user to perform", parameters: [ { name: "steps", diff --git a/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/predictive_state_updates/page.tsx b/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/predictive_state_updates/page.tsx index 78e95c5ed..19061a067 100644 --- a/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/predictive_state_updates/page.tsx +++ b/typescript-sdk/apps/dojo/src/app/[integrationId]/feature/predictive_state_updates/page.tsx @@ -127,6 +127,7 @@ const DocumentEditor = () => { } }, [text]); + // TODO(steve): Remove this when all agents have been updated to use write_document tool. useCopilotAction({ name: "confirm_changes", renderAndWaitForResponse: ({ args, respond, status }) => ( @@ -147,6 +148,40 @@ const DocumentEditor = () => { ), }); + // Action to write the document. + useCopilotAction({ + name: "write_document", + description: `Present the proposed changes to the user for review`, + parameters: [ + { + name: "document", + type: "string", + description: "The full updated document in markdown format", + }, + ], + renderAndWaitForResponse({ args, status, respond }) { + if (status === "executing") { + return ( + { + editor?.commands.setContent(fromMarkdown(currentDocument)); + setAgentState({ document: currentDocument }); + }} + onConfirm={() => { + editor?.commands.setContent(fromMarkdown(agentState?.document || "")); + setCurrentDocument(agentState?.document || ""); + setAgentState({ document: agentState?.document || "" }); + }} + /> + ); + } + return <>; + }, + }); + return (
{placeholderVisible && ( diff --git a/typescript-sdk/apps/dojo/src/menu.ts b/typescript-sdk/apps/dojo/src/menu.ts index 632c9d720..36a378c99 100644 --- a/typescript-sdk/apps/dojo/src/menu.ts +++ b/typescript-sdk/apps/dojo/src/menu.ts @@ -6,6 +6,18 @@ export const menuIntegrations: MenuIntegrationConfig[] = [ name: "Middleware Starter", features: ["agentic_chat"], }, + { + id: "pydantic-ai", + name: "Pydantic AI", + features: [ + "agentic_chat", + "human_in_the_loop", + "agentic_generative_ui", + "tool_based_generative_ui", + "shared_state", + "predictive_state_updates", + ], + }, { id: "server-starter", name: "Server Starter", diff --git a/typescript-sdk/integrations/crewai/python/ag_ui_crewai/examples/predictive_state_updates.py b/typescript-sdk/integrations/crewai/python/ag_ui_crewai/examples/predictive_state_updates.py index f933d52d6..011b399e0 100644 --- a/typescript-sdk/integrations/crewai/python/ag_ui_crewai/examples/predictive_state_updates.py +++ b/typescript-sdk/integrations/crewai/python/ag_ui_crewai/examples/predictive_state_updates.py @@ -16,7 +16,7 @@ WRITE_DOCUMENT_TOOL = { "type": "function", "function": { - "name": "write_document", + "name": "write_document_local", "description": " ".join(""" Write a document. Use markdown formatting to format the document. It's good to format the document extensively so it's easy to read. @@ -63,19 +63,19 @@ async def chat(self): Standard chat node. """ system_prompt = f""" - You are a helpful assistant for writing documents. - To write the document, you MUST use the write_document tool. + You are a helpful assistant for writing documents. + To write the document, you MUST use the write_document_local tool. You MUST write the full document, even when changing only a few words. When you wrote the document, DO NOT repeat it as a message. Just briefly summarize the changes you made. 2 sentences max. This is the current state of the document: ----\n {self.state.document}\n----- """ - # 1. Here we specify that we want to stream the tool call to write_document + # 1. Here we specify that we want to stream the tool call to write_document_local # to the frontend as state. await copilotkit_predict_state({ "document": { - "tool_name": "write_document", + "tool_name": "write_document_local", "tool_argument": "document" } }) @@ -122,7 +122,7 @@ async def chat(self): tool_call_name = tool_call["function"]["name"] tool_call_args = json.loads(tool_call["function"]["arguments"]) - if tool_call_name == "write_document": + if tool_call_name == "write_document_local": self.state.document = tool_call_args["document"] # 4.1 Append the result to the messages in state diff --git a/typescript-sdk/integrations/langgraph/examples/agents/predictive_state_updates/agent.py b/typescript-sdk/integrations/langgraph/examples/agents/predictive_state_updates/agent.py index 325f0014e..8a270f6d1 100644 --- a/typescript-sdk/integrations/langgraph/examples/agents/predictive_state_updates/agent.py +++ b/typescript-sdk/integrations/langgraph/examples/agents/predictive_state_updates/agent.py @@ -18,7 +18,7 @@ WRITE_DOCUMENT_TOOL = { "type": "function", "function": { - "name": "write_document", + "name": "write_document_local", "description": " ".join(""" Write a document. Use markdown formatting to format the document. It's good to format the document extensively so it's easy to read. @@ -64,25 +64,25 @@ async def chat_node(state: AgentState, config: RunnableConfig): """ system_prompt = f""" - You are a helpful assistant for writing documents. - To write the document, you MUST use the write_document tool. + You are a helpful assistant for writing documents. + To write the document, you MUST use the write_document_local tool. You MUST write the full document, even when changing only a few words. - When you wrote the document, DO NOT repeat it as a message. + When you wrote the document, DO NOT repeat it as a message. Just briefly summarize the changes you made. 2 sentences max. This is the current state of the document: ----\n {state.get('document')}\n----- """ # Define the model model = ChatOpenAI(model="gpt-4o") - + # Define config for the model with emit_intermediate_state to stream tool calls to frontend if config is None: config = RunnableConfig(recursion_limit=25) - # Use "predict_state" metadata to set up streaming for the write_document tool + # Use "predict_state" metadata to set up streaming for the write_document_local tool config["metadata"]["predict_state"] = [{ "state_key": "document", - "tool": "write_document", + "tool": "write_document_local", "tool_argument": "document" }] @@ -104,11 +104,11 @@ async def chat_node(state: AgentState, config: RunnableConfig): # Update messages with the response messages = state["messages"] + [response] - + # Extract any tool calls from the response if hasattr(response, "tool_calls") and response.tool_calls: tool_call = response.tool_calls[0] - + # Handle tool_call as a dictionary or an object if isinstance(tool_call, dict): tool_call_id = tool_call["id"] @@ -120,14 +120,14 @@ async def chat_node(state: AgentState, config: RunnableConfig): tool_call_name = tool_call.name tool_call_args = tool_call.args - if tool_call_name == "write_document": + if tool_call_name == "write_document_local": # Add the tool response to messages tool_response = { "role": "tool", "content": "Document written.", "tool_call_id": tool_call_id } - + # Add confirmation tool call confirm_tool_call = { "role": "assistant", @@ -140,9 +140,9 @@ async def chat_node(state: AgentState, config: RunnableConfig): } }] } - + messages = messages + [tool_response, confirm_tool_call] - + # Return Command to route to end return Command( goto=END, @@ -151,7 +151,7 @@ async def chat_node(state: AgentState, config: RunnableConfig): "document": tool_call_args["document"] } ) - + # If no tool was called, go to end return Command( goto=END, diff --git a/typescript-sdk/integrations/langgraph/python/ag_ui_langgraph/examples/agents/predictive_state_updates.py b/typescript-sdk/integrations/langgraph/python/ag_ui_langgraph/examples/agents/predictive_state_updates.py index a7b435741..6aaad5bcb 100644 --- a/typescript-sdk/integrations/langgraph/python/ag_ui_langgraph/examples/agents/predictive_state_updates.py +++ b/typescript-sdk/integrations/langgraph/python/ag_ui_langgraph/examples/agents/predictive_state_updates.py @@ -19,7 +19,7 @@ WRITE_DOCUMENT_TOOL = { "type": "function", "function": { - "name": "write_document", + "name": "write_document_local", "description": " ".join(""" Write a document. Use markdown formatting to format the document. It's good to format the document extensively so it's easy to read. @@ -66,7 +66,7 @@ async def chat_node(state: AgentState, config: RunnableConfig): system_prompt = f""" You are a helpful assistant for writing documents. - To write the document, you MUST use the write_document tool. + To write the document, you MUST use the write_document_local tool. You MUST write the full document, even when changing only a few words. When you wrote the document, DO NOT repeat it as a message. Just briefly summarize the changes you made. 2 sentences max. @@ -80,10 +80,10 @@ async def chat_node(state: AgentState, config: RunnableConfig): if config is None: config = RunnableConfig(recursion_limit=25) - # Use "predict_state" metadata to set up streaming for the write_document tool + # Use "predict_state" metadata to set up streaming for the write_document_local tool config["metadata"]["predict_state"] = [{ "state_key": "document", - "tool": "write_document", + "tool": "write_document_local", "tool_argument": "document" }] @@ -121,7 +121,7 @@ async def chat_node(state: AgentState, config: RunnableConfig): tool_call_name = tool_call.name tool_call_args = tool_call.args - if tool_call_name == "write_document": + if tool_call_name == "write_document_local": # Add the tool response to messages tool_response = { "role": "tool", diff --git a/typescript-sdk/integrations/pydantic-ai/.npmignore b/typescript-sdk/integrations/pydantic-ai/.npmignore new file mode 100644 index 000000000..aaacf1596 --- /dev/null +++ b/typescript-sdk/integrations/pydantic-ai/.npmignore @@ -0,0 +1,12 @@ +.turbo +.DS_Store +.git +.gitignore +.idea +.vscode +.env +__tests__ +src +tsup.config.ts +tsconfig.json +jest.config.js diff --git a/typescript-sdk/integrations/pydantic-ai/README.md b/typescript-sdk/integrations/pydantic-ai/README.md new file mode 100644 index 000000000..695809424 --- /dev/null +++ b/typescript-sdk/integrations/pydantic-ai/README.md @@ -0,0 +1,194 @@ +# Pydantic AI + +Implementation of the AG-UI protocol for [Pydantic AI](https://ai.pydantic.dev/). + +For more information on the Pydantic AI implementation see +the [Pydantic AI AG-UI docs](https://ai.pydantic.dev/ag-ui/). + +## Prerequisites + +This example uses a Pydantic AI agent using an OpenAI model and the AG-UI dojo. + +- An [OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key) + +## Running + +To run this integration you need to: + +1. Clone the [AG-UI repository](https://github.com/ag-ui-protocol/ag-ui) + + ```shell + git clone https://github.com/ag-ui-protocol/ag-ui.git + ``` + +2. Change into the `typescript-sdk/integrations/pydantic-ai` directory + + ```shell + cd typescript-sdk/integrations/pydantic-ai + ``` + +3. Install the `pydantic-ai-examples` package, for example: + + ```shell + pip install pydantic-ai-examples + ``` + + or: + + ```shell + uv venv + uv pip install pydantic-ai-examples + ``` + +4. Run the example dojo server + + ```shell + export OPENAI_API_KEY= + python -m pydantic_ai_examples.ag_ui + ``` + + or: + + ```shell + export OPENAI_API_KEY= + uv run python -m pydantic_ai_examples.ag_ui + ``` + +5. Open another terminal in root directory of the `ag-ui` repository clone +6. Start the integration ag-ui dojo: + + ```shell + cd typescript-sdk + pnpm install && pnpm run dev + ``` + +7. Visit [http://localhost:3000/pydantic-ai](http://localhost:3000/pydantic-ai) +8. Select View `Pydantic AI` from the sidebar + + +## Feature Examples + +### Agentic Chat + +This demonstrates a basic agent interaction including Pydantic AI server side +tools and AG-UI client side tools. + +View the [Agentic Chat example](http://localhost:3000/pydantic-ai/feature/agentic_chat). + +#### Agent Tools + +- `time` - Pydantic AI tool to check the current time for a time zone +- `background` - AG-UI tool to set the background color of the client window + +#### Agent Prompts + +```text +What is the time in New York? +``` + +```text +Change the background to blue +``` + +A complex example which mixes both AG-UI and Pydantic AI tools: + +```text +Perform the following steps, waiting for the response of each step before continuing: +1. Get the time +2. Set the background to red +3. Get the time +4. Report how long the background set took by diffing the two times +``` + +### Agentic Generative UI + +Demonstrates a long running task where the agent sends updates to the frontend +to let the user know what's happening. + +View the [Agentic Generative UI example](http://localhost:3000/pydantic-ai/feature/agentic_generative_ui). + +#### Plan Prompts + +```text +Create a plan for breakfast and execute it +``` + +### Human in the Loop + +Demonstrates simple human in the loop workflow where the agent comes up with a +plan and the user can approve it using checkboxes. + +#### Task Planning Tools + +- `generate_task_steps` - AG-UI tool to generate and confirm steps + +#### Task Planning Prompt + +```text +Generate a list of steps for cleaning a car for me to review +``` + +### Predictive State Updates + +Demonstrates how to use the predictive state updates feature to update the state +of the UI based on agent responses, including user interaction via user +confirmation. + +View the [Predictive State Updates example](http://localhost:3000/pydantic-ai/feature/predictive_state_updates). + +#### Story Tools + +- `write_document` - AG-UI tool to write the document to a window +- `document_predict_state` - Pydantic AI tool that enables document state + prediction for the `write_document` tool + +This also shows how to use custom instructions based on shared state information. + +#### Story Example + +Starting document text + +```markdown +Bruce was a good dog, +``` + +Agent prompt + +```text +Help me complete my story about bruce the dog, is should be no longer than a sentence. +``` + +### Shared State + +Demonstrates how to use the shared state between the UI and the agent. + +State sent to the agent is detected by a function based instruction. This then +validates the data using a custom pydantic model before using to create the +instructions for the agent to follow and send to the client using a AG-UI tool. + +View the [Shared State example](http://localhost:3000/pydantic-ai/feature/shared_state). + +#### Recipe Tools + +- `display_recipe` - AG-UI tool to display the recipe in a graphical format + +#### Recipe Example + +1. Customise the basic settings of your recipe +2. Click `Improve with AI` + +### Tool Based Generative UI + +Demonstrates customised rendering for tool output with used confirmation. + +View the [Tool Based Generative UI example](http://localhost:3000/pydantic-ai/feature/tool_based_generative_ui). + +#### Haiku Tools + +- `generate_haiku` - AG-UI tool to display a haiku in English and Japanese + +#### Haiku Prompt + +```text +Generate a haiku about formula 1 +``` diff --git a/typescript-sdk/integrations/pydantic-ai/jest.config.js b/typescript-sdk/integrations/pydantic-ai/jest.config.js new file mode 100644 index 000000000..0521f8d91 --- /dev/null +++ b/typescript-sdk/integrations/pydantic-ai/jest.config.js @@ -0,0 +1,10 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + testMatch: ["**/*.test.ts"], + passWithNoTests: true, + moduleNameMapper: { + "^@/(.*)$": "/src/$1", + }, +}; diff --git a/typescript-sdk/integrations/pydantic-ai/package.json b/typescript-sdk/integrations/pydantic-ai/package.json new file mode 100644 index 000000000..a5be4e338 --- /dev/null +++ b/typescript-sdk/integrations/pydantic-ai/package.json @@ -0,0 +1,35 @@ +{ + "name": "@ag-ui/pydantic-ai", + "author": "Steven Hartland ", + "version": "0.0.1", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "sideEffects": false, + "files": [ + "dist/**" + ], + "scripts": { + "build": "tsup", + "dev": "tsup --watch", + "clean": "rm -rf dist .turbo node_modules", + "typecheck": "tsc --noEmit", + "test": "jest", + "link:global": "pnpm link --global", + "unlink:global": "pnpm unlink --global" + }, + "dependencies": { + "@ag-ui/client": "workspace:*" + }, + "peerDependencies": { + "rxjs": "7.8.1" + }, + "devDependencies": { + "@types/jest": "^29.5.14", + "@types/node": "^20.11.19", + "jest": "^29.7.0", + "ts-jest": "^29.1.2", + "tsup": "^8.0.2", + "typescript": "^5.3.3" + } +} diff --git a/typescript-sdk/integrations/pydantic-ai/src/index.ts b/typescript-sdk/integrations/pydantic-ai/src/index.ts new file mode 100644 index 000000000..f3a3190a8 --- /dev/null +++ b/typescript-sdk/integrations/pydantic-ai/src/index.ts @@ -0,0 +1,3 @@ +import { HttpAgent } from "@ag-ui/client"; + +export class PydanticAIAgent extends HttpAgent {} diff --git a/typescript-sdk/integrations/pydantic-ai/tsconfig.json b/typescript-sdk/integrations/pydantic-ai/tsconfig.json new file mode 100644 index 000000000..d12ec063d --- /dev/null +++ b/typescript-sdk/integrations/pydantic-ai/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "esnext", + "lib": ["dom", "dom.iterable", "esnext"], + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "moduleResolution": "node", + "skipLibCheck": true, + "strict": true, + "jsx": "react-jsx", + "esModuleInterop": true, + "resolveJsonModule": true, + "isolatedModules": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + "stripInternal": true + }, + "include": ["src"], + "exclude": ["node_modules", "dist"] +} diff --git a/typescript-sdk/integrations/pydantic-ai/tsup.config.ts b/typescript-sdk/integrations/pydantic-ai/tsup.config.ts new file mode 100644 index 000000000..12b69b8fb --- /dev/null +++ b/typescript-sdk/integrations/pydantic-ai/tsup.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + format: ["cjs", "esm"], + dts: true, + splitting: false, + sourcemap: true, + clean: true, + minify: true, +}); diff --git a/typescript-sdk/integrations/server-starter-all-features/server/python/example_server/predictive_state_updates.py b/typescript-sdk/integrations/server-starter-all-features/server/python/example_server/predictive_state_updates.py index 2eeb072ff..6496d5d9c 100644 --- a/typescript-sdk/integrations/server-starter-all-features/server/python/example_server/predictive_state_updates.py +++ b/typescript-sdk/integrations/server-starter-all-features/server/python/example_server/predictive_state_updates.py @@ -80,7 +80,7 @@ def make_story(name: str) -> str: async def send_tool_call_events(): """Send tool call events with predictive state and incremental story generation""" tool_call_id = str(uuid.uuid4()) - tool_call_name = "write_document" + tool_call_name = "write_document_local" # Generate a random story story = make_story(random.choice(dog_names)) @@ -93,13 +93,13 @@ async def send_tool_call_events(): value=[ { "state_key": "document", - "tool": "write_document", + "tool": "write_document_local", "tool_argument": "document" } ] ) - # First tool call: write_document + # First tool call: write_document_local yield ToolCallStartEvent( type=EventType.TOOL_CALL_START, tool_call_id=tool_call_id, diff --git a/typescript-sdk/pnpm-lock.yaml b/typescript-sdk/pnpm-lock.yaml index 22a2e7225..a42d98c4b 100644 --- a/typescript-sdk/pnpm-lock.yaml +++ b/typescript-sdk/pnpm-lock.yaml @@ -96,6 +96,9 @@ importers: '@ag-ui/proto': specifier: workspace:* version: 0.0.30 + '@ag-ui/pydantic-ai': + specifier: workspace:* + version: link:../../integrations/pydantic-ai '@ag-ui/server-starter': specifier: workspace:* version: link:../../integrations/server-starter @@ -473,6 +476,34 @@ importers: specifier: ^5.3.3 version: 5.8.2 + integrations/pydantic-ai: + dependencies: + '@ag-ui/client': + specifier: workspace:* + version: link:../../packages/client + rxjs: + specifier: 7.8.1 + version: 7.8.1 + devDependencies: + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 + '@types/node': + specifier: ^20.11.19 + version: 20.17.50 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.17.50) + ts-jest: + specifier: ^29.1.2 + version: 29.3.4(@babel/core@7.27.1)(@jest/transform@30.0.4)(@jest/types@30.0.1)(babel-jest@30.0.4(@babel/core@7.27.1))(esbuild@0.25.4)(jest@29.7.0(@types/node@20.17.50))(typescript@5.8.2) + tsup: + specifier: ^8.0.2 + version: 8.5.0(jiti@2.4.2)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.2)(yaml@2.8.0) + typescript: + specifier: ^5.3.3 + version: 5.8.2 + integrations/server-starter: dependencies: '@ag-ui/client':