Skip to content
Merged
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
13 changes: 7 additions & 6 deletions docs/guides/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ tools: [fetch-paper] # own short names resolve first, then global tool ids
Research the question and cite every claim.
```

- Omit `skills` or use `skills: true` to advertise every skill visible to the
agent. Use `skills: []` to advertise none. `load_skill` remains available in
either case.
- Omit `skills` or use `skills: true` to advertise and authorize every skill
visible to the agent. Use `skills: []` to advertise none and to authorize no
project or configured skill for `load_skill`.
- `tools: true` - every currently scoped tool is authorized, while non-bootstrap
schemas are deferred behind `tool_search` until the agent searches for them.
- `skills: [..]` / `tools: [..]` - each entry resolves as the agent's own
Expand Down Expand Up @@ -269,9 +269,10 @@ export default agent({
});
```

Use `skills: ["incident-response", "repo-maintainer"]` to advertise only those
skills. Use `skills: []` to advertise no skills. This selector does not remove
`load_skill` or restrict which visible skills it can load by ID.
Use `skills: ["incident-response", "repo-maintainer"]` to advertise and
authorize only those skills. Use `skills: []` to advertise no skills and to
authorize none for `load_skill`. An explicit selector is an authorization
boundary for `load_skill`, not just a prompt filter.

Local and project runtimes also expose `load_skill_reference` and
`execute_skill_script`. Hosted chat reads an advertised reference through
Expand Down
101 changes: 66 additions & 35 deletions docs/guides/chat-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,12 @@ different requests would share the same store.
Use chat context providers only when nested components need direct state access.
Prefer preset props or composition components first.

## Render Markdown directly
## Present Markdown source safely

Use `veryfront/markdown` when a page or custom message surface needs the same
renderer without the rest of the chat composition:
`veryfront/markdown` is the dependency-free Markdown boundary used by chat
surfaces. Without an installed rich renderer, it preserves the exact source in
an escaped `<pre><code>` element. This is useful when source visibility matters
more than semantic formatting:

````tsx
import { Markdown } from "veryfront/markdown";
Expand All @@ -329,45 +331,74 @@ export default function Result() {
}
````

CommonMark and GitHub Flavored Markdown, including tables, task lists, and
strikethrough, are server-rendered. Fenced source is also present in the server
HTML. Shiki highlighting and Mermaid SVG rendering are browser enhancements;
if either enhancement cannot load or render, the source remains readable.
The default does not claim that CommonMark, GFM, highlighting, or diagrams were
rendered. It emits no Markdown-authored links, images, or raw HTML, and the
escaped source is present in server HTML.

Replace fenced-code rendering without changing inline code:
### Install a semantic renderer

Semantic Markdown is an explicit extension capability. Select a trusted
extension or application adapter that implements `MarkdownRendererProps`, then
install its component for the relevant subtree. In this example,
`ProjectMarkdownRenderer` comes from that adapter:

```tsx
import { Markdown, MarkdownRendererProvider } from "veryfront/markdown";
import { ProjectMarkdownRenderer } from "./project-markdown-renderer.tsx";

export default function Result() {
return (
<MarkdownRendererProvider renderer={ProjectMarkdownRenderer}>
<Markdown>{answer}</Markdown>
</MarkdownRendererProvider>
);
}
```

The per-instance `renderer` prop takes precedence over the provider. Pass
`renderer={null}` when a nested surface must display plain source even though
an ancestor installed a renderer.

Parser-dependent options are forwarded only after a renderer has been selected.
For example, replace fenced-code rendering without changing the renderer used
for the rest of the document:

```tsx
<Markdown
renderCodeBlock={({ language, code }) => (
<pre data-language={language}>
<code>{code}</code>
</pre>
)}
>
{answer}
</Markdown>;
<MarkdownRendererProvider renderer={ProjectMarkdownRenderer}>
<Markdown
renderCodeBlock={({ language, code }) => (
<pre data-language={language}>
<code>{code}</code>
</pre>
)}
>
{answer}
</Markdown>
</MarkdownRendererProvider>;
```

Use `components` to replace an HTML element renderer. Consumer entries win
over the built-in link, table, cell, blockquote, and code-fence renderers:
Use `components` to pass framework-neutral element overrides to the selected
renderer:

```tsx
<Markdown
components={{
a: ({ href, children }) => <a href={href}>{children}</a>,
}}
>
{"Review the [Markdown section](#render-markdown-directly)."}
</Markdown>;
<MarkdownRendererProvider renderer={ProjectMarkdownRenderer}>
<Markdown
components={{
a: ({ href, children }) => <a href={href}>{children}</a>,
}}
>
{"Review the [Markdown section](#present-markdown-source-safely)."}
</Markdown>
</MarkdownRendererProvider>;
```

Raw HTML and unsafe link protocols are not emitted by the default pipeline.
`remarkPlugins`, `rehypePlugins`, and custom components execute as trusted
application code and can change those guarantees; never build plugin lists
from untrusted input. Remote Markdown images can initiate browser requests, so
override the `img` component when untrusted content needs a stricter image or
privacy policy. Bound untrusted Markdown size before rendering when the
application accepts arbitrarily large documents.
The extension owns parsing, sanitization, unsafe link protocols, image policy,
highlighting, and diagram security. Configure parser-specific `remarkPlugins`
or `rehypePlugins` on that extension, not on core `Markdown`; removed or unknown
core props are rejected instead of ignored. Renderer failures propagate, so
handle them with an application error boundary when recovery is required.
Never derive plugin lists from untrusted input, and bound untrusted source size
before rendering.

## Verify it worked

Expand All @@ -382,8 +413,8 @@ Run `veryfront dev` and open the page that renders the chat UI:
- A conversation persistence failure renders an alert with the failed
operation.
- A chat using `memoryConversationStore()` starts empty after a page reload.
- Standalone Markdown is semantic in the initial server HTML, and fenced code
remains readable before browser enhancement.
- Standalone Markdown source is escaped and readable in the initial server
HTML; an injected renderer is used only in the subtree where it is installed.

If the assistant response is empty, check the dev-server log for provider or
agent errors and confirm the AG-UI route is mounted.
Expand Down
4 changes: 4 additions & 0 deletions docs/guides/cli-knowledge-ingestion.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,7 @@ veryfront knowledge ingest uploads/sample.pdf --json | jq '.ingested'
The `ingested` array names every file the command wrote. If the array is empty
or the command exited non-zero, check `skipped`, `failed`, and the command
output for the reason.

Next, use [Project knowledge](./project-knowledge.md) to search the generated
paths and frontmatter, retrieve an exact Markdown document, or index the files
for semantic retrieval.
58 changes: 45 additions & 13 deletions docs/guides/data-fetching.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ description: "Server data, static generation, and client-side fetching."
order: 13
---

Veryfront pages can load data three ways: `getServerData` on every request, `getStaticData` at build time, or `fetch` from a client component. Each one has its place.
Veryfront pages can load data three ways: `getServerData` on every request,
`getStaticData` during static generation and cacheable production requests, or
`fetch` from a client component. Each one has its place.

Examples below use the default app router. Set `router: "pages"` in `veryfront.config.ts` to switch to the pages router.

Expand Down Expand Up @@ -42,23 +44,27 @@ entirely, including their top-level side effects. Put client initialization in a
separate client-referenced module or a bare side-effect import that is not only
used by a server data hook.

The `props` you return are passed to the page component. To read them from a
layout or a nested component without prop-drilling, use `usePageContext().data`
(see [Pages and routing](./pages-and-routing.md)). It holds the same `props`
object on the server render, in the hydration markup, and after client-side
navigation.
The `props` you return are passed to the page component. To read the same props
data from a layout or nested component without prop-drilling, use
`usePageContext().data` (see
[Pages and routing](./pages-and-routing.md)). Veryfront serializes that data
into hydration markup and restores it after client-side navigation; do not rely
on JavaScript object identity surviving serialization.

The `DataContext` provides:

| Property | Type | Description |
| --------- | ------------------------ | ------------------------------------------- |
| `request` | `Request` | The incoming HTTP request |
| `params` | `Record<string, string>` | Route parameters (e.g. `{ slug: "hello" }`) |
| `query` | `URLSearchParams` | Query string parameters |
| Property | Type | Description |
| --------- | ------------------------------------ | ------------------------------------------- |
| `request` | `Request` | The incoming HTTP request |
| `params` | `Record<string, string \| string[]>` | Route parameters (e.g. `{ slug: "hello" }`) |
| `query` | `URLSearchParams` | Query string parameters |
| `url` | `URL` | Parsed request URL |

## Static data

`getStaticData` runs at build time. Use it for content that doesn't change per request:
`getStaticData` supplies cacheable data for static builds and production
requests. Use it for content that does not depend on request headers, cookies,
or request bodies:

```tsx
// app/blog/[slug]/page.tsx
Expand All @@ -85,9 +91,35 @@ export default function BlogPost({ post }: { post: { title: string } }) {

For dynamic routes, pair `getStaticData` with `getStaticPaths` to tell the framework which pages to generate.

`getStaticData` receives `params` and `url`. It does not receive `request`,
request headers, cookies, a body, or a separate `query` property. Read query
parameters from `url.searchParams`; the complete URL, including the query
string, participates in static cache identity.

## Revalidate static data

Set `revalidate` to a finite, non-negative number of seconds to refresh static
data after it becomes stale:

```tsx
export async function getStaticData() {
const response = await fetch("https://api.example.com/posts");
const posts = await response.json();

return {
props: { posts },
revalidate: 60,
};
}
```

Veryfront serves the cached result while one background refresh runs. A failed
refresh keeps the live cached result. Omit `revalidate` or set it to `false` to
disable background refreshes.

## Redirects and 404s

Return `redirect()` or `notFound()` from any data function:
Return `redirect()` or `notFound()` from `getServerData` or `getStaticData`:

```tsx
import { type DataContext, notFound, redirect } from "veryfront";
Expand Down
20 changes: 8 additions & 12 deletions docs/guides/deploying.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,15 @@ veryfront build
This compiles pages, bundles assets, pre-renders static routes, and writes the
output to `dist/` by default.

Customize the output directory in `veryfront.config.ts`:
Choose a different output directory explicitly:

```ts
import { defineConfig } from "veryfront";

export default defineConfig({
build: {
outDir: "dist",
trailingSlash: false,
},
});
```bash
veryfront build --output build-output
```

`build.outDir` and `build.trailingSlash` remain accepted configuration fields
for compatibility, but the production builder does not consume them.

## Run the build locally

```bash
Expand Down Expand Up @@ -135,7 +131,7 @@ output.

After `veryfront build`:

- `dist/` or your configured `outDir` contains compiled assets.
- `dist/`, or the directory passed to `--output`, contains compiled assets.
- `veryfront serve` serves the build locally.
- The route you chose responds the same way it did in development.

Expand All @@ -155,7 +151,7 @@ After `veryfront deploy`:
- [Configuration](./configuration.md): Configure build and environment behavior
- [Deploy from CI](./deploy-from-ci.md): Push and deploy reviewed Git commits from CI
- [Move Studio changes into Git](./move-studio-changes-to-git.md): Review a Studio release through a Git pull request
- [Providers](./providers.md): Configure model provider defaults
- [Providers](./providers.md): Configure model providers

## Related

Expand Down
28 changes: 20 additions & 8 deletions docs/guides/evals.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,9 @@ veryfront eval deep-research \

Usage and p95 latency deltas are reported in `summary.json` whenever both the
current report and baseline include those values. They fail the run only when
the matching threshold flag is set.
the matching threshold flag is set. A baseline is accepted only for the same
eval definition and target; a report from another eval is rejected instead of
being compared.

Update the baseline explicitly after reviewing the current report:

Expand Down Expand Up @@ -229,10 +231,11 @@ veryfront eval deep-research \
Policy metrics can reference `passRate`, `failed`, `gateFailures`,
`groundednessScore`, `inputTokens`, `outputTokens`, `totalTokens`,
`billableInputTokens`, `billableOutputTokens`, `costUsd`, `providerCostUsd`,
`veryfrontChargeUsd`, `costCredits`, and `p95Ms`. `costUsd` remains a
backward-compatible cost objective and prefers gateway Veryfront charge when it
is available. Use `min`, `max`, and `maxRegressionPct` for constraints. Use
`weight` with `direction` set to `"minimize"` or `"maximize"` for objectives.
`veryfrontChargeUsd`, `veryfrontBilledUsd`, `costCredits`, and `p95Ms`.
`costUsd` remains a backward-compatible cost objective and prefers gateway
Veryfront charge when it is available. Use `min`, `max`, and
`maxRegressionPct` for constraints. Use `weight` with `direction` set to
`"minimize"` or `"maximize"` for objectives.

Each report includes provenance metadata. Local runs record git SHA, branch,
dirty state, and a dirty hash. Cloud runs prefer release, deployment, or preview
Expand Down Expand Up @@ -299,9 +302,11 @@ metrics.ops.tokens({ maxTotal: 4_000 }).budget();
metrics.ops.cost({ maxUsd: 0.05 }).budget();
```

`metrics.ops.cost` uses gateway `veryfrontChargeUsd` first, then legacy
`costUsd`, then `providerCostUsd`. It does not maintain a separate pricing table
inside the framework.
`metrics.ops.cost` uses gateway `veryfrontBilledUsd` first, then
`veryfrontChargeUsd`, legacy `costUsd`, and finally `providerCostUsd`. It does
not maintain a separate pricing table inside the framework. Token and cost
budgets fail when the measurement required by their configured limit is
missing; absent usage evidence never passes a budget.

Use `calledTool` when the agent must call a tool. Add `input` when the tool
arguments must include specific fields. `match: "partial"` checks that the
Expand Down Expand Up @@ -575,6 +580,13 @@ calls as `record.trace.toolCalls`, captures tool call IDs, status, streamed
arguments, result payloads, and denied/error state when the AG-UI endpoint emits
them, and puts the parsed text at `record.output.text`.

Live adapters and CLI helpers require a non-empty `VERYFRONT_TOKEN`. CLI case
filters cannot opt into mutation: a requested write case still requires
`AG_UI_EVAL_WRITE=1`, and an experimental write case requires both
`AG_UI_EVAL_WRITE=1` and `AG_UI_EVAL_EXPERIMENTAL=1`. Unknown, duplicate, or
disabled case selections fail before any case runs. A run with no passing case
exits unsuccessfully instead of treating an all-skipped selection as evidence.

Projects with existing live AG-UI suites can also import reusable CLI, API, and
durable canary helpers from `veryfront/eval/agent-service`. Use those helpers
for product-specific canaries that are not yet expressed as `evalAgent`
Expand Down
1 change: 1 addition & 0 deletions docs/guides/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ details, see [API reference](../api-reference/index.md).
| Emit app and eval dashboard metrics | [Project metrics](./project-metrics.md) |
| Add memory or streamed responses | [Memory and streaming](./memory-and-streaming.md) |
| Build document Q&A with RAG | [Build a RAG app](./build-a-rag-app.md) |
| Search source-controlled project knowledge | [Project knowledge](./project-knowledge.md) |
| Coordinate more than one agent | [Multi-agent](./multi-agent.md) |
| Package reusable agent instructions | [Skills](./skills.md) |

Expand Down
26 changes: 26 additions & 0 deletions docs/guides/pages-and-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,32 @@ function PageTitle() {
}
```

### Override rendered MDX elements

Wrap an MDX page or layout with `MDXProvider` to replace generated elements:

```tsx
import type React from "react";
import { MDXProvider } from "veryfront/mdx";

const docsComponents = {
h1: (props: React.ComponentProps<"h1">) => <h1 className="docs-title" {...props} />,
a: (props: React.ComponentProps<"a">) => <a {...props} rel="noreferrer" />,
};

export default function DocsLayout({ children }: { children: React.ReactNode }) {
return <MDXProvider components={docsComponents}>{children}</MDXProvider>;
}
```

Nested providers inherit entries from outer providers. A nearer provider wins
for duplicate keys. Call `useMDXComponents(localOverrides)` when a component
needs the effective map; local entries take final precedence.

`MDXProvider` supplies application-owned React components to already compiled
MDX. It does not compile or sanitize arbitrary strings. Render runtime Markdown
strings with `veryfront/markdown`.

### Reading server data from a layout or nested component

A page's [`getServerData`](./data-fetching.md) props are passed to the page
Expand Down
Loading