# Seletores, predefinições e prompts

> Em TypeScript, leia as opções válidas dos seletores, preencha-os descrevendo a cena, carregue predefinições e melhore prompts com o Assistente de prompt.

Source: https://nodaro.ai/pt-BR/docs/developers/sdk/pickers-and-prompts

Os **seletores** são os nós de Controles criativos, como [**Clima** (Mood)](https://nodaro.ai/docs/nodes/creative-controls/mood) ou **Lente** (Lens), cuja escolha adiciona um texto testado ao prompt. **`client.pickerCatalogs`** e **`client.catalogs`** retornam as opções válidas de cada seletor, e `analyzeText()` preenche seletores a partir de uma descrição de cena. **`client.presets`** lê as configurações de nó salvas, e **`client.promptHelper`** é o Assistente de prompt (Prompt Wizard), que melhora prompts para qualquer nó de geração. Veja [Controles criativos](https://nodaro.ai/docs/guides/creative-controls) e [Catálogos de seletores](https://nodaro.ai/docs/developers/picker-catalogs) para os conceitos.

## Métodos
| Método | O que faz |
| --- | --- |
| [`pickerCatalogs.list()`](#pickercatalogslist) | Lista todos os seletores e o catálogo de cada um |
| [`pickerCatalogs.get(nodeType, opts?)`](#pickercatalogsgetnodetype-opts) | Lê as opções de um seletor |
| [`pickerCatalogs.analyzeText(params)`](#pickercatalogsanalyzetextparams) | Preenche as escolhas dos seletores a partir de uma descrição em texto |
| [`catalogs.list(opts?)`](#catalogslistopts) | Lê todos os catálogos desta implantação em uma chamada |
| [`presets.list(nodeType?)`](#presetslistnodetype) | Lista as suas predefinições salvas |
| [`presets.listGroups(nodeType?)`](#presetslistgroupsnodetype) | Lista as suas pastas e seções de predefinições |
| [`presets.listFactory(nodeType)`](#presetslistfactorynodetype) | Lista as predefinições integradas de um tipo de nó |
| [`promptHelper.analyze(input)`](#prompthelperanalyzeinput) | Transforma uma ideia vaga em perguntas |
| [`promptHelper.generate(input)`](#prompthelpergenerateinput) | Monta um prompt a partir das respostas |
| [`promptHelper.enhance(input)`](#prompthelperenhanceinput) | Melhora um prompt em uma etapa |

## client.pickerCatalogs
As listas de opções dos nós de seletor. Os dois métodos de leitura são públicos, não precisam de token e podem ser mantidos em cache pelo servidor por 5 minutos. Se o seu código pode importar `@nodaro/prompts`, os mesmos catálogos vêm nesse pacote como dados tipados; estes métodos são para clientes que não conseguem incluí-lo no bundle.

### pickerCatalogs.list()
Lista todos os seletores (`GET /v1/picker-catalogs`).

```ts
list(): Promise<{ data: PickerCatalogSummary[] }>
```

```ts
const { data: pickers } = await client.pickerCatalogs.list()
const mood = pickers.find((p) => p.nodeType === "mood")
```

Cada entrada tem `nodeType`, `label`, `catalogId`, `kind` (`single` ou `multi`), `valueField` em um seletor de uma dimensão ou `fields` em um de várias dimensões, `optionCount` e `imageCount`, o número de opções com imagem.

### pickerCatalogs.get(nodeType, opts?)
Lê as opções de um seletor (`GET /v1/picker-catalogs/:nodeType`). Um seletor de uma dimensão, como Clima, tem `options`. Um seletor de várias dimensões, como **Pessoa** (Person), tem `dimensions`, cada uma `{ field, label, options }`. Alguns seletores de uma dimensão também têm configurações extras ao lado da escolha principal: `transition` e `character-fx` têm `position`, `duration` e `intensity`, e `character-motion` tem `position` e `pace`.

```ts
get(nodeType: string, opts?: { detail?: "compact" | "full"; category?: string; field?: string }): Promise<{ data: PickerCatalog }>
```

<TypeTable
type={{
nodeType: { type: 'string', required: true, description: "O tipo de nó do seletor, como mood, lens ou person." },
detail: { type: '"compact" | "full"', default: '"compact"', description: "compact retorna id, label, category, term, icon e imageUrl. full adiciona a description e o promptHint de cada opção." },
category: { type: 'string', description: "Seletores de uma dimensão: só as opções desta categoria." },
field: { type: 'string', description: "Só uma dimensão de um seletor de várias dimensões, ou uma configuração extra de um seletor de uma dimensão." },
}}
/>

```ts
const { data } = await client.pickerCatalogs.get("mood", { detail: "full" })
const serene = data.options?.find((o) => o.id === "serene")
console.log(serene?.term)       // the short phrase, added in Compact mode
console.log(serene?.promptHint) // the full sentence, added in Full mode
```

Lança `NotFoundError` para um tipo de nó desconhecido.

**Mostre `label`, adicione `term`.** Toda opção tem um `term` nos dois níveis de detalhe: a expressão profissional curta a colocar em um prompt. `label` serve só para exibição. Nunca derive um do outro. Uma opção que não adiciona nada, como `auto` ou `none`, tem um `term` vazio.

**Imagens.** Uma opção com imagem tem um `imageUrl` absoluto, nos dois níveis de detalhe. `person` e `styling` também retornam `sections`: os temas sob os quais o editor agrupa as configurações deles, cada um `{ label, fields, imageUrl? }`. As fotos e as artes de música e de voz são servidas pela própria instalação. As prévias renderizadas de visual vêm da CDN do Nodaro, e só o Nodaro Cloud as retorna. Os nomes dos arquivos trazem um hash do conteúdo, então você pode manter as imagens em cache sem expiração.

```ts
const { data: person } = await client.pickerCatalogs.get("person")
for (const section of person.sections ?? []) {
const settings = person.dimensions?.filter((d) => section.fields.includes(d.field)) ?? []
for (const setting of settings) {
for (const option of setting.options) renderTile(option.label, option.imageUrl)
}
}
```

**Movimento de personagem.** As opções de `character-motion` trazem um objeto `motion` opcional nos dois níveis de detalhe. Ele informa o que um movimento exige e em que estado deixa o personagem: `requires`, `startPose` e `endPose`, `endVisibility`, `handsAfter`, `needsFreeHands`, `kind`, `fixedPace`, `counterpart`, os `aliases` de busca e `deprecated` com um `replacementId`. Um campo ausente significa desconhecido. Mantenha os IDs aposentados ao carregar workflows salvos e esconda-os das novas escolhas. Veja [**Movimento de personagem** (Character Motion)](https://nodaro.ai/docs/nodes/creative-controls/character-motion).

### pickerCatalogs.analyzeText(params)
Preenche as escolhas dos seletores a partir de uma descrição de cena em texto livre (`POST /v1/text-to-picker`), a versão em texto do nó [**Descrever para seletor** (Describe to Picker)](https://nodaro.ai/docs/nodes/image/describe-to-picker). Retorna `pickerJson`, organizado por tipo de seletor e depois por dimensão, com o ID ou os IDs escolhidos. Carregue os seletores a partir dele como está e depois deixe o usuário ajustá-los. Custa créditos, cobrados como os do Descrever para seletor.

```ts
analyzeText(params: TextToPickerParams): Promise<{
jobId: string
pickerJson: Record<string, Record<string, string | string[]>>
gaps?: { missingItems: object[]; missingCategories: object[] }
}>
```

<TypeTable
type={{
text: { type: 'string', required: true, description: "A descrição da cena ou da tomada." },
targetPickers: { type: 'string[]', description: "Os tipos de seletor a preencher. Omita-o para preencher todos os seletores que podem ser analisados." },
instructions: { type: 'string', description: "Orientações extras para a análise." },
llmModel: { type: 'string', description: "O ID do modelo." },
reasoningEffort: { type: 'string', description: "O esforço de raciocínio, conforme o modelo." },
origin: { type: 'string', description: "O nome do seu app, armazenado no job." },
}}
/>

```ts
const { pickerJson, gaps } = await client.pickerCatalogs.analyzeText({
text: "Neon-soaked Tokyo alley at night, rain, handheld tracking shot, moody synthwave",
})
console.log(pickerJson["setting"], pickerJson["camera-motion"])
```

As dimensões sobre as quais o texto não diz nada ficam de fora: a análise não adivinha. `gaps` lista o que o texto descreve e nenhuma opção do catálogo representa bem, em `missingItems` e `missingCategories`. Mostre isso ao usuário como “não encontramos uma opção para X; escolha uma você mesmo”.

## client.catalogs
### catalogs.list(opts?)
Retorna todos os catálogos de seletores em uma chamada, como esta implantação os serve (`GET /v1/catalogs`). Uma implantação pode registrar pacotes de catálogo que substituem, ampliam ou ocultam opções. Um cliente que desenha os próprios seletores deve ler esta lista para respeitá-los. Ela é pública e pode ficar em cache por 5 minutos.

```ts
list(opts?: { detail?: "compact" | "full" }): Promise<{
curated: boolean
packs: number
version: number
data?: ProjectedCatalog[]
}>
```

<TypeTable
type={{
detail: { type: '"compact" | "full"', default: '"compact"', description: "compact retorna id, label, category, term e icon. full adiciona description e promptHint." },
}}
/>

```ts
const { curated, data } = await client.catalogs.list({ detail: "full" })
if (curated) {
const setting = data?.find((c) => c.catalogId === "setting")
console.log(setting?.options?.[0]?.term)
}
```

`data` só está presente quando a implantação registrou pacotes de catálogo (`curated: true`). Sem pacotes, os catálogos são os padrão: leia-os um por um com `pickerCatalogs.get()`. As opções trazem o mesmo `imageUrl`, e `person` e `styling` trazem as mesmas `sections`.

## client.presets
As suas predefinições de nó salvas e as integradas, só para leitura. O `data` de uma predefinição são as configurações salvas de um nó. Para aplicar uma predefinição, mescle o `data` dela nos dados de um nó quando montar um workflow. Um token OAuth precisa do escopo `presets:read`. Veja [Predefinições](https://nodaro.ai/docs/concepts/presets).

### presets.list(nodeType?)
Lista as suas predefinições salvas, das mais recentes para as mais antigas (`GET /v1/node-presets`).

```ts
list(nodeType?: string): Promise<NodePreset[]>
```

<TypeTable
type={{
nodeType: { type: 'string', description: "Só as predefinições deste tipo de nó, como generate-image." },
}}
/>

```ts
const presets = await client.presets.list("generate-image")
const cinematic = presets.find((p) => p.name === "Cinematic Portrait")
// apply: spread cinematic.data into the node's data when you create the workflow
```

Um `NodePreset` tem `id`, `nodeType`, `name`, `description`, `data`, `groupId`, `tags`, `sortOrder`, `createdAt` e `updatedAt`.

### presets.listGroups(nodeType?)
Lista as suas pastas e seções de predefinições (`GET /v1/node-preset-groups`).

```ts
listGroups(nodeType?: string): Promise<NodePresetGroup[]>
```

<TypeTable
type={{
nodeType: { type: 'string', description: "Só os grupos deste tipo de nó." },
}}
/>

```ts
const groups = await client.presets.listGroups("generate-image")
```

Cada grupo tem `id`, `nodeType`, `name`, `kind` (`folder` ou `section`), `sortOrder`, `createdAt` e `updatedAt`.

### presets.listFactory(nodeType)
Lista as predefinições integradas de um tipo de nó (`GET /v1/node-presets/factory`).

```ts
listFactory(nodeType: string): Promise<{ data: FactoryPreset[] }>
```

<TypeTable
type={{
nodeType: { type: 'string', required: true, description: "O tipo de nó, como generate-video." },
}}
/>

```ts
const { data } = await client.presets.listFactory("generate-video")
const orbit = data.find((p) => p.id === "generate-video/orbit-360")
```

## client.promptHelper
O Assistente de prompt: ajuda de IA para escrever prompts para nós de geração. Os três métodos enviam a requisição para `POST /v1/prompt-helper/wizard`, e cada chamada custa créditos. Veja [Assistente de prompt](https://nodaro.ai/docs/developers/api/prompt-wizard) para a visão REST.

Os três recebem estes campos comuns:

<TypeTable
type={{
nodeType: { type: 'string', required: true, description: "O nó para o qual é o prompt, como generate-image ou generate-video." },
provider: { type: 'string', description: "O modelo para o qual é o prompt." },
style: { type: 'string', description: "Um estilo a buscar." },
aspectRatio: { type: 'string', description: "O formato de quadro desejado." },
duration: { type: 'number', description: "A duração desejada do clipe, para vídeo." },
llmModel: { type: 'string', description: "O modelo de linguagem que escreve o prompt." },
reasoningEffort: { type: 'string', description: "none, low, medium, high, xhigh ou max, conforme o modelo. xhigh e max cobram um nível acima, até o nível premium." },
advancedMode: { type: 'boolean', description: "Só para modelos Gemini: usa a própria API do fabricante. Cobra um nível acima, até o nível premium." },
temperature: { type: 'number', description: "Com advancedMode: a temperatura de amostragem." },
maxTokens: { type: 'number', description: "Com advancedMode: o tamanho máximo da resposta, em tokens." },
nodeContext: { type: 'WizardNodeContext', description: "O que mais está conectado ao nó, para que o assistente leve isso em conta." },
userPreference: { type: 'string', description: "Uma preferência a seguir." },
workflowId: { type: 'string', description: "Um workflow sob o qual listar esta execução." },
}}
/>

A CLI oferece o mesmo com `nodaro prompt wizard`, `analyze`, `generate` e `enhance`, com `--llm-model` e `--reasoning-effort`. Veja a [CLI](https://nodaro.ai/docs/developers/cli).

### promptHelper.analyze(input)
Transforma uma ideia vaga em perguntas guiadas para um tipo de nó. Responda às perguntas e depois passe as respostas para `generate()`.

```ts
analyze(input: AnalyzeInput): Promise<{ jobId: string; questions: WizardQuestion[] }>
```

<TypeTable
type={{
prompt: { type: 'string', description: "A ideia vaga." },
'...': { type: 'common fields', description: "nodeType e os campos comuns acima." },
}}
/>

```ts
const { questions } = await client.promptHelper.analyze({
nodeType: "generate-image",
prompt: "a snow leopard",
})
```

### promptHelper.generate(input)
Monta um prompt otimizado a partir das respostas escolhidas. Cada seleção é `{ category, value, isCustom }`.

```ts
generate(input: GenerateInput): Promise<{ jobId: string; prompt: string; recommendedModel?: RecommendedModel }>
```

<TypeTable
type={{
selections: { type: 'WizardSelection[]', required: true, description: "As respostas escolhidas, cada uma { category, value, isCustom }." },
originalPrompt: { type: 'string', description: "A ideia vaga que deu origem às perguntas." },
'...': { type: 'common fields', description: "nodeType e os campos comuns acima." },
}}
/>

```ts
const { prompt, recommendedModel } = await client.promptHelper.generate({
nodeType: "generate-image",
selections: [{ category: "subject", value: "snow leopard", isCustom: false }],
})
```

### promptHelper.enhance(input)
Melhora um prompt em uma etapa, sem as perguntas.

```ts
enhance(input: EnhanceInput): Promise<{ jobId: string; prompt: string; recommendedModel?: RecommendedModel }>
```

<TypeTable
type={{
prompt: { type: 'string', description: "O prompt a melhorar." },
'...': { type: 'common fields', description: "nodeType e os campos comuns acima." },
}}
/>

```ts
const { prompt } = await client.promptHelper.enhance({
nodeType: "generate-image",
prompt: "snow leopard on a rock",
reasoningEffort: "high",
})
```

## Frequently asked questions

### Como encontro os IDs válidos para o objeto direction?

Chame client.pickerCatalogs.list() para ver todos os seletores e depois client.pickerCatalogs.get(nodeType) para as opções de um seletor. O id de cada opção é o que direction e os nós de seletor aceitam.

### Qual é a diferença entre label, term e promptHint?

label é o nome de exibição. term é a expressão profissional curta que o seletor adiciona no modo Compacto. promptHint é a frase mais longa que ele adiciona no modo Completo, retornada só com detail full.

### Como melhoro um prompt com o SDK?

Chame client.promptHelper.enhance com o nodeType de destino e o seu prompt. A chamada retorna um prompt melhorado e, às vezes, um modelo recomendado. Cada chamada custa créditos.

### O SDK pode criar ou alterar predefinições de nó?

Não. client.presets lê as suas predefinições salvas, os grupos delas e as predefinições integradas. Para aplicar uma predefinição, mescle os dados dela nas configurações de um nó quando montar um workflow.
