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

@gencode/plugin-sdk

v0.1.0

Published

`@gencode/plugin-sdk` 提供插件作者需要的稳定类型导出,避免直接依赖 `@gencode/agents` 的内部文件路径。

Readme

@gencode/plugin-sdk

@gencode/plugin-sdk 提供插件作者需要的稳定类型导出,避免直接依赖 @gencode/agents 的内部文件路径。

最小插件结构

my-plugin/
├── aimax.plugin.json
└── index.ts

aimax.plugin.json:

{
  "id": "progress-demo",
  "name": "Progress Demo",
  "description": "Demonstrates custom plugin progress events.",
  "version": "0.0.1",
  "configSchema": {}
}

index.ts:

import type { PluginApi } from "@gencode/plugin-sdk";

export default function register(api: PluginApi) {
  const progress = api.createProgressEmitter();

  api.registerHook("session_start", async () => {
    await progress.emit({
      name: "progress_demo.session.started",
      label: "Plugin initialized",
      data: { source: "hook" },
    });
  });
}

createProgressEmitter

插件现在可以通过 api.createProgressEmitter() 主动发出自定义进度事件。

const progress = api.createProgressEmitter();

await progress.emit({
  name: "my_plugin.step.completed",
  label: "Downloaded source data",
  data: {
    step: "download",
    itemCount: 12,
  },
});

事件字段说明:

  • name: 稳定事件名,建议使用 plugin_namespace.actionplugin.namespace.action
  • label: 面向用户的短文案,可直接展示在 Web/H5 时间线
  • data: JSON-safe 结构化扩展字段,供 callback/WebSocket 消费方解析

运行时约束:

  • 只能在插件运行期调用,例如 hook handler 或 plugin tool 的 execute
  • 不能在模块顶层或 register() 执行期间直接调用
  • pluginIdsessionIdmessageIddepth 由框架注入,插件不需要也不能手工传入

事件流向

插件发出的 custom progress event 会复用现有的统一事件链路:

  1. @gencode/agents 产出 AgentProgressEvent { type: "custom", ... }
  2. @gencode/cli 继续通过 stdout / HTTP callback / websocket 分发
  3. @gencode/console 将其映射为 agent.custom

stdout 文本输出示例:

[plugin:progress-demo] progress_demo.task.completed Task completed {"step":"run","count":3}

WebSocket / callback 中的事件载荷核心字段:

{
  "type": "custom",
  "pluginId": "progress-demo",
  "name": "progress_demo.task.completed",
  "label": "Task completed",
  "data": {
    "step": "run",
    "count": 3
  }
}

建议

  • 优先让 name 稳定,便于服务端和前端做事件聚合
  • label 保持短句,适合直接展示
  • data 放结构化上下文,不要塞大段文本
  • 如果一个插件需要多个阶段事件,建议统一前缀,例如:
    • progress_demo.fetch.started
    • progress_demo.fetch.completed
    • progress_demo.report.generated

registerUiTool

插件可以通过 api.registerUiTool() 注册 UI 工具,让 LLM 在需要时暂停 agent 并通过前端表单收集结构化用户输入。

registerTool 不同,插件只需要提供 schema 和基本元数据。inputSchema 用于定义 LLM 调用这个工具时的参数结构,outputSchema 用于定义前端要渲染和回传的表单结构;session 绑定、暂停/恢复流程、结果校验都由框架自动完成。

基本用法

import type { PluginApi } from "@gencode/plugin-sdk";

export default function register(api: PluginApi) {
  api.registerUiTool({
    name: "collect_feedback",
    label: "收集用户反馈",
    description: "Collect structured feedback from the user.",
    outputSchema: {
      type: "object",
      title: "用户反馈",
      properties: {
        rating: { type: "number", title: "评分" },
        comment: { type: "string", title: "评论" },
      },
      required: ["rating"],
    },
    extra: {
      ui: {
        fields: {
          comment: { widget: "textarea" },
        },
      },
    },
  });
}

JSON Schema 约定

outputSchema 遵循 JSON Schema 风格的对象定义,推荐至少提供:

| 字段 | 说明 | |------|------| | type: "object" | UI tool 顶层 schema 必填 | | properties | 表单字段定义 | | required | 必填字段列表 | | description | 表单或字段说明 | | default | 默认值 | | enum | 单选枚举 | | format: "date" | 日期输入 | | items.enum | 多选枚举数组 |

示例:

outputSchema: {
  type: "object",
  title: "报告参数",
  properties: {
    format: {
      type: "string",
      title: "输出格式",
      enum: ["markdown", "pdf", "html"],
    },
    tags: {
      type: "array",
      title: "标签",
      items: {
        type: "string",
        enum: ["tech", "ops", "finance"],
      },
    },
    startDate: {
      type: "string",
      title: "开始日期",
      format: "date",
    },
  },
}

extra 扩展字段

有些场景不适合完全按 JSON Schema 的标准字段渲染。此时可以通过 extra 透传一份 JSON-safe 扩展配置给前端,由接入方自行解释并渲染更高自定义的 UI。

api.registerUiTool({
  name: "custom_summary_form",
  label: "自定义摘要表单",
  description: "Collect values through a custom-rendered panel.",
  outputSchema: {
    type: "object",
    title: "摘要确认",
    properties: {
      approved: { type: "boolean", title: "是否确认" },
      comment: { type: "string", title: "补充说明" },
    },
    required: ["approved"],
  },
  extra: {
    renderer: "summary-card",
    sections: [
      { kind: "markdown", title: "摘要", content: "这里放自定义摘要内容" },
    ],
    ui: {
      fields: {
        comment: { widget: "textarea", placeholder: "可选补充说明" },
      },
    },
  },
});

约束:

  • extra 只负责扩展前端渲染,不参与内置 JSON Schema 校验
  • 用户提交结果仍然统一回传到 values
  • 建议保持 JSON-safe,避免函数、类实例或不可序列化对象

推荐把非标准控件语义放在 extra.ui.fields 中,例如:

  • widget: "textarea"
  • widget: "file"
  • placeholder
  • enumLabels

自定义校验

内置 JSON Schema 校验之外,可以提供 validate 函数做跨字段校验:

api.registerUiTool({
  name: "date_range",
  label: "选择日期范围",
  description: "Collect a date range with cross-field validation.",
  outputSchema: {
    type: "object",
    title: "日期范围",
    properties: {
      startDate: { type: "string", title: "开始日期", format: "date" },
      endDate: { type: "string", title: "结束日期", format: "date" },
    },
    required: ["startDate", "endDate"],
  },
  validate(values) {
    const start = values.startDate as string;
    const end = values.endDate as string;
    if (start && end && start > end) {
      return {
        valid: false,
        errors: [{ field: "endDate", message: "结束日期不能早于开始日期。" }],
      };
    }
    return { valid: true };
  },
});

validate 支持同步和异步返回。内置校验失败时不会调用 validate

registerTool 的区别

| 维度 | registerTool | registerUiTool | |------|---------------|-----------------| | 用途 | 通用工具 | 收集前端表单输入 | | 开发者关注点 | 完整 execute 实现 | 只需提供 inputSchema? + outputSchema + 元数据 | | sessionId | 需要自行处理 | 框架自动绑定 | | 暂停/恢复 | 需要手动抛出信号 | 框架自动处理 | | 结果校验 | 自行实现 | 内置 JSON Schema 校验 + 可选自定义 validator |

运行流程

  1. LLM 调用 UI 工具 → 自动抛出 UiToolPauseSignal 暂停 agent
  2. Runner 捕获信号,发出 ui_tool_request 进度事件(包含 outputSchema
  3. 前端根据 outputSchema 渲染标准表单,或结合 extra 渲染自定义 UI
  4. 用户提交后,CLI 带 uiToolResume 重新调用 agent
  5. 框架自动校验数据(内置 + 自定义 validator)
  6. 校验通过 → 工具返回提交值给 LLM → agent 继续执行

导出类型

@gencode/plugin-sdk 导出以下 UI 工具相关类型:

  • PluginUiToolDescriptorregisterUiTool 的参数类型
  • PluginUiToolOptions — 可选参数(如 optional
  • UiToolInputSchema — LLM 调用参数 schema
  • UiToolOutputSchema / UiToolSchema — 表单 schema
  • UiToolJsonSchemaProperty — 单个字段的 JSON Schema 定义
  • UiToolJsonSchemaType — 支持的 JSON Schema type
  • UiToolExtra — 前端扩展渲染负载
  • UiToolValidationError — 校验错误
  • UiToolValidationResult — 校验结果