@lark-apaas/miaoda-cli 0.1.0-alpha.c783fb5

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.
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handlePluginListPlugins = exports.handlePluginList = exports.handlePluginInit = exports.handlePluginRemove = exports.handlePluginUpdate = exports.handlePluginInstall = void 0;
4
+ var plugin_1 = require("./plugin");
5
+ Object.defineProperty(exports, "handlePluginInstall", { enumerable: true, get: function () { return plugin_1.handlePluginInstall; } });
6
+ Object.defineProperty(exports, "handlePluginUpdate", { enumerable: true, get: function () { return plugin_1.handlePluginUpdate; } });
7
+ Object.defineProperty(exports, "handlePluginRemove", { enumerable: true, get: function () { return plugin_1.handlePluginRemove; } });
8
+ Object.defineProperty(exports, "handlePluginInit", { enumerable: true, get: function () { return plugin_1.handlePluginInit; } });
9
+ Object.defineProperty(exports, "handlePluginList", { enumerable: true, get: function () { return plugin_1.handlePluginList; } });
10
+ Object.defineProperty(exports, "handlePluginListPlugins", { enumerable: true, get: function () { return plugin_1.handlePluginListPlugins; } });
@@ -0,0 +1,382 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.getProjectRoot = getProjectRoot;
40
+ exports.getPluginPath = getPluginPath;
41
+ exports.parsePluginName = parsePluginName;
42
+ exports.readActionPlugins = readActionPlugins;
43
+ exports.writeActionPlugins = writeActionPlugins;
44
+ exports.isPluginInstalled = isPluginInstalled;
45
+ exports.getInstalledPluginVersion = getInstalledPluginVersion;
46
+ exports.getPackageVersion = getPackageVersion;
47
+ exports.readPluginPackageJson = readPluginPackageJson;
48
+ exports.extractTgzToNodeModules = extractTgzToNodeModules;
49
+ exports.checkMissingPeerDeps = checkMissingPeerDeps;
50
+ exports.installMissingDeps = installMissingDeps;
51
+ exports.npmInstall = npmInstall;
52
+ exports.removePluginDirectory = removePluginDirectory;
53
+ exports.capabilitiesDirExists = capabilitiesDirExists;
54
+ exports.readCapability = readCapability;
55
+ exports.readAllCapabilities = readAllCapabilities;
56
+ exports.hydrateCapability = hydrateCapability;
57
+ const node_fs_1 = __importDefault(require("node:fs"));
58
+ const node_path_1 = __importDefault(require("node:path"));
59
+ const node_child_process_1 = require("node:child_process");
60
+ const node_module_1 = require("node:module");
61
+ const error_1 = require("../../../utils/error");
62
+ const logger_1 = require("../../../utils/logger");
63
+ // ── Project paths ──
64
+ function getProjectRoot() {
65
+ return process.cwd();
66
+ }
67
+ function getPackageJsonPath() {
68
+ return node_path_1.default.join(getProjectRoot(), "package.json");
69
+ }
70
+ function getPluginPath(pluginName) {
71
+ return node_path_1.default.join(getProjectRoot(), "node_modules", pluginName);
72
+ }
73
+ // ── Plugin name parsing ──
74
+ function parsePluginName(input) {
75
+ const match = /^(@[^/]+\/[^@]+)(?:@(.+))?$/.exec(input);
76
+ if (!match) {
77
+ throw new error_1.AppError("INVALID_PLUGIN_NAME", `Invalid plugin name format: ${input}. Expected: @scope/name or @scope/name@version`, { next_actions: ["示例:@demo/example-plugin 或 @demo/example-plugin@1.2.3"] });
78
+ }
79
+ return { name: match[1], version: match[2] ?? "latest" };
80
+ }
81
+ // ── package.json actionPlugins CRUD ──
82
+ function readPackageJson() {
83
+ const pkgPath = getPackageJsonPath();
84
+ if (!node_fs_1.default.existsSync(pkgPath)) {
85
+ throw new error_1.AppError("PKG_JSON_NOT_FOUND", "package.json not found in current directory", { next_actions: ["在应用项目根目录运行"] });
86
+ }
87
+ const content = node_fs_1.default.readFileSync(pkgPath, "utf-8");
88
+ return JSON.parse(content);
89
+ }
90
+ function writePackageJson(pkg) {
91
+ const pkgPath = getPackageJsonPath();
92
+ node_fs_1.default.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
93
+ }
94
+ function readActionPlugins() {
95
+ const pkg = readPackageJson();
96
+ return pkg.actionPlugins ?? {};
97
+ }
98
+ function writeActionPlugins(plugins) {
99
+ const pkg = readPackageJson();
100
+ pkg.actionPlugins = plugins;
101
+ writePackageJson(pkg);
102
+ }
103
+ function isPluginInstalled(pluginName) {
104
+ const plugins = readActionPlugins();
105
+ return pluginName in plugins;
106
+ }
107
+ function getInstalledPluginVersion(pluginName) {
108
+ const plugins = readActionPlugins();
109
+ return plugins[pluginName] ?? null;
110
+ }
111
+ // ── node_modules operations ──
112
+ function getPackageVersion(pluginName) {
113
+ const pkgJsonPath = node_path_1.default.join(getPluginPath(pluginName), "package.json");
114
+ if (!node_fs_1.default.existsSync(pkgJsonPath))
115
+ return null;
116
+ try {
117
+ const content = node_fs_1.default.readFileSync(pkgJsonPath, "utf-8");
118
+ const pkg = JSON.parse(content);
119
+ return pkg.version ?? null;
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ }
125
+ function readPluginPackageJson(pluginPath) {
126
+ const pkgJsonPath = node_path_1.default.join(pluginPath, "package.json");
127
+ if (!node_fs_1.default.existsSync(pkgJsonPath))
128
+ return null;
129
+ try {
130
+ const content = node_fs_1.default.readFileSync(pkgJsonPath, "utf-8");
131
+ return JSON.parse(content);
132
+ }
133
+ catch {
134
+ return null;
135
+ }
136
+ }
137
+ function extractTgzToNodeModules(tgzPath, pluginName) {
138
+ const nodeModulesPath = node_path_1.default.join(getProjectRoot(), "node_modules");
139
+ const targetDir = node_path_1.default.join(nodeModulesPath, pluginName);
140
+ const scopeDir = node_path_1.default.dirname(targetDir);
141
+ if (!node_fs_1.default.existsSync(scopeDir)) {
142
+ node_fs_1.default.mkdirSync(scopeDir, { recursive: true });
143
+ }
144
+ if (node_fs_1.default.existsSync(targetDir)) {
145
+ node_fs_1.default.rmSync(targetDir, { recursive: true });
146
+ }
147
+ const tempDir = node_path_1.default.join(nodeModulesPath, ".cache", "miaoda-cli", "extract-temp");
148
+ if (node_fs_1.default.existsSync(tempDir)) {
149
+ node_fs_1.default.rmSync(tempDir, { recursive: true });
150
+ }
151
+ node_fs_1.default.mkdirSync(tempDir, { recursive: true });
152
+ try {
153
+ (0, node_child_process_1.execSync)(`tar -xzf "${tgzPath}" -C "${tempDir}"`, { stdio: "pipe" });
154
+ const extractedDir = node_path_1.default.join(tempDir, "package");
155
+ if (node_fs_1.default.existsSync(extractedDir)) {
156
+ node_fs_1.default.renameSync(extractedDir, targetDir);
157
+ }
158
+ else {
159
+ const files = node_fs_1.default.readdirSync(tempDir);
160
+ if (files.length === 1) {
161
+ node_fs_1.default.renameSync(node_path_1.default.join(tempDir, files[0]), targetDir);
162
+ }
163
+ else {
164
+ throw new error_1.AppError("INTERNAL_EXTRACT_FAILED", "Unexpected tgz structure");
165
+ }
166
+ }
167
+ return targetDir;
168
+ }
169
+ finally {
170
+ if (node_fs_1.default.existsSync(tempDir)) {
171
+ node_fs_1.default.rmSync(tempDir, { recursive: true });
172
+ }
173
+ }
174
+ }
175
+ function checkMissingPeerDeps(peerDeps) {
176
+ if (!peerDeps || Object.keys(peerDeps).length === 0)
177
+ return [];
178
+ const missing = [];
179
+ const nodeModulesPath = node_path_1.default.join(getProjectRoot(), "node_modules");
180
+ for (const depName of Object.keys(peerDeps)) {
181
+ const depPath = node_path_1.default.join(nodeModulesPath, depName);
182
+ if (!node_fs_1.default.existsSync(depPath)) {
183
+ missing.push(depName);
184
+ }
185
+ }
186
+ return missing;
187
+ }
188
+ function installMissingDeps(deps) {
189
+ if (deps.length === 0)
190
+ return;
191
+ (0, logger_1.log)("plugin", `Installing missing dependencies: ${deps.join(", ")}`);
192
+ const result = (0, node_child_process_1.spawnSync)("npm", ["install", ...deps, "--no-save", "--no-package-lock"], { cwd: getProjectRoot(), stdio: "inherit" });
193
+ if (result.error) {
194
+ throw new error_1.AppError("INTERNAL_NPM_FAILED", `npm install failed: ${result.error.message}`, { next_actions: ["确认本机已安装 npm,可 --verbose 查看执行详情"] });
195
+ }
196
+ if (result.status !== 0) {
197
+ throw new error_1.AppError("INTERNAL_NPM_FAILED", `npm install failed with exit code ${String(result.status)}`, { next_actions: ["检查上方 npm 输出日志定位具体错误"] });
198
+ }
199
+ }
200
+ function npmInstall(tgzPath) {
201
+ const result = (0, node_child_process_1.spawnSync)("npm", ["install", tgzPath, "--no-save", "--no-package-lock", "--ignore-scripts"], { cwd: getProjectRoot(), stdio: "inherit" });
202
+ if (result.error) {
203
+ throw new error_1.AppError("INTERNAL_NPM_FAILED", `npm install failed: ${result.error.message}`, { next_actions: ["确认本机已安装 npm,可 --verbose 查看执行详情"] });
204
+ }
205
+ if (result.status !== 0) {
206
+ throw new error_1.AppError("INTERNAL_NPM_FAILED", `npm install failed with exit code ${String(result.status)}`, { next_actions: ["检查上方 npm 输出日志定位具体错误"] });
207
+ }
208
+ }
209
+ function removePluginDirectory(pluginName) {
210
+ const pluginPath = getPluginPath(pluginName);
211
+ if (node_fs_1.default.existsSync(pluginPath)) {
212
+ node_fs_1.default.rmSync(pluginPath, { recursive: true });
213
+ }
214
+ }
215
+ // ── Capability FS ──
216
+ const CAPABILITIES_DIR = "server/capabilities";
217
+ function getCapabilitiesDir() {
218
+ return node_path_1.default.join(getProjectRoot(), CAPABILITIES_DIR);
219
+ }
220
+ function capabilitiesDirExists() {
221
+ return node_fs_1.default.existsSync(getCapabilitiesDir());
222
+ }
223
+ function listCapabilityIds() {
224
+ const dir = getCapabilitiesDir();
225
+ if (!node_fs_1.default.existsSync(dir))
226
+ return [];
227
+ const files = node_fs_1.default.readdirSync(dir);
228
+ return files
229
+ .filter((f) => f.endsWith(".json") && f !== "capabilities.json")
230
+ .map((f) => f.replace(/\.json$/, ""));
231
+ }
232
+ function readCapability(id) {
233
+ const filePath = node_path_1.default.join(getCapabilitiesDir(), `${id}.json`);
234
+ if (!node_fs_1.default.existsSync(filePath)) {
235
+ throw new error_1.AppError("CAPABILITY_NOT_FOUND", `Capability not found: ${id}`, { next_actions: ["运行 miaoda plugin list 查看所有可用 capability id"] });
236
+ }
237
+ try {
238
+ const content = node_fs_1.default.readFileSync(filePath, "utf-8");
239
+ return JSON.parse(content);
240
+ }
241
+ catch (error) {
242
+ if (error instanceof SyntaxError) {
243
+ throw new error_1.AppError("INVALID_JSON", `Invalid JSON in capability file: ${id}.json`, { next_actions: [`检查 server/capabilities/${id}.json 的 JSON 语法`] });
244
+ }
245
+ throw error;
246
+ }
247
+ }
248
+ function readAllCapabilities() {
249
+ const ids = listCapabilityIds();
250
+ const capabilities = [];
251
+ for (const id of ids) {
252
+ try {
253
+ const cap = readCapability(id);
254
+ if (!cap.pluginKey)
255
+ continue;
256
+ capabilities.push(cap);
257
+ }
258
+ catch {
259
+ continue;
260
+ }
261
+ }
262
+ return capabilities;
263
+ }
264
+ // ── Capability Hydration ──
265
+ function getPluginManifestPath(pluginKey) {
266
+ return node_path_1.default.join(getProjectRoot(), "node_modules", pluginKey, "manifest.json");
267
+ }
268
+ function readPluginManifest(pluginKey) {
269
+ const manifestPath = getPluginManifestPath(pluginKey);
270
+ if (!node_fs_1.default.existsSync(manifestPath)) {
271
+ throw new error_1.AppError("MANIFEST_NOT_FOUND", `Plugin not installed: ${pluginKey} (manifest.json not found)`, { next_actions: [`运行 miaoda plugin install ${pluginKey}`] });
272
+ }
273
+ try {
274
+ const content = node_fs_1.default.readFileSync(manifestPath, "utf-8");
275
+ return JSON.parse(content);
276
+ }
277
+ catch (error) {
278
+ if (error instanceof SyntaxError) {
279
+ throw new error_1.AppError("INVALID_JSON", `Invalid JSON in plugin manifest: ${pluginKey}/manifest.json`, { next_actions: [`检查 node_modules/${pluginKey}/manifest.json 的 JSON 语法`] });
280
+ }
281
+ throw error;
282
+ }
283
+ }
284
+ function isDynamicSchema(schema) {
285
+ return (schema !== undefined &&
286
+ typeof schema === "object" &&
287
+ "dynamic" in schema &&
288
+ schema.dynamic === true);
289
+ }
290
+ function hasValidParamsSchema(paramsSchema) {
291
+ return paramsSchema !== undefined && Object.keys(paramsSchema).length > 0;
292
+ }
293
+ async function loadPlugin(pluginKey) {
294
+ try {
295
+ const userRequire = (0, node_module_1.createRequire)(node_path_1.default.join(getProjectRoot(), "package.json"));
296
+ const resolvedPath = userRequire.resolve(pluginKey);
297
+ const pluginModule = (await Promise.resolve(`${resolvedPath}`).then(s => __importStar(require(s))));
298
+ const pluginPackage = (pluginModule.default ?? pluginModule);
299
+ if (typeof pluginPackage.create !== "function") {
300
+ throw new error_1.AppError("INTERNAL_PLUGIN_LOAD_FAILED", `Plugin ${pluginKey} does not export a valid create function`, { next_actions: [`该插件包版本可能过旧,尝试 miaoda plugin update ${pluginKey}`] });
301
+ }
302
+ return pluginPackage;
303
+ }
304
+ catch (error) {
305
+ if (error.code === "MODULE_NOT_FOUND") {
306
+ throw new error_1.AppError("PLUGIN_NOT_FOUND", `Plugin not installed: ${pluginKey}`, { next_actions: [`运行 miaoda plugin install ${pluginKey}`] });
307
+ }
308
+ throw new error_1.AppError("INTERNAL_PLUGIN_LOAD_FAILED", `Failed to load plugin ${pluginKey}: ${error instanceof Error ? error.message : String(error)}`);
309
+ }
310
+ }
311
+ async function hydrateCapability(capability) {
312
+ try {
313
+ const manifest = readPluginManifest(capability.pluginKey);
314
+ if (manifest.actions.length === 0) {
315
+ throw new error_1.AppError("INTERNAL_PLUGIN_LOAD_FAILED", `Plugin ${capability.pluginKey} has no actions defined`);
316
+ }
317
+ const hasDynamic = manifest.actions.some((action) => isDynamicSchema(action.inputSchema) ||
318
+ isDynamicSchema(action.outputSchema));
319
+ let pluginInstance = null;
320
+ if (hasDynamic) {
321
+ const plugin = await loadPlugin(capability.pluginKey);
322
+ pluginInstance = plugin.create(capability.formValue);
323
+ }
324
+ const actions = [];
325
+ for (let index = 0; index < manifest.actions.length; index++) {
326
+ const manifestAction = manifest.actions[index];
327
+ // inputSchema
328
+ let inputSchema;
329
+ if (index === 0 && hasValidParamsSchema(capability.paramsSchema)) {
330
+ inputSchema = capability.paramsSchema;
331
+ }
332
+ else if (isDynamicSchema(manifestAction.inputSchema)) {
333
+ if (!pluginInstance) {
334
+ throw new error_1.AppError("INTERNAL_SCHEMA_ERROR", "Plugin instance not available for dynamic schema");
335
+ }
336
+ const jsonSchema = pluginInstance.getInputJsonSchema(manifestAction.key);
337
+ if (!jsonSchema) {
338
+ throw new error_1.AppError("INTERNAL_SCHEMA_ERROR", `Failed to get input schema for action: ${manifestAction.key}`, { next_actions: [`检查插件 ${capability.pluginKey} 的 getInputJsonSchema 实现`] });
339
+ }
340
+ inputSchema = jsonSchema;
341
+ }
342
+ else {
343
+ inputSchema = manifestAction.inputSchema;
344
+ }
345
+ // outputSchema
346
+ let outputSchema;
347
+ if (isDynamicSchema(manifestAction.outputSchema)) {
348
+ if (!pluginInstance) {
349
+ throw new error_1.AppError("INTERNAL_SCHEMA_ERROR", "Plugin instance not available for dynamic schema");
350
+ }
351
+ const jsonSchema = pluginInstance.getOutputJsonSchema(manifestAction.key, capability.formValue);
352
+ if (!jsonSchema) {
353
+ throw new error_1.AppError("INTERNAL_SCHEMA_ERROR", `Failed to get output schema for action: ${manifestAction.key}`, { next_actions: [`检查插件 ${capability.pluginKey} 的 getOutputJsonSchema 实现`] });
354
+ }
355
+ outputSchema = jsonSchema;
356
+ }
357
+ else {
358
+ outputSchema = manifestAction.outputSchema;
359
+ }
360
+ actions.push({
361
+ key: manifestAction.key,
362
+ inputSchema,
363
+ outputSchema,
364
+ outputMode: manifestAction.outputMode || "",
365
+ });
366
+ }
367
+ return {
368
+ id: capability.id,
369
+ pluginKey: capability.pluginKey,
370
+ pluginVersion: capability.pluginVersion,
371
+ name: capability.name,
372
+ description: capability.description,
373
+ actions,
374
+ createdAt: capability.createdAt,
375
+ updatedAt: capability.updatedAt,
376
+ };
377
+ }
378
+ catch (error) {
379
+ const message = error instanceof Error ? error.message : String(error);
380
+ return { ...capability, _hydrateError: message };
381
+ }
382
+ }