Writer Framework Documentation

repository·dev·Indexed 23 days ago

https://github.com/writer/writer-framework

An open-source framework for building AI applications that separates UI development via a visual drag-and-drop editor from backend logic written in Python. It includes a CLI for scaffolding and running apps, a transaction-based system for undo/redo mutations, and tools for managing component hierarchies, bindings, and shared blueprints.

Tokens
5.1K
Snippets
6
Records
35
Agent score
80%

What's inside Writer Framework

  1. Overview of Writer Framework

    dev

    Writer Framework is an open-source framework designed for building AI applications. It employs a separation of concerns model:

    • UI: Built using a visual drag-and-drop editor.
    • Backend: Written in Python.

    This architecture allows for fast development while maintaining clean, testable business logic.

  2. Understand the role of Shared components

    dev
    Shared components in the writer-ui package are Vue.js components designed to be used in both the Builder (the development/editing environment) and the Renderer (the production/runtime environment). This ensures visual and functional consistency between how a component is configured and how it is ultimately displayed to the end-user.
  3. Serve static files via the /static route

    dev

    The apps/default/static/ directory is used to store files that should be served statically to users. Any file placed in this folder is accessible via the /static/ URL prefix. This is the recommended location for images, assets, and other files that need to be served directly to the client.

    For example, if you place an image named myimage.jpg in this folder, it will be accessible at the path static/myimage.jpg. You can then use this path as the src in an Image component.

  4. Create and manage apps with the Writer CLI

    dev

    Use the writer command-line interface to scaffold, edit, and run your AI applications.

    • writer hello: Generates a demo application to explore the framework.
    • writer create <app_name>: Scaffolds a new application with the specified name.
    • writer edit <app_name>: Opens the visual editor in your browser, allowing you to build the UI using drag-and-drop components.
    • writer run <app_name>: Starts your application.
    # Create a demo app
    writer hello
    
    # Create a new app
    writer create my_app
    
    # Edit your app (opens visual editor)
    writer edit my_app
    
    # Run your app
    writer run my_app
  5. Handle application state and user data

    dev

    The core engine manages the application's state through reactive properties:

    • userState: A reactive object representing the current application state. This state is synchronized with the backend.
    • userStateInitial: A read-only snapshot of the state as it was when the session was initialized.
    • featureFlags: A read-only array of active feature flags provided by the backend (via LaunchDarkly).
    • sessionTimestamp: A read-only timestamp of when the session was created.
  6. Manage Builder Manager Modes

    dev

    The BuilderManagerMode defines the current operational state of the editor. You can control the mode via the mode computed property.

    Available modes:

    • ui: Standard user interface mode.
    • blueprints: Blueprint editing mode (sets activeRootId to blueprints_root).
    • preview: Preview mode.
    • vault: Vault mode.
    • journal: Journal mode.

    Note: setMode and getMode are deprecated; use the mode property instead.

  7. Understand the Writer Framework application modes

    dev

    The Writer Framework UI operates in different modes depending on the context, which determines which core managers and components are initialized:

    • edit mode: Used for building applications. It initializes the BuilderManager, SecretsManager, and CollaborationManager. The UI renders the BuilderApp.vue component.
    • run mode: Used for executing/viewing the application. It initializes the NotesManager and renders the ComponentRenderer.vue component.

    These modes affect which Vue injection keys are available in the application context.

  8. Implement Undo/Redo with Mutation Transactions

    dev

    To support undo/redo functionality, the builder uses a transaction-based system. A transaction captures the state of components before and after a change.

    1. Open: Call openMutationTransaction(transactionId, transactionDesc, enableDebounce?). If enableDebounce is true and a transaction with the same ID was opened within 1000ms, it will merge into the existing transaction.
    2. Register Pre-state: Call registerPreMutation(component) to capture the component's state before modification.
    3. Register Post-state: Call registerPostMutation(component) to capture the component's state after modification.
    4. Close: Call closeMutationTransaction(transactionId) to finalize the transaction and add it to the history.

    Consuming Transactions:

    • consumeUndoTransaction(): Retrieves the last transaction from the undo stack.
    • consumeRedoTransaction(): Retrieves the next transaction from the redo stack.
    • getMutationTransactionsSnapshot(): Returns the current undo and redo transactions for UI rendering.
  9. Initialize the Writer Framework core engine

    dev

    To start the Writer Framework core engine, call generateCore() to obtain the core object, then call init() on that object. The init() method handles session initialization, WebSocket synchronization, and feature flag loading. Note that init() is an asynchronous operation.

    Important Lifecycle Note:

    • The mode (either 'run' or 'edit') is determined by the backend during initialization.
    • If the mode is 'edit', additional resources like userFunctions, runCode, and sourceFiles will be populated.
  10. Handle Component Selection

    dev

    The builder provides several ways to manage which components are currently selected in the editor:

    • setSelection(componentId, instancePath?, source?): Clears existing selection and sets a new selection. If componentId is null, the selection is cleared.
    • appendSelection(componentId, instancePath?, source?): Adds a component to the current selection. If instancePath is omitted, it attempts to resolve it from the DOM using the data-writer-instance-path attribute on the .ComponentRenderer element.
    • handleSelectionFromEvent(ev, componentId, instancePath?, source?): Handles selection logic for mouse or keyboard events. It supports multi-select via Shift, Ctrl, or Meta keys. If a key is held, it toggles the selection of the component.
    • removeSelectedComponentId(componentId): Removes a specific component from the current selection.

    Selection status can be checked via selectionStatus (returns SelectionStatus.None, SelectionStatus.Single, or SelectionStatus.Multiple).

  11. Initialize the Builder Manager with generateBuilderManager()

    dev
    The generateBuilderManager function is the primary entry point for managing the state of the visual editor. It returns a builder object containing reactive state and methods for managing editor modes, component selection, mutation transactions (undo/redo), and logging. The manager's mode is persisted in session storage.