@agentrules/core 0.0.3 → 0.0.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/index.d.ts CHANGED
@@ -1,7 +1,20 @@
1
1
  import { z } from "zod";
2
2
 
3
- //#region src/types/platform.d.ts
3
+ //#region src/types/constants.d.ts
4
+ /**
5
+ * Shared constants for agentrules presets and registry.
6
+ */
7
+ /** Filename for preset configuration */
8
+ /**
9
+ * Shared constants for agentrules presets and registry.
10
+ */
11
+ /** Filename for preset configuration */
12
+ declare const PRESET_CONFIG_FILENAME = "agentrules.json";
13
+ /** JSON Schema URL for preset configuration */
14
+ declare const PRESET_SCHEMA_URL = "https://agentrules.directory/schema/agentrules.json";
4
15
 
16
+ //#endregion
17
+ //#region src/types/platform.d.ts
5
18
  /**
6
19
  * Single source of truth for platform IDs.
7
20
  * Add new platforms here - types and config will follow.
@@ -29,6 +42,7 @@ declare const PLATFORMS: Record<PlatformId, PlatformConfig>;
29
42
  declare const CONFIG_DIR_NAME = "config";
30
43
  declare function isSupportedPlatform(value: string): value is PlatformId;
31
44
  declare function normalizePlatformInput(value: string): PlatformId;
45
+
32
46
  //#endregion
33
47
  //#region src/types/definitions.d.ts
34
48
  type AuthorInfo = {
@@ -37,7 +51,8 @@ type AuthorInfo = {
37
51
  url?: string;
38
52
  };
39
53
  type PlatformPresetConfig = {
40
- path: string;
54
+ /** Path to platform config files. Defaults to platform's projectDir (e.g., ".opencode") */
55
+ path?: string;
41
56
  features?: string[];
42
57
  installMessage?: string;
43
58
  };
@@ -45,11 +60,11 @@ type PresetConfig = {
45
60
  $schema?: string;
46
61
  name: string;
47
62
  title: string;
48
- version: string;
63
+ version?: string;
49
64
  description: string;
50
65
  tags?: string[];
51
66
  author?: AuthorInfo;
52
- license?: string;
67
+ license: string;
53
68
  platforms: Partial<Record<PlatformId, PlatformPresetConfig>>;
54
69
  };
55
70
  type BundledFile = {
@@ -67,10 +82,11 @@ type RegistryBundle = {
67
82
  description: string;
68
83
  tags: string[];
69
84
  author?: AuthorInfo;
70
- license?: string;
85
+ license: string;
86
+ licenseContent?: string;
87
+ readmeContent?: string;
71
88
  features?: string[];
72
89
  installMessage?: string;
73
- readme?: string;
74
90
  files: BundledFile[];
75
91
  };
76
92
  type RegistryEntry = {
@@ -82,15 +98,17 @@ type RegistryEntry = {
82
98
  description: string;
83
99
  tags: string[];
84
100
  author?: AuthorInfo;
85
- license?: string;
101
+ license: string;
86
102
  features?: string[];
87
103
  installMessage?: string;
88
104
  bundlePath: string;
89
105
  fileCount: number;
90
106
  /** Total size of all files in bytes */
91
107
  totalSize: number;
92
- /** Whether the preset has a README */
93
- hasReadme?: boolean;
108
+ /** Whether the preset has a README.md */
109
+ hasReadmeContent?: boolean;
110
+ /** Whether the preset has a LICENSE.md */
111
+ hasLicenseContent?: boolean;
94
112
  };
95
113
  type RegistryData = {
96
114
  $schema: string;
@@ -105,12 +123,15 @@ type RegistryFileInput = {
105
123
  type RegistryPlatformInput = {
106
124
  platform: PlatformId;
107
125
  files: RegistryFileInput[];
126
+ /** Install message from INSTALL.txt file */
127
+ installMessage?: string;
108
128
  };
109
129
  type RegistryPresetInput = {
110
130
  slug: string;
111
131
  config: PresetConfig;
112
132
  platforms: RegistryPlatformInput[];
113
- readme?: string;
133
+ readmeContent?: string;
134
+ licenseContent?: string;
114
135
  }; //#endregion
115
136
  //#region src/types/schema.d.ts
116
137
  declare const platformIdSchema: z.ZodEnum<{
@@ -124,16 +145,29 @@ declare const authorSchema: z.ZodObject<{
124
145
  email: z.ZodOptional<z.ZodEmail>;
125
146
  url: z.ZodOptional<z.ZodURL>;
126
147
  }, z.core.$strict>;
148
+ declare const titleSchema: z.ZodString;
149
+ declare const descriptionSchema: z.ZodString;
150
+ /** Validate a title string and return error message if invalid, undefined if valid */
151
+ declare function validateTitle(value: string): string | undefined;
152
+ /** Validate a description string and return error message if invalid, undefined if valid */
153
+ declare function validateDescription(value: string): string | undefined;
154
+ declare const slugSchema: z.ZodString;
155
+ /** Validate a slug string and return error message if invalid, undefined if valid */
156
+ declare function validateSlug(value: string): string | undefined;
157
+ declare const COMMON_LICENSES: readonly ["MIT", "Apache-2.0", "GPL-3.0-only", "BSD-3-Clause", "ISC", "Unlicense"];
158
+ type CommonLicense = (typeof COMMON_LICENSES)[number];
159
+ declare const licenseSchema: z.ZodString;
160
+ /** Validate a license string and return error message if invalid, undefined if valid */
161
+ declare function validateLicense(value: string): string | undefined;
127
162
  declare const platformPresetConfigSchema: z.ZodObject<{
128
- path: z.ZodString;
163
+ path: z.ZodOptional<z.ZodString>;
129
164
  features: z.ZodOptional<z.ZodArray<z.ZodString>>;
130
- installMessage: z.ZodOptional<z.ZodString>;
131
165
  }, z.core.$strict>;
132
166
  declare const presetConfigSchema: z.ZodObject<{
133
167
  $schema: z.ZodOptional<z.ZodString>;
134
168
  name: z.ZodString;
135
169
  title: z.ZodString;
136
- version: z.ZodString;
170
+ version: z.ZodOptional<z.ZodString>;
137
171
  description: z.ZodString;
138
172
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
139
173
  author: z.ZodOptional<z.ZodObject<{
@@ -141,12 +175,11 @@ declare const presetConfigSchema: z.ZodObject<{
141
175
  email: z.ZodOptional<z.ZodEmail>;
142
176
  url: z.ZodOptional<z.ZodURL>;
143
177
  }, z.core.$strict>>;
144
- license: z.ZodOptional<z.ZodString>;
178
+ license: z.ZodString;
145
179
  platforms: z.ZodObject<{
146
180
  [x: string]: z.ZodOptional<z.ZodObject<{
147
- path: z.ZodString;
181
+ path: z.ZodOptional<z.ZodString>;
148
182
  features: z.ZodOptional<z.ZodArray<z.ZodString>>;
149
- installMessage: z.ZodOptional<z.ZodString>;
150
183
  }, z.core.$strict>>;
151
184
  }, z.core.$strip>;
152
185
  }, z.core.$strict>;
@@ -173,7 +206,9 @@ declare const registryBundleSchema: z.ZodObject<{
173
206
  email: z.ZodOptional<z.ZodEmail>;
174
207
  url: z.ZodOptional<z.ZodURL>;
175
208
  }, z.core.$strict>>;
176
- license: z.ZodOptional<z.ZodString>;
209
+ license: z.ZodString;
210
+ licenseContent: z.ZodOptional<z.ZodString>;
211
+ readmeContent: z.ZodOptional<z.ZodString>;
177
212
  features: z.ZodOptional<z.ZodArray<z.ZodString>>;
178
213
  installMessage: z.ZodOptional<z.ZodString>;
179
214
  files: z.ZodArray<z.ZodObject<{
@@ -185,17 +220,16 @@ declare const registryBundleSchema: z.ZodObject<{
185
220
  }, z.core.$strip>;
186
221
  declare const registryEntrySchema: z.ZodObject<{
187
222
  features: z.ZodOptional<z.ZodArray<z.ZodString>>;
188
- installMessage: z.ZodOptional<z.ZodString>;
189
223
  title: z.ZodString;
190
- version: z.ZodString;
191
224
  description: z.ZodString;
225
+ license: z.ZodString;
226
+ version: z.ZodString;
192
227
  tags: z.ZodArray<z.ZodString>;
193
228
  author: z.ZodOptional<z.ZodObject<{
194
229
  name: z.ZodString;
195
230
  email: z.ZodOptional<z.ZodEmail>;
196
231
  url: z.ZodOptional<z.ZodURL>;
197
232
  }, z.core.$strict>>;
198
- license: z.ZodOptional<z.ZodString>;
199
233
  platform: z.ZodEnum<{
200
234
  opencode: "opencode";
201
235
  codex: "codex";
@@ -207,20 +241,21 @@ declare const registryEntrySchema: z.ZodObject<{
207
241
  bundlePath: z.ZodString;
208
242
  fileCount: z.ZodNumber;
209
243
  totalSize: z.ZodNumber;
244
+ hasReadmeContent: z.ZodOptional<z.ZodBoolean>;
245
+ hasLicenseContent: z.ZodOptional<z.ZodBoolean>;
210
246
  }, z.core.$strip>;
211
247
  declare const registryIndexSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
212
248
  features: z.ZodOptional<z.ZodArray<z.ZodString>>;
213
- installMessage: z.ZodOptional<z.ZodString>;
214
249
  title: z.ZodString;
215
- version: z.ZodString;
216
250
  description: z.ZodString;
251
+ license: z.ZodString;
252
+ version: z.ZodString;
217
253
  tags: z.ZodArray<z.ZodString>;
218
254
  author: z.ZodOptional<z.ZodObject<{
219
255
  name: z.ZodString;
220
256
  email: z.ZodOptional<z.ZodEmail>;
221
257
  url: z.ZodOptional<z.ZodURL>;
222
258
  }, z.core.$strict>>;
223
- license: z.ZodOptional<z.ZodString>;
224
259
  platform: z.ZodEnum<{
225
260
  opencode: "opencode";
226
261
  codex: "codex";
@@ -232,6 +267,8 @@ declare const registryIndexSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
232
267
  bundlePath: z.ZodString;
233
268
  fileCount: z.ZodNumber;
234
269
  totalSize: z.ZodNumber;
270
+ hasReadmeContent: z.ZodOptional<z.ZodBoolean>;
271
+ hasLicenseContent: z.ZodOptional<z.ZodBoolean>;
235
272
  }, z.core.$strip>>;
236
273
 
237
274
  //#endregion
@@ -239,6 +276,8 @@ declare const registryIndexSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
239
276
  type BuildRegistryDataOptions = {
240
277
  presets: RegistryPresetInput[];
241
278
  bundleBase?: string;
279
+ /** Override the auto-generated version. If not provided, uses current UTC date. */
280
+ version?: string;
242
281
  };
243
282
  type BuildRegistryDataResult = {
244
283
  entries: RegistryEntry[];
@@ -249,6 +288,11 @@ declare function buildRegistryData(options: BuildRegistryDataOptions): BuildRegi
249
288
 
250
289
  //#endregion
251
290
  //#region src/builder/utils.d.ts
291
+ /**
292
+ * Generates a date-based version string in format YYYY.MM.DD
293
+ * Uses UTC to ensure consistent versioning across timezones
294
+ */
295
+ declare function generateDateVersion(date?: Date): string;
252
296
  declare function normalizeBundlePublicBase(value: string): string;
253
297
  declare function isAbsoluteUrl(value: string): boolean;
254
298
  declare function cleanInstallMessage(value: unknown): string | undefined;
@@ -265,12 +309,8 @@ declare function toUtf8String(payload: ArrayBuffer | ArrayBufferView): string;
265
309
 
266
310
  //#endregion
267
311
  //#region src/client/registry.d.ts
268
- type FetchRegistryBundleResult = {
269
- bundle: RegistryBundle;
270
- etag: string | null;
271
- };
272
312
  declare function fetchRegistryIndex(baseUrl: string): Promise<RegistryIndex>;
273
- declare function fetchRegistryBundle(baseUrl: string, bundlePath: string): Promise<FetchRegistryBundleResult>;
313
+ declare function fetchRegistryBundle(baseUrl: string, bundlePath: string): Promise<RegistryBundle>;
274
314
  declare function resolveRegistryEntry(index: RegistryIndex, input: string, explicitPlatform?: PlatformId): RegistryEntry;
275
315
 
276
316
  //#endregion
@@ -295,4 +335,4 @@ declare function normalizePathFragment(value?: string): string | undefined;
295
335
  declare function maybeStripPrefix(pathInput: string, prefix?: string): string;
296
336
 
297
337
  //#endregion
298
- export { AuthorInfo, BuildRegistryDataOptions, BuildRegistryDataResult, BundledFile, CONFIG_DIR_NAME, DiffPreviewOptions, FetchRegistryBundleResult, PLATFORMS, PLATFORM_IDS, PlatformId, PlatformPresetConfig, PresetConfig, RegistryBundle, RegistryData, RegistryEntry, RegistryFileInput, RegistryIndex, RegistryIndexItem, RegistryPlatformInput, RegistryPresetInput, authorSchema, buildRegistryData, bundledFileSchema, cleanInstallMessage, collectBundledFiles, createDiffPreview, decodeBundledFile, decodeUtf8, encodeItemName, encodeUtf8, fetchRegistryBundle, fetchRegistryIndex, isAbsoluteUrl, isLikelyText, isSupportedPlatform, maybeStripPrefix, normalizeBundlePath, normalizeBundlePublicBase, normalizePathFragment, normalizePlatformInput, platformIdSchema, platformPresetConfigSchema, presetConfigSchema, registryBundleSchema, registryEntrySchema, registryIndexSchema, resolveRegistryEntry, toPosixPath, toUint8Array, toUtf8String, validatePresetConfig, verifyBundledFileChecksum };
338
+ export { AuthorInfo, BuildRegistryDataOptions, BuildRegistryDataResult, BundledFile, COMMON_LICENSES, CONFIG_DIR_NAME, CommonLicense, DiffPreviewOptions, PLATFORMS, PLATFORM_IDS, PRESET_CONFIG_FILENAME, PRESET_SCHEMA_URL, PlatformId, PlatformPresetConfig, PresetConfig, RegistryBundle, RegistryData, RegistryEntry, RegistryFileInput, RegistryIndex, RegistryIndexItem, RegistryPlatformInput, RegistryPresetInput, authorSchema, buildRegistryData, bundledFileSchema, cleanInstallMessage, collectBundledFiles, createDiffPreview, decodeBundledFile, decodeUtf8, descriptionSchema, encodeItemName, encodeUtf8, fetchRegistryBundle, fetchRegistryIndex, generateDateVersion, isAbsoluteUrl, isLikelyText, isSupportedPlatform, licenseSchema, maybeStripPrefix, normalizeBundlePath, normalizeBundlePublicBase, normalizePathFragment, normalizePlatformInput, platformIdSchema, platformPresetConfigSchema, presetConfigSchema, registryBundleSchema, registryEntrySchema, registryIndexSchema, resolveRegistryEntry, slugSchema, titleSchema, toPosixPath, toUint8Array, toUtf8String, validateDescription, validateLicense, validatePresetConfig, validateSlug, validateTitle, verifyBundledFileChecksum };
package/dist/index.js CHANGED
@@ -2,6 +2,16 @@ import { createHash } from "crypto";
2
2
  import { z } from "zod";
3
3
  import { createTwoFilesPatch } from "diff";
4
4
 
5
+ //#region src/types/constants.ts
6
+ /**
7
+ * Shared constants for agentrules presets and registry.
8
+ */
9
+ /** Filename for preset configuration */
10
+ const PRESET_CONFIG_FILENAME = "agentrules.json";
11
+ /** JSON Schema URL for preset configuration */
12
+ const PRESET_SCHEMA_URL = "https://agentrules.directory/schema/agentrules.json";
13
+
14
+ //#endregion
5
15
  //#region src/types/platform.ts
6
16
  /**
7
17
  * Single source of truth for platform IDs.
@@ -53,7 +63,7 @@ function normalizePlatformInput(value) {
53
63
 
54
64
  //#endregion
55
65
  //#region src/types/schema.ts
56
- const SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-(?:0|[1-9A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
66
+ const DATE_VERSION_REGEX = /^\d{4}\.(0[1-9]|1[0-2])\.(0[1-9]|[12]\d|3[01])(-\d+)?$/;
57
67
  const platformIdSchema = z.enum(PLATFORM_IDS);
58
68
  const authorSchema = z.object({
59
69
  name: z.string().trim().min(1),
@@ -62,30 +72,69 @@ const authorSchema = z.object({
62
72
  }).strict();
63
73
  const titleSchema = z.string().trim().min(1).max(120);
64
74
  const descriptionSchema = z.string().trim().min(1).max(500);
65
- const versionSchema = z.string().trim().regex(SEMVER_REGEX, "Version must follow semantic versioning");
75
+ /** Validate a title string and return error message if invalid, undefined if valid */
76
+ function validateTitle(value) {
77
+ const trimmed = value.trim();
78
+ if (!trimmed) return "Title is required";
79
+ if (trimmed.length > 120) return "Title must be 120 characters or less";
80
+ return;
81
+ }
82
+ /** Validate a description string and return error message if invalid, undefined if valid */
83
+ function validateDescription(value) {
84
+ const trimmed = value.trim();
85
+ if (!trimmed) return "Description is required";
86
+ if (trimmed.length > 500) return "Description must be 500 characters or less";
87
+ return;
88
+ }
89
+ const versionSchema = z.string().trim().regex(DATE_VERSION_REGEX, "Version must be date-based (YYYY.MM.DD or YYYY.MM.DD-N)");
66
90
  const tagSchema = z.string().trim().min(1).max(48);
67
91
  const tagsSchema = z.array(tagSchema).max(10);
68
92
  const featureSchema = z.string().trim().min(1).max(160);
69
93
  const featuresSchema = z.array(featureSchema).max(10);
70
94
  const installMessageSchema = z.string().trim().max(4e3);
71
- const licenseSchema = z.string().trim().max(80);
72
- const slugSchema = z.string().trim().min(1).max(64).regex(/^[a-z0-9-]+$/, "Name must be lowercase kebab-case");
95
+ const contentSchema = z.string();
96
+ const SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
97
+ const SLUG_ERROR = "Must be lowercase alphanumeric with hyphens (e.g., my-preset)";
98
+ const slugSchema = z.string().trim().min(1).max(64).regex(SLUG_REGEX, SLUG_ERROR);
99
+ /** Validate a slug string and return error message if invalid, undefined if valid */
100
+ function validateSlug(value) {
101
+ const trimmed = value.trim();
102
+ if (!trimmed) return "Name is required";
103
+ if (trimmed.length > 64) return "Name must be 64 characters or less";
104
+ if (!SLUG_REGEX.test(trimmed)) return SLUG_ERROR;
105
+ return;
106
+ }
107
+ const COMMON_LICENSES = [
108
+ "MIT",
109
+ "Apache-2.0",
110
+ "GPL-3.0-only",
111
+ "BSD-3-Clause",
112
+ "ISC",
113
+ "Unlicense"
114
+ ];
115
+ const licenseSchema = z.string().trim().min(1).max(128);
116
+ /** Validate a license string and return error message if invalid, undefined if valid */
117
+ function validateLicense(value) {
118
+ const trimmed = value.trim();
119
+ if (!trimmed) return "License is required";
120
+ if (trimmed.length > 128) return "License must be 128 characters or less";
121
+ return;
122
+ }
73
123
  const pathSchema = z.string().trim().min(1);
74
124
  const platformPresetConfigSchema = z.object({
75
- path: pathSchema,
76
- features: featuresSchema.optional(),
77
- installMessage: installMessageSchema.optional()
125
+ path: pathSchema.optional(),
126
+ features: featuresSchema.optional()
78
127
  }).strict();
79
128
  const platformsObjectSchema = z.object(Object.fromEntries(PLATFORM_IDS.map((id) => [id, platformPresetConfigSchema.optional()]))).refine((p) => Object.keys(p).length > 0, { message: "At least one platform must be configured" });
80
129
  const presetConfigSchema = z.object({
81
130
  $schema: z.string().optional(),
82
131
  name: slugSchema,
83
132
  title: titleSchema,
84
- version: versionSchema,
133
+ version: versionSchema.optional(),
85
134
  description: descriptionSchema,
86
135
  tags: tagsSchema.optional(),
87
136
  author: authorSchema.optional(),
88
- license: licenseSchema.optional(),
137
+ license: licenseSchema,
89
138
  platforms: platformsObjectSchema
90
139
  }).strict();
91
140
  const bundledFileSchema = z.object({
@@ -102,16 +151,25 @@ const registryBundleSchema = z.object({
102
151
  description: descriptionSchema,
103
152
  tags: tagsSchema,
104
153
  author: authorSchema.optional(),
105
- license: licenseSchema.optional(),
154
+ license: licenseSchema,
155
+ licenseContent: contentSchema.optional(),
156
+ readmeContent: contentSchema.optional(),
106
157
  features: featuresSchema.optional(),
107
158
  installMessage: installMessageSchema.optional(),
108
159
  files: z.array(bundledFileSchema).min(1)
109
160
  });
110
- const registryEntrySchema = registryBundleSchema.omit({ files: true }).extend({
161
+ const registryEntrySchema = registryBundleSchema.omit({
162
+ files: true,
163
+ readmeContent: true,
164
+ licenseContent: true,
165
+ installMessage: true
166
+ }).extend({
111
167
  name: z.string().trim().min(1),
112
168
  bundlePath: z.string().trim().min(1),
113
169
  fileCount: z.number().int().nonnegative(),
114
- totalSize: z.number().int().nonnegative()
170
+ totalSize: z.number().int().nonnegative(),
171
+ hasReadmeContent: z.boolean().optional(),
172
+ hasLicenseContent: z.boolean().optional()
115
173
  });
116
174
  const registryIndexSchema = z.record(z.string(), registryEntrySchema);
117
175
 
@@ -137,6 +195,16 @@ function toUint8Array(payload) {
137
195
 
138
196
  //#endregion
139
197
  //#region src/builder/utils.ts
198
+ /**
199
+ * Generates a date-based version string in format YYYY.MM.DD
200
+ * Uses UTC to ensure consistent versioning across timezones
201
+ */
202
+ function generateDateVersion(date = new Date()) {
203
+ const year = date.getUTCFullYear();
204
+ const month = String(date.getUTCMonth() + 1).padStart(2, "0");
205
+ const day = String(date.getUTCDate()).padStart(2, "0");
206
+ return `${year}.${month}.${day}`;
207
+ }
140
208
  function normalizeBundlePublicBase(value) {
141
209
  const trimmed = value.trim();
142
210
  if (!trimmed) throw new Error("--bundle-base must be a non-empty string");
@@ -162,8 +230,9 @@ function validatePresetConfig(config, slug) {
162
230
  const preset = config;
163
231
  if (!preset.name || typeof preset.name !== "string") throw new Error(`Preset ${slug} is missing a name`);
164
232
  if (!preset.title || typeof preset.title !== "string") throw new Error(`Preset ${slug} is missing a title`);
165
- if (!preset.version || typeof preset.version !== "string") throw new Error(`Preset ${slug} is missing a version`);
233
+ if (preset.version !== void 0 && typeof preset.version !== "string") throw new Error(`Preset ${slug} has invalid version (must be string or omitted)`);
166
234
  if (!preset.description || typeof preset.description !== "string") throw new Error(`Preset ${slug} is missing a description`);
235
+ if (!preset.license || typeof preset.license !== "string") throw new Error(`Preset ${slug} is missing a license (SPDX identifier required)`);
167
236
  if (!preset.platforms || typeof preset.platforms !== "object") throw new Error(`Preset ${slug} is missing platforms map`);
168
237
  return preset;
169
238
  }
@@ -185,6 +254,7 @@ function collectBundledFiles(files) {
185
254
  const NAME_PATTERN = /^[a-z0-9-]+$/;
186
255
  function buildRegistryData(options) {
187
256
  const bundleBase = normalizeBundlePublicBase(options.bundleBase ?? "/r");
257
+ const buildVersion = options.version ?? generateDateVersion();
188
258
  const entries = [];
189
259
  const bundles = [];
190
260
  for (const presetInput of options.presets) {
@@ -199,38 +269,40 @@ function buildRegistryData(options) {
199
269
  if (platformInput.files.length === 0) throw new Error(`Preset ${presetInput.slug}/${platform} does not include any files.`);
200
270
  const files = createBundledFilesFromInputs(platformInput.files);
201
271
  const totalSize = files.reduce((sum, file) => sum + file.size, 0);
202
- const installMessage = cleanInstallMessage(platformConfig.installMessage);
272
+ const installMessage = cleanInstallMessage(platformInput.installMessage);
203
273
  const features = platformConfig.features ?? [];
204
- const readme = presetInput.readme?.trim() || void 0;
274
+ const readmeContent = presetInput.readmeContent?.trim() || void 0;
275
+ const licenseContent = presetInput.licenseContent?.trim() || void 0;
205
276
  const entry = {
206
277
  name: encodeItemName(presetInput.slug, platform),
207
278
  slug: presetInput.slug,
208
279
  platform,
209
280
  title: presetConfig.title,
210
- version: presetConfig.version,
281
+ version: buildVersion,
211
282
  description: presetConfig.description,
212
283
  tags: presetConfig.tags ?? [],
213
284
  author: presetConfig.author,
214
285
  license: presetConfig.license,
215
286
  features,
216
- installMessage,
217
- bundlePath: getBundlePublicPath(bundleBase, presetInput.slug, platform),
287
+ bundlePath: getBundlePublicPath(bundleBase, presetInput.slug, platform, buildVersion),
218
288
  fileCount: files.length,
219
289
  totalSize,
220
- hasReadme: Boolean(readme)
290
+ hasReadmeContent: Boolean(readmeContent),
291
+ hasLicenseContent: Boolean(licenseContent)
221
292
  };
222
293
  const bundle = {
223
294
  slug: presetInput.slug,
224
295
  platform,
225
296
  title: presetConfig.title,
226
- version: presetConfig.version,
297
+ version: buildVersion,
227
298
  description: presetConfig.description,
228
299
  tags: presetConfig.tags ?? [],
229
300
  author: presetConfig.author,
230
301
  license: presetConfig.license,
302
+ licenseContent,
303
+ readmeContent,
231
304
  features,
232
305
  installMessage,
233
- readme,
234
306
  files
235
307
  };
236
308
  entries.push(entry);
@@ -273,9 +345,9 @@ function encodeFilePayload(buffer, filePath) {
273
345
  if (!Buffer.from(utf8, "utf8").equals(buffer)) throw new Error(`Binary files are not supported: "${filePath}". Only UTF-8 text files are allowed.`);
274
346
  return utf8;
275
347
  }
276
- function getBundlePublicPath(base, slug, platform) {
348
+ function getBundlePublicPath(base, slug, platform, version) {
277
349
  const prefix = base === "/" ? "" : base;
278
- return `${prefix}/${slug}/${platform}.json`;
350
+ return `${prefix}/${slug}/${platform}.${version}.json`;
279
351
  }
280
352
  function ensureKnownPlatform(platform, slug) {
281
353
  if (!isSupportedPlatform(platform)) throw new Error(`Unknown platform "${platform}" in ${slug}. Supported: ${PLATFORM_IDS.join(", ")}`);
@@ -334,11 +406,7 @@ async function fetchRegistryBundle(baseUrl, bundlePath) {
334
406
  const response = await fetch(bundleUrl);
335
407
  if (!response.ok) throw new Error(`Failed to download bundle (${response.status} ${response.statusText}).`);
336
408
  try {
337
- const bundle = await response.json();
338
- return {
339
- bundle,
340
- etag: response.headers.get("etag")
341
- };
409
+ return await response.json();
342
410
  } catch (error) {
343
411
  throw new Error(`Unable to parse bundle JSON: ${error.message}`);
344
412
  }
@@ -404,4 +472,4 @@ function maybeStripPrefix(pathInput, prefix) {
404
472
  }
405
473
 
406
474
  //#endregion
407
- export { CONFIG_DIR_NAME, PLATFORMS, PLATFORM_IDS, authorSchema, buildRegistryData, bundledFileSchema, cleanInstallMessage, collectBundledFiles, createDiffPreview, decodeBundledFile, decodeUtf8, encodeItemName, encodeUtf8, fetchRegistryBundle, fetchRegistryIndex, isAbsoluteUrl, isLikelyText, isSupportedPlatform, maybeStripPrefix, normalizeBundlePath, normalizeBundlePublicBase, normalizePathFragment, normalizePlatformInput, platformIdSchema, platformPresetConfigSchema, presetConfigSchema, registryBundleSchema, registryEntrySchema, registryIndexSchema, resolveRegistryEntry, toPosixPath, toUint8Array, toUtf8String, validatePresetConfig, verifyBundledFileChecksum };
475
+ export { COMMON_LICENSES, CONFIG_DIR_NAME, PLATFORMS, PLATFORM_IDS, PRESET_CONFIG_FILENAME, PRESET_SCHEMA_URL, authorSchema, buildRegistryData, bundledFileSchema, cleanInstallMessage, collectBundledFiles, createDiffPreview, decodeBundledFile, decodeUtf8, descriptionSchema, encodeItemName, encodeUtf8, fetchRegistryBundle, fetchRegistryIndex, generateDateVersion, isAbsoluteUrl, isLikelyText, isSupportedPlatform, licenseSchema, maybeStripPrefix, normalizeBundlePath, normalizeBundlePublicBase, normalizePathFragment, normalizePlatformInput, platformIdSchema, platformPresetConfigSchema, presetConfigSchema, registryBundleSchema, registryEntrySchema, registryIndexSchema, resolveRegistryEntry, slugSchema, titleSchema, toPosixPath, toUint8Array, toUtf8String, validateDescription, validateLicense, validatePresetConfig, validateSlug, validateTitle, verifyBundledFileChecksum };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentrules/core",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "author": "Brian Cheung <bcheung.dev@gmail.com> (https://github.com/bcheung)",
5
5
  "license": "MIT",
6
6
  "homepage": "https://docs.agentrules.directory",
@@ -51,4 +51,4 @@
51
51
  "tsdown": "^0.9.0",
52
52
  "typescript": "5.7.2"
53
53
  }
54
- }
54
+ }