diff --git a/README.md b/README.md index f9c91cd..a760c6d 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,21 @@ const client = new NutrientClient({ }); ``` +## Framework Quickstarts + +Framework wiring examples are available in `examples/src/`: + +- `framework_openai_agents.mjs` +- `framework_langchain.mjs` +- `framework_crewai_scope.md` (CrewAI scope note for TypeScript users) + +Syntax-check commands: + +```bash +node --check examples/src/framework_openai_agents.mjs +node --check examples/src/framework_langchain.mjs +``` + ### Working with URLs Most methods accept URLs directly. The URL is passed to the server, which fetches the content—this avoids SSRF vulnerabilities since the client never fetches URLs itself. diff --git a/examples/README.md b/examples/README.md index 52047f5..e9209d9 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,6 +8,9 @@ This example project demonstrates how to use the Nutrient DWS TypeScript Client - `src/` - Contains TypeScript source files - `direct_method.ts` - Examples using direct method calls - `workflow.ts` - Examples using the workflow builder pattern + - `framework_openai_agents.mjs` - OpenAI Agents integration sketch + - `framework_langchain.mjs` - LangChain integration sketch + - `framework_crewai_scope.md` - CrewAI scope note for TypeScript users - `output/` - Directory where processed files will be saved - `.env.example` - Example environment variables file @@ -89,6 +92,31 @@ This will: 3. Extract text with JSON output 4. Execute a complex multi-step workflow +### Framework Examples + +To run framework integration sketches: + +Install optional framework dependencies first: + +```bash +npm install @openai/agents @langchain/openai @langchain/core zod +``` + +```bash +node src/framework_openai_agents.mjs +node src/framework_langchain.mjs +``` + +Syntax-check: + +```bash +node --check src/framework_openai_agents.mjs +node --check src/framework_langchain.mjs +``` + +CrewAI note: +- CrewAI is Python-native. See `src/framework_crewai_scope.md` for a recommended bridge pattern when your app stack is TypeScript-first. + ## Output All processed files will be saved to the `output/` directory. You can examine these files to see the results of the document processing operations. diff --git a/examples/src/framework_crewai_scope.md b/examples/src/framework_crewai_scope.md new file mode 100644 index 0000000..b5ecb25 --- /dev/null +++ b/examples/src/framework_crewai_scope.md @@ -0,0 +1,23 @@ +# CrewAI Scope Note (TypeScript Repository) + +CrewAI is currently Python-native. This TypeScript client repo does not provide a first-party CrewAI TypeScript SDK path. + +## Recommended Pattern + +1. Run CrewAI orchestration in a Python service. +2. Call Nutrient DWS through one of these options: +- Python service uses `nutrient-dws-client-python`, or +- Python service calls your TypeScript app endpoint that wraps `@nutrient-sdk/dws-client-typescript`. +3. Return processed artifact metadata (output path, pages, extraction results) back to the TypeScript app. + +## Minimal Bridge Sketch + +```python +# Python CrewAI worker (separate service) +from crewai import Agent, Crew, Task + +# Inside task execution, call your TypeScript endpoint: +# POST /api/dws/process { "operation": "extract_text", "path": "input.pdf" } +``` + +This keeps CrewAI orchestration explicit while preserving a TypeScript-first application surface. diff --git a/examples/src/framework_langchain.mjs b/examples/src/framework_langchain.mjs new file mode 100644 index 0000000..acb917b --- /dev/null +++ b/examples/src/framework_langchain.mjs @@ -0,0 +1,59 @@ +import "dotenv/config"; +import { NutrientClient } from "@nutrient-sdk/dws-client-typescript"; +import { ChatOpenAI } from "@langchain/openai"; +import { tool } from "@langchain/core/tools"; +import { z } from "zod"; + +const nutrientApiKey = process.env.NUTRIENT_API_KEY; +if (!nutrientApiKey) { + throw new Error("Missing NUTRIENT_API_KEY. Add it to examples/.env before running."); +} + +if (!process.env.OPENAI_API_KEY) { + throw new Error("Missing OPENAI_API_KEY. Add it to examples/.env before running."); +} + +const client = new NutrientClient({ + apiKey: nutrientApiKey, +}); + +const redactEmails = tool( + async ({ path }) => { + const response = await client.createRedactionsPreset(path, "email-address", "apply"); + return JSON.stringify(response); + }, + { + name: "redact_emails", + description: "Redact email addresses from a document via Nutrient DWS.", + schema: z.object({ + path: z.string().describe("Local path to the input PDF file."), + }), + } +); + +async function main() { + const model = new ChatOpenAI({ + model: "gpt-4.1-mini", + apiKey: process.env.OPENAI_API_KEY, + }); + + const response = await model.bindTools([redactEmails]).invoke( + "Redact email addresses from ./assets/sample.pdf and summarize next steps." + ); + + if (response.tool_calls?.length) { + for (const call of response.tool_calls) { + if (call.name === "redact_emails") { + const args = + typeof call.args === "object" && call.args !== null ? call.args : {}; + const toolResult = await redactEmails.invoke(args); + console.log(toolResult); + return; + } + } + } + + console.log(response.content); +} + +void main(); diff --git a/examples/src/framework_openai_agents.mjs b/examples/src/framework_openai_agents.mjs new file mode 100644 index 0000000..5a60e9e --- /dev/null +++ b/examples/src/framework_openai_agents.mjs @@ -0,0 +1,48 @@ +import "dotenv/config"; +import { NutrientClient } from "@nutrient-sdk/dws-client-typescript"; +import { Agent, Runner, tool } from "@openai/agents"; + +const nutrientApiKey = process.env.NUTRIENT_API_KEY; +if (!nutrientApiKey) { + throw new Error("Missing NUTRIENT_API_KEY. Add it to examples/.env before running."); +} + +if (!process.env.OPENAI_API_KEY) { + throw new Error("Missing OPENAI_API_KEY. Add it to examples/.env before running."); +} + +const client = new NutrientClient({ + apiKey: nutrientApiKey, +}); + +const extractText = tool({ + name: "extract_text", + description: "Extract text from a document using Nutrient DWS.", + parameters: { + type: "object", + properties: { + path: { type: "string" }, + }, + required: ["path"], + }, + async execute(input) { + const result = await client.extractText(input.path); + return JSON.stringify(result); + }, +}); + +const agent = new Agent({ + name: "nutrient-openai-agents-typescript", + instructions: "Use tools to process documents and summarize outcomes.", + tools: [extractText], +}); + +async function main() { + const run = await Runner.run( + agent, + "Extract text from ./assets/sample.pdf and summarize key points." + ); + console.log(run.finalOutput); +} + +void main();