Skip to content
Merged
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
8,021 changes: 8,021 additions & 0 deletions package-lock.json

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 @@ -57,6 +57,7 @@
"@swc/core": "^1.3.102",
"@swc/jest": "^0.2.29",
"@types/jest": "^29.4.0",
"@types/tar": "^6.1.13",
"@typescript-eslint/eslint-plugin": "^6.7.0",
"@typescript-eslint/parser": "^6.7.0",
"eslint": "^8.49.0",
Expand Down
85 changes: 85 additions & 0 deletions src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Devbox } from './sdk/devbox';
import { Blueprint } from './sdk/blueprint';
import { Snapshot } from './sdk/snapshot';
import { StorageObject } from './sdk/storage-object';
import { Agent } from './sdk/agent';

// Import types used in this file
import type {
Expand All @@ -15,6 +16,7 @@ import type {
} from './resources/devboxes/devboxes';
import type { BlueprintCreateParams, BlueprintListParams } from './resources/blueprints';
import type { ObjectCreateParams, ObjectListParams } from './resources/objects';
import type { AgentCreateParams, AgentListParams } from './resources/agents';
import { PollingOptions } from './lib/polling';

export * from './index';
Expand Down Expand Up @@ -48,6 +50,7 @@ type ContentType = ObjectCreateParams['content_type'];
* - `blueprint` - {@link BlueprintOps}
* - `snapshot` - {@link SnapshotOps}
* - `storageObject` - {@link StorageObjectOps}
* - `agent` - {@link AgentOps}
*
* See the documentation for each Operations class for more details.
*
Expand Down Expand Up @@ -109,6 +112,15 @@ export class RunloopSDK {
*/
public readonly storageObject: StorageObjectOps;

/**
* **Agent Operations** - {@link AgentOps} for creating and accessing {@link Agent} class instances.
*
* Agents are registered AI agent entities that can be mounted into devboxes. Agents can be sourced
* from npm, pip, git repositories, or object storage, and provide reusable agent code that can be
* shared across multiple devboxes. Use these operations to create new agents or get existing ones by ID.
*/
public readonly agent: AgentOps;

/**
* Creates a new RunloopSDK instance.
* @param {ClientOptions} [options] - Optional client configuration options.
Expand All @@ -119,6 +131,7 @@ export class RunloopSDK {
this.blueprint = new BlueprintOps(this.api);
this.snapshot = new SnapshotOps(this.api);
this.storageObject = new StorageObjectOps(this.api);
this.agent = new AgentOps(this.api);
}
}

Expand Down Expand Up @@ -595,6 +608,75 @@ export class StorageObjectOps {
}
}

/**
* Agent SDK interface for managing agents.
*
* ## Overview
*
* The `AgentOps` class provides a high-level abstraction for managing AI agent entities.
* Agents can be sourced from npm, pip, git repositories, or object storage, and mounted
* into devboxes for execution.
*
* ## Usage
*
* This interface is accessed via {@link RunloopSDK.agent}. You should construct
* a {@link RunloopSDK} instance and use it from there:
*
* @example
* ```typescript
* const sdk = new RunloopSDK();
* const agent = await sdk.agent.create({
* name: 'my-npm-agent',
* source: {
* type: 'npm',
* npm: { package_name: '@my-org/agent' }
* }
* });
* const devbox = await agent.createDevbox({
* name: 'devbox-with-agent',
* agent_path: '/home/user/agent'
* });
* ```
*/
export class AgentOps {
/**
* @private
*/
constructor(private client: RunloopAPI) {}

/**
* Create a new agent.
*
* @param {AgentCreateParams} params - Parameters for creating the agent.
* @param {Core.RequestOptions} [options] - Request options.
* @returns {Promise<Agent>} An {@link Agent} instance.
*/
async create(params: AgentCreateParams, options?: Core.RequestOptions): Promise<Agent> {
return Agent.create(this.client, params, options);
}

/**
* Get an agent object by its ID.
*
* @param {string} id - The ID of the agent.
* @returns {Agent} An {@link Agent} instance.
*/
fromId(id: string): Agent {
return Agent.fromId(this.client, id);
}

/**
* List all agents with optional filters.
*
* @param {AgentListParams} [params] - Optional filter parameters.
* @param {Core.RequestOptions} [options] - Request options.
* @returns {Promise<Agent[]>} An array of {@link Agent} instances.
*/
async list(params?: AgentListParams, options?: Core.RequestOptions): Promise<Agent[]> {
return Agent.list(this.client, params, options);
}
}

// @deprecated Use {@link RunloopSDK} instead.
/**
* @deprecated Use {@link RunloopSDK} instead.
Expand All @@ -614,10 +696,12 @@ export declare namespace RunloopSDK {
BlueprintOps as BlueprintOps,
SnapshotOps as SnapshotOps,
StorageObjectOps as StorageObjectOps,
AgentOps as AgentOps,
Devbox as Devbox,
Blueprint as Blueprint,
Snapshot as Snapshot,
StorageObject as StorageObject,
Agent as Agent,
};
}
// Export SDK classes from sdk/sdk.ts - these are separate from RunloopSDK to avoid circular dependencies
Expand All @@ -630,6 +714,7 @@ export {
Blueprint,
Snapshot,
StorageObject,
Agent,
Execution,
ExecutionResult,
} from './sdk/index';
142 changes: 142 additions & 0 deletions src/sdk/agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { Runloop } from '../index';
import type * as Core from '../core';
import type { AgentCreateParams, AgentListParams, AgentView } from '../resources/agents';

/**
* Object-oriented interface for working with Agents.
*
* ## Overview
*
* The `Agent` class provides a high-level API for managing AI agent entities.
* Agents represent registered AI agents that can be mounted into devboxes and
* sourced from various package managers (npm, pip), git repositories, or object storage.
*
* ## Quickstart
*
* Agents are created and then mounted into devboxes via the mounts parameter:
* ```typescript
* import { RunloopSDK } from '@runloop/api-client-ts';
*
* const runloop = new RunloopSDK();
*
* // Create an agent from git
* const agent = await runloop.agent.create({
* name: 'my-agent',
* source: {
* type: 'git',
* git: {
* repository: 'https://github.com/user/agent-repo',
* ref: 'main'
* }
* }
* });
*
* // Mount agent into a devbox
* const devbox = await runloop.devbox.create({
* name: 'devbox-with-agent',
* mounts: [{
* type: 'agent_mount',
* agent_id: agent.id,
* agent_path: '/home/user/agent'
* }]
* });
* ```
*
*/
export class Agent {
private client: Runloop;
private _id: string;

constructor(client: Runloop, id: string) {
this.client = client;
this._id = id;
}

/**
* Create an Agent instance by ID without retrieving from API.
* Use getInfo() to fetch the actual data when needed.
*
* See the {@link AgentOps.fromId} method for calling this
* @private
*
* @param {Runloop} client - The Runloop client instance
* @param {string} id - The agent ID
* @returns {Agent} An {@link Agent} instance
*/
static fromId(client: Runloop, id: string): Agent {
return new Agent(client, id);
}

/**
* Create a new Agent.
*
* See the {@link AgentOps.create} method for calling this
* @private
*
* @param {Runloop} client - The Runloop client instance
* @param {AgentCreateParams} params - Agent creation parameters
* @param {Core.RequestOptions} [options] - Request options
* @returns {Promise<Agent>} A new {@link Agent} instance
*/
static async create(
client: Runloop,
params: AgentCreateParams,
options?: Core.RequestOptions,
): Promise<Agent> {
const agentData = await client.agents.create(params, options);
return new Agent(client, agentData.id);
}

/**
* List all agents, optionally filtered by name, public status, or search query.
*
* @example
* ```typescript
* const runloop = new RunloopSDK();
* // List all agents
* const agents = await runloop.agent.list();
*
* // Filter by name
* const agents = await runloop.agent.list({ name: 'my-agent' });
*
* // Search by ID or name
* const agents = await runloop.agent.list({ search: 'agent-123' });
* ```
*
* @param {Runloop} client - The Runloop client instance
* @param {AgentListParams} [params] - Optional filter parameters
* @param {Core.RequestOptions} [options] - Request options
* @returns {Promise<Agent[]>} Array of {@link Agent} instances
*/
static async list(
client: Runloop,
params?: AgentListParams,
options?: Core.RequestOptions,
): Promise<Agent[]> {
const agents = await client.agents.list(params, options);
const result: Agent[] = [];

for await (const agent of agents) {
result.push(new Agent(client, agent.id));
}

return result;
}

/**
* Get the agent ID.
*/
get id(): string {
return this._id;
}

/**
* Get the complete agent data from the API.
*
* @param {Core.RequestOptions} [options] - Request options
* @returns {Promise<AgentView>} The agent data
*/
async getInfo(options?: Core.RequestOptions): Promise<AgentView> {
return await this.client.agents.retrieve(this._id, options);
}
}
1 change: 1 addition & 0 deletions src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export { Devbox, DevboxCmdOps, DevboxFileOps, DevboxNetOps, type ExecuteStreamin
export { Blueprint } from './blueprint';
export { Snapshot } from './snapshot';
export { StorageObject } from './storage-object';
export { Agent } from './agent';
export { Execution } from './execution';
export { ExecutionResult } from './execution-result';
Loading
Loading