# Needle Inspector Agent — Tool Documentation

This file is auto-generated alongside `agent.js` and describes all available APIs and tools.
Inject `agent.js` into any page with a Three.js scene to access these tools via `window.__NEEDLE_INSPECTOR__`.

> **IMPORTANT: All API methods are async and return Promises. You MUST use `await` when calling them.**
> Calling without `await` returns a Promise object (`{}`) instead of the actual data.

## Setup

```js
// Inject the inspector (use addInitScript for pages that load Three.js immediately)
await page.addScriptTag({ url: 'https://inspector.needle.tools/agent.js' });

// Wait for scene detection
await page.waitForFunction(() => window.__NEEDLE_INSPECTOR__?.ready);
```

## API Methods

All methods are available on `window.__NEEDLE_INSPECTOR__` and return Promises.
**You MUST `await` every call**, either inside an async `page.evaluate` or by awaiting the result.

### `ready: boolean`

True once the inspector has detected a Three.js scene and booted its services.

```js
await page.waitForFunction(() => window.__NEEDLE_INSPECTOR__?.ready);
```

### `getTools(): Promise<ToolDefinition[]>`

List all available tools with their names, descriptions, and JSON input schemas.

```js
const tools = await page.evaluate(async () => await window.__NEEDLE_INSPECTOR__.getTools());
```

### `callTool(name: string, args?: object): Promise<any>`

Call any registered tool by name. Returns the tool's JSON result.

```js
const result = await page.evaluate(async () =>
  await window.__NEEDLE_INSPECTOR__.callTool('property_find', { nodeQuery: 'Mesh', includeValues: true })
);
```

### `getHierarchy(maxDepth?: number): Promise<SerializedNode[]>`

Get the full scene hierarchy as a tree of serialized nodes. Default maxDepth is 10.

```js
const tree = await page.evaluate(async () => await window.__NEEDLE_INSPECTOR__.getHierarchy());
```

### `getSelectedNodes(): Promise<SerializedNode[]>`

Get the currently selected nodes in the scene.

```js
const selected = await page.evaluate(async () => await window.__NEEDLE_INSPECTOR__.getSelectedNodes());
```

### `selectNode(id: string): Promise<{ success: boolean; message?: string }>`

Select a node in the scene by its ID.

```js
await page.evaluate(async () => await window.__NEEDLE_INSPECTOR__.selectNode('node-abc'));
```

### `searchNodes(query: string, maxResults?: number): Promise<SerializedNode[]>`

Search for nodes by name. Returns up to maxResults (default 20) matching nodes.

```js
const nodes = await page.evaluate(async () => await window.__NEEDLE_INSPECTOR__.searchNodes('player'));
```

### `getProperties(nodeId: string): Promise<any>`

Get all properties of a node with their values. Shorthand for callTool('property_find', ...).

```js
const props = await page.evaluate(async (id) => await window.__NEEDLE_INSPECTOR__.getProperties(id), nodeId);
```

### `findProperties(args: { nodeQuery?, nodesIds?, propertyQuery?, includeValues? }): Promise<any>`

Search for properties across nodes. Shorthand for the property_find tool.

```js
const found = await page.evaluate(async () =>
  await window.__NEEDLE_INSPECTOR__.findProperties({ nodeQuery: 'player', propertyQuery: 'position' })
);
```

### `readProperty(nodeId: string, propertyPath: string): Promise<any>`

Read a specific property value by node ID and path. Shorthand for the property_read tool.

```js
const val = await page.evaluate(async (id) =>
  await window.__NEEDLE_INSPECTOR__.readProperty(id, 'position.x')
, nodeId);
```

## Node Format

Hierarchy nodes are returned as:

```json
{
  "id": "string",
  "name": "string",
  "type": "string (e.g. Mesh, Light, Camera, Scene)",
  "label": "string",
  "visible": true,
  "selected": false,
  "expanded": false,
  "childCount": 0,
  "children": [
    "(nested nodes, if within maxDepth)"
  ]
}
```

## Tools

These tools can be called via `callTool(name, args)` or discovered at runtime via `getTools()`.

### `property_find`

Find property information of hierarchy nodes/objects in the scene. Supports two modes: (1) Direct query by node IDs, or (2) Search for nodes first, then query their properties. Both propertyQuery and propertyType support regex patterns for flexible matching (case-insensitive).

**Parameters:**

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `nodesIds` | array<string> | No | — | Array of node IDs to get properties for. Use this when you already know the node IDs. |
| `nodeQuery` | string | No | — | Search query to find nodes first (e.g., 'player' to find nodes with 'player' in their name). Multiple terms can be separated by commas. |
| `nodeType` | string | No | — | Filter nodes by type when using nodeQuery. Supports regex patterns (e.g., 'Mesh', 'Light.*', 'Mesh|Camera'). |
| `nodeMaxResults` | number | No | `20` | Maximum number of nodes to find when using nodeQuery. |
| `propertyQuery` | string | No | — | Optional regex query to filter properties by name (e.g., 'color' to find color-related properties). |
| `propertyType` | string | No | — | Optional regex filter by property type (e.g., 'number', 'vector.*', 'color|material'). |
| `includeValues` | boolean | No | `false` | Whether to include actual property values in the response. Can produce large output. |
| `maxValueSize` | number | No | `200` | Max character length for stringified property values when includeValues is true. |
| `maxResults` | number | No | `50` | Maximum number of properties to return per node. |
| `offset` | number | No | `0` | Number of matching properties to skip (for pagination). |

<details><summary>JSON Schema</summary>

```json
{
  "type": "object",
  "properties": {
    "nodesIds": {
      "type": "array",
      "description": "Array of node IDs to get properties for. Use this when you already know the node IDs.",
      "items": {
        "type": "string"
      }
    },
    "nodeQuery": {
      "type": "string",
      "description": "Search query to find nodes first (e.g., 'player' to find nodes with 'player' in their name). Multiple terms can be separated by commas."
    },
    "nodeType": {
      "type": "string",
      "description": "Filter nodes by type when using nodeQuery. Supports regex patterns (e.g., 'Mesh', 'Light.*', 'Mesh|Camera')."
    },
    "nodeMaxResults": {
      "type": "number",
      "description": "Maximum number of nodes to find when using nodeQuery.",
      "default": 20
    },
    "propertyQuery": {
      "type": "string",
      "description": "Optional regex query to filter properties by name (e.g., 'color' to find color-related properties)."
    },
    "propertyType": {
      "type": "string",
      "description": "Optional regex filter by property type (e.g., 'number', 'vector.*', 'color|material')."
    },
    "includeValues": {
      "type": "boolean",
      "description": "Whether to include actual property values in the response. Can produce large output.",
      "default": false
    },
    "maxValueSize": {
      "type": "number",
      "description": "Max character length for stringified property values when includeValues is true.",
      "default": 200
    },
    "maxResults": {
      "type": "number",
      "description": "Maximum number of properties to return per node.",
      "default": 50
    },
    "offset": {
      "type": "number",
      "description": "Number of matching properties to skip (for pagination).",
      "default": 0
    }
  },
  "required": []
}
```

</details>

### `component_search`

Search for Needle Engine components in the scene. Finds nodes that have components matching the query (by component type name, e.g. 'OrbitControls', 'Camera', 'Light.*'). Returns nodes with their matched components.

**Parameters:**

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `query` | string | No | — | Regex pattern to match component type names (e.g. 'OrbitControls', 'Camera', 'Light.*'). Case-insensitive. If not provided, returns all components. |
| `nodeQuery` | string | No | — | Optional search query to narrow down to specific nodes by name first. Multiple terms can be separated by commas. |
| `maxResults` | number | No | `50` | Maximum number of nodes to return. |
| `includeProperties` | boolean | No | `false` | Whether to include component properties in the response. |
| `maxValueSize` | number | No | `200` | Max character length for each stringified property value when includeProperties is true. |

<details><summary>JSON Schema</summary>

```json
{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "Regex pattern to match component type names (e.g. 'OrbitControls', 'Camera', 'Light.*'). Case-insensitive. If not provided, returns all components."
    },
    "nodeQuery": {
      "type": "string",
      "description": "Optional search query to narrow down to specific nodes by name first. Multiple terms can be separated by commas."
    },
    "maxResults": {
      "type": "number",
      "description": "Maximum number of nodes to return.",
      "default": 50
    },
    "includeProperties": {
      "type": "boolean",
      "description": "Whether to include component properties in the response.",
      "default": false
    },
    "maxValueSize": {
      "type": "number",
      "description": "Max character length for each stringified property value when includeProperties is true.",
      "default": 200
    }
  },
  "required": []
}
```

</details>

### `property_read`

Read the value or metadata of a specific property of a hierarchy node/object in the scene by its ID.

**Parameters:**

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `nodeId` | string | Yes | — | ID of the node to get the property from. |
| `propertyPath` | string | Yes | — | Path of the property to read (e.g., 'position.x', 'material.color'). |
| `value` | boolean | No | `true` | Whether to include the property value in the response. |
| `metadata` | boolean | No | `false` | Whether to include property metadata (UI settings, description, available options). |

<details><summary>JSON Schema</summary>

```json
{
  "type": "object",
  "properties": {
    "nodeId": {
      "type": "string",
      "description": "ID of the node to get the property from."
    },
    "propertyPath": {
      "type": "string",
      "description": "Path of the property to read (e.g., 'position.x', 'material.color')."
    },
    "value": {
      "type": "boolean",
      "description": "Whether to include the property value in the response.",
      "default": true
    },
    "metadata": {
      "type": "boolean",
      "description": "Whether to include property metadata (UI settings, description, available options).",
      "default": false
    }
  },
  "required": [
    "nodeId",
    "propertyPath"
  ]
}
```

</details>

## Typical Workflow

```js
// 1. Inject and wait
await page.addScriptTag({ url: 'https://inspector.needle.tools/agent.js' });
await page.waitForFunction(() => window.__NEEDLE_INSPECTOR__?.ready);

// 2. Explore the scene (note: await inside evaluate!)
const tree = await page.evaluate(async () => await window.__NEEDLE_INSPECTOR__.getHierarchy(3));

// 3. Find a node of interest
const meshes = await page.evaluate(async () => await window.__NEEDLE_INSPECTOR__.searchNodes('player'));

// 4. Inspect its properties
const nodeId = meshes[0].id;
const props = await page.evaluate(async (id) => await window.__NEEDLE_INSPECTOR__.getProperties(id), nodeId);

// 5. Read a specific value
const pos = await page.evaluate(async (id) => await window.__NEEDLE_INSPECTOR__.readProperty(id, 'position.x'), nodeId);
```
