allagents 1.11.2-next.1 → 1.11.4-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 (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +155 -63
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -97,6 +97,7 @@ clients:
97
97
  | `allagents skill add <name>` | Add a skill from a repo (plural `skills` alias supported) |
98
98
  | `allagents skill list` | List skills and status |
99
99
  | `allagents mcp add <name> <commandOrUrl>` | Add an MCP server and sync to clients |
100
+ | `allagents mcp proxy <serverUrl>` | Bridge a remote HTTP MCP server to local stdio |
100
101
  | `allagents mcp list` | List workspace MCP servers |
101
102
  | `allagents workspace status` | Show workspace state |
102
103
  | `allagents self update` | Update AllAgents CLI |
package/dist/index.js CHANGED
@@ -29425,7 +29425,7 @@ function isHttpServer(config) {
29425
29425
  return typeof config === "object" && config !== null && "url" in config && typeof config.url === "string";
29426
29426
  }
29427
29427
  function toProxiedConfig(url, headers) {
29428
- const args = ["mcp", "proxy-stdio", url];
29428
+ const args = ["mcp", "proxy", url];
29429
29429
  if (headers) {
29430
29430
  for (const [key, value] of Object.entries(headers)) {
29431
29431
  args.push("--header", `${key}=${value}`);
@@ -34876,7 +34876,10 @@ async function searchSkills(query, options2 = {}, deps = {}) {
34876
34876
  const firstSegment = item.path.split("/")[0] ?? "";
34877
34877
  return !firstSegment.startsWith(".");
34878
34878
  });
34879
- await fetchStarsForItems(visible, token, fetchFn);
34879
+ await Promise.all([
34880
+ fetchStarsForItems(visible, token, fetchFn),
34881
+ enrichDescriptionsForItems(visible, token, fetchFn)
34882
+ ]);
34880
34883
  visible.sort((a, b) => b.stars - a.stars);
34881
34884
  const finalItems = visible.slice(0, limit);
34882
34885
  return {
@@ -34900,15 +34903,9 @@ function dedupeItems(items) {
34900
34903
  }
34901
34904
  async function fetchStarsForItems(items, token, fetchFn) {
34902
34905
  const uniqueRepos = [...new Set(items.map((i2) => i2.repo))];
34903
- const headers = {
34904
- Accept: "application/vnd.github+json",
34905
- "X-GitHub-Api-Version": "2022-11-28",
34906
- "User-Agent": "allagents-cli"
34907
- };
34908
- if (token)
34909
- headers.Authorization = `token ${token}`;
34906
+ const headers = buildGitHubApiHeaders(token);
34910
34907
  const starsMap = new Map;
34911
- await Promise.allSettled(uniqueRepos.map(async (repo) => {
34908
+ await forEachWithConcurrency(uniqueRepos, ENRICHMENT_CONCURRENCY, async (repo) => {
34912
34909
  try {
34913
34910
  const res = await fetchFn(`https://api.github.com/repos/${repo}`, { headers });
34914
34911
  if (!res.ok)
@@ -34916,15 +34913,78 @@ async function fetchStarsForItems(items, token, fetchFn) {
34916
34913
  const body = await res.json();
34917
34914
  starsMap.set(repo, body.stargazers_count ?? 0);
34918
34915
  } catch {}
34919
- }));
34916
+ });
34920
34917
  for (const item of items) {
34921
34918
  const s = starsMap.get(item.repo);
34922
34919
  if (s !== undefined)
34923
34920
  item.stars = s;
34924
34921
  }
34925
34922
  }
34926
- var OWNER_REGEX, COULD_BE_OWNER_REGEX, SkillSearchError;
34923
+ async function enrichDescriptionsForItems(items, token, fetchFn) {
34924
+ const headers = buildGitHubApiHeaders(token);
34925
+ const descriptionMap = new Map;
34926
+ const uniqueSkills = [...new Set(items.map((item) => `${item.repo}#${item.sha}`))];
34927
+ await forEachWithConcurrency(uniqueSkills, ENRICHMENT_CONCURRENCY, async (key) => {
34928
+ const [repo, sha] = key.split("#");
34929
+ if (!repo || !sha)
34930
+ return;
34931
+ try {
34932
+ const res = await fetchFn(`https://api.github.com/repos/${repo}/git/blobs/${sha}`, { headers });
34933
+ if (!res.ok)
34934
+ return;
34935
+ const body = await res.json();
34936
+ const content = decodeGitBlob(body.content, body.encoding);
34937
+ if (!content)
34938
+ return;
34939
+ const metadata = parseSkillMetadata(content);
34940
+ if (!metadata?.description)
34941
+ return;
34942
+ descriptionMap.set(key, metadata.description);
34943
+ } catch {}
34944
+ });
34945
+ for (const item of items) {
34946
+ const description = descriptionMap.get(`${item.repo}#${item.sha}`);
34947
+ if (description)
34948
+ item.description = description;
34949
+ }
34950
+ }
34951
+ async function forEachWithConcurrency(items, concurrency, worker) {
34952
+ if (items.length === 0)
34953
+ return;
34954
+ let nextIndex = 0;
34955
+ const runWorker = async () => {
34956
+ while (true) {
34957
+ const currentIndex = nextIndex++;
34958
+ if (currentIndex >= items.length)
34959
+ return;
34960
+ await worker(items[currentIndex]);
34961
+ }
34962
+ };
34963
+ const workerCount = Math.min(concurrency, items.length);
34964
+ await Promise.all(Array.from({ length: workerCount }, () => runWorker()));
34965
+ }
34966
+ function buildGitHubApiHeaders(token) {
34967
+ const headers = {
34968
+ Accept: "application/vnd.github+json",
34969
+ "X-GitHub-Api-Version": "2022-11-28",
34970
+ "User-Agent": "allagents-cli"
34971
+ };
34972
+ if (token)
34973
+ headers.Authorization = `token ${token}`;
34974
+ return headers;
34975
+ }
34976
+ function decodeGitBlob(content, encoding) {
34977
+ if (!content)
34978
+ return;
34979
+ if (!encoding || encoding === "utf-8")
34980
+ return content;
34981
+ if (encoding !== "base64")
34982
+ return;
34983
+ return Buffer.from(content.replace(/\s+/g, ""), "base64").toString("utf8");
34984
+ }
34985
+ var OWNER_REGEX, COULD_BE_OWNER_REGEX, ENRICHMENT_CONCURRENCY = 10, SkillSearchError;
34927
34986
  var init_skill_search = __esm(() => {
34987
+ init_skill();
34928
34988
  OWNER_REGEX = /^[A-Za-z0-9-]{1,39}$/;
34929
34989
  COULD_BE_OWNER_REGEX = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$/;
34930
34990
  SkillSearchError = class SkillSearchError extends Error {
@@ -41907,7 +41967,7 @@ var package_default;
41907
41967
  var init_package = __esm(() => {
41908
41968
  package_default = {
41909
41969
  name: "allagents",
41910
- version: "1.11.2-next.1",
41970
+ version: "1.11.4-next.1",
41911
41971
  packageManager: "bun@1.3.12",
41912
41972
  description: "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
41913
41973
  type: "module",
@@ -44754,7 +44814,7 @@ var skillsRemoveMeta = {
44754
44814
  };
44755
44815
  var skillsSearchMeta = {
44756
44816
  command: "skill search",
44757
- 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 picker and offers to install the selected skill.",
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.",
44758
44818
  whenToUse: 'To discover available skills from public GitHub repositories without leaving the CLI. Bridges "I want a skill that does X" → install.',
44759
44819
  examples: [
44760
44820
  "allagents skill search terraform",
@@ -44762,7 +44822,7 @@ var skillsSearchMeta = {
44762
44822
  "allagents skill search docs --page 2 --limit 10",
44763
44823
  "allagents --json skill search docs --limit 5"
44764
44824
  ],
44765
- expectedOutput: "Skills sorted by star count: repo, skill name, stars, description. In TTY mode, followed by a filter-as-you-type install prompt.",
44825
+ expectedOutput: "Skills sorted by star count: repo, skill name, stars, description. In TTY mode, followed by a searchable multi-select install prompt.",
44766
44826
  positionals: [
44767
44827
  { name: "query", type: "string", required: true, description: "Search query (≥2 characters)." }
44768
44828
  ],
@@ -45790,9 +45850,30 @@ Use --plugin to specify: allagents skill add ${skill} --plugin <name>`;
45790
45850
  }
45791
45851
  }
45792
45852
  });
45853
+ function formatSkillSearchSummary(count, query, truncated) {
45854
+ return `Showing ${count} skill${count !== 1 ? "s" : ""} matching "${query}"${truncated ? " (truncated)" : ""}`;
45855
+ }
45856
+ function formatSkillSearchHint(item) {
45857
+ return [
45858
+ item.stars > 0 ? `★ ${item.stars}` : "",
45859
+ item.description ?? ""
45860
+ ].filter(Boolean).join(" ");
45861
+ }
45862
+ function collectSelectedSkillSearchRepos(items, selectedPaths) {
45863
+ const selectedSet = new Set(selectedPaths);
45864
+ const repos = [];
45865
+ const seenRepos = new Set;
45866
+ for (const item of items) {
45867
+ if (!selectedSet.has(item.path) || seenRepos.has(item.repo))
45868
+ continue;
45869
+ seenRepos.add(item.repo);
45870
+ repos.push(item.repo);
45871
+ }
45872
+ return repos;
45873
+ }
45793
45874
  function printSearchResults(items, query, truncated) {
45794
45875
  console.log(`
45795
- Showing ${items.length} result${items.length !== 1 ? "s" : ""} for "${query}"${truncated ? " (truncated)" : ""}
45876
+ ${formatSkillSearchSummary(items.length, query, truncated)}
45796
45877
  `);
45797
45878
  for (const item of items) {
45798
45879
  const repoCol = item.repo.padEnd(30);
@@ -45804,14 +45885,21 @@ Showing ${items.length} result${items.length !== 1 ? "s" : ""} for "${query}"${t
45804
45885
  }
45805
45886
  console.log("");
45806
45887
  }
45807
- async function installFromSearch(repo) {
45888
+ async function installFromSearch(repos) {
45808
45889
  const p = await Promise.resolve().then(() => (init_dist2(), exports_dist));
45809
45890
  const workspacePath = process.cwd();
45810
- const isInstalledProject = hasProjectConfig(workspacePath) ? await hasPlugin(repo, workspacePath) : false;
45811
- const isInstalledUser = await hasUserPlugin(repo);
45812
- if (isInstalledProject || isInstalledUser) {
45813
- const scopeLabel = isInstalledUser ? "user" : "project";
45814
- p.log.info(`Plugin ${source_default.bold(repo)} is already installed (${scopeLabel} scope).`);
45891
+ const installableRepos = [];
45892
+ for (const repo of repos) {
45893
+ const isInstalledProject = hasProjectConfig(workspacePath) ? await hasPlugin(repo, workspacePath) : false;
45894
+ const isInstalledUser = await hasUserPlugin(repo);
45895
+ if (isInstalledProject || isInstalledUser) {
45896
+ const scopeLabel = isInstalledUser ? "user" : "project";
45897
+ p.log.info(`Plugin ${source_default.bold(repo)} is already installed (${scopeLabel} scope).`);
45898
+ continue;
45899
+ }
45900
+ installableRepos.push(repo);
45901
+ }
45902
+ if (installableRepos.length === 0) {
45815
45903
  return false;
45816
45904
  }
45817
45905
  const scopeChoice = await p.select({
@@ -45824,36 +45912,36 @@ async function installFromSearch(repo) {
45824
45912
  if (p.isCancel(scopeChoice))
45825
45913
  return false;
45826
45914
  const s = p.spinner();
45827
- s.start("Installing plugin...");
45915
+ s.start(`Installing ${installableRepos.length === 1 ? "plugin" : "plugins"}...`);
45828
45916
  try {
45829
- if (scopeChoice === "project") {
45830
- const result = await addPlugin(repo, workspacePath);
45917
+ const installedRepos = [];
45918
+ const failedRepos = [];
45919
+ for (const repo of installableRepos) {
45920
+ const result = scopeChoice === "project" ? await addPlugin(repo, workspacePath) : await addUserPlugin(repo);
45831
45921
  if (!result.success) {
45832
- s.stop("Installation failed");
45833
- p.log.error(result.error ?? "Unknown error");
45834
- return false;
45922
+ failedRepos.push({ repo, error: result.error ?? "Unknown error" });
45923
+ continue;
45835
45924
  }
45836
- s.message("Syncing...");
45837
- const syncResult = await syncWorkspace(workspacePath);
45838
- s.stop("Installed and synced");
45839
- const lines = formatVerboseSyncLines(syncResult);
45840
- if (lines.length > 0)
45841
- p.note(lines.join(`
45842
- `), `Installed: ${repo}`);
45843
- } else {
45844
- const result = await addUserPlugin(repo);
45845
- if (!result.success) {
45846
- s.stop("Installation failed");
45847
- p.log.error(result.error ?? "Unknown error");
45848
- return false;
45925
+ installedRepos.push(repo);
45926
+ }
45927
+ if (installedRepos.length === 0) {
45928
+ s.stop("Installation failed");
45929
+ for (const { repo, error } of failedRepos) {
45930
+ p.log.error(`${source_default.bold(repo)}: ${error}`);
45849
45931
  }
45850
- s.message("Syncing...");
45851
- const syncResult = await syncUserWorkspace();
45852
- s.stop("Installed and synced");
45853
- const lines = formatVerboseSyncLines(syncResult);
45854
- if (lines.length > 0)
45855
- p.note(lines.join(`
45856
- `), `Installed: ${repo}`);
45932
+ return false;
45933
+ }
45934
+ s.message("Syncing...");
45935
+ const syncResult = scopeChoice === "project" ? await syncWorkspace(workspacePath) : await syncUserWorkspace();
45936
+ s.stop(installedRepos.length === 1 ? "Installed and synced" : "Installed plugins and synced");
45937
+ for (const { repo, error } of failedRepos) {
45938
+ p.log.error(`${source_default.bold(repo)}: ${error}`);
45939
+ }
45940
+ const lines = formatVerboseSyncLines(syncResult);
45941
+ const noteLines = installedRepos.length > 1 ? [...installedRepos, "", ...lines] : lines;
45942
+ if (noteLines.length > 0) {
45943
+ p.note(noteLines.join(`
45944
+ `), installedRepos.length === 1 ? `Installed: ${installedRepos[0]}` : `Installed: ${installedRepos.length} plugins`);
45857
45945
  }
45858
45946
  return true;
45859
45947
  } catch (err) {
@@ -45932,23 +46020,27 @@ var searchCmd = import_cmd_ts3.command({
45932
46020
  printSearchResults(result.items, query, result.truncated);
45933
46021
  return;
45934
46022
  }
45935
- const { autocomplete, isCancel } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
45936
- printSearchResults(result.items, query, result.truncated);
46023
+ const { autocompleteMultiselect: autocompleteMultiselect2, isCancel, log } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
46024
+ log.success(formatSkillSearchSummary(result.items.length, query, result.truncated));
45937
46025
  const options2 = result.items.map((item) => ({
45938
46026
  label: `${qualifiedName(item)} ${source_default.dim(item.repo)}`,
45939
- value: item.repo,
45940
- hint: `${item.stars > 0 ? `★${item.stars} ` : ""}${item.description ?? ""}`
46027
+ value: item.path,
46028
+ hint: formatSkillSearchHint(item)
45941
46029
  }));
45942
- options2.push({ label: "Cancel", value: "__cancel__", hint: "" });
45943
- const selected = await autocomplete({
45944
- message: `Select a skill to install (type to filter ${result.items.length} results)`,
46030
+ const selected = await autocompleteMultiselect2({
46031
+ message: "Select skills to install",
45945
46032
  options: options2,
45946
- placeholder: "Type to filter..."
46033
+ placeholder: "Type to filter...",
46034
+ required: false
45947
46035
  });
45948
- if (isCancel(selected) || selected === "__cancel__") {
46036
+ if (isCancel(selected)) {
46037
+ return;
46038
+ }
46039
+ const reposToInstall = collectSelectedSkillSearchRepos(result.items, selected);
46040
+ if (reposToInstall.length === 0) {
45949
46041
  return;
45950
46042
  }
45951
- await installFromSearch(selected);
46043
+ await installFromSearch(reposToInstall);
45952
46044
  } catch (error) {
45953
46045
  if (error instanceof SkillSearchError) {
45954
46046
  const exitCode = error.kind === "validation" ? 2 : 1;
@@ -56220,9 +56312,9 @@ var mcpRemoveCmd = import_cmd_ts5.command({
56220
56312
  await runPostMutationSync("mcp remove", `✓ Removed MCP server '${name}' from workspace.yaml`, { name });
56221
56313
  }
56222
56314
  });
56223
- var mcpProxyStdioCmd = import_cmd_ts5.command({
56224
- name: "proxy-stdio",
56225
- description: "Internal: expose a remote HTTP MCP server as local stdio",
56315
+ var mcpProxyCmd = import_cmd_ts5.command({
56316
+ name: "proxy",
56317
+ description: "Expose a remote HTTP MCP server locally over stdio",
56226
56318
  args: {
56227
56319
  serverUrl: import_cmd_ts5.positional({ type: import_cmd_ts5.string, displayName: "serverUrl" }),
56228
56320
  header: import_cmd_ts5.multioption({
@@ -56234,7 +56326,7 @@ var mcpProxyStdioCmd = import_cmd_ts5.command({
56234
56326
  handler: async ({ serverUrl, header }) => {
56235
56327
  const headerResult = parseKeyValuePairs(header, "--header");
56236
56328
  if ("error" in headerResult) {
56237
- exitWithError("mcp proxy-stdio", headerResult.error);
56329
+ exitWithError("mcp proxy", headerResult.error);
56238
56330
  }
56239
56331
  await runHttpMcpStdioProxy(serverUrl, headerResult.values);
56240
56332
  }
@@ -56356,7 +56448,7 @@ var mcpCmd = conciseSubcommands({
56356
56448
  description: "Manage MCP servers for AI clients",
56357
56449
  cmds: {
56358
56450
  add: mcpAddCmd,
56359
- "proxy-stdio": mcpProxyStdioCmd,
56451
+ proxy: mcpProxyCmd,
56360
56452
  remove: mcpRemoveCmd,
56361
56453
  list: mcpListCmd,
56362
56454
  get: mcpGetCmd,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "1.11.2-next.1",
3
+ "version": "1.11.4-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",