create-openclaw-plugin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create.js +249 -0
- package/package.json +13 -0
package/bin/create.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
// ---- 颜色 ----
|
|
7
|
+
const green = (s) => `\x1b[32m${s}\x1b[0m`;
|
|
8
|
+
const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
|
|
9
|
+
const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
|
|
10
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
11
|
+
|
|
12
|
+
// ---- 参数解析 ----
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
15
|
+
console.log(`
|
|
16
|
+
${bold("create-openclaw-plugin")} — 一键创建 OpenClaw Plugin 项目
|
|
17
|
+
|
|
18
|
+
${bold("用法:")}
|
|
19
|
+
npx create-openclaw-plugin ${cyan("<plugin-name>")}
|
|
20
|
+
|
|
21
|
+
${bold("示例:")}
|
|
22
|
+
npx create-openclaw-plugin my-weather-plugin
|
|
23
|
+
npx create-openclaw-plugin openclaw-plugin-translator
|
|
24
|
+
|
|
25
|
+
${bold("生成结构:")}
|
|
26
|
+
<plugin-name>/
|
|
27
|
+
├── src/index.ts # 插件源码(含示例 Tool)
|
|
28
|
+
├── openclaw.plugin.json # 插件清单
|
|
29
|
+
├── package.json # npm 包描述
|
|
30
|
+
├── tsconfig.json # TypeScript 配置
|
|
31
|
+
├── tsup.config.ts # 构建配置
|
|
32
|
+
└── README.md # 说明文档
|
|
33
|
+
`);
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const projectName = args[0];
|
|
38
|
+
const projectDir = path.resolve(process.cwd(), projectName);
|
|
39
|
+
|
|
40
|
+
// 插件 ID:如果名字已经带 openclaw-plugin- 前缀就直接用,否则加上
|
|
41
|
+
const pluginId = projectName.startsWith("openclaw-plugin-")
|
|
42
|
+
? projectName
|
|
43
|
+
: `openclaw-plugin-${projectName}`;
|
|
44
|
+
|
|
45
|
+
// Tool name: 把 - 转 _,去掉 openclaw-plugin- 前缀
|
|
46
|
+
const toolBaseName = pluginId
|
|
47
|
+
.replace("openclaw-plugin-", "")
|
|
48
|
+
.replace(/-/g, "_");
|
|
49
|
+
const toolName = `${toolBaseName}_hello`;
|
|
50
|
+
|
|
51
|
+
// ---- 检查目录 ----
|
|
52
|
+
if (fs.existsSync(projectDir)) {
|
|
53
|
+
console.error(`\n❌ 目录已存在: ${projectDir}\n`);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ---- 模板文件 ----
|
|
58
|
+
const templates = {
|
|
59
|
+
"package.json": JSON.stringify(
|
|
60
|
+
{
|
|
61
|
+
name: pluginId,
|
|
62
|
+
version: "0.1.0",
|
|
63
|
+
description: `OpenClaw plugin: ${pluginId}`,
|
|
64
|
+
type: "commonjs",
|
|
65
|
+
main: "dist/index.js",
|
|
66
|
+
types: "dist/index.d.ts",
|
|
67
|
+
openclaw: {
|
|
68
|
+
id: pluginId,
|
|
69
|
+
extensions: ["./dist/index.js"],
|
|
70
|
+
},
|
|
71
|
+
scripts: {
|
|
72
|
+
build: "tsup",
|
|
73
|
+
dev: "tsup --watch",
|
|
74
|
+
},
|
|
75
|
+
peerDependencies: {
|
|
76
|
+
openclaw: ">=2026.3.22",
|
|
77
|
+
},
|
|
78
|
+
devDependencies: {
|
|
79
|
+
openclaw: "^2026.3.22",
|
|
80
|
+
tsup: "^8.5.1",
|
|
81
|
+
typescript: "^5.7.0",
|
|
82
|
+
"@sinclair/typebox": "^0.34.0",
|
|
83
|
+
},
|
|
84
|
+
engines: { node: ">=18.0.0" },
|
|
85
|
+
files: ["dist", "openclaw.plugin.json", "package.json", "README.md"],
|
|
86
|
+
license: "MIT",
|
|
87
|
+
},
|
|
88
|
+
null,
|
|
89
|
+
2
|
|
90
|
+
),
|
|
91
|
+
|
|
92
|
+
"openclaw.plugin.json": JSON.stringify(
|
|
93
|
+
{
|
|
94
|
+
id: pluginId,
|
|
95
|
+
configSchema: {
|
|
96
|
+
type: "object",
|
|
97
|
+
additionalProperties: false,
|
|
98
|
+
properties: {},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
null,
|
|
102
|
+
2
|
|
103
|
+
),
|
|
104
|
+
|
|
105
|
+
"tsup.config.ts": `import { defineConfig } from "tsup";
|
|
106
|
+
export default defineConfig({
|
|
107
|
+
entry: ["src/index.ts"],
|
|
108
|
+
format: ["cjs"],
|
|
109
|
+
target: "node18",
|
|
110
|
+
dts: true,
|
|
111
|
+
clean: true,
|
|
112
|
+
external: ["openclaw"],
|
|
113
|
+
sourcemap: true,
|
|
114
|
+
});
|
|
115
|
+
`,
|
|
116
|
+
|
|
117
|
+
"tsconfig.json": JSON.stringify(
|
|
118
|
+
{
|
|
119
|
+
compilerOptions: {
|
|
120
|
+
target: "ES2022",
|
|
121
|
+
module: "ESNext",
|
|
122
|
+
moduleResolution: "bundler",
|
|
123
|
+
esModuleInterop: true,
|
|
124
|
+
strict: true,
|
|
125
|
+
outDir: "dist",
|
|
126
|
+
declaration: true,
|
|
127
|
+
skipLibCheck: true,
|
|
128
|
+
},
|
|
129
|
+
include: ["src"],
|
|
130
|
+
},
|
|
131
|
+
null,
|
|
132
|
+
2
|
|
133
|
+
),
|
|
134
|
+
|
|
135
|
+
"src/index.ts": `/**
|
|
136
|
+
* ${pluginId}
|
|
137
|
+
*
|
|
138
|
+
* TODO: Replace this demo tool with your own implementation.
|
|
139
|
+
*/
|
|
140
|
+
|
|
141
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
142
|
+
import type { AnyAgentTool } from "openclaw/plugin-sdk/plugin-entry";
|
|
143
|
+
import type { OpenClawPluginToolContext } from "openclaw/plugin-sdk/core";
|
|
144
|
+
import { Type } from "@sinclair/typebox";
|
|
145
|
+
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
// Tool definition
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
|
|
150
|
+
function createHelloTool(): AnyAgentTool {
|
|
151
|
+
return {
|
|
152
|
+
name: "${toolName}",
|
|
153
|
+
label: "${toolBaseName} Hello",
|
|
154
|
+
description:
|
|
155
|
+
"A demo tool from ${pluginId}. Returns a greeting message. " +
|
|
156
|
+
"Replace this with your own tool implementation.",
|
|
157
|
+
parameters: Type.Object({
|
|
158
|
+
name: Type.Optional(
|
|
159
|
+
Type.String({ description: "Name to greet. Defaults to 'World'." })
|
|
160
|
+
),
|
|
161
|
+
}),
|
|
162
|
+
async execute(_toolCallId, params) {
|
|
163
|
+
const greeting = \`Hello, \${params.name || "World"}! 👋 from ${pluginId}\`;
|
|
164
|
+
return {
|
|
165
|
+
content: [{ type: "text", text: greeting }],
|
|
166
|
+
details: { greeting },
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
// Tool factory
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
|
|
176
|
+
function helloToolFactory(_ctx: OpenClawPluginToolContext): AnyAgentTool {
|
|
177
|
+
// Read config if needed:
|
|
178
|
+
// const config = _ctx.config?.plugins?.entries?.["${pluginId}"]?.config;
|
|
179
|
+
return createHelloTool();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// Plugin entry
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
export default definePluginEntry({
|
|
187
|
+
id: "${pluginId}",
|
|
188
|
+
name: "${pluginId}",
|
|
189
|
+
description: "TODO: Add your plugin description here.",
|
|
190
|
+
|
|
191
|
+
register(api) {
|
|
192
|
+
api.registerTool(helloToolFactory, {
|
|
193
|
+
name: "${toolName}",
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
api.logger.info("✅ ${pluginId} loaded");
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
`,
|
|
200
|
+
|
|
201
|
+
"README.md": `# ${pluginId}
|
|
202
|
+
|
|
203
|
+
An OpenClaw plugin.
|
|
204
|
+
|
|
205
|
+
## Quick Start
|
|
206
|
+
|
|
207
|
+
\`\`\`bash
|
|
208
|
+
npm install
|
|
209
|
+
npm run build
|
|
210
|
+
openclaw plugins install .
|
|
211
|
+
openclaw gateway restart
|
|
212
|
+
\`\`\`
|
|
213
|
+
|
|
214
|
+
## Development
|
|
215
|
+
|
|
216
|
+
\`\`\`bash
|
|
217
|
+
# Edit src/index.ts, then:
|
|
218
|
+
npm run build
|
|
219
|
+
cp -rf dist openclaw.plugin.json package.json ~/.openclaw/extensions/${pluginId}/
|
|
220
|
+
openclaw gateway restart
|
|
221
|
+
\`\`\`
|
|
222
|
+
`,
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// ---- 写文件 ----
|
|
226
|
+
console.log(`\n🔌 Creating OpenClaw plugin: ${bold(pluginId)}\n`);
|
|
227
|
+
|
|
228
|
+
fs.mkdirSync(path.join(projectDir, "src"), { recursive: true });
|
|
229
|
+
|
|
230
|
+
for (const [filePath, content] of Object.entries(templates)) {
|
|
231
|
+
const fullPath = path.join(projectDir, filePath);
|
|
232
|
+
fs.writeFileSync(fullPath, content, "utf-8");
|
|
233
|
+
console.log(` ${green("✓")} ${filePath}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ---- 完成提示 ----
|
|
237
|
+
console.log(`
|
|
238
|
+
${green("✅ Done!")} Plugin created at ${cyan(projectDir)}
|
|
239
|
+
|
|
240
|
+
${bold("Next steps:")}
|
|
241
|
+
|
|
242
|
+
cd ${projectName}
|
|
243
|
+
npm install
|
|
244
|
+
npm run build
|
|
245
|
+
openclaw plugins install .
|
|
246
|
+
openclaw gateway restart
|
|
247
|
+
|
|
248
|
+
${yellow("📝 记得修改 src/index.ts 中的 demo tool 为你自己的实现!")}
|
|
249
|
+
`);
|
package/package.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-openclaw-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scaffold a new OpenClaw plugin in seconds",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-openclaw-plugin": "./bin/create.js"
|
|
7
|
+
},
|
|
8
|
+
"files": ["bin", "template"],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18.0.0"
|
|
12
|
+
}
|
|
13
|
+
}
|