MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / parseSpec

Function parseSpec

src/cli/custom-commands.ts:107–195  ·  view source on GitHub ↗
(
  raw: string,
  name: string,
  filePath: string,
  origin: 'project' | 'user' | 'plugin',
)

Source from the content-addressed store, hash-verified

105
106/** Parse a Markdown file into a CustomCommandSpec. */
107export function parseSpec(
108 raw: string,
109 name: string,
110 filePath: string,
111 origin: 'project' | 'user' | 'plugin',
112): CustomCommandSpec {
113 let description: string | undefined;
114 let argumentHint: string | undefined;
115 let allowedTools: string[] | undefined;
116 let model: string | undefined;
117 let mode: 'plan' | 'normal' | undefined;
118 let body = raw;
119
120 // Frontmatter must be at the very top, delimited by --- on its own line.
121 const fmMatch = raw.match(/^---\s*\n([\s\S]*?)\n---\s*\r?\n?([\s\S]*)$/);
122 if (fmMatch) {
123 const fm = fmMatch[1] ?? '';
124 body = fmMatch[2] ?? '';
125 const fmLines = fm.split('\n');
126 let i = 0;
127 while (i < fmLines.length) {
128 const line = fmLines[i]!;
129 // Skip empty/comment lines
130 if (/^\s*(#.*)?$/.test(line)) { i++; continue; }
131 const m = line.match(/^([a-zA-Z][\w-]*)\s*:\s*(.*)$/);
132 if (!m) { i++; continue; }
133 const key = m[1]!.toLowerCase();
134 const rawValue = m[2]!.trim();
135
136 let value: string | string[];
137 if (rawValue === '') {
138 // Look ahead for ` - item` lines (YAML multiline list form)
139 const items: string[] = [];
140 i++;
141 while (i < fmLines.length && /^\s+-\s+/.test(fmLines[i]!)) {
142 items.push(stripQuotes(fmLines[i]!.replace(/^\s+-\s+/, '').trim()));
143 i++;
144 }
145 value = items;
146 } else if (rawValue.startsWith('[') && rawValue.endsWith(']')) {
147 // Inline array
148 value = rawValue
149 .slice(1, -1)
150 .split(',')
151 .map(s => stripQuotes(s.trim()))
152 .filter(Boolean);
153 i++;
154 } else {
155 value = stripQuotes(rawValue);
156 i++;
157 }
158
159 // Apply the key. Validate types loosely.
160 switch (key) {
161 case 'description':
162 if (typeof value === 'string') description = value;
163 break;
164 case 'argument-hint':

Callers 2

loadCustomCommandsFunction · 0.85

Calls 3

stripQuotesFunction · 0.70
pushMethod · 0.45
hasMethod · 0.45

Tested by

no test coverage detected