@agentrules/core 0.0.9 → 0.0.11
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 +310 -27
- package/dist/index.js +229 -34
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ declare const platformIdSchema: z.ZodEnum<{
|
|
|
9
9
|
}>;
|
|
10
10
|
declare const titleSchema: z.ZodString;
|
|
11
11
|
declare const descriptionSchema: z.ZodString;
|
|
12
|
+
declare const tagSchema: z.ZodString;
|
|
13
|
+
declare const tagsSchema: z.ZodArray<z.ZodString>;
|
|
12
14
|
declare const slugSchema: z.ZodString;
|
|
13
15
|
declare const COMMON_LICENSES: readonly ["MIT", "Apache-2.0", "GPL-3.0-only", "BSD-3-Clause", "ISC", "Unlicense"];
|
|
14
16
|
type CommonLicense = (typeof COMMON_LICENSES)[number];
|
|
@@ -19,7 +21,7 @@ declare const presetConfigSchema: z.ZodObject<{
|
|
|
19
21
|
title: z.ZodString;
|
|
20
22
|
version: z.ZodOptional<z.ZodNumber>;
|
|
21
23
|
description: z.ZodString;
|
|
22
|
-
tags: z.
|
|
24
|
+
tags: z.ZodArray<z.ZodString>;
|
|
23
25
|
features: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
24
26
|
license: z.ZodString;
|
|
25
27
|
platform: z.ZodEnum<{
|
|
@@ -40,9 +42,12 @@ declare const bundledFileSchema: z.ZodObject<{
|
|
|
40
42
|
/**
|
|
41
43
|
* Schema for what clients send to publish a preset.
|
|
42
44
|
* Version is optional major version. Registry assigns full MAJOR.MINOR.
|
|
45
|
+
*
|
|
46
|
+
* Note: Clients send `name` (e.g., "my-preset"), and the registry defines the format of the slug.
|
|
47
|
+
* For example, a namespaced slug could be returned as "username/my-preset"
|
|
43
48
|
*/
|
|
44
49
|
declare const presetPublishInputSchema: z.ZodObject<{
|
|
45
|
-
|
|
50
|
+
name: z.ZodString;
|
|
46
51
|
platform: z.ZodEnum<{
|
|
47
52
|
opencode: "opencode";
|
|
48
53
|
codex: "codex";
|
|
@@ -67,11 +72,12 @@ declare const presetPublishInputSchema: z.ZodObject<{
|
|
|
67
72
|
}, z.core.$strip>;
|
|
68
73
|
/**
|
|
69
74
|
* Schema for what registries store and return.
|
|
70
|
-
* Includes
|
|
75
|
+
* Includes full namespaced slug and version assigned by registry.
|
|
71
76
|
*/
|
|
72
77
|
declare const presetBundleSchema: z.ZodObject<{
|
|
73
78
|
title: z.ZodString;
|
|
74
79
|
description: z.ZodString;
|
|
80
|
+
tags: z.ZodArray<z.ZodString>;
|
|
75
81
|
license: z.ZodString;
|
|
76
82
|
platform: z.ZodEnum<{
|
|
77
83
|
opencode: "opencode";
|
|
@@ -79,9 +85,7 @@ declare const presetBundleSchema: z.ZodObject<{
|
|
|
79
85
|
claude: "claude";
|
|
80
86
|
cursor: "cursor";
|
|
81
87
|
}>;
|
|
82
|
-
tags: z.ZodArray<z.ZodString>;
|
|
83
88
|
features: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
84
|
-
slug: z.ZodString;
|
|
85
89
|
licenseContent: z.ZodOptional<z.ZodString>;
|
|
86
90
|
readmeContent: z.ZodOptional<z.ZodString>;
|
|
87
91
|
installMessage: z.ZodOptional<z.ZodString>;
|
|
@@ -91,11 +95,13 @@ declare const presetBundleSchema: z.ZodObject<{
|
|
|
91
95
|
checksum: z.ZodString;
|
|
92
96
|
contents: z.ZodString;
|
|
93
97
|
}, z.core.$strip>>;
|
|
98
|
+
slug: z.ZodString;
|
|
94
99
|
version: z.ZodString;
|
|
95
100
|
}, z.core.$strip>;
|
|
96
101
|
declare const presetSchema: z.ZodObject<{
|
|
97
102
|
title: z.ZodString;
|
|
98
103
|
description: z.ZodString;
|
|
104
|
+
tags: z.ZodArray<z.ZodString>;
|
|
99
105
|
license: z.ZodString;
|
|
100
106
|
platform: z.ZodEnum<{
|
|
101
107
|
opencode: "opencode";
|
|
@@ -104,7 +110,6 @@ declare const presetSchema: z.ZodObject<{
|
|
|
104
110
|
cursor: "cursor";
|
|
105
111
|
}>;
|
|
106
112
|
version: z.ZodString;
|
|
107
|
-
tags: z.ZodArray<z.ZodString>;
|
|
108
113
|
features: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
109
114
|
slug: z.ZodString;
|
|
110
115
|
name: z.ZodString;
|
|
@@ -115,6 +120,7 @@ declare const presetSchema: z.ZodObject<{
|
|
|
115
120
|
declare const presetIndexSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
116
121
|
title: z.ZodString;
|
|
117
122
|
description: z.ZodString;
|
|
123
|
+
tags: z.ZodArray<z.ZodString>;
|
|
118
124
|
license: z.ZodString;
|
|
119
125
|
platform: z.ZodEnum<{
|
|
120
126
|
opencode: "opencode";
|
|
@@ -123,7 +129,6 @@ declare const presetIndexSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
|
123
129
|
cursor: "cursor";
|
|
124
130
|
}>;
|
|
125
131
|
version: z.ZodString;
|
|
126
|
-
tags: z.ZodArray<z.ZodString>;
|
|
127
132
|
features: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
128
133
|
slug: z.ZodString;
|
|
129
134
|
name: z.ZodString;
|
|
@@ -135,29 +140,192 @@ declare const presetIndexSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
|
135
140
|
//#endregion
|
|
136
141
|
//#region src/platform/types.d.ts
|
|
137
142
|
/**
|
|
138
|
-
*
|
|
139
|
-
* Add new platforms here - types and config will follow.
|
|
143
|
+
* Platform and rule type definitions.
|
|
140
144
|
*/
|
|
141
145
|
declare const PLATFORM_ID_TUPLE: readonly ["opencode", "codex", "claude", "cursor"];
|
|
142
|
-
/** Union type of supported platform IDs
|
|
146
|
+
/** Union type of supported platform IDs */
|
|
143
147
|
type PlatformId = (typeof PLATFORM_ID_TUPLE)[number];
|
|
144
|
-
/**
|
|
145
|
-
type
|
|
146
|
-
|
|
148
|
+
/** File format for a rule type */
|
|
149
|
+
type RuleFileFormat = "markdown" | "typescript" | "mdc";
|
|
150
|
+
/** Configuration for a single rule type */
|
|
151
|
+
type RuleTypeConfig = {
|
|
152
|
+
/** Human-readable description */
|
|
153
|
+
description: string;
|
|
154
|
+
/** File format */
|
|
155
|
+
format: RuleFileFormat;
|
|
156
|
+
/** File extension (without dot) */
|
|
157
|
+
extension: string;
|
|
158
|
+
/**
|
|
159
|
+
* Install path pattern relative to project root.
|
|
160
|
+
* Use {name} as placeholder for the rule slug/filename.
|
|
161
|
+
* null if project install not supported.
|
|
162
|
+
*/
|
|
163
|
+
projectPath: string | null;
|
|
164
|
+
/**
|
|
165
|
+
* Install path pattern for global/user install.
|
|
166
|
+
* Use ~ for home directory.
|
|
167
|
+
* null if global install not supported.
|
|
168
|
+
*/
|
|
169
|
+
globalPath: string | null;
|
|
170
|
+
};
|
|
171
|
+
/** Platform configuration with all its rule types */
|
|
172
|
+
type PlatformRuleConfig = {
|
|
173
|
+
/** Human-readable platform name */
|
|
174
|
+
label: string;
|
|
175
|
+
/** Platform's project directory (e.g., ".opencode") */
|
|
147
176
|
projectDir: string;
|
|
148
|
-
/**
|
|
149
|
-
globalDir: string;
|
|
177
|
+
/** Platform's global config directory (null if not supported) */
|
|
178
|
+
globalDir: string | null;
|
|
179
|
+
/** Rule types supported by this platform */
|
|
180
|
+
types: Record<string, RuleTypeConfig>;
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* Discriminated union of valid platform + type combinations.
|
|
184
|
+
* Must be kept in sync with PLATFORMS in config.ts.
|
|
185
|
+
*/
|
|
186
|
+
type PlatformRuleType = {
|
|
187
|
+
platform: "opencode";
|
|
188
|
+
type: "instruction" | "agent" | "command" | "tool";
|
|
189
|
+
} | {
|
|
190
|
+
platform: "claude";
|
|
191
|
+
type: "instruction" | "command" | "skill";
|
|
192
|
+
} | {
|
|
193
|
+
platform: "cursor";
|
|
194
|
+
type: "rule";
|
|
195
|
+
} | {
|
|
196
|
+
platform: "codex";
|
|
197
|
+
type: "instruction" | "command";
|
|
150
198
|
};
|
|
199
|
+
/** Extract rule type for a specific platform */
|
|
200
|
+
type RuleTypeForPlatform<P extends PlatformId> = Extract<PlatformRuleType, {
|
|
201
|
+
platform: P;
|
|
202
|
+
}>["type"];
|
|
203
|
+
/** Union of all valid rule types across all platforms */
|
|
204
|
+
type RuleType = PlatformRuleType["type"];
|
|
151
205
|
|
|
152
206
|
//#endregion
|
|
153
207
|
//#region src/platform/config.d.ts
|
|
154
|
-
|
|
155
|
-
declare const PLATFORM_IDS: readonly ["opencode", "codex", "claude", "cursor"];
|
|
208
|
+
declare const PLATFORM_IDS: [PlatformId, ...PlatformId[]];
|
|
156
209
|
/**
|
|
157
|
-
* Platform
|
|
158
|
-
* Single source of truth for all platform paths.
|
|
210
|
+
* Platform configuration including supported rule types and install paths.
|
|
159
211
|
*/
|
|
160
|
-
declare const PLATFORMS:
|
|
212
|
+
declare const PLATFORMS: {
|
|
213
|
+
readonly opencode: {
|
|
214
|
+
readonly label: "OpenCode";
|
|
215
|
+
readonly projectDir: ".opencode";
|
|
216
|
+
readonly globalDir: "~/.config/opencode";
|
|
217
|
+
readonly types: {
|
|
218
|
+
readonly instruction: {
|
|
219
|
+
readonly description: "Project instructions (AGENTS.md)";
|
|
220
|
+
readonly format: "markdown";
|
|
221
|
+
readonly extension: "md";
|
|
222
|
+
readonly projectPath: "AGENTS.md";
|
|
223
|
+
readonly globalPath: "~/.config/opencode/AGENTS.md";
|
|
224
|
+
};
|
|
225
|
+
readonly agent: {
|
|
226
|
+
readonly description: "Specialized AI agent definition";
|
|
227
|
+
readonly format: "markdown";
|
|
228
|
+
readonly extension: "md";
|
|
229
|
+
readonly projectPath: ".opencode/agent/{name}.md";
|
|
230
|
+
readonly globalPath: "~/.config/opencode/agent/{name}.md";
|
|
231
|
+
};
|
|
232
|
+
readonly command: {
|
|
233
|
+
readonly description: "Custom slash command";
|
|
234
|
+
readonly format: "markdown";
|
|
235
|
+
readonly extension: "md";
|
|
236
|
+
readonly projectPath: ".opencode/command/{name}.md";
|
|
237
|
+
readonly globalPath: "~/.config/opencode/command/{name}.md";
|
|
238
|
+
};
|
|
239
|
+
readonly tool: {
|
|
240
|
+
readonly description: "Custom tool definition";
|
|
241
|
+
readonly format: "typescript";
|
|
242
|
+
readonly extension: "ts";
|
|
243
|
+
readonly projectPath: ".opencode/tool/{name}.ts";
|
|
244
|
+
readonly globalPath: "~/.config/opencode/tool/{name}.ts";
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
readonly claude: {
|
|
249
|
+
readonly label: "Claude Code";
|
|
250
|
+
readonly projectDir: ".claude";
|
|
251
|
+
readonly globalDir: "~/.claude";
|
|
252
|
+
readonly types: {
|
|
253
|
+
readonly instruction: {
|
|
254
|
+
readonly description: "Project instructions (CLAUDE.md)";
|
|
255
|
+
readonly format: "markdown";
|
|
256
|
+
readonly extension: "md";
|
|
257
|
+
readonly projectPath: "CLAUDE.md";
|
|
258
|
+
readonly globalPath: "~/.claude/CLAUDE.md";
|
|
259
|
+
};
|
|
260
|
+
readonly command: {
|
|
261
|
+
readonly description: "Custom slash command";
|
|
262
|
+
readonly format: "markdown";
|
|
263
|
+
readonly extension: "md";
|
|
264
|
+
readonly projectPath: ".claude/commands/{name}.md";
|
|
265
|
+
readonly globalPath: "~/.claude/commands/{name}.md";
|
|
266
|
+
};
|
|
267
|
+
readonly skill: {
|
|
268
|
+
readonly description: "Custom skill definition";
|
|
269
|
+
readonly format: "markdown";
|
|
270
|
+
readonly extension: "md";
|
|
271
|
+
readonly projectPath: ".claude/skills/{name}/SKILL.md";
|
|
272
|
+
readonly globalPath: "~/.claude/skills/{name}/SKILL.md";
|
|
273
|
+
};
|
|
274
|
+
};
|
|
275
|
+
};
|
|
276
|
+
readonly cursor: {
|
|
277
|
+
readonly label: "Cursor";
|
|
278
|
+
readonly projectDir: ".cursor";
|
|
279
|
+
readonly globalDir: null;
|
|
280
|
+
readonly types: {
|
|
281
|
+
readonly rule: {
|
|
282
|
+
readonly description: "Project rule (MDC format)";
|
|
283
|
+
readonly format: "mdc";
|
|
284
|
+
readonly extension: "mdc";
|
|
285
|
+
readonly projectPath: ".cursor/rules/{name}.mdc";
|
|
286
|
+
readonly globalPath: null;
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
readonly codex: {
|
|
291
|
+
readonly label: "Codex";
|
|
292
|
+
readonly projectDir: "";
|
|
293
|
+
readonly globalDir: "~/.codex";
|
|
294
|
+
readonly types: {
|
|
295
|
+
readonly instruction: {
|
|
296
|
+
readonly description: "Project instructions (AGENTS.md)";
|
|
297
|
+
readonly format: "markdown";
|
|
298
|
+
readonly extension: "md";
|
|
299
|
+
readonly projectPath: "AGENTS.md";
|
|
300
|
+
readonly globalPath: "~/.codex/AGENTS.md";
|
|
301
|
+
};
|
|
302
|
+
readonly command: {
|
|
303
|
+
readonly description: "Custom prompt (global only)";
|
|
304
|
+
readonly format: "markdown";
|
|
305
|
+
readonly extension: "md";
|
|
306
|
+
readonly projectPath: null;
|
|
307
|
+
readonly globalPath: "~/.codex/prompts/{name}.md";
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
/** Valid rule types for each platform. Must be kept in sync with PLATFORMS. */
|
|
313
|
+
declare const PLATFORM_RULE_TYPES: {
|
|
314
|
+
readonly opencode: readonly ["instruction", "agent", "command", "tool"];
|
|
315
|
+
readonly claude: readonly ["instruction", "command", "skill"];
|
|
316
|
+
readonly cursor: readonly ["rule"];
|
|
317
|
+
readonly codex: readonly ["instruction", "command"];
|
|
318
|
+
};
|
|
319
|
+
/** Get valid rule types for a specific platform */
|
|
320
|
+
declare function getValidRuleTypes(platform: PlatformId): readonly string[];
|
|
321
|
+
/** Check if a type is valid for a given platform */
|
|
322
|
+
declare function isValidRuleType(platform: PlatformId, type: string): boolean;
|
|
323
|
+
/** Get the configuration for a specific platform + type combination */
|
|
324
|
+
declare function getRuleTypeConfig(platform: PlatformId, type: string): RuleTypeConfig | undefined;
|
|
325
|
+
/** Get the install path for a rule, replacing {name} placeholder */
|
|
326
|
+
declare function getInstallPath(platform: PlatformId, type: string, name: string, location?: "project" | "global"): string | null;
|
|
327
|
+
/** Get platform configuration */
|
|
328
|
+
declare function getPlatformConfig(platform: PlatformId): PlatformRuleConfig;
|
|
161
329
|
|
|
162
330
|
//#endregion
|
|
163
331
|
//#region src/platform/utils.d.ts
|
|
@@ -200,9 +368,12 @@ type BundledFile = {
|
|
|
200
368
|
/**
|
|
201
369
|
* What clients send to publish a preset.
|
|
202
370
|
* Version is optional major version. Registry assigns full MAJOR.MINOR.
|
|
371
|
+
*
|
|
372
|
+
* Note: Clients send `name` (e.g., "my-preset"), and the registry defines the format of the slug.
|
|
373
|
+
* For example, a namespaced slug could be returned as "username/my-preset"
|
|
203
374
|
*/
|
|
204
375
|
type PresetPublishInput = {
|
|
205
|
-
|
|
376
|
+
name: string;
|
|
206
377
|
platform: PlatformId;
|
|
207
378
|
title: string;
|
|
208
379
|
description: string;
|
|
@@ -218,9 +389,11 @@ type PresetPublishInput = {
|
|
|
218
389
|
};
|
|
219
390
|
/**
|
|
220
391
|
* What registries store and return.
|
|
221
|
-
* Includes
|
|
392
|
+
* Includes full namespaced slug and version assigned by registry.
|
|
222
393
|
*/
|
|
223
|
-
type PresetBundle = Omit<PresetPublishInput, "version"> & {
|
|
394
|
+
type PresetBundle = Omit<PresetPublishInput, "name" | "version"> & {
|
|
395
|
+
/** Full namespaced slug (e.g., "username/my-preset") */
|
|
396
|
+
slug: string;
|
|
224
397
|
/** Full version in MAJOR.MINOR format (e.g., "1.3", "2.1") */
|
|
225
398
|
version: string;
|
|
226
399
|
};
|
|
@@ -244,7 +417,7 @@ type PresetFileInput = {
|
|
|
244
417
|
contents: ArrayBuffer | ArrayBufferView | string;
|
|
245
418
|
};
|
|
246
419
|
type PresetInput = {
|
|
247
|
-
|
|
420
|
+
name: string;
|
|
248
421
|
config: PresetConfig;
|
|
249
422
|
files: PresetFileInput[];
|
|
250
423
|
/** Install message from INSTALL.txt file */
|
|
@@ -259,7 +432,7 @@ type PresetInput = {
|
|
|
259
432
|
* Directory name for bundle files in static registry output.
|
|
260
433
|
* Used by `agentrules registry build` to structure output.
|
|
261
434
|
*/
|
|
262
|
-
declare const STATIC_BUNDLE_DIR = "
|
|
435
|
+
declare const STATIC_BUNDLE_DIR = "registry";
|
|
263
436
|
/**
|
|
264
437
|
* Options for building a PresetPublishInput (for CLI publish command).
|
|
265
438
|
*/
|
|
@@ -349,12 +522,20 @@ declare const PRESET_SCHEMA_URL = "https://agentrules.directory/schema/agentrule
|
|
|
349
522
|
declare const LATEST_VERSION = "latest";
|
|
350
523
|
/**
|
|
351
524
|
* API endpoint paths (relative to registry base URL).
|
|
525
|
+
*
|
|
526
|
+
* Note: Path parameters (slug, platform, version) are NOT URI-encoded.
|
|
527
|
+
* - Slugs may contain slashes (e.g., "username/my-preset") which should flow
|
|
528
|
+
* through as path segments for static registry compatibility
|
|
529
|
+
* - Platform and version are constrained values (enums, validated formats)
|
|
530
|
+
* that only contain URL-safe characters
|
|
531
|
+
*
|
|
532
|
+
* The client is responsible for validating these values before making requests.
|
|
352
533
|
*/
|
|
353
534
|
declare const API_ENDPOINTS: {
|
|
354
535
|
/** Preset endpoints */
|
|
355
536
|
readonly presets: {
|
|
356
537
|
/** Base path for preset operations */
|
|
357
|
-
readonly base: "api/
|
|
538
|
+
readonly base: "api/preset";
|
|
358
539
|
/** Get preset by slug, platform, and version (defaults to "latest") */
|
|
359
540
|
readonly get: (slug: string, platform: string, version?: string) => string;
|
|
360
541
|
/** Unpublish preset version */
|
|
@@ -369,10 +550,112 @@ declare const API_ENDPOINTS: {
|
|
|
369
550
|
/** Device token exchange */
|
|
370
551
|
readonly deviceToken: "api/auth/device/token";
|
|
371
552
|
};
|
|
553
|
+
/** Rule endpoints */
|
|
554
|
+
readonly rule: {
|
|
555
|
+
/** Base path for rule operations */
|
|
556
|
+
readonly base: "api/rule";
|
|
557
|
+
/** Get or update rule by slug */
|
|
558
|
+
readonly get: (slug: string) => string;
|
|
559
|
+
};
|
|
372
560
|
};
|
|
373
561
|
|
|
562
|
+
//#endregion
|
|
563
|
+
//#region src/rule/schema.d.ts
|
|
564
|
+
/**
|
|
565
|
+
* Schema for the rule name.
|
|
566
|
+
* This is what users provide when creating a rule.
|
|
567
|
+
*/
|
|
568
|
+
declare const ruleNameSchema: z.ZodString;
|
|
569
|
+
declare const ruleTitleSchema: z.ZodString;
|
|
570
|
+
declare const ruleDescriptionSchema: z.ZodString;
|
|
571
|
+
declare const rulePlatformSchema: z.ZodEnum<{
|
|
572
|
+
opencode: "opencode";
|
|
573
|
+
codex: "codex";
|
|
574
|
+
claude: "claude";
|
|
575
|
+
cursor: "cursor";
|
|
576
|
+
}>;
|
|
577
|
+
declare const ruleTypeSchema: z.ZodString;
|
|
578
|
+
declare const ruleContentSchema: z.ZodString;
|
|
579
|
+
declare const ruleTagSchema: z.ZodString;
|
|
580
|
+
declare const ruleTagsSchema: z.ZodArray<z.ZodString>;
|
|
581
|
+
/**
|
|
582
|
+
* Discriminated union schema for platform + type combinations.
|
|
583
|
+
* Each platform has its own set of valid types.
|
|
584
|
+
*/
|
|
585
|
+
declare const rulePlatformTypeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
586
|
+
platform: z.ZodLiteral<"opencode">;
|
|
587
|
+
type: z.ZodEnum<{
|
|
588
|
+
instruction: "instruction";
|
|
589
|
+
agent: "agent";
|
|
590
|
+
command: "command";
|
|
591
|
+
tool: "tool";
|
|
592
|
+
}>;
|
|
593
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
594
|
+
platform: z.ZodLiteral<"claude">;
|
|
595
|
+
type: z.ZodEnum<{
|
|
596
|
+
instruction: "instruction";
|
|
597
|
+
command: "command";
|
|
598
|
+
skill: "skill";
|
|
599
|
+
}>;
|
|
600
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
601
|
+
platform: z.ZodLiteral<"cursor">;
|
|
602
|
+
type: z.ZodEnum<{
|
|
603
|
+
rule: "rule";
|
|
604
|
+
}>;
|
|
605
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
606
|
+
platform: z.ZodLiteral<"codex">;
|
|
607
|
+
type: z.ZodEnum<{
|
|
608
|
+
instruction: "instruction";
|
|
609
|
+
command: "command";
|
|
610
|
+
}>;
|
|
611
|
+
}, z.core.$strip>], "platform">;
|
|
612
|
+
/** Schema for rule creation with discriminated union for platform+type */
|
|
613
|
+
declare const ruleCreateInputSchema: z.ZodIntersection<z.ZodObject<{
|
|
614
|
+
name: z.ZodString;
|
|
615
|
+
title: z.ZodString;
|
|
616
|
+
description: z.ZodOptional<z.ZodString>;
|
|
617
|
+
content: z.ZodString;
|
|
618
|
+
tags: z.ZodArray<z.ZodString>;
|
|
619
|
+
}, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
620
|
+
platform: z.ZodLiteral<"opencode">;
|
|
621
|
+
type: z.ZodEnum<{
|
|
622
|
+
instruction: "instruction";
|
|
623
|
+
agent: "agent";
|
|
624
|
+
command: "command";
|
|
625
|
+
tool: "tool";
|
|
626
|
+
}>;
|
|
627
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
628
|
+
platform: z.ZodLiteral<"claude">;
|
|
629
|
+
type: z.ZodEnum<{
|
|
630
|
+
instruction: "instruction";
|
|
631
|
+
command: "command";
|
|
632
|
+
skill: "skill";
|
|
633
|
+
}>;
|
|
634
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
635
|
+
platform: z.ZodLiteral<"cursor">;
|
|
636
|
+
type: z.ZodEnum<{
|
|
637
|
+
rule: "rule";
|
|
638
|
+
}>;
|
|
639
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
640
|
+
platform: z.ZodLiteral<"codex">;
|
|
641
|
+
type: z.ZodEnum<{
|
|
642
|
+
instruction: "instruction";
|
|
643
|
+
command: "command";
|
|
644
|
+
}>;
|
|
645
|
+
}, z.core.$strip>], "platform">>;
|
|
646
|
+
declare const ruleUpdateInputSchema: z.ZodObject<{
|
|
647
|
+
name: z.ZodString;
|
|
648
|
+
title: z.ZodOptional<z.ZodString>;
|
|
649
|
+
description: z.ZodOptional<z.ZodString>;
|
|
650
|
+
content: z.ZodOptional<z.ZodString>;
|
|
651
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
652
|
+
}, z.core.$strip>;
|
|
653
|
+
type RuleCreateInput = z.infer<typeof ruleCreateInputSchema>;
|
|
654
|
+
type RuleUpdateInput = z.infer<typeof ruleUpdateInputSchema>;
|
|
655
|
+
|
|
374
656
|
//#endregion
|
|
375
657
|
//#region src/utils/diff.d.ts
|
|
658
|
+
/** Re-export platform-rule types for convenience */
|
|
376
659
|
type DiffPreviewOptions = {
|
|
377
660
|
context?: number;
|
|
378
661
|
maxLines?: number;
|
|
@@ -395,4 +678,4 @@ declare function toUint8Array(payload: ArrayBuffer | ArrayBufferView): Uint8Arra
|
|
|
395
678
|
declare function normalizeBundlePath(value: string): string;
|
|
396
679
|
|
|
397
680
|
//#endregion
|
|
398
|
-
export { AGENT_RULES_DIR, API_ENDPOINTS, BuildPresetPublishInputOptions, BuildPresetRegistryOptions, BuildPresetRegistryResult, BundledFile, COMMON_LICENSES, CommonLicense, DiffPreviewOptions, LATEST_VERSION, PLATFORMS, PLATFORM_IDS, PLATFORM_ID_TUPLE, PRESET_CONFIG_FILENAME, PRESET_SCHEMA_URL,
|
|
681
|
+
export { AGENT_RULES_DIR, API_ENDPOINTS, BuildPresetPublishInputOptions, BuildPresetRegistryOptions, BuildPresetRegistryResult, BundledFile, COMMON_LICENSES, CommonLicense, DiffPreviewOptions, LATEST_VERSION, PLATFORMS, PLATFORM_IDS, PLATFORM_ID_TUPLE, PLATFORM_RULE_TYPES, PRESET_CONFIG_FILENAME, PRESET_SCHEMA_URL, PlatformId, PlatformRuleConfig, PlatformRuleType, Preset, PresetBundle, PresetConfig, PresetFileInput, PresetIndex, PresetInput, PresetPublishInput, ResolvedPreset, RuleCreateInput, RuleFileFormat, RuleType, RuleTypeConfig, RuleTypeForPlatform, RuleUpdateInput, STATIC_BUNDLE_DIR, buildPresetPublishInput, buildPresetRegistry, bundledFileSchema, cleanInstallMessage, createDiffPreview, decodeBundledFile, decodeUtf8, descriptionSchema, encodeItemName, encodeUtf8, fetchBundle, getInstallPath, getPlatformConfig, getPlatformFromDir, getRuleTypeConfig, getValidRuleTypes, isLikelyText, isPlatformDir, isSupportedPlatform, isValidRuleType, licenseSchema, normalizeBundlePath, normalizePlatformInput, platformIdSchema, presetBundleSchema, presetConfigSchema, presetIndexSchema, presetPublishInputSchema, presetSchema, resolvePreset, ruleContentSchema, ruleCreateInputSchema, ruleDescriptionSchema, ruleNameSchema, rulePlatformSchema, rulePlatformTypeSchema, ruleTagSchema, ruleTagsSchema, ruleTitleSchema, ruleTypeSchema, ruleUpdateInputSchema, slugSchema, tagSchema, tagsSchema, titleSchema, toPosixPath, toUint8Array, toUtf8String, validatePresetConfig, verifyBundledFileChecksum };
|
package/dist/index.js
CHANGED
|
@@ -17,25 +17,36 @@ const API_PATH = "api";
|
|
|
17
17
|
const LATEST_VERSION = "latest";
|
|
18
18
|
/**
|
|
19
19
|
* API endpoint paths (relative to registry base URL).
|
|
20
|
+
*
|
|
21
|
+
* Note: Path parameters (slug, platform, version) are NOT URI-encoded.
|
|
22
|
+
* - Slugs may contain slashes (e.g., "username/my-preset") which should flow
|
|
23
|
+
* through as path segments for static registry compatibility
|
|
24
|
+
* - Platform and version are constrained values (enums, validated formats)
|
|
25
|
+
* that only contain URL-safe characters
|
|
26
|
+
*
|
|
27
|
+
* The client is responsible for validating these values before making requests.
|
|
20
28
|
*/
|
|
21
29
|
const API_ENDPOINTS = {
|
|
22
30
|
presets: {
|
|
23
|
-
base: `${API_PATH}/
|
|
24
|
-
get: (slug, platform, version = LATEST_VERSION) => `${API_PATH}/
|
|
25
|
-
unpublish: (slug, platform, version) => `${API_PATH}/
|
|
31
|
+
base: `${API_PATH}/preset`,
|
|
32
|
+
get: (slug, platform, version = LATEST_VERSION) => `${API_PATH}/preset/${slug}/${platform}/${version}`,
|
|
33
|
+
unpublish: (slug, platform, version) => `${API_PATH}/preset/${slug}/${platform}/${version}`
|
|
26
34
|
},
|
|
27
35
|
auth: {
|
|
28
36
|
session: `${API_PATH}/auth/get-session`,
|
|
29
37
|
deviceCode: `${API_PATH}/auth/device/code`,
|
|
30
38
|
deviceToken: `${API_PATH}/auth/device/token`
|
|
39
|
+
},
|
|
40
|
+
rule: {
|
|
41
|
+
base: `${API_PATH}/rule`,
|
|
42
|
+
get: (slug) => `${API_PATH}/rule/${slug}`
|
|
31
43
|
}
|
|
32
44
|
};
|
|
33
45
|
|
|
34
46
|
//#endregion
|
|
35
47
|
//#region src/platform/types.ts
|
|
36
48
|
/**
|
|
37
|
-
*
|
|
38
|
-
* Add new platforms here - types and config will follow.
|
|
49
|
+
* Platform and rule type definitions.
|
|
39
50
|
*/
|
|
40
51
|
const PLATFORM_ID_TUPLE = [
|
|
41
52
|
"opencode",
|
|
@@ -46,30 +57,149 @@ const PLATFORM_ID_TUPLE = [
|
|
|
46
57
|
|
|
47
58
|
//#endregion
|
|
48
59
|
//#region src/platform/config.ts
|
|
49
|
-
/** List of supported platform IDs as a readonly tuple */
|
|
50
60
|
const PLATFORM_IDS = PLATFORM_ID_TUPLE;
|
|
51
61
|
/**
|
|
52
|
-
* Platform
|
|
53
|
-
* Single source of truth for all platform paths.
|
|
62
|
+
* Platform configuration including supported rule types and install paths.
|
|
54
63
|
*/
|
|
55
64
|
const PLATFORMS = {
|
|
56
65
|
opencode: {
|
|
66
|
+
label: "OpenCode",
|
|
57
67
|
projectDir: ".opencode",
|
|
58
|
-
globalDir: "~/.config/opencode"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
globalDir: "~/.config/opencode",
|
|
69
|
+
types: {
|
|
70
|
+
instruction: {
|
|
71
|
+
description: "Project instructions (AGENTS.md)",
|
|
72
|
+
format: "markdown",
|
|
73
|
+
extension: "md",
|
|
74
|
+
projectPath: "AGENTS.md",
|
|
75
|
+
globalPath: "~/.config/opencode/AGENTS.md"
|
|
76
|
+
},
|
|
77
|
+
agent: {
|
|
78
|
+
description: "Specialized AI agent definition",
|
|
79
|
+
format: "markdown",
|
|
80
|
+
extension: "md",
|
|
81
|
+
projectPath: ".opencode/agent/{name}.md",
|
|
82
|
+
globalPath: "~/.config/opencode/agent/{name}.md"
|
|
83
|
+
},
|
|
84
|
+
command: {
|
|
85
|
+
description: "Custom slash command",
|
|
86
|
+
format: "markdown",
|
|
87
|
+
extension: "md",
|
|
88
|
+
projectPath: ".opencode/command/{name}.md",
|
|
89
|
+
globalPath: "~/.config/opencode/command/{name}.md"
|
|
90
|
+
},
|
|
91
|
+
tool: {
|
|
92
|
+
description: "Custom tool definition",
|
|
93
|
+
format: "typescript",
|
|
94
|
+
extension: "ts",
|
|
95
|
+
projectPath: ".opencode/tool/{name}.ts",
|
|
96
|
+
globalPath: "~/.config/opencode/tool/{name}.ts"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
63
99
|
},
|
|
64
100
|
claude: {
|
|
101
|
+
label: "Claude Code",
|
|
65
102
|
projectDir: ".claude",
|
|
66
|
-
globalDir: "~/.claude"
|
|
103
|
+
globalDir: "~/.claude",
|
|
104
|
+
types: {
|
|
105
|
+
instruction: {
|
|
106
|
+
description: "Project instructions (CLAUDE.md)",
|
|
107
|
+
format: "markdown",
|
|
108
|
+
extension: "md",
|
|
109
|
+
projectPath: "CLAUDE.md",
|
|
110
|
+
globalPath: "~/.claude/CLAUDE.md"
|
|
111
|
+
},
|
|
112
|
+
command: {
|
|
113
|
+
description: "Custom slash command",
|
|
114
|
+
format: "markdown",
|
|
115
|
+
extension: "md",
|
|
116
|
+
projectPath: ".claude/commands/{name}.md",
|
|
117
|
+
globalPath: "~/.claude/commands/{name}.md"
|
|
118
|
+
},
|
|
119
|
+
skill: {
|
|
120
|
+
description: "Custom skill definition",
|
|
121
|
+
format: "markdown",
|
|
122
|
+
extension: "md",
|
|
123
|
+
projectPath: ".claude/skills/{name}/SKILL.md",
|
|
124
|
+
globalPath: "~/.claude/skills/{name}/SKILL.md"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
67
127
|
},
|
|
68
128
|
cursor: {
|
|
129
|
+
label: "Cursor",
|
|
69
130
|
projectDir: ".cursor",
|
|
70
|
-
globalDir:
|
|
131
|
+
globalDir: null,
|
|
132
|
+
types: { rule: {
|
|
133
|
+
description: "Project rule (MDC format)",
|
|
134
|
+
format: "mdc",
|
|
135
|
+
extension: "mdc",
|
|
136
|
+
projectPath: ".cursor/rules/{name}.mdc",
|
|
137
|
+
globalPath: null
|
|
138
|
+
} }
|
|
139
|
+
},
|
|
140
|
+
codex: {
|
|
141
|
+
label: "Codex",
|
|
142
|
+
projectDir: "",
|
|
143
|
+
globalDir: "~/.codex",
|
|
144
|
+
types: {
|
|
145
|
+
instruction: {
|
|
146
|
+
description: "Project instructions (AGENTS.md)",
|
|
147
|
+
format: "markdown",
|
|
148
|
+
extension: "md",
|
|
149
|
+
projectPath: "AGENTS.md",
|
|
150
|
+
globalPath: "~/.codex/AGENTS.md"
|
|
151
|
+
},
|
|
152
|
+
command: {
|
|
153
|
+
description: "Custom prompt (global only)",
|
|
154
|
+
format: "markdown",
|
|
155
|
+
extension: "md",
|
|
156
|
+
projectPath: null,
|
|
157
|
+
globalPath: "~/.codex/prompts/{name}.md"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
71
160
|
}
|
|
72
161
|
};
|
|
162
|
+
/** Valid rule types for each platform. Must be kept in sync with PLATFORMS. */
|
|
163
|
+
const PLATFORM_RULE_TYPES = {
|
|
164
|
+
opencode: [
|
|
165
|
+
"instruction",
|
|
166
|
+
"agent",
|
|
167
|
+
"command",
|
|
168
|
+
"tool"
|
|
169
|
+
],
|
|
170
|
+
claude: [
|
|
171
|
+
"instruction",
|
|
172
|
+
"command",
|
|
173
|
+
"skill"
|
|
174
|
+
],
|
|
175
|
+
cursor: ["rule"],
|
|
176
|
+
codex: ["instruction", "command"]
|
|
177
|
+
};
|
|
178
|
+
/** Get valid rule types for a specific platform */
|
|
179
|
+
function getValidRuleTypes(platform) {
|
|
180
|
+
return PLATFORM_RULE_TYPES[platform];
|
|
181
|
+
}
|
|
182
|
+
/** Check if a type is valid for a given platform */
|
|
183
|
+
function isValidRuleType(platform, type) {
|
|
184
|
+
return PLATFORM_RULE_TYPES[platform].includes(type);
|
|
185
|
+
}
|
|
186
|
+
/** Get the configuration for a specific platform + type combination */
|
|
187
|
+
function getRuleTypeConfig(platform, type) {
|
|
188
|
+
const platformConfig = PLATFORMS[platform];
|
|
189
|
+
return platformConfig.types[type];
|
|
190
|
+
}
|
|
191
|
+
/** Get the install path for a rule, replacing {name} placeholder */
|
|
192
|
+
function getInstallPath(platform, type, name, location = "project") {
|
|
193
|
+
const config = getRuleTypeConfig(platform, type);
|
|
194
|
+
if (!config) return null;
|
|
195
|
+
const pathTemplate = location === "project" ? config.projectPath : config.globalPath;
|
|
196
|
+
if (!pathTemplate) return null;
|
|
197
|
+
return pathTemplate.replace("{name}", name);
|
|
198
|
+
}
|
|
199
|
+
/** Get platform configuration */
|
|
200
|
+
function getPlatformConfig(platform) {
|
|
201
|
+
return PLATFORMS[platform];
|
|
202
|
+
}
|
|
73
203
|
|
|
74
204
|
//#endregion
|
|
75
205
|
//#region src/platform/utils.ts
|
|
@@ -154,7 +284,7 @@ const presetConfigSchema = z.object({
|
|
|
154
284
|
title: titleSchema,
|
|
155
285
|
version: majorVersionSchema.optional(),
|
|
156
286
|
description: descriptionSchema,
|
|
157
|
-
tags: tagsSchema
|
|
287
|
+
tags: tagsSchema,
|
|
158
288
|
features: featuresSchema.optional(),
|
|
159
289
|
license: licenseSchema,
|
|
160
290
|
platform: platformIdSchema,
|
|
@@ -170,9 +300,12 @@ const bundledFileSchema = z.object({
|
|
|
170
300
|
/**
|
|
171
301
|
* Schema for what clients send to publish a preset.
|
|
172
302
|
* Version is optional major version. Registry assigns full MAJOR.MINOR.
|
|
303
|
+
*
|
|
304
|
+
* Note: Clients send `name` (e.g., "my-preset"), and the registry defines the format of the slug.
|
|
305
|
+
* For example, a namespaced slug could be returned as "username/my-preset"
|
|
173
306
|
*/
|
|
174
307
|
const presetPublishInputSchema = z.object({
|
|
175
|
-
|
|
308
|
+
name: slugSchema,
|
|
176
309
|
platform: platformIdSchema,
|
|
177
310
|
title: titleSchema,
|
|
178
311
|
description: descriptionSchema,
|
|
@@ -187,9 +320,15 @@ const presetPublishInputSchema = z.object({
|
|
|
187
320
|
});
|
|
188
321
|
/**
|
|
189
322
|
* Schema for what registries store and return.
|
|
190
|
-
* Includes
|
|
323
|
+
* Includes full namespaced slug and version assigned by registry.
|
|
191
324
|
*/
|
|
192
|
-
const presetBundleSchema = presetPublishInputSchema.omit({
|
|
325
|
+
const presetBundleSchema = presetPublishInputSchema.omit({
|
|
326
|
+
name: true,
|
|
327
|
+
version: true
|
|
328
|
+
}).extend({
|
|
329
|
+
slug: z.string().trim().min(1),
|
|
330
|
+
version: versionSchema
|
|
331
|
+
});
|
|
193
332
|
const presetSchema = presetBundleSchema.omit({
|
|
194
333
|
files: true,
|
|
195
334
|
readmeContent: true,
|
|
@@ -235,7 +374,7 @@ const NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
|
235
374
|
* Directory name for bundle files in static registry output.
|
|
236
375
|
* Used by `agentrules registry build` to structure output.
|
|
237
376
|
*/
|
|
238
|
-
const STATIC_BUNDLE_DIR = "
|
|
377
|
+
const STATIC_BUNDLE_DIR = "registry";
|
|
239
378
|
/**
|
|
240
379
|
* Compute SHA-256 hash using Web Crypto API (works in browser and Node.js 15+)
|
|
241
380
|
*/
|
|
@@ -250,11 +389,11 @@ async function sha256(data) {
|
|
|
250
389
|
*/
|
|
251
390
|
async function buildPresetPublishInput(options) {
|
|
252
391
|
const { preset: presetInput, version } = options;
|
|
253
|
-
if (!NAME_PATTERN.test(presetInput.
|
|
254
|
-
const presetConfig = validatePresetConfig(presetInput.config, presetInput.
|
|
392
|
+
if (!NAME_PATTERN.test(presetInput.name)) throw new Error(`Invalid name "${presetInput.name}". Names must be lowercase kebab-case.`);
|
|
393
|
+
const presetConfig = validatePresetConfig(presetInput.config, presetInput.name);
|
|
255
394
|
const platform = presetConfig.platform;
|
|
256
|
-
ensureKnownPlatform(platform, presetInput.
|
|
257
|
-
if (presetInput.files.length === 0) throw new Error(`Preset ${presetInput.
|
|
395
|
+
ensureKnownPlatform(platform, presetInput.name);
|
|
396
|
+
if (presetInput.files.length === 0) throw new Error(`Preset ${presetInput.name} does not include any files.`);
|
|
258
397
|
const files = await createBundledFilesFromInputs(presetInput.files);
|
|
259
398
|
const installMessage = cleanInstallMessage(presetInput.installMessage);
|
|
260
399
|
const features = presetConfig.features ?? [];
|
|
@@ -262,7 +401,7 @@ async function buildPresetPublishInput(options) {
|
|
|
262
401
|
const licenseContent = presetInput.licenseContent?.trim() || void 0;
|
|
263
402
|
const majorVersion = version ?? presetConfig.version;
|
|
264
403
|
return {
|
|
265
|
-
|
|
404
|
+
name: presetInput.name,
|
|
266
405
|
platform,
|
|
267
406
|
title: presetConfig.title,
|
|
268
407
|
description: presetConfig.description,
|
|
@@ -286,11 +425,11 @@ async function buildPresetRegistry(options) {
|
|
|
286
425
|
const entries = [];
|
|
287
426
|
const bundles = [];
|
|
288
427
|
for (const presetInput of options.presets) {
|
|
289
|
-
if (!NAME_PATTERN.test(presetInput.
|
|
290
|
-
const presetConfig = validatePresetConfig(presetInput.config, presetInput.
|
|
428
|
+
if (!NAME_PATTERN.test(presetInput.name)) throw new Error(`Invalid name "${presetInput.name}". Names must be lowercase kebab-case.`);
|
|
429
|
+
const presetConfig = validatePresetConfig(presetInput.config, presetInput.name);
|
|
291
430
|
const platform = presetConfig.platform;
|
|
292
|
-
ensureKnownPlatform(platform, presetInput.
|
|
293
|
-
if (presetInput.files.length === 0) throw new Error(`Preset ${presetInput.
|
|
431
|
+
ensureKnownPlatform(platform, presetInput.name);
|
|
432
|
+
if (presetInput.files.length === 0) throw new Error(`Preset ${presetInput.name} does not include any files.`);
|
|
294
433
|
const files = await createBundledFilesFromInputs(presetInput.files);
|
|
295
434
|
const totalSize = files.reduce((sum, file) => sum + file.size, 0);
|
|
296
435
|
const installMessage = cleanInstallMessage(presetInput.installMessage);
|
|
@@ -299,9 +438,10 @@ async function buildPresetRegistry(options) {
|
|
|
299
438
|
const licenseContent = presetInput.licenseContent?.trim() || void 0;
|
|
300
439
|
const majorVersion = presetConfig.version ?? 1;
|
|
301
440
|
const version = `${majorVersion}.0`;
|
|
441
|
+
const slug = presetInput.name;
|
|
302
442
|
const entry = {
|
|
303
|
-
name: encodeItemName(
|
|
304
|
-
slug
|
|
443
|
+
name: encodeItemName(slug, platform),
|
|
444
|
+
slug,
|
|
305
445
|
platform,
|
|
306
446
|
title: presetConfig.title,
|
|
307
447
|
version,
|
|
@@ -309,13 +449,13 @@ async function buildPresetRegistry(options) {
|
|
|
309
449
|
tags: presetConfig.tags ?? [],
|
|
310
450
|
license: presetConfig.license,
|
|
311
451
|
features,
|
|
312
|
-
bundleUrl: getBundlePath(bundleBase,
|
|
452
|
+
bundleUrl: getBundlePath(bundleBase, slug, platform, version),
|
|
313
453
|
fileCount: files.length,
|
|
314
454
|
totalSize
|
|
315
455
|
};
|
|
316
456
|
entries.push(entry);
|
|
317
457
|
const bundle = {
|
|
318
|
-
slug
|
|
458
|
+
slug,
|
|
319
459
|
platform,
|
|
320
460
|
title: presetConfig.title,
|
|
321
461
|
version,
|
|
@@ -471,6 +611,61 @@ async function fetchBundle(bundleUrl) {
|
|
|
471
611
|
}
|
|
472
612
|
}
|
|
473
613
|
|
|
614
|
+
//#endregion
|
|
615
|
+
//#region src/rule/schema.ts
|
|
616
|
+
const NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
617
|
+
/**
|
|
618
|
+
* Schema for the rule name.
|
|
619
|
+
* This is what users provide when creating a rule.
|
|
620
|
+
*/
|
|
621
|
+
const ruleNameSchema = z.string().trim().min(1, "Name is required").max(64, "Name must be 64 characters or less").regex(NAME_REGEX, "Must be lowercase alphanumeric with hyphens");
|
|
622
|
+
const ruleTitleSchema = z.string().trim().min(1, "Title is required").max(80, "Title must be 80 characters or less");
|
|
623
|
+
const ruleDescriptionSchema = z.string().trim().max(500, "Description must be 500 characters or less");
|
|
624
|
+
const rulePlatformSchema = z.enum(PLATFORM_IDS);
|
|
625
|
+
const ruleTypeSchema = z.string().trim().min(1).max(32);
|
|
626
|
+
const ruleContentSchema = z.string().min(1, "Content is required").max(1e5, "Content must be 100KB or less");
|
|
627
|
+
const ruleTagSchema = z.string().trim().min(1).max(32).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Tags must be lowercase alphanumeric with single hyphens between words");
|
|
628
|
+
const ruleTagsSchema = z.array(ruleTagSchema).min(1, "At least 1 tag is required").max(10, "Maximum 10 tags allowed");
|
|
629
|
+
/** Common fields shared across all platform-type combinations */
|
|
630
|
+
const ruleCommonFields = {
|
|
631
|
+
name: ruleNameSchema,
|
|
632
|
+
title: ruleTitleSchema,
|
|
633
|
+
description: ruleDescriptionSchema.optional(),
|
|
634
|
+
content: ruleContentSchema,
|
|
635
|
+
tags: ruleTagsSchema
|
|
636
|
+
};
|
|
637
|
+
/**
|
|
638
|
+
* Discriminated union schema for platform + type combinations.
|
|
639
|
+
* Each platform has its own set of valid types.
|
|
640
|
+
*/
|
|
641
|
+
const rulePlatformTypeSchema = z.discriminatedUnion("platform", [
|
|
642
|
+
z.object({
|
|
643
|
+
platform: z.literal("opencode"),
|
|
644
|
+
type: z.enum(PLATFORM_RULE_TYPES.opencode)
|
|
645
|
+
}),
|
|
646
|
+
z.object({
|
|
647
|
+
platform: z.literal("claude"),
|
|
648
|
+
type: z.enum(PLATFORM_RULE_TYPES.claude)
|
|
649
|
+
}),
|
|
650
|
+
z.object({
|
|
651
|
+
platform: z.literal("cursor"),
|
|
652
|
+
type: z.enum(PLATFORM_RULE_TYPES.cursor)
|
|
653
|
+
}),
|
|
654
|
+
z.object({
|
|
655
|
+
platform: z.literal("codex"),
|
|
656
|
+
type: z.enum(PLATFORM_RULE_TYPES.codex)
|
|
657
|
+
})
|
|
658
|
+
]);
|
|
659
|
+
/** Schema for rule creation with discriminated union for platform+type */
|
|
660
|
+
const ruleCreateInputSchema = z.object(ruleCommonFields).and(rulePlatformTypeSchema);
|
|
661
|
+
const ruleUpdateInputSchema = z.object({
|
|
662
|
+
name: ruleNameSchema,
|
|
663
|
+
title: ruleTitleSchema.optional(),
|
|
664
|
+
description: ruleDescriptionSchema.optional(),
|
|
665
|
+
content: ruleContentSchema.optional(),
|
|
666
|
+
tags: ruleTagsSchema.optional()
|
|
667
|
+
});
|
|
668
|
+
|
|
474
669
|
//#endregion
|
|
475
670
|
//#region src/utils/diff.ts
|
|
476
671
|
const DEFAULT_CONTEXT = 2;
|
|
@@ -495,4 +690,4 @@ function normalizeBundlePath(value) {
|
|
|
495
690
|
}
|
|
496
691
|
|
|
497
692
|
//#endregion
|
|
498
|
-
export { AGENT_RULES_DIR, API_ENDPOINTS, COMMON_LICENSES, LATEST_VERSION, PLATFORMS, PLATFORM_IDS, PLATFORM_ID_TUPLE, PRESET_CONFIG_FILENAME, PRESET_SCHEMA_URL, STATIC_BUNDLE_DIR, buildPresetPublishInput, buildPresetRegistry, bundledFileSchema, cleanInstallMessage, createDiffPreview, decodeBundledFile, decodeUtf8, descriptionSchema, encodeItemName, encodeUtf8, fetchBundle, getPlatformFromDir, isLikelyText, isPlatformDir, isSupportedPlatform, licenseSchema, normalizeBundlePath, normalizePlatformInput, platformIdSchema, presetBundleSchema, presetConfigSchema, presetIndexSchema, presetPublishInputSchema, presetSchema, resolvePreset, slugSchema, titleSchema, toPosixPath, toUint8Array, toUtf8String, validatePresetConfig, verifyBundledFileChecksum };
|
|
693
|
+
export { AGENT_RULES_DIR, API_ENDPOINTS, COMMON_LICENSES, LATEST_VERSION, PLATFORMS, PLATFORM_IDS, PLATFORM_ID_TUPLE, PLATFORM_RULE_TYPES, PRESET_CONFIG_FILENAME, PRESET_SCHEMA_URL, STATIC_BUNDLE_DIR, buildPresetPublishInput, buildPresetRegistry, bundledFileSchema, cleanInstallMessage, createDiffPreview, decodeBundledFile, decodeUtf8, descriptionSchema, encodeItemName, encodeUtf8, fetchBundle, getInstallPath, getPlatformConfig, getPlatformFromDir, getRuleTypeConfig, getValidRuleTypes, isLikelyText, isPlatformDir, isSupportedPlatform, isValidRuleType, licenseSchema, normalizeBundlePath, normalizePlatformInput, platformIdSchema, presetBundleSchema, presetConfigSchema, presetIndexSchema, presetPublishInputSchema, presetSchema, resolvePreset, ruleContentSchema, ruleCreateInputSchema, ruleDescriptionSchema, ruleNameSchema, rulePlatformSchema, rulePlatformTypeSchema, ruleTagSchema, ruleTagsSchema, ruleTitleSchema, ruleTypeSchema, ruleUpdateInputSchema, slugSchema, tagSchema, tagsSchema, titleSchema, toPosixPath, toUint8Array, toUtf8String, validatePresetConfig, verifyBundledFileChecksum };
|