# Stage Action Buttons (`stage-actions`) - SignalOS page block

> Re-run and Reset controls for a semantics pipeline stage, with a model-picker confirmation dialog. All API calls and navigation are handled by the parent via the onAction callback.

- **Version:** 0.2.4
- **Kind:** block (group: semantics-details) · **Category:** pages
- **Install:** `npx shadcn@latest add @signalos/stage-actions`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/button, @signalos/tooltip, @signalos/select, @signalos/label, @signalos/form-dialog
- **npm dependencies:** lucide-react@^0.468.0
- **Files installed:** `src/components/blocks/stage-actions/StageActionButtons.tsx`, `src/components/blocks/stage-actions/StageActionButtons.types.ts`, `src/components/blocks/stage-actions/StageActionButtons.constants.ts`, `src/components/blocks/stage-actions/components/StageActionDialog.tsx`

## Access

This is a private registry: pulling source requires a `SIGNALOS_REGISTRY_TOKEN`
(GitHub fine-grained PAT with read access to the signal-widgets repo) and an
`@signalos` entry in components.json `"registries"`. Previews and this document are public.

## Usage

```tsx
// after: npx shadcn@latest add @signalos/stage-actions
// mount the pulled page in a route, e.g. src/app/semantics-details/page.tsx
import { StageActionButtons } from "@/components/blocks/stage-actions/StageActionButtons"

export default function Page() {
  return <StageActionButtons />
}
```

## Props

### `StageAction`

```ts
export type StageAction = "rerun" | "reset_to_stage"
```

### `LlmModelOption`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - | Unique model id / slug passed to the API. |
| `label` | `string` | yes | - | Human-readable label shown in the select. |

### `ModelProviderFamily`

```ts
export type ModelProviderFamily =
  | "anthropic"
  | "amazon"
  | "meta"
  | "mistral"
  | "deepseek"
  | "openai"
  | "google"
  | "cohere"
  | "xai"
  | "moonshot"
  | "unknown"
```

### `OrchestrationModel`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `canonical` | `string` | yes | - |  |
| `label` | `string` | yes | - |  |
| `display` | `string \| null \| undefined` | no | - |  |
| `family` | `ModelProviderFamily` | yes | - |  |
| `family_display` | `string` | yes | - |  |
| `lifecycle_warning` | `string \| null \| undefined` | no | - |  |
| `retire_after` | `string \| null \| undefined` | no | - |  |
| `resolved` | `string \| undefined` | no | - |  |

### `StageActionPayload`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `action` | `StageAction` | yes | - | The action the user selected. |
| `model` | `string \| undefined` | no | - | Reasoning model id — omitted when the user leaves it at the pipeline default. |
| `supporting_model` | `string \| undefined` | no | - | Supporting model id — omitted when the user leaves it at the pipeline default. |

### `StageActionButtonsProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `stageLabel` | `string` | yes | - | Friendly stage label shown in the dialog description, e.g. "Extraction". Required — the parent owns all domain label mapping. |
| `connectorName` | `string \| undefined` | no | - | Friendly connector / source name shown for per-connector stages. Omit for shared (cross-source) stages. |
| `models` | `OrchestrationModel[] \| undefined` | no | - | Available LLM models to populate the model pickers. |
| `isLoadingModels` | `boolean \| undefined` | no | - | True while the model list is being fetched. |
| `isConfirmed` | `boolean \| undefined` | no | - | When true, the Reset button is rendered (only for already-confirmed stages). |
| `isSubmitting` | `boolean \| undefined` | no | - | True while an action is being submitted — disables both buttons. |
| `onAction` | `(payload: StageActionPayload) => void` | yes | - | Called when the user confirms an action. The parent is responsible for calling the API, showing a toast, closing the dialog, and navigating. |
| `className` | `string \| undefined` | no | - |  |
| `data-testid` | `string \| undefined` | no | - | Test identifier rendered as `data-testid` on the root element. |
| `onCreateModel` | `(() => void) \| undefined` | no | - |  |

### `StageActionDialogProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `action` | `StageAction` | yes | - | Which action this dialog runs — drives copy, button style, and payload. |
| `stageLabel` | `string` | yes | - | Friendly stage label shown in the dialog description. |
| `connectorName` | `string \| undefined` | no | - | Friendly connector name shown in the reset description. Omit for shared stages. |
| `models` | `OrchestrationModel[] \| undefined` | no | - | Available LLM models to pick from. |
| `isLoadingModels` | `boolean \| undefined` | no | - | True while the model list is being fetched. |
| `isSubmitting` | `boolean \| undefined` | no | - | True while the action is being submitted. |
| `open` | `boolean` | yes | `false` |  |
| `onOpenChange` | `(open: boolean) => void` | yes | - |  |
| `onConfirm` | `(payload: StageActionPayload) => void` | yes | - | Called when the user confirms. The parent is responsible for calling the API, showing a toast, closing the dialog, and navigating. |
| `data-testid` | `string \| undefined` | no | - | Test identifier rendered as `data-testid` on the root dialog element. |
| `onCreateModel` | `(() => void) \| undefined` | no | - |  |

## Changelog

## 0.2.4

- Fix cross-item imports to use canonical @/components paths; add missing signalos.category to manifests.

## 0.2.3

- `StageActionButtons.types.ts`: allow `null` for `OrchestrationModel.display` field (was `string | undefined`, now `string | null | undefined`).
- `StageActionButtons.types.ts`: remove stale JSDoc module comment.

## 0.2.2

- Add `onCreateModel` callback prop to `StageActionButtonsProps` and thread it through to `StageActionDialog` to support inline model creation.

## 0.2.0

- Move `StageActionDialog` into `components/StageActionDialog.tsx` (decomposition ladder stage 3).
- Extract all types into `StageActionButtons.types.ts` — `StageAction`, `LlmModelOption`, `StageActionPayload`, `StageActionButtonsProps`, `StageActionDialogProps`.
- Extract string constants into `StageActionButtons.constants.ts` — `TEST_IDS`, `PIPELINE_DEFAULT_VALUE`, `PIPELINE_DEFAULT_LABEL`, `MODELS_LOADING_PLACEHOLDER`.
- Add `StageActionButtons.test.tsx` with full coverage: default render, isConfirmed toggle, isSubmitting disable, dialog open/close, onAction payload, cancel without firing.
- Add `StageActionButtons.preview.tsx` with four catalog scenarios.

## 0.1.0

- Initial release: `StageActionButtons` and `StageActionDialog` extracted from the app and rewritten as registry-compliant components.
- All store access, API calls, navigation, and toast logic removed — parent owns these via the `onAction` callback.
- `StageActionDialog` now uses `FormDialog` instead of a raw `Dialog`.
- Model pickers receive `models` and `isLoadingModels` props instead of reading from the Redux store.
- Semantic tokens used throughout (`text-text-error` instead of raw `text-error-600`).
