bfi-cli 0.1.44 → 0.1.55

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.
@@ -4,6 +4,13 @@ import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  import os from "node:os";
6
6
  const CACHE_FILE = path.join(os.homedir(), ".bfi", "agents-cache.json");
7
+ function makeDetectInstalled(globalSkillsDir) {
8
+ return async () => {
9
+ if (!globalSkillsDir) return false;
10
+ const resolved = globalSkillsDir.startsWith("~/") ? path.join(os.homedir(), globalSkillsDir.slice(2)) : globalSkillsDir;
11
+ return fs.existsSync(resolved);
12
+ };
13
+ }
7
14
  function loadCache() {
8
15
  try {
9
16
  if (fs.existsSync(CACHE_FILE)) {
@@ -27,21 +34,25 @@ function saveCache(agents, maxUpdatedAt) {
27
34
  } catch {}
28
35
  }
29
36
  function mapToAgentConfig(a) {
37
+ const gsd = a.globalSkillsDir || void 0;
30
38
  return {
31
39
  name: a.name,
32
40
  displayName: a.displayName || a.name,
33
41
  skillsDir: a.skillsDir,
34
- globalSkillsDir: a.globalSkillsDir || void 0,
35
- detectInstalled: async () => false
42
+ globalSkillsDir: gsd,
43
+ sortOrder: typeof a.sortOrder === "number" ? a.sortOrder : 0,
44
+ detectInstalled: makeDetectInstalled(gsd)
36
45
  };
37
46
  }
38
47
  function mapCustomEntry(name, entry) {
48
+ const gsd = entry.globalSkillsDir || void 0;
39
49
  return {
40
50
  name,
41
51
  displayName: entry.displayName || name,
42
52
  skillsDir: entry.skillsDir,
43
- globalSkillsDir: entry.globalSkillsDir,
44
- detectInstalled: async () => false
53
+ globalSkillsDir: gsd,
54
+ sortOrder: 0,
55
+ detectInstalled: makeDetectInstalled(gsd)
45
56
  };
46
57
  }
47
58
  function parseLastModifiedHeader(headers) {
@@ -74,7 +85,15 @@ async function resolveAgents(api) {
74
85
  if (cache) remoteAgents = cache.agents.map(mapToAgentConfig);
75
86
  }
76
87
  if (shouldSaveCache && remoteAgents) saveCache(remoteAgents, newMaxUpdatedAt);
77
- if (remoteAgents) for (const agent of remoteAgents) merged.set(agent.name, agent);
88
+ if (remoteAgents) for (const agent of remoteAgents) {
89
+ const existing = merged.get(agent.name);
90
+ if (existing) merged.set(agent.name, {
91
+ ...agent,
92
+ showInUniversalList: existing.showInUniversalList,
93
+ showInUniversalPrompt: existing.showInUniversalPrompt
94
+ });
95
+ else merged.set(agent.name, agent);
96
+ }
78
97
  }
79
98
  const config = loadGlobalConfig();
80
99
  if (config?.customAgents) for (const [name, entry] of Object.entries(config.customAgents)) merged.set(name, mapCustomEntry(name, entry));
package/dist/cli.mjs CHANGED
@@ -352,11 +352,15 @@ async function searchMultiselect(options) {
352
352
  lines.push(`${icon} ${import_picocolors.default.bold(message)}`);
353
353
  if (state === "active") {
354
354
  if (lockedSection && lockedSection.items.length > 0) {
355
+ const maxVisible = lockedSection.maxVisibleItems;
356
+ const visibleLocked = maxVisible && maxVisible < lockedSection.items.length ? lockedSection.items.slice(0, maxVisible) : lockedSection.items;
357
+ const lockedRemaining = lockedSection.items.length - visibleLocked.length;
355
358
  lines.push(`${S_BAR}`);
356
359
  const lockedTitle = `${import_picocolors.default.bold(lockedSection.title)} ${import_picocolors.default.dim("── always included")}`;
357
360
  lines.push(`${S_BAR} ${S_BAR_H}${S_BAR_H} ${lockedTitle} ${S_BAR_H.repeat(12)}`);
358
- for (const item of lockedSection.items) lines.push(`${S_BAR} ${S_BULLET} ${import_picocolors.default.bold(item.label)}`);
359
- if (lockedSection.hiddenCount && lockedSection.hiddenCount > 0) lines.push(`${S_BAR} ${import_picocolors.default.dim(`...and ${lockedSection.hiddenCount} more`)}`);
361
+ for (const item of visibleLocked) lines.push(`${S_BAR} ${S_BULLET} ${import_picocolors.default.bold(item.label)}`);
362
+ if (lockedRemaining > 0) lines.push(`${S_BAR} ${import_picocolors.default.dim(`...and ${lockedRemaining} more`)}`);
363
+ else if (lockedSection.hiddenCount && lockedSection.hiddenCount > 0) lines.push(`${S_BAR} ${import_picocolors.default.dim(`...and ${lockedSection.hiddenCount} more`)}`);
360
364
  lines.push(`${S_BAR}`);
361
365
  lines.push(`${S_BAR} ${S_BAR_H}${S_BAR_H} ${import_picocolors.default.bold("Additional agents")} ${S_BAR_H.repeat(29)}`);
362
366
  }
@@ -2997,59 +3001,46 @@ async function selectAgentsInteractive(options) {
2997
3001
  try {
2998
3002
  installedAgents = await detectInstalledAgents();
2999
3003
  } catch {}
3000
- const hasDetected = installedAgents.length > 0;
3001
3004
  const installedSet = new Set(installedAgents);
3002
3005
  const universalAgents = getUniversalAgents().filter(supportsGlobalFilter);
3003
3006
  const visibleUniversalAgents = getVisibleUniversalAgents().filter(supportsGlobalFilter);
3004
3007
  const otherAgents = getNonUniversalAgents().filter((agent) => agent !== "eve" && supportsGlobalFilter(agent));
3005
- const showAll = hasDetected ? false : true;
3006
- const filteredUniversal = showAll ? visibleUniversalAgents : visibleUniversalAgents.filter((a) => installedSet.has(a));
3008
+ const sortByPriority = (a, b) => {
3009
+ const orderA = agents[a]?.sortOrder ?? 0;
3010
+ const orderB = agents[b]?.sortOrder ?? 0;
3011
+ if (orderA !== orderB) return orderA - orderB;
3012
+ return (agents[a]?.displayName || a).localeCompare(agents[b]?.displayName || b);
3013
+ };
3014
+ universalAgents.sort(sortByPriority);
3015
+ visibleUniversalAgents.sort(sortByPriority);
3016
+ otherAgents.sort(sortByPriority);
3007
3017
  const universalSection = {
3008
- title: `共享目录 (.agents/skills) — ${showAll ? "全部" : `已检测到 ${filteredUniversal.length} 个`}`,
3009
- items: filteredUniversal.map((a) => ({
3018
+ title: `共享目录 (.agents/skills)${installedAgents.length > 0 ? ` — 已检测到 ${visibleUniversalAgents.filter((a) => installedSet.has(a)).length} 个` : ""}`,
3019
+ items: visibleUniversalAgents.map((a) => ({
3010
3020
  value: a,
3011
3021
  label: agents[a].displayName
3012
3022
  })),
3013
- hiddenCount: showAll ? universalAgents.length - visibleUniversalAgents.length : 0
3023
+ hiddenCount: universalAgents.length - visibleUniversalAgents.length,
3024
+ maxVisibleItems: 5
3014
3025
  };
3015
- const filteredOther = showAll ? otherAgents : otherAgents.filter((a) => installedSet.has(a));
3016
- const otherChoices = filteredOther.map((a) => ({
3026
+ const otherChoices = otherAgents.map((a) => ({
3017
3027
  value: a,
3018
3028
  label: agents[a].displayName,
3019
3029
  hint: options.global ? agents[a].globalSkillsDir : agents[a].skillsDir
3020
3030
  }));
3021
- if (!showAll && otherAgents.length > filteredOther.length) otherChoices.push({
3022
- value: "__show_all__",
3023
- label: `显示全部 ${otherAgents.length + universalAgents.length} 个 Agent...`,
3024
- hint: "包括未检测到的"
3025
- });
3026
- let lastSelected;
3031
+ let lastSelected = [];
3027
3032
  try {
3028
- lastSelected = await getLastSelectedAgents();
3033
+ lastSelected = await getLastSelectedAgents() || [];
3029
3034
  } catch {}
3030
3035
  const selected = await searchMultiselect({
3031
3036
  message: "请选择要安装到的 Agent:",
3032
3037
  items: otherChoices,
3033
- initialSelected: lastSelected ? lastSelected.filter((a) => otherAgents.includes(a) && !universalAgents.includes(a)) : [],
3038
+ initialSelected: [.../* @__PURE__ */ new Set([...installedAgents, ...lastSelected])].filter((a) => otherAgents.includes(a) && !universalAgents.includes(a)),
3034
3039
  lockedSection: universalSection
3035
3040
  });
3036
- if (!isCancelled(selected)) {
3037
- const selection = selected;
3038
- if (selection.includes("__show_all__")) {
3039
- const allSelected = [
3040
- ...selection.filter((s) => s !== "__show_all__"),
3041
- ...otherAgents.filter((a) => !installedSet.has(a)),
3042
- ...universalAgents.filter((a) => !installedSet.has(a))
3043
- ];
3044
- try {
3045
- await saveSelectedAgents(allSelected);
3046
- } catch {}
3047
- return [...new Set(allSelected)];
3048
- }
3049
- try {
3050
- await saveSelectedAgents(selection);
3051
- } catch {}
3052
- }
3041
+ if (!isCancelled(selected)) try {
3042
+ await saveSelectedAgents(selected);
3043
+ } catch {}
3053
3044
  return selected;
3054
3045
  }
3055
3046
  async function handleWellKnownSkills(source, url, options, spinner) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bfi-cli",
3
- "version": "0.1.44",
3
+ "version": "0.1.55",
4
4
  "description": "用友大业财BFI统一命令行工具,支持技能,技能包,元数据,UI元数据等",
5
5
  "type": "module",
6
6
  "bin": {