agentshq 0.1.1 → 0.1.3

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/cli.mjs +70 -34
  2. package/package.json +48 -10
package/dist/cli.mjs CHANGED
@@ -31,29 +31,48 @@ const DEFAULT_REPO = "ulpi-io/agents";
31
31
  //#endregion
32
32
  //#region src/source-parser.ts
33
33
  /**
34
- * Extract owner/repo (or group/subgroup/repo for GitLab) from a parsed source
34
+ * Extract host/owner/repo (e.g., "github.com/ulpi-io/agents") from a parsed source
35
35
  * for lockfile tracking and telemetry.
36
36
  * Returns null for local paths or unparseable sources.
37
- * Supports any Git host with an owner/repo URL structure, including GitLab subgroups.
37
+ * The host is derived from the parsed source type:
38
+ * - github → github.com
39
+ * - gitlab → gitlab.com (or the actual host for self-hosted instances)
40
+ * - git → extracted from URL
41
+ * Bare owner/repo CLI input defaults to github.com.
38
42
  */
39
43
  function getOwnerRepo(parsed) {
40
44
  if (parsed.type === "local") return null;
41
- const sshMatch = parsed.url.match(/^git@[^:]+:(.+)$/);
45
+ const sshMatch = parsed.url.match(/^git@([^:]+):(.+)$/);
42
46
  if (sshMatch) {
43
- let path = sshMatch[1];
47
+ const host = sshMatch[1];
48
+ let path = sshMatch[2];
44
49
  path = path.replace(/\.git$/, "");
45
- if (path.includes("/")) return path;
50
+ if (path.includes("/")) return `${host}/${path}`;
46
51
  return null;
47
52
  }
48
53
  if (!parsed.url.startsWith("http://") && !parsed.url.startsWith("https://")) return null;
49
54
  try {
50
- let path = new URL(parsed.url).pathname.slice(1);
55
+ const url = new URL(parsed.url);
56
+ const host = url.hostname;
57
+ let path = url.pathname.slice(1);
51
58
  path = path.replace(/\.git$/, "");
52
- if (path.includes("/")) return path;
59
+ if (path.includes("/")) return `${host}/${path}`;
53
60
  } catch {}
54
61
  return null;
55
62
  }
56
63
  /**
64
+ * Strip the host prefix from a host/owner/repo string to get bare owner/repo.
65
+ * Returns null if the input doesn't have at least 3 segments (host/owner/repo).
66
+ * For GitLab subgroups, returns the full path after the host (e.g., "group/subgroup/repo").
67
+ */
68
+ function stripHost(hostOwnerRepo) {
69
+ const slashIndex = hostOwnerRepo.indexOf("/");
70
+ if (slashIndex === -1) return null;
71
+ const rest = hostOwnerRepo.slice(slashIndex + 1);
72
+ if (!rest.includes("/")) return null;
73
+ return rest;
74
+ }
75
+ /**
57
76
  * Extract owner and repo from an owner/repo string.
58
77
  * Returns null if the format is invalid.
59
78
  */
@@ -631,9 +650,9 @@ function detectFormat(filePath) {
631
650
  function parseFromFlatMd(content, filePath) {
632
651
  try {
633
652
  const { data, content: body } = (0, import_gray_matter.default)(content);
634
- const name = typeof data.name === "string" && data.name.length > 0 ? data.name : basename(filePath, ".md");
653
+ const name = typeof data.name === "string" && data.name.length > 0 ? data.name : void 0;
635
654
  const description = typeof data.description === "string" && data.description.length > 0 ? data.description : void 0;
636
- if (!name && !description) return null;
655
+ if (!name) return null;
637
656
  return {
638
657
  name,
639
658
  description: description ?? "",
@@ -1001,26 +1020,36 @@ async function discoverAgents(basePath, subpath, options) {
1001
1020
  join(searchPath, "agents/.system"),
1002
1021
  join(searchPath, ".agent/agents"),
1003
1022
  join(searchPath, ".agents/agents"),
1023
+ join(searchPath, ".augment/agents"),
1004
1024
  join(searchPath, ".claude/agents"),
1005
1025
  join(searchPath, ".cline/agents"),
1006
1026
  join(searchPath, ".codebuddy/agents"),
1007
1027
  join(searchPath, ".codex/agents"),
1008
1028
  join(searchPath, ".commandcode/agents"),
1009
1029
  join(searchPath, ".continue/agents"),
1030
+ join(searchPath, ".cortex/agents"),
1031
+ join(searchPath, ".crush/agents"),
1032
+ join(searchPath, ".factory/agents"),
1033
+ join(searchPath, ".gemini/agents"),
1010
1034
  join(searchPath, ".github/agents"),
1011
1035
  join(searchPath, ".goose/agents"),
1012
1036
  join(searchPath, ".iflow/agents"),
1013
1037
  join(searchPath, ".junie/agents"),
1014
1038
  join(searchPath, ".kilocode/agents"),
1015
1039
  join(searchPath, ".kiro/agents"),
1040
+ join(searchPath, ".kode/agents"),
1041
+ join(searchPath, ".mcpjam/agents"),
1016
1042
  join(searchPath, ".mux/agents"),
1017
1043
  join(searchPath, ".neovate/agents"),
1018
1044
  join(searchPath, ".opencode/agents"),
1019
1045
  join(searchPath, ".openhands/agents"),
1020
1046
  join(searchPath, ".pi/agents"),
1047
+ join(searchPath, ".pochi/agents"),
1021
1048
  join(searchPath, ".qoder/agents"),
1049
+ join(searchPath, ".qwen/agents"),
1022
1050
  join(searchPath, ".roo/agents"),
1023
1051
  join(searchPath, ".trae/agents"),
1052
+ join(searchPath, ".vibe/agents"),
1024
1053
  join(searchPath, ".windsurf/agents"),
1025
1054
  join(searchPath, ".zencoder/agents")
1026
1055
  ];
@@ -2916,7 +2945,7 @@ var WellKnownProvider = class {
2916
2945
  const wellKnownProvider = new WellKnownProvider();
2917
2946
  //#endregion
2918
2947
  //#region package.json
2919
- var version$1 = "0.1.1";
2948
+ var version$1 = "0.1.3";
2920
2949
  //#endregion
2921
2950
  //#region src/add.ts
2922
2951
  const isCancelled$1 = (value) => typeof value === "symbol";
@@ -3133,8 +3162,9 @@ async function handleWellKnownAgents(source, url, options, spinner) {
3133
3162
  options: agentDefs.map((s) => ({
3134
3163
  value: s,
3135
3164
  label: s.installName,
3136
- hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
3165
+ hint: s.description
3137
3166
  })),
3167
+ initialValues: agentDefs,
3138
3168
  required: true
3139
3169
  });
3140
3170
  if (pD(selected)) {
@@ -3264,7 +3294,7 @@ async function handleWellKnownAgents(source, url, options, spinner) {
3264
3294
  if (await isSourcePrivate(sourceIdentifier) !== true) track({
3265
3295
  event: "install",
3266
3296
  source: sourceIdentifier,
3267
- agents: targetIdes.join(","),
3297
+ agents: selectedAgents.map((s) => s.installName).join(","),
3268
3298
  ...installGlobally && { global: "1" },
3269
3299
  agentFiles: JSON.stringify(agentFiles),
3270
3300
  sourceType: "well-known"
@@ -3479,7 +3509,7 @@ async function runAdd(args, options = {}) {
3479
3509
  grouped[groupName].push({
3480
3510
  value: s,
3481
3511
  label: getAgentDisplayName(s),
3482
- hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
3512
+ hint: s.description
3483
3513
  });
3484
3514
  }
3485
3515
  selected = await be({
@@ -3492,8 +3522,9 @@ async function runAdd(args, options = {}) {
3492
3522
  options: sortedAgents.map((s) => ({
3493
3523
  value: s,
3494
3524
  label: getAgentDisplayName(s),
3495
- hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
3525
+ hint: s.description
3496
3526
  })),
3527
+ initialValues: sortedAgents,
3497
3528
  required: true
3498
3529
  });
3499
3530
  if (pD(selected)) {
@@ -3504,7 +3535,8 @@ async function runAdd(args, options = {}) {
3504
3535
  selectedAgents = selected;
3505
3536
  }
3506
3537
  const ownerRepoForAudit = getOwnerRepo(parsed);
3507
- const ownerRepoParsed = ownerRepoForAudit ? parseOwnerRepo(ownerRepoForAudit) : null;
3538
+ const bareOwnerRepo = ownerRepoForAudit ? stripHost(ownerRepoForAudit) : null;
3539
+ const ownerRepoParsed = bareOwnerRepo ? parseOwnerRepo(bareOwnerRepo) : null;
3508
3540
  const repoIsPrivate = ownerRepoParsed ? await isRepoPrivate(ownerRepoParsed.owner, ownerRepoParsed.repo) : null;
3509
3541
  const auditPromise = ownerRepoForAudit && repoIsPrivate === false ? fetchAuditData(ownerRepoForAudit, selectedAgents.map((s) => getAgentDisplayName(s))) : Promise.resolve(null);
3510
3542
  let targetIdes;
@@ -3669,11 +3701,12 @@ async function runAdd(args, options = {}) {
3669
3701
  agentFiles[agentDef.name] = relativePath;
3670
3702
  }
3671
3703
  const normalizedSource = getOwnerRepo(parsed);
3704
+ const bareNormalizedSource = normalizedSource ? stripHost(normalizedSource) : null;
3672
3705
  const lockSource = parsed.url.startsWith("git@") ? parsed.url : normalizedSource;
3673
3706
  if (normalizedSource && repoIsPrivate !== true) track({
3674
3707
  event: "install",
3675
3708
  source: normalizedSource,
3676
- agents: targetIdes.join(","),
3709
+ agents: selectedAgents.map((s) => getAgentDisplayName(s)).join(","),
3677
3710
  ...installGlobally && { global: "1" },
3678
3711
  agentFiles: JSON.stringify(agentFiles)
3679
3712
  });
@@ -3684,8 +3717,8 @@ async function runAdd(args, options = {}) {
3684
3717
  if (successfulAgentNames.has(agentDisplayName)) try {
3685
3718
  let agentFolderHash = "";
3686
3719
  const agentPathValue = agentFiles[agentDef.name];
3687
- if (parsed.type === "github" && agentPathValue) {
3688
- const hash = await fetchAgentFolderHash(normalizedSource, agentPathValue, getGitHubToken());
3720
+ if (parsed.type === "github" && agentPathValue && bareNormalizedSource) {
3721
+ const hash = await fetchAgentFolderHash(bareNormalizedSource, agentPathValue, getGitHubToken());
3689
3722
  if (hash) agentFolderHash = hash;
3690
3723
  }
3691
3724
  const installs = {};
@@ -5107,26 +5140,29 @@ async function runCheck(args = []) {
5107
5140
  console.log(`${DIM}Checking ${totalAgents} agent(s) for updates...${RESET}`);
5108
5141
  const updates = [];
5109
5142
  const errors = [];
5110
- for (const [source, agents] of agentsBySource) for (const { name, entry } of agents) try {
5111
- const latestHash = await fetchAgentFolderHash(source, entry.agentPath, token);
5112
- if (!latestHash) {
5143
+ for (const [source, agents] of agentsBySource) {
5144
+ const bareSource = stripHost(source) ?? source;
5145
+ for (const { name, entry } of agents) try {
5146
+ const latestHash = await fetchAgentFolderHash(bareSource, entry.agentPath, token);
5147
+ if (!latestHash) {
5148
+ errors.push({
5149
+ name,
5150
+ source,
5151
+ error: "Could not fetch from GitHub"
5152
+ });
5153
+ continue;
5154
+ }
5155
+ if (latestHash !== entry.agentFolderHash) updates.push({
5156
+ name,
5157
+ source
5158
+ });
5159
+ } catch (err) {
5113
5160
  errors.push({
5114
5161
  name,
5115
5162
  source,
5116
- error: "Could not fetch from GitHub"
5163
+ error: err instanceof Error ? err.message : "Unknown error"
5117
5164
  });
5118
- continue;
5119
5165
  }
5120
- if (latestHash !== entry.agentFolderHash) updates.push({
5121
- name,
5122
- source
5123
- });
5124
- } catch (err) {
5125
- errors.push({
5126
- name,
5127
- source,
5128
- error: err instanceof Error ? err.message : "Unknown error"
5129
- });
5130
5166
  }
5131
5167
  console.log();
5132
5168
  if (updates.length === 0) console.log(`${TEXT}✓ All agents are up to date${RESET}`);
@@ -5177,7 +5213,7 @@ async function runUpdate() {
5177
5213
  continue;
5178
5214
  }
5179
5215
  try {
5180
- const latestHash = await fetchAgentFolderHash(entry.source, entry.agentPath, token);
5216
+ const latestHash = await fetchAgentFolderHash(stripHost(entry.source) ?? entry.source, entry.agentPath, token);
5181
5217
  if (latestHash && latestHash !== entry.agentFolderHash) updates.push({
5182
5218
  name: agentName,
5183
5219
  source: entry.source,
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "agentshq",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "The package manager for AI coding agents. Discover, install, and manage agent definitions across 43+ IDEs.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "agentshq": "./bin/cli.mjs",
8
- "add-agent": "./bin/cli.mjs"
7
+ "agentshq": "bin/cli.mjs",
8
+ "add-agent": "bin/cli.mjs"
9
9
  },
10
10
  "files": [
11
11
  "dist",
@@ -22,13 +22,51 @@
22
22
  "type-check": "tsc --noEmit"
23
23
  },
24
24
  "keywords": [
25
- "cli", "agent-definitions", "agents", "ai-agents", "amp", "antigravity", "augment",
26
- "claude-code", "openclaw", "cline", "codebuddy", "codex", "command-code",
27
- "continue", "cortex", "crush", "cursor", "droid", "gemini-cli",
28
- "github-copilot", "goose", "junie", "iflow-cli", "kilo", "kimi-cli",
29
- "kiro-cli", "kode", "mcpjam", "mistral-vibe", "mux", "opencode",
30
- "openhands", "pi", "qoder", "qwen-code", "replit", "roo", "trae",
31
- "trae-cn", "warp", "windsurf", "zencoder", "neovate", "pochi", "adal",
25
+ "cli",
26
+ "agent-definitions",
27
+ "agents",
28
+ "ai-agents",
29
+ "amp",
30
+ "antigravity",
31
+ "augment",
32
+ "claude-code",
33
+ "openclaw",
34
+ "cline",
35
+ "codebuddy",
36
+ "codex",
37
+ "command-code",
38
+ "continue",
39
+ "cortex",
40
+ "crush",
41
+ "cursor",
42
+ "droid",
43
+ "gemini-cli",
44
+ "github-copilot",
45
+ "goose",
46
+ "junie",
47
+ "iflow-cli",
48
+ "kilo",
49
+ "kimi-cli",
50
+ "kiro-cli",
51
+ "kode",
52
+ "mcpjam",
53
+ "mistral-vibe",
54
+ "mux",
55
+ "opencode",
56
+ "openhands",
57
+ "pi",
58
+ "qoder",
59
+ "qwen-code",
60
+ "replit",
61
+ "roo",
62
+ "trae",
63
+ "trae-cn",
64
+ "warp",
65
+ "windsurf",
66
+ "zencoder",
67
+ "neovate",
68
+ "pochi",
69
+ "adal",
32
70
  "universal"
33
71
  ],
34
72
  "repository": {