npm package: @lumi.new/sdk
Description: SDK for Lumi.new
Latest version: 0.4.5

# @lumi.new/sdk

The official JavaScript/TypeScript SDK for Lumi.new. It offers a simple interface for handling user authentication and managing your project's data entities.

## Installation

```bash
# pnpm
pnpm add @lumi.new/sdk

# npm
npm install @lumi.new/sdk

# yarn
yarn add @lumi.new/sdk
```

## Getting Started

First, initialize the Lumi client. You can get your `projectId` from your Lumi project settings.

```typescript
import { createClient } from '@lumi.new/sdk'

export const lumi = createClient({
  projectId: 'YOUR_PROJECT_ID',
  apiBaseUrl: 'YOUR_API_BASE_URL',
  authOrigin: 'YOUR_AUTH_ORIGIN',
})
```

### Usage on the Server (Deno)

Here is an example of how to use the Lumi SDK in a Deno environment. Make sure to handle secrets like your authorization token securely, for example, by using environment variables.

```typescript
Deno.serve(async (req) => {
  const authorization = req.headers.get('Authorization')
  const lumi = createClient({
    projectId: 'YOUR_PROJECT_ID',
    apiBaseUrl: 'YOUR_API_BASE_URL',
    authOrigin: '',
    authorization,
  })
  const user = await lumi.auth.refreshUser()
  return lumi.auth.user
})
```

## Authentication

The Lumi SDK provides methods to handle user authentication.

### Server-side Usage and Limitations

When using the SDK in a server-side environment (like Node.js), please note the following differences:

- **Initialization**: You must provide an `authorization` token when creating the client. See the `createClient` API Reference for more details.
- **Disabled Methods**: Methods that rely on a browser environment are disabled and will throw an error if called. This includes:
  - `lumi.auth.signIn()`
  - `lumi.auth.signInWithOAuth()`
  - `lumi.auth.signOut()`
  - `lumi.auth.onAuthChange()`
- **Fetching User Data**: On the server, `lumi.auth.user` is `null` by default. You must explicitly call `await lumi.auth.refreshUser()` to fetch the user's profile based on the token provided during initialization.

- **AI Tools**: Most of the `lumi.tools.ai` methods are server-side only and require a `LUMI_API_KEY` environment variable. The `parseStream` method is an exception, designed for client-side use.

### Sign In

To sign in a user, call the `signIn` method. This will open a popup window for the user to authenticate. Upon successful authentication, the access token and user information will be automatically stored.

```typescript
import { LumiClient } from '@lumi.new/sdk'

async function handleSignIn(lumi: LumiClient) {
  try {
    const { user, accessToken } = await lumi.auth.signIn()
    console.log('Signed in as:', user)
    console.log('Access Token:', accessToken)
  } catch (error) {
    console.error('Authentication failed:', error)
  }
}
```

### Sign In with Password

Sign in a user using their email and password.

```typescript
async function handleSignInWithPassword(lumi: LumiClient) {
  try {
    const { user, accessToken } = await lumi.auth.signInWithPassword({
      email: 'user@example.com',
      password: 'your-password',
    })
    console.log('Signed in as:', user)
  } catch (error) {
    console.error('Authentication failed:', error)
  }
}
```

### Sign In with OAuth

Sign in a user using a third-party OAuth provider (e.g., Google). This will open a popup window for the user to authenticate with the provider.

```typescript
async function handleSignInWithGoogle(lumi: LumiClient) {
  try {
    const { user, accessToken } = await lumi.auth.signInWithOAuth({
      provider: 'google',
    })
    console.log('Signed in with Google as:', user)
  } catch (error) {
    console.error('OAuth authentication failed:', error)
  }
}
```

### Sign Up with Password

Register a new user with email and password. You must first send an OTP to the user's email using `sendOtp`.

```typescript
async function handleSignUp(lumi: LumiClient) {
  const email = 'newuser@example.com'

  // Step 1: Send OTP to the user's email
  await lumi.auth.sendOtp({ email, type: 'register' })
  console.log('OTP sent to email')

  // Step 2: After user receives OTP, complete registration
  const otp = '123456' // OTP entered by user
  try {
    await lumi.auth.signUpWithPassword({
      email,
      password: 'secure-password',
      otp,
      userName: 'New User', // optional
    })
    console.log('Registration successful')
  } catch (error) {
    console.error('Registration failed:', error)
  }
}
```

### Reset Password

Reset a user's password. You must first send an OTP to the user's email using `sendOtp`.

```typescript
async function handleResetPassword(lumi: LumiClient) {
  const email = 'user@example.com'

  // Step 1: Send OTP to the user's email
  await lumi.auth.sendOtp({ email, type: 'resetPassword' })
  console.log('OTP sent to email')

  // Step 2: After user receives OTP, reset password
  const otp = '123456' // OTP entered by user
  try {
    await lumi.auth.resetPassword({
      email,
      newPassword: 'new-secure-password',
      otp,
    })
    console.log('Password reset successful')
  } catch (error) {
    console.error('Password reset failed:', error)
  }
}
```

### Sign Out

To sign out a user, simply call the `signOut` method. This will clear the stored access token and user information.

```typescript
function handleSignOut(lumi: LumiClient) {
  lumi.auth.signOut()
  console.log('User signed out.')
}
```

### Refresh User Profile

Fetch the latest profile of the currently authenticated user and update the local cache. This method requires a valid access token.

```typescript
async function fetchUser(lumi: LumiClient) {
  if (lumi.auth.isAuthenticated) {
    try {
      const user = await lumi.auth.refreshUser()
      console.log('Current user:', user)
    } catch (error) {
      console.error('Failed to fetch user:', error)
    }
  } else {
    console.log('User is not authenticated.')
  }
}
```

### Manage Access Token

You can directly access the access token.

```typescript
// Get the access token
const token = lumi.auth.accessToken

// Check if the user is authenticated
const isAuthenticated = lumi.auth.isAuthenticated
```

### Access User Information

You can directly access the cached user data. This data is available after a successful sign-in or a call to `refreshUser`.

```typescript
// Get the user object from the cache
const user = lumi.auth.user

if (user) {
  console.log('Current user from cache:', user.userName)
}
```

### Listen for Auth Changes

You can listen for changes in the authentication state. This is useful for reacting to sign-ins, sign-outs, or any direct modifications to the access token or user information, whether they happen in the current tab or another one.

```typescript
function listenForAuthChanges(lumi: LumiClient) {
  const unsubscribe = lumi.auth.onAuthChange(({ isAuthenticated, user }) => {
    console.log(`User is now ${isAuthenticated ? 'signed in' : 'signed out'}.`)
    if (isAuthenticated) {
      console.log('User details:', user)
    }
    // You can update your UI based on the authentication state
  })

  // To stop listening, call the unsubscribe function
  // unsubscribe()
}
```

## Entities

The `entities` client allows you to interact with your project's data collections. You can access a specific entity by its name.

```typescript
const posts = lumi.entities.Posts
```

### List Records

Retrieve a list of records from an entity. This method returns an object containing the list of records and the total count. You can use `filter`, `sort`, `limit`, and `skip` to control the query.

```typescript
async function getPosts() {
  const { list, total } = await lumi.entities.Posts.list({
    filter: { published: true },
    sort: { createdAt: -1 }, // Sort by creation date in descending order
    limit: 10,
    skip: 0,
  })
  console.log('Posts:', list)
  console.log('Total records:', total)
}

// Example Request:
getPosts();

// Example Response:
// Posts: [
//   { id: 'post-id-1', title: 'First Post', content: '...', published: true, createdAt: '...' },
//   { id: 'post-id-2', title: 'Second Post', content: '...', published: true, createdAt: '...' }
// ]
// Total records: 2
```

### Get a Single Record

Retrieve a single record by its ID.

```typescript
async function getPost(id: string) {
  const post = await lumi.entities.Posts.get(id)
  console.log('Post:', post)
}

// Example Request:
getPost('your-post-id');

// Example Response:
// Post: { id: 'post-id-1', title: 'My Post', content: '...', published: true, createdAt: '...' }
```

### Create a Record

Create a new record in an entity.

```typescript
async function createPost(title: string, content: string) {
  const newPost = await lumi.entities.Posts.create({
    title,
    content,
    published: false,
  })
  console.log('Created post:', newPost)
}

// Example Request:
createPost('My Awesome Post', 'This is the content of my new post.');

// Example Response:
// Created post: { id: 'new-post-id', title: 'My Awesome Post', content: 'This is the content of my new post.', published: false, creator: 'user-id-123', createdAt: '2024-01-16T10:30:00Z', updatedAt: '2024-01-16T10:30:00Z' }
```

### Create Multiple Records

Create multiple records in a single request.

```typescript
async function createMultiplePosts(newPostsData: any[]) {
  const newPosts = await lumi.entities.Posts.createMany(newPostsData)
  console.log('Created posts:', newPosts)
}

// Example Request:
const postsToCreate = [
  { title: 'First Awesome Post', content: 'Content for the first post.' },
  { title: 'Second Awesome Post', content: 'Content for the second post.' }
];
createMultiplePosts(postsToCreate);

// Example Response:
// Created posts: [
//   { id: 'post-1', title: 'Post 1', content: '...', published: false, creator: 'user-id-123', createdAt: '...', updatedAt: '...' },
//   { id: 'post-2', title: 'Post 2', content: '...', published: false, creator: 'user-id-123', createdAt: '...', updatedAt: '...' }
// ]
```

### Update a Record

Update an existing record by its ID.

```typescript
async function updatePost(id: string, updates: Record<string, any>) {
  const updatedPost = await lumi.entities.Posts.update(id, updates)
  console.log('Updated post:', updatedPost)
}

// Example Request:
updatePost('your-post-id', { published: true, title: 'My Updated Post' });

// Example Response:
// Updated post: { id: 'post-id-1', title: 'My Updated Post', content: '...', published: true, creator: 'user-id-123', createdAt: '...', updatedAt: '...' }
```

### Delete a Record

Delete a record by its ID.

```typescript
async function deletePost(id: string) {
  await lumi.entities.Posts.delete(id)
  console.log('Post deleted.')
}

// Example Request:
deletePost('your-post-id');
```

### Delete Multiple Records

Delete multiple records by their IDs in a single request.

```typescript
async function deleteMultiplePosts(ids: string[]) {
  await lumi.entities.Posts.deleteMany(ids)
  console.log('Posts deleted.')
}

// Example Request:
deleteMultiplePosts(['post-id-1', 'post-id-2']);
```

## Tools

The `tools` client provides access to various utilities, such as sending emails, managing files, and AI text/image generation.

### Email

#### Send an Email

You can send an email using the `email.send` method.

```typescript
async function sendWelcomeEmail(email: string) {
  try {
    await lumi.tools.email.send({
      to: email,
      subject: 'Welcome to Our Service!',
      fromName: 'The Team',
      html: '<h1>Welcome!</h1><p>We are glad to have you with us.</p>',
    });
    console.log('Email sent successfully.');
  } catch (error) {
    console.error('Failed to send email:', error);
  }
}

// Example Request:
sendWelcomeEmail('test@example.com');
```

### File

#### Upload Files

Upload multiple files in a single request. This method returns an array of objects, each representing the result of one file upload.

```typescript
async function uploadFiles(files: File[]) {
  const results = await lumi.tools.file.upload(files)
  console.log('Upload results:', results)
}

// Example Request (in a browser environment):
// const fileInput = document.querySelector('input[type="file"]');
// if (fileInput.files) {
//   uploadFiles(Array.from(fileInput.files));
// }

// Example Response:
// Upload results: [
//   { fileName: 'image.png', fileUrl: 'https://your-storage.com/image.png' },
//   { fileName: 'application.exe', uploadError: 'Invalid file type' }
// ]
```

#### Delete Files

Delete multiple files by their URLs in a single request.

```typescript
async function deleteFiles(urls:string[]) {
  await lumi.tools.file.delete(urls);
  console.log('Files deleted.');
}

// Example Request:
const filesToDelete = [
  'https://your-storage.com/image.png',
  'https://your-storage.com/document.pdf'
];
deleteFiles(filesToDelete);
```

### AI

> Note:
> - Most AI methods are server-side only. The `parseStream` method is an exception, designed for client-side use.
> - You must provide `LUMI_API_KEY` via environment variables when calling AI methods on the server.

#### AI: Generate Text

```typescript
async function aiGenerateText() {
  const result = await lumi.tools.ai.generateText({
    // optional; defaults to 'gemini-2.5-flash'
    model: 'gemini-2.5-flash',
    messages: [
      { role: 'system', content: 'You are a helpful assistant.' },
      { role: 'user', content: 'Write a haiku about the sea.' },
    ],
  })
  console.log(result.chatId, result.content)
}
```

#### AI: Generate Text (Streaming)

The streaming process involves two steps: first, calling `generateTextStream` in a server-side function (Deno) to get a raw stream, and then parsing it on the client with `parseStream`.

**1. Server-Side Example (Deno)**

Create a Lumi Function (e.g., named `ai-stream`) that calls `generateTextStream` and streams the raw response back to the client as Server-Sent Events (SSE).

> **Note:** Ensure `LUMI_API_KEY` is set in your environment variables.

```typescript
// Example: A Deno-based Lumi Function
Deno.serve(async (request: Request) => {
  // Initialize Lumi client with authorization token if needed
  // const lumi = createClient({ ... });

  const rawStream = await lumi.tools.ai.generateTextStream({
    model: 'gemini-2.5-flash',
    messages: [
      { role: 'system', content: 'You are a helpful assistant.' },
      { role: 'user', content: 'Stream a short poem line by line.' },
    ],
  });

  // Pipe the raw stream to the response with proper SSE headers
  return new Response(rawStream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'X-Accel-Buffering': 'no',
    },
  });
});
```

**2. Client-Side Example**

In your frontend code, use `lumi.functions.invoke` to call the function and `lumi.tools.ai.parseStream` to process the streaming data. `invoke` automatically handles authentication headers.

```typescript
async function consumeAiStream() {
  // Invoke the 'ai-stream' function.
  // Setting responseType: 'stream' ensures we get the raw stream.
  const rawStream = await lumi.functions.invoke('ai-stream', {
    responseType: 'stream',
  });

  if (!rawStream) {
    console.error("The response stream is empty.");
    return;
  }

  const parsedStream = await lumi.tools.ai.parseStream(rawStream);
  const reader = parsedStream.getReader();

  try {
    while (true) {
      const { value, done } = await reader.read();
      if (done) break;
      // value: { event?: string, data: { chatId, content } }
      const content = value?.data?.content ?? '';
      console.log(content); // Update your UI with the content
    }
  } finally {
    reader.releaseLock();
  }
}
```

#### AI: Generate Image

```typescript
async function aiGenerateImage() {
  const result = await lumi.tools.ai.generateImage({
    // optional; defaults to 'gemini-2.5-flash-image'
    model: 'gemini-2.5-flash-image',
    messages: [
      { role: 'user', content: 'A watercolor painting of a serene mountain lake at sunrise.' },
    ],
  })

  if (result.generationStatus === 'SUCCESS') {
    console.log('Image URL:', result.imageURL)
  } else {
    console.log('Image generation failed:', result)
  }
}
```

## Functions

The `functions` client allows you to invoke serverless functions deployed in your Lumi project.

### Invoke a Function

You can call a function by its name and pass options like `method`, `query`, and `body`. This is essentially a wrapper around `fetch` that automatically includes the user's authentication token if available.

```typescript
async function sendNewsletter(recipient: string) {
  try {
    const result = await lumi.functions.invoke('sendNewsletter', {
      method: 'POST',
      headers: {
        'X-Campaign-ID': 'weekly-digest',
      },
      body: {
        to: recipient,
        subject: 'Your Weekly Newsletter'
      }
    })
    console.log('Newsletter function invoked successfully:', result)
  } catch (error) {
    console.error('Failed to invoke newsletter function:', error)
  }
}

sendNewsletter('subscriber@example.com');
```

---

## API Reference

### `createClient(config)`

Initializes the Lumi client.

**Parameters:**

- `config` (`object`): The configuration object for the client.
    - `projectId` (`string`): Your Lumi project ID.
    - `apiBaseUrl` (`string`): The base URL of the Lumi API.
    - `authOrigin` (`string`): The origin URL for the authentication popup.
    - `authorization` (`string`, optional): An authorization token (e.g., `Bearer YOUR_TOKEN`). Recommended for server-side usage.

**Returns:**

- `LumiClient`: An instance of the Lumi client.

### Authentication (`lumi.auth`)

Provides methods for user authentication.

#### `signIn()`

> **Note:** This method is not available in server-side environments and will throw an error if called.

Initiates the sign-in process by opening a popup window.

**Returns:**

- `Promise<object>`: A promise that resolves with an object containing:
    - `projectId` (`string`): The project ID associated with the authenticated session.
    - `user` (`object`): The authenticated user's information.
        - `userId` (`string`): The user's unique identifier.
        - `email` (`string`): The user's email address.
        - `userName` (`string`): The user's name.
        - `userRole` (`'ADMIN' | 'USER'`): The user's role.
        - `createdTime` (`string`): The timestamp of when the user was created.
    - `accessToken` (`string`): The access token for the session.

#### `signInWithPassword(options)`

Signs in a user using their email and password.

**Parameters:**

- `options` (`object`):
    - `email` (`string`): The user's email address.
    - `password` (`string`): The user's password.

**Returns:**

- `Promise<object>`: A promise that resolves with an object containing:
    - `projectId` (`string`): The project ID associated with the authenticated session.
    - `user` (`object`): The authenticated user's information.
    - `accessToken` (`string`): The access token for the session.

#### `signInWithOAuth(options)`

> **Note:** This method is not available in server-side environments and will throw an error if called.

Signs in a user using a third-party OAuth provider. This will open a popup window for the user to authenticate with the provider.

**Parameters:**

- `options` (`object`):
    - `provider` (`'google'`): The OAuth provider to use. Currently only `'google'` is supported.

**Returns:**

- `Promise<object>`: A promise that resolves with an object containing:
    - `projectId` (`string`): The project ID associated with the authenticated session.
    - `user` (`object`): The authenticated user's information.
    - `accessToken` (`string`): The access token for the session.

#### `sendOtp(options)`

Sends a one-time password (OTP) to the user's email for registration or password reset.

**Parameters:**

- `options` (`object`):
    - `email` (`string`): The user's email address.
    - `type` (`'register' | 'resetPassword'`): The purpose of the OTP.

**Returns:**

- `Promise<void>`: A promise that resolves when the OTP is sent.

#### `signUpWithPassword(options)`

Registers a new user with email and password. Requires a valid OTP obtained via `sendOtp`.

**Parameters:**

- `options` (`object`):
    - `email` (`string`): The user's email address.
    - `password` (`string`): The user's password.
    - `otp` (`string`): The OTP received via email.
    - `userName` (`string`, optional): The user's display name.

**Returns:**

- `Promise<void>`: A promise that resolves when registration is complete.

#### `resetPassword(options)`

Resets a user's password. Requires a valid OTP obtained via `sendOtp`.

**Parameters:**

- `options` (`object`):
    - `email` (`string`): The user's email address.
    - `newPassword` (`string`): The new password.
    - `otp` (`string`): The OTP received via email.

**Returns:**

- `Promise<void>`: A promise that resolves when the password is reset.

#### `signOut()`

> **Note:** This method is not available in server-side environments and will throw an error if called.

Signs out the current user by clearing the stored access token and user data.

#### `refreshUser()`

Fetches the latest profile of the currently authenticated user and updates the local cache. Requires a valid access token.

**Returns:**

- `Promise<object>`: A promise that resolves with the user's profile information.
    - `userId` (`string`): The user's unique identifier.
    - `email` (`string`): The user's email address.
    - `userName` (`string`): The user's name.
    - `userRole` (`'ADMIN' | 'USER'`): The user's role.
    - `createdTime` (`string`): The timestamp of when the user was created.

#### `accessToken`

A getter/setter for the access token.

- **Get**: `lumi.auth.accessToken` (`string | null`): Returns the currently stored access token, or `null` if not authenticated.
- **Set**: `lumi.auth.accessToken = 'YOUR_TOKEN'`: Sets the access token in local storage. Note: This will trigger the `onAuthChange` event.

#### `user`

A getter/setter for the cached user object. The user object is automatically set on sign-in and after calling `refreshUser`.

- **Get**: `lumi.auth.user` (`User | null`): Returns the currently cached user object, or `null` if it's not available.
- **Set**: `lumi.auth.user = userObject`: Sets the user object in local storage. Note: This will trigger the `onAuthChange` event.

#### `isAuthenticated`

A getter that checks if a user is currently authenticated.

- **Get**: `lumi.auth.isAuthenticated` (`boolean`): Returns `true` if an access token exists, otherwise `false`.

#### `onAuthChange(callback)`

> **Note:** This method is not available in server-side environments and will throw an error if called.

Listens for changes in the authentication state. It triggers when `signIn()` or `signOut()` is called, or when `accessToken` or `user` are modified directly. This works across different browser tabs and within the same page.

**Parameters:**

- `callback` (`({ isAuthenticated: boolean, user: User | null }) => void`): A function that is called whenever the authentication state changes. It receives an object containing the `isAuthenticated` flag and the `user` object from local storage.

**Returns:**

- `() => void`: A function that, when called, unsubscribes the listener.

**Example:**
```typescript
const unsubscribe = lumi.auth.onAuthChange(({ isAuthenticated, user }) => {
  console.log('Authentication state changed:', isAuthenticated)
  if (isAuthenticated) {
    // Typically you would update your UI here
    console.log('User is now signed in:', user)
  } else {
    // And here as well
    console.log('User is now signed out.')
  }
})

// When the component unmounts or you no longer need to listen for changes:
// unsubscribe();
```

### Entities (`lumi.entities.YourEntity`)

Provides methods for interacting with your project's data entities.

#### `list(options)`

Retrieves a list of records from an entity.

**Parameters:**

- `options` (`object`, optional): Query options.
    - `filter` (`object`, optional): An object specifying query conditions.
    - `sort` (`object`, optional): An object specifying the sort order. Use `1` for ascending and `-1` for descending. Example: `{ createdAt: -1 }`.
    - `limit` (`number`, optional): The maximum number of records to return.
    - `skip` (`number`, optional): The number of records to skip from the beginning.

**Returns:**

- `Promise<object>`: A promise that resolves with an object containing:
    - `list` (`Array<object>`): An array of the retrieved records.
    - `total` (`number`): The total number of records matching the query.

#### `get(id)`

Retrieves a single record by its ID.

**Parameters:**

- `id` (`string`): The unique identifier of the record to retrieve.

**Returns:**

- `Promise<object | null>`: A promise that resolves with the record object, or `null` if not found.

#### `create(data)`

Creates a new record.

**Parameters:**

- `data` (`object`): The data for the new record.

**Returns:**

- `Promise<object>`: A promise that resolves with the newly created record object.

#### `createMany(data)`

Creates multiple records in a single request.

**Parameters:**

- `data` (`Array<object>`): An array of data objects for the new records.

**Returns:**

- `Promise<Array<object>>`: A promise that resolves with an array of the newly created record objects.

#### `update(id, data)`

Updates an existing record by its ID.

**Parameters:**

- `id` (`string`): The unique identifier of the record to update.
- `data` (`object`): An object containing the fields to update.

**Returns:**

- `Promise<object>`: A promise that resolves with the updated record object.

#### `delete(id)`

Deletes a record by its ID.

**Parameters:**

- `id` (`string`): The unique identifier of the record to delete.

**Returns:**

- `Promise<void>`: A promise that resolves when the operation is complete.

#### `deleteMany(ids)`

Deletes multiple records by their IDs.

**Parameters:**

- `ids` (`Array<string>`): An array of unique identifiers of the records to delete.

**Returns:**

- `Promise<void>`: A promise that resolves when the operation is complete.

### Tools (`lumi.tools`)

Provides access to various tools and utilities.

#### `email.send(options)`

Sends an email.

**Parameters:**

- `options` (`object`): Email options.
    - `to` (`string | string[]`): The recipient's email address or addresses.
    - `subject` (`string`): The subject of the email.
    - `fromName` (`string`, optional): The sender's name.
    - `html` (`string`, optional): The HTML body of the email. At least one of `html` or `text` must be provided.
    - `text` (`string`, optional): The plain text body of the email. At least one of `html` or `text` must be provided.
    - `replyTo` (`string | string[]`, optional): Email address or addresses to reply to.
    - `scheduledAt` (`string`, optional): An ISO 8601 formatted date string to schedule the email for later sending.

**Returns:**

- `Promise<void>`: A promise that resolves when the email sending request is accepted.

#### `file.upload(files)`

Uploads one or more files.

**Parameters:**

- `files` (`File[]`): An array of `File` objects to upload.

**Returns:**

- `Promise<Array<object>>`: A promise that resolves with an array of objects, where each object represents the result of a single file upload.
    - `fileName` (`string`): The original name of the file.
    - `fileUrl` (`string`, optional): The URL of the uploaded file. Present only on successful upload.
    - `uploadError` (`string`, optional): An error message if the upload for this specific file failed.

#### `file.delete(fileUrls)`

Deletes one or more files based on their URLs.

**Parameters:**

- `fileUrls` (`string[]`): An array of file URLs to be deleted.

**Returns:**

- `Promise<void>`: A promise that resolves when the delete operation is complete.

#### `ai.generateText(options)`

Generates text with the specified model and messages.

**Parameters:**

- `options` (`object`):
    - `model` (`string`, optional): Model name. Defaults to `'gemini-2.5-flash'`.
    - `messages` (`Message[]`): The chat history/messages.

**Returns:**

- `Promise<GenerateTextResult>`: See “Types used by AI”.

**Environment:**

- Server-side only. Requires `LUMI_API_KEY` in environment variables.

#### `ai.generateTextStream(options)`

Generates text as a stream of chunks. This method returns a raw stream from the API. To use it on the client-side, you'll need to parse it using `ai.parseStream`.

**Parameters:**

- `options` (`object`):
    - `model` (`string`, optional): Model name. Defaults to `'gemini-2.5-flash'`.
    - `messages` (`Message[]`): The chat history/messages.

**Returns:**

- `Promise<ReadableStream>`: A raw readable stream.

**Environment:**

- Server-side only. Requires `LUMI_API_KEY` in environment variables.

#### `ai.parseStream(stream)`

Parses a raw stream from `ai.generateTextStream` into a stream of structured data chunks. This is particularly useful on the client-side (e.g., in the browser) to process the server-sent events.

**Parameters:**

- `stream` (`ReadableStream<Uint8Array>`): The raw stream obtained from `ai.generateTextStream` (typically `response.body` from `fetch`).

**Returns:**

- `Promise<ReadableStream<{ event?: string, data: GenerateTextResult }>>`: A readable stream producing event/data chunks.

**Recommended Usage:**

1. **Server-Side:** Call `ai.generateTextStream` in a Lumi Function to get a raw stream and return it as an SSE response.
2. **Client-Side:** Use `lumi.functions.invoke` (with `responseType: 'stream'`) to fetch the stream, then pass it to `ai.parseStream` for processing.

For a complete code example, see the **AI: Generate Text (Streaming)** section in the **Tools** chapter.

#### `ai.generateImage(options)`

Generates an image with the specified model and messages. The call completes after the task finishes (internally polled).

**Parameters:**

- `options` (`object`):
    - `model` (`string`, optional): Model name. Defaults to `'gemini-2.5-flash-image'`.
    - `messages` (`Message[]`): The prompt/messages for image generation.

**Returns:**

- `Promise<GenerateImageResult>`: See “Types used by AI”. This method resolves only when the result is `'SUCCESS'` or `'FAILED'`.

**Environment:**

- Server-side only. Requires `LUMI_API_KEY` in environment variables.

#### Types used by AI

- `MessageMedia`:
  - `mimeType` (`string`)
  - `url` (`string`)

- `Message`:
  - `role` (`'system' | 'user' | 'assistant'`)
  - `content` (`string`)
  - `medias?` (`MessageMedia[]`)

- `GenerateTextResult`:
  - `chatId` (`string`)
  - `content` (`string`)

- `GenerateImageResult`:
  - `chatId` (`string`)
  - `messageId` (`string`)
  - `generationStatus` (`'SUCCESS' | 'FAILED'`)
  - `content?` (`string`)
  - `imageURL?` (`string`)

### Functions (`lumi.functions`)

Provides a method for invoking serverless functions.

#### `invoke(functionName, options)`

Invokes a serverless function by its name.

**Parameters:**

- `functionName` (`string`): The name of the function to invoke.
- `options` (`object`, optional): Fetch options compatible with `ofetch`, including:
    - `method` (`string`, optional): The HTTP method (e.g., `'GET'`, `'POST'`).
    - `query` (`object`, optional): An object of query parameters to be appended to the URI.
    - `body` (`object` | `FormData`, optional): The request body.
    - `headers` (`object`, optional): Custom request headers.
    - `responseType` (`string`, optional): The type of data expected (e.g., `'json'`, `'stream'`). Defaults to `'json'`.

**Returns:**

- `Promise<any>`: A promise that resolves with the response from the function.