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
7 changes: 7 additions & 0 deletions .changeset/migrate-assistant-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@truefoundry/trueforge-assistant-ui-runtime': major
'@truefoundry/trueforge-ui': major
'@truefoundry/trueforge': patch
---

Rename the published runtime package to `@truefoundry/trueforge-assistant-ui-runtime`, move it into the TrueForge workspace, rename its public runtime APIs to TrueForge, and remove the legacy TrueFoundry server adapter and server configuration.
2 changes: 1 addition & 1 deletion .cursor/BUGBOT.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ If a `catch` throws a new error, flag unless the new error sets `{ cause: caught

Flag duplicate type, schema, helper, or contract definitions and forwarding shims that hide ownership. Each must have one canonical owner.

`AgentChatServer`, `AgentBuilderServer`, catalog ports, session/turn DTOs, and stream events must be defined only in `@truefoundry/assistant-ui-runtime` (`src/server/types.ts` / `events.ts`). Flag hand-written parallel definitions in `@truefoundry/trueforge-ui`. That package may only re-export them from `src/server/types.ts`. React wiring (`ServerContext`, `ShellModeContext`, `TrueForgeServerConfig`) may import those types; it must not redefine ports.
`AgentChatServer`, `AgentBuilderServer`, catalog ports, session/turn DTOs, and stream events must be defined only in `@truefoundry/trueforge-assistant-ui-runtime` (`src/server/types.ts` / `events.ts`). Flag hand-written parallel definitions in `@truefoundry/trueforge-ui`. That package may only re-export them from `src/server/types.ts`. React wiring (`ServerContext`, `ShellModeContext`, `TrueForgeServerConfig`) may import those types; it must not redefine ports.

Flag runtime types backed by Zod schemas that are duplicated as hand-written interfaces or indirect utility-type chains. They must be named `z.infer<typeof Schema>` aliases.

Expand Down
7 changes: 4 additions & 3 deletions .cursor/rules/server-types-runtime-only.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@ alwaysApply: false
# Server types — runtime is the sole owner

Canonical `AgentUIServer` / chat / builder / catalog port types live only in
`@truefoundry/assistant-ui-runtime` (`src/server/types.ts` + `events.ts`).
[`packages/assistant-ui-runtime`](packages/assistant-ui-runtime)
(`src/server/types.ts` + `events.ts`).

## Rules

- [`packages/trueforge-ui/src/server/types.ts`](packages/trueforge-ui/src/server/types.ts)
is the host-facing barrel: re-export only from `@truefoundry/assistant-ui-runtime`
is the host-facing barrel: re-export only from `@truefoundry/trueforge-assistant-ui-runtime`
(prefer `/server` when avoiding root name collisions). Do **not** put hand-written
server port/DTO interfaces there or elsewhere in this monorepo.
- Hosts import types from `@truefoundry/trueforge-ui` only — they must not need the
runtime package for types.
- Need a new field/method on the contract? Change runtime `server/types.ts` first,
publish/bump, then re-export — never fork the shape in the UI SDK.
then re-export and changeset both affected packages — never fork the shape in the UI SDK.
- React wiring may stay here (`ServerContext`, `ShellModeContext`,
`TrueForgeServerConfig`). Those modules **import** runtime types; they do not
redefine ports.
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,21 @@ jobs:
- 'packages/frontend/**'
# trueforge-sdk is workspace:* (no version bump); SDK-only PRs must still run FE checks.
- 'packages/trueforge-sdk/**'
# trueforge-ui depends on the runtime workspace package.
- 'packages/assistant-ui-runtime/**'
- 'package.json'
- 'pnpm-workspace.yaml'
- 'tsconfig.base.json'
- '.github/workflows/ci.yml'
trueforge-ui:
- 'packages/trueforge-ui/**'
- 'packages/assistant-ui-runtime/**'
- 'package.json'
- 'pnpm-workspace.yaml'
- 'tsconfig.base.json'
- '.github/workflows/ci.yml'
assistant-ui-runtime:
- 'packages/assistant-ui-runtime/**'
- 'package.json'
- 'pnpm-workspace.yaml'
- 'tsconfig.base.json'
Expand Down Expand Up @@ -96,13 +105,15 @@ jobs:
TRUEFORGE: ${{ steps.filter.outputs.trueforge }}
FRONTEND: ${{ steps.filter.outputs.frontend }}
TRUEFORGE_UI: ${{ steps.filter.outputs['trueforge-ui'] }}
ASSISTANT_UI_RUNTIME: ${{ steps.filter.outputs['assistant-ui-runtime'] }}
run: |
node <<'EOF' >> "$GITHUB_OUTPUT"
const changedPackages = [];
if (process.env.TRUEFORGE_CORE === 'true') changedPackages.push('trueforge-core');
if (process.env.TRUEFORGE === 'true') changedPackages.push('trueforge');
if (process.env.FRONTEND === 'true') changedPackages.push('frontend');
if (process.env.TRUEFORGE_UI === 'true') changedPackages.push('trueforge-ui');
if (process.env.ASSISTANT_UI_RUNTIME === 'true') changedPackages.push('assistant-ui-runtime');
console.log(`list=${JSON.stringify(changedPackages)}`);
EOF

Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ docs/openapi.json
# Helm chart sources and downloaded Bitnami subcharts; not ours to reformat.
charts/
coverage/
data/
# Prettier's markdown parser escapes `*` inside MDX `{/* */}` comments, breaking MDX parsing.
*.mdx
.turbo/
Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
- Workspace tasks MUST use `package.json` scripts; add a script when a missing workflow is repeatable like the existing commands, not ad hoc commands.
- CI package path filters, matrix package ids, and root scripts `test:*` in `.github/workflows/ci.yml` and root `package.json` MUST stay synchronized when a workspace package is added, renamed, or moved; the `store` filter sync rule lives in `packages/trueforge-core/src/agent-session/store/AGENTS.md`.
- Release wiring MUST keep dist-free host development, `pnpm smoke`, and packed CJS/ESM consumers of `@truefoundry/trueforge-core` and `@truefoundry/trueforge-sdk` working without changes. Workspace loaders opt into SDK/core `src/` via the `trueforge-dev` export condition (never `"development"`); the SDK's `trueforge-dev` branch MUST keep `types` on its generated `.d.ts` (emitted by root `sdk:types`) because generated source is not `exactOptionalPropertyTypes`-clean.
- PRs that change published-package code (`packages/trueforge-core`, `packages/trueforge`, `packages/trueforge-ui`, `packages/trueforge-sdk`) or `packages/frontend` (ships inside `@truefoundry/trueforge`) MUST include a new `.changeset/*.md` file (`pnpm changeset`). Docs, CI/workflows, charts, and docker-compose changes do not. SDK regeneration already adds `@truefoundry/trueforge-sdk` via `pnpm changeset:sdk-regen`.
- PRs that change published-package code (`packages/assistant-ui-runtime`, `packages/trueforge-core`, `packages/trueforge`, `packages/trueforge-ui`, `packages/trueforge-sdk`) or `packages/frontend` (ships inside `@truefoundry/trueforge`) MUST include a new `.changeset/*.md` file (`pnpm changeset`). Docs, CI/workflows, charts, and docker-compose changes do not. SDK regeneration already adds `@truefoundry/trueforge-sdk` via `pnpm changeset:sdk-regen`.
- Shared Postgres/Redis settings in `docker-compose.yml` and `docker-compose.dev.yml` (image versions, health checks, `env_file`) MUST stay synchronized; intentional differences (app services, data paths, project `name`, host ports, in-network `POSTGRES_HOST` / `REDIS_URL`) MUST stay explicit. `packages/trueforge/.env` is the host-dev + secrets source; `docker-compose.yml` may read it but MUST override container connectivity so host-dev localhost values are not used inside the smoke-test stack.
- Changes to types or schemas MUST keep `packages/trueforge-core`, `packages/frontend`, `packages/trueforge`, and `patches` synchronized; they MUST NOT update only one affected layer.
- TypeScript code MUST NOT use assertion escapes such as `as T`, `as unknown as T`, non-null `!`, or `as never` to silence type errors; implementations MUST use sound contracts, guards, or corrected types.
- When catching an error and throwing another, the new error MUST set `{ cause: caught }` so the original failure is preserved for logs and debugging.
- Every type, schema, helper, and contract MUST have one canonical owner; code MUST NOT introduce duplicate definitions or forwarding shims that hide ownership.
- AgentUIServer / server-port types (`AgentChatServer`, `AgentBuilderServer`, catalog ports, session/turn DTOs, stream events) MUST be defined only in `@truefoundry/assistant-ui-runtime` (`src/server/types.ts` / `events.ts`). `@truefoundry/trueforge-ui` MUST re-export them from `src/server/types.ts` (pass-through aliases only) and MUST NOT add hand-written parallel definitions of those ports/DTOs.
- AgentUIServer / server-port types (`AgentChatServer`, `AgentBuilderServer`, catalog ports, session/turn DTOs, stream events) MUST be defined only in `packages/assistant-ui-runtime/src/server/types.ts` / `events.ts`. `@truefoundry/trueforge-ui` MUST re-export them from `src/server/types.ts` (pass-through aliases only) and MUST NOT add hand-written parallel definitions of those ports/DTOs.
- Runtime types backed by Zod schemas MUST be derived with named `z.infer<typeof Schema>` aliases; code MUST NOT duplicate those schemas as hand-written interfaces or indirect utility-type chains.
- Modules MUST use static `import` and `import type`; they MUST NOT use `require()`, `require.resolve()`, or lint suppressions to bypass import checks.
- A change that makes code unused MUST remove that dead code in the same change; it MUST NOT leave stale exports, files, documentation, duplicates, or “just in case” shims.
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ COPY packages/trueforge/package.json packages/trueforge/package.json
COPY packages/trueforge-sdk/package.json packages/trueforge-sdk/package.json
COPY packages/frontend/package.json packages/frontend/package.json
COPY packages/trueforge-ui/package.json packages/trueforge-ui/package.json
COPY packages/assistant-ui-runtime/package.json packages/assistant-ui-runtime/package.json
COPY packages/trueforge-core/scripts packages/trueforge-core/scripts
COPY packages/trueforge-core/src/core/sandbox/scripts packages/trueforge-core/src/core/sandbox/scripts

Expand All @@ -65,6 +66,7 @@ RUN pnpm --filter @truefoundry/trueforge-core build && pnpm --filter @truefoundr
FROM workspace AS frontend-builder
RUN pnpm install --frozen-lockfile --offline --filter frontend...
COPY packages/trueforge-sdk packages/trueforge-sdk
COPY packages/assistant-ui-runtime packages/assistant-ui-runtime
COPY packages/trueforge-ui packages/trueforge-ui
RUN pnpm --filter @truefoundry/trueforge-ui build
COPY packages/frontend packages/frontend
Expand Down
4 changes: 4 additions & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@
"pages": [
"chat-ui",
"ui-sdk/get-started/quickstart",
{
"group": "Server setup",
"pages": ["ui-sdk/setup-custom-servers/server-contract", "ui-sdk/setup-custom-servers/custom-server"]
},
{
"group": "Frontend Customisation",
"pages": [
Expand Down
8 changes: 4 additions & 4 deletions docs/ui-sdk/concepts/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,18 @@ That replacement is what `overrides` does: name a component, supply your own, an
<SlotsProvider overrides={overrides} theme={theme}>
<ServerProvider server={server}>
<ShellModeProvider agentConfig={{ mode: "AgentLibrary" }}>
<TrueFoundryChatProvider server={server}>
<TrueForgeChatProvider server={server}>
<MyLayout />
</TrueFoundryChatProvider>
</TrueForgeChatProvider>
</ShellModeProvider>
</ServerProvider>
</SlotsProvider>
```

Order matters: `SlotsProvider` must be outside `TrueFoundryChatProvider`.
Order matters: `SlotsProvider` must be outside `TrueForgeChatProvider`.

<Warning>
Composing manually means you own runtime resets. `TrueForgeUI` remounts the chat runtime when the selected agent changes, a new draft starts, or the chat is cleared; a hand-rolled stack does not. Change the `key` on `TrueFoundryChatProvider` yourself at those moments, or stale messages carry over between agents.
Composing manually means you own runtime resets. `TrueForgeUI` remounts the chat runtime when the selected agent changes, a new draft starts, or the chat is cleared; a hand-rolled stack does not. Change the `key` on `TrueForgeChatProvider` yourself at those moments, or stale messages carry over between agents.
</Warning>

## Styling hooks
Expand Down
3 changes: 1 addition & 2 deletions docs/ui-sdk/guides/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ description: "Common failure modes and their causes."
<Accordion title="An error alert appears immediately on mount">
The built-in server failed to resolve. For `type: "trueforge"`, confirm `@truefoundry/trueforge-sdk`
is installed, `baseUrl` is reachable, and you passed either `token` or a working `fetch` — see
[Quickstart](/ui-sdk/get-started/quickstart). For `type: "truefoundry"`, check that `apiKey` and
`controlPlaneURL` are set and reachable. Attach an `onError` handler to see the underlying error.
[Quickstart](/ui-sdk/get-started/quickstart). Attach an `onError` handler to see the underlying error.
</Accordion>

<Accordion title="Requests fail in composer mode with an unknown model">
Expand Down
8 changes: 4 additions & 4 deletions docs/ui-sdk/reference/containers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ need few props. Use them to build a [custom layout](/ui-sdk/guides/layouts).
| `ThreadContainer` | `{ composer?: ReactNode }` | The message transcript with an optional composer slot beneath it. |
| `ComposerContainer` | `{ placeholder?: string }` | Input, attachments, model label, send/cancel. |
| `ThreadListContainer` | `{ onThreadOpen?: () => void }` | Session list with new-chat affordance. |
| `TrueFoundryChatProvider` | see below | Mounts the chat runtime. |
| `TrueForgeChatProvider` | see below | Mounts the chat runtime. |

```ts
type TrueFoundryChatProviderProps = {
type TrueForgeChatProviderProps = {
server: AgentUIServer;
initialSessionId?: string;
adapters?: UseTrueFoundryAgentRuntimeOptions["adapters"];
adapters?: UseTrueForgeAgentRuntimeOptions["adapters"];
onError?: (error: unknown) => void;
children: ReactNode;
agent?: TrueFoundryAgentConfig;
agent?: TrueForgeAgentConfig;
agentName?: string;
listSessionsAgentId?: string;
};
Expand Down
6 changes: 3 additions & 3 deletions docs/ui-sdk/reference/events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface TurnStreamData {
page for you — emit an event whose fields do not match and it compiles cleanly, then fails to
render. Treat these shapes as required regardless.

The named event interfaces below are declared in `@truefoundry/assistant-ui-runtime`. Import
The named event interfaces below are declared in `@truefoundry/trueforge-assistant-ui-runtime`. Import
them from there if you want compile-time checking when building a server.
</Note>

Expand Down Expand Up @@ -156,9 +156,9 @@ interface ToolCall {
}

type ToolInfo =
| { type: "truefoundry-system"; name: string }
| { type: "trueforge-system"; name: string }
| { type: "mcp"; serverId: string; serverName: string; name: string }
| { type: string; name?: string; [key: string]: unknown };
| { type: string; name?: string };
```

`function.arguments` is a JSON **string**, not an object. `toolInfo` drives presentation: the
Expand Down
26 changes: 13 additions & 13 deletions docs/ui-sdk/reference/hooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,21 @@ Import these from `@truefoundry/trueforge-ui` like everything else:

| Export | Purpose |
| --- | --- |
| `useTrueFoundryAgentRuntime` | The underlying runtime hook. |
| `useTrueFoundryAgentSpec` | Read the active agent spec. |
| `useTrueFoundryUpdateAgentSpec` | Mutate the draft spec. |
| `useTrueFoundryCancel` | Cancel the in-flight turn. |
| `useTrueFoundryTurnId` | The id of the current turn. |
| `useTrueFoundryHistoryPagination` | Page backwards through history. |
| `useTrueFoundryMcpAuth` | Low-level MCP auth state. |
| `useTrueFoundryRespondToToolApproval` | Approve or reject a tool call. |
| `useTrueFoundryToolResponses` | Read tool responses. |
| `useTrueFoundryDownloadSandboxFile` | Download a sandbox artifact. |
| `useTrueForgeAgentRuntime` | The underlying runtime hook. |
| `useTrueForgeAgentSpec` | Read the active agent spec. |
| `useTrueForgeUpdateAgentSpec` | Mutate the draft spec. |
| `useTrueForgeCancel` | Cancel the in-flight turn. |
| `useTrueForgeTurnId` | The id of the current turn. |
| `useTrueForgeHistoryPagination` | Page backwards through history. |
| `useTrueForgeMcpAuth` | Low-level MCP auth state. |
| `useTrueForgeRespondToToolApproval` | Approve or reject a tool call. |
| `useTrueForgeToolResponses` | Read tool responses. |
| `useTrueForgeDownloadSandboxFile` | Download a sandbox artifact. |
| `mergeAgentSpec` | Merge partial specs. |
| `trueFoundryAttachmentAdapter` | Default attachment adapter. |
| `trueForgeAttachmentAdapter` | Default attachment adapter. |

Types: `DraftAgentConfig`, `NamedAgentConfig`, `TrueFoundryAgentConfig`,
`UseTrueFoundryAgentRuntimeOptions`.
Types: `DraftAgentConfig`, `NamedAgentConfig`, `TrueForgeAgentConfig`,
`UseTrueForgeAgentRuntimeOptions`.

## Utilities

Expand Down
7 changes: 3 additions & 4 deletions docs/ui-sdk/reference/server.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: "Server factory, context hooks, shell mode, and contract types."
## Factory

```ts
createTrueFoundryServer(options: CreateTrueFoundryServerOptions): TrueFoundryServer;
createTrueForgeServer(options: CreateTrueForgeServerOptions): TrueForgeServer;
```

Options: `{ chatServer, getCapabilities, getModels, getSkills, getMcp, searchAgents, saveAgent, deleteAgent?, catalog? }`.
Expand Down Expand Up @@ -49,7 +49,7 @@ to reference:
<Accordion title="Server interfaces">
`AgentUIServer`, `AgentChatServer`, `AgentBuilderServer`,
`AgentBuilderCapabilitiesResponse`, `CatalogServer`, `TrueForgeServerConfig`,
`CreateTrueFoundryServerOptions`, `TrueFoundryServer`.
`CreateTrueForgeServerOptions`, `TrueForgeServer`.
</Accordion>
<Accordion title="Sessions and turns">
`Session`, `CreateSessionRequest`, `UpdateSessionRequest`, `Turn`, `TurnState`,
Expand All @@ -60,8 +60,7 @@ to reference:
`UserToolResponseEvent`, `ApprovalDecision`.
</Accordion>
<Accordion title="Events and streaming">
`TurnStreamData`, `TurnStreamingEvent`, `SessionEvent`, `SessionEventItem`. These are typed
openly as `{ type: string; [key: string]: unknown }`; the concrete shapes are in
`TurnStreamData`, `TurnStreamingEvent`, `SessionEventItem`. The concrete event shapes are in
[Streaming events](/ui-sdk/reference/events).
</Accordion>
<Accordion title="Agents and models">
Expand Down
2 changes: 1 addition & 1 deletion docs/ui-sdk/reference/theme.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: "Theme provider, hooks, presets, brand, and slots."
| Export | Purpose |
| --- | --- |
| `ThemeProvider` | Owns light/dark/system state and injects token CSS variables on a wrapper `div.aui-theme-root`. |
| `SlotsProvider` | Slot override registry. Must sit outside `TrueFoundryChatProvider`. |
| `SlotsProvider` | Slot override registry. Must sit outside `TrueForgeChatProvider`. |
| `BrandLogo` | Product mark. `variant="icon"` renders the compact square asset; `variant="logo"` renders the wider asset and falls back to the icon. With no brand override, the logo variant uses the built-in TrueForge wordmark. Overridable slot. Props: `{ className?, variant?: "icon" \| "logo" }`. |
| `Icon` | Renders a built-in icon by name, or your replacement when `theme.icons` maps that name. Props: `{ name: string \| readonly string[] } & IconProps`. An array resolves to its **last** element, accommodating Font Awesome-style `["far", "clone"]` tuples; it is not a fallback chain. An unresolved name renders nothing. |

Expand Down
Loading
Loading