@cloudglab/confluence-cli 0.0.2 → 0.0.4
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/CHANGELOG.md +34 -6
- package/README.md +7 -3
- package/dist/core/cli-output.js +6 -4
- package/dist/install.js +42 -17
- package/dist/manifest.json +1 -1
- package/dist/tools/install.js +1 -0
- package/dist/tools/transfer.js +20 -15
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -2
- package/skills/confluence-cli/SKILL.md +0 -63
- package/skills/confluence-cli/reference/cli.md +0 -36
- package/skills/confluence-cli/reference/commands.md +0 -41
- package/skills/confluence-cli/reference/content.md +0 -23
- package/skills/confluence-cli/reference/overview.md +0 -23
- package/skills/confluence-cli/reference/rest.md +0 -19
- package/skills/confluence-cli/reference/transfer.md +0 -27
package/CHANGELOG.md
CHANGED
|
@@ -2,17 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## 0.0.
|
|
5
|
+
## 0.0.4 - 2026-06-17
|
|
6
|
+
|
|
7
|
+
### 修复
|
|
8
|
+
|
|
9
|
+
- Mermaid 渲染器从 `@mermaid-js/mermaid-cli` 全量替换为 `coolamit/mermaid-cli` 的原生二进制 `mmd-cli`,不再保留 `mmdc` / Puppeteer 兼容路径。
|
|
10
|
+
- `install` / `update` 链路会自动执行上游 `mmd-cli` 安装脚本,避免 npm 安装阶段拉取 Chrome 失败。
|
|
11
|
+
- `uninstall` 链路会一并清理 `~/.local/bin/mmd-cli` 和 `/usr/local/bin/mmd-cli`。
|
|
12
|
+
- `uploadMarkdown` 的 Mermaid 附件匹配逻辑改为优先按预期文件名命中,减少多附件场景下图片宏指向错误的问题。
|
|
13
|
+
|
|
14
|
+
### 测试
|
|
15
|
+
|
|
16
|
+
- `tests/install.test.ts` 新增 `mmd-cli` 安装步骤断言,覆盖 install / update 流程。
|
|
17
|
+
- `tests/tools/transfer.test.ts` 新增 Mermaid 渲染调用测试,校验 `mmd-cli` 的输入、输出、背景和缩放参数。
|
|
18
|
+
|
|
19
|
+
### 说明
|
|
20
|
+
|
|
21
|
+
- `mmd-cli` 运行时仍要求系统已有 Chrome/Chromium;如果目标机器没有浏览器,可在上传时传 `--mermaid none`,保留 Mermaid 代码块。
|
|
22
|
+
|
|
23
|
+
## 0.0.3 - 2026-06-16
|
|
6
24
|
|
|
7
25
|
### Fixed
|
|
8
26
|
|
|
9
|
-
-
|
|
10
|
-
- `
|
|
27
|
+
- 撤掉 0.0.2 在 `npx -y skills add` 命令里默认追加的 `--global`。`vercel-labs/skills` 在 agent 内运行时本身就走项目级(`cwd` 下对应 agent 的 skills 目录),与 npx 临时目录是否被回收无关;强制传 `--global` 会让不支持全局安装的 agent(如 `PromptScript`,见 `vercel-labs/skills` `src/installer.ts`)直接报 `does not support global skill installation`。
|
|
28
|
+
- 新增 `--skill-global` opt-in 标记,用户明确需要 user-level 全局时通过 `confluence install --skill-global true` / `confluence update --skill-global true` 显式开启。`InstallOptions` 新增 `skillGlobal: boolean`(默认 `false`),CLI 工具层 schema 与 help 文本同步更新。
|
|
29
|
+
- `runUninstallCommand` 链路行为不变(仍同时清理项目级与全局级残留),0.0.2 升级到 0.0.3 不会丢清理路径。
|
|
11
30
|
|
|
12
|
-
###
|
|
31
|
+
### Tests
|
|
32
|
+
|
|
33
|
+
- `tests/install.test.ts` 回退 3 处 `npx -y skills add` 期望参数为 `--yes`(默认项目级),新增 `--skill-global true` 用例验证 opt-in 路径会追加 `--global`。
|
|
34
|
+
- `tests/cli.test.ts` / `tests/update-probe.test.ts` 硬编码版本号同步 0.0.2 → 0.0.3。
|
|
35
|
+
|
|
36
|
+
## 0.0.2 - 2026-06-16(已撤回)
|
|
37
|
+
|
|
38
|
+
> 0.0.2 在 `createSkillAddArgs` 里默认传 `--global`,对不支持全局的 agent 不可用,发布后已被 0.0.3 撤回。已通过 `npm deprecate` 标记,请直接升级到 0.0.3。
|
|
39
|
+
|
|
40
|
+
### Reverted by 0.0.3
|
|
13
41
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
42
|
+
- 撤掉 `createSkillAddArgs` 默认追加的 `--global`;改回 `--yes`(项目级)。
|
|
43
|
+
- `runUninstallCommand` 链路保持兼容。
|
|
16
44
|
|
|
17
45
|
## 0.0.1 - 2026-06-15
|
|
18
46
|
|
package/README.md
CHANGED
|
@@ -21,6 +21,10 @@ pnpm test
|
|
|
21
21
|
pnpm release:smoke-query --dry-run
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
从 `0.0.4` 起,Mermaid 渲染不再依赖 `@mermaid-js/mermaid-cli`。CLI 安装/更新时会自动安装 `coolamit/mermaid-cli` 提供的原生二进制 `mmd-cli`,避开 Puppeteer/Chrome 下载链路,并在卸载时清理常见安装位置下的 `mmd-cli` 二进制。
|
|
25
|
+
|
|
26
|
+
`mmd-cli` 运行时仍需要系统已有 Chrome/Chromium;如果机器完全没有浏览器,可在上传时传 `--mermaid none`,保留 Mermaid 代码块。
|
|
27
|
+
|
|
24
28
|
安装/更新入口:
|
|
25
29
|
|
|
26
30
|
```bash
|
|
@@ -32,7 +36,7 @@ confluence-reader list
|
|
|
32
36
|
confluence-writer list
|
|
33
37
|
```
|
|
34
38
|
|
|
35
|
-
> `install` / `update`
|
|
39
|
+
> `install` / `update` 默认走 `vercel-labs/skills` 推荐的项目级安装(`cwd` 下 agent skills 目录,兼容所有 agent,包括不支持全局的 PromptScript)。需要 user-level 全局时显式传 `--skill-global`(仅当 agent 支持,如 Claude Code / Cursor / OpenCode)。`confluence uninstall --confirm true` 会同时清理项目级与全局级残留。
|
|
36
40
|
|
|
37
41
|
卸载入口(默认仅打印卸载计划,真实执行需显式确认):
|
|
38
42
|
|
|
@@ -132,7 +136,7 @@ CONFLUENCE_SKIP_UPDATE_CHECK=true
|
|
|
132
136
|
- Confluence 7.13.7 全量 REST API 端点注册与通用调用
|
|
133
137
|
- MCP 页面/子页/评论/标签能力的语义化 CLI 命令
|
|
134
138
|
- Markdown 转 Confluence Wiki Markup
|
|
135
|
-
- Markdown/HTML 上传时默认用 `
|
|
139
|
+
- Markdown/HTML 上传时默认用 `mmd-cli` 将 Mermaid 渲染为 PNG 附件并以内置图片宏展示,必要时可用 `--mermaid none` 保留原代码块
|
|
136
140
|
- mark 风格 metadata 生成
|
|
137
141
|
- Markdown 上传预览、确认写入和附件上传
|
|
138
142
|
- 页面下载为带 frontmatter 的 Markdown,并可下载附件和一层子页
|
|
@@ -143,7 +147,7 @@ CONFLUENCE_SKIP_UPDATE_CHECK=true
|
|
|
143
147
|
|
|
144
148
|
`.opencode/opencode.json` 提供了两个项目级 OpenCode 命令:
|
|
145
149
|
|
|
146
|
-
- `release`:复刻 zentao-cli 的 `/release` 流程,按
|
|
150
|
+
- `release`:复刻 zentao-cli 的 `/release` 流程,按 14 步固定顺序准备发布;默认手动发包,**未经再次授权不会执行 `npm publish`、`git push`、打 tag 或创建 GitHub Release**。
|
|
147
151
|
- `smoke`:检查当前 CLI 的烟测与验证入口(`pnpm release:smoke-query --dry-run`、`pnpm typecheck`、`pnpm build` 等)。
|
|
148
152
|
|
|
149
153
|
修改 `.opencode/opencode.json` 后,需要退出并重启 OpenCode 才能生效。
|
package/dist/core/cli-output.js
CHANGED
|
@@ -126,15 +126,16 @@ export function getBuiltinCommandHelp(commandName) {
|
|
|
126
126
|
"confluence install",
|
|
127
127
|
"",
|
|
128
128
|
"用法:",
|
|
129
|
-
" confluence install [--skill-source local|git|npm] [--skill-local-path <path>] [--skip-config-check] [--cli-only] [--skill-only]",
|
|
129
|
+
" confluence install [--skill-source local|git|npm] [--skill-local-path <path>] [--skill-global] [--skip-config-check] [--cli-only] [--skill-only]",
|
|
130
130
|
" npx -y @cloudglab/confluence-cli@latest install",
|
|
131
131
|
"",
|
|
132
132
|
"说明:",
|
|
133
|
-
" 安装或更新 CLI,并按来源安装 Confluence skill
|
|
133
|
+
" 安装或更新 CLI,并按来源安装 Confluence skill。默认走 vercel-labs/skills 推荐的项目级(cwd 下 agent skills 目录),兼容所有 agent;需要 user-level 全局时显式传 --skill-global(需 agent 支持)。",
|
|
134
134
|
"",
|
|
135
135
|
"参数:",
|
|
136
136
|
" --skill-source <local|git|npm> (可选):skill 安装来源,默认 local。",
|
|
137
137
|
" --skill-local-path <string> (可选):直接从本地目录安装 skill。",
|
|
138
|
+
" --skill-global (可选):将 skill 装到 user-level 全局目录;不支持的 agent(如 PromptScript)会失败。",
|
|
138
139
|
" --skip-config-check (可选):安装后跳过 Confluence 配置校验。",
|
|
139
140
|
" --cli-only (可选):只安装 CLI,不安装 skill。",
|
|
140
141
|
" --skill-only (可选):只安装 skill,不安装 CLI。",
|
|
@@ -143,15 +144,16 @@ export function getBuiltinCommandHelp(commandName) {
|
|
|
143
144
|
"confluence update",
|
|
144
145
|
"",
|
|
145
146
|
"用法:",
|
|
146
|
-
" confluence update [--skill-source local|git|npm] [--skill-local-path <path>] [--skip-config-check] [--cli-only] [--skill-only]",
|
|
147
|
+
" confluence update [--skill-source local|git|npm] [--skill-local-path <path>] [--skill-global] [--skip-config-check] [--cli-only] [--skill-only]",
|
|
147
148
|
" npx -y @cloudglab/confluence-cli@latest update",
|
|
148
149
|
"",
|
|
149
150
|
"说明:",
|
|
150
|
-
" 更新或重新安装 CLI,并按来源更新 Confluence skill。",
|
|
151
|
+
" 更新或重新安装 CLI,并按来源更新 Confluence skill。默认走项目级,--skill-global 同 install。",
|
|
151
152
|
"",
|
|
152
153
|
"参数:",
|
|
153
154
|
" --skill-source <local|git|npm> (可选):skill 更新来源,默认 local。",
|
|
154
155
|
" --skill-local-path <string> (可选):直接从本地目录更新 skill。",
|
|
156
|
+
" --skill-global (可选):将 skill 装到 user-level 全局目录;不支持的 agent 会失败。",
|
|
155
157
|
" --skip-config-check (可选):更新后跳过 Confluence 配置校验。",
|
|
156
158
|
" --cli-only (可选):只更新 CLI,不更新 skill。",
|
|
157
159
|
" --skill-only (可选):只更新 skill,不更新 CLI。",
|
package/dist/install.js
CHANGED
|
@@ -7,6 +7,7 @@ import { loadConfluenceConfig, normalizeConfig, saveConfig } from "./core/config
|
|
|
7
7
|
import { writeUpdateCacheAfterInstall } from "./update-probe.js";
|
|
8
8
|
const PACKAGE_NAME = "@cloudglab/confluence-cli";
|
|
9
9
|
const GIT_SKILL_SOURCE = "cloudglab/confluence-cli";
|
|
10
|
+
const MMD_CLI_INSTALL_URL = "https://raw.githubusercontent.com/coolamit/mermaid-cli/master/install.sh";
|
|
10
11
|
export async function runInstallCommand(args = []) {
|
|
11
12
|
const options = parseInstallOptions(args);
|
|
12
13
|
await installPackageAndSkill("安装", options);
|
|
@@ -55,6 +56,8 @@ function printSuccessGuide(action, status) {
|
|
|
55
56
|
常用配置:
|
|
56
57
|
confluence update 更新 CLI 和 Skill
|
|
57
58
|
confluence install --skip-config-check 仅安装,跳过配置校验
|
|
59
|
+
confluence install --skill-global 把 skill 装到 user-level 全局目录
|
|
60
|
+
mmd-cli --version 检查 Mermaid 渲染器
|
|
58
61
|
CONFLUENCE_DISABLE_WRITE=true 禁用真实写操作
|
|
59
62
|
|
|
60
63
|
写操作提示:真实写入仍需显式传 confirm=true。
|
|
@@ -63,6 +66,7 @@ function printSuccessGuide(action, status) {
|
|
|
63
66
|
function parseInstallOptions(args) {
|
|
64
67
|
let skillSource = "local";
|
|
65
68
|
let skillLocalPath;
|
|
69
|
+
let skillGlobal = false;
|
|
66
70
|
let skipConfigCheck = false;
|
|
67
71
|
let cliOnly = false;
|
|
68
72
|
let skillOnly = false;
|
|
@@ -84,6 +88,12 @@ function parseInstallOptions(args) {
|
|
|
84
88
|
index += 1;
|
|
85
89
|
continue;
|
|
86
90
|
}
|
|
91
|
+
if (arg === "--skill-global" || arg.startsWith("--skill-global=")) {
|
|
92
|
+
const parsed = readBooleanFlag(args, index, "--skill-global");
|
|
93
|
+
skillGlobal = parsed.value;
|
|
94
|
+
index += parsed.consumedArgs;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
87
97
|
if (arg === "--skip-config-check" || arg.startsWith("--skip-config-check=")) {
|
|
88
98
|
const parsed = readBooleanFlag(args, index, "--skip-config-check");
|
|
89
99
|
skipConfigCheck = parsed.value;
|
|
@@ -107,7 +117,7 @@ function parseInstallOptions(args) {
|
|
|
107
117
|
if (cliOnly && skillOnly) {
|
|
108
118
|
throw new Error("--cli-only 和 --skill-only 不能同时使用");
|
|
109
119
|
}
|
|
110
|
-
return { skillSource, skillLocalPath, skipConfigCheck, cliOnly, skillOnly };
|
|
120
|
+
return { skillSource, skillLocalPath, skillGlobal, skipConfigCheck, cliOnly, skillOnly };
|
|
111
121
|
}
|
|
112
122
|
function parseUninstallOptions(args) {
|
|
113
123
|
let confirm = false;
|
|
@@ -150,7 +160,7 @@ function parseUninstallOptions(args) {
|
|
|
150
160
|
function printUninstallPreview(options) {
|
|
151
161
|
const steps = [
|
|
152
162
|
...(!options.cliOnly ? ["卸载 confluence skill(项目级和全局级)"] : []),
|
|
153
|
-
...(!options.skillOnly ? ["卸载全局 CLI
|
|
163
|
+
...(!options.skillOnly ? ["卸载全局 CLI 包、清理 npm 残留目录,并删除 mmd-cli 二进制"] : []),
|
|
154
164
|
...(shouldRemoveConfig(options) ? ["删除 ~/.confluence/config.json"] : ["保留 ~/.confluence/config.json"]),
|
|
155
165
|
];
|
|
156
166
|
process.stdout.write(`卸载预览:\n${steps.map((step) => ` - ${step}`).join("\n")}\n\n真实执行请运行:\n confluence uninstall --confirm true\n npx -y ${PACKAGE_NAME}@latest uninstall --confirm true\n\n可选参数:\n --keep-config true 保留 Confluence 配置\n --cli-only true 只卸载 CLI\n --skill-only true 只卸载 skill\n`);
|
|
@@ -158,11 +168,11 @@ function printUninstallPreview(options) {
|
|
|
158
168
|
function shouldRemoveConfig(options) {
|
|
159
169
|
return !options.keepConfig && !options.cliOnly && !options.skillOnly;
|
|
160
170
|
}
|
|
161
|
-
function createSkillAddArgs(source) {
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
return ["-y", "skills", "add", source, "--global", "--yes"];
|
|
171
|
+
function createSkillAddArgs(source, global = false) {
|
|
172
|
+
// 默认走 vercel-labs/skills 推荐的项目级(cwd 下 agent skills 目录),
|
|
173
|
+
// 兼容所有 agent(包括不支持 --global 的,如 PromptScript)。
|
|
174
|
+
// 用户明确需要 user-level 全局时再通过 --skill-global 显式开启。
|
|
175
|
+
return ["-y", "skills", "add", source, ...(global ? ["--global"] : []), "--yes"];
|
|
166
176
|
}
|
|
167
177
|
function createSkillRemoveArgs(global = false) {
|
|
168
178
|
return ["-y", "skills", "remove", "confluence-cli", "--yes", ...(global ? ["--global"] : [])];
|
|
@@ -214,6 +224,7 @@ async function installPackageAndSkill(action, options) {
|
|
|
214
224
|
if (!options.skillOnly) {
|
|
215
225
|
await cleanupGlobalPackageResidues();
|
|
216
226
|
await installGlobalCli(action);
|
|
227
|
+
await installMmdCli(action);
|
|
217
228
|
}
|
|
218
229
|
if (!options.cliOnly) {
|
|
219
230
|
await installSkill(action, options);
|
|
@@ -234,6 +245,9 @@ async function installGlobalCli(action) {
|
|
|
234
245
|
await runStep(`${action} Confluence CLI`, "npm", args);
|
|
235
246
|
}
|
|
236
247
|
}
|
|
248
|
+
async function installMmdCli(action) {
|
|
249
|
+
await runStep(`${action} Mermaid 原生渲染器 mmd-cli`, "sh", ["-c", `curl -fsSL ${MMD_CLI_INSTALL_URL} | sh`]);
|
|
250
|
+
}
|
|
237
251
|
function isNpmDirectoryNotEmptyError(error) {
|
|
238
252
|
const message = error instanceof Error ? error.message : String(error);
|
|
239
253
|
return message.includes("ENOTEMPTY") || message.toLowerCase().includes("directory not empty");
|
|
@@ -253,20 +267,20 @@ async function runNpxStepWithRetry(title, args) {
|
|
|
253
267
|
}
|
|
254
268
|
async function installSkill(action, options) {
|
|
255
269
|
if (options.skillLocalPath) {
|
|
256
|
-
await runNpxStepWithRetry(`${action} Confluence skill`, createSkillAddArgs(path.resolve(options.skillLocalPath)));
|
|
270
|
+
await runNpxStepWithRetry(`${action} Confluence skill`, createSkillAddArgs(path.resolve(options.skillLocalPath), options.skillGlobal));
|
|
257
271
|
return;
|
|
258
272
|
}
|
|
259
273
|
if (options.skillSource === "local") {
|
|
260
|
-
await installSkillFromInstalledPackage(action);
|
|
274
|
+
await installSkillFromInstalledPackage(action, options.skillGlobal);
|
|
261
275
|
return;
|
|
262
276
|
}
|
|
263
277
|
if (options.skillSource === "git") {
|
|
264
|
-
await runNpxStepWithRetry(`${action} Confluence skill`, createSkillAddArgs(GIT_SKILL_SOURCE));
|
|
278
|
+
await runNpxStepWithRetry(`${action} Confluence skill`, createSkillAddArgs(GIT_SKILL_SOURCE, options.skillGlobal));
|
|
265
279
|
return;
|
|
266
280
|
}
|
|
267
|
-
await installSkillFromNpmPackage(action);
|
|
281
|
+
await installSkillFromNpmPackage(action, options.skillGlobal);
|
|
268
282
|
}
|
|
269
|
-
async function installSkillFromInstalledPackage(action) {
|
|
283
|
+
async function installSkillFromInstalledPackage(action, skillGlobal) {
|
|
270
284
|
const skillPath = await getInstalledPackageSkillPath();
|
|
271
285
|
try {
|
|
272
286
|
await access(skillPath);
|
|
@@ -274,7 +288,7 @@ async function installSkillFromInstalledPackage(action) {
|
|
|
274
288
|
catch {
|
|
275
289
|
throw new Error(`未找到已安装包内的 Confluence skill:${skillPath}。可重试 --skill-source npm 或 --skill-source git。`);
|
|
276
290
|
}
|
|
277
|
-
await runNpxStepWithRetry(`${action} Confluence skill`, createSkillAddArgs(skillPath));
|
|
291
|
+
await runNpxStepWithRetry(`${action} Confluence skill`, createSkillAddArgs(skillPath, skillGlobal));
|
|
278
292
|
}
|
|
279
293
|
async function getInstalledPackageSkillPath() {
|
|
280
294
|
const globalNodeModules = (await runCommandOutput("npm", ["root", "-g"])).trim();
|
|
@@ -282,7 +296,7 @@ async function getInstalledPackageSkillPath() {
|
|
|
282
296
|
throw new Error("npm root -g 没有返回全局 node_modules 路径");
|
|
283
297
|
return path.join(globalNodeModules, PACKAGE_NAME, "skills", "confluence-cli");
|
|
284
298
|
}
|
|
285
|
-
async function installSkillFromNpmPackage(action) {
|
|
299
|
+
async function installSkillFromNpmPackage(action, skillGlobal) {
|
|
286
300
|
const tempDir = await mkdtemp(path.join(os.tmpdir(), "confluence-cli-skill-"));
|
|
287
301
|
try {
|
|
288
302
|
const stdout = await runCommandOutput("npm", ["pack", `${PACKAGE_NAME}@latest`, "--pack-destination", tempDir, "--silent"]);
|
|
@@ -290,7 +304,7 @@ async function installSkillFromNpmPackage(action) {
|
|
|
290
304
|
if (!tarballName)
|
|
291
305
|
throw new Error("npm pack 没有返回包文件名");
|
|
292
306
|
await runStep("解压 Confluence npm 包", "tar", ["-xzf", path.join(tempDir, tarballName), "-C", tempDir]);
|
|
293
|
-
await runNpxStepWithRetry(`${action} Confluence skill`, createSkillAddArgs(path.join(tempDir, "package")));
|
|
307
|
+
await runNpxStepWithRetry(`${action} Confluence skill`, createSkillAddArgs(path.join(tempDir, "package"), skillGlobal));
|
|
294
308
|
}
|
|
295
309
|
finally {
|
|
296
310
|
await rm(tempDir, { recursive: true, force: true });
|
|
@@ -303,6 +317,11 @@ async function uninstallSkill() {
|
|
|
303
317
|
async function uninstallPackage() {
|
|
304
318
|
await runStep("卸载 Confluence CLI", "npm", ["uninstall", "-g", PACKAGE_NAME]);
|
|
305
319
|
await cleanupGlobalPackageResidues();
|
|
320
|
+
await removeMmdCliBinary();
|
|
321
|
+
}
|
|
322
|
+
async function removeMmdCliBinary() {
|
|
323
|
+
await rm(path.join(os.homedir(), ".local", "bin", "mmd-cli"), { force: true });
|
|
324
|
+
await rm("/usr/local/bin/mmd-cli", { force: true });
|
|
306
325
|
}
|
|
307
326
|
async function cleanupGlobalPackageResidues() {
|
|
308
327
|
const globalNodeModules = (await runCommandOutput("npm", ["root", "-g"])).trim();
|
|
@@ -362,7 +381,7 @@ async function runStep(title, command, args) {
|
|
|
362
381
|
}
|
|
363
382
|
function runCommand(command, args) {
|
|
364
383
|
return new Promise((resolve, reject) => {
|
|
365
|
-
const child = spawn(command, args, { shell: process.platform === "win32" });
|
|
384
|
+
const child = spawn(command, args, { shell: process.platform === "win32", env: createInstallEnv() });
|
|
366
385
|
let stderr = "";
|
|
367
386
|
child.stdout?.pipe(process.stdout);
|
|
368
387
|
child.stderr?.on("data", (chunk) => {
|
|
@@ -381,7 +400,7 @@ function runCommand(command, args) {
|
|
|
381
400
|
}
|
|
382
401
|
function runCommandOutput(command, args) {
|
|
383
402
|
return new Promise((resolve, reject) => {
|
|
384
|
-
const child = spawn(command, args, { shell: process.platform === "win32" });
|
|
403
|
+
const child = spawn(command, args, { shell: process.platform === "win32", env: createInstallEnv() });
|
|
385
404
|
let stdout = "";
|
|
386
405
|
let stderr = "";
|
|
387
406
|
child.stdout?.on("data", (chunk) => { stdout += chunk.toString("utf8"); });
|
|
@@ -396,6 +415,12 @@ function runCommandOutput(command, args) {
|
|
|
396
415
|
});
|
|
397
416
|
});
|
|
398
417
|
}
|
|
418
|
+
function createInstallEnv() {
|
|
419
|
+
return {
|
|
420
|
+
...process.env,
|
|
421
|
+
CI: process.env.CI ?? "true",
|
|
422
|
+
};
|
|
423
|
+
}
|
|
399
424
|
function renderBanner() {
|
|
400
425
|
return [
|
|
401
426
|
" ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ",
|
package/dist/manifest.json
CHANGED
package/dist/tools/install.js
CHANGED
|
@@ -4,6 +4,7 @@ import { jsonResult } from "../utils/result.js";
|
|
|
4
4
|
const installSchema = z.object({
|
|
5
5
|
"skill-source": z.enum(["local", "git", "npm"]).optional().default("local").describe("技能来源"),
|
|
6
6
|
"skill-local-path": z.string().optional().describe("本地 skill 目录"),
|
|
7
|
+
"skill-global": z.boolean().optional().default(false).describe("将 skill 装到 user-level 全局目录(需 agent 支持)"),
|
|
7
8
|
"skip-config-check": z.boolean().optional().default(false).describe("跳过配置校验"),
|
|
8
9
|
"cli-only": z.boolean().optional().default(false).describe("只安装 CLI"),
|
|
9
10
|
"skill-only": z.boolean().optional().default(false).describe("只安装 skill"),
|
package/dist/tools/transfer.js
CHANGED
|
@@ -171,10 +171,9 @@ function applyMermaidImageMacros(body, generatedFiles, uploadedAttachments) {
|
|
|
171
171
|
for (let index = 0; index < generatedFiles.length; index += 1) {
|
|
172
172
|
const generated = generatedFiles[index];
|
|
173
173
|
const uploaded = uploadedAttachments[index];
|
|
174
|
-
const attachment = readUploadedAttachment(uploaded?.result);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const macro = buildImageMacro(attachment.title ?? generated.attachmentName);
|
|
174
|
+
const attachment = readUploadedAttachment(uploaded?.result, generated.attachmentName);
|
|
175
|
+
const filename = attachment?.title ?? generated.attachmentName;
|
|
176
|
+
const macro = buildImageMacro(filename);
|
|
178
177
|
output = output.replaceAll(`<p>${generated.marker}</p>`, macro).replaceAll(generated.marker, macro);
|
|
179
178
|
}
|
|
180
179
|
return output;
|
|
@@ -182,11 +181,17 @@ function applyMermaidImageMacros(body, generatedFiles, uploadedAttachments) {
|
|
|
182
181
|
function buildImageMacro(filename) {
|
|
183
182
|
return `<ac:image><ri:attachment ri:filename="${escapeXml(filename)}" /></ac:image>`;
|
|
184
183
|
}
|
|
185
|
-
function readUploadedAttachment(value) {
|
|
184
|
+
function readUploadedAttachment(value, expectedTitle) {
|
|
186
185
|
if (typeof value !== "object" || value === null)
|
|
187
186
|
return undefined;
|
|
188
187
|
if ("results" in value && Array.isArray(value.results)) {
|
|
189
|
-
|
|
188
|
+
const list = value.results ?? [];
|
|
189
|
+
if (expectedTitle) {
|
|
190
|
+
const matched = list.find((entry) => entry?.title === expectedTitle);
|
|
191
|
+
if (matched)
|
|
192
|
+
return matched;
|
|
193
|
+
}
|
|
194
|
+
return list[0];
|
|
190
195
|
}
|
|
191
196
|
if ("id" in value)
|
|
192
197
|
return value;
|
|
@@ -377,29 +382,29 @@ function createMermaidFile(mermaidSource, pageTitle, sourceFile, idx, renderKind
|
|
|
377
382
|
function renderMermaidFile(mermaidSource, outputFile, renderKind) {
|
|
378
383
|
const inputFile = join(dirname(outputFile), `${basename(outputFile, extname(outputFile))}.mmd`);
|
|
379
384
|
writeFileSync(inputFile, mermaidSource, "utf8");
|
|
380
|
-
const
|
|
385
|
+
const mmdCli = resolveMmdCliBin();
|
|
381
386
|
const args = ["-i", inputFile, "-o", outputFile, "-b", "transparent"];
|
|
382
387
|
if (renderKind === "png") {
|
|
383
|
-
args.push("
|
|
388
|
+
args.push("-s", "3");
|
|
384
389
|
}
|
|
385
390
|
try {
|
|
386
|
-
execFileSync(
|
|
391
|
+
execFileSync(mmdCli, args, { stdio: "pipe" });
|
|
387
392
|
}
|
|
388
393
|
catch (error) {
|
|
389
394
|
const message = error instanceof Error ? error.message : String(error);
|
|
390
|
-
throw new Error(`Failed to render Mermaid as ${renderKind} with
|
|
395
|
+
throw new Error(`Failed to render Mermaid as ${renderKind} with mmd-cli: ${message}`);
|
|
391
396
|
}
|
|
392
397
|
}
|
|
393
|
-
function
|
|
394
|
-
const extension = process.platform === "win32" ? ".
|
|
398
|
+
function resolveMmdCliBin() {
|
|
399
|
+
const extension = process.platform === "win32" ? ".exe" : "";
|
|
395
400
|
const candidates = [
|
|
396
|
-
join(process.
|
|
397
|
-
|
|
401
|
+
join(process.env.HOME ?? "", ".local", "bin", `mmd-cli${extension}`),
|
|
402
|
+
"/usr/local/bin/mmd-cli",
|
|
398
403
|
];
|
|
399
404
|
const found = candidates.find((candidate) => existsSync(candidate));
|
|
400
405
|
if (found)
|
|
401
406
|
return found;
|
|
402
|
-
return `
|
|
407
|
+
return `mmd-cli${extension}`;
|
|
403
408
|
}
|
|
404
409
|
function safeFileName(value) {
|
|
405
410
|
return value.replace(/[\\/:*?"<>|]/g, "_");
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.0.
|
|
1
|
+
export declare const VERSION = "0.0.4";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "0.0.
|
|
1
|
+
export const VERSION = "0.0.4";
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudglab/confluence-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Confluence REST CLI for agents and local automation",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
"prepare": "node scripts/prepare.mjs"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@mermaid-js/mermaid-cli": "^11.15.0",
|
|
42
41
|
"@whitebite/diagram-converter": "^0.2.0",
|
|
43
42
|
"axios": "^1.7.9",
|
|
44
43
|
"marked": "^18.0.5",
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: confluence-cli
|
|
3
|
-
description: Use this CLI for Confluence REST operations from a terminal or agent workflow. Triggers on Confluence page search, read, upload (Markdown/HTML with Mermaid + TOC), download, labels, attachments, comments, and Confluence 7.13.7 REST pass-through.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Confluence CLI Skill
|
|
7
|
-
|
|
8
|
-
Use this CLI when a task needs Confluence REST operations from a terminal or agent workflow.
|
|
9
|
-
|
|
10
|
-
Start with these references when you need details:
|
|
11
|
-
|
|
12
|
-
- `reference/overview.md`:整体工作流与安全原则
|
|
13
|
-
- `reference/commands.md`:命令速查
|
|
14
|
-
- `reference/cli.md`:安装、更新、角色入口和环境变量
|
|
15
|
-
- `reference/content.md`:页面查询、读取、子页、评论、标签
|
|
16
|
-
- `reference/transfer.md`:Markdown/HTML 发布、下载、附件、Mermaid/TOC
|
|
17
|
-
- `reference/rest.md`:Confluence 7.13.7 REST 端点透传
|
|
18
|
-
- `../../docs/release.md`:发布前检查与 npm 发布流程
|
|
19
|
-
|
|
20
|
-
## Decision Matrix
|
|
21
|
-
|
|
22
|
-
- Read/search small content: `confluence searchContent` or `confluence getContent`.
|
|
23
|
-
- Convert Markdown locally: `confluence convertMarkdownToWiki`.
|
|
24
|
-
- Generate mark metadata: `confluence generateMarkMetadata`.
|
|
25
|
-
- Upload large Markdown through REST: `confluence uploadMarkdown --toc --confirm true`.
|
|
26
|
-
- Upload raw HTML through REST: `confluence uploadHtml --toc --confirm true`.
|
|
27
|
-
- For full page publishes or republish flows, include `--toc` by default; only omit it when the user explicitly says no TOC.
|
|
28
|
-
- Upload Markdown with attachments: `confluence uploadMarkdown --attachments '["a.png"]' --toc --confirm true`.
|
|
29
|
-
- Dry-run uploads first: omit `--confirm true`.
|
|
30
|
-
- Render Mermaid on the fly: any ```mermaid fence in Markdown/HTML auto-generates PNG attachments by default.
|
|
31
|
-
- Download editable backup: `confluence downloadPage`.
|
|
32
|
-
- Download page with attachments/children: `confluence downloadPage --downloadAttachments true --downloadChildren true`.
|
|
33
|
-
- Use MCP-style page tools: `getPageChildren`, `getComments`, `addComment`, `getLabels`, `addLabels`.
|
|
34
|
-
- Use attachment tools: `listAttachments`, `uploadAttachment`, `updateAttachment`, `downloadAttachment`.
|
|
35
|
-
- Check PAT identity: `confluence getCurrentUser`.
|
|
36
|
-
|
|
37
|
-
## Safety
|
|
38
|
-
|
|
39
|
-
All writes must pass `--confirm true`. Without confirmation, upload, delete, label, comment and attachment write commands return a dry-run preview.
|
|
40
|
-
|
|
41
|
-
## CQL Examples
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
confluence searchContent --cql 'space = "DEV" AND text ~ "API"'
|
|
45
|
-
confluence searchContent --cql 'type = page AND title ~ "Runbook"'
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Upload Patterns
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
# Markdown → Confluence,自动 Mermaid → PNG 附件图片,默认注入双 TOC 宏
|
|
52
|
-
confluence uploadMarkdown --file doc.md --id 142552620 --toc --tocMaxLevel 3 --confirm true
|
|
53
|
-
|
|
54
|
-
# 保持原代码块不渲染
|
|
55
|
-
confluence uploadMarkdown --file doc.md --id 142552620 --mermaid none --toc --confirm true
|
|
56
|
-
|
|
57
|
-
# HTML → Confluence,同样支持Mermaid和TOC
|
|
58
|
-
confluence uploadHtml --file page.html --space DEV --toc --confirm true
|
|
59
|
-
|
|
60
|
-
# 只预览(dry-run)
|
|
61
|
-
confluence uploadMarkdown --file doc.md --id 142552620 --toc
|
|
62
|
-
confluence uploadHtml --file page.html --space DEV --toc
|
|
63
|
-
```
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# CLI
|
|
2
|
-
|
|
3
|
-
## 安装与更新
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
confluence install --skip-config-check true
|
|
7
|
-
confluence update --skip-config-check true
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
可选参数:
|
|
11
|
-
|
|
12
|
-
- `--skill-source local|git|npm`
|
|
13
|
-
- `--skill-local-path <dir>`
|
|
14
|
-
- `--cli-only true|false`
|
|
15
|
-
- `--skill-only true|false`
|
|
16
|
-
- `--skip-config-check true|false`
|
|
17
|
-
|
|
18
|
-
## 角色入口
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
confluence list
|
|
22
|
-
confluence-reader list
|
|
23
|
-
confluence-writer list
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
- `confluence`:完整入口。
|
|
27
|
-
- `confluence-reader`:不注册发布上传类 transfer 命令。
|
|
28
|
-
- `confluence-writer`:注册写入和发布命令,但仍需要 `--confirm true`。
|
|
29
|
-
|
|
30
|
-
## 环境变量
|
|
31
|
-
|
|
32
|
-
- `CONFLUENCE_URL`
|
|
33
|
-
- `CONFLUENCE_PAT` 或 `CONFLUENCE_PERSONAL_TOKEN`
|
|
34
|
-
- `CONFLUENCE_USERNAME` + `CONFLUENCE_PASSWORD`
|
|
35
|
-
- `CONFLUENCE_DISABLE_WRITE=true`
|
|
36
|
-
- `CONFLUENCE_SKIP_UPDATE_CHECK=true`
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# 命令速查
|
|
2
|
-
|
|
3
|
-
## 基础
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
confluence help
|
|
7
|
-
confluence list
|
|
8
|
-
confluence version
|
|
9
|
-
confluence help searchContent
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## 配置
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
confluence initConfluence --url https://confluence.example.com --pat TOKEN --save true
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## 查询
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
confluence searchContent --cql 'space = "DEV" AND text ~ "API"'
|
|
22
|
-
confluence getContent --id 123456
|
|
23
|
-
confluence findContent --space DEV --title "API Guide"
|
|
24
|
-
confluence getPageChildren --id 123456 --type page
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## 发布与下载
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
confluence uploadMarkdown --file docs/page.md --space DEV --toc --confirm false
|
|
31
|
-
confluence uploadMarkdown --file docs/page.md --id 123456 --attachments '["docs/a.png"]' --toc --confirm true
|
|
32
|
-
confluence uploadHtml --file docs/page.html --space DEV --toc --confirm true
|
|
33
|
-
confluence downloadPage --id 123456 --outputDir exports --downloadAttachments true --downloadChildren true
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## REST 透传
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
confluence listRestApis --group content --limit 20
|
|
40
|
-
confluence callRestApi --method GET --path '/content/{id}' --pathParams '{"id":"123456"}' --query '{"expand":"body.storage,version"}'
|
|
41
|
-
```
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# 内容操作
|
|
2
|
-
|
|
3
|
-
## 查询页面
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
confluence searchContent --cql 'type = page AND title ~ "Runbook"'
|
|
7
|
-
confluence findContent --space DEV --title "Runbook"
|
|
8
|
-
confluence getContent --id 123456
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## 子页、评论、标签
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
confluence getPageChildren --id 123456 --type page
|
|
15
|
-
confluence getComments --id 123456
|
|
16
|
-
confluence addComment --id 123456 --text "LGTM" --confirm true
|
|
17
|
-
confluence getLabels --id 123456
|
|
18
|
-
confluence addLabels --id 123456 --labels '["api","docs"]' --confirm true
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## 安全原则
|
|
22
|
-
|
|
23
|
-
所有删除、评论、标签等写命令都必须显式 `--confirm true`;不传确认时只返回 preview。
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# 总览
|
|
2
|
-
|
|
3
|
-
## 这个 skill 做什么
|
|
4
|
-
|
|
5
|
-
- 用命令行方式操作 Confluence Server/Data Center REST API。
|
|
6
|
-
- 默认写操作只 preview,真实写入必须显式 `--confirm true`。
|
|
7
|
-
- 支持页面搜索、读取、评论、标签、附件、Markdown/HTML 发布、页面下载和 REST 端点透传。
|
|
8
|
-
|
|
9
|
-
## 推荐工作流
|
|
10
|
-
|
|
11
|
-
1. 先确认本机是否安装 `confluence`。
|
|
12
|
-
2. 如果没有,优先运行 `confluence install --skip-config-check true`。
|
|
13
|
-
3. 对命令参数不确定时,先运行 `confluence help <command>` 校对。
|
|
14
|
-
4. 查询类任务优先用 `searchContent`、`getContent`、`findContent`。
|
|
15
|
-
5. 发布类任务优先 dry-run,再加 `--confirm true`。
|
|
16
|
-
6. Markdown/HTML 全量发布默认加 `--toc`,除非用户明确不要目录。
|
|
17
|
-
7. 自动化环境可设置 `CONFLUENCE_DISABLE_WRITE=true` 彻底禁用真实写入。
|
|
18
|
-
|
|
19
|
-
## 适合谁
|
|
20
|
-
|
|
21
|
-
- 需要命令行操作 Confluence 的人。
|
|
22
|
-
- 需要把 Confluence 接入智能体的人。
|
|
23
|
-
- 需要在 Confluence 7.13.7 环境下稳定自动化的人。
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# REST 透传
|
|
2
|
-
|
|
3
|
-
`listRestApis` 和 `callRestApi` 用于覆盖 Confluence 7.13.7 官方 REST 端点。
|
|
4
|
-
|
|
5
|
-
## 查看端点
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
confluence listRestApis --limit 20
|
|
9
|
-
confluence listRestApis --group content --limit 20
|
|
10
|
-
confluence listRestApis --method GET --write false --limit 20
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## 调用端点
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
confluence callRestApi --method GET --path '/content/{id}' --pathParams '{"id":"123456"}' --query '{"expand":"body.storage,version"}'
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
写 REST 端点仍受 `--confirm true` 和 `CONFLUENCE_DISABLE_WRITE=true` 保护。
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# 发布与下载
|
|
2
|
-
|
|
3
|
-
## Markdown 发布
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
confluence uploadMarkdown --file docs/page.md --space DEV --toc --confirm false
|
|
7
|
-
confluence uploadMarkdown --file docs/page.md --id 123456 --toc --confirm true
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
## HTML 发布
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
confluence uploadHtml --file docs/page.html --space DEV --toc --confirm false
|
|
14
|
-
confluence uploadHtml --file docs/page.html --id 123456 --toc --confirm true
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Mermaid 与附件
|
|
18
|
-
|
|
19
|
-
- 默认将 Markdown/HTML 中的 Mermaid 渲染为 PNG 附件并插入图片宏。
|
|
20
|
-
- 如需保留原代码块,使用 `--mermaid none`。
|
|
21
|
-
- 附件用 JSON 数组传入:`--attachments '["docs/a.png"]'`。
|
|
22
|
-
|
|
23
|
-
## 下载
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
confluence downloadPage --id 123456 --outputDir exports --downloadAttachments true --downloadChildren true
|
|
27
|
-
```
|