### 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 ```