@llmist/cli 9.2.0 → 9.3.1

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/dist/cli.js CHANGED
@@ -79,7 +79,7 @@ import { Command, InvalidArgumentError as InvalidArgumentError2 } from "commande
79
79
  // package.json
80
80
  var package_default = {
81
81
  name: "@llmist/cli",
82
- version: "9.2.0",
82
+ version: "9.3.1",
83
83
  description: "CLI for llmist - run LLM agents from the command line",
84
84
  type: "module",
85
85
  main: "dist/cli.js",
@@ -94,6 +94,7 @@ var package_default = {
94
94
  clean: "rimraf dist",
95
95
  postinstall: "node scripts/postinstall.js"
96
96
  },
97
+ homepage: "https://llmist.dev",
97
98
  repository: {
98
99
  type: "git",
99
100
  url: "https://github.com/zbigniewsobiecki/llmist.git",
@@ -917,7 +918,9 @@ import os from "os";
917
918
  import { pathToFileURL } from "url";
918
919
  var CACHE_DIR = path4.join(os.homedir(), ".llmist", "gadget-cache");
919
920
  function isExternalPackageSpecifier(specifier) {
920
- if (/^@?[a-z0-9][\w.-]*(?:@[\w.-]+)?(?::[a-z]+)?(?:\/\w+)?$/i.test(specifier)) {
921
+ if (/^(?:@[a-z0-9][\w.-]*\/)?[a-z0-9][\w.-]*(?:@[\w.-]+)?(?::[a-z]+)?(?:\/[A-Z]\w*)?$/i.test(
922
+ specifier
923
+ )) {
921
924
  return true;
922
925
  }
923
926
  if (specifier.startsWith("git+")) {
@@ -931,49 +934,71 @@ function parseGadgetSpecifier(specifier) {
931
934
  let baseUrl;
932
935
  let ref;
933
936
  let preset;
937
+ let gadgetName;
938
+ const extractGadgetName = (str) => {
939
+ const match = str.match(/^(.*)\/([A-Z][a-zA-Z0-9]*)$/);
940
+ if (match) {
941
+ return { rest: match[1], gadgetName: match[2] };
942
+ }
943
+ return { rest: str };
944
+ };
934
945
  if (url.includes("#")) {
935
946
  const hashIndex = url.indexOf("#");
936
947
  baseUrl = url.slice(0, hashIndex);
937
- const refAndPreset = url.slice(hashIndex + 1);
938
- if (refAndPreset.includes(":")) {
939
- const colonIndex = refAndPreset.indexOf(":");
940
- ref = refAndPreset.slice(0, colonIndex);
941
- preset = refAndPreset.slice(colonIndex + 1);
948
+ let refAndRest = url.slice(hashIndex + 1);
949
+ const gadgetResult = extractGadgetName(refAndRest);
950
+ refAndRest = gadgetResult.rest;
951
+ gadgetName = gadgetResult.gadgetName;
952
+ if (refAndRest.includes(":")) {
953
+ const colonIndex = refAndRest.indexOf(":");
954
+ ref = refAndRest.slice(0, colonIndex);
955
+ preset = refAndRest.slice(colonIndex + 1);
942
956
  } else {
943
- ref = refAndPreset;
957
+ ref = refAndRest;
944
958
  }
945
959
  } else {
946
960
  const gitExtIndex = url.indexOf(".git");
947
961
  if (gitExtIndex !== -1) {
948
- const afterGit = url.slice(gitExtIndex + 4);
962
+ let afterGit = url.slice(gitExtIndex + 4);
963
+ baseUrl = url.slice(0, gitExtIndex + 4);
964
+ const gadgetResult = extractGadgetName(afterGit);
965
+ afterGit = gadgetResult.rest;
966
+ gadgetName = gadgetResult.gadgetName;
949
967
  if (afterGit.startsWith(":")) {
950
- baseUrl = url.slice(0, gitExtIndex + 4);
951
968
  preset = afterGit.slice(1);
952
- } else {
953
- baseUrl = url;
954
969
  }
955
970
  } else {
956
- baseUrl = url;
971
+ const gadgetResult = extractGadgetName(url);
972
+ baseUrl = gadgetResult.rest;
973
+ gadgetName = gadgetResult.gadgetName;
957
974
  }
958
975
  }
959
976
  return {
960
977
  type: "git",
961
978
  package: baseUrl,
962
979
  version: ref,
963
- preset
980
+ preset,
981
+ gadgetName
964
982
  };
965
983
  }
966
- const npmMatch = specifier.match(
967
- /^(@?[a-z0-9][\w.-]*)(?:@([\w.-]+))?(?::([a-z]+))?(?:\/(\w+))?$/i
984
+ let npmSpecifier = specifier;
985
+ let npmGadgetName;
986
+ const gadgetMatch = specifier.match(/^(.+)\/([A-Z][a-zA-Z0-9]*)$/);
987
+ if (gadgetMatch) {
988
+ npmSpecifier = gadgetMatch[1];
989
+ npmGadgetName = gadgetMatch[2];
990
+ }
991
+ const npmMatch = npmSpecifier.match(
992
+ /^(@[a-z0-9][\w.-]*\/[a-z0-9][\w.-]*|[a-z0-9][\w.-]*)(?:@([\w.-]+))?(?::([a-z]+))?$/i
968
993
  );
969
994
  if (npmMatch) {
970
- const [, pkg, version, preset, gadgetName] = npmMatch;
995
+ const [, pkg, version, preset] = npmMatch;
971
996
  return {
972
997
  type: "npm",
973
998
  package: pkg,
974
999
  version,
975
1000
  preset,
976
- gadgetName
1001
+ gadgetName: npmGadgetName
977
1002
  };
978
1003
  }
979
1004
  return null;
@@ -1101,10 +1126,13 @@ async function loadExternalGadgets(specifier, forceInstall = false) {
1101
1126
  const manifest = readManifest(packagePath);
1102
1127
  let entryPoint;
1103
1128
  let gadgetNames = null;
1129
+ let isSubagent = false;
1104
1130
  if (spec.gadgetName) {
1105
1131
  gadgetNames = [spec.gadgetName];
1106
- if (manifest?.subagents?.[spec.gadgetName]) {
1107
- entryPoint = manifest.subagents[spec.gadgetName].entryPoint;
1132
+ const subagentInfo = manifest?.subagents?.[spec.gadgetName];
1133
+ if (subagentInfo) {
1134
+ entryPoint = subagentInfo.entryPoint;
1135
+ isSubagent = true;
1108
1136
  } else {
1109
1137
  entryPoint = manifest?.gadgets || "./dist/index.js";
1110
1138
  }
@@ -1137,7 +1165,7 @@ async function loadExternalGadgets(specifier, forceInstall = false) {
1137
1165
  throw new Error(`Failed to import '${specifier}': ${message}`);
1138
1166
  }
1139
1167
  let gadgets = [];
1140
- if (manifest?.factory) {
1168
+ if (manifest?.factory && !isSubagent) {
1141
1169
  const exportsObj = exports;
1142
1170
  if (spec.preset && typeof exportsObj.createGadgetsByPreset === "function") {
1143
1171
  const result = await exportsObj.createGadgetsByPreset(
@@ -1227,6 +1255,14 @@ function expandHomePath(input) {
1227
1255
  }
1228
1256
  return path5.join(home, input.slice(1));
1229
1257
  }
1258
+ function parseLocalSpecifier(specifier) {
1259
+ const match = specifier.match(/^(.+):([A-Z][a-zA-Z0-9]*)$/);
1260
+ if (match) {
1261
+ const [, basePath, gadgetName] = match;
1262
+ return { path: basePath, gadgetName };
1263
+ }
1264
+ return { path: specifier };
1265
+ }
1230
1266
  function isFileLikeSpecifier(specifier) {
1231
1267
  return PATH_PREFIXES.some((prefix) => specifier.startsWith(prefix)) || specifier.includes(path5.sep);
1232
1268
  }
@@ -1310,7 +1346,10 @@ async function loadGadgets(specifiers, cwd, importer = (specifier) => import(spe
1310
1346
  throw new Error(`Failed to load external package '${specifier}': ${message}`);
1311
1347
  }
1312
1348
  }
1313
- const resolved = resolveGadgetSpecifier(specifier, cwd);
1349
+ const localSpec = isFileLikeSpecifier(specifier) ? parseLocalSpecifier(specifier) : null;
1350
+ const pathToResolve = localSpec?.path ?? specifier;
1351
+ const gadgetNameFilter = localSpec?.gadgetName;
1352
+ const resolved = resolveGadgetSpecifier(pathToResolve, cwd);
1314
1353
  let exports;
1315
1354
  try {
1316
1355
  exports = await importer(resolved);
@@ -1325,6 +1364,17 @@ async function loadGadgets(specifiers, cwd, importer = (specifier) => import(spe
1325
1364
  const message = error instanceof Error ? error.message : String(error);
1326
1365
  throw new Error(`Failed to initialize gadgets from module '${specifier}': ${message}`);
1327
1366
  }
1367
+ if (gadgetNameFilter) {
1368
+ const filtered = extracted.filter(
1369
+ (g) => g.name?.toLowerCase() === gadgetNameFilter.toLowerCase()
1370
+ );
1371
+ if (filtered.length === 0) {
1372
+ throw new Error(
1373
+ `Gadget '${gadgetNameFilter}' not found in module '${pathToResolve}'. Available gadgets: ${extracted.map((g) => g.name).join(", ")}`
1374
+ );
1375
+ }
1376
+ extracted = filtered;
1377
+ }
1328
1378
  if (extracted.length === 0) {
1329
1379
  throw new Error(`Module '${specifier}' does not export any Gadget instances.`);
1330
1380
  }