77 * This allows OpenCode to discover and use the agents.
88 */
99
10- import { copyFileSync , existsSync , mkdirSync , readdirSync , statSync } from "node:fs"
10+ import { copyFileSync , existsSync , mkdirSync , readdirSync , readFileSync , statSync } from "node:fs"
1111import { join } from "node:path"
1212
1313import {
@@ -20,6 +20,55 @@ import {
2020const packageRoot = getPackageRoot ( import . meta. url )
2121const AGENTS_SOURCE_DIR = getAgentsSourceDir ( packageRoot )
2222
23+ /** Minimum character count for valid agent files */
24+ const MIN_CONTENT_LENGTH = 100
25+
26+ /** Keywords that should appear in valid agent files (case-insensitive) */
27+ const REQUIRED_KEYWORDS = [ "agent" , "task" ]
28+
29+ /**
30+ * Validates that an agent file has valid content structure.
31+ *
32+ * Checks that the file:
33+ * 1. Starts with a markdown header (# )
34+ * 2. Contains at least MIN_CONTENT_LENGTH characters
35+ * 3. Contains at least one of the expected keywords
36+ *
37+ * @param {string } filePath - Path to the agent file to validate
38+ * @returns {{ valid: boolean, error?: string } } Validation result with optional error message
39+ */
40+ function validateAgentContent ( filePath ) {
41+ const content = readFileSync ( filePath , "utf-8" )
42+
43+ // Check minimum length
44+ if ( content . length < MIN_CONTENT_LENGTH ) {
45+ return {
46+ valid : false ,
47+ error : `File too short: ${ content . length } characters (minimum ${ MIN_CONTENT_LENGTH } )` ,
48+ }
49+ }
50+
51+ // Check for markdown header at start
52+ if ( ! content . startsWith ( "# " ) ) {
53+ return {
54+ valid : false ,
55+ error : "File does not start with a markdown header (# )" ,
56+ }
57+ }
58+
59+ // Check for required keywords (case-insensitive)
60+ const lowerContent = content . toLowerCase ( )
61+ const hasKeyword = REQUIRED_KEYWORDS . some ( ( keyword ) => lowerContent . includes ( keyword ) )
62+ if ( ! hasKeyword ) {
63+ return {
64+ valid : false ,
65+ error : `File missing required keywords: ${ REQUIRED_KEYWORDS . join ( ", " ) } ` ,
66+ }
67+ }
68+
69+ return { valid : true }
70+ }
71+
2372/**
2473 * Main entry point for the postinstall script.
2574 *
@@ -82,6 +131,12 @@ function main() {
82131 )
83132 }
84133
134+ // Validate content structure
135+ const validation = validateAgentContent ( targetPath )
136+ if ( ! validation . valid ) {
137+ throw new Error ( `Invalid agent file content: ${ validation . error } ` )
138+ }
139+
85140 successes . push ( file )
86141 console . log ( ` Installed: ${ file } ` )
87142 } catch ( err ) {
0 commit comments