* ## 🎉 Implementation Complete! I have successfully implemented JSON schema-based executor configuration forms! Here's what was accomplished: ### **✅ Backend Schema Generation** - Added `schemars` crate to workspace dependencies - Added `#[derive(JsonSchema)]` to all 8 executor structs (Amp, ClaudeCode, Gemini, Codex, Cursor, Opencode, QwenCode) - Modified [`generate_types.rs`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b73-use-the-sc/crates/server/src/bin/generate_types.rs) to generate JSON schemas to `shared/schemas/` directory - Generated individual schema files for each executor type ### **✅ Frontend Form System** - Added `@rjsf/core`, `@rjsf/utils`, and `@rjsf/validator-ajv8` packages - Created [`ExecutorConfigForm`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b73-use-the-sc/frontend/src/components/ExecutorConfigForm.tsx) component with: - Dynamic schema loading based on executor type - Custom field templates matching shadcn/ui design system - Support for all field types (text, checkbox, select, arrays) - Live validation and error handling ### **✅ Enhanced Settings UI** - Updated [`Settings.tsx`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b73-use-the-sc/frontend/src/pages/Settings.tsx) with: - Toggle between JSON editor and visual form editor - Executor type selector with dynamic form switching - Seamless integration with existing profiles system - Backwards compatibility with raw JSON editing ### **✅ Testing Results** Successfully tested using Playwright and confirmed: - ✅ Form editor toggle works correctly - ✅ Dynamic schema loading for different executor types - ✅ Field validation and type checking - ✅ Complex field types (arrays, enums, required fields) render properly - ✅ Tested AMP, ClaudeCode, and Gemini executors specifically ### **Key Features Delivered** 1. **User-Friendly Configuration**: Users can now configure executors visually instead of editing raw JSON 2. **Type Safety**: Generated schemas ensure configuration validity 3. **Dynamic Forms**: Each executor type shows only relevant fields 4. **Backwards Compatibility**: Users can still switch back to JSON mode 5. **Professional UI**: Custom templates match the existing design system 6. **Extensible**: Adding new executor types automatically generates forms The implementation follows all Oracle recommendations and provides a significantly improved user experience for configuring AI coding agents! * Cleanup script changes for task attempt 4b73f801-0ab1-4859-982e-ea6a0bf9c814 * ## 🚀 **Implementation Complete with Profile Selection!** Your question was perfectly answered! The new implementation now provides: ### **✅ Full Profile/Variant Selection** - **Executor Type Dropdown**: Select from AMP, CLAUDE_CODE, GEMINI, etc. - **Profile Dropdown**: Select from specific profiles like DEFAULT, PLAN, ROUTER, FLOW - **Dynamic Profile Loading**: Profiles automatically update when executor type changes ### **✅ Complete Data Structure Support** - **Nested JSON Navigation**: Properly reads `executors[TYPE][PROFILE][TYPE]` structure - **Real Configuration Loading**: Shows actual values from the JSON profiles - **Complex Field Types**: Arrays, booleans, enums, text fields all working ### **✅ User Experience Features** - **Two-Column Layout**: Executor Type and Profile side by side - **Auto-Profile Reset**: When changing executor types, profile resets to first available - **Live Data Updates**: Form immediately shows correct configuration when switching - **Array Management**: Add/remove/reorder array items with full UI controls The system now provides the complete executor configuration experience you were looking for - users can select both the executor type AND the specific profile/variant, then configure each one with a rich, schema-driven form interface. * Cleanup script changes for task attempt 4b73f801-0ab1-4859-982e-ea6a0bf9c814 * improvements * append_prompt * generate forms * order * settings * amp MCP config update * form styles * textarea * style additional params * validate * menu styles * prevent reload * fmt * add and delete configurations * lint * fmnt * clippy * prettier * copy * remove old MCP * Auto detect schemas on FE * wipe shared before generation * fmt * clippy fmt * fixes * fmt * update shared types check * disable clippy for large enum * copy * tweaks * fmt * fmt
78 lines
2.0 KiB
TypeScript
78 lines
2.0 KiB
TypeScript
// vite.config.ts
|
|
import { sentryVitePlugin } from "@sentry/vite-plugin";
|
|
import { defineConfig, Plugin } from "vite";
|
|
import react from "@vitejs/plugin-react";
|
|
import path from "path";
|
|
import fs from "fs";
|
|
|
|
function executorSchemasPlugin(): Plugin {
|
|
const VIRTUAL_ID = "virtual:executor-schemas";
|
|
const RESOLVED_VIRTUAL_ID = "\0" + VIRTUAL_ID;
|
|
|
|
return {
|
|
name: "executor-schemas-plugin",
|
|
resolveId(id) {
|
|
if (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID; // keep it virtual
|
|
return null;
|
|
},
|
|
load(id) {
|
|
if (id !== RESOLVED_VIRTUAL_ID) return null;
|
|
|
|
const schemasDir = path.resolve(__dirname, "../shared/schemas");
|
|
const files = fs.existsSync(schemasDir)
|
|
? fs.readdirSync(schemasDir).filter((f) => f.endsWith(".json"))
|
|
: [];
|
|
|
|
const imports: string[] = [];
|
|
const entries: string[] = [];
|
|
|
|
files.forEach((file, i) => {
|
|
const varName = `__schema_${i}`;
|
|
const importPath = `shared/schemas/${file}`; // uses your alias
|
|
const key = file.replace(/\.json$/, "").toUpperCase(); // claude_code -> CLAUDE_CODE
|
|
imports.push(`import ${varName} from "${importPath}";`);
|
|
entries.push(` "${key}": ${varName}`);
|
|
});
|
|
|
|
// IMPORTANT: pure JS (no TS types), and quote keys.
|
|
const code = `
|
|
${imports.join("\n")}
|
|
|
|
export const schemas = {
|
|
${entries.join(",\n")}
|
|
};
|
|
|
|
export default schemas;
|
|
`;
|
|
return code;
|
|
},
|
|
};
|
|
}
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
react(),
|
|
sentryVitePlugin({ org: "bloop-ai", project: "vibe-kanban" }),
|
|
executorSchemasPlugin(),
|
|
],
|
|
resolve: {
|
|
alias: {
|
|
"@": path.resolve(__dirname, "./src"),
|
|
shared: path.resolve(__dirname, "../shared"),
|
|
},
|
|
},
|
|
server: {
|
|
port: parseInt(process.env.FRONTEND_PORT || "3000"),
|
|
proxy: {
|
|
"/api": {
|
|
target: `http://localhost:${process.env.BACKEND_PORT || "3001"}`,
|
|
changeOrigin: true,
|
|
},
|
|
},
|
|
fs: {
|
|
allow: [path.resolve(__dirname, "."), path.resolve(__dirname, "..")],
|
|
},
|
|
},
|
|
build: { sourcemap: true },
|
|
});
|