toolcraft 0.0.14 → 0.0.15

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +52 -14
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -387,7 +387,7 @@ export function slackApprovalProvider(opts: {
387
387
 
388
388
  ## Errors
389
389
 
390
- Throw `UserError` for expected, user-facing failures. The CLI prints the message without a stack trace and sets exit code 1; MCP and SDK surface the message as the error body. Any other thrown error is treated as unexpected and shows a stack with `--verbose`.
390
+ Throw `UserError` for expected, user-facing failures. The CLI prints the message without a stack trace and sets exit code 1; MCP and SDK surface the message as the error body. Any other thrown error is treated as unexpected and shows a stack with `--debug`.
391
391
 
392
392
  ## Migrating from a folder of scripts
393
393
 
package/dist/cli.js CHANGED
@@ -300,6 +300,7 @@ function collectFields(schema, casing, globalLongOptionFlags, path = [], inherit
300
300
  hasDefault: childSchema.default !== undefined,
301
301
  defaultValue: childSchema.default,
302
302
  requiredWhenActive,
303
+ global: childSchema.global === true ? true : undefined,
303
304
  variantId: variantContext?.id,
304
305
  variantBranchId: variantContext?.branchId
305
306
  });
@@ -494,7 +495,7 @@ function createOption(field, globalLongOptionFlags) {
494
495
  option.argParser((value) => commanderValue(parseScalarValue(value, field.schema, field.displayPath)));
495
496
  return [option];
496
497
  }
497
- const ALWAYS_GLOBAL_LONG_OPTION_FLAGS = ["--yes", "--output", "--verbose"];
498
+ const ALWAYS_GLOBAL_LONG_OPTION_FLAGS = ["--yes", "--output", "--debug"];
498
499
  function getGlobalLongOptionFlags(presetsEnabled) {
499
500
  return new Set(presetsEnabled
500
501
  ? ["--preset", ...ALWAYS_GLOBAL_LONG_OPTION_FLAGS]
@@ -817,6 +818,7 @@ function formatCommandParameterTokens(command, casing, globalLongOptionFlags) {
817
818
  const collected = collectFields(command.params, casing, globalLongOptionFlags);
818
819
  const fields = assignPositionals(collected.fields, command.positional);
819
820
  return fields
821
+ .filter((field) => field.global !== true)
820
822
  .map((field) => wrapOptionalCommandParameterToken(formatHelpFieldFlags(field, globalLongOptionFlags), field.positionalIndex === undefined && (field.optional || field.hasDefault)))
821
823
  .concat(collected.dynamicFields.flatMap((field) => formatCommandDynamicParameterTokens(field, casing)));
822
824
  }
@@ -848,6 +850,9 @@ function formatGlobalOptionRows(ctx) {
848
850
  }, {
849
851
  flags: "--output <format>",
850
852
  description: "Output format: rich, md, json."
853
+ }, {
854
+ flags: "--debug",
855
+ description: "Print stack traces for unexpected errors."
851
856
  });
852
857
  if (ctx.showVersion) {
853
858
  rows.push({
@@ -857,6 +862,33 @@ function formatGlobalOptionRows(ctx) {
857
862
  }
858
863
  return rows;
859
864
  }
865
+ function collectSchemaGlobalFieldRows(group, scope, casing, globalLongOptionFlags) {
866
+ const seen = new Map();
867
+ const visit = (node) => {
868
+ if (node.kind === "command") {
869
+ const collected = collectFields(node.params, casing, globalLongOptionFlags);
870
+ for (const field of collected.fields) {
871
+ if (field.global !== true) {
872
+ continue;
873
+ }
874
+ const dedupeKey = `${field.optionFlag}|${field.shortFlag ?? ""}`;
875
+ if (seen.has(dedupeKey)) {
876
+ continue;
877
+ }
878
+ seen.set(dedupeKey, {
879
+ flags: formatHelpFieldFlags(field, globalLongOptionFlags),
880
+ description: formatHelpFieldDescription(field)
881
+ });
882
+ }
883
+ return;
884
+ }
885
+ for (const child of getVisibleChildren(node, scope)) {
886
+ visit(child);
887
+ }
888
+ };
889
+ visit(group);
890
+ return [...seen.values()];
891
+ }
860
892
  function renderHelpSections(sections) {
861
893
  return sections.filter((section) => section.length > 0).join("\n\n");
862
894
  }
@@ -877,18 +909,24 @@ function buildUsageLine(breadcrumb, rootUsageName, suffix) {
877
909
  const tokens = [rootUsageName, subPath, suffix].filter((segment) => segment.length > 0);
878
910
  return tokens.join(" ");
879
911
  }
880
- function renderGroupHelp(group, breadcrumb, scope, casing, globalOptions, rootUsageName) {
912
+ function renderGroupHelp(group, breadcrumb, scope, casing, globalOptions, rootUsageName, isRoot) {
881
913
  const sections = [];
882
914
  const globalLongOptionFlags = getGlobalLongOptionFlags(globalOptions.presetsEnabled);
883
915
  const commandRows = formatCommandRows(group, scope, casing, globalLongOptionFlags);
884
916
  if (commandRows.length > 0) {
885
917
  sections.push(`${text.sectionHeader("Commands")}\n${formatHelpCommandList(commandRows)}`);
886
918
  }
887
- sections.push(`${text.sectionHeader("Options")}\n${formatHelpOptionList(formatGlobalOptionRows(globalOptions))}`);
919
+ if (isRoot) {
920
+ const globalRows = [
921
+ ...formatGlobalOptionRows(globalOptions),
922
+ ...collectSchemaGlobalFieldRows(group, scope, casing, globalLongOptionFlags)
923
+ ];
924
+ sections.push(`${text.sectionHeader("Global options")}\n${formatHelpOptionList(globalRows)}`);
925
+ }
888
926
  return renderHelpDocument({
889
927
  breadcrumb,
890
928
  rootUsageName,
891
- usageLine: buildUsageLine(breadcrumb, rootUsageName, "[command] [options]"),
929
+ usageLine: buildUsageLine(breadcrumb, rootUsageName, "[command] [OPTIONS]"),
892
930
  description: group.description,
893
931
  requiresAuth: group.requires?.auth === true,
894
932
  sections
@@ -900,6 +938,7 @@ function renderLeafHelp(command, breadcrumb, casing, globalOptions, rootUsageNam
900
938
  const collected = collectFields(command.params, casing, globalLongOptionFlags);
901
939
  const fields = assignPositionals(collected.fields, command.positional);
902
940
  const optionRows = fields
941
+ .filter((field) => field.global !== true)
903
942
  .map((field) => ({
904
943
  flags: formatHelpFieldFlags(field, globalLongOptionFlags),
905
944
  description: formatHelpFieldDescription(field)
@@ -908,15 +947,14 @@ function renderLeafHelp(command, breadcrumb, casing, globalOptions, rootUsageNam
908
947
  if (optionRows.length > 0) {
909
948
  sections.push(`${text.sectionHeader("Options")}\n${formatHelpOptionList(optionRows)}`);
910
949
  }
911
- sections.push(`${text.sectionHeader("Options")}\n${formatHelpOptionList(formatGlobalOptionRows(globalOptions))}`);
912
950
  const secretRows = formatSecretRows(command.secrets);
913
951
  if (secretRows.length > 0) {
914
952
  sections.push(`${text.sectionHeader("Secrets (environment)")}\n${formatHelpOptionList(secretRows)}`);
915
953
  }
916
954
  const positionalFields = fields.filter((f) => f.positionalIndex !== undefined);
917
955
  const usageSuffix = positionalFields.length > 0
918
- ? `[options] ${positionalFields.map(formatPositionalToken).join(" ")}`
919
- : "[options]";
956
+ ? `[OPTIONS] ${positionalFields.map(formatPositionalToken).join(" ")}`
957
+ : "[OPTIONS]";
920
958
  return renderHelpDocument({
921
959
  breadcrumb,
922
960
  rootUsageName,
@@ -957,7 +995,7 @@ async function renderGeneratedHelp(root, argv, options) {
957
995
  ? renderGroupHelp(target.node, target.breadcrumb, "cli", casing, {
958
996
  showVersion: options.version !== undefined,
959
997
  presetsEnabled: options.presets === true
960
- }, rootUsageName)
998
+ }, rootUsageName, target.node === root)
961
999
  : renderLeafHelp(target.node, target.breadcrumb, casing, {
962
1000
  showVersion: options.version !== undefined,
963
1001
  presetsEnabled: options.presets === true
@@ -1047,7 +1085,7 @@ function addGlobalOptions(command, presetsEnabled) {
1047
1085
  }
1048
1086
  throw new InvalidArgumentError('Invalid value for "--output". Expected one of: rich, md, markdown, json.');
1049
1087
  })
1050
- .option("--verbose", "Print stack traces for unexpected errors.");
1088
+ .option("--debug", "Print stack traces for unexpected errors.");
1051
1089
  }
1052
1090
  function setNestedValue(target, path, value) {
1053
1091
  let cursor = target;
@@ -2109,7 +2147,7 @@ async function executeCommand(state, services, requirementOptions, runtimeOption
2109
2147
  }
2110
2148
  });
2111
2149
  }
2112
- function handleRunError(error, verbose) {
2150
+ function handleRunError(error, debug) {
2113
2151
  const logger = createLogger();
2114
2152
  if (error instanceof UserError) {
2115
2153
  logger.error(error.message);
@@ -2124,8 +2162,8 @@ function handleRunError(error, verbose) {
2124
2162
  return;
2125
2163
  }
2126
2164
  const message = error instanceof Error ? error.message : String(error);
2127
- logger.error(verbose ? message : `${message} Use --verbose for a stack trace.`);
2128
- if (verbose && error instanceof Error && error.stack) {
2165
+ logger.error(debug ? message : `${message} Use --debug for a stack trace.`);
2166
+ if (debug && error instanceof Error && error.stack) {
2129
2167
  process.stderr.write(`${error.stack}\n`);
2130
2168
  }
2131
2169
  process.exitCode = 1;
@@ -2185,7 +2223,7 @@ export async function runCLI(roots, options = {}) {
2185
2223
  return;
2186
2224
  }
2187
2225
  handleRunError(error, lastActionCommand
2188
- ? Boolean(getResolvedFlags(lastActionCommand).verbose)
2189
- : process.argv.includes("--verbose"));
2226
+ ? Boolean(getResolvedFlags(lastActionCommand).debug)
2227
+ : process.argv.includes("--debug"));
2190
2228
  }
2191
2229
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -49,7 +49,7 @@
49
49
  "mustache": "^4.2.0",
50
50
  "smol-toml": "^1.3.0",
51
51
  "tiny-stdio-mcp-server": "^0.1.0",
52
- "toolcraft-schema": "^0.0.14",
52
+ "toolcraft-schema": "^0.0.15",
53
53
  "yaml": "^2.8.2"
54
54
  },
55
55
  "files": [