@jspg-ai/coding-bb 0.0.3-beta.29 → 0.0.3-beta.30
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.
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* Claude Code 适配器
|
|
3
3
|
*
|
|
4
4
|
* 将编码规范分发到 .claude/rules/ 目录
|
|
5
|
+
*
|
|
6
|
+
* 退市(selectable: false):团队当前不使用 Claude Code,不在安装面板提供。
|
|
7
|
+
* 适配器代码与全部能力保留(含用户级 settings hook);先前已安装的空间按
|
|
8
|
+
* .last-tools 记录**粘性维护**(见 tool-selection.js),内容不被清理。
|
|
9
|
+
* 恢复入口:删掉 selectable 即可重新出现在面板(决策:不留参数开关)。
|
|
5
10
|
*/
|
|
6
11
|
|
|
7
12
|
const path = require('path');
|
|
@@ -13,8 +18,10 @@ module.exports = {
|
|
|
13
18
|
rulesDir: '.claude/rules',
|
|
14
19
|
skillsDir: '.claude/skills',
|
|
15
20
|
commandsDir: '.claude/commands/opsx',
|
|
16
|
-
// 用户级 settings,写入全局生效,不污染项目目录
|
|
21
|
+
// 用户级 settings,写入全局生效,不污染项目目录
|
|
17
22
|
settingsFile: path.join(os.homedir(), '.claude', 'settings.json'),
|
|
18
23
|
settingsFileIsUserLevel: true,
|
|
19
24
|
hookEvents: ['UserPromptSubmit'],
|
|
25
|
+
// 退市:不在安装面板提供(代码保留,存量空间粘性维护)
|
|
26
|
+
selectable: false,
|
|
20
27
|
};
|
package/cbb/lib/install/init.js
CHANGED
|
@@ -100,6 +100,9 @@ const agentsNav = require('./agents-nav');
|
|
|
100
100
|
// 命令 → skill 形态转换(commandsAsSkills 适配器,当前仅 MiniMax Code)
|
|
101
101
|
const commandSkill = require('./command-skill');
|
|
102
102
|
|
|
103
|
+
// 工具选择策略(退市工具不在面板提供 + 存量粘性保留)
|
|
104
|
+
const toolSelection = require('./tool-selection');
|
|
105
|
+
|
|
103
106
|
/** 适配器的 hook 方言参数(Trae 需顶层 version 字段等差异) */
|
|
104
107
|
function hookOpts(adapter) {
|
|
105
108
|
return adapter.hookDialect ? { dialect: adapter.hookDialect } : {};
|
|
@@ -341,19 +344,22 @@ function ask(question) {
|
|
|
341
344
|
async function selectTools(isUpgrade) {
|
|
342
345
|
const action = isUpgrade ? '升级' : '安装';
|
|
343
346
|
|
|
347
|
+
// 面板可选项 = 未退市适配器(Claude Code / MiniMax Code 已退市,见 tool-selection.js)
|
|
348
|
+
const selectable = toolSelection.selectableAdapters(adapters);
|
|
349
|
+
|
|
344
350
|
// 读取上次选择的工具:有记录则预选上次选择,首次安装则全部不选
|
|
345
351
|
const lastTools = readLastTools();
|
|
346
352
|
const preSelected = lastTools
|
|
347
|
-
?
|
|
353
|
+
? selectable.map((a, i) => lastTools.has(a.name) ? i : -1).filter(i => i >= 0)
|
|
348
354
|
: [];
|
|
349
355
|
|
|
350
356
|
// checkbox 多选:
|
|
351
357
|
// - 不切换 → 确认当前选择
|
|
352
358
|
// - 取消某项 → 只装剩下的
|
|
353
|
-
// - 全部不选 →
|
|
359
|
+
// - 全部不选 → 提示后回退全部可选项
|
|
354
360
|
const selectedIdx = await checkbox.promptCheckbox({
|
|
355
361
|
header: `🔧 选择要${action}的 AI 工具(空格切换,回车确认)`,
|
|
356
|
-
items:
|
|
362
|
+
items: selectable.map(a => ({
|
|
357
363
|
label: c('cyan', a.displayName),
|
|
358
364
|
})),
|
|
359
365
|
preSelected,
|
|
@@ -362,15 +368,18 @@ async function selectTools(isUpgrade) {
|
|
|
362
368
|
let result;
|
|
363
369
|
if (selectedIdx.size === 0) {
|
|
364
370
|
log(`未选择任何工具,默认全部${action}`, 'warn');
|
|
365
|
-
result =
|
|
371
|
+
result = selectable;
|
|
366
372
|
} else {
|
|
367
373
|
// 转成有序适配器数组(按原始顺序)
|
|
368
374
|
result = [...selectedIdx]
|
|
369
375
|
.sort((a, b) => a - b)
|
|
370
|
-
.map(i =>
|
|
376
|
+
.map(i => selectable[i]);
|
|
371
377
|
}
|
|
372
378
|
|
|
373
|
-
//
|
|
379
|
+
// 退市但该空间旧记录里有的工具:粘性保留(继续维护,不因退市清删其内容)
|
|
380
|
+
result = toolSelection.carryOverRetired(adapters, result, lastTools);
|
|
381
|
+
|
|
382
|
+
// 保存本次选择(含粘性保留项,避免记录丢失导致下次被清理),供下次运行时预选
|
|
374
383
|
saveLastTools(result);
|
|
375
384
|
return result;
|
|
376
385
|
}
|
|
@@ -1038,16 +1047,27 @@ async function init(targetDir, options = {}) {
|
|
|
1038
1047
|
} else if (isNonInteractive) {
|
|
1039
1048
|
const lastTools = readLastTools();
|
|
1040
1049
|
const reused = lastTools ? adapters.filter(a => lastTools.has(a.name)) : [];
|
|
1041
|
-
selectedAdapters = reused.length > 0 ? reused : adapters;
|
|
1050
|
+
selectedAdapters = reused.length > 0 ? reused : toolSelection.selectableAdapters(adapters);
|
|
1042
1051
|
fromRecord = reused.length > 0;
|
|
1043
1052
|
if (yes && process.stdin.isTTY) {
|
|
1044
1053
|
log(reused.length > 0
|
|
1045
1054
|
? `--yes 非交互模式,沿用上次工具选择:${reused.map(a => a.displayName).join('、')}`
|
|
1046
|
-
: '--yes
|
|
1055
|
+
: '--yes 非交互模式,无上次选择记录,已默认选中全部可选工具', 'info');
|
|
1047
1056
|
}
|
|
1048
1057
|
} else {
|
|
1049
1058
|
selectedAdapters = await selectTools(isUpgrade);
|
|
1050
1059
|
}
|
|
1060
|
+
|
|
1061
|
+
// 退市工具粘性保留(面板不出现,但本空间旧记录里有 → 继续维护,内容不被清理)。
|
|
1062
|
+
// 覆盖面板外入口:setup 预设(presetAdapters)与非交互记录沿用;交互面板已在 selectTools 内并过。
|
|
1063
|
+
const lastToolsForDir = readLastTools();
|
|
1064
|
+
const withRetired = toolSelection.carryOverRetired(adapters, selectedAdapters, lastToolsForDir);
|
|
1065
|
+
const retiredKept = toolSelection.retiredNames(withRetired);
|
|
1066
|
+
if (retiredKept.length > 0) {
|
|
1067
|
+
log(`保留上次选择的退市工具:${retiredKept.join('、')}(当前不在安装面板提供,内容继续维护)`, 'dim');
|
|
1068
|
+
}
|
|
1069
|
+
selectedAdapters = withRetired;
|
|
1070
|
+
|
|
1051
1071
|
// 业务空间根记录本次选择,供 cbb update 等非交互场景沿用;
|
|
1052
1072
|
// 沿用旧记录时同样落盘,使历史工具名(codebuddy → workbuddy)归一化自愈
|
|
1053
1073
|
if (isWorkspaceRoot && fromRecord) {
|
|
@@ -1765,20 +1785,21 @@ async function setupWorkspace() {
|
|
|
1765
1785
|
.sort((a, b) => a - b)
|
|
1766
1786
|
.map(i => list[i]);
|
|
1767
1787
|
|
|
1768
|
-
// 2.5 选择 AI
|
|
1788
|
+
// 2.5 选择 AI 工具适配器(一次选择,作用于用户级组件与全部空间;非交互默认全选可选工具)
|
|
1789
|
+
const selectable = toolSelection.selectableAdapters(adapters);
|
|
1769
1790
|
let selectedAdapters;
|
|
1770
1791
|
if (!process.stdin.isTTY) {
|
|
1771
|
-
selectedAdapters =
|
|
1792
|
+
selectedAdapters = selectable;
|
|
1772
1793
|
} else {
|
|
1773
1794
|
const toolIdx = await checkbox.promptCheckbox({
|
|
1774
1795
|
header: '🔧 选择要安装的 AI 工具(空格切换,回车确认)',
|
|
1775
|
-
items:
|
|
1796
|
+
items: selectable.map(a => ({ label: c('cyan', a.displayName) })),
|
|
1776
1797
|
// 默认只预选 opencode(团队当前主用),可空格加选其他工具
|
|
1777
|
-
preSelected:
|
|
1798
|
+
preSelected: selectable.reduce((acc, a, i) => (a.name === 'opencode' ? acc.concat(i) : acc), []),
|
|
1778
1799
|
});
|
|
1779
1800
|
selectedAdapters = toolIdx.size === 0
|
|
1780
|
-
?
|
|
1781
|
-
: [...toolIdx].sort((a, b) => a - b).map(i =>
|
|
1801
|
+
? selectable
|
|
1802
|
+
: [...toolIdx].sort((a, b) => a - b).map(i => selectable[i]);
|
|
1782
1803
|
}
|
|
1783
1804
|
|
|
1784
1805
|
// 3. 配置摘要(业务空间 / 目标目录 / AI 工具)
|
|
@@ -1834,7 +1855,7 @@ const USER_MANIFEST_FILE = path.join(os.homedir(), '.cbb', '.user-components');
|
|
|
1834
1855
|
// 当前为空:cbb-wiki-ops 保留在源仓库(cbb/tools/)但不分发,有用户需要时再加入此清单。
|
|
1835
1856
|
const USER_LEVEL_SKILLS = [];
|
|
1836
1857
|
|
|
1837
|
-
async function setupUserLevelComponents(targetAdapters = adapters) {
|
|
1858
|
+
async function setupUserLevelComponents(targetAdapters = toolSelection.selectableAdapters(adapters)) {
|
|
1838
1859
|
const home = os.homedir();
|
|
1839
1860
|
const srcDir = path.join(SHARED_STANDARDS_DIR, 'cbb', 'tools');
|
|
1840
1861
|
if (!fs.existsSync(srcDir)) return;
|
|
@@ -1913,7 +1934,7 @@ async function updateInstalled() {
|
|
|
1913
1934
|
// 用户级组件沿用本目录的工具选择(.last-tools),无记录或为空才回退全量
|
|
1914
1935
|
const lastTools = readLastTools();
|
|
1915
1936
|
const reused = lastTools ? adapters.filter(a => lastTools.has(a.name)) : [];
|
|
1916
|
-
await setupUserLevelComponents(reused.length > 0 ? reused : adapters);
|
|
1937
|
+
await setupUserLevelComponents(reused.length > 0 ? reused : toolSelection.selectableAdapters(adapters));
|
|
1917
1938
|
|
|
1918
1939
|
const manifest = readManifest();
|
|
1919
1940
|
if (manifest.size === 0) {
|
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
*
|
|
16
16
|
* 数据目录:MINIMAX_DATA_DIR(优先)> MAVIS_DATA_DIR > ~/.minimax,与 mcode
|
|
17
17
|
* 运行时一致;用户若改过数据目录,需重跑 cbb update 以重装插件到新位置。
|
|
18
|
+
*
|
|
19
|
+
* 退市(selectable: false):实测 MiniMax Code 不支持目录级 skill 与 command
|
|
20
|
+
* (无项目级 commands 目录,skill 亦需插件形态承载),当前分发形态不可用。
|
|
21
|
+
* 适配器代码与全部能力保留(备将来改走插件形态),但不在安装面板提供;
|
|
22
|
+
* 已安装过(beta.29)的空间按 .last-tools 记录**粘性维护**,内容不被清理。
|
|
18
23
|
*/
|
|
19
24
|
|
|
20
25
|
const path = require('path');
|
|
@@ -50,4 +55,6 @@ module.exports = {
|
|
|
50
55
|
timeout: 10,
|
|
51
56
|
},
|
|
52
57
|
resolveDataDir,
|
|
58
|
+
// 退市:不在安装面板提供(代码保留,存量空间粘性维护)
|
|
59
|
+
selectable: false,
|
|
53
60
|
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 工具选择策略:安装面板的可见集合 + 退市工具的粘性保留。
|
|
5
|
+
*
|
|
6
|
+
* 背景(2026-09-28 决策):MiniMax Code 实测不支持目录级 skill 与 command、
|
|
7
|
+
* Claude Code 团队当前未用,两者**退市**——适配器与全部能力保留(见各适配器
|
|
8
|
+
* 文件头),仅不在 `cbb setup` / `cbb update` 的安装面板提供。
|
|
9
|
+
*
|
|
10
|
+
* 两条规则:
|
|
11
|
+
* 1. **可选项**(selectableAdapters):面板项、非交互全选兜底、setup 默认预选、
|
|
12
|
+
* 用户级组件新装,一律只用未退市适配器(`selectable !== false`);
|
|
13
|
+
* 2. **粘性保留**(carryOverRetired):某空间的 `.last-tools` 记录过退市工具
|
|
14
|
+
* (即确曾安装),则继续纳入本次安装/升级集合——面板不出现,内容不因退市
|
|
15
|
+
* 被清单差集清删;`.last-tools` 一并保持该记录,避免记录丢失导致下次清理。
|
|
16
|
+
*
|
|
17
|
+
* 恢复入口:删掉适配器的 `selectable: false` 即回到面板(决策:不留参数开关)。
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** 面板/默认可选适配器(未标 selectable: false 的全部) */
|
|
21
|
+
function selectableAdapters(adapters) {
|
|
22
|
+
return adapters.filter(a => a.selectable !== false);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 把「本空间旧记录中的退市工具」并入选择结果(按注册表顺序追加,去重)。
|
|
27
|
+
* @param {Array} adapters 注册表全量
|
|
28
|
+
* @param {Array} selected 本次选择(面板 / 预设 / 记录沿用)
|
|
29
|
+
* @param {Set<string>|null} lastTools 该空间的旧工具记录(.last-tools)
|
|
30
|
+
* @returns {Array} 并入后的有序数组(无退市工具需保留时原样返回)
|
|
31
|
+
*/
|
|
32
|
+
function carryOverRetired(adapters, selected, lastTools) {
|
|
33
|
+
if (!lastTools || lastTools.size === 0) return selected;
|
|
34
|
+
const selectedNames = new Set(selected.map(a => a.name));
|
|
35
|
+
const carried = adapters.filter(a =>
|
|
36
|
+
a.selectable === false && lastTools.has(a.name) && !selectedNames.has(a.name));
|
|
37
|
+
return carried.length > 0 ? selected.concat(carried) : selected;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** 结果集中退市工具的显示名(供安装输出提示,如「保留上次选择的 Claude Code」) */
|
|
41
|
+
function retiredNames(selected) {
|
|
42
|
+
return selected.filter(a => a.selectable === false).map(a => a.displayName);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { selectableAdapters, carryOverRetired, retiredNames };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jspg-ai/coding-bb",
|
|
3
|
-
"version": "0.0.3-beta.
|
|
3
|
+
"version": "0.0.3-beta.30",
|
|
4
4
|
"description": "整合业界热门且高价值的工具、框架与技能,为 AI CODING AGENT 提供统一的行为准则与工作流,辅助开发者将需求高效落地为符合规范的代码",
|
|
5
5
|
"main": "cbb/lib/install/init.js",
|
|
6
6
|
"bin": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"sync:shared": "node scripts/sync-shared.js",
|
|
21
21
|
"pretest": "node scripts/sync-shared.js --check",
|
|
22
|
-
"test": "node test/lib/install/cleanup.test.js && node test/lib/utils/settings.test.js && node test/lib/utils/gitignore.test.js && node test/lib/utils/githook.test.js && node test/lib/utils/version.test.js && node test/lib/install/workspaces.test.js && node test/lib/utils/checkbox.test.js && node test/lib/utils/output.test.js && node test/lib/install/cli-help.test.js && node test/lib/install/adapters.test.js && node test/lib/install/agents-nav.test.js && node test/lib/install/command-skill.test.js && node test/lib/utils/plugin-hook.test.js && node test/lib/wiki/wiki-publish.test.js && node test/lib/wiki/wiki-parse-args.test.js && node test/lib/wiki/wiki-split.test.js && node test/lib/superpowers/superpowers.test.js && node test/worktrees/push-branches.test.js && node test/worktrees/commit-worktrees.test.js && node test/worktrees/push-worktrees.test.js && node test/worktrees/check-env-deep.test.js && node test/worktrees/create-worktrees.test.js && node test/worktrees/make-mr-urls.test.js && node test/lib/install/setup-decision.test.js && node test/lib/openspec/protected-paths.test.js"
|
|
22
|
+
"test": "node test/lib/install/cleanup.test.js && node test/lib/utils/settings.test.js && node test/lib/utils/gitignore.test.js && node test/lib/utils/githook.test.js && node test/lib/utils/version.test.js && node test/lib/install/workspaces.test.js && node test/lib/utils/checkbox.test.js && node test/lib/utils/output.test.js && node test/lib/install/cli-help.test.js && node test/lib/install/adapters.test.js && node test/lib/install/tool-selection.test.js && node test/lib/install/agents-nav.test.js && node test/lib/install/command-skill.test.js && node test/lib/utils/plugin-hook.test.js && node test/lib/wiki/wiki-publish.test.js && node test/lib/wiki/wiki-parse-args.test.js && node test/lib/wiki/wiki-split.test.js && node test/lib/superpowers/superpowers.test.js && node test/worktrees/push-branches.test.js && node test/worktrees/commit-worktrees.test.js && node test/worktrees/push-worktrees.test.js && node test/worktrees/check-env-deep.test.js && node test/worktrees/create-worktrees.test.js && node test/worktrees/make-mr-urls.test.js && node test/lib/install/setup-decision.test.js && node test/lib/openspec/protected-paths.test.js"
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|
|
25
25
|
"cbb",
|