Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
- Built-in `markdown` (with `--markdown` alias via output alias map).
- Global format selectors: `--json`, `--xml`, `--yaml`, `--yml`, `--output:<format>`.
- Unknown format returns explicit error text and non-zero exit code.
- Result flow:
- `IReplPagingContext` lets handlers page at the data source.
- `ReplPage<T>` carries current-page data plus continuation metadata.
- Human/Spectre terminal output can use an integrated pager; redirected stdout remains pipe-friendly.
- MCP maps `_replCursor` and `_replPageSize` to structured paged tool results.
- Numeric parsing:
- Numeric culture is configurable via `ParsingOptions.NumericCulture` (`Invariant` default, `Current` optional).
- Integer literals support C-like forms: hexadecimal (`0xFF`), binary (`0b1010` or `1010b`), and `_` separators (`1_000_000`).
Expand Down Expand Up @@ -101,6 +106,7 @@ The toolkit provides two application entry points for different scenarios.
## Related docs

- Command reference: `docs/commands.md`
- Result flow and paging: `docs/result-flow.md`
- Parameter system: `docs/parameter-system.md`
- Shell completion: `docs/shell-completion.md`

Expand Down
30 changes: 30 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ These flags are parsed before route execution:
- `--no-interactive`
- `--no-logo`
- `--output:<format>`
- `--result:page-size <n>` / `--result:page-size=<n>`
- `--result:cursor <value>` / `--result:cursor=<value>`
- `--result:all`
- `--result:pager=auto|off|more|scroll|external`
- output aliases mapped by `OutputOptions.Aliases` (defaults include `--json`, `--xml`, `--yaml`, `--yml`, `--markdown`)
- `--answer:<name>[=value]` for non-interactive prompt answers
- custom global options registered via `options.Parsing.AddGlobalOption<T>(...)`
Expand All @@ -29,6 +33,7 @@ Global parsing notes:
- option value syntaxes accepted by command parsing: `--name value`, `--name=value`, `--name:value`
- use `--` to stop option parsing and force remaining tokens to positional arguments
- response files are supported with `@file.rsp` (enabled by default); nested `@` expansion is not supported
- result-flow options are reserved by the framework and do not bind to handler business parameters

## Declaring command options

Expand Down Expand Up @@ -249,6 +254,7 @@ Handlers can return any type. The framework renders the return value through the
| `string` | Rendered as plain text |
| Object / anonymous type | Rendered as key-value pairs (human) or serialized (JSON/XML/YAML) |
| `IEnumerable<T>` | Rendered as a table (human) or collection (structured formats) |
| `ReplPage<T>` | Rendered as the current page plus `PageInfo`; JSON uses `{ items, pageInfo }` |
| `IReplResult` | Structured result with kind prefix (`Results.Ok`, `Error`, `NotFound`...) |
| `ReplNavigationResult` | Renders payload and navigates scope (`Results.NavigateUp`, `NavigateTo`) |
| `IExitResult` | Renders optional payload and sets process exit code (`Results.Exit`) |
Expand Down Expand Up @@ -294,6 +300,30 @@ Tuple semantics:
- null elements are silently skipped
- nested tuples are not flattened — use a flat tuple instead

## Paging large results

Handlers that may return large result sets can request `IReplPagingContext`:

```csharp
app.Map("contacts", async (IReplPagingContext paging, ContactStore store, CancellationToken ct) =>
{
var rows = await store.QueryAsync(paging.Cursor, paging.SuggestedPageSize, ct);
return paging.Page(rows.Items, rows.NextCursor, rows.TotalCount);
});
```

When human users should continue through later pages without rerunning the
command, return a page source:

```csharp
app.Map("contacts", (ContactStore store) =>
ReplPageSource.FromOffset<ContactRow>(
(offset, take, ct) => store.QueryAsync(offset, take, ct),
totalCount: store.Count));
```

Use this when the data source can page efficiently. See [Result Flow And Paging](result-flow.md) for CLI flags, pager behavior, MCP paging arguments, and output format details.

## Interactive prompts

Handlers can use `IReplInteractionChannel` for guided prompts, progress reporting, and user-facing feedback. Extension methods add enum prompts, numeric input, validated text, notices, warnings, problem summaries, and more.
Expand Down
11 changes: 11 additions & 0 deletions docs/configuration-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,21 @@ Accessed via `ReplOptions.Output`.
- `ColorizeStructuredInteractive` (`bool`, default: `true`) — Colorize JSON/XML in interactive mode.
- `PreferredWidth` (`int?`, default: `null`) — Preferred render width. `null` uses automatic detection.
- `FallbackWidth` (`int`, default: `120`) — Fallback width when the terminal is unavailable.
- `ResultFlow` (`ResultFlowOptions`) - Paging and large-result behavior.
- `JsonSerializerOptions` (`JsonSerializerOptions`, default: Web defaults + indented) — JSON serializer options.

Built-in transformers: `human`, `json`, `xml`, `yaml`, `markdown`.

### ResultFlowOptions

Accessed via `ReplOptions.Output.ResultFlow`.

- `DefaultPageSize` (`int`, default: `100`) - Page size used when no caller or terminal hint provides one.
- `MaxPageSize` (`int`, default: `1000`) - Maximum accepted page size.
- `ReservedVisibleRows` (`int`, default: `2`) - Rows reserved when computing terminal-visible data rows.
- `DefaultPagerMode` (`ReplPagerMode`, default: `Auto`) - Pager behavior for human formats.
- `ProgrammaticMaxInlineBytes` (`int`, default: `65536`) - Reserved for programmatic inline payload policy.

### OutputOptions Methods

- `AddTransformer(name, transformer)` — Register a custom output transformer.
Expand Down
26 changes: 25 additions & 1 deletion docs/mcp-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ app.UseMcpServer(o => o.InteractivityMode = InteractivityMode.PrefillThenElicita

| Method | Where it goes | Use? |
|---|---|---|
| **Return value** | `CallToolResult.Content` (JSON) | **Yes.** Preferred for all data. |
| **Return value** | `CallToolResult.Content` and, for paged results, `StructuredContent` | **Yes.** Preferred for all data. |
| **`IReplInteractionChannel`** | MCP primitives (progress, prompts, user-facing notices/problems) | **Yes.** Portable feedback that also works outside MCP. |
| **`IMcpFeedback`** | MCP progress and logging/message notifications | **Yes.** MCP-specific feedback when you need direct control. |
| **`ReplSessionIO.Output`** | Session output | Advanced cases only. |
Expand All @@ -187,6 +187,30 @@ app.UseMcpServer(o => o.InteractivityMode = InteractivityMode.PrefillThenElicita

> **Why this matters:** Console-style writes blur the boundary between result data, progress, logs, and protocol traffic. In MCP, this ranges from confusing agent behavior to protocol corruption.

### Paged tool results

Every MCP tool schema includes two reserved Repl result-flow inputs:

- `_replCursor`: opaque continuation cursor returned by a previous paged result.
- `_replPageSize`: requested page size.

Handlers receive these values through `IReplPagingContext`, not as business parameters. A handler can return `ReplPage<T>`:

```csharp
app.Map("contacts", (IReplPagingContext paging, ContactStore store) =>
{
var page = store.Query(paging.Cursor, paging.SuggestedPageSize);
return paging.Page(page.Items, page.NextCursor, page.TotalCount);
}).ReadOnly();
```

MCP responses for `ReplPage<T>` include:

- `StructuredContent`: `{ items, pageInfo }`
- `Content`: short text summary with the next `_replCursor` when more data exists

This avoids dumping large JSON arrays into a single `TextContentBlock`.

`WriteProgressAsync` maps to MCP progress notifications. `WriteStatusAsync` maps to log messages (`level: info`). See [Progress](progress.md#mcp) for the centralized progress model across console, hosted sessions, Spectre, and MCP:

```csharp
Expand Down
9 changes: 9 additions & 0 deletions docs/output-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

The output system controls how command results are serialized and rendered to the user. It supports multiple built-in formats, custom transformers, ANSI detection, and banner rendering.

Large result flow and paging are documented separately in [Result Flow And Paging](result-flow.md).

## Format Selection Precedence

The active output format is resolved in this order:
Expand Down Expand Up @@ -102,7 +104,14 @@ The output width used for wrapping and table layout is resolved as:

In interactive mode, when ANSI is supported, JSON output is syntax-highlighted automatically. This applies only to the `json` format rendered to a terminal — redirected or non-ANSI output remains plain.

## Paging

Human terminal formats (`human` and `spectre`) can use the integrated result pager when rendered output exceeds the visible row capacity or a result-flow page source has more data. The pager is never used for redirected stdout, protocol passthrough, MCP/programmatic execution, or machine formats.

Paged handler results should return `ReplPage<T>` through `IReplPagingContext`. JSON serializes these as `{ items, pageInfo }`; human and Spectre formats render the current page plus continuation metadata.

## See Also

- [Configuration Reference](configuration-reference.md) — `OutputOptions` properties.
- [Execution Pipeline](execution-pipeline.md) — output formatting occurs at stage 11.
- [Result Flow And Paging](result-flow.md) - paging contracts, CLI flags, and MCP behavior.
Loading
Loading