npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@agent-ils/workflow-sdk

v0.0.4

Published

Framework-agnostic workflow infrastructure for AgentILS

Readme

AgentILS Workflow SDK

@agent-ils/workflow-sdk 是一个框架无关的工作流执行引擎。将多步骤工作流定义为节点数组,运行时通过 context 传递和 patch 更新状态,并可选用 React hooks 或 Vue 3 composables 接入响应式 UI。

提供可视化编辑器、持久化存储或服务端运行时——它是一个轻量级的客户端编排层。

安装

pnpm add @agent-ils/workflow-sdk

场景:鉴权后查看敏感数据

用户点击「查看敏感数据」→ 弹出验证码表单 → 验证码正确则拉取并展示数据,验证码错误则工作流立即中断——数据拉取不会执行。

init → verify → fetch-data → complete
                ↑
                └── 验证码错误 → stop(fetch-data 不会执行)

定义工作流

// workflow.ts
import { defineNode, defineWorkflow } from '@agent-ils/workflow-sdk/core'

export interface AuthContext {
    requestId: string
    code: string
    secretData: string
    fetchedAt: number
    completed: boolean
}

export const authWorkflow = defineWorkflow<AuthContext>({
    id: 'auth-view-secret',
    nodes: [
        defineNode({
            id: 'init',
            run: async () => ({
                type: 'continue',
                patch: { requestId: `req_${Date.now()}` },
            }),
        }),
        // 关键:验证码错误时返回 stop,后续节点不会执行
        defineNode({
            id: 'verify',
            run: async (ctx) => {
                if (ctx.code !== '123456') {
                    return { type: 'stop', reason: `验证码错误:${ctx.code}` }
                }
                return { type: 'continue' }
            },
        }),
        defineNode({
            id: 'fetch-data',
            run: async () => ({
                type: 'continue',
                patch: { secretData: '机密内容...', fetchedAt: Date.now() },
            }),
        }),
        defineNode({
            id: 'complete',
            run: async () => ({ type: 'continue', patch: { completed: true } }),
        }),
    ],
})

React + Antd

pnpm add @agent-ils/workflow-sdk react antd
import { useWorkflow } from '@agent-ils/workflow-sdk/react'
import { Steps, Button, Alert } from 'antd'
import { authWorkflow, type AuthContext } from './workflow'
import { VerifyForm } from './VerifyForm'
import { DataViewer } from './DataViewer'

function App() {
    const { status, start } = useWorkflow({ definition: authWorkflow })

    const handleVerify = async (code: string) => {
        const res = await start({
            requestId: '',
            code,
            secretData: '',
            fetchedAt: 0,
            completed: false,
        })
        if (res.status === 'stopped') {
            // 验证失败 — fetch-data 从未执行
            message.error(res.reason)
        }
    }

    return (
        <>
            <Steps
                current={status === 'done' ? 3 : status === 'stopped' ? 1 : 0}
                status={status === 'stopped' ? 'error' : 'process'}
            >
                <Step title="初始化" />
                <Step title="身份验证" />
                <Step title="获取数据" />
                <Step title="完成" />
            </Steps>
            {status === 'idle' && <VerifyForm onSubmit={handleVerify} />}
            {status === 'stopped' && <Alert type="error" description="验证失败" />}
            {status === 'done' && <DataViewer />}
        </>
    )
}

完整可运行项目:examples/react-antd/

Vue 3 + Element Plus

pnpm add @agent-ils/workflow-sdk vue element-plus
<script setup lang="ts">
import { useWorkflow } from '@agent-ils/workflow-sdk/vue'
import { authWorkflow, type AuthContext } from './workflow'

const { status, start, abort } = useWorkflow({ definition: authWorkflow })

async function handleVerify(code: string) {
    const res = await start({
        requestId: '',
        code,
        secretData: '',
        fetchedAt: 0,
        completed: false,
    })
    if (res.status === 'stopped') {
        ElMessage.error(res.reason)
    }
}
</script>

<template>
    <el-steps :active="status === 'done' ? 3 : status === 'stopped' ? 1 : 0">
        <el-step title="初始化" /><el-step title="身份验证" /> <el-step title="获取数据" /><el-step title="完成" />
    </el-steps>
    <VerifyForm v-if="status === 'idle'" @submit="handleVerify" />
    <el-alert v-if="status === 'stopped'" type="error" description="验证失败" />
    <DataViewer v-if="status === 'done'" />
</template>

完整可运行项目:examples/vue-element-plus/

中断工作流

有三种方式阻止后续节点执行:

1. stop 信号 — 受控中断

在节点的 run 中返回 { type: 'stop', reason: '...' }。工作流立即中断,patch 仍然会被应用,result.status === 'stopped'

defineNode({
    id: 'gate',
    run: async (ctx) => {
        if (!ctx.authorized) return { type: 'stop', reason: '未授权' }
        return { type: 'continue' }
    },
})

2. 抛出异常 — 意外失败

run 内部 throw。工作流捕获异常,设置 result.status === 'failed',错误存储在 result.error

defineNode({
    id: 'api-call',
    run: async (ctx) => {
        const res = await fetch(ctx.url)
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        return { type: 'continue', patch: { data: await res.json() } }
    },
})

3. AbortSignal — 外部取消

通过 run({ signal }) 传入 AbortSignal。引擎在节点之间检查是否已取消。

const ac = new AbortController()
setTimeout(() => ac.abort(), 5000)
const result = await workflow.run({ initialContext: {}, signal: ac.signal })

API

核心

| 导出 | 类型 | 说明 | | ------------------------- | ---- | ----------------------------------- | | defineNode(opts) | 函数 | 创建带类型节点的辅助函数 | | defineWorkflow(def) | 函数 | 创建带类型工作流定义的辅助函数 | | createWorkflow(def) | 函数 | 返回 { definition, run(options) } | | applyPatch(ctx, patch?) | 函数 | 浅合并 partial patch 到 context |

节点 run 返回值 — WorkflowSignal

| 类型 | 字段 | 效果 | | ---------- | --------------------------- | ------------------------ | | continue | patch?: Partial<TContext> | 合并 patch,进入下个节点 | | stop | reason: string, patch? | 合并 patch,停止工作流 |

run() 参数

| 选项 | 类型 | 说明 | | ---------------- | --------------------- | -------------------------------- | | initialContext | TContext | 必填,传给第一个节点的初始上下文 | | hook? | { before?, after? } | 每个节点执行前后的生命周期回调 | | signal? | AbortSignal | 节点间合作式取消 |

run() 返回值 — WorkflowRunResult

| 字段 | 类型 | 说明 | | --------- | --------------------------------- | -------------------------------- | | status | 'done' \| 'stopped' \| 'failed' | 终态 | | context | TContext | 最终上下文(含最后一次 patch) | | reason? | string | 当 status === 'stopped' 时存在 | | error? | unknown | 当 status === 'failed' 时存在 |

不做的事

  • 不提供可视化工作流编辑器或 DAG UI。
  • 不提供内置持久化、回放或时间旅行调试。
  • 不提供服务端编排、队列或分布式执行。
  • 不校验节点间的输入/输出 schema——类型安全由 TypeScript 编译期保证。