@klingai/plugin-cn 0.0.0-stage → 0.0.2-beta
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/.claude-plugin/plugin.json +20 -0
- package/.codex-plugin/plugin.json +40 -0
- package/.mcp.json +13 -0
- package/.workbuddy-plugin/plugin.json +20 -0
- package/README.cn.md +48 -0
- package/README.global.md +48 -0
- package/README.md +47 -2
- package/archives/claude-skill.zip +0 -0
- package/assets/kling-logo.png +0 -0
- package/bin/plugin.mjs +179 -0
- package/bin/postinstall.mjs +16 -0
- package/dist/cli.js +22255 -0
- package/lib/install.mjs +910 -0
- package/lib/region-data.mjs +48 -0
- package/lib/region.mjs +16 -0
- package/lib/uninstall.mjs +236 -0
- package/mcp.json +24 -0
- package/package.json +67 -4
- package/plugin.json +44 -0
- package/skills/kling-ai-plugin/SKILL.md +154 -0
- package/skills/kling-ai-plugin/agents/openai.yaml +6 -0
- package/skills/kling-ai-plugin/api-examples.md +328 -0
- package/skills/kling-ai-plugin/dist/cli.mjs +22255 -0
- package/skills/kling-ai-plugin/package.json +9 -0
- package/skills/kling-ai-plugin/reference.md +90 -0
- package/skills/kling-ai-plugin/region.md +9 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
|
+
"name": "kling-universal",
|
|
4
|
+
"displayName": "可灵 AI",
|
|
5
|
+
"version": "0.0.2-beta",
|
|
6
|
+
"description": "使用可灵 AI 生成和编辑图片、创作可灵 4.0 视频,支持关键帧、全能参考、角色主体与动作控制。",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Kling AI"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://klingai.com",
|
|
11
|
+
"license": "Proprietary",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"kling",
|
|
14
|
+
"image-generation",
|
|
15
|
+
"video-generation",
|
|
16
|
+
"claude-code"
|
|
17
|
+
],
|
|
18
|
+
"mcpServers": "./.mcp.json",
|
|
19
|
+
"skills": "./skills/"
|
|
20
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kling-universal",
|
|
3
|
+
"version": "0.0.2-beta",
|
|
4
|
+
"description": "使用可灵 AI 生成和编辑图片、创作可灵 4.0 视频,支持关键帧、全能参考、角色主体与动作控制。",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Kling AI"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://klingai.com",
|
|
9
|
+
"license": "Proprietary",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"kling",
|
|
12
|
+
"image-generation",
|
|
13
|
+
"video-generation",
|
|
14
|
+
"codex"
|
|
15
|
+
],
|
|
16
|
+
"mcpServers": "./.mcp.json",
|
|
17
|
+
"skills": "./skills/",
|
|
18
|
+
"interface": {
|
|
19
|
+
"displayName": "可灵 AI",
|
|
20
|
+
"shortDescription": "一句话,让灵感从想法变成大片",
|
|
21
|
+
"longDescription": "使用可灵 AI 生成和编辑图片,以可灵 4.0、4.0 Flash 等可用模型创作视频,支持关键帧、全能参考、角色主体与动作控制,并管理素材、任务和灵感值。",
|
|
22
|
+
"developerName": "可灵 AI",
|
|
23
|
+
"category": "Creativity",
|
|
24
|
+
"capabilities": [
|
|
25
|
+
"Interactive",
|
|
26
|
+
"Read",
|
|
27
|
+
"Write"
|
|
28
|
+
],
|
|
29
|
+
"websiteURL": "https://klingai.com",
|
|
30
|
+
"defaultPrompt": [
|
|
31
|
+
"生成一张电影感图片:一只小萨摩耶在开满野花的草地上快乐奔跑,阳光逆光,毛发细节清晰",
|
|
32
|
+
"使用可灵 4.0 生成一段 5 秒电影感视频:机甲战士从空中落地,碎石与尘土飞散,镜头快速推进",
|
|
33
|
+
"查询我的可灵任务状态,只查询,不创建新的生成任务"
|
|
34
|
+
],
|
|
35
|
+
"brandColor": "#000000",
|
|
36
|
+
"logo": "./assets/kling-logo.png",
|
|
37
|
+
"logoDark": "./assets/kling-logo.png",
|
|
38
|
+
"composerIcon": "./assets/kling-logo.png"
|
|
39
|
+
}
|
|
40
|
+
}
|
package/.mcp.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
|
+
"name": "kling-universal",
|
|
4
|
+
"displayName": "可灵 AI",
|
|
5
|
+
"version": "0.0.2-beta",
|
|
6
|
+
"description": "使用可灵 AI 生成和编辑图片、创作可灵 4.0 视频,支持关键帧、全能参考、角色主体与动作控制。",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Kling AI"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://klingai.com",
|
|
11
|
+
"license": "Proprietary",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"kling",
|
|
14
|
+
"image-generation",
|
|
15
|
+
"video-generation",
|
|
16
|
+
"workbuddy"
|
|
17
|
+
],
|
|
18
|
+
"mcpServers": "./.mcp.json",
|
|
19
|
+
"skills": "./skills/"
|
|
20
|
+
}
|
package/README.cn.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# 可灵 AI 插件
|
|
2
|
+
|
|
3
|
+
在 AI 助手中使用可灵 AI 生成图片、创作视频、复用角色主体和控制动作。内置 CLI、创作 Skill 和 MCP 集成。
|
|
4
|
+
|
|
5
|
+
需要 Node.js 18 或更高版本。本包适用于中国站账号;海外站账号请安装 `@klingai/plugin-global`。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i -g @klingai/plugin-cn@latest
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
安装时自动为默认支持的全部助手安装 Skill,无需选择助手。安装后重启助手,新建会话即可使用 **Kling AI Plugin**。
|
|
14
|
+
|
|
15
|
+
## 快速开始
|
|
16
|
+
|
|
17
|
+
在助手中输入:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
使用可灵 AI 插件,生成一张图片:一只柴犬坐在咖啡馆窗边。
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
首次使用时按提示完成登录。生成图片和视频会消耗灵感值,可用模型和功能以当前账号为准。
|
|
24
|
+
|
|
25
|
+
也可以在终端使用内置 CLI:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
kling-plugin login
|
|
29
|
+
kling-plugin who_am_i
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 升级
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm i -g @klingai/plugin-cn@latest
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
升级后重启助手。
|
|
39
|
+
|
|
40
|
+
## 检查与卸载
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# 检查安装
|
|
44
|
+
plugin-cn doctor --host all
|
|
45
|
+
|
|
46
|
+
# 完整卸载,保留登录凭据和日志
|
|
47
|
+
plugin-cn uninstall
|
|
48
|
+
```
|
package/README.global.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Kling AI Plugin
|
|
2
|
+
|
|
3
|
+
Generate images and videos, reuse Elements, and control motion with Kling AI in your AI assistant. Includes a CLI, a creation Skill, and MCP integration.
|
|
4
|
+
|
|
5
|
+
Requires Node.js 18+. This package is for Global accounts; use `@klingai/plugin-cn` for China-site accounts.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i -g @klingai/plugin-global@latest
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Installation automatically adds the Skill for all default supported assistants. No assistant selection is needed. Restart your assistant and open a new conversation to use **Kling AI Plugin**.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
Ask your assistant:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
Use Kling AI Plugin to generate an image of a shiba inu sitting by a cafe window.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Follow the sign-in instructions when prompted. Image and video generation consumes credits. Available models and features depend on your account.
|
|
24
|
+
|
|
25
|
+
You can also use the bundled CLI in your terminal:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
kling-plugin login
|
|
29
|
+
kling-plugin who_am_i
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Upgrade
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm i -g @klingai/plugin-global@latest
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Restart your assistant after upgrading.
|
|
39
|
+
|
|
40
|
+
## Check And Uninstall
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Check installation
|
|
44
|
+
plugin-global doctor --host all
|
|
45
|
+
|
|
46
|
+
# Uninstall; keep login credentials and logs
|
|
47
|
+
plugin-global uninstall
|
|
48
|
+
```
|
package/README.md
CHANGED
|
@@ -1,3 +1,48 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 可灵 AI 插件
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
在 AI 助手中使用可灵 AI 生成图片、创作视频、复用角色主体和控制动作。内置 CLI、创作 Skill 和 MCP 集成。
|
|
4
|
+
|
|
5
|
+
需要 Node.js 18 或更高版本。本包适用于中国站账号;海外站账号请安装 `@klingai/plugin-global`。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i -g @klingai/plugin-cn@latest
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
安装时自动为默认支持的全部助手安装 Skill,无需选择助手。安装后重启助手,新建会话即可使用 **Kling AI Plugin**。
|
|
14
|
+
|
|
15
|
+
## 快速开始
|
|
16
|
+
|
|
17
|
+
在助手中输入:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
使用可灵 AI 插件,生成一张图片:一只柴犬坐在咖啡馆窗边。
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
首次使用时按提示完成登录。生成图片和视频会消耗灵感值,可用模型和功能以当前账号为准。
|
|
24
|
+
|
|
25
|
+
也可以在终端使用内置 CLI:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
kling-plugin login
|
|
29
|
+
kling-plugin who_am_i
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 升级
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm i -g @klingai/plugin-cn@latest
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
升级后重启助手。
|
|
39
|
+
|
|
40
|
+
## 检查与卸载
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# 检查安装
|
|
44
|
+
plugin-cn doctor --host all
|
|
45
|
+
|
|
46
|
+
# 完整卸载,保留登录凭据和日志
|
|
47
|
+
plugin-cn uninstall
|
|
48
|
+
```
|
|
Binary file
|
|
Binary file
|
package/bin/plugin.mjs
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
PACKAGE_NAME,
|
|
5
|
+
PLUGIN_BASE_URL,
|
|
6
|
+
PLUGIN_DISPLAY_NAME,
|
|
7
|
+
SUPPORTED_HOSTS,
|
|
8
|
+
DEFAULT_SKILL_HOSTS,
|
|
9
|
+
createInstallPlan,
|
|
10
|
+
displayPath,
|
|
11
|
+
doctor,
|
|
12
|
+
doctorSkillDirectory,
|
|
13
|
+
exposeCommand,
|
|
14
|
+
installHost,
|
|
15
|
+
installSkillDirectory,
|
|
16
|
+
parseArgs,
|
|
17
|
+
preflightInstallHosts,
|
|
18
|
+
resolveInstallHosts,
|
|
19
|
+
removeManagedObsoleteSkills,
|
|
20
|
+
stagePackage,
|
|
21
|
+
uninstallHost,
|
|
22
|
+
uninstallSkillDirectory,
|
|
23
|
+
} from '../lib/install.mjs';
|
|
24
|
+
import { uninstallAll } from '../lib/uninstall.mjs';
|
|
25
|
+
|
|
26
|
+
function reportCommand(wrapper) {
|
|
27
|
+
console.log(`CLI: ${displayPath(wrapper)}`);
|
|
28
|
+
if (process.platform === 'win32') return;
|
|
29
|
+
const result = exposeCommand(wrapper);
|
|
30
|
+
if (result.status === 'linked') console.log(`Command: ${displayPath(result.path)} -> kling-plugin is available in new terminals`);
|
|
31
|
+
else if (result.status === 'conflict') console.log(`Command: kling-plugin was not linked (${result.reason}); run ${displayPath(wrapper)} directly or remove that file`);
|
|
32
|
+
else if (result.status === 'not-on-path') console.log(`Command: add ~/.kling/bin to PATH to run kling-plugin, e.g. echo 'export PATH="$HOME/.kling/bin:$PATH"' >> ~/.zshrc`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function usage() {
|
|
36
|
+
const installerName = PACKAGE_NAME.split('/').at(-1);
|
|
37
|
+
return [
|
|
38
|
+
`${PLUGIN_DISPLAY_NAME} installer`,
|
|
39
|
+
'',
|
|
40
|
+
'Usage:',
|
|
41
|
+
` ${installerName} install # Install Skills for the checked Host set`,
|
|
42
|
+
` ${installerName} install --host <${DEFAULT_SKILL_HOSTS.join('|')}|all>`,
|
|
43
|
+
` ${installerName} install --skills-dir <path>`,
|
|
44
|
+
` ${installerName} install --host <directory-host> --link-skills`,
|
|
45
|
+
` ${installerName} install [--host <host>] --dry-run`,
|
|
46
|
+
` ${installerName} doctor --host <host|all>`,
|
|
47
|
+
` ${installerName} doctor --skills-dir <path>`,
|
|
48
|
+
` ${installerName} uninstall [--dry-run] # Remove all managed Skills, CLI and npm installs`,
|
|
49
|
+
` ${installerName} uninstall --host <host> [--purge]`,
|
|
50
|
+
` ${installerName} uninstall --skills-dir <path> [--purge]`,
|
|
51
|
+
'',
|
|
52
|
+
`${PACKAGE_NAME} has a fixed endpoint: ${PLUGIN_BASE_URL}.`,
|
|
53
|
+
].join('\n');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const { command, host, skillsDir, purge, dryRun, linkSkills } = parseArgs(process.argv.slice(2));
|
|
58
|
+
const installOptions = { skillsOnly: !host || host === 'all' };
|
|
59
|
+
if (command === 'help' || command === '--help' || command === '-h') {
|
|
60
|
+
console.log(usage());
|
|
61
|
+
process.exitCode = 0;
|
|
62
|
+
} else if (!host && !skillsDir && command !== 'install' && command !== 'uninstall') {
|
|
63
|
+
throw new Error(`--host or --skills-dir is required. Choose: ${SUPPORTED_HOSTS.join(', ')}, all`);
|
|
64
|
+
} else if (command === 'install') {
|
|
65
|
+
if (skillsDir) {
|
|
66
|
+
if (dryRun) {
|
|
67
|
+
console.log(JSON.stringify({
|
|
68
|
+
...createInstallPlan([]),
|
|
69
|
+
customSkillsDir: displayPath(skillsDir),
|
|
70
|
+
}, null, 2));
|
|
71
|
+
process.exitCode = 0;
|
|
72
|
+
} else {
|
|
73
|
+
const staged = stagePackage();
|
|
74
|
+
const result = installSkillDirectory(skillsDir, staged, { linkSkills });
|
|
75
|
+
console.log(`[written] custom: ${displayPath(result.path)}`);
|
|
76
|
+
reportCommand(staged.wrapper);
|
|
77
|
+
console.log('Skill files written; Host discovery is not verified. Restart the Host or reload Skills, then start a new session.');
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
const hosts = resolveInstallHosts(host);
|
|
81
|
+
if (host && host !== 'all' && !DEFAULT_SKILL_HOSTS.includes(host) && host !== 'agents') {
|
|
82
|
+
console.error(`Unverified Host target: ${host}. This writes Skill files only; application discovery and invocation have not passed acceptance.`);
|
|
83
|
+
}
|
|
84
|
+
const preflight = preflightInstallHosts(hosts, { ...installOptions, linkSkills });
|
|
85
|
+
if (dryRun) {
|
|
86
|
+
console.log(JSON.stringify({ ...createInstallPlan(hosts, installOptions), preflight }, null, 2));
|
|
87
|
+
process.exitCode = 0;
|
|
88
|
+
} else {
|
|
89
|
+
const failedPreflight = preflight.filter((result) => result.status === 'failed');
|
|
90
|
+
const unavailable = preflight.filter((result) => result.status === 'unavailable');
|
|
91
|
+
const conflicts = preflight.filter((result) => result.status === 'conflict');
|
|
92
|
+
if (failedPreflight.length > 0 || (host !== 'all' && host !== undefined && (unavailable.length > 0 || conflicts.length > 0))) {
|
|
93
|
+
const reasons = [...failedPreflight, ...unavailable, ...conflicts]
|
|
94
|
+
.map((result) => `${result.host}: ${result.reason}`)
|
|
95
|
+
.join('; ');
|
|
96
|
+
throw new Error(`Install preflight failed: ${reasons}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const installableHosts = preflight
|
|
100
|
+
.filter((result) => result.status === 'ready')
|
|
101
|
+
.map((result) => result.host);
|
|
102
|
+
if (installableHosts.length === 0) {
|
|
103
|
+
throw new Error('No available Host remained after install preflight');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const staged = stagePackage();
|
|
107
|
+
const results = [...unavailable, ...conflicts].map((result) => ({
|
|
108
|
+
host: result.host,
|
|
109
|
+
status: 'skipped',
|
|
110
|
+
reason: result.reason,
|
|
111
|
+
}));
|
|
112
|
+
for (const item of installableHosts) {
|
|
113
|
+
try {
|
|
114
|
+
const result = installHost(item, staged, { ...installOptions, linkSkills });
|
|
115
|
+
results.push({ host: item, status: result.status, path: result.path });
|
|
116
|
+
} catch (error) {
|
|
117
|
+
results.push({ host: item, status: 'failed', reason: error.message });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
console.log('Install summary:');
|
|
122
|
+
for (const result of results) {
|
|
123
|
+
const detail = result.path ? displayPath(result.path) : result.reason;
|
|
124
|
+
const status = result.status === 'installed' && (installOptions.skillsOnly || !['codex', 'claude', 'pi'].includes(result.host))
|
|
125
|
+
? 'written' : result.status;
|
|
126
|
+
console.log(` [${status}] ${result.host}: ${detail}`);
|
|
127
|
+
}
|
|
128
|
+
reportCommand(staged.wrapper);
|
|
129
|
+
console.log('Host discovery and invocation are not verified by installation. Restart the Host or reload Skills, then start a new session.');
|
|
130
|
+
if (results.some((result) => result.host === 'workbuddy' && result.status === 'installed')) {
|
|
131
|
+
console.log(`WorkBuddy: look for Kling AI Plugin under Installed Skills (user-defined); the plugin marketplace is separate.`);
|
|
132
|
+
}
|
|
133
|
+
if (!installOptions.skillsOnly && results.some((result) => result.host === 'codex' && result.status === 'installed')) {
|
|
134
|
+
console.log('Codex MCP OAuth is separate from kling login. Check: codex mcp list; if kling-ai is Not logged in, run: codex mcp login kling-ai. Then restart Codex and open a new session. UI rendering still depends on the Host.');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const failures = results.filter((result) => result.status === 'failed');
|
|
138
|
+
if (failures.length > 0) {
|
|
139
|
+
throw new Error(`${failures.length} Host installation${failures.length === 1 ? '' : 's'} failed`);
|
|
140
|
+
}
|
|
141
|
+
if (installOptions.skillsOnly) removeManagedObsoleteSkills(staged);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} else if (command === 'doctor') {
|
|
145
|
+
if (skillsDir) {
|
|
146
|
+
const result = doctorSkillDirectory(skillsDir);
|
|
147
|
+
console.log(JSON.stringify(result, null, 2));
|
|
148
|
+
if (!result.ok) process.exitCode = 1;
|
|
149
|
+
} else {
|
|
150
|
+
let result;
|
|
151
|
+
if (host === 'all') {
|
|
152
|
+
const plan = createInstallPlan(resolveInstallHosts('all'), { skillsOnly: true });
|
|
153
|
+
const results = plan.hosts.map(({ host: item, target }) => ({
|
|
154
|
+
host: item, path: target, ...doctor(item, { skillsOnly: true }),
|
|
155
|
+
}));
|
|
156
|
+
result = { ok: results.every((item) => item.ok), hosts: results };
|
|
157
|
+
} else {
|
|
158
|
+
result = doctor(host);
|
|
159
|
+
}
|
|
160
|
+
console.log(JSON.stringify(result, null, 2));
|
|
161
|
+
if (!result.ok) process.exitCode = 1;
|
|
162
|
+
}
|
|
163
|
+
} else if (command === 'uninstall') {
|
|
164
|
+
if (!host && !skillsDir) {
|
|
165
|
+
console.log(JSON.stringify(uninstallAll({ dryRun }), null, 2));
|
|
166
|
+
} else if (skillsDir) {
|
|
167
|
+
uninstallSkillDirectory(skillsDir, { purge });
|
|
168
|
+
} else {
|
|
169
|
+
const hosts = host === 'all' ? resolveInstallHosts('all', { includeUnverified: true }) : [host];
|
|
170
|
+
for (const item of hosts) uninstallHost(item, { skillsOnly: host === 'all', purge: purge && item === hosts.at(-1) });
|
|
171
|
+
}
|
|
172
|
+
if (host || skillsDir) console.log('Plugin registration removed. OAuth credentials and logs were preserved.');
|
|
173
|
+
} else {
|
|
174
|
+
throw new Error(`Unknown command: ${command}\n\n${usage()}`);
|
|
175
|
+
}
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error(`Error: ${error.message}`);
|
|
178
|
+
process.exitCode = 1;
|
|
179
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { recordNpmInstallation } from '../lib/install.mjs';
|
|
4
|
+
|
|
5
|
+
// npm exec / npx runs the user's installer arguments after fetching the package.
|
|
6
|
+
// Installing here would turn --dry-run and single-Host operations into full installs.
|
|
7
|
+
if (process.env.npm_command !== 'exec') {
|
|
8
|
+
const result = spawnSync(
|
|
9
|
+
process.execPath,
|
|
10
|
+
[fileURLToPath(new URL('./plugin.mjs', import.meta.url)), 'install'],
|
|
11
|
+
{ stdio: 'inherit' },
|
|
12
|
+
);
|
|
13
|
+
if (result.error) throw result.error;
|
|
14
|
+
process.exitCode = result.status ?? 1;
|
|
15
|
+
if (result.status === 0) recordNpmInstallation(fileURLToPath(new URL('..', import.meta.url)));
|
|
16
|
+
}
|