agentpacks 0.3.0 → 0.4.0
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/README.md +168 -8
- package/dist/api.d.ts +2 -0
- package/dist/api.js +929 -409
- package/dist/cli/export-cmd.js +281 -149
- package/dist/cli/generate.js +740 -247
- package/dist/cli/import-cmd.js +57 -85
- package/dist/cli/info.d.ts +4 -0
- package/dist/cli/info.js +232 -0
- package/dist/cli/init.js +8 -36
- package/dist/cli/install.js +414 -129
- package/dist/cli/login.d.ts +9 -0
- package/dist/cli/login.js +202 -0
- package/dist/cli/models-explain.d.ts +16 -0
- package/dist/cli/models-explain.js +1205 -0
- package/dist/cli/pack/create.js +4 -32
- package/dist/cli/pack/enable.js +1 -29
- package/dist/cli/pack/list.js +266 -134
- package/dist/cli/pack/validate.js +274 -127
- package/dist/cli/publish.d.ts +8 -0
- package/dist/cli/publish.js +672 -0
- package/dist/cli/search.d.ts +12 -0
- package/dist/cli/search.js +210 -0
- package/dist/core/config.d.ts +2 -1
- package/dist/core/config.js +74 -117
- package/dist/core/dependency-resolver.js +4 -28
- package/dist/core/feature-merger.d.ts +7 -0
- package/dist/core/feature-merger.js +289 -29
- package/dist/core/index.js +283 -140
- package/dist/core/lockfile.js +0 -28
- package/dist/core/metarepo.js +74 -116
- package/dist/core/pack-loader.d.ts +2 -0
- package/dist/core/pack-loader.js +266 -133
- package/dist/core/profile-resolver.d.ts +75 -0
- package/dist/core/profile-resolver.js +111 -0
- package/dist/exporters/cursor-plugin.js +4 -32
- package/dist/exporters/index.js +4 -32
- package/dist/features/agents.d.ts +5 -0
- package/dist/features/agents.js +2 -30
- package/dist/features/commands.js +2 -30
- package/dist/features/hooks.js +2 -30
- package/dist/features/ignore.js +0 -28
- package/dist/features/index.d.ts +1 -0
- package/dist/features/index.js +176 -31
- package/dist/features/mcp.js +2 -30
- package/dist/features/models.d.ts +167 -0
- package/dist/features/models.js +293 -0
- package/dist/features/plugins.js +2 -30
- package/dist/features/rules.js +2 -30
- package/dist/features/skills.js +2 -30
- package/dist/importers/claude-code.js +10 -38
- package/dist/importers/cursor.js +15 -43
- package/dist/importers/opencode.js +16 -44
- package/dist/importers/rulesync.js +22 -50
- package/dist/index.js +1710 -538
- package/dist/node/api.js +929 -409
- package/dist/node/cli/export-cmd.js +281 -149
- package/dist/node/cli/generate.js +740 -247
- package/dist/node/cli/import-cmd.js +57 -85
- package/dist/node/cli/info.js +232 -0
- package/dist/node/cli/init.js +8 -36
- package/dist/node/cli/install.js +414 -129
- package/dist/node/cli/login.js +202 -0
- package/dist/node/cli/models-explain.js +1205 -0
- package/dist/node/cli/pack/create.js +4 -32
- package/dist/node/cli/pack/enable.js +1 -29
- package/dist/node/cli/pack/list.js +266 -134
- package/dist/node/cli/pack/validate.js +274 -127
- package/dist/node/cli/publish.js +672 -0
- package/dist/node/cli/search.js +210 -0
- package/dist/node/core/config.js +74 -117
- package/dist/node/core/dependency-resolver.js +4 -28
- package/dist/node/core/feature-merger.js +289 -29
- package/dist/node/core/index.js +283 -140
- package/dist/node/core/lockfile.js +0 -28
- package/dist/node/core/metarepo.js +74 -116
- package/dist/node/core/pack-loader.js +266 -133
- package/dist/node/core/profile-resolver.js +111 -0
- package/dist/node/exporters/cursor-plugin.js +4 -32
- package/dist/node/exporters/index.js +4 -32
- package/dist/node/features/agents.js +2 -30
- package/dist/node/features/commands.js +2 -30
- package/dist/node/features/hooks.js +2 -30
- package/dist/node/features/ignore.js +0 -28
- package/dist/node/features/index.js +176 -31
- package/dist/node/features/mcp.js +2 -30
- package/dist/node/features/models.js +293 -0
- package/dist/node/features/plugins.js +2 -30
- package/dist/node/features/rules.js +2 -30
- package/dist/node/features/skills.js +2 -30
- package/dist/node/importers/claude-code.js +10 -38
- package/dist/node/importers/cursor.js +15 -43
- package/dist/node/importers/opencode.js +16 -44
- package/dist/node/importers/rulesync.js +22 -50
- package/dist/node/index.js +1710 -538
- package/dist/node/sources/git-ref.js +7 -30
- package/dist/node/sources/git.js +7 -30
- package/dist/node/sources/index.js +337 -39
- package/dist/node/sources/local.js +0 -28
- package/dist/node/sources/npm-ref.js +0 -28
- package/dist/node/sources/npm.js +10 -37
- package/dist/node/sources/registry-ref.js +37 -0
- package/dist/node/sources/registry.js +355 -0
- package/dist/node/targets/additional-targets.js +196 -37
- package/dist/node/targets/agents-md.js +5 -33
- package/dist/node/targets/base-target.js +0 -28
- package/dist/node/targets/claude-code.js +211 -41
- package/dist/node/targets/codex-cli.js +7 -35
- package/dist/node/targets/copilot.js +202 -41
- package/dist/node/targets/cursor.js +188 -40
- package/dist/node/targets/gemini-cli.js +10 -38
- package/dist/node/targets/generic-md-target.js +196 -37
- package/dist/node/targets/index.js +414 -106
- package/dist/node/targets/opencode.js +171 -51
- package/dist/node/targets/registry.js +414 -106
- package/dist/node/utils/credentials.js +38 -0
- package/dist/node/utils/diff.js +22 -34
- package/dist/node/utils/filesystem.js +2 -30
- package/dist/node/utils/frontmatter.js +0 -28
- package/dist/node/utils/global.js +3 -31
- package/dist/node/utils/markdown.js +0 -28
- package/dist/node/utils/model-allowlist.js +110 -0
- package/dist/node/utils/model-guidance.js +78 -0
- package/dist/node/utils/registry-client.js +142 -0
- package/dist/node/utils/tarball.js +49 -0
- package/dist/sources/git-ref.js +7 -30
- package/dist/sources/git.d.ts +2 -2
- package/dist/sources/git.js +7 -30
- package/dist/sources/index.d.ts +2 -0
- package/dist/sources/index.js +337 -39
- package/dist/sources/local.js +0 -28
- package/dist/sources/npm-ref.js +0 -28
- package/dist/sources/npm.js +10 -37
- package/dist/sources/registry-ref.d.ts +30 -0
- package/dist/sources/registry-ref.js +37 -0
- package/dist/sources/registry.d.ts +18 -0
- package/dist/sources/registry.js +355 -0
- package/dist/targets/additional-targets.js +196 -37
- package/dist/targets/agents-md.js +5 -33
- package/dist/targets/base-target.d.ts +2 -0
- package/dist/targets/base-target.js +0 -28
- package/dist/targets/claude-code.js +211 -41
- package/dist/targets/codex-cli.js +7 -35
- package/dist/targets/copilot.js +202 -41
- package/dist/targets/cursor.js +188 -40
- package/dist/targets/gemini-cli.js +10 -38
- package/dist/targets/generic-md-target.js +196 -37
- package/dist/targets/index.js +414 -106
- package/dist/targets/opencode.js +171 -51
- package/dist/targets/registry.js +414 -106
- package/dist/utils/credentials.d.ts +19 -0
- package/dist/utils/credentials.js +38 -0
- package/dist/utils/diff.js +22 -34
- package/dist/utils/filesystem.js +2 -30
- package/dist/utils/frontmatter.js +0 -28
- package/dist/utils/global.js +3 -31
- package/dist/utils/markdown.js +0 -28
- package/dist/utils/model-allowlist.d.ts +39 -0
- package/dist/utils/model-allowlist.js +110 -0
- package/dist/utils/model-guidance.d.ts +6 -0
- package/dist/utils/model-guidance.js +78 -0
- package/dist/utils/registry-client.d.ts +141 -0
- package/dist/utils/registry-client.js +142 -0
- package/dist/utils/tarball.d.ts +13 -0
- package/dist/utils/tarball.js +49 -0
- package/package.json +171 -5
- package/templates/pack/models.json +38 -0
package/dist/cli/install.js
CHANGED
|
@@ -1,51 +1,85 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
7
|
-
var __toCommonJS = (from) => {
|
|
8
|
-
var entry = __moduleCache.get(from), desc;
|
|
9
|
-
if (entry)
|
|
10
|
-
return entry;
|
|
11
|
-
entry = __defProp({}, "__esModule", { value: true });
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
13
|
-
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
14
|
-
get: () => from[key],
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
}));
|
|
17
|
-
__moduleCache.set(from, entry);
|
|
18
|
-
return entry;
|
|
19
|
-
};
|
|
20
|
-
var __export = (target, all) => {
|
|
21
|
-
for (var name in all)
|
|
22
|
-
__defProp(target, name, {
|
|
23
|
-
get: all[name],
|
|
24
|
-
enumerable: true,
|
|
25
|
-
configurable: true,
|
|
26
|
-
set: (newValue) => all[name] = () => newValue
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
30
2
|
var __require = import.meta.require;
|
|
31
3
|
|
|
32
4
|
// src/core/config.ts
|
|
33
|
-
var exports_config = {};
|
|
34
|
-
__export(exports_config, {
|
|
35
|
-
resolveTargets: () => resolveTargets,
|
|
36
|
-
resolveFeatures: () => resolveFeatures,
|
|
37
|
-
loadWorkspaceConfig: () => loadWorkspaceConfig,
|
|
38
|
-
loadPackManifest: () => loadPackManifest,
|
|
39
|
-
WorkspaceConfigSchema: () => WorkspaceConfigSchema,
|
|
40
|
-
TARGET_IDS: () => TARGET_IDS,
|
|
41
|
-
REPO_MODES: () => REPO_MODES,
|
|
42
|
-
PackManifestSchema: () => PackManifestSchema,
|
|
43
|
-
FEATURE_IDS: () => FEATURE_IDS
|
|
44
|
-
});
|
|
45
5
|
import { z } from "zod";
|
|
46
6
|
import { readFileSync, existsSync } from "fs";
|
|
47
7
|
import { resolve } from "path";
|
|
48
8
|
import { parse as parseJsonc } from "jsonc-parser";
|
|
9
|
+
var TARGET_IDS = [
|
|
10
|
+
"opencode",
|
|
11
|
+
"cursor",
|
|
12
|
+
"claudecode",
|
|
13
|
+
"codexcli",
|
|
14
|
+
"geminicli",
|
|
15
|
+
"copilot",
|
|
16
|
+
"agentsmd",
|
|
17
|
+
"cline",
|
|
18
|
+
"kilo",
|
|
19
|
+
"roo",
|
|
20
|
+
"qwencode",
|
|
21
|
+
"kiro",
|
|
22
|
+
"factorydroid",
|
|
23
|
+
"antigravity",
|
|
24
|
+
"junie",
|
|
25
|
+
"augmentcode",
|
|
26
|
+
"windsurf",
|
|
27
|
+
"warp",
|
|
28
|
+
"replit",
|
|
29
|
+
"zed"
|
|
30
|
+
];
|
|
31
|
+
var FEATURE_IDS = [
|
|
32
|
+
"rules",
|
|
33
|
+
"commands",
|
|
34
|
+
"agents",
|
|
35
|
+
"skills",
|
|
36
|
+
"hooks",
|
|
37
|
+
"plugins",
|
|
38
|
+
"mcp",
|
|
39
|
+
"ignore",
|
|
40
|
+
"models"
|
|
41
|
+
];
|
|
42
|
+
var REPO_MODES = ["repo", "monorepo", "metarepo"];
|
|
43
|
+
var PackManifestSchema = z.object({
|
|
44
|
+
name: z.string().min(1),
|
|
45
|
+
version: z.string().default("1.0.0"),
|
|
46
|
+
description: z.string().default(""),
|
|
47
|
+
author: z.union([
|
|
48
|
+
z.string(),
|
|
49
|
+
z.object({ name: z.string(), email: z.string().optional() })
|
|
50
|
+
]).optional(),
|
|
51
|
+
tags: z.array(z.string()).default([]),
|
|
52
|
+
dependencies: z.array(z.string()).default([]),
|
|
53
|
+
conflicts: z.array(z.string()).default([]),
|
|
54
|
+
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
55
|
+
features: z.union([z.literal("*"), z.array(z.string())]).default("*")
|
|
56
|
+
});
|
|
57
|
+
var FeaturesSchema = z.union([
|
|
58
|
+
z.literal("*"),
|
|
59
|
+
z.array(z.string()),
|
|
60
|
+
z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
|
|
61
|
+
]);
|
|
62
|
+
var WorkspaceConfigSchema = z.object({
|
|
63
|
+
$schema: z.string().optional(),
|
|
64
|
+
packs: z.array(z.string()).default(["./packs/default"]),
|
|
65
|
+
disabled: z.array(z.string()).default([]),
|
|
66
|
+
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
67
|
+
features: FeaturesSchema.default("*"),
|
|
68
|
+
mode: z.enum(REPO_MODES).default("repo"),
|
|
69
|
+
baseDirs: z.array(z.string()).default(["."]),
|
|
70
|
+
global: z.boolean().default(false),
|
|
71
|
+
delete: z.boolean().default(true),
|
|
72
|
+
verbose: z.boolean().default(false),
|
|
73
|
+
silent: z.boolean().default(false),
|
|
74
|
+
overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
75
|
+
sources: z.array(z.object({
|
|
76
|
+
source: z.string(),
|
|
77
|
+
packs: z.array(z.string()).optional(),
|
|
78
|
+
skills: z.array(z.string()).optional()
|
|
79
|
+
})).default([]),
|
|
80
|
+
modelProfile: z.string().optional()
|
|
81
|
+
});
|
|
82
|
+
var CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
|
|
49
83
|
function loadWorkspaceConfig(projectRoot) {
|
|
50
84
|
for (const filename of CONFIG_FILES) {
|
|
51
85
|
const filepath = resolve(projectRoot, filename);
|
|
@@ -91,81 +125,6 @@ function resolveTargets(config) {
|
|
|
91
125
|
return [...TARGET_IDS];
|
|
92
126
|
return config.targets;
|
|
93
127
|
}
|
|
94
|
-
var TARGET_IDS, FEATURE_IDS, REPO_MODES, PackManifestSchema, FeaturesSchema, WorkspaceConfigSchema, CONFIG_FILES;
|
|
95
|
-
var init_config = __esm(() => {
|
|
96
|
-
TARGET_IDS = [
|
|
97
|
-
"opencode",
|
|
98
|
-
"cursor",
|
|
99
|
-
"claudecode",
|
|
100
|
-
"codexcli",
|
|
101
|
-
"geminicli",
|
|
102
|
-
"copilot",
|
|
103
|
-
"agentsmd",
|
|
104
|
-
"cline",
|
|
105
|
-
"kilo",
|
|
106
|
-
"roo",
|
|
107
|
-
"qwencode",
|
|
108
|
-
"kiro",
|
|
109
|
-
"factorydroid",
|
|
110
|
-
"antigravity",
|
|
111
|
-
"junie",
|
|
112
|
-
"augmentcode",
|
|
113
|
-
"windsurf",
|
|
114
|
-
"warp",
|
|
115
|
-
"replit",
|
|
116
|
-
"zed"
|
|
117
|
-
];
|
|
118
|
-
FEATURE_IDS = [
|
|
119
|
-
"rules",
|
|
120
|
-
"commands",
|
|
121
|
-
"agents",
|
|
122
|
-
"skills",
|
|
123
|
-
"hooks",
|
|
124
|
-
"plugins",
|
|
125
|
-
"mcp",
|
|
126
|
-
"ignore"
|
|
127
|
-
];
|
|
128
|
-
REPO_MODES = ["repo", "monorepo", "metarepo"];
|
|
129
|
-
PackManifestSchema = z.object({
|
|
130
|
-
name: z.string().min(1),
|
|
131
|
-
version: z.string().default("1.0.0"),
|
|
132
|
-
description: z.string().default(""),
|
|
133
|
-
author: z.union([
|
|
134
|
-
z.string(),
|
|
135
|
-
z.object({ name: z.string(), email: z.string().optional() })
|
|
136
|
-
]).optional(),
|
|
137
|
-
tags: z.array(z.string()).default([]),
|
|
138
|
-
dependencies: z.array(z.string()).default([]),
|
|
139
|
-
conflicts: z.array(z.string()).default([]),
|
|
140
|
-
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
141
|
-
features: z.union([z.literal("*"), z.array(z.string())]).default("*")
|
|
142
|
-
});
|
|
143
|
-
FeaturesSchema = z.union([
|
|
144
|
-
z.literal("*"),
|
|
145
|
-
z.array(z.string()),
|
|
146
|
-
z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
|
|
147
|
-
]);
|
|
148
|
-
WorkspaceConfigSchema = z.object({
|
|
149
|
-
$schema: z.string().optional(),
|
|
150
|
-
packs: z.array(z.string()).default(["./packs/default"]),
|
|
151
|
-
disabled: z.array(z.string()).default([]),
|
|
152
|
-
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
153
|
-
features: FeaturesSchema.default("*"),
|
|
154
|
-
mode: z.enum(REPO_MODES).default("repo"),
|
|
155
|
-
baseDirs: z.array(z.string()).default(["."]),
|
|
156
|
-
global: z.boolean().default(false),
|
|
157
|
-
delete: z.boolean().default(true),
|
|
158
|
-
verbose: z.boolean().default(false),
|
|
159
|
-
silent: z.boolean().default(false),
|
|
160
|
-
overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
161
|
-
sources: z.array(z.object({
|
|
162
|
-
source: z.string(),
|
|
163
|
-
packs: z.array(z.string()).optional(),
|
|
164
|
-
skills: z.array(z.string()).optional()
|
|
165
|
-
})).default([])
|
|
166
|
-
});
|
|
167
|
-
CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
|
|
168
|
-
});
|
|
169
128
|
|
|
170
129
|
// src/core/lockfile.ts
|
|
171
130
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
@@ -241,9 +200,14 @@ function parseGitSourceRef(source) {
|
|
|
241
200
|
if (parts.length < 2) {
|
|
242
201
|
throw new Error(`Invalid git source reference: "${source}". Expected owner/repo format.`);
|
|
243
202
|
}
|
|
203
|
+
const owner = parts[0];
|
|
204
|
+
const repo = parts[1];
|
|
205
|
+
if (!owner || !repo) {
|
|
206
|
+
throw new Error(`Invalid git source reference: "${source}". Expected owner/repo format.`);
|
|
207
|
+
}
|
|
244
208
|
return {
|
|
245
|
-
owner
|
|
246
|
-
repo
|
|
209
|
+
owner,
|
|
210
|
+
repo,
|
|
247
211
|
ref,
|
|
248
212
|
path: path || ""
|
|
249
213
|
};
|
|
@@ -312,6 +276,36 @@ function npmSourceKey(parsed) {
|
|
|
312
276
|
return `npm:${parsed.packageName}`;
|
|
313
277
|
}
|
|
314
278
|
|
|
279
|
+
// src/sources/registry-ref.ts
|
|
280
|
+
function parseRegistrySourceRef(source) {
|
|
281
|
+
let s = source;
|
|
282
|
+
if (s.startsWith("registry:")) {
|
|
283
|
+
s = s.slice(9);
|
|
284
|
+
}
|
|
285
|
+
if (!s) {
|
|
286
|
+
throw new Error(`Invalid registry source reference: "${source}". Expected pack name.`);
|
|
287
|
+
}
|
|
288
|
+
let version = "latest";
|
|
289
|
+
const atIdx = s.indexOf("@");
|
|
290
|
+
if (atIdx > 0) {
|
|
291
|
+
version = s.slice(atIdx + 1);
|
|
292
|
+
s = s.slice(0, atIdx);
|
|
293
|
+
}
|
|
294
|
+
if (!s) {
|
|
295
|
+
throw new Error(`Invalid registry source reference: "${source}". Pack name is empty.`);
|
|
296
|
+
}
|
|
297
|
+
if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(s)) {
|
|
298
|
+
throw new Error(`Invalid registry pack name: "${s}". Must be lowercase alphanumeric with hyphens.`);
|
|
299
|
+
}
|
|
300
|
+
return { packName: s, version };
|
|
301
|
+
}
|
|
302
|
+
function isRegistryPackRef(packRef) {
|
|
303
|
+
return packRef.startsWith("registry:");
|
|
304
|
+
}
|
|
305
|
+
function registrySourceKey(parsed) {
|
|
306
|
+
return `registry:${parsed.packName}`;
|
|
307
|
+
}
|
|
308
|
+
|
|
315
309
|
// src/sources/git.ts
|
|
316
310
|
import { mkdirSync, writeFileSync as writeFileSync2 } from "fs";
|
|
317
311
|
import { resolve as resolve4, join } from "path";
|
|
@@ -444,7 +438,7 @@ async function installGitSource(projectRoot, source, lockfile, options = {}) {
|
|
|
444
438
|
}
|
|
445
439
|
|
|
446
440
|
// src/sources/npm.ts
|
|
447
|
-
import { mkdirSync as mkdirSync2, existsSync as existsSync4 } from "fs";
|
|
441
|
+
import { mkdirSync as mkdirSync2, existsSync as existsSync4, readdirSync } from "fs";
|
|
448
442
|
import { resolve as resolve5, join as join2 } from "path";
|
|
449
443
|
import { execSync } from "child_process";
|
|
450
444
|
var NPM_REGISTRY = "https://registry.npmjs.org";
|
|
@@ -469,18 +463,15 @@ async function installNpmSource(projectRoot, source, lockfile, options = {}) {
|
|
|
469
463
|
throw new Error(`Frozen mode: no lockfile entry for source "${sourceKey}".`);
|
|
470
464
|
}
|
|
471
465
|
let resolvedVersion;
|
|
472
|
-
let tarballUrl;
|
|
473
466
|
if (locked && !options.update) {
|
|
474
467
|
resolvedVersion = locked.resolvedRef;
|
|
475
|
-
tarballUrl = "";
|
|
476
468
|
} else {
|
|
477
469
|
const resolved = await resolveNpmVersion(parsed);
|
|
478
470
|
resolvedVersion = resolved.version;
|
|
479
|
-
tarballUrl = resolved.tarball;
|
|
480
471
|
}
|
|
481
472
|
const curatedDir = resolve5(projectRoot, ".agentpacks", ".curated");
|
|
482
473
|
mkdirSync2(curatedDir, { recursive: true });
|
|
483
|
-
|
|
474
|
+
extractNpmPack(parsed, resolvedVersion, curatedDir, installed, warnings);
|
|
484
475
|
const newEntry = {
|
|
485
476
|
requestedRef: parsed.version,
|
|
486
477
|
resolvedRef: resolvedVersion,
|
|
@@ -502,12 +493,17 @@ function extractNpmPack(parsed, version, curatedDir, installed, warnings) {
|
|
|
502
493
|
stdio: "pipe",
|
|
503
494
|
timeout: 30000
|
|
504
495
|
});
|
|
505
|
-
const tgzFiles =
|
|
496
|
+
const tgzFiles = readdirSync(tmpDir).filter((f) => f.endsWith(".tgz"));
|
|
506
497
|
if (tgzFiles.length === 0) {
|
|
507
498
|
warnings.push(`No tarball found for ${pkgSpec}`);
|
|
508
499
|
return packOutDir;
|
|
509
500
|
}
|
|
510
|
-
const
|
|
501
|
+
const firstTgz = tgzFiles[0];
|
|
502
|
+
if (!firstTgz) {
|
|
503
|
+
warnings.push(`No tarball found for ${pkgSpec}`);
|
|
504
|
+
return packOutDir;
|
|
505
|
+
}
|
|
506
|
+
const tgzPath = join2(tmpDir, firstTgz);
|
|
511
507
|
mkdirSync2(packOutDir, { recursive: true });
|
|
512
508
|
execSync(`tar xzf "${tgzPath}" -C "${packOutDir}" --strip-components=1`, {
|
|
513
509
|
stdio: "pipe",
|
|
@@ -525,8 +521,7 @@ function extractNpmPack(parsed, version, curatedDir, installed, warnings) {
|
|
|
525
521
|
return packOutDir;
|
|
526
522
|
}
|
|
527
523
|
function collectFiles(dir, out) {
|
|
528
|
-
const
|
|
529
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
524
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
530
525
|
for (const entry of entries) {
|
|
531
526
|
const full = join2(dir, entry.name);
|
|
532
527
|
if (entry.isDirectory()) {
|
|
@@ -537,14 +532,299 @@ function collectFiles(dir, out) {
|
|
|
537
532
|
}
|
|
538
533
|
}
|
|
539
534
|
|
|
535
|
+
// src/utils/registry-client.ts
|
|
536
|
+
var DEFAULT_REGISTRY_URL = "https://registry.agentpacks.dev";
|
|
537
|
+
function createRegistryClient(config) {
|
|
538
|
+
return new RegistryClient({
|
|
539
|
+
registryUrl: config?.registryUrl ?? DEFAULT_REGISTRY_URL,
|
|
540
|
+
authToken: config?.authToken,
|
|
541
|
+
timeout: config?.timeout ?? 30000
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
class RegistryClient {
|
|
546
|
+
config;
|
|
547
|
+
constructor(config) {
|
|
548
|
+
this.config = {
|
|
549
|
+
registryUrl: config.registryUrl.replace(/\/+$/, ""),
|
|
550
|
+
authToken: config.authToken,
|
|
551
|
+
timeout: config.timeout ?? 30000
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
async search(params) {
|
|
555
|
+
const searchParams = new URLSearchParams;
|
|
556
|
+
if (params.query)
|
|
557
|
+
searchParams.set("q", params.query);
|
|
558
|
+
if (params.tags?.length)
|
|
559
|
+
searchParams.set("tags", params.tags.join(","));
|
|
560
|
+
if (params.targets?.length)
|
|
561
|
+
searchParams.set("targets", params.targets.join(","));
|
|
562
|
+
if (params.features?.length)
|
|
563
|
+
searchParams.set("features", params.features.join(","));
|
|
564
|
+
if (params.author)
|
|
565
|
+
searchParams.set("author", params.author);
|
|
566
|
+
if (params.sort)
|
|
567
|
+
searchParams.set("sort", params.sort);
|
|
568
|
+
if (params.limit)
|
|
569
|
+
searchParams.set("limit", String(params.limit));
|
|
570
|
+
if (params.offset)
|
|
571
|
+
searchParams.set("offset", String(params.offset));
|
|
572
|
+
const url = `${this.config.registryUrl}/packs?${searchParams.toString()}`;
|
|
573
|
+
const res = await this.fetch(url);
|
|
574
|
+
return res;
|
|
575
|
+
}
|
|
576
|
+
async info(packName) {
|
|
577
|
+
const url = `${this.config.registryUrl}/packs/${encodeURIComponent(packName)}`;
|
|
578
|
+
const res = await this.fetch(url);
|
|
579
|
+
return res;
|
|
580
|
+
}
|
|
581
|
+
async download(packName, version = "latest") {
|
|
582
|
+
const url = `${this.config.registryUrl}/packs/${encodeURIComponent(packName)}/versions/${encodeURIComponent(version)}/download`;
|
|
583
|
+
const response = await fetch(url, {
|
|
584
|
+
headers: this.headers(),
|
|
585
|
+
signal: AbortSignal.timeout(this.config.timeout)
|
|
586
|
+
});
|
|
587
|
+
if (!response.ok) {
|
|
588
|
+
throw new RegistryApiError(response.status, `Failed to download ${packName}@${version}: ${response.statusText}`);
|
|
589
|
+
}
|
|
590
|
+
const integrity = response.headers.get("x-integrity") ?? "";
|
|
591
|
+
const data = await response.arrayBuffer();
|
|
592
|
+
return { data, integrity };
|
|
593
|
+
}
|
|
594
|
+
async publish(tarball, metadata) {
|
|
595
|
+
if (!this.config.authToken) {
|
|
596
|
+
throw new Error("Authentication required. Run `agentpacks login` first.");
|
|
597
|
+
}
|
|
598
|
+
const formData = new FormData;
|
|
599
|
+
formData.append("tarball", new Blob([tarball], { type: "application/gzip" }), `${metadata.name}-${metadata.version}.tgz`);
|
|
600
|
+
formData.append("metadata", JSON.stringify(metadata));
|
|
601
|
+
const url = `${this.config.registryUrl}/packs`;
|
|
602
|
+
const response = await fetch(url, {
|
|
603
|
+
method: "POST",
|
|
604
|
+
headers: {
|
|
605
|
+
Authorization: `Bearer ${this.config.authToken}`
|
|
606
|
+
},
|
|
607
|
+
body: formData,
|
|
608
|
+
signal: AbortSignal.timeout(this.config.timeout)
|
|
609
|
+
});
|
|
610
|
+
if (!response.ok) {
|
|
611
|
+
const body = await response.text();
|
|
612
|
+
throw new RegistryApiError(response.status, `Publish failed: ${body || response.statusText}`);
|
|
613
|
+
}
|
|
614
|
+
return await response.json();
|
|
615
|
+
}
|
|
616
|
+
async featured(limit) {
|
|
617
|
+
const url = limit ? `${this.config.registryUrl}/featured?limit=${limit}` : `${this.config.registryUrl}/featured`;
|
|
618
|
+
const res = await this.fetch(url);
|
|
619
|
+
return res.packs;
|
|
620
|
+
}
|
|
621
|
+
async tags() {
|
|
622
|
+
const url = `${this.config.registryUrl}/tags`;
|
|
623
|
+
const res = await this.fetch(url);
|
|
624
|
+
return res.tags;
|
|
625
|
+
}
|
|
626
|
+
async stats() {
|
|
627
|
+
const url = `${this.config.registryUrl}/stats`;
|
|
628
|
+
return await this.fetch(url);
|
|
629
|
+
}
|
|
630
|
+
async health() {
|
|
631
|
+
try {
|
|
632
|
+
const url = `${this.config.registryUrl}/health`;
|
|
633
|
+
await this.fetch(url);
|
|
634
|
+
return true;
|
|
635
|
+
} catch {
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
async fetch(url) {
|
|
640
|
+
const response = await fetch(url, {
|
|
641
|
+
headers: this.headers(),
|
|
642
|
+
signal: AbortSignal.timeout(this.config.timeout)
|
|
643
|
+
});
|
|
644
|
+
if (!response.ok) {
|
|
645
|
+
const body = await response.text();
|
|
646
|
+
throw new RegistryApiError(response.status, body || response.statusText);
|
|
647
|
+
}
|
|
648
|
+
return response.json();
|
|
649
|
+
}
|
|
650
|
+
headers() {
|
|
651
|
+
const h = {
|
|
652
|
+
Accept: "application/json"
|
|
653
|
+
};
|
|
654
|
+
if (this.config.authToken) {
|
|
655
|
+
h["Authorization"] = `Bearer ${this.config.authToken}`;
|
|
656
|
+
}
|
|
657
|
+
return h;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
class RegistryApiError extends Error {
|
|
662
|
+
status;
|
|
663
|
+
constructor(status, message) {
|
|
664
|
+
super(message);
|
|
665
|
+
this.name = "RegistryApiError";
|
|
666
|
+
this.status = status;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// src/utils/credentials.ts
|
|
671
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
672
|
+
import { join as join3, dirname } from "path";
|
|
673
|
+
import { homedir } from "os";
|
|
674
|
+
var CONFIG_DIR = join3(homedir(), ".config", "agentpacks");
|
|
675
|
+
var CREDENTIALS_FILE = join3(CONFIG_DIR, "credentials.json");
|
|
676
|
+
function loadCredentials() {
|
|
677
|
+
if (!existsSync5(CREDENTIALS_FILE)) {
|
|
678
|
+
return { registryUrl: "https://registry.agentpacks.dev" };
|
|
679
|
+
}
|
|
680
|
+
try {
|
|
681
|
+
const raw = readFileSync3(CREDENTIALS_FILE, "utf-8");
|
|
682
|
+
return JSON.parse(raw);
|
|
683
|
+
} catch {
|
|
684
|
+
return { registryUrl: "https://registry.agentpacks.dev" };
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
function saveCredentials(credentials) {
|
|
688
|
+
mkdirSync3(dirname(CREDENTIALS_FILE), { recursive: true });
|
|
689
|
+
writeFileSync3(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2) + `
|
|
690
|
+
`, {
|
|
691
|
+
mode: 384
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
function clearCredentials() {
|
|
695
|
+
if (existsSync5(CREDENTIALS_FILE)) {
|
|
696
|
+
writeFileSync3(CREDENTIALS_FILE, JSON.stringify({ registryUrl: "https://registry.agentpacks.dev" }) + `
|
|
697
|
+
`);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// src/utils/tarball.ts
|
|
702
|
+
import { execSync as execSync2 } from "child_process";
|
|
703
|
+
import { readFileSync as readFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync4, rmSync } from "fs";
|
|
704
|
+
import { join as join4, resolve as resolve6 } from "path";
|
|
705
|
+
import { createHash as createHash2 } from "crypto";
|
|
706
|
+
import { tmpdir } from "os";
|
|
707
|
+
async function createTarball(packDir) {
|
|
708
|
+
const absDir = resolve6(packDir);
|
|
709
|
+
const tmpFile = join4(tmpdir(), `agentpacks-${Date.now()}.tgz`);
|
|
710
|
+
try {
|
|
711
|
+
execSync2(`tar -czf "${tmpFile}" -C "${absDir}" .`, {
|
|
712
|
+
stdio: "pipe"
|
|
713
|
+
});
|
|
714
|
+
const buffer = readFileSync4(tmpFile);
|
|
715
|
+
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
716
|
+
} finally {
|
|
717
|
+
if (existsSync6(tmpFile)) {
|
|
718
|
+
rmSync(tmpFile);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
async function extractTarball(data, targetDir) {
|
|
723
|
+
mkdirSync4(targetDir, { recursive: true });
|
|
724
|
+
const tmpFile = join4(tmpdir(), `agentpacks-${Date.now()}.tgz`);
|
|
725
|
+
try {
|
|
726
|
+
const buffer = Buffer.from(data);
|
|
727
|
+
const { writeFileSync: writeFileSync4 } = await import("fs");
|
|
728
|
+
writeFileSync4(tmpFile, buffer);
|
|
729
|
+
execSync2(`tar -xzf "${tmpFile}" -C "${targetDir}"`, {
|
|
730
|
+
stdio: "pipe"
|
|
731
|
+
});
|
|
732
|
+
} finally {
|
|
733
|
+
if (existsSync6(tmpFile)) {
|
|
734
|
+
rmSync(tmpFile);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
function computeTarballIntegrity(data) {
|
|
739
|
+
const hash = createHash2("sha256").update(Buffer.from(data)).digest("hex");
|
|
740
|
+
return `sha256-${hash}`;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// src/sources/registry.ts
|
|
744
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readdirSync as readdirSync2, rmSync as rmSync2 } from "fs";
|
|
745
|
+
import { resolve as resolve7, join as join5 } from "path";
|
|
746
|
+
async function installRegistrySource(projectRoot, source, lockfile, options = {}) {
|
|
747
|
+
const parsed = parseRegistrySourceRef(source);
|
|
748
|
+
const sourceKey = registrySourceKey(parsed);
|
|
749
|
+
const installed = [];
|
|
750
|
+
const warnings = [];
|
|
751
|
+
const locked = getLockedSource(lockfile, sourceKey);
|
|
752
|
+
if (options.frozen && !locked) {
|
|
753
|
+
throw new Error(`Frozen mode: no lockfile entry for source "${sourceKey}".`);
|
|
754
|
+
}
|
|
755
|
+
let targetVersion = parsed.version;
|
|
756
|
+
if (locked && !options.update) {
|
|
757
|
+
targetVersion = locked.resolvedRef;
|
|
758
|
+
} else if (targetVersion === "latest") {
|
|
759
|
+
const clientCfg2 = buildClientConfig(options.registryUrl);
|
|
760
|
+
const client2 = createRegistryClient(clientCfg2);
|
|
761
|
+
const info = await client2.info(parsed.packName);
|
|
762
|
+
targetVersion = info.latestVersion;
|
|
763
|
+
}
|
|
764
|
+
const clientCfg = buildClientConfig(options.registryUrl);
|
|
765
|
+
const client = createRegistryClient(clientCfg);
|
|
766
|
+
const { data } = await client.download(parsed.packName, targetVersion);
|
|
767
|
+
const localIntegrity = computeTarballIntegrity(data);
|
|
768
|
+
if (locked && !options.update && locked.skills?.["__integrity"]) {
|
|
769
|
+
const expectedIntegrity = locked.skills["__integrity"].integrity;
|
|
770
|
+
if (expectedIntegrity && localIntegrity !== expectedIntegrity) {
|
|
771
|
+
throw new Error(`Integrity mismatch for ${parsed.packName}@${targetVersion}. ` + `Expected ${expectedIntegrity}, got ${localIntegrity}.`);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
const curatedDir = resolve7(projectRoot, ".agentpacks", ".curated");
|
|
775
|
+
const packOutDir = resolve7(curatedDir, parsed.packName);
|
|
776
|
+
if (existsSync7(packOutDir)) {
|
|
777
|
+
rmSync2(packOutDir, { recursive: true, force: true });
|
|
778
|
+
}
|
|
779
|
+
mkdirSync5(packOutDir, { recursive: true });
|
|
780
|
+
await extractTarball(data, packOutDir);
|
|
781
|
+
collectFiles2(packOutDir, installed);
|
|
782
|
+
const newEntry = {
|
|
783
|
+
requestedRef: parsed.version,
|
|
784
|
+
resolvedRef: targetVersion,
|
|
785
|
+
resolvedAt: new Date().toISOString(),
|
|
786
|
+
skills: {
|
|
787
|
+
__integrity: { integrity: localIntegrity }
|
|
788
|
+
},
|
|
789
|
+
packs: {
|
|
790
|
+
[parsed.packName]: { integrity: localIntegrity }
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
setLockedSource(lockfile, sourceKey, newEntry);
|
|
794
|
+
return { installed, warnings };
|
|
795
|
+
}
|
|
796
|
+
function buildClientConfig(registryUrl) {
|
|
797
|
+
const cfg = {};
|
|
798
|
+
if (registryUrl) {
|
|
799
|
+
cfg.registryUrl = registryUrl;
|
|
800
|
+
}
|
|
801
|
+
try {
|
|
802
|
+
const creds = loadCredentials();
|
|
803
|
+
if (creds?.token) {
|
|
804
|
+
cfg.authToken = creds.token;
|
|
805
|
+
}
|
|
806
|
+
} catch {}
|
|
807
|
+
return cfg;
|
|
808
|
+
}
|
|
809
|
+
function collectFiles2(dir, out) {
|
|
810
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
811
|
+
for (const entry of entries) {
|
|
812
|
+
const full = join5(dir, entry.name);
|
|
813
|
+
if (entry.isDirectory()) {
|
|
814
|
+
collectFiles2(full, out);
|
|
815
|
+
} else {
|
|
816
|
+
out.push(full);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
540
821
|
// src/cli/install.ts
|
|
541
|
-
init_config();
|
|
542
822
|
import chalk from "chalk";
|
|
543
823
|
async function runInstall(projectRoot, options) {
|
|
544
824
|
const config = loadWorkspaceConfig(projectRoot);
|
|
545
825
|
const lockfile = loadLockfile(projectRoot);
|
|
546
826
|
const verbose = options.verbose ?? config.verbose;
|
|
547
|
-
const remotePacks = config.packs.filter((ref) => isGitPackRef(ref) || isNpmPackRef(ref));
|
|
827
|
+
const remotePacks = config.packs.filter((ref) => isGitPackRef(ref) || isNpmPackRef(ref) || isRegistryPackRef(ref));
|
|
548
828
|
const localPacks = config.packs.filter((ref) => isLocalPackRef(ref));
|
|
549
829
|
if (remotePacks.length === 0) {
|
|
550
830
|
console.log(chalk.dim("No remote packs to install. All packs are local."));
|
|
@@ -570,7 +850,12 @@ async function runInstall(projectRoot, options) {
|
|
|
570
850
|
}
|
|
571
851
|
try {
|
|
572
852
|
let result;
|
|
573
|
-
if (
|
|
853
|
+
if (isRegistryPackRef(packRef)) {
|
|
854
|
+
result = await installRegistrySource(projectRoot, packRef, lockfile, {
|
|
855
|
+
update: options.update,
|
|
856
|
+
frozen: options.frozen
|
|
857
|
+
});
|
|
858
|
+
} else if (isGitPackRef(packRef)) {
|
|
574
859
|
const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN ?? undefined;
|
|
575
860
|
result = await installGitSource(projectRoot, packRef, lockfile, {
|
|
576
861
|
update: options.update,
|