diff --git a/packages/core/README.md b/packages/core/README.md index b8c5da7..01f8c0b 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -7,6 +7,7 @@ Orchestrate complex, long-running coding tasks to an ephemeral cloud environment ## Examples - [Basic Session](./examples/basic-session/README.md) +- [Database Triggers](./examples/database-triggers/README.md) - [Advanced Session](./examples/advanced-session/README.md) - [Agent Workflow](./examples/agent/README.md) - [Webhook Integration](./examples/webhook/README.md) diff --git a/packages/core/examples/custom-mcp-server/index.ts b/packages/core/examples/custom-mcp-server/index.ts old mode 100644 new mode 100755 diff --git a/packages/core/examples/database-triggers/README.md b/packages/core/examples/database-triggers/README.md new file mode 100644 index 0000000..2500d16 --- /dev/null +++ b/packages/core/examples/database-triggers/README.md @@ -0,0 +1,48 @@ +# Database Triggers Example + +This example demonstrates how to listen to PostgreSQL database events (using `LISTEN` / `NOTIFY`) and automatically trigger a Jules session when an event occurs. + +This pattern is highly useful for event-driven workflows, such as automatically generating or refactoring code when schema definitions change or synchronizing state with an AI agent. + +## Prerequisites + +- Ensure you have [Bun](https://bun.sh/) installed, or another compatible runtime like Node.js. +- Ensure you have a running PostgreSQL database (e.g., local, Supabase, or ElephantSQL). +- Ensure your `JULES_API_KEY` is set as an environment variable. + +## Setup & Running the Example + +1. Start your local database or get your PostgreSQL connection string. Set the environment variable if you aren't using a default local Postgres instance: + + ```bash + export DATABASE_URL=postgres://user:password@localhost:5432/my_database + ``` + +2. Install dependencies: + + ```bash + bun install + ``` + +3. Run the script: + + ```bash + bun run index.ts + ``` + + The script will connect to the database and start listening to the `user_updates` channel. + +4. Trigger a notification from PostgreSQL: + + Connect to your database via `psql` (or another SQL client) and execute the following SQL command to simulate a trigger event: + + ```sql + NOTIFY user_updates, '{"event": "user_created", "id": 123, "email": "newuser@example.com"}'; + ``` + +5. The terminal running `index.ts` will capture the event, log it, and start a new Jules session. + +## Notes + +- In a real-world application, you would attach a PostgreSQL `TRIGGER` to a table, which calls a function that performs the `pg_notify` automatically when rows are `INSERT`, `UPDATE`, or `DELETE`. +- You can adapt the `source` in `index.ts` to attach the agent to a specific GitHub repository instead of running a Repoless session. diff --git a/packages/core/examples/database-triggers/index.ts b/packages/core/examples/database-triggers/index.ts new file mode 100644 index 0000000..98fa2e0 --- /dev/null +++ b/packages/core/examples/database-triggers/index.ts @@ -0,0 +1,66 @@ +import { Client } from 'pg'; +import { jules } from '@google/jules-sdk'; + +/** + * Example demonstrating how to listen to a PostgreSQL database trigger/event using LISTEN/NOTIFY + * and trigger a Jules session when an event occurs. + */ +async function main() { + // Use connection string from environment variables, or a default one for local development + const connectionString = + process.env.DATABASE_URL || 'postgres://postgres:postgres@localhost:5432/postgres'; + + const client = new Client({ connectionString }); + + try { + console.log(`Connecting to database at ${connectionString}...`); + await client.connect(); + console.log('Connected.'); + + // Listen to a specific channel (e.g., 'user_updates') + const channelName = 'user_updates'; + await client.query(`LISTEN ${channelName}`); + console.log(`Listening for notifications on channel: ${channelName}`); + + // Handle incoming notifications + client.on('notification', async (msg) => { + console.log(`Received notification on ${msg.channel}:`, msg.payload); + + try { + let parsedPayload = msg.payload ? JSON.parse(msg.payload) : {}; + + console.log('Creating Jules session for event...'); + + // Create a new Jules session + const session = await jules.session({ + prompt: `Process the following database event: ${JSON.stringify(parsedPayload, null, 2)} + + **Instructions** + 1. Analyze the change. + 2. Update relevant systems or code based on the new data.`, + + // Using a repoless session for this example, or provide a source + // source: { github: 'your-org/your-repo', baseBranch: 'main' }, + }); + + console.log(`Successfully created Jules session: ${session.id}`); + + } catch (err) { + console.error('Error handling notification or creating session:', err); + } + }); + + // Keep the process alive + process.on('SIGINT', async () => { + console.log('Closing database connection...'); + await client.end(); + process.exit(0); + }); + + } catch (error) { + console.error('Error connecting to database:', error); + process.exit(1); + } +} + +main(); diff --git a/packages/core/examples/database-triggers/package.json b/packages/core/examples/database-triggers/package.json new file mode 100644 index 0000000..7791b64 --- /dev/null +++ b/packages/core/examples/database-triggers/package.json @@ -0,0 +1,18 @@ +{ + "name": "database-triggers", + "version": "1.0.0", + "description": "Example demonstrating how to trigger a Jules session from a database trigger or event stream.", + "main": "index.ts", + "type": "module", + "scripts": { + "start": "bun run index.ts" + }, + "dependencies": { + "@google/jules-sdk": "workspace:*", + "pg": "^8.11.3" + }, + "devDependencies": { + "@types/pg": "^8.11.2", + "bun-types": "^1.1.8" + } +}