@cloudglab/confluence-cli 0.0.3 → 0.0.5
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 +35 -0
- package/README.md +11 -2
- package/dist/install.js +30 -4
- package/dist/manifest.json +1 -1
- 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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.0.5 - 2026-06-17
|
|
6
|
+
|
|
7
|
+
### 修复
|
|
8
|
+
|
|
9
|
+
- `install` / `update` 链路:把仓库内 `skills/confluence-cli` 从指向 `.agents/skills/confluence-cli` 的符号链接替换为真实目录副本,避免 npm tarball 中 `skills/confluence-cli` 路径在用户机器上不可用导致“未找到已安装包内的 Confluence skill”错误。
|
|
10
|
+
- `install` / `update` 链路:`installMmdCli` 不再因 `curl -fsSL ... | sh` 网络失败而中断整个安装,改为捕获异常并输出 `已跳过 mmd-cli 安装:<原因>` 与后续 `--mermaid none` 退路提示。
|
|
11
|
+
- `install` / `update` 链路:`installSkillFromInstalledPackage` 在 `access` 失败时不再直接抛错,自动回退到 `installSkillFromNpmPackage`(`npm pack` + `tar -xzf` + `npx -y skills add`),覆盖包内 skill 缺失场景。
|
|
12
|
+
|
|
13
|
+
### 测试
|
|
14
|
+
|
|
15
|
+
- `tests/install.test.ts` 新增回归用例 `本地 skill 缺失时自动回退到 npm 包解压安装,mmd-cli 失败不阻断安装`:mock `curl` 退出码 35、stderr 含 `curl: (35) LibreSSL SSL_connect...`,断言安装链路按 `npm install -g` → 跳过 `mmd-cli` → `npm pack` → `tar` → `npx -y skills add` 顺序完成,并校验 stdout 中包含“已跳过 mmd-cli 安装”与“正在自动回退到 npm 包解压安装”两行提示。
|
|
16
|
+
|
|
17
|
+
### 说明
|
|
18
|
+
|
|
19
|
+
- 本次热修不改变 `mmd-cli` 运行时仍需系统 Chrome/Chromium 的前提;网络环境下无法自动安装 `mmd-cli` 时,建议用户改用 `--mermaid none` 保留代码块。
|
|
20
|
+
- 验证结果:`pnpm test -- tests/install.test.ts tests/skill.test.ts tests/tools/transfer.test.ts` 全部通过(3 个文件、10 个测试)。
|
|
21
|
+
|
|
22
|
+
## 0.0.4 - 2026-06-17
|
|
23
|
+
|
|
24
|
+
### 修复
|
|
25
|
+
|
|
26
|
+
- Mermaid 渲染器从 `@mermaid-js/mermaid-cli` 全量替换为 `coolamit/mermaid-cli` 的原生二进制 `mmd-cli`,不再保留 `mmdc` / Puppeteer 兼容路径。
|
|
27
|
+
- `install` / `update` 链路会自动执行上游 `mmd-cli` 安装脚本,避免 npm 安装阶段拉取 Chrome 失败。
|
|
28
|
+
- `uninstall` 链路会一并清理 `~/.local/bin/mmd-cli` 和 `/usr/local/bin/mmd-cli`。
|
|
29
|
+
- `uploadMarkdown` 的 Mermaid 附件匹配逻辑改为优先按预期文件名命中,减少多附件场景下图片宏指向错误的问题。
|
|
30
|
+
|
|
31
|
+
### 测试
|
|
32
|
+
|
|
33
|
+
- `tests/install.test.ts` 新增 `mmd-cli` 安装步骤断言,覆盖 install / update 流程。
|
|
34
|
+
- `tests/tools/transfer.test.ts` 新增 Mermaid 渲染调用测试,校验 `mmd-cli` 的输入、输出、背景和缩放参数。
|
|
35
|
+
|
|
36
|
+
### 说明
|
|
37
|
+
|
|
38
|
+
- `mmd-cli` 运行时仍要求系统已有 Chrome/Chromium;如果目标机器没有浏览器,可在上传时传 `--mermaid none`,保留 Mermaid 代码块。
|
|
39
|
+
|
|
5
40
|
## 0.0.3 - 2026-06-16
|
|
6
41
|
|
|
7
42
|
### Fixed
|
package/README.md
CHANGED
|
@@ -21,6 +21,15 @@ 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
|
+
|
|
28
|
+
从 `0.0.5` 起,`install` / `update` 在以下两种情况会**继续完成安装**而不是中断:
|
|
29
|
+
|
|
30
|
+
- `mmd-cli` 官方安装脚本因网络问题失败时,会打印 `已跳过 mmd-cli 安装:<原因>` 与 `后续如需 Mermaid 图片渲染,可稍后重试安装,或在上传时传 --mermaid none 保留代码块。`。
|
|
31
|
+
- 全局包内 `skills/confluence-cli` 缺失时,会打印 `未找到已安装包内的 Confluence skill:<path>,正在自动回退到 npm 包解压安装...` 并自动用 `npm pack` + `tar` + `npx -y skills add` 完成 skill 安装,无需手动切换 `--skill-source npm`。
|
|
32
|
+
|
|
24
33
|
安装/更新入口:
|
|
25
34
|
|
|
26
35
|
```bash
|
|
@@ -132,7 +141,7 @@ CONFLUENCE_SKIP_UPDATE_CHECK=true
|
|
|
132
141
|
- Confluence 7.13.7 全量 REST API 端点注册与通用调用
|
|
133
142
|
- MCP 页面/子页/评论/标签能力的语义化 CLI 命令
|
|
134
143
|
- Markdown 转 Confluence Wiki Markup
|
|
135
|
-
- Markdown/HTML 上传时默认用 `
|
|
144
|
+
- Markdown/HTML 上传时默认用 `mmd-cli` 将 Mermaid 渲染为 PNG 附件并以内置图片宏展示,必要时可用 `--mermaid none` 保留原代码块
|
|
136
145
|
- mark 风格 metadata 生成
|
|
137
146
|
- Markdown 上传预览、确认写入和附件上传
|
|
138
147
|
- 页面下载为带 frontmatter 的 Markdown,并可下载附件和一层子页
|
|
@@ -143,7 +152,7 @@ CONFLUENCE_SKIP_UPDATE_CHECK=true
|
|
|
143
152
|
|
|
144
153
|
`.opencode/opencode.json` 提供了两个项目级 OpenCode 命令:
|
|
145
154
|
|
|
146
|
-
- `release`:复刻 zentao-cli 的 `/release` 流程,按
|
|
155
|
+
- `release`:复刻 zentao-cli 的 `/release` 流程,按 14 步固定顺序准备发布;默认手动发包,**未经再次授权不会执行 `npm publish`、`git push`、打 tag 或创建 GitHub Release**。
|
|
147
156
|
- `smoke`:检查当前 CLI 的烟测与验证入口(`pnpm release:smoke-query --dry-run`、`pnpm typecheck`、`pnpm build` 等)。
|
|
148
157
|
|
|
149
158
|
修改 `.opencode/opencode.json` 后,需要退出并重启 OpenCode 才能生效。
|
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);
|
|
@@ -56,6 +57,7 @@ function printSuccessGuide(action, status) {
|
|
|
56
57
|
confluence update 更新 CLI 和 Skill
|
|
57
58
|
confluence install --skip-config-check 仅安装,跳过配置校验
|
|
58
59
|
confluence install --skill-global 把 skill 装到 user-level 全局目录
|
|
60
|
+
mmd-cli --version 检查 Mermaid 渲染器
|
|
59
61
|
CONFLUENCE_DISABLE_WRITE=true 禁用真实写操作
|
|
60
62
|
|
|
61
63
|
写操作提示:真实写入仍需显式传 confirm=true。
|
|
@@ -158,7 +160,7 @@ function parseUninstallOptions(args) {
|
|
|
158
160
|
function printUninstallPreview(options) {
|
|
159
161
|
const steps = [
|
|
160
162
|
...(!options.cliOnly ? ["卸载 confluence skill(项目级和全局级)"] : []),
|
|
161
|
-
...(!options.skillOnly ? ["卸载全局 CLI
|
|
163
|
+
...(!options.skillOnly ? ["卸载全局 CLI 包、清理 npm 残留目录,并删除 mmd-cli 二进制"] : []),
|
|
162
164
|
...(shouldRemoveConfig(options) ? ["删除 ~/.confluence/config.json"] : ["保留 ~/.confluence/config.json"]),
|
|
163
165
|
];
|
|
164
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`);
|
|
@@ -222,6 +224,7 @@ async function installPackageAndSkill(action, options) {
|
|
|
222
224
|
if (!options.skillOnly) {
|
|
223
225
|
await cleanupGlobalPackageResidues();
|
|
224
226
|
await installGlobalCli(action);
|
|
227
|
+
await installMmdCli(action);
|
|
225
228
|
}
|
|
226
229
|
if (!options.cliOnly) {
|
|
227
230
|
await installSkill(action, options);
|
|
@@ -242,6 +245,16 @@ async function installGlobalCli(action) {
|
|
|
242
245
|
await runStep(`${action} Confluence CLI`, "npm", args);
|
|
243
246
|
}
|
|
244
247
|
}
|
|
248
|
+
async function installMmdCli(action) {
|
|
249
|
+
try {
|
|
250
|
+
await runStep(`${action} Mermaid 原生渲染器 mmd-cli`, "sh", ["-c", `curl -fsSL ${MMD_CLI_INSTALL_URL} | sh`]);
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
254
|
+
process.stdout.write(`已跳过 mmd-cli 安装:${message}\n`);
|
|
255
|
+
process.stdout.write("后续如需 Mermaid 图片渲染,可稍后重试安装,或在上传时传 --mermaid none 保留代码块。\n");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
245
258
|
function isNpmDirectoryNotEmptyError(error) {
|
|
246
259
|
const message = error instanceof Error ? error.message : String(error);
|
|
247
260
|
return message.includes("ENOTEMPTY") || message.toLowerCase().includes("directory not empty");
|
|
@@ -280,7 +293,9 @@ async function installSkillFromInstalledPackage(action, skillGlobal) {
|
|
|
280
293
|
await access(skillPath);
|
|
281
294
|
}
|
|
282
295
|
catch {
|
|
283
|
-
|
|
296
|
+
process.stdout.write(`未找到已安装包内的 Confluence skill:${skillPath},正在自动回退到 npm 包解压安装...\n`);
|
|
297
|
+
await installSkillFromNpmPackage(action, skillGlobal);
|
|
298
|
+
return;
|
|
284
299
|
}
|
|
285
300
|
await runNpxStepWithRetry(`${action} Confluence skill`, createSkillAddArgs(skillPath, skillGlobal));
|
|
286
301
|
}
|
|
@@ -311,6 +326,11 @@ async function uninstallSkill() {
|
|
|
311
326
|
async function uninstallPackage() {
|
|
312
327
|
await runStep("卸载 Confluence CLI", "npm", ["uninstall", "-g", PACKAGE_NAME]);
|
|
313
328
|
await cleanupGlobalPackageResidues();
|
|
329
|
+
await removeMmdCliBinary();
|
|
330
|
+
}
|
|
331
|
+
async function removeMmdCliBinary() {
|
|
332
|
+
await rm(path.join(os.homedir(), ".local", "bin", "mmd-cli"), { force: true });
|
|
333
|
+
await rm("/usr/local/bin/mmd-cli", { force: true });
|
|
314
334
|
}
|
|
315
335
|
async function cleanupGlobalPackageResidues() {
|
|
316
336
|
const globalNodeModules = (await runCommandOutput("npm", ["root", "-g"])).trim();
|
|
@@ -370,7 +390,7 @@ async function runStep(title, command, args) {
|
|
|
370
390
|
}
|
|
371
391
|
function runCommand(command, args) {
|
|
372
392
|
return new Promise((resolve, reject) => {
|
|
373
|
-
const child = spawn(command, args, { shell: process.platform === "win32" });
|
|
393
|
+
const child = spawn(command, args, { shell: process.platform === "win32", env: createInstallEnv() });
|
|
374
394
|
let stderr = "";
|
|
375
395
|
child.stdout?.pipe(process.stdout);
|
|
376
396
|
child.stderr?.on("data", (chunk) => {
|
|
@@ -389,7 +409,7 @@ function runCommand(command, args) {
|
|
|
389
409
|
}
|
|
390
410
|
function runCommandOutput(command, args) {
|
|
391
411
|
return new Promise((resolve, reject) => {
|
|
392
|
-
const child = spawn(command, args, { shell: process.platform === "win32" });
|
|
412
|
+
const child = spawn(command, args, { shell: process.platform === "win32", env: createInstallEnv() });
|
|
393
413
|
let stdout = "";
|
|
394
414
|
let stderr = "";
|
|
395
415
|
child.stdout?.on("data", (chunk) => { stdout += chunk.toString("utf8"); });
|
|
@@ -404,6 +424,12 @@ function runCommandOutput(command, args) {
|
|
|
404
424
|
});
|
|
405
425
|
});
|
|
406
426
|
}
|
|
427
|
+
function createInstallEnv() {
|
|
428
|
+
return {
|
|
429
|
+
...process.env,
|
|
430
|
+
CI: process.env.CI ?? "true",
|
|
431
|
+
};
|
|
432
|
+
}
|
|
407
433
|
function renderBanner() {
|
|
408
434
|
return [
|
|
409
435
|
" ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ",
|
package/dist/manifest.json
CHANGED
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.5";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "0.0.
|
|
1
|
+
export const VERSION = "0.0.5";
|
|
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.5",
|
|
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",
|