Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4d91052
feat(configs): lazy-load config versions on expand & extract inline S…
Ayush8923 Mar 27, 2026
78c33cb
feat(configs): lazy-load config versions on expand & extract inline S…
Ayush8923 Mar 27, 2026
42ad650
fix(*): linting and js comment
Ayush8923 Mar 27, 2026
3274e9d
fix(*): remove the unused files
Ayush8923 Mar 27, 2026
9a2da8f
fix(*): added the infinite scroll hook and update the icons
Ayush8923 Mar 27, 2026
f12d2d6
fix(*): update the constants
Ayush8923 Mar 27, 2026
e1b80be
fix(*): update imports
Ayush8923 Mar 27, 2026
395fabc
fix(*): remove the unused js comment
Ayush8923 Mar 27, 2026
bee1fc3
fix(*): update the tailwind style
Ayush8923 Mar 27, 2026
0c1d83c
fix(*): fix the alignment
Ayush8923 Mar 27, 2026
7a5b11f
fix(*): refactoring loader component
Ayush8923 Mar 27, 2026
133bdc4
feat(*): change grouping name routes->main
Ayush8923 Mar 27, 2026
8a38504
fix(*): formatting
Ayush8923 Mar 27, 2026
034efc3
feat(*): document pagination params & document folder restructuring &…
Ayush8923 Mar 29, 2026
8df6880
fix(*): added the reusable component
Ayush8923 Mar 29, 2026
7cc670d
fix(*): some updates and cleanups
Ayush8923 Mar 29, 2026
a79f4f4
fix(*): create the own modal component and cleanups
Ayush8923 Mar 29, 2026
e60b32f
fix(*): Remove unwanted types
Ayush8923 Mar 29, 2026
86daedc
fix(*): Remove unwanted types
Ayush8923 Mar 29, 2026
f1032ca
fix(*): added the quers params in the api endpoint
Ayush8923 Mar 30, 2026
4936b8b
Feat/document pagination params (#98)
Ayush8923 Mar 30, 2026
7ff52af
Change grouping name `routes` -> `main` (#97)
Ayush8923 Mar 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
427 changes: 177 additions & 250 deletions app/(routes)/configurations/page.tsx

Large diffs are not rendered by default.

54 changes: 20 additions & 34 deletions app/(routes)/configurations/prompt-editor/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
/**
* Prompt Editor - Version Controlled Prompt + Config Editor
*
* A WYSIWYG editor for managing prompts and configs with linear versioning.
* Features: save, load, compare configs with backend persistence.
* Uses shared useConfigs hook for caching.
* Supports URL query params for cross-navigation from Config Library/Evaluations.
* Prompt WYSIWYG Editor: Manage prompts and configs with versioning, caching, and URL-based navigation support.
*/

"use client";
Expand All @@ -15,7 +10,6 @@
import { colors } from "@/app/lib/colors";
import { ConfigBlob, Tool } from "./types";
import { hasConfigChanges } from "./utils";
import { ConfigCreate, ConfigVersionCreate } from "@/app/lib/configTypes";
import Header from "@/app/components/prompt-editor/Header";
import HistorySidebar from "@/app/components/prompt-editor/HistorySidebar";
import PromptEditorPane from "@/app/components/prompt-editor/PromptEditorPane";
Expand All @@ -26,7 +20,12 @@
import { useApp } from "@/app/lib/context/AppContext";
import { useAuth } from "@/app/lib/context/AuthContext";
import { useConfigs } from "@/app/hooks/useConfigs";
import { SavedConfig } from "@/app/lib/types/configs";
import {
SavedConfig,
ConfigCreate,
ConfigVersionCreate,
ConfigVersionItems,
} from "@/app/lib/types/configs";
import { invalidateConfigCache } from "@/app/lib/utils";
import { configState } from "@/app/lib/store/configStore";
import { apiFetch } from "@/app/lib/apiClient";
Expand All @@ -36,20 +35,16 @@
const searchParams = useSearchParams();
const { sidebarCollapsed, setSidebarCollapsed } = useApp();
const { activeKey } = useAuth();

// URL query params for cross-navigation
const urlConfigId = searchParams.get("config");
const urlVersion = searchParams.get("version");
const showHistory = searchParams.get("history") === "true";
const isNewConfig = searchParams.get("new") === "true";

// Evaluation context to preserve (when coming from evaluations page)
const urlDatasetId = searchParams.get("dataset");
const urlExperimentName = searchParams.get("experiment");
const fromEvaluations = searchParams.get("from") === "evaluations";

// Default config for new versions
const defaultConfig: ConfigBlob = {

Check warning on line 47 in app/(routes)/configurations/prompt-editor/page.tsx

View workflow job for this annotation

GitHub Actions / lint-and-build

The 'defaultConfig' object makes the dependencies of useEffect Hook (at line 212) change on every render. To fix this, wrap the initialization of 'defaultConfig' in its own useMemo() Hook

Check warning on line 47 in app/(routes)/configurations/prompt-editor/page.tsx

View workflow job for this annotation

GitHub Actions / lint-and-build

The 'defaultConfig' object makes the dependencies of useCallback Hook (at line 164) change on every render. To fix this, wrap the initialization of 'defaultConfig' in its own useMemo() Hook
completion: {
provider: "openai",
type: "text",
Expand All @@ -76,20 +71,9 @@
const initialLoadComplete = !isLoading;
const editorInitialized = React.useRef(false);
const [editorReady, setEditorReady] = useState<boolean>(!urlConfigId);

const [stableVersionItemsMap, setStableVersionItemsMap] = useState<
Record<string, import("@/app/lib/types/configs").ConfigVersionItems[]>
Record<string, ConfigVersionItems[]>
>({});

useEffect(() => {
if (Object.keys(hookVersionItemsMap).length > 0) {
setStableVersionItemsMap((prev) => ({ ...prev, ...hookVersionItemsMap }));
}
}, [hookVersionItemsMap]);

const versionItemsMap = stableVersionItemsMap;

// Current working state
const [currentContent, setCurrentContent] = useState<string>(
"You are a helpful AI assistant.\nYou provide clear and concise answers.\nYou are polite and professional.",
);
Expand All @@ -106,20 +90,22 @@
const [expandedConfigs, setExpandedConfigs] = useState<Set<string>>(
new Set(),
);

// UI state
const [hasUnsavedChanges, setHasUnsavedChanges] = useState<boolean>(false);
const [commitMessage, setCommitMessage] = useState<string>("");
const [showHistorySidebar, setShowHistorySidebar] = useState<boolean>(true); // Default open, or from URL param
const [showConfigPane, setShowConfigPane] = useState<boolean>(true); // Config pane collapse state

// History viewing state
const [showHistorySidebar, setShowHistorySidebar] = useState<boolean>(true);
const [showConfigPane, setShowConfigPane] = useState<boolean>(true);
const [selectedVersion, setSelectedVersion] = useState<SavedConfig | null>(
null,
);
const [compareWith, setCompareWith] = useState<SavedConfig | null>(null);

const getApiKey = (): string | null => activeKey?.key ?? null;
useEffect(() => {
if (Object.keys(hookVersionItemsMap).length > 0) {
setStableVersionItemsMap((prev) => ({ ...prev, ...hookVersionItemsMap }));
}
}, [hookVersionItemsMap]);

const versionItemsMap = stableVersionItemsMap;

// Populate the editor from a fully-loaded SavedConfig
const applyConfig = React.useCallback(
Expand Down Expand Up @@ -152,7 +138,7 @@
);
if (selectInHistory) setSelectedVersion(config);
},
[],

Check warning on line 141 in app/(routes)/configurations/prompt-editor/page.tsx

View workflow job for this annotation

GitHub Actions / lint-and-build

React Hook React.useCallback has a missing dependency: 'currentConfigParentId'. Either include it or remove the dependency array. You can also replace multiple useState variables with useReducer if 'setExpandedConfigs' needs the current value of 'currentConfigParentId'
);

// Load a config directly from a SavedConfig object (no savedConfigs lookup needed)
Expand All @@ -175,7 +161,7 @@
loadVersionsForConfig(config.config_id);
applyConfig(config);
},
[applyConfig, loadVersionsForConfig],
[applyConfig, loadVersionsForConfig, defaultConfig],
);

// Initialize editor from URL params — runs once, on first load completion
Expand Down Expand Up @@ -232,6 +218,7 @@
loadVersionsForConfig,
loadSingleVersion,
applyConfig,
defaultConfig,
]);

// Re-populate version items when missing (e.g. after background cache revalidation wipes versionItemsCache)
Expand Down Expand Up @@ -288,7 +275,7 @@
return;
}

const apiKey = getApiKey();
const apiKey = activeKey?.key;
if (!apiKey) {
toast.error("No API key found. Please add an API key in the Keystore.");
return;
Expand Down Expand Up @@ -494,7 +481,6 @@
loadSingleVersionForConfig={loadSingleVersion}
/>

{/* Show DiffView only when comparing versions (sidebar open + version selected) */}
{showHistorySidebar && selectedVersion ? (
<DiffView
selectedCommit={selectedVersion}
Expand Down
5 changes: 4 additions & 1 deletion app/api/configs/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { apiClient } from "@/app/lib/apiClient";

export async function GET(request: Request) {
try {
const { status, data } = await apiClient(request, "/api/v1/configs/");
const { searchParams } = new URL(request.url);
const queryString = searchParams.toString();
const endpoint = `/api/v1/configs/${queryString ? `?${queryString}` : ""}`;
const { status, data } = await apiClient(request, endpoint);
return NextResponse.json(data, { status });
} catch (error) {
return NextResponse.json(
Expand Down
Loading
Loading