6.2.0 • Published 5 months ago

@sashimo/lib v6.2.0

Weekly downloads
-
License
MIT
Repository
-
Last release
5 months ago

🌟 Sashi - Your Magical AI-Powered Admin Companion! 🤖

🚀 Welcome to the Enchanted World of Sashi

Sashi is the core TypeScript/JavaScript library that powers the Sashi workflow system. It runs inside your app or service and transforms complex admin tasks into simple conversations. With its AI-powered interface, you can perform admin tasks with the ease of a magical spell. 🪄

✨ Core Features

  • 🔹 Function Registration Interface: Declaratively expose your backend functions
  • 🔹 Workflow Execution Runtime: Run complex workflows with simple commands
  • 🔹 UI Metadata Hooks: Auto-generate beautiful interfaces
  • 🔹 SashiHub Integration: Connect with the external SashiHub API
  • 🔹 AI-Powered Chat: Execute admin tasks with natural language
  • 🔹 Secure & Reliable: Built-in support for sensitive function confirmation

🧩 Core Responsibilities

1. Function Registration

  • Provides a registerFunction() API to declare named functions, their parameters, and return types
  • Supports:
    • Zod-based parameter schemas
    • Sync and async functions
    • Visualization functions (with metadata)
    • Repository-scoped functions

2. Function Metadata

Functions are registered with:

  • Name/ID
  • Description (used for AI prompt/context)
  • Input parameter schema (Zod)
  • Return value type (for UI rendering)
  • Optional visibility/config flags (e.g., hidden, inactive)
  • Automatically generates metadata used by the AI layer and/or workflow editor

3. Workflow Execution

  • Accepts a serialized workflow object (steps + parameters) and executes them in sequence
  • Handles:
    • Parameter chaining
    • Type conversion
    • Error catching and reporting
    • Array mapping (* style execution)
    • Optionally runs in debug mode for step-by-step inspection

4. UI Metadata & Type Hints

  • Includes utility to infer UI types from data (e.g., table, badge, graph)
  • Used by the LLM and front-end UI generator to create input/output forms

5. Communication with SashiHub (sashihub)

  • Sends workflow save/load requests to sashihub via authenticated API calls
  • Relies on the developer to provide an x-api-token
  • Supports repository metadata sync via forward-call or metadata endpoints

🔒 Assumptions and Boundaries

  • sashilib is frontend-safe if used in limited exposure contexts
  • It does not persist workflows itself — all workflow state lives in sashihub
  • It does not handle user auth or rate limiting — this is up to the surrounding app or sashihub

🛠️ Use Cases

  • Register custom backend logic to be used in workflows
  • Create a shared interface for internal tools or ops automation
  • Power AI-driven workflows with securely validated parameters
  • Chain local and remote function calls in one workflow

📦 Installation

npm install @usesashi/sashi-lib

🔧 Basic Usage

import { createMiddleware, AIFunction } from "@usesashi/sashi-lib"

// Create a function
const getUsers = new AIFunction("get_users", "Get all users")
    .args()
    .returns({
        name: "users",
        type: "array",
        description: "Array of user objects",
    })
    .implement(async () => {
        return [
            { email: "user1@example.com", name: "User 1" },
            { email: "user2@example.com", name: "User 2" },
        ]
    })

// Create middleware
const router = createMiddleware({
    openAIKey: process.env.OPENAI_API_KEY,
    sashiServerUrl: "https://your-server.com",
    apiSecretKey: "your-secret-key",
})

// Use in Express app
app.use(router)

🏷️ Advanced Examples

Basic Example

import {
    AIArray,
    AIFunction,
    AIObject,
    registerFunctionIntoAI,
} from "@sashimo/lib"

const UserObject = new AIObject("User", "a user in the system", true).field({
    name: "email",
    description: "the email of the user",
    type: "string",
    required: true,
})

const GetUserByIdFunction = new AIFunction("get_user_by_id", "get a user by id")
    .args({
        name: "userId",
        description: "a user's id",
        type: "number",
        required: true,
    })
    .returns(UserObject)
    .implement(async (userId: number) => {
        const user = await getUserById(userId)
        return user
    })

registerFunctionIntoAI("get_user_by_id", GetUserByIdFunction)

Advanced Example: Handling Multiple Objects

const ProductObject = new AIObject(
    "Product",
    "a product in the inventory",
    true
)
    .field({
        name: "productId",
        description: "the unique identifier for a product",
        type: "number",
        required: true,
    })
    .field({
        name: "productName",
        description: "the name of the product",
        type: "string",
        required: true,
    })

const GetProductsFunction = new AIFunction(
    "get_products",
    "retrieve a list of products"
)
    .returns(new AIArray(ProductObject))
    .implement(async () => {
        const products = await getAllProducts()
        return products
    })

registerFunctionIntoAI("get_products", GetProductsFunction)

Example: Using Enums

import { AIFieldEnum, AIFunction, registerFunctionIntoAI } from "@sashimo/lib"

// Create a function that changes a user's role using an enum
const ChangeUserRoleFunction = new AIFunction(
    "change_user_type",
    "change a user type"
)
    .args(
        {
            name: "userId",
            description: "a users id",
            type: "string",
            required: true,
        },
        new AIFieldEnum(
            "type",
            "the type to change the user to",
            ["CASE_MANAGER", "COMMUNITY_ENGAGEMENT"],
            true
        )
    )
    .returns({
        name: "userid",
        description: "the user id",
        type: "string",
    })
    .implement(async (userId: string, role: string) => {
        // Implementation to change the user's role
        console.log("Changing role for user", userId, "to", role)
        return userId
    })

registerFunctionIntoAI("change_user_type", ChangeUserRoleFunction)

This example shows how to:

  • Use AIFieldEnum to create a dropdown selector in the UI
  • Define allowed values for the enum parameter
  • Handle enum validation automatically
  • Provide clear descriptions for the UI and AI

🛡️ Security

Protect your magical realm with robust security:

import { Request, Response, NextFunction } from "express"
import { createMiddleware } from "@sashimo/lib"

const verifySessionMiddleware = async (
    req: Request,
    res: Response,
    next: NextFunction
) => {
    const sessionToken = req.headers["x-sashi-session-token"]

    if (!sessionToken) {
        return res.status(401).send("Unauthorized")
    }

    if (sessionToken !== "userone-session-token") {
        return res.status(401).send("Unauthorized")
    }

    next()
}

app.use(
    "/sashi",
    verifySessionMiddleware,
    createMiddleware({
        openAIKey: process.env.OPENAI_API_KEY || "",
        getSession: async (req, res) => {
            return "userone-session-token"
        },
    })
)

🔍 API Reference

Middleware Options

interface MiddlewareOptions {
    openAIKey: string
    sashiServerUrl?: string // where the sashi server is hosted if you can't find it automatically
    apiSecretKey?: string // used to validate requests from and to the hub
    addStdLib?: boolean // add the standard library to the hub
    langFuseInfo?: {
        publicKey: string
        secretKey: string
        baseUrl: string
    }
    getSession?: (req: Request, res: Response) => Promise<string> // function to get the session id for a request
}

📚 Documentation

For more spells and incantations, visit our Sashi documentation.

🤝 Join the Sashi Fellowship

Are you ready to make admin tasks a breeze? Join us on this magical journey! Check out our Contributing Guide.

⚖️ License

Sashi is released under the MIT License.

🔄 Workflow System

This update introduces a powerful workflow system that enables users to create automated sequences of your registered functions.

📊 How Workflows Work

Once you register your functions with Sashi, they automatically become available for use in workflows. Users can then:

  1. Create sequences of actions using your registered functions
  2. Pass data between steps - Output from one function becomes input to another
  3. Save and reuse workflows for common tasks
  4. Execute workflows with a single click instead of multiple manual steps
graph TD
    A[Register Functions] --> B[Functions Available in Workflow System]
    B --> C[Users Create Workflows]
    C --> D[Workflows Executed When Needed]
    D --> E[Results Displayed to User]

    A1[Developer] --> A
    C1[End User] --> C

    style A fill:#a4c2f4
    style B fill:#b6d7a8
    style C fill:#f9d77e
    style D fill:#d5a6bd
    style E fill:#ea9999
    style A1,C1 fill:#d9d9d9

🔗 Function Integration in Workflows

Your registered functions become building blocks that users can connect together:

graph LR
    A[Function: Get Users] --> B[Function: Filter Active Users]
    B --> C[Function: Send Notification]

    A1[Output: User List] --> B1[Input: Users]
    B2[Output: Filtered Users] --> C1[Input: Recipients]

    style A,B,C fill:#a4c2f4
    style A1,B1,B2,C1 fill:#d5a6bd

🌐 Data Flow Between Systems

The workflow system handles all the data flow between your registered functions and external systems without you needing to implement any additional code:

sequenceDiagram
    participant Dev as Developer
    participant Sashi as Sashi System
    participant User as User
    participant Ext as External Services

    Dev->>Sashi: Register functions
    User->>Sashi: Create workflows using functions
    User->>Sashi: Execute workflow
    Sashi->>Ext: Call external APIs if needed
    Ext-->>Sashi: Return results
    Sashi->>Sashi: Process data between steps
    Sashi-->>User: Display final results

📝 What You Need To Do

As a developer, you only need to:

  1. Register your functions using the AIFunction system (as shown in previous examples)
  2. Ensure proper input/output typing so the workflow system knows what data can be passed between steps
  3. Document your functions well so users understand what each function does

The workflow storage, execution, and visualization are all handled automatically by the Sashi system.

For more information on how users can use the workflows you enable, direct them to our Workflow Documentation.


5.6.0

5 months ago

5.5.0

5 months ago

5.4.0

5 months ago

5.3.0

6 months ago

5.2.0

6 months ago

5.1.0

6 months ago

5.0.0

6 months ago

6.1.0

5 months ago

6.0.0

5 months ago

6.2.0

5 months ago

3.9.0

11 months ago

3.11.0

11 months ago

3.8.0

11 months ago

3.10.0

11 months ago

3.7.0

11 months ago

3.6.0

11 months ago

3.12.0

11 months ago

4.0.0

6 months ago

3.5.0

12 months ago

3.4.0

1 year ago

3.3.0

1 year ago

3.2.0

1 year ago

3.1.0

1 year ago

2.17.0

1 year ago

3.0.0

1 year ago

2.15.0

1 year ago

2.16.0

1 year ago

2.14.0

1 year ago

2.13.0

1 year ago

2.11.0

1 year ago

2.3.0

1 year ago

2.12.0

1 year ago

2.2.0

1 year ago

2.5.0

1 year ago

2.10.0

1 year ago

2.4.0

1 year ago

2.7.0

1 year ago

2.6.0

1 year ago

2.9.0

1 year ago

2.8.0

1 year ago

2.1.0

1 year ago

2.0.0

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago