allagents 1.11.4-next.1 → 1.11.5-next.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.
Files changed (2) hide show
  1. package/dist/index.js +149 -20
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -34841,6 +34841,23 @@ async function runOneQuery(q3, page, limit, token, fetchFn) {
34841
34841
  truncated: Boolean(parsed.incomplete_results)
34842
34842
  };
34843
34843
  }
34844
+ async function fetchPrimaryPages(q3, page, limit, token, fetchFn) {
34845
+ const needed = page * limit * 3;
34846
+ const numPages = Math.min(Math.max(1, Math.ceil(needed / SEARCH_PAGE_SIZE)), MAX_RESULTS / SEARCH_PAGE_SIZE);
34847
+ const items = [];
34848
+ let total = 0;
34849
+ let truncated = false;
34850
+ for (let currentPage = 1;currentPage <= numPages; currentPage += 1) {
34851
+ const result = await runOneQuery(q3, currentPage, SEARCH_PAGE_SIZE, token, fetchFn);
34852
+ items.push(...result.items);
34853
+ total = result.total;
34854
+ truncated = truncated || result.truncated;
34855
+ if (result.items.length < SEARCH_PAGE_SIZE) {
34856
+ break;
34857
+ }
34858
+ }
34859
+ return { items, total, truncated };
34860
+ }
34844
34861
  async function searchSkills(query, options2 = {}, deps = {}) {
34845
34862
  validateSkillSearchArgs(query, options2);
34846
34863
  const fetchFn = deps.fetch ?? fetch;
@@ -34850,7 +34867,7 @@ async function searchSkills(query, options2 = {}, deps = {}) {
34850
34867
  const limit = options2.limit ?? 15;
34851
34868
  const token = await (deps.tokenResolver ?? resolveGhToken)();
34852
34869
  const queries = buildSearchQueries(query, options2.owner);
34853
- const settled = await Promise.allSettled(queries.map((entry) => runOneQuery(entry.q, page, limit, token, fetchFn)));
34870
+ const settled = await Promise.allSettled(queries.map((entry) => entry.priority === 4 ? fetchPrimaryPages(entry.q, page, limit, token, fetchFn) : runOneQuery(entry.q, 1, SEARCH_PAGE_SIZE, token, fetchFn)));
34854
34871
  const primaryIdx = queries.findIndex((q3) => q3.priority === 4);
34855
34872
  const primarySettled = settled[primaryIdx];
34856
34873
  if (primarySettled?.status === "rejected") {
@@ -34876,17 +34893,21 @@ async function searchSkills(query, options2 = {}, deps = {}) {
34876
34893
  const firstSegment = item.path.split("/")[0] ?? "";
34877
34894
  return !firstSegment.startsWith(".");
34878
34895
  });
34896
+ rankByRelevance(visible, query);
34897
+ const workingSet = truncateForProcessing(visible, page, limit);
34879
34898
  await Promise.all([
34880
- fetchStarsForItems(visible, token, fetchFn),
34881
- enrichDescriptionsForItems(visible, token, fetchFn)
34899
+ fetchStarsForItems(workingSet, token, fetchFn),
34900
+ enrichDescriptionsForItems(workingSet, token, fetchFn)
34882
34901
  ]);
34883
- visible.sort((a, b) => b.stars - a.stars);
34884
- const finalItems = visible.slice(0, limit);
34902
+ const filtered = filterByRelevance(workingSet, query);
34903
+ rankByRelevance(filtered, query);
34904
+ const dedupedByName = deduplicateByName(filtered);
34905
+ const { items: finalItems, totalPages } = paginate(dedupedByName, page, limit);
34885
34906
  return {
34886
34907
  query,
34887
34908
  items: finalItems,
34888
- total: finalItems.length,
34889
- truncated: buckets.some((b) => b.result.truncated) || visible.length > limit
34909
+ total: dedupedByName.length,
34910
+ truncated: buckets.some((b) => b.result.truncated) || totalPages > page
34890
34911
  };
34891
34912
  }
34892
34913
  function dedupeItems(items) {
@@ -34901,6 +34922,73 @@ function dedupeItems(items) {
34901
34922
  }
34902
34923
  return out;
34903
34924
  }
34925
+ function splitRepo(item) {
34926
+ const [owner = item.repo, repoName = ""] = item.repo.split("/", 2);
34927
+ return { owner, repoName };
34928
+ }
34929
+ function relevanceScore(item, query) {
34930
+ const term = query.trim().toLowerCase();
34931
+ const termHyphen = term.replace(/ /g, "-");
34932
+ const name = item.name.toLowerCase();
34933
+ const namespace = item.namespace.toLowerCase();
34934
+ const description = item.description.toLowerCase();
34935
+ let score = 0;
34936
+ if (name === term || name === termHyphen) {
34937
+ score += 3000;
34938
+ } else if (name.includes(term) || name.includes(termHyphen)) {
34939
+ score += 1000;
34940
+ }
34941
+ if (namespace?.includes(term)) {
34942
+ score += 500;
34943
+ }
34944
+ if (description.includes(term)) {
34945
+ score += 100;
34946
+ }
34947
+ if (item.stars > 0) {
34948
+ score += Math.floor(Math.sqrt(item.stars) * 30);
34949
+ }
34950
+ return score;
34951
+ }
34952
+ function rankByRelevance(items, query) {
34953
+ items.sort((a, b) => relevanceScore(b, query) - relevanceScore(a, query));
34954
+ }
34955
+ function filterByRelevance(items, query) {
34956
+ const term = query.trim().toLowerCase();
34957
+ const termHyphen = term.replace(/ /g, "-");
34958
+ return items.filter((item) => {
34959
+ const { owner, repoName } = splitRepo(item);
34960
+ return item.name.toLowerCase().includes(term) || item.name.toLowerCase().includes(termHyphen) || item.namespace.toLowerCase().includes(term) || item.description.toLowerCase().includes(term) || owner.toLowerCase().includes(term) || repoName.toLowerCase().includes(term);
34961
+ });
34962
+ }
34963
+ function truncateForProcessing(items, page, limit) {
34964
+ const maxToProcess = Math.max(page * limit * 3, limit * 3);
34965
+ return items.length > maxToProcess ? items.slice(0, maxToProcess) : items;
34966
+ }
34967
+ function deduplicateByName(items) {
34968
+ const maxPerName = 3;
34969
+ const counts = new Map;
34970
+ const out = [];
34971
+ for (const item of items) {
34972
+ const key = qualifiedName(item).toLowerCase();
34973
+ const count = counts.get(key) ?? 0;
34974
+ if (count >= maxPerName)
34975
+ continue;
34976
+ counts.set(key, count + 1);
34977
+ out.push(item);
34978
+ }
34979
+ return out;
34980
+ }
34981
+ function paginate(items, page, limit) {
34982
+ if (items.length === 0) {
34983
+ return { items: [], totalPages: 0 };
34984
+ }
34985
+ const totalPages = Math.ceil(items.length / limit);
34986
+ const start = (page - 1) * limit;
34987
+ return {
34988
+ items: items.slice(start, start + limit),
34989
+ totalPages
34990
+ };
34991
+ }
34904
34992
  async function fetchStarsForItems(items, token, fetchFn) {
34905
34993
  const uniqueRepos = [...new Set(items.map((i2) => i2.repo))];
34906
34994
  const headers = buildGitHubApiHeaders(token);
@@ -34982,7 +35070,7 @@ function decodeGitBlob(content, encoding) {
34982
35070
  return;
34983
35071
  return Buffer.from(content.replace(/\s+/g, ""), "base64").toString("utf8");
34984
35072
  }
34985
- var OWNER_REGEX, COULD_BE_OWNER_REGEX, ENRICHMENT_CONCURRENCY = 10, SkillSearchError;
35073
+ var OWNER_REGEX, SEARCH_PAGE_SIZE = 100, MAX_RESULTS = 1000, COULD_BE_OWNER_REGEX, ENRICHMENT_CONCURRENCY = 10, SkillSearchError;
34986
35074
  var init_skill_search = __esm(() => {
34987
35075
  init_skill();
34988
35076
  OWNER_REGEX = /^[A-Za-z0-9-]{1,39}$/;
@@ -41967,7 +42055,7 @@ var package_default;
41967
42055
  var init_package = __esm(() => {
41968
42056
  package_default = {
41969
42057
  name: "allagents",
41970
- version: "1.11.4-next.1",
42058
+ version: "1.11.5-next.1",
41971
42059
  packageManager: "bun@1.3.12",
41972
42060
  description: "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
41973
42061
  type: "module",
@@ -44814,15 +44902,17 @@ var skillsRemoveMeta = {
44814
44902
  };
44815
44903
  var skillsSearchMeta = {
44816
44904
  command: "skill search",
44817
- description: "Search GitHub for skills by querying SKILL.md files via the Code Search API. Results are sorted by star count. In TTY mode, shows a filter-as-you-type multi-select picker and offers to install the selected skills.",
44905
+ description: "Search GitHub for skills by querying SKILL.md files via the Code Search API. Results are ranked by relevance, with skill-name matches first. In TTY mode, shows a filter-as-you-type multi-select picker and offers to install the selected skills.",
44818
44906
  whenToUse: 'To discover available skills from public GitHub repositories without leaving the CLI. Bridges "I want a skill that does X" → install.',
44819
44907
  examples: [
44820
44908
  "allagents skill search terraform",
44909
+ "allagents skill pr-search",
44910
+ 'allagents skill "pr search"',
44821
44911
  "allagents skill search terraform --owner hashicorp",
44822
44912
  "allagents skill search docs --page 2 --limit 10",
44823
44913
  "allagents --json skill search docs --limit 5"
44824
44914
  ],
44825
- expectedOutput: "Skills sorted by star count: repo, skill name, stars, description. In TTY mode, followed by a searchable multi-select install prompt.",
44915
+ expectedOutput: "Skills ranked by relevance: repo, skill name, stars, description. In TTY mode, followed by a searchable multi-select install prompt.",
44826
44916
  positionals: [
44827
44917
  { name: "query", type: "string", required: true, description: "Search query (≥2 characters)." }
44828
44918
  ],
@@ -45954,7 +46044,7 @@ var searchCmd = import_cmd_ts3.command({
45954
46044
  name: "search",
45955
46045
  description: buildDescription(skillsSearchMeta),
45956
46046
  args: {
45957
- query: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "query" }),
46047
+ query: import_cmd_ts3.restPositionals({ type: import_cmd_ts3.string, displayName: "query" }),
45958
46048
  owner: import_cmd_ts3.option({
45959
46049
  type: import_cmd_ts3.optional(import_cmd_ts3.string),
45960
46050
  long: "owner",
@@ -45973,6 +46063,7 @@ var searchCmd = import_cmd_ts3.command({
45973
46063
  },
45974
46064
  handler: async ({ query, owner, page, limit }) => {
45975
46065
  try {
46066
+ const searchQuery = query.join(" ").trim();
45976
46067
  const opts = {};
45977
46068
  if (owner)
45978
46069
  opts.owner = owner;
@@ -46002,7 +46093,7 @@ var searchCmd = import_cmd_ts3.command({
46002
46093
  }
46003
46094
  opts.limit = n;
46004
46095
  }
46005
- const result = await searchSkills(query, opts);
46096
+ const result = await searchSkills(searchQuery, opts);
46006
46097
  if (isJsonMode()) {
46007
46098
  jsonOutput({
46008
46099
  success: true,
@@ -46012,16 +46103,16 @@ var searchCmd = import_cmd_ts3.command({
46012
46103
  return;
46013
46104
  }
46014
46105
  if (result.items.length === 0) {
46015
- console.log(`No skills found for "${query}".`);
46106
+ console.log(`No skills found for "${searchQuery}".`);
46016
46107
  return;
46017
46108
  }
46018
46109
  const isTTY = process.stdout.isTTY && process.stdin.isTTY;
46019
46110
  if (!isTTY) {
46020
- printSearchResults(result.items, query, result.truncated);
46111
+ printSearchResults(result.items, searchQuery, result.truncated);
46021
46112
  return;
46022
46113
  }
46023
46114
  const { autocompleteMultiselect: autocompleteMultiselect2, isCancel, log } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
46024
- log.success(formatSkillSearchSummary(result.items.length, query, result.truncated));
46115
+ log.success(formatSkillSearchSummary(result.items.length, searchQuery, result.truncated));
46025
46116
  const options2 = result.items.map((item) => ({
46026
46117
  label: `${qualifiedName(item)} ${source_default.dim(item.repo)}`,
46027
46118
  value: item.path,
@@ -58135,6 +58226,44 @@ var selfCmd = conciseSubcommands({
58135
58226
  }
58136
58227
  });
58137
58228
 
58229
+ // src/cli/skill-arg-normalizer.ts
58230
+ var SKILL_SUBCOMMANDS = new Set(["list", "remove", "add", "search"]);
58231
+ function normalizeSkillAlias(args) {
58232
+ if (args.length === 0)
58233
+ return args;
58234
+ return args[0] === "skills" ? ["skill", ...args.slice(1)] : args;
58235
+ }
58236
+ function shouldUseSkillSearchShorthand(rest) {
58237
+ const first2 = rest[0] ?? "";
58238
+ if (rest.length === 0)
58239
+ return false;
58240
+ if (first2.startsWith("-") || SKILL_SUBCOMMANDS.has(first2))
58241
+ return false;
58242
+ return rest.length > 1 || /[-\s]/.test(first2);
58243
+ }
58244
+ function normalizeSkillHelpArgs(args) {
58245
+ const normalized = normalizeSkillAlias(args);
58246
+ if (normalized.length === 0 || normalized[0] !== "skill") {
58247
+ return normalized;
58248
+ }
58249
+ const [, ...rest] = normalized;
58250
+ return shouldUseSkillSearchShorthand(rest) ? ["skill", "search"] : normalized;
58251
+ }
58252
+ function normalizeSkillArgs(args) {
58253
+ const normalized = normalizeSkillAlias(args);
58254
+ if (normalized.length === 0 || normalized[0] !== "skill") {
58255
+ return args;
58256
+ }
58257
+ const [, ...rest] = normalized;
58258
+ if (rest.length === 0) {
58259
+ return ["skill"];
58260
+ }
58261
+ if (!shouldUseSkillSearchShorthand(rest)) {
58262
+ return ["skill", ...rest];
58263
+ }
58264
+ return ["skill", "search", ...rest];
58265
+ }
58266
+
58138
58267
  // src/cli/agent-help.ts
58139
58268
  var allCommands = [
58140
58269
  initMeta,
@@ -58189,7 +58318,7 @@ function findMetaByCommand(commandPath) {
58189
58318
  }
58190
58319
  function printAgentHelp(args, version2) {
58191
58320
  const positional5 = args.filter((a) => !a.startsWith("-"));
58192
- const normalized = positional5[0] === "skills" ? ["skill", ...positional5.slice(1)] : positional5;
58321
+ const normalized = normalizeSkillHelpArgs(positional5);
58193
58322
  const commandPath = normalized.join(" ");
58194
58323
  if (!commandPath) {
58195
58324
  const tree = {
@@ -58242,8 +58371,8 @@ var app = conciseSubcommands({
58242
58371
  var rawArgs = process.argv.slice(2);
58243
58372
  var { args: argsNoJson, json: json2, jsonFields: jsonFields2 } = extractJsonFlag(rawArgs);
58244
58373
  var { args: argsNoJq, jqExpr: jqExpr2 } = extractJqFlag(argsNoJson);
58245
- var { args: argsWithSkillAlias, agentHelp } = extractAgentHelpFlag(argsNoJq);
58246
- var finalArgs = argsWithSkillAlias[0] === "skills" ? ["skill", ...argsWithSkillAlias.slice(1)] : argsWithSkillAlias;
58374
+ var { args: argsAfterAgentHelp, agentHelp } = extractAgentHelpFlag(argsNoJq);
58375
+ var finalArgs = normalizeSkillArgs(argsAfterAgentHelp);
58247
58376
  if (jqExpr2 && !json2) {
58248
58377
  process.stderr.write(`Error: --jq requires --json.
58249
58378
  `);
@@ -58269,7 +58398,7 @@ if (!agentHelp && !json2 && !isWizard) {
58269
58398
  `);
58270
58399
  }
58271
58400
  if (agentHelp) {
58272
- printAgentHelp(finalArgs, package_default.version);
58401
+ printAgentHelp(normalizeSkillHelpArgs(argsAfterAgentHelp), package_default.version);
58273
58402
  } else if (isWizard) {
58274
58403
  const { runWizard: runWizard2 } = await Promise.resolve().then(() => (init_wizard(), exports_wizard));
58275
58404
  await runWizard2();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "1.11.4-next.1",
3
+ "version": "1.11.5-next.1",
4
4
  "packageManager": "bun@1.3.12",
5
5
  "description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
6
6
  "type": "module",