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.
- package/dist/cli.mjs +70 -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.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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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(
|
|
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)
|
|
5111
|
-
const
|
|
5112
|
-
|
|
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:
|
|
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.
|
|
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": "
|
|
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": {
|