@agentrules/core 0.0.1

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.
@@ -0,0 +1,237 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/types.d.ts
4
+ type PlatformId = "opencode" | "codex" | "claude" | "cursor";
5
+ type AuthorInfo = {
6
+ name: string;
7
+ email?: string;
8
+ url?: string;
9
+ };
10
+ type PlatformSpecificConfig = {
11
+ features?: string[];
12
+ installMessage?: string;
13
+ };
14
+ type PresetConfig = {
15
+ title: string;
16
+ version: string;
17
+ description: string;
18
+ tags?: string[];
19
+ author?: AuthorInfo;
20
+ license?: string;
21
+ primary?: PlatformId;
22
+ platforms: Partial<Record<PlatformId, PlatformSpecificConfig>>;
23
+ };
24
+ type BundledFile = {
25
+ path: string;
26
+ size: number;
27
+ checksum: string;
28
+ encoding: "utf-8" | "base64";
29
+ contents: string;
30
+ };
31
+ type RegistryBundle = {
32
+ slug: string;
33
+ platform: PlatformId;
34
+ title: string;
35
+ version: string;
36
+ description: string;
37
+ tags: string[];
38
+ author?: AuthorInfo;
39
+ license?: string;
40
+ features?: string[];
41
+ installMessage?: string;
42
+ files: BundledFile[];
43
+ };
44
+ type RegistryEntry = {
45
+ name: string;
46
+ slug: string;
47
+ platform: PlatformId;
48
+ title: string;
49
+ version: string;
50
+ description: string;
51
+ tags: string[];
52
+ author?: AuthorInfo;
53
+ license?: string;
54
+ features?: string[];
55
+ installMessage?: string;
56
+ bundlePath: string;
57
+ fileCount: number;
58
+ totalBytes: number;
59
+ isPrimary?: boolean;
60
+ };
61
+ type RegistryData = {
62
+ $schema: string;
63
+ items: RegistryEntry[];
64
+ };
65
+ type RegistryIndex = Record<string, RegistryEntry>;
66
+ type RegistryIndexItem = RegistryEntry; //#endregion
67
+ //#region src/build-utils.d.ts
68
+ declare function normalizeBundlePublicBase(value: string): string;
69
+ declare function isAbsoluteUrl(value: string): boolean;
70
+ declare function cleanInstallMessage(value: unknown): string | undefined;
71
+ declare function encodeItemName(slug: string, platform: PlatformId): string;
72
+ declare function validatePresetConfig(config: unknown, slug: string): PresetConfig;
73
+ declare function collectBundledFiles(files: Record<string, string>): BundledFile[];
74
+
75
+ //#endregion
76
+ //#region src/bundle.d.ts
77
+ declare function decodeBundledFile(file: BundledFile): Uint8Array;
78
+ declare function verifyBundledFileChecksum(file: BundledFile, payload: ArrayBuffer | ArrayBufferView): Promise<void>;
79
+ declare function isLikelyText(payload: ArrayBuffer | ArrayBufferView): boolean;
80
+ declare function toUtf8String(payload: ArrayBuffer | ArrayBufferView): string;
81
+
82
+ //#endregion
83
+ //#region src/diff.d.ts
84
+ type DiffPreviewOptions = {
85
+ context?: number;
86
+ maxLines?: number;
87
+ };
88
+ declare function createDiffPreview(path: string, currentText: string, incomingText: string, options?: DiffPreviewOptions): string;
89
+
90
+ //#endregion
91
+ //#region src/encoding.d.ts
92
+ declare function toPosixPath(pathValue: string): string;
93
+ declare function encodeUtf8(value: string): Uint8Array<ArrayBuffer>;
94
+ declare function decodeUtf8(payload: ArrayBuffer | ArrayBufferView): string;
95
+ declare function toUint8Array(payload: ArrayBuffer | ArrayBufferView): Uint8Array<ArrayBufferLike>;
96
+
97
+ //#endregion
98
+ //#region src/paths.d.ts
99
+ declare function normalizeBundlePath(value: string): string;
100
+ declare function normalizePathFragment(value?: string): string | undefined;
101
+ declare function maybeStripPrefix(pathInput: string, prefix?: string): string;
102
+
103
+ //#endregion
104
+ //#region src/platform.d.ts
105
+ declare const PLATFORM_IDS: ["opencode", "codex", "claude", "cursor"];
106
+ declare function isSupportedPlatform(value: string): value is PlatformId;
107
+ declare function normalizePlatformInput(value: string): PlatformId;
108
+
109
+ //#endregion
110
+ //#region src/preset.d.ts
111
+ declare function definePreset(config: PresetConfig): PresetConfig;
112
+
113
+ //#endregion
114
+ //#region src/registry.d.ts
115
+ type FetchRegistryBundleResult = {
116
+ bundle: RegistryBundle;
117
+ etag: string | null;
118
+ };
119
+ declare function fetchRegistryIndex(baseUrl: string): Promise<RegistryIndex>;
120
+ declare function fetchRegistryBundle(baseUrl: string, bundlePath: string): Promise<FetchRegistryBundleResult>;
121
+ declare function resolveRegistryEntry(index: RegistryIndex, input: string, explicitPlatform?: PlatformId): RegistryEntry;
122
+
123
+ //#endregion
124
+ //#region src/schema.d.ts
125
+ declare const platformIdSchema: z.ZodEnum<{
126
+ opencode: "opencode";
127
+ codex: "codex";
128
+ claude: "claude";
129
+ cursor: "cursor";
130
+ }>;
131
+ declare const authorSchema: z.ZodObject<{
132
+ name: z.ZodString;
133
+ email: z.ZodOptional<z.ZodEmail>;
134
+ url: z.ZodOptional<z.ZodURL>;
135
+ }, z.core.$strict>;
136
+ declare const platformPresetSchema: z.ZodObject<{
137
+ title: z.ZodString;
138
+ version: z.ZodString;
139
+ description: z.ZodString;
140
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
141
+ author: z.ZodOptional<z.ZodObject<{
142
+ name: z.ZodString;
143
+ email: z.ZodOptional<z.ZodEmail>;
144
+ url: z.ZodOptional<z.ZodURL>;
145
+ }, z.core.$strict>>;
146
+ license: z.ZodOptional<z.ZodString>;
147
+ features: z.ZodOptional<z.ZodArray<z.ZodString>>;
148
+ installMessage: z.ZodOptional<z.ZodString>;
149
+ }, z.core.$strict>;
150
+ declare const bundledFileSchema: z.ZodObject<{
151
+ path: z.ZodString;
152
+ size: z.ZodNumber;
153
+ checksum: z.ZodString;
154
+ encoding: z.ZodUnion<readonly [z.ZodLiteral<"utf-8">, z.ZodLiteral<"base64">]>;
155
+ contents: z.ZodString;
156
+ }, z.core.$strip>;
157
+ declare const registryBundleSchema: z.ZodObject<{
158
+ slug: z.ZodString;
159
+ platform: z.ZodEnum<{
160
+ opencode: "opencode";
161
+ codex: "codex";
162
+ claude: "claude";
163
+ cursor: "cursor";
164
+ }>;
165
+ title: z.ZodString;
166
+ version: z.ZodString;
167
+ description: z.ZodString;
168
+ tags: z.ZodArray<z.ZodString>;
169
+ author: z.ZodOptional<z.ZodObject<{
170
+ name: z.ZodString;
171
+ email: z.ZodOptional<z.ZodEmail>;
172
+ url: z.ZodOptional<z.ZodURL>;
173
+ }, z.core.$strict>>;
174
+ license: z.ZodOptional<z.ZodString>;
175
+ features: z.ZodOptional<z.ZodArray<z.ZodString>>;
176
+ installMessage: z.ZodOptional<z.ZodString>;
177
+ files: z.ZodArray<z.ZodObject<{
178
+ path: z.ZodString;
179
+ size: z.ZodNumber;
180
+ checksum: z.ZodString;
181
+ encoding: z.ZodUnion<readonly [z.ZodLiteral<"utf-8">, z.ZodLiteral<"base64">]>;
182
+ contents: z.ZodString;
183
+ }, z.core.$strip>>;
184
+ }, z.core.$strip>;
185
+ declare const registryEntrySchema: z.ZodObject<{
186
+ title: z.ZodString;
187
+ version: z.ZodString;
188
+ description: z.ZodString;
189
+ tags: z.ZodArray<z.ZodString>;
190
+ author: z.ZodOptional<z.ZodObject<{
191
+ name: z.ZodString;
192
+ email: z.ZodOptional<z.ZodEmail>;
193
+ url: z.ZodOptional<z.ZodURL>;
194
+ }, z.core.$strict>>;
195
+ license: z.ZodOptional<z.ZodString>;
196
+ features: z.ZodOptional<z.ZodArray<z.ZodString>>;
197
+ installMessage: z.ZodOptional<z.ZodString>;
198
+ platform: z.ZodEnum<{
199
+ opencode: "opencode";
200
+ codex: "codex";
201
+ claude: "claude";
202
+ cursor: "cursor";
203
+ }>;
204
+ slug: z.ZodString;
205
+ name: z.ZodString;
206
+ bundlePath: z.ZodString;
207
+ fileCount: z.ZodNumber;
208
+ totalBytes: z.ZodNumber;
209
+ }, z.core.$strip>;
210
+ declare const registryIndexSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
211
+ title: z.ZodString;
212
+ version: z.ZodString;
213
+ description: z.ZodString;
214
+ tags: z.ZodArray<z.ZodString>;
215
+ author: z.ZodOptional<z.ZodObject<{
216
+ name: z.ZodString;
217
+ email: z.ZodOptional<z.ZodEmail>;
218
+ url: z.ZodOptional<z.ZodURL>;
219
+ }, z.core.$strict>>;
220
+ license: z.ZodOptional<z.ZodString>;
221
+ features: z.ZodOptional<z.ZodArray<z.ZodString>>;
222
+ installMessage: z.ZodOptional<z.ZodString>;
223
+ platform: z.ZodEnum<{
224
+ opencode: "opencode";
225
+ codex: "codex";
226
+ claude: "claude";
227
+ cursor: "cursor";
228
+ }>;
229
+ slug: z.ZodString;
230
+ name: z.ZodString;
231
+ bundlePath: z.ZodString;
232
+ fileCount: z.ZodNumber;
233
+ totalBytes: z.ZodNumber;
234
+ }, z.core.$strip>>;
235
+
236
+ //#endregion
237
+ export { AuthorInfo, BundledFile, DiffPreviewOptions, FetchRegistryBundleResult, PLATFORM_IDS, PlatformId, PlatformSpecificConfig, PresetConfig, RegistryBundle, RegistryData, RegistryEntry, RegistryIndex, RegistryIndexItem, authorSchema, bundledFileSchema, cleanInstallMessage, collectBundledFiles, createDiffPreview, decodeBundledFile, decodeUtf8, definePreset, encodeItemName, encodeUtf8, fetchRegistryBundle, fetchRegistryIndex, isAbsoluteUrl, isLikelyText, isSupportedPlatform, maybeStripPrefix, normalizeBundlePath, normalizeBundlePublicBase, normalizePathFragment, normalizePlatformInput, platformIdSchema, platformPresetSchema, registryBundleSchema, registryEntrySchema, registryIndexSchema, resolveRegistryEntry, toPosixPath, toUint8Array, toUtf8String, validatePresetConfig, verifyBundledFileChecksum };
package/dist/index.js ADDED
@@ -0,0 +1,306 @@
1
+ import { createTwoFilesPatch } from "diff";
2
+ import { z } from "zod";
3
+
4
+ //#region src/encoding.ts
5
+ function toPosixPath(pathValue) {
6
+ return pathValue.split("\\").join("/");
7
+ }
8
+ function encodeUtf8(value) {
9
+ if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(value, "utf8"));
10
+ return new TextEncoder().encode(value);
11
+ }
12
+ function decodeUtf8(payload) {
13
+ const bytes = toUint8Array(payload);
14
+ if (typeof Buffer !== "undefined") return Buffer.from(bytes).toString("utf8");
15
+ return new TextDecoder("utf-8", { fatal: false }).decode(bytes);
16
+ }
17
+ function toUint8Array(payload) {
18
+ if (payload instanceof Uint8Array) return payload;
19
+ if (ArrayBuffer.isView(payload)) return new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength);
20
+ return new Uint8Array(payload);
21
+ }
22
+
23
+ //#endregion
24
+ //#region src/build-utils.ts
25
+ function normalizeBundlePublicBase(value) {
26
+ const trimmed = value.trim();
27
+ if (!trimmed) throw new Error("--bundle-base must be a non-empty string");
28
+ if (isAbsoluteUrl(trimmed)) return trimmed.replace(/\/+$/, "");
29
+ let normalized = trimmed;
30
+ if (!normalized.startsWith("/")) normalized = `/${normalized}`;
31
+ normalized = normalized.replace(/\/+$/, "");
32
+ return normalized === "" ? "/" : normalized;
33
+ }
34
+ function isAbsoluteUrl(value) {
35
+ return /^[a-zA-Z][a-zA-Z\d+-.]*:/.test(value);
36
+ }
37
+ function cleanInstallMessage(value) {
38
+ if (typeof value !== "string") return;
39
+ const trimmed = value.trim();
40
+ return trimmed.length > 0 ? trimmed : void 0;
41
+ }
42
+ function encodeItemName(slug, platform) {
43
+ return `${slug}.${platform}`;
44
+ }
45
+ function validatePresetConfig(config, slug) {
46
+ if (!config || typeof config !== "object") throw new Error(`Invalid preset config export for ${slug}`);
47
+ const preset = config;
48
+ if (!preset.title || typeof preset.title !== "string") throw new Error(`Preset ${slug} is missing a title`);
49
+ if (!preset.version || typeof preset.version !== "string") throw new Error(`Preset ${slug} is missing a version`);
50
+ if (!preset.description || typeof preset.description !== "string") throw new Error(`Preset ${slug} is missing a description`);
51
+ if (!preset.platforms || typeof preset.platforms !== "object") throw new Error(`Preset ${slug} is missing platforms map`);
52
+ return preset;
53
+ }
54
+ function collectBundledFiles(files) {
55
+ return Object.entries(files).map(([path, contents]) => {
56
+ const normalizedPath = toPosixPath(path);
57
+ const payload = encodeUtf8(contents);
58
+ return {
59
+ path: normalizedPath,
60
+ size: payload.length,
61
+ checksum: "",
62
+ encoding: "utf-8",
63
+ contents
64
+ };
65
+ }).sort((a, b) => a.path.localeCompare(b.path));
66
+ }
67
+
68
+ //#endregion
69
+ //#region src/bundle.ts
70
+ const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
71
+ const BASE64_LOOKUP = Object.fromEntries(Array.from(BASE64_ALPHABET).map((char, index) => [char, index]));
72
+ function decodeBundledFile(file) {
73
+ if (file.encoding === "utf-8") return encodeUtf8(file.contents);
74
+ if (file.encoding === "base64") return decodeBase64(file.contents);
75
+ throw new Error(`Unsupported encoding "${file.encoding}" for ${file.path}.`);
76
+ }
77
+ async function verifyBundledFileChecksum(file, payload) {
78
+ const bytes = toUint8Array(payload);
79
+ const computed = await sha256Hex(bytes);
80
+ if (computed !== file.checksum) throw new Error(`Checksum mismatch for ${file.path}. Expected ${file.checksum}, received ${computed}.`);
81
+ }
82
+ function isLikelyText(payload) {
83
+ const bytes = toUint8Array(payload);
84
+ const sample = bytes.subarray(0, Math.min(bytes.length, 128));
85
+ for (const byte of sample) {
86
+ if (byte === 0) return false;
87
+ if (byte < 9) return false;
88
+ if (byte > 13 && byte < 32) return false;
89
+ }
90
+ return true;
91
+ }
92
+ function toUtf8String(payload) {
93
+ return decodeUtf8(payload);
94
+ }
95
+ function decodeBase64(input) {
96
+ const sanitized = input.replace(/[^A-Za-z0-9+/=]/g, "");
97
+ if (sanitized.length % 4 !== 0) throw new Error("Invalid base64 payload length.");
98
+ let outputLength = sanitized.length / 4 * 3;
99
+ if (sanitized.endsWith("==")) outputLength -= 2;
100
+ else if (sanitized.endsWith("=")) outputLength -= 1;
101
+ const bytes = new Uint8Array(outputLength);
102
+ let byteIndex = 0;
103
+ for (let i = 0; i < sanitized.length; i += 4) {
104
+ const chunk = sanitized.slice(i, i + 4);
105
+ const enc1 = decodeBase64Char(chunk[0]);
106
+ const enc2 = decodeBase64Char(chunk[1]);
107
+ const enc3 = chunk[2] === "=" ? 0 : decodeBase64Char(chunk[2]);
108
+ const enc4 = chunk[3] === "=" ? 0 : decodeBase64Char(chunk[3]);
109
+ const combined = enc1 * 262144 + enc2 * 4096 + enc3 * 64 + enc4;
110
+ bytes[byteIndex] = Math.floor(combined / 65536) % 256;
111
+ byteIndex += 1;
112
+ if (chunk[2] !== "=") {
113
+ bytes[byteIndex] = Math.floor(combined / 256) % 256;
114
+ byteIndex += 1;
115
+ }
116
+ if (chunk[3] !== "=") {
117
+ bytes[byteIndex] = combined % 256;
118
+ byteIndex += 1;
119
+ }
120
+ }
121
+ return bytes;
122
+ }
123
+ function decodeBase64Char(char) {
124
+ const value = BASE64_LOOKUP[char];
125
+ if (value === void 0) throw new Error(`Invalid base64 character "${char}".`);
126
+ return value;
127
+ }
128
+ async function sha256Hex(payload) {
129
+ const crypto = globalThis.crypto;
130
+ if (!crypto?.subtle) throw new Error("SHA-256 hashing requires Web Crypto API support.");
131
+ const digest = await crypto.subtle.digest("SHA-256", payload);
132
+ return Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
133
+ }
134
+
135
+ //#endregion
136
+ //#region src/diff.ts
137
+ const DEFAULT_CONTEXT = 2;
138
+ const DEFAULT_MAX_LINES = 40;
139
+ function createDiffPreview(path, currentText, incomingText, options = {}) {
140
+ const patch = createTwoFilesPatch(`${path} (current)`, `${path} (incoming)`, currentText, incomingText, void 0, void 0, { context: options.context ?? DEFAULT_CONTEXT });
141
+ const lines = patch.trim().split("\n");
142
+ const maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
143
+ const limited = lines.slice(0, maxLines);
144
+ if (lines.length > maxLines) limited.push("...");
145
+ return limited.join("\n");
146
+ }
147
+
148
+ //#endregion
149
+ //#region src/paths.ts
150
+ function normalizeBundlePath(value) {
151
+ return value.replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/^\/+/, "");
152
+ }
153
+ function normalizePathFragment(value) {
154
+ if (!value) return;
155
+ const normalized = value.replace(/\\/g, "/").replace(/^\/+/, "");
156
+ return normalized.replace(/\/+$/, "");
157
+ }
158
+ function maybeStripPrefix(pathInput, prefix) {
159
+ if (!prefix) return pathInput;
160
+ if (pathInput === prefix) return "";
161
+ if (pathInput.startsWith(`${prefix}/`)) return pathInput.slice(prefix.length + 1);
162
+ return pathInput;
163
+ }
164
+
165
+ //#endregion
166
+ //#region src/platform.ts
167
+ const PLATFORM_IDS = [
168
+ "opencode",
169
+ "codex",
170
+ "claude",
171
+ "cursor"
172
+ ];
173
+ function isSupportedPlatform(value) {
174
+ return PLATFORM_IDS.includes(value);
175
+ }
176
+ function normalizePlatformInput(value) {
177
+ const normalized = value.toLowerCase();
178
+ if (isSupportedPlatform(normalized)) return normalized;
179
+ throw new Error(`Unknown platform "${value}". Supported platforms: ${PLATFORM_IDS.join(", ")}.`);
180
+ }
181
+
182
+ //#endregion
183
+ //#region src/preset.ts
184
+ function definePreset(config) {
185
+ return config;
186
+ }
187
+
188
+ //#endregion
189
+ //#region src/registry.ts
190
+ async function fetchRegistryIndex(baseUrl) {
191
+ const indexUrl = new URL("registry.index.json", baseUrl);
192
+ const response = await fetch(indexUrl);
193
+ if (!response.ok) throw new Error(`Failed to load registry index (${response.status} ${response.statusText}).`);
194
+ try {
195
+ return await response.json();
196
+ } catch (error) {
197
+ throw new Error(`Unable to parse registry index JSON: ${error.message}`);
198
+ }
199
+ }
200
+ async function fetchRegistryBundle(baseUrl, bundlePath) {
201
+ const bundleUrl = new URL(bundlePath, baseUrl);
202
+ const response = await fetch(bundleUrl);
203
+ if (!response.ok) throw new Error(`Failed to download bundle (${response.status} ${response.statusText}).`);
204
+ try {
205
+ const bundle = await response.json();
206
+ return {
207
+ bundle,
208
+ etag: response.headers.get("etag")
209
+ };
210
+ } catch (error) {
211
+ throw new Error(`Unable to parse bundle JSON: ${error.message}`);
212
+ }
213
+ }
214
+ function resolveRegistryEntry(index, input, explicitPlatform) {
215
+ const map = new Map();
216
+ for (const [key, value] of Object.entries(index)) map.set(key.toLowerCase(), value);
217
+ const normalizedInput = input.toLowerCase();
218
+ const direct = map.get(normalizedInput);
219
+ if (direct) return direct;
220
+ let slugHint = normalizedInput;
221
+ let platform = explicitPlatform;
222
+ if (!platform) {
223
+ const parts = normalizedInput.split(".");
224
+ const maybePlatform = parts.at(-1);
225
+ if (maybePlatform && PLATFORM_IDS.includes(maybePlatform)) {
226
+ platform = maybePlatform;
227
+ slugHint = parts.slice(0, -1).join(".");
228
+ }
229
+ }
230
+ const matches = Object.values(index).filter((entry) => entry.slug.toLowerCase() === slugHint);
231
+ if (platform) {
232
+ const match = matches.find((entry) => entry.platform === platform);
233
+ if (match) return match;
234
+ throw new Error(`Preset "${input}" is not available for platform "${platform}".`);
235
+ }
236
+ if (matches.length === 1) return matches[0];
237
+ if (matches.length > 1) {
238
+ const platforms = matches.map((entry) => entry.platform).join(", ");
239
+ throw new Error(`Preset "${input}" is available for multiple platforms (${platforms}). Use --platform to pick one or specify <slug>.<platform>.`);
240
+ }
241
+ throw new Error(`Preset "${input}" was not found in the active registry.`);
242
+ }
243
+
244
+ //#endregion
245
+ //#region src/schema.ts
246
+ 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-]+)*)?$/;
247
+ const platformIdSchema = z.enum([
248
+ "opencode",
249
+ "codex",
250
+ "claude",
251
+ "cursor"
252
+ ]);
253
+ const authorSchema = z.object({
254
+ name: z.string().trim().min(1),
255
+ email: z.email().trim().optional(),
256
+ url: z.url().trim().optional()
257
+ }).strict();
258
+ const titleSchema = z.string().trim().min(1).max(120);
259
+ const descriptionSchema = z.string().trim().min(1).max(500);
260
+ const versionSchema = z.string().trim().regex(SEMVER_REGEX, "Version must follow semantic versioning");
261
+ const tagSchema = z.string().trim().min(1).max(48);
262
+ const tagsSchema = z.array(tagSchema).max(10);
263
+ const featureSchema = z.string().trim().min(1).max(160);
264
+ const featuresSchema = z.array(featureSchema).max(10);
265
+ const installMessageSchema = z.string().trim().max(4e3);
266
+ const licenseSchema = z.string().trim().max(80);
267
+ const platformPresetSchema = z.object({
268
+ title: titleSchema,
269
+ version: versionSchema,
270
+ description: descriptionSchema,
271
+ tags: tagsSchema.optional(),
272
+ author: authorSchema.optional(),
273
+ license: licenseSchema.optional(),
274
+ features: featuresSchema.optional(),
275
+ installMessage: installMessageSchema.optional()
276
+ }).strict();
277
+ const bundledFileSchema = z.object({
278
+ path: z.string().min(1),
279
+ size: z.number().int().nonnegative(),
280
+ checksum: z.string().length(64),
281
+ encoding: z.union([z.literal("utf-8"), z.literal("base64")]),
282
+ contents: z.string()
283
+ });
284
+ const registryBundleSchema = z.object({
285
+ slug: z.string().trim().min(1),
286
+ platform: platformIdSchema,
287
+ title: titleSchema,
288
+ version: versionSchema,
289
+ description: descriptionSchema,
290
+ tags: tagsSchema,
291
+ author: authorSchema.optional(),
292
+ license: licenseSchema.optional(),
293
+ features: featuresSchema.optional(),
294
+ installMessage: installMessageSchema.optional(),
295
+ files: z.array(bundledFileSchema).min(1)
296
+ });
297
+ const registryEntrySchema = registryBundleSchema.omit({ files: true }).extend({
298
+ name: z.string().trim().min(1),
299
+ bundlePath: z.string().trim().min(1),
300
+ fileCount: z.number().int().nonnegative(),
301
+ totalBytes: z.number().int().nonnegative()
302
+ });
303
+ const registryIndexSchema = z.record(z.string(), registryEntrySchema);
304
+
305
+ //#endregion
306
+ export { PLATFORM_IDS, authorSchema, bundledFileSchema, cleanInstallMessage, collectBundledFiles, createDiffPreview, decodeBundledFile, decodeUtf8, definePreset, encodeItemName, encodeUtf8, fetchRegistryBundle, fetchRegistryIndex, isAbsoluteUrl, isLikelyText, isSupportedPlatform, maybeStripPrefix, normalizeBundlePath, normalizeBundlePublicBase, normalizePathFragment, normalizePlatformInput, platformIdSchema, platformPresetSchema, registryBundleSchema, registryEntrySchema, registryIndexSchema, resolveRegistryEntry, toPosixPath, toUint8Array, toUtf8String, validatePresetConfig, verifyBundledFileChecksum };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@agentrules/core",
3
+ "version": "0.0.1",
4
+ "author": "Brian Cheung <bcheung.dev@gmail.com> (https://github.com/bcheung)",
5
+ "license": "MIT",
6
+ "homepage": "https://docs.agentrules.directory",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/agentrules-sh/agentrules",
10
+ "directory": "packages/core"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/agentrules-sh/agentrules/issues"
14
+ },
15
+ "keywords": [
16
+ "agentrules",
17
+ "agents",
18
+ "agentic",
19
+ "coding",
20
+ "development"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "main": "./dist/index.js",
26
+ "module": "./dist/index.js",
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js",
32
+ "default": "./dist/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "type": "module",
39
+ "sideEffects": false,
40
+ "scripts": {
41
+ "build": "tsdown",
42
+ "dev": "tsdown --watch",
43
+ "typecheck": "tsc --noEmit",
44
+ "test": "bun test"
45
+ },
46
+ "dependencies": {
47
+ "diff": "^8.0.2",
48
+ "zod": "^4.1.12"
49
+ },
50
+ "devDependencies": {
51
+ "tsdown": "^0.9.0",
52
+ "typescript": "5.7.2"
53
+ }
54
+ }