Skip to main content

openJiuwen Plugin CLI utilities

Project description

openjiuwen-plugin(插件命令行工具)

面向 openJiuwen 插件市场的命令行工具:在本地生成与校验插件工程、打包上传、检索与安装。PyPI 发行名将使用 openjiuwen-plugin(安装后入口命令同名);Python 包目录名为 openjiuwen_plugin

分发说明:CLI 尚未发布到 PyPI。请从本仓库 cli/ 目录以可编辑方式安装(见下文)。后续发布 PyPI 后,可直接 pip install openjiuwen-plugin 使用。


1. 环境要求

项目 说明
Python ≥ 3.11.4(与 pyproject.tomlrequires-python 一致)
操作系统 Windows / Linux / macOS 均可
对接市场 可选。使用市场相关子命令时需已知市场根 URL(见第 5 节;参数见第 6 节)

2. 安装

在克隆后的仓库中进入 cli 目录执行:

cd cli
pip install -e .
  • -e(可编辑):修改源码后立即生效,适合开发与联调。
  • 安装成功后,终端中应可使用命令 openjiuwen-plugin。建议执行 openjiuwen-plugin -h 确认子命令列表。

若安装成功但提示 openjiuwen-plugin 不是内部或外部命令(常见于 Windows 用户级安装路径未加入 PATH),可使用模块方式调用(效果相同):

cd cli
python -m openjiuwen_plugin.main --help

3. 快速上手(不依赖市场)

以下命令仅需本地文件系统,无需访问市场服务。

# 1)生成 tools 类型脚手架(默认)
openjiuwen-plugin init demo-weather --path .

# 其他类型示例
openjiuwen-plugin init demo-mcp --path . --type mcp-stdio
openjiuwen-plugin init demo-api --path . --type restful-api
openjiuwen-plugin init my-skill --path . --type skill

# 2)校验插件目录
openjiuwen-plugin validate ./demo-weather

# 3)打包(默认输出到插件目录下的 out/)
openjiuwen-plugin pack ./demo-weather
# 或指定输出目录
openjiuwen-plugin pack ./demo-weather -o ./dist-zips

说明:

  • tools 类型打包前会执行 pip wheel,请保证当前环境可访问 PyPI 或已配置 wheel 构建所需依赖。
  • skill 类型默认不生成根目录 README.md;若自行添加,pack 会将其一并打入 zip。

4. 环境变量

仅指当前进程可见的环境变量(os.environ;不含仓库内 .env 自动加载)。CLI 读取任意路径下的 .env;与 Compose / 市场仓库里的 .env 无自动联动。若用 .env 启了市场,运行 CLI 的终端仍需自行 export / $env: 下表变量(或写入用户级环境变量)。

变量 作用
OPENJIUWEN_MARKET_URL 市场服务根地址(不含 /api/v1/...),例如 http://127.0.0.1:8100
OPENJIUWEN_USER_TOKEN 用户 Bearer Token;用于 publish / delete(与 --token 二选一优先级:命令行优先)
OPENJIUWEN_SYSTEM_TOKEN 系统管理员 Token(请求头 X-System-Token);与 --system-token 同理
LOG_LEVEL 根日志级别,默认 INFO

安全提示:勿将 Token 写入仓库。searchinfoinstall(下载 zip)对市场侧为公开接口,CLI 不会附带用户鉴权头。

配置示例(当前 PowerShell 会话)

$env:OPENJIUWEN_MARKET_URL = "http://127.0.0.1:8100"
$env:OPENJIUWEN_USER_TOKEN = "<你的 Token>"

配置示例(Linux / macOS)

export OPENJIUWEN_MARKET_URL=http://127.0.0.1:8100
export OPENJIUWEN_USER_TOKEN="<你的 Token>"

5. 对接市场服务(简要)

OPENJIUWEN_MARKET_URL 设为插件市场根地址(不含 /api/v1/...);或在各子命令上使用 --market-url命令行优先于环境变量)。未设置且命令也未带 --market-url 时,依赖市场的子命令会报错退出。

版本号约定plugin.yaml 中的 version--plugin-version 均须为 x.y.z 三位非负整数段(如 1.0.0),不支持 1.0.0-rc1 等预发布后缀。允许前缀 v/V,规范化后上传。

帮助openjiuwen-plugin -h 列出子命令;openjiuwen-plugin <子命令> -h 与下表一致,以程序输出为准。

各子命令的全部参数见第 6 节。


6. 子命令与参数

子命令 简述
init 生成插件脚手架
validate 校验插件目录
pack 单个插件目录打成 zip
publish 上传单个插件(zip 或先 pack 再传)
info 查询插件版本详情
search 列表 / 搜索
delete 删除版本或整包
install 下载 zip 并安装到本地
skill-import 系统管理员:批量导入技能集合包.zip 或符合布局的目录

6.1 init — 生成脚手架

参数 必填 说明
name 插件名,如 weather-plugin(须满足 ^[a-z][a-z0-9-]*$skill 另有 Agent Skills 风格限制)
--path 在哪个父目录下创建 name/ 子目录,默认当前目录 .
--type tools(默认)| mcp-stdio | restful-api | skill
--force 目标 name 目录已存在且非空时仍覆盖初始化

6.2 validate — 校验插件目录

参数 必填 说明
path 插件根目录(内含 plugin.yaml 等)
  • tools 类型下 validate 默认要求根目录 pyproject.tomlsrc/schemas/tools.json 等,并在存在 src/.../plugin.py 时校验其与 schemas/tools.json 中工具名一致。

  • mcp-stdio / restful-api / skill 不把根目录 pyproject.toml 作为通过结构校验的硬性条件。

6.3 pack — 打包为 zip

参数 必填 说明
path 插件根目录
-o / --output zip 输出目录,默认 out。若为相对路径,则相对于插件根目录 path 解析;绝对路径则直接使用

打包前会先执行与 validate 相同的校验。tools 会执行 pip wheel(需网络或本地构建环境),产物 zip 不写 src/,只带 dist/*.whl 与上述元数据文件。

6.4 publish — 上传市场

参数 必填 说明
path 条件 插件根目录;--file 二选一:未使用 --file必填(先 pack 再上传)
-f / --file 条件 已有 zip 路径;指定则跳过 pack,直接上传该文件
--token 条件 普通用户:Authorization: Bearer …。与 --system-token 互斥;可省略并从 OPENJIUWEN_USER_TOKEN 读取(命令行优先)
--system-token 条件 系统管理员:X-System-Token。与 --token 互斥;可省略并从 OPENJIUWEN_SYSTEM_TOKEN 读取
--market-url 条件 市场根 URL;未设则用 OPENJIUWEN_MARKET_URL
--plugin-id 条件 首发勿传(由市场分配);同一插件再次发版必须传(与包内 name 对应的那条资产的 plugin_id
--plugin-version 覆盖版本号(x.y.z,可选 v 前缀)
--version-desc 本版本的 release notes(语义上);市场侧落库/展示为该版本的 changelog 字段(与 plugin.yamldescription、插件卡片/详情里的插件总描述不是同一字段)
--force 允许覆盖市场侧已存在的同版本(以服务端策略为准)

publishdelete 的用户或系统鉴权须通过 --tokenOPENJIUWEN_USER_TOKEN(或 --system-token / OPENJIUWEN_SYSTEM_TOKEN);未提供则报错退出。

日志LOG_LEVELINFO 时,开始上传 multipart 前会打印「正在上传插件包,请稍候…」;大包耗时可更长。

6.5 info — 查询版本详情

不携带用户鉴权;需市场 URL。

参数 必填 说明
asset_id 资产 ID(与发布返回的 plugin_id 一致)
-v / --version 目标版本,如 1.0.0
--market-url 条件 市场根 URL;未设则用环境变量

6.6 search — 列表 / 搜索

不携带 Authorization。

参数 必填 说明
query 搜索关键词;可省略,表示空关键词
--market-url 条件 市场根 URL
--type plugin_type 精确匹配:tools / mcp-stdio / restful-api / skill
--author 发布者展示名(模糊)
--asset-id 资产 ID
--asset-type 资产类型(精确匹配;当前列表以 plugin 为主,其它取值以后端为准,如后续扩展 workflow 等)
--publisher-id 发布者 ID
--page 页码,默认 1
--page-size 每页条数,默认 20,最大 100
--order-by install_count(默认)| like_count | create_time | update_time | review_count
--desc 是否降序:true / false / yes / no 等,默认 true

6.7 delete — 删除版本或整包

参数 必填 说明
plugin_id 资产 ID
--market-url 条件 市场根 URL
--token 条件 普通用户 Bearer;与 --system-token 互斥;可配合 OPENJIUWEN_USER_TOKEN(命令行优先)
--system-token 条件 系统管理员 X-System-Token;与 --token 互斥;可配合 OPENJIUWEN_SYSTEM_TOKEN
--version 要删的版本号;省略则删除全部版本(与 CLI --help 描述一致;服务端行为以市场 API 为准)

6.8 install — 下载并安装

不携带用户鉴权。具体行为取决于制品 zip 内 plugin.yamlruntime.type,详见下表之后说明。

参数 必填 说明
asset_id 市场 asset_id
--market-url 条件 市场根 URL
--version / -v 语义化版本(如 1.0.0);传给 GET /api/v1/artifacts/{asset_id}?version=省略则由服务端决定(一般为最新版)
-o / --output 插件包父目录(默认当前工作目录)
--force 目标目录已存在时允许覆盖

说明

  • 父目录-o 指向的目录;省略则为当前工作目录。

  • 包目录<父目录>/<zip 顶层目录>/(即内含 plugin.yaml 的那一层;tools / mcp-stdio / restful-api 同此约定)。

  • tools:解压后按 dist/*.whl 用当前解释器执行 pip install;wheel 一般仍留在包内 dist/-o 只影响包目录的父路径;建议 venv;系统 Python 易权限失败。

  • mcp-stdio / restful-api:只解压到包目录,pip;依赖在包目录内自行 pip install .;不自动起服务。

  • skill:解压到 <父目录>/<name>/pipname 须与目录、plugin.yamlSKILL.md frontmatter 一致。

6.9 skill-import — 管理员批量导入技能集合包

调用市场 POST /api/v1/plugins/skill-import系统管理员(X-System-Token),不支持普通用户 Bearer。用于一次上传内含多个顶层 skill 目录的集合包(与单条 publish 上架的 skill zip 不是同一格式)。

参数 必填 说明
BUNDLE 集合包 .zip 路径,或本地目录(布局须与 zip 解压后一致:多个顶层 skill 子目录 + 可选根级 manifest.json)。为目录时 CLI 先在临时目录内打成 zip 再上传
--market-url 条件 市场根 URL;未设则用 OPENJIUWEN_MARKET_URL
--system-token 条件 X-System-Token;未设则用 OPENJIUWEN_SYSTEM_TOKEN必填其一
--force 与表单 force 一致;可与 manifest.json 条目的 force 逻辑或
--fail-fast 首条条目失败即停止处理后续目录(默认部分成功)

退出码:任一条目失败(summary.failed > 0)、路径无效、本地打包失败、或 zip 超过 512MB 预检时,进程以非 0 退出。HTTP 200 仍可能带项内失败,请看日志中的 summary / 各 entry 状态。

日志LOG_LEVELINFO 时,开始上传前会打印「正在上传 skills 包,请稍候…」;大包耗时可更长。

export OPENJIUWEN_MARKET_URL=http://127.0.0.1:8100
export OPENJIUWEN_SYSTEM_TOKEN="<系统管理员 Token>"

openjiuwen-plugin skill-import ./my-skills-bundle-dir
openjiuwen-plugin skill-import ./bundle.zip --fail-fast

6.10 市场相关命令示例

BASE=http://127.0.0.1:8100   # 占位;或已 export OPENJIUWEN_MARKET_URL

openjiuwen-plugin publish ./demo-weather --token <TOKEN> --market-url $BASE
openjiuwen-plugin publish -f ./out/demo-weather-0.0.1.zip --token <TOKEN> --market-url $BASE
openjiuwen-plugin info <asset_id> -v 1.0.0 --market-url $BASE
openjiuwen-plugin search weather --type tools --page-size 20 --order-by create_time --market-url $BASE
openjiuwen-plugin install <asset_id> --market-url $BASE
openjiuwen-plugin install <asset_id> -v 1.0.0 --market-url $BASE
openjiuwen-plugin install <asset_id> -o ./plugins --market-url $BASE
openjiuwen-plugin delete <asset_id> --version all --token <TOKEN> --market-url $BASE

(Windows PowerShell 可将 $BASE 换为变量或字面 URL。)


7. 代码结构(维护与二次开发)

可安装包位于 cli/openjiuwen_plugin/

模块 职责
main.py 入口:日志初始化、解析参数、分发子命令
parsers.py 各子命令 argparse 定义
handlers.py 子命令业务编排、日志输出、进程退出码
plugin.py init / validate / pack / publish / install 落盘与 pip 等
market.py 对市场 HTTP API 的调用与响应解析
schemas/ 与市场对齐的请求/响应模型(Pydantic)
logging_config.py 控制台日志与敏感信息脱敏

HTTP 与重试publish(上传)与 delete单次请求、不自动重试,避免非幂等写操作在「服务端已成功、客户端未收到响应」时重复提交。searchinfo、制品元数据与 zip 下载等只读调用在 market.py 内对网络错误及部分可恢复状态码做有限次数退避重试(细节见源码)。

约定:market.py 只负责 HTTP 与契约对象;handlers.py 负责面向用户的日志与返回码;扩展接口时优先改 schemas,再改 markethandlers


8. 脚手架类型与目录结构

init --type 支持 tools(默认)、mcp-stdiorestful-apiskill。下图为各类型生成后的典型布局(包目录名由插件名将 - 换为 _ 得到,如 demo-mcpdemo_mcp)。

tools

plugin-name/
  plugin.yaml
  README.md
  icon.png
  pyproject.toml
  schemas/tools.json
  src/plugin_name/
    __init__.py
    plugin.py

mcp-stdio

demo-mcp/
  plugin.yaml
  README.md
  icon.png
  pyproject.toml
  schemas/tools.json
  src/demo_mcp/
    __init__.py
    mcp_server.py

mcp_server.py 为 FastMCP 模板;依赖见生成的 pyproject.toml

restful-api

demo-api/
  plugin.yaml
  README.md
  icon.png
  pyproject.toml
  schemas/tools.json
  src/demo_api/
    __init__.py
    rest_api.py

rest_api.py可选占位(便于本地写客户端或示例);服务已独立部署时,宿主一般只需 plugin.yaml 中的 api.base_urlschemas/tools.json 即可知道如何调用,可不依赖 rest_api.py
建议schemas/tools.json 中维护完整的 REST tool contract;当前 validate 会对 restful-api 校验该文件,包括 tools[]namedescriptionpathmethodinput_schemaoutput_schematools[].headers 与请求映射元数据。

skill

my-skill/
  plugin.yaml
  icon.png
  my-skill/
    SKILL.md
    scripts/
    references/
    assets/

关于 schemas/tools.json

toolsmcp-stdiorestful-api 脚手架都会生成 schemas/tools.json(模板内容)。validate 会在不同 runtime.type 下按不同规则校验该文件

  • tools:校验结构,以及与 src/.../plugin.py@tool(name=...) 名称一致
  • restful-api:校验 REST tool contract,包括 path / method / input_schema / output_schematools[].headers 及请求映射元数据
  • mcp-stdio:当前不对该文件做额外强校验

9. plugin.yaml 与校验摘要(MVP)

字段 / 规则 说明
name 正则 ^[a-z][a-z0-9-]*$
version 与市场约定一致: x.y.z 三位数字段(如 1.0.0),无预发布/构建后缀
display_namedescription 非空字符串
runtime.type tools | mcp-stdio | restful-api | skill
metadata.authormetadata.tags 必填;tags 为非空字符串数组
compatibility.python 非 skill 必填;PEP 440 版本说明符(如 >=3.11, <3.14);skill 不要求
tools 类型 tools_schema 路径须为 schemas/tools.json 且文件存在
mcp-stdio mcp.transportstdiomcp.command 为非空字符串数组
restful-api 须含非空 api.base_url(见下节 api 标准字段
skill 恰好一个非隐藏子目录含 SKILL.md;frontmatter name/description 等规则与 Agent Skills 一致

restful-apiapi 标准字段与运行方式

契约重心(已部署的 HTTP 服务)api.base_url + schemas/tools.json。前者给出服务根地址,后者用 tools[] 描述每个可调能力(名称、说明、input_schema / output_schema 等),宿主即可编排请求路径、方法与参数,不必使用 rest_api.py

api 对象约定(当前 CLI validate 强制校验 base_url;其余字段为推荐扩展,宿主可自行约定解析方式):

字段 必填 说明
base_url 服务根 URL(不含具体 path 时可只写到版本前缀,与 tools.json 内约定一致即可)
openapi_url OpenAPI 文档地址(JSON/YAML);与 tools.json 可二选一或并存,由宿主决定优先级
auth 鉴权说明,建议为对象,例如:type: none | bearer | api_keyapi_key 时可含 headerinheader / query)等
default_headers 默认 HTTP 头(如 Accept: application/json),map 结构
timeout_seconds 建议超时秒数(数字),供宿主参考

rest_api.py:脚手架中的占位文件,可保留;需要本地封装调用逻辑时再实现,不是「仅远程服务」场景的必需项。

schemas/tools.json(校验范围)

runtime.typetools 时:tools 数组非空;每项含 namedescriptioninput_schemaoutput_schema,且 schema 根类型为 objectsrc/.../plugin.py@tool(name="...") 与 JSON 中工具名须一一对应。

runtime.typerestful-api 时:tools 数组也必须非空;每项必须包含合法的 name、非空 description、非空 path、受支持的 HTTP method,以及 canonical 的 input_schema / output_schema;其中 input_schema 根类型必须为 object,参数发送位置通过 input_schema.properties.<field>.send_method 指定为 None / Header / Query / Body / Path。CLI 还会校验 tools[].headers 的基础结构:字段必须为数组,元素必须为对象,且 name 为非空字符串、value 为字符串。插件级默认请求头可通过 plugin.yaml -> api.default_headers 提供,工具级静态请求头可通过 tools[].headers 提供。

runtime.typemcp-stdio 时:当前不对该文件做额外强校验。


10. 开发与测试

cli 目录下:

pip install -e .
pip install pytest
python -m pytest -q

未做可编辑安装时,可临时设置 PYTHONPATH

cd cli
$env:PYTHONPATH = "."
python -m pytest -q

11. 常见问题

Q:openjiuwen-plugin 命令找不到?
A:使用 python -m openjiuwen_plugin.main,或检查 Python 的 Scripts 目录是否已加入 PATH。

Q:提示连不上市场?
A:确认 OPENJIUWEN_MARKET_URL根地址(不要带 /api/v1),且该 URL 在本机或网络内可访问。

Q:发布失败提示版本格式错误?
A:使用 x.y.z 三位数字版本;不要使用 1.0.0-rc1 等形式。

Q:路径含空格报错?
A:在 shell 中为路径加引号,例如 openjiuwen-plugin validate "D:\My Plugins\demo"

Q:只执行 openjiuwen-plugin 不带子命令会怎样?
A:会打印总帮助并退出(退出码非 0);查看子命令请用 openjiuwen-plugin -hopenjiuwen-plugin <子命令> -h

Q:search 里关键词含 *#( 等异常?
A:多数由 Shell 先解释 导致:* 会展开为文件名、# 起注释、( 在 bash 中有语法含义。请对关键词加引号,例如 openjiuwen-plugin search '*'openjiuwen-plugin search '#'(PowerShell 同理用引号包裹)。

Q:publish 失败时打印一大段 JSON?
A:已改为尽量解析服务端 message 并输出单行可读文案(如 Invalid X-System-Token、版本冲突说明等)。若仍为长文本,请直接查看市场接口返回或本地复现请求排查。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openjiuwen_plugin-0.0.1b1-py3-none-any.whl (38.3 kB view details)

Uploaded Python 3

File details

Details for the file openjiuwen_plugin-0.0.1b1-py3-none-any.whl.

File metadata

File hashes

Hashes for openjiuwen_plugin-0.0.1b1-py3-none-any.whl
Algorithm Hash digest
SHA256 07615d18ccfb4f26c9e74678ee688369fb4992fcf689e0fd8db13a4287edf8e9
MD5 250e5928b01d20c4bdc7fe6410d0170d
BLAKE2b-256 91abc5c5394e30809f08f18d666c7d1968d0774216c9a7cc7b1fc60df6e3fadc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page