Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
636 changes: 622 additions & 14 deletions bun.lock

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ Orchestrate complex, long-running coding tasks to an ephemeral cloud environment
## Examples

- [Basic Session](./examples/basic-session/README.md)
- [Google Docs Context](./examples/google-docs/README.md)
- [MCP Plan Generation](./examples/mcp-plan-generation/README.md)
- [Database Triggers](./examples/database-triggers/README.md)
- [File System Events](./examples/file-system-events/README.md)
- [Hono Integration](./examples/hono/README.md)
- [Express Integration](./examples/express/README.md)
- [Stitch Integration](./examples/stitch/README.md)
- [Cron Jobs](./examples/cron-jobs/README.md)
- [Advanced Session](./examples/advanced-session/README.md)
- [Agent Workflow](./examples/agent/README.md)
- [Webhook Integration](./examples/webhook/README.md)
Expand Down
39 changes: 39 additions & 0 deletions packages/core/examples/cron-jobs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Cron Jobs Example

This example demonstrates how to trigger a Jules session from a scheduled cron job using [node-cron](https://www.npmjs.com/package/node-cron).

This approach is highly useful for scheduling automated tasks such as:
- Nightly code reviews.
- Scheduled repo cleanups.
- Regular synchronization tasks.

## Prerequisites

- Ensure you have [Bun](https://bun.sh/) installed, or another compatible runtime like Node.js.
- Ensure your `JULES_API_KEY` is set as an environment variable.

## Running the Example

1. Navigate to the example directory and install dependencies:

```bash
bun install
```

2. Start the scheduled cron job. By default, the script triggers a repoless session every minute.

```bash
export JULES_API_KEY="your-api-key"
bun run start
```

3. The script will output its progress to the console every minute as the cron job fires and starts a session. You can stop it at any time using `Ctrl+C`.

## Customizing

You can modify the cron schedule in `index.ts` to suit your needs:

```typescript
// Example: run every night at midnight
cron.schedule('0 0 * * *', runTask);
```
78 changes: 78 additions & 0 deletions packages/core/examples/cron-jobs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { jules } from '@google/jules-sdk';
import cron from 'node-cron';

/**
* Cron Jobs Example
*
* Demonstrates how to trigger a Jules session from a scheduled cron job using `node-cron`.
* This can be useful for regular tasks such as running a daily review or nightly automation script.
*/
async function runTask() {
console.log(`[${new Date().toISOString()}] Cron job triggered! Creating a Jules session...`);

try {
// For demonstration, we run a repoless session generating a simple joke.
// In a real-world scenario, you might pass a source repo and specific automation instructions.
const session = await jules.session({
prompt: 'Write a short programmer joke.',
});

console.log(`Session created! ID: ${session.id}`);
console.log('Waiting for the session to complete...');

const outcome = await session.result();

console.log('\n--- Session Result ---');
console.log(`State: ${outcome.state}`);

if (outcome.state === 'completed') {
const activities = await jules.select({
from: 'activities',
where: { type: 'agentMessaged', 'session.id': session.id },
order: 'desc',
limit: 1,
});

if (activities.length > 0) {
console.log('\nAgent Response:');
console.log(activities[0].message);
} else {
const files = outcome.generatedFiles();
if (files.size > 0) {
console.log('\nGenerated Files:');
for (const [filename, content] of files.entries()) {
console.log(`\nFile: ${filename}`);
console.log(content.content);
}
} else {
console.log('\nThe agent did not leave a final message or file.');
}
}
} else {
console.error('The session did not complete successfully.');
}
} catch (error) {
console.error('An error occurred during the scheduled session:', error);
}
}

function main() {
if (!process.env.JULES_API_KEY) {
console.error('Error: JULES_API_KEY environment variable is not set.');
console.error('Please set it using: export JULES_API_KEY="your-api-key"');
process.exit(1);
}

// Schedule a task to run every minute for demonstration purposes.
// The cron expression '* * * * *' means "every minute".
console.log('Starting cron job scheduler. It will trigger every minute...');
console.log('Press Ctrl+C to exit.');

cron.schedule('* * * * *', () => {
// Avoid unhandled promise rejections by wrapping the async call in a catch block if needed
// However, runTask has its own try/catch block.
runTask();
});
}

main();
17 changes: 17 additions & 0 deletions packages/core/examples/cron-jobs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "cron-jobs",
"version": "1.0.0",
"description": "Example demonstrating how to trigger a Jules session via a scheduled cron job.",
"type": "module",
"main": "index.ts",
"scripts": {
"start": "bun run index.ts"
},
"dependencies": {
"@google/jules-sdk": "workspace:*",
"node-cron": "^4.2.1"
},
"devDependencies": {
"bun-types": "^1.1.8"
}
}
Empty file modified packages/core/examples/custom-mcp-server/index.ts
100644 → 100755
Empty file.
48 changes: 48 additions & 0 deletions packages/core/examples/database-triggers/README.md
Original file line number Diff line number Diff line change
@@ -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.
66 changes: 66 additions & 0 deletions packages/core/examples/database-triggers/index.ts
Original file line number Diff line number Diff line change
@@ -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();
18 changes: 18 additions & 0 deletions packages/core/examples/database-triggers/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
52 changes: 52 additions & 0 deletions packages/core/examples/express/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Express Integration Example

This example demonstrates how to integrate the Jules SDK into an Express application.

It covers a common pattern for starting Jules sessions from a REST API endpoint.

## Prerequisites

- A Jules API Key (`JULES_API_KEY` environment variable).

## How to use in your Express app

You can use the `POST /api/jules` endpoint pattern from `index.ts` to create a REST endpoint for your Express application to trigger Jules sessions.

```typescript
import express, { Request, Response } from 'express';
import { jules } from '@google/jules-sdk';

const app = express();
app.use(express.json());

app.post('/api/jules', async (req: Request, res: Response) => {
try {
const { githubUrl, taskDescription } = req.body;

const session = await jules.session({
prompt: taskDescription,
source: { github: githubUrl },
});

return res.status(200).json({ sessionId: session.id });
} catch (error) {
return res.status(500).json({ error: 'Internal Server Error' });
}
});
```

## Running the Example Locally

The `index.ts` file includes a runnable test script to verify that the Express endpoint works as expected.

Ensure you have your API key set:

```bash
export JULES_API_KEY="your-api-key-here"
```

Then, you can run the file using `bun` (or another runner like `tsx`):

```bash
bun run index.ts
```
Loading
Loading