> ## Documentation Index
> Fetch the complete documentation index at: https://botmesh.afaya.com.co/llms.txt
> Use this file to discover all available pages before exploring further.

# ConversationControls

> Interface exported by @botmesh/core.

Defined in: [conversations/controls.ts:46](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L46)

## Extends

* [`ConversationControlsBase`](https://botmesh.afaya.com.co/api/core/interfaces/ConversationControlsBase)

## Properties

### state

```ts theme={null}
state: Record<string, unknown>;
```

Defined in: [conversations/ConversationRuntime.ts:88](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/ConversationRuntime.ts#L88)

#### Inherited from

[`ConversationControlsBase`](https://botmesh.afaya.com.co/api/core/interfaces/ConversationControlsBase).[`state`](https://botmesh.afaya.com.co/api/core/interfaces/ConversationControlsBase#state)

***

### lang

```ts theme={null}
readonly lang: string;
```

Defined in: [conversations/controls.ts:129](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L129)

The conversation's current language (see [t](#t)).

## Methods

### waitAny()

```ts theme={null}
waitAny(opts?): Promise<RuntimeMessage>;
```

Defined in: [conversations/ConversationRuntime.ts:86](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/ConversationRuntime.ts#L86)

#### Parameters

| Parameter | Type |
| - | - |
| `opts?` | [`ResolvedWaitOptions`](https://botmesh.afaya.com.co/api/core/interfaces/ResolvedWaitOptions) |

#### Returns

`Promise`\<[`RuntimeMessage`](https://botmesh.afaya.com.co/api/core/interfaces/RuntimeMessage)>

#### Inherited from

[`ConversationControlsBase`](https://botmesh.afaya.com.co/api/core/interfaces/ConversationControlsBase).[`waitAny`](https://botmesh.afaya.com.co/api/core/interfaces/ConversationControlsBase#waitany)

***

### say()

```ts theme={null}
say(text): Promise<void>;
```

Defined in: [conversations/ConversationRuntime.ts:87](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/ConversationRuntime.ts#L87)

#### Parameters

| Parameter | Type |
| - | - |
| `text` | `string` |

#### Returns

`Promise`\<`void`>

#### Inherited from

[`ConversationControlsBase`](https://botmesh.afaya.com.co/api/core/interfaces/ConversationControlsBase).[`say`](https://botmesh.afaya.com.co/api/core/interfaces/ConversationControlsBase#say)

***

### end()

```ts theme={null}
end(farewell?): never;
```

Defined in: [conversations/ConversationRuntime.ts:89](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/ConversationRuntime.ts#L89)

#### Parameters

| Parameter | Type |
| - | - |
| `farewell?` | `string` |

#### Returns

`never`

#### Inherited from

[`ConversationControlsBase`](https://botmesh.afaya.com.co/api/core/interfaces/ConversationControlsBase).[`end`](https://botmesh.afaya.com.co/api/core/interfaces/ConversationControlsBase#end)

***

### ask()

#### Call Signature

```ts theme={null}
ask<T>(text, opts): Promise<T>;
```

Defined in: [conversations/controls.ts:54](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L54)

Send `text` and wait for a text answer. With `{ schema }` (any zod-compatible `safeParse`)
the answer is parsed and the PARSED value is returned (`z.coerce.number()` → `number`); a
rejected answer re-prompts with `otherwise`, else the schema's first issue message.
A native button or list tap that carries text (`type: 'buttons' | 'list'` with a non-empty
`body`, the button id or selected title) counts as a typed answer, as in [choose](#choose).

##### Type Parameters

| Type Parameter |
| - |
|  `T` |

##### Parameters

| Parameter | Type |
| - | - |
| `text` | `string` |
| `opts` | [`SchemaWaitOptions`](https://botmesh.afaya.com.co/api/core/type-aliases/SchemaWaitOptions)\<`T`> |

##### Returns

`Promise`\<`T`>

#### Call Signature

```ts theme={null}
ask(text, opts?): Promise<string>;
```

Defined in: [conversations/controls.ts:55](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L55)

##### Parameters

| Parameter | Type |
| - | - |
| `text` | `string` |
| `opts?` | [`WaitOptions`](https://botmesh.afaya.com.co/api/core/interfaces/WaitOptions) |

##### Returns

`Promise`\<`string`>

***

### waitText()

#### Call Signature

```ts theme={null}
waitText<T>(opts): Promise<T>;
```

Defined in: [conversations/controls.ts:57](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L57)

Wait for a text message or a button/list tap with text (no prompt). Accepts `{ schema }` like [ask](#ask).

##### Type Parameters

| Type Parameter |
| - |
|  `T` |

##### Parameters

| Parameter | Type |
| - | - |
| `opts` | [`SchemaWaitOptions`](https://botmesh.afaya.com.co/api/core/type-aliases/SchemaWaitOptions)\<`T`> |

##### Returns

`Promise`\<`T`>

#### Call Signature

```ts theme={null}
waitText(opts?): Promise<string>;
```

Defined in: [conversations/controls.ts:58](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L58)

##### Parameters

| Parameter | Type |
| - | - |
| `opts?` | [`WaitOptions`](https://botmesh.afaya.com.co/api/core/interfaces/WaitOptions) |

##### Returns

`Promise`\<`string`>

***

### waitMedia()

```ts theme={null}
waitMedia(types?, opts?): Promise<RuntimeMessage>;
```

Defined in: [conversations/controls.ts:59](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L59)

#### Parameters

| Parameter | Type |
| - | - |
| `types?` | [`WaitMediaType`](https://botmesh.afaya.com.co/api/core/type-aliases/WaitMediaType)\[] |
| `opts?` | [`WaitOptions`](https://botmesh.afaya.com.co/api/core/interfaces/WaitOptions) |

#### Returns

`Promise`\<[`RuntimeMessage`](https://botmesh.afaya.com.co/api/core/interfaces/RuntimeMessage)>

***

### waitLocation()

```ts theme={null}
waitLocation(opts?): Promise<InboundLocation>;
```

Defined in: [conversations/controls.ts:67](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L67)

Wait for a shared location (`type: 'location'` with a normalized `sharedLocation`) and
resolve with it. Anything else re-prompts with `otherwise` (default: the localized
`core.wait.location`) and counts against `maxAttempts`; `validate(body, message)` can reject a
location (`message.sharedLocation`), e.g. a live one. A location message whose provider
could not read valid coordinates is treated as "anything else".

#### Parameters

| Parameter | Type |
| - | - |
| `opts?` | [`WaitOptions`](https://botmesh.afaya.com.co/api/core/interfaces/WaitOptions) |

#### Returns

`Promise`\<[`InboundLocation`](https://botmesh.afaya.com.co/api/core/interfaces/InboundLocation)>

***

### choose()

```ts theme={null}
choose(
   prompt, 
   options, 
   opts?
): Promise<string>;
```

Defined in: [conversations/controls.ts:68](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L68)

#### Parameters

| Parameter | Type |
| - | - |
| `prompt` | `string` |
| `options` | `Record`\<`string`, `string`> |
| `opts?` | [`WaitOptions`](https://botmesh.afaya.com.co/api/core/interfaces/WaitOptions) |

#### Returns

`Promise`\<`string`>

***

### goto()

```ts theme={null}
goto(name, args?): never;
```

Defined in: [conversations/controls.ts:69](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L69)

#### Parameters

| Parameter | Type |
| - | - |
| `name` | `string` |
| `args?` | `unknown` |

#### Returns

`never`

***

### retry()

```ts theme={null}
retry<T>(message?): Promise<T>;
```

Defined in: [conversations/controls.ts:107](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L107)

Re-run the most recent wait (`ask` / `waitText` / `waitMedia` / `choose` / `waitAny`) with
its original options (`validate`, `filter`, `timeout`, `otherwise`, `maxAttempts`/`retries`).

Before waiting again it re-sends the wait's prompt — the `ask` question or the `choose`
menu — or `message` instead (for `choose`, `message` replaces only the menu header; the
numbered options are kept). Waits without a prompt send just `message`, if given;
`c.retry('')` waits again without sending anything.

**Async conversations** (`bot.conversation()`), and waits made inside the current
`flow().do()` step: resolves with the new value — `letra = await c.retry('Solo una letra')`.
`T` is that wait's result type: `string` for ask/waitText/choose, `RuntimeMessage` for
waitMedia/waitAny, `InboundLocation` for waitLocation.

**Flow steps** (`flow().do()`, a `.choose()` `then` action) whose most recent wait belongs
to an EARLIER step (`.ask()`, `.choose()`): rewinds the flow to that step — it is re-prompted
(with `message` instead of its prompt, when given), its state key gets the new answer, and
every following step (including the calling `.do()`) runs again. It throws a control signal
synchronously, so code after `c.retry()` in the step does not run (like `c.end()`).

**Budget:** each retry counts as one invalid attempt of that wait, shared with `validate`
rejections; reaching the wait's `maxAttempts` (default 3: the first answer plus 2 retries;
`retries: N` is `maxAttempts: N + 1`) throws `RetriesExceeded` (the conversation ends with
`retriesMessage`). A new wait starts a fresh budget. Use `maxAttempts: Infinity` on the
wait for unlimited retries.

**From a `c.idle()` callback** (outside the conversation's flow) it only re-prompts the
wait the conversation is parked on — the conversation still receives the answer — and
resolves with that answer (`undefined` if the wait ends another way). If no wait is pending
(the conversation is busy between waits, or has not waited yet) it does nothing and
resolves `undefined`; it never re-asks an answered question or rewinds a flow.

With no previous wait (in the conversation itself) it rejects with `RetryUnavailableError`.
Always `await` (or `return`) it: the conversation has one pending-wait slot, so a wait
started while an un-awaited retry is still waiting is refused with `ConcurrentWaitError`
(the conversation ends through the error path).

#### Type Parameters

| Type Parameter | Default type |
| - | - |
|  `T` | `string` |

#### Parameters

| Parameter | Type |
| - | - |
| `message?` | `string` |

#### Returns

`Promise`\<`T`>

***

### idle()

```ts theme={null}
idle(duration, callback): void;
```

Defined in: [conversations/controls.ts:119](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L119)

Arm an inactivity watchdog: `callback` runs once when `duration` (`'30s'`, `'2m'`, ms…)
passes without an inbound message from this conversation's user; each inbound message
reschedules it and re-arms it after it fired. The callback may reply, `c.end(farewell)` /
`c.goto(name)` to finish the conversation (applied at the pending wait), or `c.retry()` to
re-prompt the pending wait (it cannot start new waits). Other errors go to the bot
`'error'` event. `duration` accepts the same formats as `bot.onIdle()` (`'1d'`,
`'10 minutes'`…) up to 2^31 − 1 ms (about 24.8 days). Calling it again replaces the
previous watchdog; it is disarmed automatically when the conversation ends or is aborted.
Independent from the wait `timeout` (which ends the conversation with `timeoutMessage`).

#### Parameters

| Parameter | Type |
| - | - |
| `duration` | `string` \| `number` |
| `callback` | [`IdleCallback`](https://botmesh.afaya.com.co/api/core/type-aliases/IdleCallback) |

#### Returns

`void`

***

### idleClear()

```ts theme={null}
idleClear(): void;
```

Defined in: [conversations/controls.ts:121](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L121)

Disarm the watchdog armed with [idle](#idle) (no-op if none).

#### Returns

`void`

***

### t()

```ts theme={null}
t(key, params?): string;
```

Defined in: [conversations/controls.ts:127](https://github.com/andresayac/botmesh/blob/main/packages/core/src/conversations/controls.ts#L127)

Translate `key` in the conversation's current language — that of the latest message
the user sent to it (so a `ctx.setLang()` mid-conversation is honoured). Same
semantics as `ctx.t`.

#### Parameters

| Parameter | Type |
| - | - |
| `key` | `string` |
| `params?` | [`TranslateParams`](https://botmesh.afaya.com.co/api/core/type-aliases/TranslateParams) |

#### Returns

`string`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.