Compare commits

...

3 Commits

Author SHA1 Message Date
Jim Liu 宝玉 6cd709b9e7 chore: release v1.85.0 2026-03-25 17:37:18 -05:00
Jim Liu 宝玉 aaf0f188dd feat(baoyu-image-gen): add deprecation redirect skill to guide migration to baoyu-imagine 2026-03-25 17:36:49 -05:00
Jim Liu 宝玉 b6bf8ecd06 feat(baoyu-imagine): auto-migrate legacy baoyu-image-gen EXTEND.md config path 2026-03-25 17:36:46 -05:00
7 changed files with 133 additions and 8 deletions
+2 -1
View File
@@ -6,7 +6,7 @@
},
"metadata": {
"description": "Skills shared by Baoyu for improving daily work efficiency",
"version": "1.84.0"
"version": "1.85.0"
},
"plugins": [
{
@@ -22,6 +22,7 @@
"./skills/baoyu-danger-gemini-web",
"./skills/baoyu-danger-x-to-markdown",
"./skills/baoyu-format-markdown",
"./skills/baoyu-image-gen",
"./skills/baoyu-imagine",
"./skills/baoyu-infographic",
"./skills/baoyu-markdown-to-html",
+6
View File
@@ -2,6 +2,12 @@
English | [中文](./CHANGELOG.zh.md)
## 1.85.0 - 2026-03-25
### Features
- `baoyu-imagine`: auto-migrate legacy `baoyu-image-gen` EXTEND.md config path at runtime
- Add `baoyu-image-gen` deprecation redirect skill to guide users to install `baoyu-imagine` and remove the old skill
## 1.84.0 - 2026-03-25
### Features
+6
View File
@@ -2,6 +2,12 @@
[English](./CHANGELOG.md) | 中文
## 1.85.0 - 2026-03-25
### 新功能
- `baoyu-imagine`:运行时自动迁移旧版 `baoyu-image-gen` 的 EXTEND.md 配置路径
- 新增 `baoyu-image-gen` 废弃重定向技能,引导用户安装 `baoyu-imagine` 并移除旧技能
## 1.84.0 - 2026-03-25
### 新功能
+19
View File
@@ -0,0 +1,19 @@
---
name: baoyu-image-gen
description: "[DEPRECATED] This skill has been renamed to baoyu-imagine. Triggers on any reference to 'baoyu-image-gen' so users can be guided to upgrade. Use this whenever you detect the old skill name in user prompts, EXTEND.md, or installed skill lists."
---
# baoyu-image-gen is now baoyu-imagine
This skill has been renamed to **baoyu-imagine** with new features and providers.
## What to do
When this skill is triggered, inform the user that `baoyu-image-gen` has been renamed to `baoyu-imagine` with new features and providers, and ask for their confirmation to:
1. **Install the new skill** from: `https://github.com/JimLiu/baoyu-skills/blob/main/skills/baoyu-imagine/SKILL.md`
2. **Remove the old `baoyu-image-gen` skill**
No config changes are needed — `baoyu-imagine` reads the same EXTEND.md settings (API keys, default provider, etc.).
Once the user confirms, help them complete the installation and removal using whatever mechanism the current environment supports. If the user also has an image generation request, proceed with `baoyu-imagine` after migration.
+2
View File
@@ -55,6 +55,8 @@ if (Test-Path "$HOME/.baoyu-skills/baoyu-imagine/EXTEND.md") { "user" }
| `.baoyu-skills/baoyu-imagine/EXTEND.md` | Project directory |
| `$HOME/.baoyu-skills/baoyu-imagine/EXTEND.md` | User home |
Legacy compatibility: if `.baoyu-skills/baoyu-image-gen/EXTEND.md` exists and the new path does not, runtime renames it to `baoyu-imagine`. If both files exist, runtime leaves them unchanged and uses the new path.
**EXTEND.md Supports**: Default provider | Default quality | Default aspect ratio | Default image size | Default models | Batch worker cap | Provider-specific batch limits
Schema: `references/config/preferences-schema.md`
+56
View File
@@ -13,6 +13,7 @@ import {
getWorkerCount,
isRetryableGenerationError,
loadBatchTasks,
loadExtendConfig,
mergeConfig,
normalizeOutputImagePath,
parseArgs,
@@ -170,6 +171,61 @@ batch:
});
});
test("loadExtendConfig renames legacy EXTEND.md when the new path is missing", async () => {
const root = await makeTempDir("baoyu-imagine-extend-");
const cwd = path.join(root, "project");
const home = path.join(root, "home");
const legacyPath = path.join(cwd, ".baoyu-skills", "baoyu-image-gen", "EXTEND.md");
const currentPath = path.join(cwd, ".baoyu-skills", "baoyu-imagine", "EXTEND.md");
await fs.mkdir(path.dirname(legacyPath), { recursive: true });
await fs.mkdir(home, { recursive: true });
await fs.writeFile(legacyPath, `---
default_provider: google
default_quality: 2k
---
`);
const config = await loadExtendConfig(cwd, home);
assert.equal(config.default_provider, "google");
assert.equal(config.default_quality, "2k");
await fs.access(currentPath);
await assert.rejects(() => fs.access(legacyPath));
});
test("loadExtendConfig leaves legacy EXTEND.md untouched when both paths exist", async () => {
const root = await makeTempDir("baoyu-imagine-extend-dual-");
const cwd = path.join(root, "project");
const home = path.join(root, "home");
const legacyPath = path.join(cwd, ".baoyu-skills", "baoyu-image-gen", "EXTEND.md");
const currentPath = path.join(cwd, ".baoyu-skills", "baoyu-imagine", "EXTEND.md");
await fs.mkdir(path.dirname(legacyPath), { recursive: true });
await fs.mkdir(path.dirname(currentPath), { recursive: true });
await fs.mkdir(home, { recursive: true });
await fs.writeFile(legacyPath, `---
default_provider: google
---
`);
await fs.writeFile(currentPath, `---
default_provider: openai
---
`);
const config = await loadExtendConfig(cwd, home);
assert.equal(config.default_provider, "openai");
assert.equal(await fs.readFile(legacyPath, "utf8"), `---
default_provider: google
---
`);
assert.equal(await fs.readFile(currentPath, "utf8"), `---
default_provider: openai
---
`);
});
test("mergeConfig only fills values missing from CLI args", () => {
const merged = mergeConfig(
makeArgs({
+42 -7
View File
@@ -2,7 +2,7 @@ import path from "node:path";
import process from "node:process";
import { homedir } from "node:os";
import { fileURLToPath } from "node:url";
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
import { access, mkdir, readFile, rename, writeFile } from "node:fs/promises";
import type {
BatchFile,
BatchTaskInput,
@@ -471,14 +471,49 @@ export function parseSimpleYaml(yaml: string): Partial<ExtendConfig> {
return config;
}
async function loadExtendConfig(): Promise<Partial<ExtendConfig>> {
const home = homedir();
const cwd = process.cwd();
type ExtendConfigPathPair = {
current: string;
legacy: string;
};
const paths = [
path.join(cwd, ".baoyu-skills", "baoyu-imagine", "EXTEND.md"),
path.join(home, ".baoyu-skills", "baoyu-imagine", "EXTEND.md"),
function getExtendConfigPathPairs(cwd: string, home: string): ExtendConfigPathPair[] {
return [
{
current: path.join(cwd, ".baoyu-skills", "baoyu-imagine", "EXTEND.md"),
legacy: path.join(cwd, ".baoyu-skills", "baoyu-image-gen", "EXTEND.md"),
},
{
current: path.join(home, ".baoyu-skills", "baoyu-imagine", "EXTEND.md"),
legacy: path.join(home, ".baoyu-skills", "baoyu-image-gen", "EXTEND.md"),
},
];
}
async function exists(filePath: string): Promise<boolean> {
try {
await access(filePath);
return true;
} catch {
return false;
}
}
async function migrateLegacyExtendConfig(cwd: string, home: string): Promise<void> {
for (const { current, legacy } of getExtendConfigPathPairs(cwd, home)) {
const [hasCurrent, hasLegacy] = await Promise.all([exists(current), exists(legacy)]);
if (hasCurrent || !hasLegacy) continue;
await mkdir(path.dirname(current), { recursive: true });
await rename(legacy, current);
}
}
export async function loadExtendConfig(
cwd = process.cwd(),
home = homedir(),
): Promise<Partial<ExtendConfig>> {
await migrateLegacyExtendConfig(cwd, home);
const paths = getExtendConfigPathPairs(cwd, home).map(({ current }) => current);
for (const p of paths) {
try {