# Agent API Documentation

This document provides comprehensive documentation for the BlockWerk Agent API, designed specifically for AI models and programmatic interaction.

## Quick Start

The Agent API is globally available at `window.blockwerk.agent` when the BlockWerk application is running.

```javascript
// Access the API
const agent = window.blockwerk.agent;

// Create a simple diagram
agent.clear();
const source = agent.addBlock('Constant', 100, 100);
const display = agent.addBlock('NumericDisplay', 400, 100);
agent.connect(source, 'out', display, 'in');
```

## API Reference

### State Access Methods

#### `getState()`
Returns the current state of the canvas.

**Returns:**
```typescript
{
  blocks: BlockState[],
  connections: Connection[],
  currentProjectId: string | null,
  currentProjectName: string | null,
  zoom: number
}
```

**Example:**
```javascript
const state = agent.getState();
console.log(`Canvas has ${state.blocks.length} blocks`);
```

#### `getLibrary()`
Returns the complete block library with all available block types.

**Returns:**
```typescript
{
  id: string,
  name: string,
  version: string,
  blocks: BlockDefinition[]
}
```

**Example:**
```javascript
const library = agent.getLibrary();
const blockTypes = library.blocks.map(b => b.type);
console.log('Available blocks:', blockTypes);
```

### Canvas Manipulation Methods

#### `addBlock(type, x, y)`
Adds a new block to the canvas.

**Parameters:**
- `type` (string): The block type (e.g., 'Constant', 'Sum', 'Integrator')
- `x` (number): X coordinate in pixels
- `y` (number): Y coordinate in pixels

**Returns:** `string | null` - The ID of the newly created block, or null if failed

**Example:**
```javascript
const blockId = agent.addBlock('PIDController', 200, 150);
if (blockId) {
  console.log('Created block:', blockId);
}
```

#### `connect(fromBlockId, fromPortId, toBlockId, toPortId)`
Creates a connection between two blocks.

**Parameters:**
- `fromBlockId` (string): Source block ID
- `fromPortId` (string): Source port ID (typically 'out' for single-output blocks)
- `toBlockId` (string): Target block ID
- `toPortId` (string): Target port ID (typically 'in' for single-input blocks)

**Returns:** `boolean` - true if connection was successful

**Example:**
```javascript
const success = agent.connect('block-1', 'out', 'block-2', 'in');
if (success) {
  console.log('Connection established');
}
```

#### `deleteBlock(id)`
Removes a block and all its connections from the canvas.

**Parameters:**
- `id` (string): Block ID to delete

**Example:**
```javascript
agent.deleteBlock('block-1');
```

#### `moveBlock(id, x, y)`
Moves a block to a new position.

**Parameters:**
- `id` (string): Block ID
- `x` (number): New X coordinate
- `y` (number): New Y coordinate

**Example:**
```javascript
agent.moveBlock('block-1', 300, 200);
```

#### `updateParams(id, params)`
Updates the parameters of a block.

**Parameters:**
- `id` (string): Block ID
- `params` (object): Parameter key-value pairs

**Example:**
```javascript
// Update a Constant block's value
agent.updateParams('block-1', { value: 5.0 });

// Update PID controller gains
agent.updateParams('block-2', { 
  kp: 1.0, 
  ki: 0.1, 
  kd: 0.01 
});
```

### Project Operations

#### `clear()`
Clears the entire canvas, removing all blocks and connections.

**Example:**
```javascript
agent.clear();
```

#### `exportJson()`
Exports the current project as a JSON string.

**Returns:** `string` - JSON representation of the project

**Example:**
```javascript
const projectJson = agent.exportJson();
localStorage.setItem('myProject', projectJson);
```

#### `loadJson(json)`
Loads a project from a JSON string.

**Parameters:**
- `json` (string): JSON project data

**Returns:** `boolean` - true if load was successful

**Example:**
```javascript
const projectJson = localStorage.getItem('myProject');
const success = agent.loadJson(projectJson);
```

### AI Helper Methods

#### `describeCanvas()`
Generates a human-readable text description of the current canvas state.

**Returns:** `string` - Text description of blocks and connections

**Example:**
```javascript
const description = agent.describeCanvas();
console.log(description);
// Output:
// Canvas contains 3 blocks and 2 connections.
// 
// Blocks:
// - [block-1] Constant at (100, 100)
//   Params: {"value":1}
// - [block-2] Integrator at (300, 100)
// - [block-3] Scope at (500, 100)
// 
// Connections:
// - block-1:out -> block-2:in
// - block-2:out -> block-3:in
```

## Common Block Types

Here are the most commonly used block types:

### Sources
- `Constant` - Outputs a constant value
- `Step` - Step input signal
- `Ramp` - Ramp input signal
- `SignalGenerator` - Generates various waveforms (sine, square, etc.)

### Math Operations
- `Sum` - Adds or subtracts inputs
- `Gain` - Multiplies input by a constant
- `Product` - Multiplies inputs together
- `Integrator` - Integrates the input signal
- `Derivative` - Differentiates the input signal

### Control Systems
- `PIDController` - PID controller
- `TransferFunction` - Transfer function block
- `StateSpace` - State-space model

### Visualization
- `Scope` - Plots signals over time
- `NumericDisplay` - Shows numeric value
- `XYPlot` - XY plotting

## Common Patterns

### Creating a Simple Control Loop
```javascript
agent.clear();

// Create blocks
const setpoint = agent.addBlock('Constant', 100, 100);
const error = agent.addBlock('Sum', 250, 100);
const controller = agent.addBlock('PIDController', 400, 100);
const plant = agent.addBlock('TransferFunction', 550, 100);
const scope = agent.addBlock('Scope', 700, 100);

// Configure blocks
agent.updateParams(setpoint, { value: 1.0 });
agent.updateParams(error, { signs: '+-' });
agent.updateParams(controller, { kp: 1.0, ki: 0.1, kd: 0.01 });

// Create connections
agent.connect(setpoint, 'out', error, 'in1');
agent.connect(error, 'out', controller, 'in');
agent.connect(controller, 'out', plant, 'in');
agent.connect(plant, 'out', scope, 'in');
agent.connect(plant, 'out', error, 'in2'); // Feedback
```

### Creating a Signal Processing Chain
```javascript
agent.clear();

// Create signal chain
const generator = agent.addBlock('SignalGenerator', 100, 150);
const gain = agent.addBlock('Gain', 300, 150);
const filter = agent.addBlock('TransferFunction', 500, 150);
const scope = agent.addBlock('Scope', 700, 150);

// Configure
agent.updateParams(generator, { waveform: 'sine', frequency: 1.0 });
agent.updateParams(gain, { gain: 2.0 });

// Connect
agent.connect(generator, 'out', gain, 'in');
agent.connect(gain, 'out', filter, 'in');
agent.connect(filter, 'out', scope, 'in');
```

### Layout Optimization
```javascript
// Get current state
const state = agent.getState();

// Arrange blocks in a grid
const gridSpacing = 200;
state.blocks.forEach((block, index) => {
  const row = Math.floor(index / 4);
  const col = index % 4;
  agent.moveBlock(block.id, 100 + col * gridSpacing, 100 + row * gridSpacing);
});
```

## Port Naming Conventions

Most blocks follow these conventions:

**Single Input/Output:**
- Input: `'in'`
- Output: `'out'`

**Multiple Inputs (e.g., Sum block):**
- Inputs: `'in1'`, `'in2'`, `'in3'`, etc.

**Multiple Outputs (rare):**
- Outputs: `'out1'`, `'out2'`, etc.

**Special Blocks:**
- PID Controller: input `'in'`, output `'out'`
- Transfer Function: input `'in'`, output `'out'`
- State Space: input `'u'`, output `'y'`

## Tips for LLM Usage

1. **Always check block types first:**
   ```javascript
   const library = agent.getLibrary();
   const availableTypes = library.blocks.map(b => b.type);
   ```

2. **Use describeCanvas() to understand current state:**
   ```javascript
   const description = agent.describeCanvas();
   // Parse this to understand what's already on the canvas
   ```

3. **Store block IDs for later reference:**
   ```javascript
   const blocks = {
     source: agent.addBlock('Constant', 100, 100),
     processor: agent.addBlock('Gain', 300, 100),
     sink: agent.addBlock('Scope', 500, 100)
   };
   
   agent.connect(blocks.source, 'out', blocks.processor, 'in');
   agent.connect(blocks.processor, 'out', blocks.sink, 'in');
   ```

4. **Handle errors gracefully:**
   ```javascript
   const blockId = agent.addBlock('UnknownBlock', 100, 100);
   if (!blockId) {
     console.log('Failed to create block - type may not exist');
   }
   ```

5. **Use getState() to verify changes:**
   ```javascript
   const before = agent.getState();
   agent.addBlock('Constant', 100, 100);
   const after = agent.getState();
   console.log(`Added ${after.blocks.length - before.blocks.length} blocks`);
   ```

## Complete Example: Building a System from Scratch

```javascript
// 1. Clear canvas
agent.clear();

// 2. Get available block types
const library = agent.getLibrary();
console.log('Available blocks:', library.blocks.map(b => b.type).join(', '));

// 3. Create a complete control system
const blocks = {
  reference: agent.addBlock('Constant', 50, 200),
  error: agent.addBlock('Sum', 200, 200),
  controller: agent.addBlock('PIDController', 350, 200),
  plant: agent.addBlock('TransferFunction', 500, 200),
  sensor: agent.addBlock('Gain', 500, 350),
  scope1: agent.addBlock('Scope', 650, 200),
  scope2: agent.addBlock('Scope', 350, 350)
};

// 4. Configure parameters
agent.updateParams(blocks.reference, { value: 1.0 });
agent.updateParams(blocks.error, { signs: '+-' });
agent.updateParams(blocks.controller, { kp: 2.0, ki: 1.0, kd: 0.5 });
agent.updateParams(blocks.sensor, { gain: 1.0 });

// 5. Create connections
agent.connect(blocks.reference, 'out', blocks.error, 'in1');
agent.connect(blocks.error, 'out', blocks.controller, 'in');
agent.connect(blocks.controller, 'out', blocks.plant, 'in');
agent.connect(blocks.plant, 'out', blocks.scope1, 'in');
agent.connect(blocks.plant, 'out', blocks.sensor, 'in');
agent.connect(blocks.sensor, 'out', blocks.error, 'in2');
agent.connect(blocks.error, 'out', blocks.scope2, 'in');

// 6. Verify the result
console.log(agent.describeCanvas());

// 7. Export for later use
const projectJson = agent.exportJson();
console.log('Project saved:', projectJson.length, 'characters');
```

## Troubleshooting

**Block not appearing:**
- Check if the block type exists in the library
- Verify coordinates are within visible canvas area (typically 0-2000 pixels)

**Connection failing:**
- Ensure both blocks exist
- Verify port names are correct (use `getState()` to inspect block definitions)
- Check that the target port doesn't already have a connection (most inputs accept only one connection)

**Parameters not updating:**
- Verify parameter names match the block definition
- Check parameter types (numbers vs strings)
- Use `getState()` to inspect current parameter values
---
*Back to [Top](#agent-api-documentation)*
