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
93 changes: 92 additions & 1 deletion bun.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
},
"workspaces": [
"packages/*",
"packages/core/examples/*",
"examples/*"
],
"description": "Official Jules TypeScript SDK",
Expand Down
8 changes: 8 additions & 0 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

Orchestrate complex, long-running coding tasks to an ephemeral cloud environment integrated with a GitHub repo.

## Examples

- [Basic Session](./examples/basic-session/README.md)
- [Advanced Session](./examples/advanced-session/README.md)
- [Agent Workflow](./examples/agent/README.md)
- [Webhook Integration](./examples/webhook/README.md)
- [GitHub Actions](./examples/github-actions/README.md)

## Send work to a Cloud based session

```ts
Expand Down
14 changes: 14 additions & 0 deletions packages/core/examples/advanced-session/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Advanced Session Example

This example demonstrates how to use the Jules SDK to run a session, interact with it, wait for plan approvals, and monitor stream progress while parsing the output for artifacts.

## Running

Ensure you have your `JULES_API_KEY` set.
You can run the script via:

```sh
bun run index.ts
```

This will run the advanced session and stream activities.
81 changes: 81 additions & 0 deletions packages/core/examples/advanced-session/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { jules, JulesError } from '@google/jules-sdk';

/**
* Advanced Session Example
*
* Demonstrates:
* - Interactive session creation
* - Waiting for plan approval
* - Monitoring progress via reactive streams
* - Handling code diffs (changeSet)
*/
async function runAdvancedSession() {
try {
console.log('Starting advanced session...');

// Interactive Sessions allow you to provide feedback and guide the process
const session = await jules.session({
prompt: `Create a simple python script that prints 'Hello Advanced Session!' and test it.`,
// For a repoless session, we don't provide a source
});

console.log(`Session created: ${session.id}`);

// Wait for the plan to be generated and ready for approval
console.log('Waiting for plan approval...');
await session.waitFor('awaitingPlanApproval');

console.log('Plan is ready. Approving it now.');
await session.approve();

// Stream activities and artifacts
for await (const activity of session.stream()) {
switch (activity.type) {
case 'planGenerated':
console.log(
'Plan:',
activity.plan?.steps.map((s) => s.title)
);
break;
case 'agentMessaged':
console.log('Agent says:', activity.message);
break;
case 'progressUpdated':
console.log(`Progress: ${activity.title}`);
break;
case 'sessionCompleted':
console.log('Session complete!');
break;
}

// Check artifacts
for (const artifact of activity.artifacts ?? []) {
if (artifact.type === 'bashOutput') {
console.log(`[BASH] ${artifact.toString()}`);
}
if (artifact.type === 'changeSet') {
const parsed = artifact.parsed();
for (const file of parsed.files) {
console.log(
`[DIFF] ${file.path}: +${file.additions} -${file.deletions}`
);
}
}
}
}

const outcome = await session.result();
console.log(`Session finished with state: ${outcome.state}`);

} catch (error) {
if (error instanceof JulesError) {
console.error(`SDK error: ${error.message}`);
} else {
console.error('Unknown error:', error);
}
}
}

if (require.main === module) {
runAdvancedSession();
}
65 changes: 65 additions & 0 deletions packages/core/examples/agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Agent Workflow Example

This example demonstrates how to use the `jules.all()` API to create an AI agent workflow that manages multiple tasks concurrently. It orchestrates complex, long-running coding tasks to an ephemeral cloud environment.

## Overview

The example runs multiple prompts in parallel using `jules.all()`:

1. Analyzing a repository for improvements.
2. Writing an automation script.
3. Suggesting test cases.

It demonstrates how to configure concurrency, handle errors without stopping the whole process, and process the results (like reading generated files) from each session.

## Prerequisites

- Node.js or Bun installed.
- A Jules API Key. Set it using:
```bash
export JULES_API_KEY=<your-api-key>
```

## Running the Example

You can run this example using `bun`, `tsx`, or `ts-node`:

### Using Bun

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

### Using Node.js and TSX

If you don't have `bun` installed, you can run the example using `tsx`:

```bash
npm install -g tsx
tsx index.ts
```

## Example Output

```text
Starting Agent Workflow Example...
Creating 3 sessions...
Finished creating 3 sessions.

Session jules:session:12345:
State: succeeded
Generated 1 files.
- improvements.md

Session jules:session:67890:
State: succeeded
Generated 1 files.
- deploy.sh

Session jules:session:54321:
State: succeeded
Generated 1 files.
- test_cases.md

Workflow complete.
```
75 changes: 75 additions & 0 deletions packages/core/examples/agent/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { jules } from '@google/jules-sdk';

/**
* Agent Workflow Example
*
* This example demonstrates how to use `jules.all()` to orchestrate
* multiple agent sessions concurrently.
*/
async function main() {
console.log('Starting Agent Workflow Example...');

// Define a list of tasks for the agents to complete
const tasks = [
'Analyze the repository and create a list of potential improvements',
'Write a script to automate the deployment process',
'Review the existing test suite and suggest additional test cases',
];

console.log(`Creating ${tasks.length} sessions...`);

// Use jules.all() to run sessions concurrently
const sessions = await jules.all(
tasks,
(task) => ({
prompt: task,
// In a real scenario, you would provide a source repository:
// source: { github: 'your-org/your-repo', baseBranch: 'main' },
}),
{
concurrency: 2, // Limit concurrency to 2
stopOnError: false, // Continue processing even if one session fails
},
);

console.log(`Finished creating ${sessions.length} sessions.`);

// Process the results
for (const session of sessions) {
console.log(`\nSession ${session.id}:`);

// Wait for the session to complete and get the outcome
try {
const outcome = await session.result();
console.log(` State: ${outcome.state}`);

if (outcome.state === 'failed') {
console.log(` Failed. Check logs or session stream for details.`);
} else {
// Retrieve generated files
const files = outcome.generatedFiles();
if (files.size > 0) {
console.log(` Generated ${files.size} files.`);
for (const [path, _] of files.entries()) {
console.log(` - ${path}`);
}
} else {
console.log(' No files generated.');
}
}
} catch (error) {
console.error(` Error processing session ${session.id}:`, error);
}
}

console.log('\nWorkflow complete.');
}

// Ensure JULES_API_KEY is set
if (!process.env.JULES_API_KEY) {
console.error('Error: JULES_API_KEY environment variable is missing.');
console.log('Please set it using: export JULES_API_KEY=<your-key>');
process.exit(1);
}

main().catch(console.error);
36 changes: 36 additions & 0 deletions packages/core/examples/basic-session/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Basic Session Example

This example demonstrates how to use the Jules SDK to create a simple interactive session. It will use the `jules.session` method to connect to the Jules API, create a session without a specific repository context (a "Repoless" session), provide a prompt to an AI agent, and wait for the results.

## Requirements

- Node.js >= 18 or Bun
- A Jules API Key (`JULES_API_KEY` environment variable)

## Setup

1. Make sure you have installed the SDK dependencies in the project root.

2. Export your Jules API key:

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

## Running the Example

Using `bun`:

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

Using `npm` and `tsx` (or similar TypeScript runner):

```bash
npx tsx index.ts
```

## What it does

The script creates a session using `jules.session` and asks the agent to write a haiku. It then waits for the result and retrieves the output. This is a basic demonstration of the isolated core Jules API.
75 changes: 75 additions & 0 deletions packages/core/examples/basic-session/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { jules } from '@google/jules-sdk';

/**
* Basic Session Example
*
* Demonstrates a simple interaction with the Jules SDK.
* It creates a repoless session (no GitHub source), provides a simple prompt,
* and awaits the final outcome.
*/
async function main() {
// Ensure the JULES_API_KEY environment variable is set.
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);
}

console.log('Creating a new Jules session...');

try {
// 1. Create a basic session
// We use a repoless session (no source) for this simple demonstration.
const session = await jules.session({
prompt: 'Write a haiku about artificial intelligence programming itself.',
});

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

// 2. Await the result of the session
// This will poll the API until the session reaches a terminal state (completed or failed).
const outcome = await session.result();

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

if (outcome.state === 'completed') {
// 3. Retrieve and display the final message from the agent
// Since it's a haiku, we expect it in the generated files or the agent's messages.
// Often, the agent writes its final output to a file or answers in a message.
// Let's print out the latest agent message.
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 Message:');
console.log(activities[0].message);
} else {
console.log('\nThe agent did not leave a final message.');

// Let's check generated files
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.error('The session did not complete successfully.');
}

} catch (error) {
console.error('An error occurred during the session:', error);
}
}

// Run the example
main();
Loading
Loading