diff --git a/agent-reactflow/.gitignore b/agent-reactflow/.gitignore new file mode 100644 index 0000000..96fab4f --- /dev/null +++ b/agent-reactflow/.gitignore @@ -0,0 +1,38 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# Dependencies +node_modules +.pnp +.pnp.js + +# Local env files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Testing +coverage + +# Turbo +.turbo + +# Vercel +.vercel + +# Build Outputs +.next/ +out/ +build +dist + + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Misc +.DS_Store +*.pem diff --git a/agent-reactflow/.vscode/settings.json b/agent-reactflow/.vscode/settings.json new file mode 100644 index 0000000..44a73ec --- /dev/null +++ b/agent-reactflow/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "eslint.workingDirectories": [ + { + "mode": "auto" + } + ] +} diff --git a/agent-reactflow/Dockerfile b/agent-reactflow/Dockerfile new file mode 100644 index 0000000..606d030 --- /dev/null +++ b/agent-reactflow/Dockerfile @@ -0,0 +1,69 @@ +# ============ +# Base stage +# ============ +FROM node:20-bullseye-slim AS base +# Use the official Node 20 image based on bullseye slim. +# This stage serves as the base image for all subsequent stages. + +# ============ +# Builder stage +# ============ +FROM base AS builder + +WORKDIR /app + +# Install Turbo globally as it is needed during the build. +RUN npm install -g turbo@2.4.4 + +# Copy all application source code. +COPY . . + +# Prune the workspace to only include the necessary scopes. +RUN turbo prune --docker --scope @agent-reactflow/backend + +# ============ +# Installer stage +# ============ +FROM base AS installer + +WORKDIR /app + +# Update the certificate store in this Debian-based stage. +RUN apt-get update && \ + apt-get install -y ca-certificates && \ + update-ca-certificates + +RUN npm install -g pnpm@10.6.1 && \ + npm install -g turbo@2.4.4 + +# Copy pre-pruned dependency files from the builder stage. +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml + +# Install dependencies. +RUN pnpm install + +# Copy the full application and build it. +COPY --from=builder /app/out/full/ . +RUN pnpm build + +# ============ +# Final Runner stage +# ============ +FROM node:20-alpine AS runner + +WORKDIR /app + +# Copy the production-ready built application from the installer stage. +COPY --from=installer /app . + +# Install only runtime packages. Here we install curl and ca-certificates, +# then update the certificate store for secure TLS connections. +RUN npm install -g pnpm@10.6.1 && \ + apk add --no-cache curl ca-certificates && update-ca-certificates + +# Start the application using pnpm. +CMD ["pnpm", "start"] + +# # Dummy shell for troubleshooting +# CMD ["sh"] \ No newline at end of file diff --git a/agent-reactflow/README.md b/agent-reactflow/README.md new file mode 100644 index 0000000..a731269 --- /dev/null +++ b/agent-reactflow/README.md @@ -0,0 +1,37 @@ +# Agent with React Flow + +A sample repository to have low code editor with React Flow of Agents built with Restack. + +### Apps + +- `frontend`: another [Next.js](https://nextjs.org/) app +- `backend`: a [Restack](https://restack.io/) app + +## Requirements + +- **Node 20+** +- **pnpm** (recommended) + +## Start Restack + +To start Restack, use the following Docker command: + +```bash +docker run -d --pull always --name restack -p 5233:5233 -p 6233:6233 -p 7233:7233 -p 9233:9233 ghcr.io/restackio/restack:main +``` + +## Install dependencies and start services + +```bash +pnpm i +pnpm run dev +``` + +Leveraging turborepo, this will start both frontend and backend. +Your code will be running and syncing with Restack to execute agents. + +## Run agents + +### from frontend + + \ No newline at end of file diff --git a/agent-reactflow/agent-reactflow.png b/agent-reactflow/agent-reactflow.png new file mode 100644 index 0000000..9be5cbc Binary files /dev/null and b/agent-reactflow/agent-reactflow.png differ diff --git a/agent-reactflow/apps/backend/.env.example b/agent-reactflow/apps/backend/.env.example new file mode 100644 index 0000000..75dbb88 --- /dev/null +++ b/agent-reactflow/apps/backend/.env.example @@ -0,0 +1,10 @@ + +# For inference +OPENAI_API_KEY= + +# For Restack Cloud deployment +RESTACK_ENGINE_ID= +RESTACK_ENGINE_ADDRESS= +RESTACK_ENGINE_API_KEY= +RESTACK_ENGINE_API_ADDRESS= + diff --git a/agent-reactflow/apps/backend/.gitignore b/agent-reactflow/apps/backend/.gitignore new file mode 100644 index 0000000..65e7c43 --- /dev/null +++ b/agent-reactflow/apps/backend/.gitignore @@ -0,0 +1,4 @@ +.env +node_modules +media +dist \ No newline at end of file diff --git a/agent-reactflow/apps/backend/Dockerfile b/agent-reactflow/apps/backend/Dockerfile new file mode 100644 index 0000000..2417164 --- /dev/null +++ b/agent-reactflow/apps/backend/Dockerfile @@ -0,0 +1,40 @@ +# ------- Image ---------- + +FROM node:20-bullseye-slim AS installer + +RUN apt-get update \ + && apt-get install -y ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +COPY ./package.json ./app/package.json +COPY ./tsconfig.json ./app/tsconfig.json + + +WORKDIR /app + +RUN npm install + +# ------- Builder ---------- + +FROM node:20-bullseye-slim AS builder +WORKDIR /app +COPY --from=installer /app . +COPY ./src ./src + +RUN npm run build + +# ------- Runner ---------- + +FROM node:20-bullseye-slim AS runner + +RUN addgroup --system --gid 1001 service +RUN adduser --system --uid 1001 service +USER service + +WORKDIR /app + +COPY --from=builder /app . + +ENV NODE_OPTIONS=”--max-old-space-size=4096″ + +CMD ["node", "dist/services"] \ No newline at end of file diff --git a/agent-reactflow/apps/backend/eventAgent.ts b/agent-reactflow/apps/backend/eventAgent.ts new file mode 100644 index 0000000..4c4cfdf --- /dev/null +++ b/agent-reactflow/apps/backend/eventAgent.ts @@ -0,0 +1,38 @@ +import { client } from "./src/client"; + +export type EventInput = { + agentId: string; + runId: string; +}; + +async function eventAgent(input: EventInput) { + try { + await client.sendAgentEvent({ + event: { + name: "flowEvent", + input: { name: "idVerification", input: { type: "id", documentNumber: "1234567890" } }, + }, + agent: { + agentId: input.agentId, + runId: input.runId, + }, + }); + + // await client.sendAgentEvent({ + // event: { + // name: "end", + // }, + // agent: { + // agentId: input.agentId, + // runId: input.runId, + // }, + // }); + + process.exit(0); // Exit the process successfully + } catch (error) { + console.error("Error sending event to agent:", error); + process.exit(1); // Exit the process with an error code + } +} + +eventAgent({"agentId":"1743008631706-agentFlow","runId":"0195d369-0b9d-7ded-ab82-20e275e295da"}); diff --git a/agent-reactflow/apps/backend/index.html b/agent-reactflow/apps/backend/index.html new file mode 100644 index 0000000..2333578 --- /dev/null +++ b/agent-reactflow/apps/backend/index.html @@ -0,0 +1,289 @@ + + + + +
+ + +{exportToJson()}
+ {message.content}
+Updating flow...
+
+ {JSON.stringify(part.toolInvocation, null, 2)}
+
+
+ {JSON.stringify(part.toolInvocation.result.flow, null, 2)}
+
+
+ {JSON.stringify({agentId, runId}, null, 2)}
+ {workflow.id}
+Response
+{JSON.stringify(workflow.response, null, 2)}
+ Raw Response
+{JSON.stringify(workflow.rawResponse, null, 2)}
+ {JSON.stringify(testResult.results, null, 2)}
+ {sourceHandleId}
+