agentshq 0.1.1 → 0.1.4
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.mjs +72 -34
- 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 (
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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 :
|
|
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
|
|
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.
|
|
2948
|
+
var version$1 = "0.1.4";
|
|
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
|
|
3165
|
+
hint: s.description
|
|
3137
3166
|
})),
|
|
3167
|
+
initialValues: agentDefs,
|
|
3138
3168
|
required: true
|
|
3139
3169
|
});
|
|
3140
3170
|
if (pD(selected)) {
|
|
@@ -3264,8 +3294,9 @@ 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:
|
|
3297
|
+
agents: selectedAgents.map((s) => s.installName).join(","),
|
|
3268
3298
|
...installGlobally && { global: "1" },
|
|
3299
|
+
ide: targetIdes.join(","),
|
|
3269
3300
|
agentFiles: JSON.stringify(agentFiles),
|
|
3270
3301
|
sourceType: "well-known"
|
|
3271
3302
|
});
|
|
@@ -3479,7 +3510,7 @@ async function runAdd(args, options = {}) {
|
|
|
3479
3510
|
grouped[groupName].push({
|
|
3480
3511
|
value: s,
|
|
3481
3512
|
label: getAgentDisplayName(s),
|
|
3482
|
-
hint: s.description
|
|
3513
|
+
hint: s.description
|
|
3483
3514
|
});
|
|
3484
3515
|
}
|
|
3485
3516
|
selected = await be({
|
|
@@ -3492,8 +3523,9 @@ async function runAdd(args, options = {}) {
|
|
|
3492
3523
|
options: sortedAgents.map((s) => ({
|
|
3493
3524
|
value: s,
|
|
3494
3525
|
label: getAgentDisplayName(s),
|
|
3495
|
-
hint: s.description
|
|
3526
|
+
hint: s.description
|
|
3496
3527
|
})),
|
|
3528
|
+
initialValues: sortedAgents,
|
|
3497
3529
|
required: true
|
|
3498
3530
|
});
|
|
3499
3531
|
if (pD(selected)) {
|
|
@@ -3504,7 +3536,8 @@ async function runAdd(args, options = {}) {
|
|
|
3504
3536
|
selectedAgents = selected;
|
|
3505
3537
|
}
|
|
3506
3538
|
const ownerRepoForAudit = getOwnerRepo(parsed);
|
|
3507
|
-
const
|
|
3539
|
+
const bareOwnerRepo = ownerRepoForAudit ? stripHost(ownerRepoForAudit) : null;
|
|
3540
|
+
const ownerRepoParsed = bareOwnerRepo ? parseOwnerRepo(bareOwnerRepo) : null;
|
|
3508
3541
|
const repoIsPrivate = ownerRepoParsed ? await isRepoPrivate(ownerRepoParsed.owner, ownerRepoParsed.repo) : null;
|
|
3509
3542
|
const auditPromise = ownerRepoForAudit && repoIsPrivate === false ? fetchAuditData(ownerRepoForAudit, selectedAgents.map((s) => getAgentDisplayName(s))) : Promise.resolve(null);
|
|
3510
3543
|
let targetIdes;
|
|
@@ -3669,12 +3702,14 @@ async function runAdd(args, options = {}) {
|
|
|
3669
3702
|
agentFiles[agentDef.name] = relativePath;
|
|
3670
3703
|
}
|
|
3671
3704
|
const normalizedSource = getOwnerRepo(parsed);
|
|
3705
|
+
const bareNormalizedSource = normalizedSource ? stripHost(normalizedSource) : null;
|
|
3672
3706
|
const lockSource = parsed.url.startsWith("git@") ? parsed.url : normalizedSource;
|
|
3673
3707
|
if (normalizedSource && repoIsPrivate !== true) track({
|
|
3674
3708
|
event: "install",
|
|
3675
3709
|
source: normalizedSource,
|
|
3676
|
-
agents:
|
|
3710
|
+
agents: selectedAgents.map((s) => getAgentDisplayName(s)).join(","),
|
|
3677
3711
|
...installGlobally && { global: "1" },
|
|
3712
|
+
ide: targetIdes.join(","),
|
|
3678
3713
|
agentFiles: JSON.stringify(agentFiles)
|
|
3679
3714
|
});
|
|
3680
3715
|
if (successful.length > 0 && installGlobally && normalizedSource) {
|
|
@@ -3684,8 +3719,8 @@ async function runAdd(args, options = {}) {
|
|
|
3684
3719
|
if (successfulAgentNames.has(agentDisplayName)) try {
|
|
3685
3720
|
let agentFolderHash = "";
|
|
3686
3721
|
const agentPathValue = agentFiles[agentDef.name];
|
|
3687
|
-
if (parsed.type === "github" && agentPathValue) {
|
|
3688
|
-
const hash = await fetchAgentFolderHash(
|
|
3722
|
+
if (parsed.type === "github" && agentPathValue && bareNormalizedSource) {
|
|
3723
|
+
const hash = await fetchAgentFolderHash(bareNormalizedSource, agentPathValue, getGitHubToken());
|
|
3689
3724
|
if (hash) agentFolderHash = hash;
|
|
3690
3725
|
}
|
|
3691
3726
|
const installs = {};
|
|
@@ -5107,26 +5142,29 @@ async function runCheck(args = []) {
|
|
|
5107
5142
|
console.log(`${DIM}Checking ${totalAgents} agent(s) for updates...${RESET}`);
|
|
5108
5143
|
const updates = [];
|
|
5109
5144
|
const errors = [];
|
|
5110
|
-
for (const [source, agents] of agentsBySource)
|
|
5111
|
-
const
|
|
5112
|
-
|
|
5145
|
+
for (const [source, agents] of agentsBySource) {
|
|
5146
|
+
const bareSource = stripHost(source) ?? source;
|
|
5147
|
+
for (const { name, entry } of agents) try {
|
|
5148
|
+
const latestHash = await fetchAgentFolderHash(bareSource, entry.agentPath, token);
|
|
5149
|
+
if (!latestHash) {
|
|
5150
|
+
errors.push({
|
|
5151
|
+
name,
|
|
5152
|
+
source,
|
|
5153
|
+
error: "Could not fetch from GitHub"
|
|
5154
|
+
});
|
|
5155
|
+
continue;
|
|
5156
|
+
}
|
|
5157
|
+
if (latestHash !== entry.agentFolderHash) updates.push({
|
|
5158
|
+
name,
|
|
5159
|
+
source
|
|
5160
|
+
});
|
|
5161
|
+
} catch (err) {
|
|
5113
5162
|
errors.push({
|
|
5114
5163
|
name,
|
|
5115
5164
|
source,
|
|
5116
|
-
error:
|
|
5165
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
5117
5166
|
});
|
|
5118
|
-
continue;
|
|
5119
5167
|
}
|
|
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
5168
|
}
|
|
5131
5169
|
console.log();
|
|
5132
5170
|
if (updates.length === 0) console.log(`${TEXT}✓ All agents are up to date${RESET}`);
|
|
@@ -5177,7 +5215,7 @@ async function runUpdate() {
|
|
|
5177
5215
|
continue;
|
|
5178
5216
|
}
|
|
5179
5217
|
try {
|
|
5180
|
-
const latestHash = await fetchAgentFolderHash(entry.source, entry.agentPath, token);
|
|
5218
|
+
const latestHash = await fetchAgentFolderHash(stripHost(entry.source) ?? entry.source, entry.agentPath, token);
|
|
5181
5219
|
if (latestHash && latestHash !== entry.agentFolderHash) updates.push({
|
|
5182
5220
|
name: agentName,
|
|
5183
5221
|
source: entry.source,
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentshq",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
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": "
|
|
8
|
-
"add-agent": "
|
|
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",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
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": {
|