skill-atlas-cli 0.1.23 → 0.1.25

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.
Files changed (2) hide show
  1. package/lib/index.js +40 -17
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -313,7 +313,7 @@ var import_picocolors = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin((
313
313
  async function get(apiPath, params = {}) {
314
314
  const url = new URL(apiPath, config_default.getApiBase());
315
315
  for (const [k, v] of Object.entries(params)) if (v !== void 0 && v !== null && v !== "") url.searchParams.set(k, String(v));
316
- const res = await fetch(url.toString(), { headers: { agent_id: config_default.getAgentId() } });
316
+ const res = await fetch(url.toString(), { headers: { "X-SkillAtlas-Agent-Id": config_default.getAgentId() } });
317
317
  if (!res.ok) {
318
318
  const body = await res.text().catch(() => "");
319
319
  throw new Error(`API error ${res.status}: ${body || res.statusText}`);
@@ -953,6 +953,10 @@ ${asset.readme || ""}
953
953
  }
954
954
  //#endregion
955
955
  //#region src/commands/install.ts
956
+ /** 非 TTY 环境(如 OpenClaw、CI、管道)下自动启用非交互模式,避免阻塞 */
957
+ function isNonInteractiveEnv() {
958
+ return !process.stdin.isTTY;
959
+ }
956
960
  async function promptForAgents(message, choices, initialValues) {
957
961
  return await searchMultiselect({
958
962
  message,
@@ -980,8 +984,12 @@ function buildAgentChoices(globalInstall) {
980
984
  function getDefaultAgents(choices) {
981
985
  return ["claude-code", "openclaw"].filter((agent) => choices.some((choice) => choice.value === agent));
982
986
  }
983
- async function resolveSkillName(inputSkill) {
987
+ async function resolveSkillName(inputSkill, nonInteractive) {
984
988
  if (inputSkill?.trim()) return inputSkill.trim();
989
+ if (nonInteractive) errorAndExit("Please provide skill name", {
990
+ title: "Usage",
991
+ body: "skill-atlas install <skillName>\n\nExample: skill-atlas install my-skill"
992
+ });
985
993
  const input = await p.text({
986
994
  message: "Enter skill to install",
987
995
  placeholder: "my-skill",
@@ -992,9 +1000,9 @@ async function resolveSkillName(inputSkill) {
992
1000
  if (p.isCancel(input)) cancelAndExit("Cancelled");
993
1001
  return input.trim();
994
1002
  }
995
- async function resolveTargetAgents(options) {
996
- const allAgentChoices = buildAgentChoices(Boolean(options.global ?? options.yes));
997
- if (options.yes) {
1003
+ async function resolveTargetAgents(options, nonInteractive) {
1004
+ const allAgentChoices = buildAgentChoices(Boolean(options.global ?? options.yes ?? nonInteractive));
1005
+ if (options.yes || nonInteractive) {
998
1006
  const defaults = getDefaultAgents(allAgentChoices);
999
1007
  if (defaults.length === 0) cancelAndExit("No default agents available");
1000
1008
  return defaults;
@@ -1003,9 +1011,9 @@ async function resolveTargetAgents(options) {
1003
1011
  if (p.isCancel(selected) || selected.length === 0) cancelAndExit("Installation cancelled");
1004
1012
  return selected;
1005
1013
  }
1006
- async function resolveInstallScope(options, targetAgents) {
1014
+ async function resolveInstallScope(options, targetAgents, nonInteractive) {
1007
1015
  const supportsGlobal = targetAgents.some((agent) => agents[agent].globalSkillsDir !== void 0);
1008
- if (options.global !== void 0 || options.yes || !supportsGlobal) return options.global ?? (options.yes ? true : false);
1016
+ if (options.global !== void 0 || options.yes || nonInteractive || !supportsGlobal) return options.global ?? (options.yes || nonInteractive ? true : false);
1009
1017
  const scope = await p.select({
1010
1018
  message: "Installation scope",
1011
1019
  options: [{
@@ -1021,15 +1029,30 @@ async function resolveInstallScope(options, targetAgents) {
1021
1029
  if (p.isCancel(scope)) cancelAndExit("Installation cancelled");
1022
1030
  return scope;
1023
1031
  }
1032
+ /** 非 TTY 下使用静态输出替代 spinner,避免动画帧被逐行打印造成刷屏 */
1033
+ function createProgressReporter(nonInteractive) {
1034
+ if (nonInteractive) return {
1035
+ start: (msg) => p.log.message(msg),
1036
+ stop: (msg) => {
1037
+ if (msg) p.log.message(msg);
1038
+ }
1039
+ };
1040
+ const s = p.spinner();
1041
+ return {
1042
+ start: (msg) => s.start(msg),
1043
+ stop: (msg) => s.stop(msg ?? "")
1044
+ };
1045
+ }
1024
1046
  const run = async (args, options = {}) => {
1047
+ const nonInteractive = options.yes || isNonInteractiveEnv();
1025
1048
  p.intro(chalk.bold("skill-atlas install"));
1026
- const skill = await resolveSkillName(args[0]);
1027
- const s = p.spinner();
1028
- s.start(`Searching for ${chalk.bold(skill)}...`);
1049
+ const skill = await resolveSkillName(args[0], nonInteractive);
1050
+ const progress = createProgressReporter(nonInteractive);
1051
+ progress.start(`Searching for ${chalk.bold(skill)}...`);
1029
1052
  try {
1030
1053
  const asset = await findAsset(skill);
1031
1054
  if (!asset) {
1032
- s.stop();
1055
+ progress.stop();
1033
1056
  errorAndExit(`Not found: ${chalk.bold(skill)}`, {
1034
1057
  title: "Suggest",
1035
1058
  body: `Try: skill-atlas search ${skill}`
@@ -1037,12 +1060,12 @@ const run = async (args, options = {}) => {
1037
1060
  }
1038
1061
  const displayName = asset.displayName || asset.slug;
1039
1062
  const version = asset.currentVersion.version ?? "0.0.0";
1040
- s.stop(`${chalk.bold(displayName)} ${chalk.dim(`v${version}`)}`);
1041
- const targetAgents = await resolveTargetAgents(options);
1042
- const installGlobally = await resolveInstallScope(options, targetAgents);
1063
+ progress.stop(`${chalk.bold(displayName)} ${chalk.dim(`v${version}`)}`);
1064
+ const targetAgents = await resolveTargetAgents(options, nonInteractive);
1065
+ const installGlobally = await resolveInstallScope(options, targetAgents, nonInteractive);
1043
1066
  const selectedLabels = targetAgents.map((a) => agents[a].displayName);
1044
1067
  p.log.message(chalk.green("Selected:") + " " + selectedLabels.join(", "));
1045
- s.start("Installing skills...");
1068
+ progress.start("Installing skills...");
1046
1069
  const installMode = options.copy ? "copy" : "symlink";
1047
1070
  const installResults = [];
1048
1071
  for (const agent of targetAgents) {
@@ -1056,13 +1079,13 @@ const run = async (args, options = {}) => {
1056
1079
  path: result.path
1057
1080
  });
1058
1081
  }
1059
- s.stop("Skills installed successfully");
1082
+ progress.stop("Skills installed successfully");
1060
1083
  const title = import_picocolors.default.green("Installed 1 skill");
1061
1084
  const resultLines = installResults.map((r) => ` ${agents[r.agent].displayName}: ${r.path}`);
1062
1085
  p.note(resultLines.join("\n"), title);
1063
1086
  p.outro(import_picocolors.default.green("Done!") + import_picocolors.default.dim(" Skill ready. Review before use."));
1064
1087
  } catch (err) {
1065
- s.stop();
1088
+ progress.stop();
1066
1089
  p.log.error(`Install failed: ${err.message}`);
1067
1090
  process.exit(1);
1068
1091
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skill-atlas-cli",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "skill-atlas CLI - 虾小宝 命令行工具",
5
5
  "homepage": "https://ai.skillatlas.cn/",
6
6
  "type": "module",