MCPcopy Create free account
hub / github.com/ForestHubAI/edge-agents / promptCustomComponents

Function promptCustomComponents

ts/workflow-cli/cli/deploy/components.ts:168–224  ·  view source on GitHub ↗
(
  preloaded: LoadedComponent[],
)

Source from the content-addressed store, hash-verified

166// Each component's <name>.env is resolved as it is added, so the operator answers
167// a component's env right after picking it — never a second batch pass.
168export async function promptCustomComponents(
169 preloaded: LoadedComponent[],
170): Promise<{ components: DeployComponent[]; env: Record<string, string> }> {
171 const components: DeployComponent[] = [];
172 const env: Record<string, string> = {};
173 const seen = new Set<string>();
174
175 // Take in a component: record it, then turn its env.example into env text.
176 const add = async (loaded: LoadedComponent): Promise<void> => {
177 seen.add(loaded.component.name);
178 components.push(loaded.component);
179 const text = await resolveComponentEnv(loaded.dir, loaded.component.name, { interactive: true });
180 if (text !== null) env[loaded.component.name] = text;
181 };
182
183 if (preloaded.length > 0) {
184 process.stdout.write(` Already added: ${preloaded.map((c) => c.component.name).join(", ")}\n`);
185 }
186 for (const loaded of preloaded) await add(loaded);
187
188 while (
189 await confirm({
190 message: components.length === 0 ? "Add a custom component?" : "Add another custom component?",
191 default: false,
192 })
193 ) {
194 const dir = (
195 await input({
196 message: "Custom component folder",
197 // Full inline validation: path, component.json presence, contract shape,
198 // and a name not already taken — the same checks the batch path runs, so
199 // a bad folder is rejected here instead of failing late in the build.
200 validate: async (v) => {
201 const t = v.trim();
202 if (!t) return "enter a folder path";
203 if (!existsSync(t)) return `folder not found: ${t}`;
204 if (!existsSync(path.join(t, "component.json"))) return `no component.json in ${t}`;
205 let data: unknown;
206 try {
207 data = await readComponentJson(t);
208 } catch (err) {
209 return err instanceof Error ? err.message : String(err);
210 }
211 const errors = validateComponent(data);
212 if (errors.length > 0) return errors.join("; ");
213 const name = (data as DeployComponent).name;
214 return seen.has(name) ? `"${name}" already added` : true;
215 },
216 })
217 ).trim();
218
219 // The prompt's validator proved the shape; re-read for the typed value.
220 await add({ component: (await readComponentJson(dir)) as DeployComponent, dir });
221 }
222
223 return { components, env };
224}

Callers 2

promptMissingFunction · 0.90
components.test.tsFile · 0.90

Calls 5

inputStruct · 0.85
readComponentJsonFunction · 0.85
validateComponentFunction · 0.85
writeMethod · 0.80
addFunction · 0.70

Tested by

no test coverage detected