create-dwy 0.29.0 → 0.31.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/CHANGELOG.md +16 -0
- package/bin/index.js +4 -2
- package/package.json +1 -1
- package/src/cli-help.js +3 -1
- package/src/sync-codex.js +1 -0
- package/src/template-source.js +56 -1
- package/templates/ai-tools/CHANGELOG.md +6 -0
- package/templates/ai-tools/VERSION +1 -1
- package/templates/ai-tools/hook-manifests/hooks.json +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# create-dwy
|
|
2
2
|
|
|
3
|
+
## [0.31.0] - 2026-11-09
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Codex 中由 dwy 同步的 Hook 执行时显示带 `dwy` 前缀的功能说明,便于识别来源。模板详情见 ai-tools 0.36.1。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## [0.30.0] - 2026-11-08
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- 支持通过 `dwy source` 查看、设置或清除本地模板来源,优先使用本地仓库或模板目录;本地不可用时回退 GitHub。
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
3
19
|
## [0.29.0] - 2026-11-08
|
|
4
20
|
|
|
5
21
|
### Added
|
package/bin/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { runDwy, migrateSkills } from '../src/sync-all.js'
|
|
|
7
7
|
import { refreshSharedSkills } from '../src/skill-store.js'
|
|
8
8
|
import { selfUpgrade } from '../src/self-upgrade.js'
|
|
9
9
|
import { buildHelpText } from '../src/cli-help.js'
|
|
10
|
+
import { manageTemplateSource } from '../src/template-source.js'
|
|
10
11
|
|
|
11
12
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
12
13
|
const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf-8'))
|
|
@@ -25,8 +26,8 @@ if (wantsHelp(argv)) {
|
|
|
25
26
|
printHelp()
|
|
26
27
|
} else if (argv.includes('--version') || argv.includes('-V')) {
|
|
27
28
|
console.log(pkg.version)
|
|
28
|
-
} else if (['upgrade', 'refresh', 'migrate'].includes(argv[0])) {
|
|
29
|
-
if (argv.length > 1) {
|
|
29
|
+
} else if (['upgrade', 'refresh', 'migrate', 'source'].includes(argv[0])) {
|
|
30
|
+
if (argv.length > (argv[0] === 'source' ? 2 : 1)) {
|
|
30
31
|
console.error(`未知命令: dwy ${argv.join(' ')}`)
|
|
31
32
|
printHelp()
|
|
32
33
|
process.exitCode = 1
|
|
@@ -35,6 +36,7 @@ if (wantsHelp(argv)) {
|
|
|
35
36
|
if (argv[0] === 'upgrade') await selfUpgrade()
|
|
36
37
|
if (argv[0] === 'refresh') await refreshSharedSkills()
|
|
37
38
|
if (argv[0] === 'migrate') await migrateSkills()
|
|
39
|
+
if (argv[0] === 'source') await manageTemplateSource(argv[1])
|
|
38
40
|
} catch (error) {
|
|
39
41
|
console.error(error.message)
|
|
40
42
|
process.exitCode = 1
|
package/package.json
CHANGED
package/src/cli-help.js
CHANGED
|
@@ -19,6 +19,7 @@ export function buildHelpText(version) {
|
|
|
19
19
|
' dwy upgrade 升级到 npm 最新正式版,并刷新共享 Skills',
|
|
20
20
|
' dwy refresh 用最新模板刷新已安装的共享 Skills',
|
|
21
21
|
' dwy migrate 一键迁移老项目已有的托管 Skills,原目录先备份',
|
|
22
|
+
' dwy source [路径|--clear] 查看、设置或清除本地模板路径',
|
|
22
23
|
' dwy --help 显示本说明',
|
|
23
24
|
' dwy --version 显示版本',
|
|
24
25
|
'',
|
|
@@ -75,7 +76,8 @@ export function buildHelpText(version) {
|
|
|
75
76
|
'Hooks 的模板更新仍需执行 dwy sync;已有会话缓存的 Skill 可能需要重新加载。',
|
|
76
77
|
'',
|
|
77
78
|
'模板更新:',
|
|
78
|
-
'
|
|
79
|
+
' dwy source 路径 设置本地仓库或模板路径;dwy source --clear 恢复远端。',
|
|
80
|
+
' 本地不可用时从 GitHub develop 获取;离线优先使用缓存,无有效缓存时使用随包模板。',
|
|
79
81
|
' DWY_TEMPLATE_SOURCE_DIR 开发覆盖优先;设置后直接使用指定本地模板。',
|
|
80
82
|
' Skills 新增或变更不需要 CLI 发版;dwy upgrade 更新 CLI 程序。',
|
|
81
83
|
'',
|
package/src/sync-codex.js
CHANGED
|
@@ -282,6 +282,7 @@ export function buildCodexHooksJson(manifests, selectedHookNames, global, config
|
|
|
282
282
|
command: global
|
|
283
283
|
? globalHookCommand(configDir, manifest.name)
|
|
284
284
|
: `bash "$(git rev-parse --show-toplevel)/.codex/hooks/${manifest.name}"`,
|
|
285
|
+
...(manifest.statusMessage ? { statusMessage: manifest.statusMessage } : {}),
|
|
285
286
|
...(manifest.timeout ? { timeout: manifest.timeout } : {}),
|
|
286
287
|
})
|
|
287
288
|
grouped.set(key, hooks)
|
package/src/template-source.js
CHANGED
|
@@ -34,6 +34,45 @@ async function validateTemplates(directory) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
async function localTemplateDirectory(localPath) {
|
|
38
|
+
const repositoryTemplates = path.join(localPath, ...TEMPLATE_PATH)
|
|
39
|
+
const directory = await fs.pathExists(repositoryTemplates) ? repositoryTemplates : localPath
|
|
40
|
+
await validateTemplates(directory)
|
|
41
|
+
return directory
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 查看或设置本机模板来源;无参数查看,--clear 恢复远端来源。 */
|
|
45
|
+
export async function manageTemplateSource(value, { homeDir = os.homedir() } = {}) {
|
|
46
|
+
const root = process.env.DWY_HOME || path.join(homeDir, '.dwy')
|
|
47
|
+
const file = path.join(root, 'template-source.json')
|
|
48
|
+
const config = await fs.readJson(file).catch(error => {
|
|
49
|
+
if (error.code === 'ENOENT') return {}
|
|
50
|
+
throw error
|
|
51
|
+
})
|
|
52
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) throw new Error('模板来源配置不是有效对象')
|
|
53
|
+
if (value === undefined) {
|
|
54
|
+
console.log(config.localPath ? `本地模板路径:${config.localPath}` : '未配置本地模板路径,将使用 GitHub。')
|
|
55
|
+
} else {
|
|
56
|
+
if (value === '--clear') {
|
|
57
|
+
delete config.localPath
|
|
58
|
+
} else {
|
|
59
|
+
const localPath = path.resolve(value)
|
|
60
|
+
await localTemplateDirectory(localPath)
|
|
61
|
+
config.localPath = localPath
|
|
62
|
+
}
|
|
63
|
+
await fs.ensureDir(root)
|
|
64
|
+
const temporary = path.join(root, `.template-source-config-${randomUUID()}`)
|
|
65
|
+
try {
|
|
66
|
+
await fs.writeJson(temporary, config, { spaces: 2, flag: 'wx' })
|
|
67
|
+
await fs.rename(temporary, file)
|
|
68
|
+
} finally {
|
|
69
|
+
await fs.remove(temporary)
|
|
70
|
+
}
|
|
71
|
+
console.log(config.localPath ? `已设置本地模板路径:${config.localPath}` : '已清除本地模板路径,将使用 GitHub。')
|
|
72
|
+
}
|
|
73
|
+
if (process.env.DWY_TEMPLATE_SOURCE_DIR) console.warn('当前 DWY_TEMPLATE_SOURCE_DIR 优先于本地模板配置。')
|
|
74
|
+
}
|
|
75
|
+
|
|
37
76
|
async function validateTree(directory) {
|
|
38
77
|
for (const entry of await fs.readdir(directory, { withFileTypes: true })) {
|
|
39
78
|
if (entry.isSymbolicLink()) throw new Error(`模板不能包含软链接:${entry.name}`)
|
|
@@ -199,7 +238,7 @@ async function refreshTemplates(root, cache, repositoryUrl) {
|
|
|
199
238
|
|
|
200
239
|
/**
|
|
201
240
|
* 从固定公开仓库更新用户模板缓存;只读取已验证的目录,不执行模板脚本。
|
|
202
|
-
*
|
|
241
|
+
* 显式目录优先,其次用户配置的本地模板;更新失败保留缓存,无有效缓存才用随包模板。
|
|
203
242
|
*/
|
|
204
243
|
export async function resolveTemplateSource({ homeDir = os.homedir(), repository = REMOTE } = {}) {
|
|
205
244
|
const explicitSourceDir = process.env.DWY_TEMPLATE_SOURCE_DIR
|
|
@@ -210,6 +249,22 @@ export async function resolveTemplateSource({ homeDir = os.homedir(), repository
|
|
|
210
249
|
return explicitSourceDir
|
|
211
250
|
}
|
|
212
251
|
const root = process.env.DWY_HOME || path.join(homeDir, '.dwy')
|
|
252
|
+
try {
|
|
253
|
+
const config = await fs.readJson(path.join(root, 'template-source.json'))
|
|
254
|
+
if (typeof config?.localPath !== 'string' || !path.isAbsolute(config.localPath)) {
|
|
255
|
+
throw new Error('localPath 必须是绝对路径')
|
|
256
|
+
}
|
|
257
|
+
const localTemplates = await localTemplateDirectory(config.localPath)
|
|
258
|
+
console.log(`使用本地模板:${localTemplates}(会读取本地未提交的修改)`)
|
|
259
|
+
const date = await git(['show', '-s', '--format=%cI', 'HEAD'], localTemplates).catch(() => '未知')
|
|
260
|
+
console.log(`本地仓库最近提交时间:${date}`)
|
|
261
|
+
return localTemplates
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if (error.code !== 'ENOENT') console.warn(`本地模板配置或目录不可用(${error.message});回退 GitHub。`)
|
|
264
|
+
else if (error.path !== path.join(root, 'template-source.json')) {
|
|
265
|
+
console.warn('本地模板目录不存在;回退 GitHub。')
|
|
266
|
+
}
|
|
267
|
+
}
|
|
213
268
|
const cache = path.join(root, 'template-source')
|
|
214
269
|
const progress = process.stdout.isTTY ? spinner() : null
|
|
215
270
|
progress?.start('正在检查 AI 模板更新,首次获取可能较慢')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.36.
|
|
1
|
+
0.36.1
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"event": "PreToolUse",
|
|
5
5
|
"matcher": "Bash",
|
|
6
6
|
"platforms": ["claude", "codex"],
|
|
7
|
+
"statusMessage": "dwy:检查提交中的敏感信息",
|
|
7
8
|
"timeout": 30
|
|
8
9
|
},
|
|
9
10
|
{
|
|
@@ -11,6 +12,7 @@
|
|
|
11
12
|
"event": "PreToolUse",
|
|
12
13
|
"matcher": "Bash",
|
|
13
14
|
"platforms": ["claude", "codex"],
|
|
15
|
+
"statusMessage": "dwy:检查提交命令中的反引号",
|
|
14
16
|
"timeout": 30
|
|
15
17
|
},
|
|
16
18
|
{
|
|
@@ -18,6 +20,7 @@
|
|
|
18
20
|
"event": "PreToolUse",
|
|
19
21
|
"matcher": "Bash",
|
|
20
22
|
"platforms": ["claude", "codex"],
|
|
23
|
+
"statusMessage": "dwy:检查提交信息中的 AI 签名",
|
|
21
24
|
"timeout": 30
|
|
22
25
|
}
|
|
23
26
|
]
|