@workspace-agent/sdk
v0.0.1-beta.6
Published
Node.js SDK for Workspace Agent API - Manage containerized development environments
Downloads
35
Maintainers
Readme
@workspace-agent/sdk
A comprehensive Node.js/TypeScript SDK for the Workspace Agent API. Manage containerized development environments with full support for files, git, terminals, processes, and LSP.
Features
- Workspace Management - Create, start, stop, and delete workspaces
- Multiple Runtimes - Bun, Node.js, Python, Go, and Rust
- File Operations - Read, write, delete, copy, and move files
- Git Integration - Clone, pull, commit, branch, and view history
- Interactive Terminals - PTY-based terminal sessions via WebSocket
- Process Management - Start background processes, sync execution, logs
- LSP Client - Full Language Server Protocol support
- Real-time Metrics - CPU, memory, network, and I/O monitoring via SSE
- TypeScript First - Complete type definitions and JSDoc documentation
- Fluent API - Builder pattern for easy workspace creation
Installation
npm install @workspace-agent/sdk
# or
yarn add @workspace-agent/sdk
# or
pnpm add @workspace-agent/sdk
# or
bun add @workspace-agent/sdkQuick Start
import { WorkspaceClient } from '@workspace-agent/sdk';
const client = new WorkspaceClient();
// Create a workspace
const workspace = await client.workspaces.create({
name: 'my-project',
runtime: 'bun'
});
// Write some code
await workspace.files.write('index.ts', `
console.log('Hello from workspace!');
`);
// Run it
const result = await workspace.exec(['bun', 'run', 'index.ts']);
console.log(result.output); // Hello from workspace!
// Clean up
await workspace.delete();API Reference
WorkspaceClient
The main entry point for the SDK.
import { WorkspaceClient } from '@workspace-agent/sdk';
// Default configuration (localhost:18080)
const client = new WorkspaceClient();
// Custom configuration
const client = new WorkspaceClient({
baseUrl: 'http://api.example.com:18080',
timeout: 60000,
debug: true
});Runtimes
List available runtime environments:
const runtimes = await client.runtimes.list();
// [
// { id: 'bun', name: 'Bun', dockerImage: 'workspace-agent/bun:latest', ... },
// { id: 'node', name: 'Node.js', ... },
// { id: 'python', name: 'Python', ... },
// { id: 'go', name: 'Go', ... },
// { id: 'rust', name: 'Rust', ... }
// ]Workspaces
// Create workspace
const workspace = await client.workspaces.create({
name: 'my-project',
runtime: 'bun',
repoUrl: 'https://github.com/user/repo.git', // optional
branch: 'main' // optional
});
// Fluent builder pattern
const workspace = await client
.create('my-project')
.withRuntime('node')
.withRepo('https://github.com/user/repo.git', 'develop')
.build();
// Quick create
const workspace = await client.quickCreate('my-project', 'bun');
// List workspaces
const workspaces = await client.workspaces.list();
// Get by ID
const workspace = await client.workspaces.get('ws-abc12345');
// Find by name
const workspace = await client.findByName('my-project');
// Find by pattern
const devWorkspaces = await client.find('dev-*');
// Start/Stop
await workspace.start();
await workspace.stop();
// Delete
await workspace.delete();Files
// List files
const files = await workspace.files.list('src');
// Read file
const content = await workspace.files.read('package.json');
// Read JSON
const pkg = await workspace.files.readJson<{name: string}>('package.json');
// Write file
await workspace.files.write('config.json', '{"key": "value"}');
// Write JSON
await workspace.files.writeJson('config.json', { key: 'value' });
// Check existence
if (await workspace.files.exists('package.json')) {
console.log('Node.js project detected');
}
// Copy/Move/Delete
await workspace.files.copy('src/main.ts', 'src/main.backup.ts');
await workspace.files.move('old.txt', 'new.txt');
await workspace.files.delete('temp.txt');Git
// Clone repository
await workspace.git.clone({
url: 'https://github.com/user/repo.git',
branch: 'main',
target: 'my-app'
});
// Clone private repo
await workspace.git.clone({
url: 'https://github.com/user/private-repo.git',
username: 'user',
password: 'github_pat_xxx'
});
// Pull changes
await workspace.git.pull();
await workspace.git.pull({ remote: 'origin', branch: 'develop' });
// Check status
const status = await workspace.git.status();
if (await workspace.git.isDirty()) {
console.log('Uncommitted changes');
}
// Stage and commit
await workspace.git.add(['src/main.ts', 'package.json']);
await workspace.git.commit('feat: add new feature');
// Or commit all at once
await workspace.git.commitAll('chore: update deps');
// Create branch
await workspace.git.branch('feature/new-feature', true); // create and checkout
// View history
const commits = await workspace.git.log(10);
for (const commit of commits) {
console.log(`${commit.hash} ${commit.message}`);
}Terminal
Interactive PTY terminal sessions:
// Create and connect to terminal
const terminal = await workspace.terminal.spawn();
// Listen for output
terminal.on('data', (data) => {
process.stdout.write(data);
});
// Send commands (include \n to execute)
terminal.write('ls -la\n');
terminal.write('npm install\n');
// Resize terminal
terminal.resize(120, 40);
// Send control characters
terminal.sendCtrlC(); // Ctrl+C
terminal.sendCtrlD(); // Ctrl+D (EOF)
terminal.clear(); // Clear screen
// Disconnect when done
terminal.disconnect();
// Quick command execution
const output = await workspace.terminal.exec('pwd');
console.log(output); // /workspaceProcesses
Background process management:
// Start background process
const proc = await workspace.processes.start({
command: ['bun', 'run', 'dev'],
cwd: '/workspace/app',
env: { PORT: '3000' }
});
console.log(`Started ${proc.id} (PID: ${proc.pid})`);
// List processes
const processes = await workspace.processes.list();
// Get logs
const logs = await workspace.processes.logs(proc.id, { tail: 50 });
// Kill process
await workspace.processes.kill(proc.id);
// Kill all
await workspace.processes.killAll();
// Sync execution (wait for completion)
const result = await workspace.processes.exec({
command: ['npm', 'test'],
timeoutSecs: 120,
separateStderr: true
});
if (result.success) {
console.log(result.output);
} else {
console.error(result.stderr);
}
// Convenience method
const output = await workspace.processes.run('npm run build');
// Or use workspace.exec shorthand
const { output, exitCode } = await workspace.exec(['npm', 'test']);LSP (Language Server Protocol)
Full LSP client for IDE-like features:
// Connect and initialize
const lsp = await workspace.lsp.start();
// Open a document
lsp.didOpen(
'file:///workspace/src/main.ts',
'typescript',
'const x: number = "hello";'
);
// Listen for diagnostics
lsp.on('diagnostics', (uri, diagnostics) => {
for (const diag of diagnostics) {
console.log(`${uri}:${diag.range.start.line}: ${diag.message}`);
}
});
// Get completions
const completions = await lsp.completion(
'file:///workspace/src/main.ts',
{ line: 0, character: 6 }
);
// Get hover info
const hover = await lsp.hover(
'file:///workspace/src/main.ts',
{ line: 0, character: 6 }
);
// Go to definition
const definitions = await lsp.definition(
'file:///workspace/src/main.ts',
{ line: 10, character: 15 }
);
// Find references
const refs = await lsp.references(
'file:///workspace/src/main.ts',
{ line: 5, character: 10 }
);
// Update document
lsp.didChange('file:///workspace/src/main.ts', 2, 'const x: number = 42;');
// Close document
lsp.didClose('file:///workspace/src/main.ts');
// Shutdown
await lsp.shutdown();Metrics
Real-time resource monitoring for workspaces:
// Get current metrics snapshot
const metrics = await workspace.metrics.get();
console.log(`CPU: ${metrics.cpu.usagePercent.toFixed(2)}%`);
console.log(`Memory: ${(metrics.memory.usage / 1024 / 1024).toFixed(1)} MB`);
console.log(`Memory Limit: ${(metrics.memory.limit / 1024 / 1024).toFixed(1)} MB`);
// Get formatted summary
const summary = await workspace.metrics.summary();
console.log(summary);
// CPU: 12.5% | Memory: 256.0 MB / 512.0 MB (50.0%) | Network: RX 1.2 MB / TX 0.5 MB
// Stream metrics in real-time (SSE)
const stream = workspace.metrics.stream({ intervalMs: 500 });
stream.on('data', (metrics) => {
console.log(`CPU: ${metrics.cpu.usagePercent.toFixed(1)}%`);
console.log(`Memory: ${metrics.memory.usagePercent.toFixed(1)}%`);
});
stream.on('error', (error) => {
console.error('Stream error:', error);
});
await stream.start();
// Stop streaming when done
stream.stop();
// Watch metrics for a duration
const samples = await workspace.metrics.watch(5000, 500);
console.log(`Collected ${samples.length} samples`);
const avgCpu = samples.reduce((sum, m) => sum + m.cpu.usagePercent, 0) / samples.length;
console.log(`Average CPU: ${avgCpu.toFixed(2)}%`);
// Continuous monitoring with callback
const stopMonitor = workspace.metrics.monitor((metrics) => {
console.log(`CPU: ${metrics.cpu.usagePercent.toFixed(1)}%`);
}, { intervalMs: 1000 });
// Later, stop monitoring
stopMonitor();Error Handling
import { WorkspaceApiError } from '@workspace-agent/sdk';
try {
await client.workspaces.get('non-existent');
} catch (error) {
if (error instanceof WorkspaceApiError) {
console.error(`API Error ${error.status}: ${error.message}`);
}
}Examples
Create a Bun Project
const workspace = await client.quickCreate('bun-app', 'bun');
// Initialize project
await workspace.exec(['bun', 'init', '-y']);
// Add dependencies
await workspace.exec(['bun', 'add', 'hono']);
// Create server
await workspace.files.write('index.ts', `
import { Hono } from 'hono';
const app = new Hono();
app.get('/', (c) => c.text('Hello Hono!'));
export default app;
`);
// Start dev server
const server = await workspace.processes.start({
command: ['bun', 'run', '--hot', 'index.ts']
});
console.log('Server started on PID:', server.pid);Interactive Development Session
const workspace = await client.quickCreate('dev-session');
// Start terminal
const terminal = await workspace.terminal.spawn();
// Pipe to stdout
terminal.on('data', (data) => process.stdout.write(data));
// Pipe stdin (Node.js example)
process.stdin.setRawMode(true);
process.stdin.on('data', (data) => terminal.write(data.toString()));
// Handle exit
terminal.on('close', () => {
process.stdin.setRawMode(false);
process.exit();
});Type Checking with LSP
const workspace = await client.quickCreate('type-check');
await workspace.files.write('test.ts', `
interface User {
id: number;
name: string;
}
const user: User = {
id: "123", // Type error!
name: 123 // Type error!
};
`);
const lsp = await workspace.lsp.start();
const errors: string[] = [];
lsp.on('diagnostics', (uri, diagnostics) => {
for (const d of diagnostics) {
if (d.severity === 1) { // Error
errors.push(`Line ${d.range.start.line + 1}: ${d.message}`);
}
}
});
lsp.didOpen('file:///workspace/test.ts', 'typescript',
await workspace.files.read('test.ts'));
// Wait for diagnostics
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Type errors found:');
errors.forEach(e => console.log(` ${e}`));
await lsp.shutdown();TypeScript Support
The SDK is written in TypeScript and provides complete type definitions:
import type {
Workspace,
RuntimeId,
FileEntry,
GitCommit,
ProcessInfo,
LspDiagnostic,
WorkspaceMetrics,
CpuMetrics,
MemoryMetrics
} from '@workspace-agent/sdk';Requirements
- Node.js 18+
- Workspace API server running (default: http://localhost:18080)
License
MIT
