@bluealba/platform-cli 1.0.1 → 1.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/dist/index.js +278 -15
- package/docs/404.mdx +5 -0
- package/docs/architecture/api-explorer.mdx +478 -0
- package/docs/architecture/architecture-diagrams.mdx +12 -0
- package/docs/architecture/authentication-system.mdx +903 -0
- package/docs/architecture/authorization-system.mdx +886 -0
- package/docs/architecture/bootstrap.mdx +1442 -0
- package/docs/architecture/gateway-architecture.mdx +845 -0
- package/docs/architecture/multi-tenancy.mdx +1150 -0
- package/docs/architecture/overview.mdx +776 -0
- package/docs/architecture/scheduler.mdx +818 -0
- package/docs/architecture/shell.mdx +885 -0
- package/docs/architecture/ui-extension-points.mdx +781 -0
- package/docs/architecture/user-states.mdx +794 -0
- package/docs/development/overview.mdx +21 -0
- package/docs/development/workflow.mdx +914 -0
- package/docs/getting-started/core-concepts.mdx +892 -0
- package/docs/getting-started/installation.mdx +780 -0
- package/docs/getting-started/overview.mdx +83 -0
- package/docs/getting-started/quick-start.mdx +940 -0
- package/docs/guides/adding-documentation-sites.mdx +1367 -0
- package/docs/guides/creating-services.mdx +1736 -0
- package/docs/guides/creating-ui-modules.mdx +1860 -0
- package/docs/guides/identity-providers.mdx +1007 -0
- package/docs/guides/mermaid-diagrams.mdx +212 -0
- package/docs/guides/using-feature-flags.mdx +1059 -0
- package/docs/guides/working-with-rooms.mdx +566 -0
- package/docs/index.mdx +57 -0
- package/docs/platform-cli/commands.mdx +604 -0
- package/docs/platform-cli/overview.mdx +195 -0
- package/package.json +5 -2
- package/skills/ba-platform/platform-cli.skill.md +26 -0
- package/skills/ba-platform/platform.skill.md +35 -0
- package/templates/application-monorepo-template/gitignore +95 -0
- package/templates/bootstrap-service-template/Dockerfile.development +1 -1
- package/templates/bootstrap-service-template/gitignore +57 -0
- package/templates/bootstrap-service-template/package.json +1 -1
- package/templates/bootstrap-service-template/src/main.ts +6 -16
- package/templates/customization-ui-module-template/Dockerfile.development +1 -1
- package/templates/customization-ui-module-template/gitignore +73 -0
- package/templates/nestjs-service-module-template/Dockerfile.development +1 -1
- package/templates/nestjs-service-module-template/gitignore +56 -0
- package/templates/platform-init-template/{{platformName}}-core/gitignore +97 -0
- package/templates/platform-init-template/{{platformName}}-core/local/.env.example +1 -1
- package/templates/platform-init-template/{{platformName}}-core/local/platform-docker-compose.yml +1 -1
- package/templates/platform-init-template/{{platformName}}-core/local/{{platformName}}-core-docker-compose.yml +0 -1
- package/templates/react-ui-module-template/Dockerfile +1 -1
- package/templates/react-ui-module-template/Dockerfile.development +1 -3
- package/templates/react-ui-module-template/caddy/Caddyfile +1 -1
- package/templates/react-ui-module-template/gitignore +72 -0
- package/templates/react-ui-module-template/Dockerfile_nginx +0 -11
- package/templates/react-ui-module-template/nginx/default.conf +0 -23
package/dist/index.js
CHANGED
|
@@ -213,7 +213,7 @@ import { join as join2, dirname as dirname2 } from "path";
|
|
|
213
213
|
|
|
214
214
|
// src/utils/template-engine.ts
|
|
215
215
|
import { readdir, readFile, writeFile, mkdir, copyFile, stat, chmod } from "fs/promises";
|
|
216
|
-
import { join, dirname, extname } from "path";
|
|
216
|
+
import { join, dirname, extname, basename } from "path";
|
|
217
217
|
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
218
218
|
".pem",
|
|
219
219
|
".crt",
|
|
@@ -239,6 +239,13 @@ function applyVariables(text, variables) {
|
|
|
239
239
|
}
|
|
240
240
|
return result;
|
|
241
241
|
}
|
|
242
|
+
function transformFilename(relativePath) {
|
|
243
|
+
const base = basename(relativePath);
|
|
244
|
+
if (base === "gitignore") {
|
|
245
|
+
return join(dirname(relativePath), ".gitignore");
|
|
246
|
+
}
|
|
247
|
+
return relativePath;
|
|
248
|
+
}
|
|
242
249
|
function isBinary(filePath) {
|
|
243
250
|
return BINARY_EXTENSIONS.has(extname(filePath).toLowerCase());
|
|
244
251
|
}
|
|
@@ -263,7 +270,7 @@ async function applyTemplate(config, onProgress) {
|
|
|
263
270
|
const relativePath = srcPath.slice(templateDir4.length + 1);
|
|
264
271
|
if (relativePath.endsWith(".gitkeep")) continue;
|
|
265
272
|
if (exclude.includes(relativePath)) continue;
|
|
266
|
-
const transformedRelative = applyVariables(relativePath, variables);
|
|
273
|
+
const transformedRelative = transformFilename(applyVariables(relativePath, variables));
|
|
267
274
|
const destPath = join(outputDir, transformedRelative);
|
|
268
275
|
await mkdir(dirname(destPath), { recursive: true });
|
|
269
276
|
if (isBinary(srcPath)) {
|
|
@@ -453,7 +460,6 @@ function buildBootstrapBlock(platformName, applicationName) {
|
|
|
453
460
|
- NODE_TLS_REJECT_UNAUTHORIZED=0
|
|
454
461
|
- SERVICE_ACCESS_NAME=${applicationName}-bootstrap
|
|
455
462
|
- WAIT_TIME=5000
|
|
456
|
-
- SYNC_STRATEGY=\${PAE_BOOTSTRAP_SYNC_STRATEGY}
|
|
457
463
|
- GATEWAY_SERVICE_URL=\${PAE_GATEWAY_URL}
|
|
458
464
|
- SERVICE_ACCESS_SECRET=\${PAE_GATEWAY_SERVICE_ACCESS_SECRET}
|
|
459
465
|
volumes:
|
|
@@ -481,8 +487,6 @@ function buildBackendBlock(platformName, applicationName, servicePort) {
|
|
|
481
487
|
build:
|
|
482
488
|
context: ../../${platformName}-${applicationName}/services/${serviceName}
|
|
483
489
|
dockerfile: Dockerfile.development
|
|
484
|
-
args:
|
|
485
|
-
- BA_NPM_AUTH_TOKEN=$BA_NPM_AUTH_TOKEN
|
|
486
490
|
ports:
|
|
487
491
|
- ${servicePort}:80
|
|
488
492
|
environment:
|
|
@@ -1120,8 +1124,6 @@ async function appendServiceToDockerCompose(dockerComposePath, serviceName, plat
|
|
|
1120
1124
|
build:
|
|
1121
1125
|
context: ../../${platformName}-${applicationName}/services/${serviceName}
|
|
1122
1126
|
dockerfile: Dockerfile.development
|
|
1123
|
-
args:
|
|
1124
|
-
- BA_NPM_AUTH_TOKEN=$BA_NPM_AUTH_TOKEN
|
|
1125
1127
|
ports:
|
|
1126
1128
|
- ${port}:80
|
|
1127
1129
|
environment:
|
|
@@ -1617,7 +1619,7 @@ async function installDependencies(layout, manifest, logger, signal, includeCore
|
|
|
1617
1619
|
logger.log(`Installing dependencies in parallel: ${targets.map((t) => t.name).join(", ")}...`);
|
|
1618
1620
|
await Promise.all(
|
|
1619
1621
|
targets.map(
|
|
1620
|
-
({ name, dir }) => runCommand("npm", ["install"], dir, logger, signal).then(() => {
|
|
1622
|
+
({ name, dir }) => runCommand("npm", ["install", "--prefer-offline"], dir, logger, signal).then(() => {
|
|
1621
1623
|
logger.log(`\u2713 ${name} install done`);
|
|
1622
1624
|
})
|
|
1623
1625
|
)
|
|
@@ -2047,8 +2049,8 @@ async function checkIdpProviders(layout) {
|
|
|
2047
2049
|
return { configured: false, providers: [], error: `gateway responded with ${response.status}` };
|
|
2048
2050
|
}
|
|
2049
2051
|
const data = await response.json();
|
|
2050
|
-
const
|
|
2051
|
-
return { configured:
|
|
2052
|
+
const providers2 = data.map((p) => ({ name: p.name, type: p.type, active: p.active }));
|
|
2053
|
+
return { configured: providers2.length > 0, providers: providers2 };
|
|
2052
2054
|
}
|
|
2053
2055
|
async function gatherStatus() {
|
|
2054
2056
|
const layout = await findPlatformLayout();
|
|
@@ -2268,6 +2270,91 @@ async function removePlatformAdmin(ruleId, logger) {
|
|
|
2268
2270
|
return true;
|
|
2269
2271
|
}
|
|
2270
2272
|
|
|
2273
|
+
// src/commands/install-ai-plugin/plugins/ba-platform/index.ts
|
|
2274
|
+
var baPlatformPlugin = {
|
|
2275
|
+
name: "ba-platform-plugin",
|
|
2276
|
+
description: "Blue Alba Platform knowledge and CLI skills for AI assistants",
|
|
2277
|
+
version: "1.0.0",
|
|
2278
|
+
skills: [
|
|
2279
|
+
{
|
|
2280
|
+
name: "platform",
|
|
2281
|
+
description: "Comprehensive Blue Alba Platform architecture and concepts knowledge",
|
|
2282
|
+
type: "skill",
|
|
2283
|
+
sourceFile: "skills/ba-platform/platform.skill.md"
|
|
2284
|
+
},
|
|
2285
|
+
{
|
|
2286
|
+
name: "platform-cli",
|
|
2287
|
+
description: "Blue Alba Platform CLI commands and usage knowledge",
|
|
2288
|
+
type: "skill",
|
|
2289
|
+
sourceFile: "skills/ba-platform/platform-cli.skill.md"
|
|
2290
|
+
}
|
|
2291
|
+
]
|
|
2292
|
+
};
|
|
2293
|
+
|
|
2294
|
+
// src/commands/install-ai-plugin/plugins/registry.ts
|
|
2295
|
+
var pluginCatalog = [baPlatformPlugin];
|
|
2296
|
+
function findPlugin(name) {
|
|
2297
|
+
return pluginCatalog.find((p) => p.name === name);
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
// src/commands/install-ai-plugin/install-ai-plugin.command.ts
|
|
2301
|
+
var INSTALL_AI_PLUGIN_COMMAND_NAME = "install-ai-plugin";
|
|
2302
|
+
var installAiPluginCommand = {
|
|
2303
|
+
name: INSTALL_AI_PLUGIN_COMMAND_NAME,
|
|
2304
|
+
description: "Install AI assistant plugins (skills, MCPs, hooks) for your AI provider"
|
|
2305
|
+
};
|
|
2306
|
+
async function installAiPlugin(params, context) {
|
|
2307
|
+
const { provider, docsSource, logger, confirmUpdate } = context;
|
|
2308
|
+
for (const pluginName of params.plugins) {
|
|
2309
|
+
const plugin = findPlugin(pluginName);
|
|
2310
|
+
if (!plugin) {
|
|
2311
|
+
logger.log(`Error: Plugin "${pluginName}" not found in catalog.`);
|
|
2312
|
+
continue;
|
|
2313
|
+
}
|
|
2314
|
+
const manifest = await provider.readManifest(pluginName);
|
|
2315
|
+
const diff = provider.calculateDiff(manifest, plugin);
|
|
2316
|
+
const hasStructuralChanges = diff.versionChanged || diff.newSkills.length > 0 || diff.removedSkills.length > 0;
|
|
2317
|
+
if (manifest && hasStructuralChanges) {
|
|
2318
|
+
logger.log(
|
|
2319
|
+
`Plugin "${pluginName}" is already installed (v${diff.currentVersion} \u2192 v${diff.targetVersion}).`
|
|
2320
|
+
);
|
|
2321
|
+
if (diff.newSkills.length > 0) {
|
|
2322
|
+
logger.log(` New skills: ${diff.newSkills.map((s) => s.name).join(", ")}`);
|
|
2323
|
+
}
|
|
2324
|
+
if (diff.removedSkills.length > 0) {
|
|
2325
|
+
logger.log(` Removed skills: ${diff.removedSkills.join(", ")}`);
|
|
2326
|
+
}
|
|
2327
|
+
if (diff.existingSkills.length > 0) {
|
|
2328
|
+
logger.log(` Updated skills: ${diff.existingSkills.map((s) => s.name).join(", ")}`);
|
|
2329
|
+
}
|
|
2330
|
+
if (!params.force && confirmUpdate) {
|
|
2331
|
+
const proceed = await confirmUpdate(diff, plugin);
|
|
2332
|
+
if (!proceed) {
|
|
2333
|
+
logger.log(`Skipped "${pluginName}".`);
|
|
2334
|
+
continue;
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
for (const skillName of diff.removedSkills) {
|
|
2338
|
+
await provider.removeSkill(skillName, logger);
|
|
2339
|
+
}
|
|
2340
|
+
} else if (!manifest) {
|
|
2341
|
+
logger.log(`Installing plugin "${pluginName}" v${plugin.version}...`);
|
|
2342
|
+
}
|
|
2343
|
+
for (const skill of plugin.skills) {
|
|
2344
|
+
await provider.installSkill(skill, docsSource, logger);
|
|
2345
|
+
}
|
|
2346
|
+
await provider.writeManifest({
|
|
2347
|
+
plugin: pluginName,
|
|
2348
|
+
version: plugin.version,
|
|
2349
|
+
provider: provider.name,
|
|
2350
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2351
|
+
skills: plugin.skills.map((s) => s.name)
|
|
2352
|
+
});
|
|
2353
|
+
await provider.updatePermissions(docsSource, logger);
|
|
2354
|
+
logger.log(`Plugin "${pluginName}" v${plugin.version} installed successfully.`);
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2271
2358
|
// src/commands/registry.ts
|
|
2272
2359
|
var CommandRegistry = class {
|
|
2273
2360
|
commands = /* @__PURE__ */ new Map();
|
|
@@ -2308,6 +2395,7 @@ for (const cmd of localScriptCommands) {
|
|
|
2308
2395
|
}
|
|
2309
2396
|
registry.register(statusCommand);
|
|
2310
2397
|
registry.register(managePlatformAdminsCommand);
|
|
2398
|
+
registry.register(installAiPluginCommand);
|
|
2311
2399
|
|
|
2312
2400
|
// src/app-state.ts
|
|
2313
2401
|
var APP_STATE = {
|
|
@@ -2405,12 +2493,12 @@ async function configureIdpUiController(ctx) {
|
|
|
2405
2493
|
ctx.log("Error: Cannot configure an IDP \u2014 no platform initialized in this directory.");
|
|
2406
2494
|
return;
|
|
2407
2495
|
}
|
|
2408
|
-
const
|
|
2496
|
+
const providers2 = getAllProviders();
|
|
2409
2497
|
const providerType = await ctx.select(
|
|
2410
2498
|
"Select IDP type:",
|
|
2411
|
-
|
|
2499
|
+
providers2.map((p) => ({ label: p.displayName, value: p.type }))
|
|
2412
2500
|
);
|
|
2413
|
-
const provider =
|
|
2501
|
+
const provider = providers2.find((p) => p.type === providerType);
|
|
2414
2502
|
const name = await ctx.prompt("Provider name:");
|
|
2415
2503
|
const issuer = await ctx.prompt("Issuer URL:");
|
|
2416
2504
|
const clientId = await ctx.prompt("Client ID:");
|
|
@@ -2819,6 +2907,153 @@ async function handleRemove(ctx) {
|
|
|
2819
2907
|
ctx.log(`Successfully removed ${successCount} of ${selected.length} admin(s).`);
|
|
2820
2908
|
}
|
|
2821
2909
|
|
|
2910
|
+
// src/services/install-ai-plugin.service.ts
|
|
2911
|
+
async function installAiPluginService(params, context) {
|
|
2912
|
+
await installAiPlugin(params, context);
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
// src/commands/install-ai-plugin/providers/claude.provider.ts
|
|
2916
|
+
import { homedir as homedir2 } from "os";
|
|
2917
|
+
import { join as join26 } from "path";
|
|
2918
|
+
import { readFile as readFile10, writeFile as writeFile9, mkdir as mkdir3, rm } from "fs/promises";
|
|
2919
|
+
var ClaudeProvider = class {
|
|
2920
|
+
name = "claude";
|
|
2921
|
+
baseDir = join26(homedir2(), ".claude");
|
|
2922
|
+
getInstallPath(skillName) {
|
|
2923
|
+
return join26(this.baseDir, "skills", skillName, "SKILL.md");
|
|
2924
|
+
}
|
|
2925
|
+
manifestPath(pluginName) {
|
|
2926
|
+
return join26(this.baseDir, `${pluginName}.manifest.json`);
|
|
2927
|
+
}
|
|
2928
|
+
async readManifest(pluginName) {
|
|
2929
|
+
try {
|
|
2930
|
+
const content = await readFile10(this.manifestPath(pluginName), "utf-8");
|
|
2931
|
+
return JSON.parse(content);
|
|
2932
|
+
} catch {
|
|
2933
|
+
return null;
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
async writeManifest(manifest) {
|
|
2937
|
+
await mkdir3(this.baseDir, { recursive: true });
|
|
2938
|
+
await writeFile9(
|
|
2939
|
+
this.manifestPath(manifest.plugin),
|
|
2940
|
+
JSON.stringify(manifest, null, 2),
|
|
2941
|
+
"utf-8"
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
calculateDiff(manifest, plugin) {
|
|
2945
|
+
const installedSkills = manifest?.skills ?? [];
|
|
2946
|
+
const targetSkillNames = plugin.skills.map((s) => s.name);
|
|
2947
|
+
return {
|
|
2948
|
+
newSkills: plugin.skills.filter((s) => !installedSkills.includes(s.name)),
|
|
2949
|
+
removedSkills: installedSkills.filter((name) => !targetSkillNames.includes(name)),
|
|
2950
|
+
existingSkills: plugin.skills.filter((s) => installedSkills.includes(s.name)),
|
|
2951
|
+
versionChanged: manifest?.version !== plugin.version,
|
|
2952
|
+
currentVersion: manifest?.version ?? null,
|
|
2953
|
+
targetVersion: plugin.version
|
|
2954
|
+
};
|
|
2955
|
+
}
|
|
2956
|
+
async installSkill(skill, docsSource, logger) {
|
|
2957
|
+
const sourcePath = docsSource.resolve(skill.sourceFile);
|
|
2958
|
+
let content = await readFile10(sourcePath, "utf-8");
|
|
2959
|
+
const docsPath = docsSource.resolve("docs");
|
|
2960
|
+
content = content.replaceAll("{{docsPath}}", docsPath);
|
|
2961
|
+
const installPath = this.getInstallPath(skill.name);
|
|
2962
|
+
await mkdir3(join26(installPath, ".."), { recursive: true });
|
|
2963
|
+
await writeFile9(installPath, content, "utf-8");
|
|
2964
|
+
logger.log(` Installed skill: ${installPath}`);
|
|
2965
|
+
}
|
|
2966
|
+
async removeSkill(skillName, logger) {
|
|
2967
|
+
const skillDir = join26(this.baseDir, "skills", skillName);
|
|
2968
|
+
try {
|
|
2969
|
+
await rm(skillDir, { recursive: true, force: true });
|
|
2970
|
+
logger.log(` Removed skill: ${skillDir}`);
|
|
2971
|
+
} catch {
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
async updatePermissions(docsSource, logger) {
|
|
2975
|
+
const settingsPath = join26(this.baseDir, "settings.json");
|
|
2976
|
+
const docsPath = docsSource.resolve("docs");
|
|
2977
|
+
let settings = {};
|
|
2978
|
+
try {
|
|
2979
|
+
const content = await readFile10(settingsPath, "utf-8");
|
|
2980
|
+
settings = JSON.parse(content);
|
|
2981
|
+
} catch {
|
|
2982
|
+
}
|
|
2983
|
+
const permissions = settings.permissions ?? {};
|
|
2984
|
+
const additionalDirectories = permissions.additionalDirectories ?? [];
|
|
2985
|
+
if (additionalDirectories.includes(docsPath)) {
|
|
2986
|
+
return;
|
|
2987
|
+
}
|
|
2988
|
+
permissions.additionalDirectories = [...additionalDirectories, docsPath];
|
|
2989
|
+
settings.permissions = permissions;
|
|
2990
|
+
await mkdir3(this.baseDir, { recursive: true });
|
|
2991
|
+
await writeFile9(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
2992
|
+
logger.log(` Granted read access to docs: ${docsPath}`);
|
|
2993
|
+
}
|
|
2994
|
+
};
|
|
2995
|
+
|
|
2996
|
+
// src/commands/install-ai-plugin/providers/index.ts
|
|
2997
|
+
var providers = {
|
|
2998
|
+
claude: () => new ClaudeProvider()
|
|
2999
|
+
};
|
|
3000
|
+
var providerNames = Object.keys(providers);
|
|
3001
|
+
function getProvider(name) {
|
|
3002
|
+
const factory = providers[name];
|
|
3003
|
+
if (!factory) {
|
|
3004
|
+
throw new Error(`Unknown AI provider: "${name}". Available: ${providerNames.join(", ")}`);
|
|
3005
|
+
}
|
|
3006
|
+
return factory();
|
|
3007
|
+
}
|
|
3008
|
+
|
|
3009
|
+
// src/commands/install-ai-plugin/docs-source/local.docs-source.ts
|
|
3010
|
+
import { fileURLToPath as fileURLToPath10 } from "url";
|
|
3011
|
+
import { join as join27, dirname as dirname12 } from "path";
|
|
3012
|
+
var packageRoot = join27(dirname12(fileURLToPath10(import.meta.url)), "..");
|
|
3013
|
+
var LocalDocsSource = class {
|
|
3014
|
+
resolve(relativePath) {
|
|
3015
|
+
return join27(packageRoot, relativePath);
|
|
3016
|
+
}
|
|
3017
|
+
};
|
|
3018
|
+
|
|
3019
|
+
// src/controllers/ui/install-ai-plugin.ui-controller.ts
|
|
3020
|
+
async function installAiPluginUiController(ctx) {
|
|
3021
|
+
const providerName = await ctx.select(
|
|
3022
|
+
"Select AI provider:",
|
|
3023
|
+
providerNames.map((name) => ({
|
|
3024
|
+
label: name.charAt(0).toUpperCase() + name.slice(1),
|
|
3025
|
+
value: name
|
|
3026
|
+
}))
|
|
3027
|
+
);
|
|
3028
|
+
const selectedPlugins = await ctx.multiselect(
|
|
3029
|
+
"Select plugins to install:",
|
|
3030
|
+
pluginCatalog.map((p) => ({
|
|
3031
|
+
label: `${p.name} \u2014 ${p.description}`,
|
|
3032
|
+
value: p.name
|
|
3033
|
+
}))
|
|
3034
|
+
);
|
|
3035
|
+
if (selectedPlugins.length === 0) {
|
|
3036
|
+
ctx.log("No plugins selected.");
|
|
3037
|
+
return;
|
|
3038
|
+
}
|
|
3039
|
+
const provider = getProvider(providerName);
|
|
3040
|
+
const docsSource = new LocalDocsSource();
|
|
3041
|
+
await installAiPluginService(
|
|
3042
|
+
{ provider: providerName, plugins: selectedPlugins },
|
|
3043
|
+
{
|
|
3044
|
+
provider,
|
|
3045
|
+
docsSource,
|
|
3046
|
+
logger: ctx,
|
|
3047
|
+
confirmUpdate: async (diff, plugin) => {
|
|
3048
|
+
return ctx.confirm(
|
|
3049
|
+
`Update "${plugin.name}" from v${diff.currentVersion} to v${diff.targetVersion}?`,
|
|
3050
|
+
true
|
|
3051
|
+
);
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
);
|
|
3055
|
+
}
|
|
3056
|
+
|
|
2822
3057
|
// src/controllers/ui/registry.ts
|
|
2823
3058
|
var uiControllers = /* @__PURE__ */ new Map([
|
|
2824
3059
|
[CREATE_APPLICATION_COMMAND_NAME, createApplicationUiController],
|
|
@@ -2832,7 +3067,8 @@ var uiControllers = /* @__PURE__ */ new Map([
|
|
|
2832
3067
|
[START_COMMAND_NAME, createLocalScriptUiController(START_COMMAND_NAME)],
|
|
2833
3068
|
[STOP_COMMAND_NAME, createLocalScriptUiController(STOP_COMMAND_NAME)],
|
|
2834
3069
|
[DESTROY_COMMAND_NAME, createLocalScriptUiController(DESTROY_COMMAND_NAME)],
|
|
2835
|
-
[MANAGE_PLATFORM_ADMINS_COMMAND_NAME, managePlatformAdminsUiController]
|
|
3070
|
+
[MANAGE_PLATFORM_ADMINS_COMMAND_NAME, managePlatformAdminsUiController],
|
|
3071
|
+
[INSTALL_AI_PLUGIN_COMMAND_NAME, installAiPluginUiController]
|
|
2836
3072
|
]);
|
|
2837
3073
|
|
|
2838
3074
|
// src/hooks/use-command-runner.ts
|
|
@@ -3463,6 +3699,32 @@ async function managePlatformAdminsCliController(args2) {
|
|
|
3463
3699
|
}
|
|
3464
3700
|
}
|
|
3465
3701
|
|
|
3702
|
+
// src/controllers/cli/install-ai-plugin.cli-controller.ts
|
|
3703
|
+
async function installAiPluginCliController(args2) {
|
|
3704
|
+
const { provider: providerName, plugins: pluginsArg, force } = args2;
|
|
3705
|
+
if (!providerName) {
|
|
3706
|
+
console.error('Error: "provider" argument is required (e.g., provider=claude).');
|
|
3707
|
+
process.exit(1);
|
|
3708
|
+
}
|
|
3709
|
+
if (!pluginsArg) {
|
|
3710
|
+
console.error(
|
|
3711
|
+
'Error: "plugins" argument is required (e.g., plugins=ba-platform-plugin).'
|
|
3712
|
+
);
|
|
3713
|
+
process.exit(1);
|
|
3714
|
+
}
|
|
3715
|
+
const plugins = pluginsArg.split(",").map((s) => s.trim());
|
|
3716
|
+
const provider = getProvider(providerName);
|
|
3717
|
+
const docsSource = new LocalDocsSource();
|
|
3718
|
+
await installAiPluginService(
|
|
3719
|
+
{ provider: providerName, plugins, force: force === "true" },
|
|
3720
|
+
{
|
|
3721
|
+
provider,
|
|
3722
|
+
docsSource,
|
|
3723
|
+
logger: { log: console.log }
|
|
3724
|
+
}
|
|
3725
|
+
);
|
|
3726
|
+
}
|
|
3727
|
+
|
|
3466
3728
|
// src/controllers/cli/registry.ts
|
|
3467
3729
|
var cliControllers = /* @__PURE__ */ new Map([
|
|
3468
3730
|
[CREATE_APPLICATION_COMMAND_NAME, createApplicationCliController],
|
|
@@ -3476,7 +3738,8 @@ var cliControllers = /* @__PURE__ */ new Map([
|
|
|
3476
3738
|
[START_COMMAND_NAME, createLocalScriptCliController(START_COMMAND_NAME)],
|
|
3477
3739
|
[STOP_COMMAND_NAME, createLocalScriptCliController(STOP_COMMAND_NAME)],
|
|
3478
3740
|
[DESTROY_COMMAND_NAME, createLocalScriptCliController(DESTROY_COMMAND_NAME)],
|
|
3479
|
-
[MANAGE_PLATFORM_ADMINS_COMMAND_NAME, managePlatformAdminsCliController]
|
|
3741
|
+
[MANAGE_PLATFORM_ADMINS_COMMAND_NAME, managePlatformAdminsCliController],
|
|
3742
|
+
[INSTALL_AI_PLUGIN_COMMAND_NAME, installAiPluginCliController]
|
|
3480
3743
|
]);
|
|
3481
3744
|
|
|
3482
3745
|
// src/utils/parse-args.ts
|