### Minimal Example: Complete App - TypeScript & MEL
Source: https://github.com/manifesto-ai/core/blob/main/docs/guides/getting-started.md
Provides a complete, minimal example of a counter application, demonstrating domain definition, host creation, dispatching actions, and reading the snapshot. Includes both TypeScript and MEL implementations.
```typescript
// counter-app.ts
import { z } from "zod";
import { defineDomain } from "@manifesto-ai/builder";
import { createIntent } from "@manifesto-ai/core";
import { createHost } from "@manifesto-ai/host";
// 1. Define domain
const CounterDomain = defineDomain(
z.object({
count: z.number().default(0),
}),
({ state, actions, expr, flow }) => {
const { increment } = actions.define({
increment: {
flow: flow.patch(state.count).set(expr.add(state.count, 1)),
},
});
return { actions: { increment } };
}
);
// 2. Create host
const host = createHost(CounterDomain.schema, {
initialData: { count: 0 },
context: { now: () => Date.now() },
});
// 3. Dispatch and read snapshot
await host.dispatch(createIntent("increment", "intent-1"));
const snapshot = await host.getSnapshot();
console.log("Count:", snapshot?.data.count);
// → Count: 1
```
```mel
domain CounterDomain {
state {
count: number = 0
}
action increment() {
when true {
patch count = add(count, 1)
}
}
}
```
--------------------------------
### Install @manifesto-ai/memory and @manifesto-ai/world
Source: https://github.com/manifesto-ai/core/blob/main/packages/memory/docs/GUIDE.md
Installs the necessary packages for using the memory and world protocols. This is the first step to getting started with the @manifesto-ai/memory library.
```bash
pnpm add @manifesto-ai/memory @manifesto-ai/world
```
--------------------------------
### Minimal Setup for @manifesto-ai/core
Source: https://github.com/manifesto-ai/core/blob/main/packages/core/docs/GUIDE.md
Demonstrates the minimal setup required to initialize the @manifesto-ai/core library. It includes creating a core instance, defining a schema, setting up context, and creating an initial snapshot.
```typescript
import { createCore, createSnapshot, createIntent } from "@manifesto-ai/core";
import type { DomainSchema } from "@manifesto-ai/core";
// 1. Create core instance
const core = createCore();
// 2. Define a minimal schema
const schema: DomainSchema = {
id: "example:counter",
version: "1.0.0",
hash: "example-hash",
types: {},
state: {
fields: {
count: { type: "number", required: true, default: 0 },
},
},
computed: {
fields: {
"computed.count": {
deps: ["count"],
expr: { kind: "get", path: "count" },
},
},
},
actions: {
increment: {
flow: {
kind: "patch",
op: "set",
path: "count",
value: {
kind: "add",
left: { kind: "get", path: "count" },
right: { kind: "lit", value: 1 },
},
},
},
},
};
// 3. Provide host context (deterministic inputs)
const context = { now: 0, randomSeed: "seed" };
// 4. Create initial snapshot
const snapshot = createSnapshot({ count: 0 }, schema.hash, context);
// 5. Verify
console.log(snapshot.data.count);
// → 0
```
--------------------------------
### Install @manifesto-ai/world and Dependencies
Source: https://github.com/manifesto-ai/core/blob/main/packages/world/docs/GUIDE.md
Installs the necessary @manifesto-ai/world, @manifesto-ai/host, and @manifesto-ai/core packages using npm. This is the first step before setting up the world.
```bash
npm install @manifesto-ai/world @manifesto-ai/host @manifesto-ai/core
```
--------------------------------
### Setting up and Running a Counter App with Manifesto AI
Source: https://github.com/manifesto-ai/core/blob/main/packages/builder/docs/GUIDE.md
Provides instructions and commands to set up a new project directory, install necessary dependencies, save the counter application code, and run it using tsx. This setup is for a demo application showcasing Manifesto AI components.
```bash
mkdir manifesto-counter
cd manifesto-counter
npm init -y
npm install @manifesto-ai/builder @manifesto-ai/core @manifesto-ai/host @manifesto-ai/world @manifesto-ai/bridge zod
npm install -D tsx typescript
# Save the code above as counter-app.ts
npx tsx counter-app.ts
```
--------------------------------
### Minimal Host Setup with Schema Definition
Source: https://github.com/manifesto-ai/core/blob/main/packages/host/docs/GUIDE.md
Demonstrates the minimal setup for creating a host instance. It involves defining a DomainSchema, creating the host with initial data and context, and then retrieving an initial snapshot.
```typescript
import { createHost } from "@manifesto-ai/host";
import type { DomainSchema } from "@manifesto-ai/core";
// 1. Define schema
const schema: DomainSchema = {
id: "example:counter",
version: "1.0.0",
hash: "example-hash",
state: {
count: { type: "number", default: 0 },
},
actions: {
increment: {
flow: {
kind: "patch",
op: "set",
path: "count",
value: { kind: "add", left: { kind: "get", path: "count" }, right: 1 },
},
},
},
};
// 2. Create host
const host = createHost(schema, {
initialData: { count: 0 },
context: { now: () => Date.now() },
});
// 3. Verify
const snapshot = await host.getSnapshot();
console.log(snapshot?.data.count);
// → 0
```
--------------------------------
### Install Manifesto Core Packages
Source: https://github.com/manifesto-ai/core/blob/main/docs/guides/getting-started.md
Installs the necessary packages for the low-level approach of Manifesto, including builder, core, host, and Zod for schema definition. Supports npm, pnpm, and bun package managers.
```bash
npm install @manifesto-ai/builder @manifesto-ai/core @manifesto-ai/host zod
# or
pnpm add @manifesto-ai/builder @manifesto-ai/core @manifesto-ai/host zod
# or
bun add @manifesto-ai/builder @manifesto-ai/core @manifesto-ai/host zod
```
--------------------------------
### Minimal @manifesto-ai/world Setup with Host
Source: https://github.com/manifesto-ai/core/blob/main/packages/world/docs/GUIDE.md
Demonstrates the minimal setup for creating a Manifesto World. It involves creating a host instance and then initializing the world with a schema hash and an auto-approve authority handler. The world ID is then logged.
```typescript
import { createManifestoWorld, createAutoApproveHandler } from "@manifesto-ai/world";
import { createHost } from "@manifesto-ai/host";
// 1. Create host
const host = createHost(schema, {
initialData: {},
context: { now: () => Date.now() },
});
// 2. Create world with auto-approve authority
const world = createManifestoWorld({
schemaHash: "my-app-v1",
host,
defaultAuthority: createAutoApproveHandler(),
});
// 3. Verify
console.log(world.getCurrentWorld().worldId);
// → "w_abc123..."
```
--------------------------------
### Hook Usage Examples
Source: https://github.com/manifesto-ai/core/blob/main/docs/packages/app/api-reference.md
Demonstrates practical examples of using `app.hooks.on()` to log action completion details and `app.hooks.once()` to execute a one-time setup when the application is ready.
```typescript
// Log all action completions
app.hooks.on("action:completed", ({ proposalId, result }) => {
console.log(`Action ${proposalId} completed:`, result.status);
});
// One-time ready handler
app.hooks.once("app:ready", () => {
console.log("App is ready!");
});
```
--------------------------------
### Complete Host Setup and Dispatch Example (TypeScript)
Source: https://github.com/manifesto-ai/core/blob/main/docs/core-concepts/host.md
A comprehensive example demonstrating the initialization of a host, registration of an effect handler for creating a todo item via an API, dispatching an intent, and retrieving the updated snapshot. This showcases the typical workflow of the Host.
```typescript
import { createIntent } from "@manifesto-ai/core";
import { createHost } from "@manifesto-ai/host";
// 1. Create host
const host = createHost(TodoSchema, {
snapshot: initialSnapshot,
loop: { maxIterations: 10 },
context: { now: () => Date.now() },
});
// 2. Register effect handlers
host.registerEffect('api:createTodo', async (type, params, _context) => {
const response = await fetch('/api/todos', {
method: 'POST',
body: JSON.stringify({
title: params.title,
localId: params.localId
})
});
const todo = await response.json();
return [
{ op: 'set', path: `todos.${params.localId}.serverId`, value: todo.id },
{ op: 'set', path: `todos.${params.localId}.syncStatus`, value: 'synced' }
];
});
// 3. Dispatch intent
const intent = createIntent(
'addTodo',
{ title: 'Buy milk', localId: 'local-123' },
'intent-1'
);
const result = await host.dispatch(intent);
console.log(result.status); // 'complete'
const snapshot = await host.getSnapshot();
console.log(snapshot?.data.todos);
```
--------------------------------
### Install @manifesto-ai/bridge and Core Packages
Source: https://github.com/manifesto-ai/core/blob/main/packages/bridge/docs/GUIDE.md
Installs the necessary @manifesto-ai/bridge, @manifesto-ai/world, @manifesto-ai/host, and @manifesto-ai/core packages using npm.
```bash
npm install @manifesto-ai/bridge @manifesto-ai/world @manifesto-ai/host @manifesto-ai/core
```
--------------------------------
### Minimal @manifesto-ai/lab Setup in TypeScript
Source: https://github.com/manifesto-ai/core/blob/main/packages/lab/docs/GUIDE.md
Demonstrates the minimal setup required to initialize and use @manifesto-ai/lab. It involves importing necessary modules, creating a base Manifesto World, wrapping it with the lab functionality, and verifying basic lab metadata.
```typescript
// 1. Import
import { createManifestoWorld } from '@manifesto-ai/world';
import { withLab } from '@manifesto-ai/lab';
// 2. Create base World
const world = createManifestoWorld({
schemaHash: schema.hash,
host,
});
// 3. Wrap with Lab
const labWorld = withLab(world, {
runId: 'exp-001',
necessityLevel: 0,
outputPath: './traces',
});
// 4. Verify
console.log(labWorld.labMeta.runId);
// → 'exp-001'
console.log(labWorld.state.status);
// → 'running'
```
--------------------------------
### Submit Proposal Example (Node.js)
Source: https://github.com/manifesto-ai/core/blob/main/packages/world/docs/GUIDE.md
Demonstrates how an AI agent submits a proposal through the world protocol. The example shows expected output statuses and proposal IDs, and mentions that email notifications are sent automatically.
```typescript
// AI agent submits a proposal
const result = await world.submitProposal({
actorId: "agent-assistant",
intent: {
type: "data.delete",
input: { recordId: "rec_123" },
},
});
// Result will be pending
console.log(result.status); // → "pending"
console.log(result.proposal.proposalId); // → "p_abc123"
```
--------------------------------
### Minimal React Setup with @manifesto-ai/react
Source: https://github.com/manifesto-ai/core/blob/main/packages/react/docs/GUIDE.md
Demonstrates a minimal setup for a React application using @manifesto-ai/react and @manifesto-ai/builder. It includes defining a domain with state and actions, creating the Manifesto app, and integrating it into React components using hooks like `useValue` and `useActions`.
```tsx
import { z } from "zod";
import { defineDomain, expr, flow } from "@manifesto-ai/builder";
import { createManifestoApp } from "@manifesto-ai/react";
// 1. Define domain
const CounterDomain = defineDomain(
z.object({ count: z.number().default(0) }),
({ state, actions }) => ({
actions: {
increment: actions.define({
flow: flow.patch(state.count).set(expr.add(state.count, 1)),
}),
},
})
);
// 2. Create app
const Counter = createManifestoApp(CounterDomain, {
initialState: { count: 0 },
});
// 3. Use in components
function App() {
return (
);
}
function CounterDisplay() {
const count = Counter.useValue((s) => s.count);
const { increment } = Counter.useActions();
return (
);
}
```
--------------------------------
### Install @manifesto-ai/react and Dependencies
Source: https://github.com/manifesto-ai/core/blob/main/packages/react/docs/GUIDE.md
Installs the necessary @manifesto-ai/react, @manifesto-ai/builder, zod, and react packages using npm. This is the first step for setting up a new project or adding the library to an existing one.
```bash
npm install @manifesto-ai/react @manifesto-ai/builder zod react
```
--------------------------------
### Install @manifesto-ai/lab and Core Packages
Source: https://github.com/manifesto-ai/core/blob/main/packages/lab/docs/GUIDE.md
Installs the necessary @manifesto-ai/lab package along with related core packages like @manifesto-ai/world, @manifesto-ai/host, and @manifesto-ai/core using npm. This is the first step before setting up any experiments.
```bash
npm install @manifesto-ai/lab @manifesto-ai/world @manifesto-ai/host @manifesto-ai/core
```
--------------------------------
### Basic Application Setup and Domain Action
Source: https://github.com/manifesto-ai/core/blob/main/packages/app/docs/SPEC-0.4.7v.md
Demonstrates how to create a basic application with initial data and services, and how to perform a domain action.
```APIDOC
## POST /api/application
### Description
Creates a new application instance with specified initial data and services.
### Method
POST
### Endpoint
/api/application
### Parameters
#### Request Body
- **domainMel** (string) - Required - The domain definition for the application.
- **initialData** (object) - Optional - The initial state of the application's data.
- **services** (object) - Optional - An object containing service configurations.
- **http.fetch** (function) - Optional - A function to handle HTTP fetch requests.
### Request Example
```json
{
"domainMel": "...your domain definition...",
"initialData": {
"todos": []
},
"services": {
"http.fetch": "async (params, ctx) => { ... }"
}
}
```
### Response
#### Success Response (200)
- **app** (object) - The created application instance.
- **ready** (function) - A function to call to prepare the application for use.
- **act** (function) - A function to perform actions within the application's domain.
#### Response Example
```json
{
"app": {
"ready": "function",
"act": "function"
}
}
```
## POST /api/application/action/domain
### Description
Performs a domain-specific action within the application.
### Method
POST
### Endpoint
/api/application/action/domain
### Parameters
#### Request Body
- **actionType** (string) - Required - The type of the domain action to perform (e.g., 'todo.add').
- **payload** (object) - Optional - The data required for the action.
- **options** (object) - Optional - Options for performing the action.
- **done** (boolean) - If true, returns the completed action handle.
### Request Example
```json
{
"actionType": "todo.add",
"payload": {
"title": "Buy milk"
},
"options": {
"done": true
}
}
```
### Response
#### Success Response (200)
- **result** (object) - The result of the action.
- **worldId** (string) - The ID of the world created by the action.
- **runtime** (string) - The runtime environment of the action ('domain').
#### Response Example
```json
{
"result": {
"worldId": "some-world-id",
"runtime": "domain"
}
}
```
```
--------------------------------
### Install Manifesto AI App and Compiler Packages
Source: https://github.com/manifesto-ai/core/blob/main/docs/packages/app/getting-started.md
Installs the necessary Manifesto AI packages for app development. Supports npm, pnpm, and bun package managers.
```bash
# Using npm
npm install @manifesto-ai/app @manifesto-ai/compiler
# Using pnpm
pnpm add @manifesto-ai/app @manifesto-ai/compiler
# Using bun
bun add @manifesto-ai/app @manifesto-ai/compiler
```
--------------------------------
### Quickstart: Create World, register actor, submit proposal
Source: https://github.com/manifesto-ai/core/blob/main/packages/world/README.md
Demonstrates the basic usage of the World package. It shows how to initialize a World instance with an auto-approve authority handler, register a human actor, and submit a proposal for execution.
```typescript
import { createManifestoWorld, createAutoApproveHandler } from "@manifesto-ai/world";
import { createHost } from "@manifesto-ai/host";
// Assuming 'schema' is defined elsewhere
const host = createHost(schema, {
initialData: {},
context: { now: () => Date.now() },
});
const world = createManifestoWorld({
schemaHash: "todo-v1",
host,
defaultAuthority: createAutoApproveHandler(),
});
// Register an actor
world.registerActor({
actorId: "user-1",
kind: "human",
name: "Alice",
});
// Submit a proposal
const result = await world.submitProposal({
actorId: "user-1",
intent: {
type: "todo.add",
input: { title: "Buy milk" },
},
});
console.log(result.status); // → "completed"
console.log(result.world.worldId); // → "w_abc123..."
```
--------------------------------
### Quick Example: Setting up and using Bridge
Source: https://github.com/manifesto-ai/core/blob/main/packages/bridge/docs/README.md
Demonstrates the basic setup and usage of the Bridge. This includes creating a world and bridge instance, registering a projection to transform UI events into intents, subscribing to snapshot changes, dispatching events, and finally cleaning up resources.
```typescript
import { createBridge, createUISourceEvent } from "@manifesto-ai/bridge";
import { createManifestoWorld } from "@manifesto-ai/world";
// Create world and bridge
const world = createManifestoWorld({ schemaHash: "todo-v1", host });
const bridge = createBridge({
world,
schemaHash: world.schemaHash,
defaultActor: { actorId: "user-1", kind: "human" },
});
// Register a projection
bridge.registerProjection({
projectionId: "ui:todo-add",
project(req) {
if (req.source.payload?.action === "add") {
return {
kind: "intent",
body: { type: "todo.add", input: req.source.payload.data },
};
}
return { kind: "none" };
},
});
// Subscribe to snapshot changes
const unsubscribe = bridge.subscribe((snapshot) => {
console.log("Todos:", snapshot.data.todos);
});
// Dispatch an event
await bridge.dispatchEvent(
createUISourceEvent("add-button", { action: "add", data: { title: "Buy milk" } })
);
// Or dispatch intent directly
await bridge.dispatch({ type: "todo.add", input: { title: "Walk dog" } });
// Clean up
unsubscribe();
bridge.dispose();
```
--------------------------------
### Define Computed Values in MEL
Source: https://github.com/manifesto-ai/core/blob/main/docs/guides/getting-started.md
Defines computed values in MEL, a domain-specific language. Similar to the TypeScript example, these computed properties are derived from the state and always recalculated.
```mel
domain CounterDomain {
state {
count: number = 0
lastAction: string | null = null
}
computed isPositive = gt(count, 0)
computed isZero = eq(count, 0)
computed description = cond(
gt(count, 0),
"positive",
cond(
lt(count, 0),
"negative",
"zero"
)
)
}
```
--------------------------------
### TypeScript Flow Data Structure Example
Source: https://github.com/manifesto-ai/core/blob/main/docs/guides/getting-started.md
Illustrates the declarative data structure of a 'Flow' in TypeScript. Flows do not execute code but describe computations, modify the Snapshot, always terminate, and have no memory between executions.
```typescript
// This is DATA, not CODE
{
kind: "seq",
steps: [
{ kind: "patch", op: "set", path: "count", value: { kind: "lit", value: 0 } },
{ kind: "patch", op: "set", path: "lastAction", value: { kind: "lit", value: "reset" } }
]
}
```
--------------------------------
### Quick Example: Creating and using a Host
Source: https://github.com/manifesto-ai/core/blob/main/packages/host/README.md
Demonstrates how to create a Host instance, register an effect handler for API calls, dispatch an intent, and log the result. It requires schema, initial data, and a context.
```typescript
import { createHost } from "@manifesto-ai/host";
import { createIntent } from "@manifesto-ai/core";
import type { DomainSchema } from "@manifesto-ai/core";
// Create host
const host = createHost(schema, {
initialData: { user: null },
context: { now: () => Date.now() },
});
// Register effect handler
host.registerEffect("api.fetch", async (_type, params) => {
const response = await fetch(params.url);
const data = await response.json();
return [{ op: "set", path: params.targetPath, value: data }];
});
// Dispatch intent
const intent = createIntent("loadUser", { userId: "123" }, "intent-1");
const result = await host.dispatch(intent);
console.log(result.status); // → "complete"
console.log(result.snapshot.data.user); // → { id: "123", name: "..." }
```
--------------------------------
### Define Computed Value in MEL
Source: https://github.com/manifesto-ai/core/blob/main/docs/guides/getting-started.md
Provides the MEL equivalent for defining a computed value with dependencies, corresponding to the TypeScript example. This demonstrates how to define a domain, state, and a computed value using MEL syntax.
```mel
domain Example {
state {
items: Array = []
}
computed total = len(items)
}
```
--------------------------------
### Fix Schema Validation Error in TypeScript
Source: https://github.com/manifesto-ai/core/blob/main/docs/guides/getting-started.md
Corrects a schema validation error in Manifesto AI Core by ensuring the initial state matches the Zod schema. This example demonstrates the incorrect and correct way to initialize a snapshot with a number type.
```typescript
import { createSnapshot } from "@manifesto-ai/core";
const context = { now: 0, randomSeed: "seed" };
const initialSnapshot = createSnapshot({ count: "0" }, schema.hash, context); // WRONG: should be number
// Fix:
const initialSnapshot = createSnapshot({ count: 0 }, schema.hash, context); // RIGHT
```
--------------------------------
### Add Re-entry Safety - TypeScript & MEL
Source: https://github.com/manifesto-ai/core/blob/main/docs/guides/getting-started.md
Illustrates how to prevent actions from running multiple times, which is crucial for maintaining data consistency. The TypeScript example uses `flow.onceNull` to ensure the code within only runs once, and the MEL equivalent uses `isNull`.
```typescript
// WRONG: Runs every time
flow.patch(state.count).set(expr.add(state.count, 1))
// RIGHT: Only runs once
flow.onceNull(state.initialized, ({ patch }) => {
patch(state.count).set(expr.add(state.count, 1));
patch(state.initialized).set(expr.lit(true));
})
```
```mel
domain CounterDomain {
state {
count: number = 0
initialized: boolean | null = null
}
action init() {
when isNull(initialized) {
patch count = add(count, 1)
patch initialized = true
}
}
}
```
--------------------------------
### Minimal @manifesto-ai/bridge Setup
Source: https://github.com/manifesto-ai/core/blob/main/packages/bridge/docs/GUIDE.md
Demonstrates the essential steps to set up a bridge instance, including creating a host, a world, and the bridge itself, followed by verifying the initial state.
```typescript
import { createBridge } from "@manifesto-ai/bridge";
import { createManifestoWorld, createAutoApproveHandler } from "@manifesto-ai/world";
import { createHost } from "@manifesto-ai/host";
// 1. Create host and world
const host = createHost(schema, {
initialData: {},
context: { now: () => Date.now() },
});
const world = createManifestoWorld({
schemaHash: "my-app-v1",
host,
defaultAuthority: createAutoApproveHandler(),
});
// 2. Create bridge
const bridge = createBridge({
world,
schemaHash: world.schemaHash,
defaultActor: { actorId: "user-1", kind: "human" },
});
// 3. Verify
const snapshot = bridge.getSnapshot();
console.log(snapshot?.data);
// → { ... initial state }
```
--------------------------------
### Add Effects (API Calls) - TypeScript & MEL
Source: https://github.com/manifesto-ai/core/blob/main/docs/guides/getting-started.md
Demonstrates how to define and register effects, which are used to perform asynchronous operations like API calls. The TypeScript example shows how to declare an effect within a flow, and the MEL equivalent provides a declarative approach.
```typescript
// Define action with effect
const { fetchUser } = actions.define({
fetchUser: {
input: z.object({ id: z.string() }),
flow: flow.seq(
// Mark as loading
flow.patch(state.loading).set(expr.lit(true)),
// Declare effect (NOT executed yet)
flow.effect("api:fetchUser", {
userId: expr.input("id")
}),
// Mark as loaded (executed after effect completes)
flow.patch(state.loading).set(expr.lit(false))
),
},
});
// Register effect handler in Host
host.registerEffect("api:fetchUser", async (type, params) => {
const response = await fetch(`/api/users/${params.userId}`);
const user = await response.json();
return [
{ op: "set", path: "user", value: user }
];
});
```
```mel
domain UsersDomain {
state {
loading: boolean = false
}
action fetchUser(id: string) {
when true {
patch loading = true
effect api.fetchUser({
userId: id
})
patch loading = false
}
}
}
```
--------------------------------
### App Initialization with ready() Method
Source: https://github.com/manifesto-ai/core/blob/main/packages/app/docs/SPEC-0.4.10v.md
The `ready()` method is responsible for completing all asynchronous initialization tasks for the application. This includes compiling the domain, validating the schema, caching it, and initializing runtimes and plugins. It must emit a `domain:resolved` hook only after validation passes and throws errors for failures.
```typescript
interface App {
ready(): Promise;
}
```
--------------------------------
### App Initialization (ready())
Source: https://github.com/manifesto-ai/core/blob/main/packages/app/docs/SPEC-0.4.10v.md
The `ready()` method initializes the application and completes asynchronous operations. It validates the domain schema and prepares the application for use.
```APIDOC
## READY Initialization
### Description
The `ready()` method is responsible for completing asynchronous initialization tasks, validating the domain schema, caching the resolved domain schema, and emitting the `domain:resolved` hook. It also handles the initialization of Domain and System Runtimes, validating services, and initializing plugins.
### Method
`ready()`
### Endpoint
N/A
### Parameters
N/A
### Request Example
N/A
### Response
#### Success Response (Promise)
- Completes all asynchronous initialization.
#### Response Example
N/A
### Errors
- `AppNotReadyError`: Thrown if mutation/read APIs are called before `ready()` resolves (READY-1).
- `ReservedNamespaceError`: Thrown if DomainSchema contains action types with `system.*` prefix (READY-4).
- `ReservedEffectTypeError`: Thrown if `CreateAppOptions.services` contains `system.get` (READY-5).
```
--------------------------------
### Counter App: End-to-End Example in TypeScript
Source: https://github.com/manifesto-ai/core/blob/main/packages/builder/docs/GUIDE.md
This TypeScript code demonstrates the complete Counter App example, integrating domain definition, core creation, snapshot generation, host setup, world configuration, and bridge for state management and action dispatching. It requires Node.js 18+ and TypeScript. The output includes initial state, state updates, computed properties, and action history.
```typescript
// counter-app.ts
// Copy this entire file and run: npx tsx counter-app.ts
import { z } from "zod";
import { defineDomain } from "@manifesto-ai/builder";
import { createCore, createSnapshot } from "@manifesto-ai/core";
import { createHost } from "@manifesto-ai/host";
import { createManifestoWorld, createAutoApproveHandler } from "@manifesto-ai/world";
import { createBridge } from "@manifesto-ai/bridge";
// ============ Step 1: Define Domain ============
const CounterDomain = defineDomain(
// State schema (Zod-first)
z.object({
count: z.number().default(0),
lastAction: z.string().optional(),
history: z.array(z.number()).default([]),
}),
// Domain definition
({ state, computed, actions, expr, flow }) => {
// Computed: Is count positive?
const { isPositive } = computed.define({
isPositive: expr.gt(state.count, 0),
});
// Computed: Average of history
const { average } = computed.define({
average: expr.cond(
expr.gt(expr.len(state.history), 0),
expr.div(
expr.reduce(state.history, (sum, val) => expr.add(sum, val), 0),
expr.len(state.history)
),
expr.lit(0)
),
});
// Actions
const { increment } = actions.define({
increment: {
flow: flow.seq(
flow.patch(state.count).set(expr.add(state.count, 1)),
flow.patch(state.history).set(expr.append(state.history, state.count)),
flow.patch(state.lastAction).set(expr.lit("increment"))
),
},
});
const { decrement } = actions.define({
decrement: {
flow: flow.seq(
flow.patch(state.count).set(expr.sub(state.count, 1)),
flow.patch(state.history).set(expr.append(state.history, state.count)),
flow.patch(state.lastAction).set(expr.lit("decrement"))
),
},
});
const { reset } = actions.define({
reset: {
flow: flow.seq(
flow.patch(state.count).set(expr.lit(0)),
flow.patch(state.history).set(expr.lit([])),
flow.patch(state.lastAction).set(expr.lit("reset"))
),
},
});
const { setCount } = actions.define({
setCount: {
input: z.object({ value: z.number() }),
flow: flow.seq(
flow.patch(state.count).set(expr.input("value")),
flow.patch(state.lastAction).set(expr.lit("setCount"))
),
},
});
return {
computed: { isPositive, average },
actions: { increment, decrement, reset, setCount },
};
},
{ id: "counter-domain", version: "1.0.0" }
);
// ============ Step 2: Create Core ============
const core = createCore();
// ============ Step 3: Create Initial Snapshot ============
const context = { now: 0, randomSeed: "seed" };
const initialSnapshot = createSnapshot(
{ count: 0, lastAction: undefined, history: [] },
CounterDomain.schema.hash,
context
);
console.log("Initial state:", initialSnapshot.data);
// → { count: 0, lastAction: undefined, history: [] }
// ============ Step 4: Create Host ============
const host = createHost(CounterDomain.schema, {
snapshot: initialSnapshot,
context: { now: () => Date.now() },
});
// ============ Step 5: Create World with Auto-Approve Authority ============
const world = createManifestoWorld({
schemaHash: "counter-app-v1",
host,
defaultAuthority: createAutoApproveHandler(),
});
// Register actors
world.registerActor({
actorId: "user-1",
kind: "human",
name: "Alice",
});
// ============ Step 6: Create Bridge ============
const bridge = createBridge({
world,
schemaHash: "counter-app-v1",
defaultActor: { actorId: "user-1", kind: "human" },
});
// ============ Step 7: Subscribe to State Changes ============
bridge.subscribe((snapshot) => {
console.log("\n=== State Updated ===");
console.log("Count:", snapshot.data.count);
console.log("Last Action:", snapshot.data.lastAction);
console.log("History:", snapshot.data.history);
console.log("Is Positive:", snapshot.computed.isPositive);
console.log("Average:", snapshot.computed.average);
});
// ============ Step 8: Run Actions ============
async function runDemo() {
console.log("\n🚀 Starting Counter App Demo\n");
// Action 1: Increment
console.log(">>> Dispatching: increment");
await bridge.dispatch({ type: "increment", input: {} });
// Action 2: Increment again
console.log("\n>>> Dispatching: increment");
await bridge.dispatch({ type: "increment", input: {} });
// Action 3: Decrement
console.log("\n>>> Dispatching: decrement");
await bridge.dispatch({ type: "decrement", input: {} });
// Action 4: Set count to 10
console.log("\n>>> Dispatching: setCount with value 10");
await bridge.dispatch({ type: "setCount", input: { value: 10 } });
// Action 5: Reset
console.log("\n>>> Dispatching: reset");
await bridge.dispatch({ type: "reset", input: {} });
console.log("\n✅ Counter App Demo Finished");
}
runDemo();
```
--------------------------------
### Guarded Action Execution with Mel
Source: https://github.com/manifesto-ai/core/blob/main/docs/packages/app/getting-started.md
Demonstrates the importance of re-entry guards in Mel actions to ensure they complete properly. The 'RIGHT' example uses `once()` to create a guard, ensuring the action logic runs only once, preventing infinite loops or unintended multiple executions.
```mel
// WRONG: No guard, never "completes"
action doSomething() {
patch count = add(count, 1)
}
```
```mel
// RIGHT: Guarded, runs once
action doSomething() {
once(doSomethingIntent) {
patch doSomethingIntent = $meta.intentId
patch count = add(count, 1)
}
}
```
--------------------------------
### Clone and Run Example Apps using Git and PNPM
Source: https://github.com/manifesto-ai/core/blob/main/docs/packages/app/examples.md
Provides instructions on how to clone the Manifesto AI core repository and run example applications like 'todo-app' and 'logistics-app' using Git and PNPM.
```bash
git clone https://github.com/manifesto-ai/core
cd core
pnpm install
pnpm dev:todo # Run todo app
pnpm dev:logistics # Run logistics app
```
--------------------------------
### Basic Experiment with Tracing in TypeScript
Source: https://github.com/manifesto-ai/core/blob/main/packages/lab/docs/GUIDE.md
Illustrates a basic experiment setup using @manifesto-ai/lab, including host and world creation, lab wrapping with tracing enabled, actor registration, proposal submission, and trace retrieval. It shows how to get experiment outcome, event count, and duration.
```typescript
import { createManifestoWorld } from '@manifesto-ai/world';
import { createManifestoHost } from '@manifesto-ai/host';
import { withLab } from '@manifesto-ai/lab';
// 1. Setup
const host = createManifestoHost();
const world = createManifestoWorld({ schemaHash: schema.hash, host });
// 2. Wrap with Lab
const labWorld = withLab(world, {
runId: 'simple-exp-001',
necessityLevel: 0,
outputPath: './traces',
projection: { enabled: true, mode: 'watch' },
});
// 3. Register actors
labWorld.registerActor({
actorId: 'system',
kind: 'system',
name: 'System Actor',
});
// 4. Execute
await labWorld.submitProposal({
actorId: 'system',
intent: {
type: 'incrementCounter',
input: {},
},
});
// 5. Get trace
const trace = labWorld.trace();
console.log(`Outcome: ${trace.outcome}`);
console.log(`Events: ${trace.events.length}`);
console.log(`Duration: ${trace.header.durationMs}ms`);
// Expected output:
// → Outcome: success
// → Events: 5
// → Duration: 12ms
```
--------------------------------
### Development Setup Bash Commands
Source: https://github.com/manifesto-ai/core/blob/main/CONTRIBUTING.md
This snippet provides essential bash commands for setting up the development environment. It includes cloning the repository, installing dependencies using pnpm, building all packages, and running tests.
```bash
git clone https://github.com/manifesto-ai/core.git
cd core
pnpm install
pnpm build
pnpm test
```
--------------------------------
### Specify Dependencies for Computed Values in TypeScript
Source: https://github.com/manifesto-ai/core/blob/main/docs/guides/getting-started.md
Resolves the "Computed value is undefined" error in Manifesto AI Core by ensuring correct dependency specification for computed values. This TypeScript example shows how to include all state fields used in the expression within the `deps` array.
```typescript
const { total } = computed.define({
total: {
deps: [state.items], // Must include dependencies
expr: expr.len(state.items),
},
});
```
--------------------------------
### App Initialization and Disposal
Source: https://github.com/manifesto-ai/core/blob/main/packages/app/docs/SPEC-0.4.7v.md
Documentation for the `ready()` and `dispose()` methods of the App interface, including their behavior and associated rules.
```APIDOC
## App Lifecycle Management
### `ready()` Method
#### Description
Initializes the application by completing asynchronous tasks, compiling the domain, validating schemas, and initializing runtimes and plugins.
#### Method
`Promise`
#### Behavior
1. Completes all asynchronous initialization.
2. Compiles domain if provided as MEL text.
3. Validates that `DomainSchema` contains no `system.*` action types.
4. Initializes Domain Runtime with user schema.
5. Initializes System Runtime with fixed system schema.
6. Validates services if `validation.services='strict'`.
7. Initializes plugins in order.
8. Throws appropriate errors for failures.
#### Rules (MUST):
- **READY-1**: Calling mutation/read APIs before `ready()` MUST throw `AppNotReadyError`.
- **READY-2**: Affected APIs include `getState`, `subscribe`, `act`, `fork`, `switchBranch`, `currentBranch`, `listBranches`, `session`, `getActionHandle`, `getMigrationLinks`, `system.*`, `memory.*`, `branch.*`.
- **READY-3**: Implicit lazy initialization is FORBIDDEN.
- **READY-4**: If `DomainSchema` contains action types with `system.*` prefix, `ready()` MUST throw `ReservedNamespaceError`.
- **READY-5**: If `CreateAppOptions.services` contains `system.get`, `ready()` MUST throw `ReservedEffectTypeError`.
### `dispose()` Method
#### Description
Disposes of the application, performing a graceful shutdown or immediate termination based on options.
#### Method
`dispose(opts?: DisposeOptions): Promise`
#### Parameters
**Path Parameters**
- None
**Query Parameters**
- None
**Request Body**
- **force** (`boolean`) - Optional - Force immediate termination.
- **timeoutMs** (`number`) - Optional - Graceful shutdown timeout in ms.
#### Rules (MUST):
- **DISPOSE-1**: All API calls after `dispose()` MUST throw `AppDisposedError`.
- **DISPOSE-2**: `dispose()` MUST trigger AbortSignal for pending operations.
- **DISPOSE-3**: If `force=false`, MUST wait for in-progress actions; if `force=true`, MUST terminate immediately.
```
--------------------------------
### Install @manifesto-ai/builder and Dependencies
Source: https://github.com/manifesto-ai/core/blob/main/packages/builder/docs/GUIDE.md
Installs the @manifesto-ai/builder, @manifesto-ai/core, and zod packages using npm. These are essential for setting up and using the builder library.
```bash
npm install @manifesto-ai/builder @manifesto-ai/core zod
```
--------------------------------
### Quick Example: Initialize and use [mainExport] from @[org]/[package]
Source: https://github.com/manifesto-ai/core/blob/main/docs-original/oss-doc-templates/10-PKG-README.template.md
A minimal, runnable example demonstrating the core functionality of the @[org]/[package] package. It shows how to set up an instance using [mainExport] and perform a basic operation using its [method].
```typescript
import { [mainExport] } from '@[org]/[package]';
// Setup
const [instance] = [mainExport]({
[minimalConfig]: [value]
});
// Usage
const result = [instance].[method]([args]);
console.log(result);
// → [expected_output]
```
--------------------------------
### Minimal Setup for @manifesto-ai/memory
Source: https://github.com/manifesto-ai/core/blob/main/packages/memory/docs/GUIDE.md
Sets up the core components of the @manifesto-ai/memory library: InMemoryStore, ExistenceVerifier, and SimpleSelector. This minimal setup is essential for basic memory operations.
```typescript
// 1. Import
import {
InMemoryStore,
createExistenceVerifier,
createSimpleSelector,
} from "@manifesto-ai/memory";
// 2. Setup the 4-Layer stack
const store = new InMemoryStore();
const verifier = createExistenceVerifier();
const selector = createSimpleSelector(store, verifier);
// 3. Verify
console.log(store.size);
// → 0
```