Skip to content

Commit a3f17a2

Browse files
committed
feat(sandboxes): Improve code evaluator editor ux (#12690)
1 parent d661829 commit a3f17a2

27 files changed

Lines changed: 3677 additions & 551 deletions

app/schema.graphql

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ input CreateCodeEvaluatorInput {
602602
sourceCode: String!
603603
language: Language!
604604
description: String = null
605-
sandboxConfigId: Int = null
605+
sandboxConfigId: ID = null
606606
outputConfigs: [AnnotationConfigInput!] = null
607607
inputMapping: EvaluatorInputMappingInput = null
608608
}
@@ -1448,6 +1448,7 @@ input EvaluatorPreviewInput @oneOf {
14481448
builtInEvaluatorId: ID
14491449
inlineLlmEvaluator: InlineLLMEvaluatorInput
14501450
codeEvaluatorId: ID
1451+
inlineCodeEvaluator: InlineCodeEvaluatorInput
14511452
}
14521453

14531454
input EvaluatorPreviewItemInput {
@@ -2053,6 +2054,15 @@ input GoogleGenAIHttpOptionsInput {
20532054

20542055
scalar Identifier
20552056

2057+
input InlineCodeEvaluatorInput {
2058+
name: String!
2059+
language: Language!
2060+
sourceCode: String!
2061+
outputConfigs: [AnnotationConfigInput!]!
2062+
sandboxConfigId: ID = null
2063+
description: String = null
2064+
}
2065+
20562066
input InlineLLMEvaluatorInput {
20572067
name: String!
20582068
promptVersion: ChatPromptVersionInput!
@@ -3877,7 +3887,7 @@ input UpdateCodeEvaluatorInput {
38773887
sourceCode: String
38783888
language: Language
38793889
description: String
3880-
sandboxConfigId: Int
3890+
sandboxConfigId: ID
38813891
outputConfigs: [AnnotationConfigInput!]
38823892
inputMapping: EvaluatorInputMappingInput
38833893
}

app/src/components/dataset/CreateCodeDatasetEvaluatorSlideover.tsx

Lines changed: 70 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Suspense, useMemo, useState } from "react";
1+
import { Suspense, useCallback, useEffect, useRef, useState } from "react";
22
import type { ModalOverlayProps } from "react-aria-components";
33
import { graphql, useLazyLoadQuery, useMutation } from "react-relay";
44
import invariant from "tiny-invariant";
@@ -9,11 +9,11 @@ import { Modal, ModalOverlay } from "@phoenix/components/core/overlay/Modal";
99
import type { CreateCodeDatasetEvaluatorSlideover_createCodeEvaluatorMutation } from "@phoenix/components/dataset/__generated__/CreateCodeDatasetEvaluatorSlideover_createCodeEvaluatorMutation.graphql";
1010
import type { CreateCodeDatasetEvaluatorSlideover_createDatasetCodeEvaluatorMutation } from "@phoenix/components/dataset/__generated__/CreateCodeDatasetEvaluatorSlideover_createDatasetCodeEvaluatorMutation.graphql";
1111
import type { CreateCodeDatasetEvaluatorSlideoverQuery } from "@phoenix/components/dataset/__generated__/CreateCodeDatasetEvaluatorSlideoverQuery.graphql";
12+
import { mapSandboxConfigOptions } from "@phoenix/components/evaluators/CodeEvaluatorLanguageSandboxFields";
1213
import { DEFAULT_CODE_EVALUATOR_SOURCE } from "@phoenix/components/evaluators/codeEvaluatorUtils";
1314
import {
14-
EditCodeEvaluatorDialogContent,
15-
mapSandboxConfigOptions,
1615
createDefaultContinuousOutputConfig,
16+
EditCodeEvaluatorDialogContent,
1717
} from "@phoenix/components/evaluators/EditCodeEvaluatorDialogContent";
1818
import { buildOutputConfigsInput } from "@phoenix/components/evaluators/utils";
1919
import { EvaluatorStoreProvider } from "@phoenix/contexts/EvaluatorContext";
@@ -29,20 +29,49 @@ export const CreateCodeDatasetEvaluatorSlideover = ({
2929
datasetId,
3030
updateConnectionIds,
3131
onEvaluatorCreated,
32+
onOpenChange,
33+
isOpen,
3234
...props
3335
}: {
3436
datasetId: string;
3537
updateConnectionIds?: string[];
3638
onEvaluatorCreated?: (datasetEvaluatorId: string) => void;
3739
} & ModalOverlayProps) => {
40+
const isDirtyRef = useRef(false);
41+
42+
// Reset dirty state when slideover opens
43+
useEffect(() => {
44+
if (isOpen) {
45+
isDirtyRef.current = false;
46+
}
47+
}, [isOpen]);
48+
49+
const handleOpenChange = useCallback(
50+
(nextIsOpen: boolean) => {
51+
if (!nextIsOpen && isDirtyRef.current) {
52+
const confirmed = window.confirm(
53+
"You have unsaved changes. Are you sure you want to close?"
54+
);
55+
if (!confirmed) return;
56+
}
57+
onOpenChange?.(nextIsOpen);
58+
},
59+
[onOpenChange]
60+
);
61+
62+
const handleDirtyChange = useCallback((isDirty: boolean) => {
63+
isDirtyRef.current = isDirty;
64+
}, []);
65+
3866
return (
39-
<ModalOverlay {...props}>
67+
<ModalOverlay {...props} isOpen={isOpen} onOpenChange={handleOpenChange}>
4068
<Modal variant="slideover" size="fullscreen">
4169
<Dialog>
4270
{({ close }) => (
4371
<Suspense fallback={<Loading />}>
4472
<CreateCodeEvaluatorDialog
4573
onClose={close}
74+
onDirtyChange={handleDirtyChange}
4675
datasetId={datasetId}
4776
updateConnectionIds={updateConnectionIds}
4877
onEvaluatorCreated={onEvaluatorCreated}
@@ -57,11 +86,13 @@ export const CreateCodeDatasetEvaluatorSlideover = ({
5786

5887
const CreateCodeEvaluatorDialog = ({
5988
onClose,
89+
onDirtyChange,
6090
datasetId,
6191
updateConnectionIds,
6292
onEvaluatorCreated,
6393
}: {
6494
onClose: () => void;
95+
onDirtyChange?: (isDirty: boolean) => void;
6596
datasetId: string;
6697
updateConnectionIds?: string[];
6798
onEvaluatorCreated?: (datasetEvaluatorId: string) => void;
@@ -74,19 +105,24 @@ const CreateCodeEvaluatorDialog = ({
74105
sandboxProviders {
75106
backendType
76107
language
108+
enabled
77109
configs {
78110
id
79111
name
80112
description
81113
}
82114
}
115+
sandboxBackends {
116+
backendType
117+
status
118+
}
83119
}
84120
`,
85121
{}
86122
);
87-
const sandboxConfigs = useMemo(
88-
() => mapSandboxConfigOptions(data.sandboxProviders),
89-
[data.sandboxProviders]
123+
const sandboxConfigs = mapSandboxConfigOptions(
124+
data.sandboxProviders,
125+
data.sandboxBackends
90126
);
91127
const [createCodeEvaluator, isCreatingCodeEvaluator] =
92128
useMutation<CreateCodeDatasetEvaluatorSlideover_createCodeEvaluatorMutation>(graphql`
@@ -119,40 +155,36 @@ const CreateCodeEvaluatorDialog = ({
119155
}
120156
}
121157
`);
122-
const initialState = useMemo(
123-
() =>
124-
({
125-
evaluator: {
126-
globalName: "",
127-
name: "",
128-
description: "",
129-
inputMapping: {
130-
literalMapping: {},
131-
pathMapping: {},
132-
},
133-
kind: "CODE",
134-
isBuiltin: false,
135-
includeExplanation: false,
136-
},
137-
outputConfigs: [createDefaultContinuousOutputConfig("")],
138-
dataset: {
139-
readonly: true,
140-
id: datasetId,
141-
selectedExampleId: null,
142-
selectedSplitIds: [],
143-
},
144-
evaluatorMappingSource: EVALUATOR_MAPPING_SOURCE_DEFAULT,
145-
showPromptPreview: false,
146-
}) satisfies EvaluatorStoreProps,
147-
[datasetId]
148-
);
158+
const initialState: EvaluatorStoreProps = {
159+
evaluator: {
160+
globalName: "",
161+
name: "",
162+
description: "",
163+
inputMapping: {
164+
literalMapping: {},
165+
pathMapping: {},
166+
},
167+
kind: "CODE",
168+
isBuiltin: false,
169+
includeExplanation: false,
170+
},
171+
outputConfigs: [createDefaultContinuousOutputConfig("")],
172+
dataset: {
173+
readonly: true,
174+
id: datasetId,
175+
selectedExampleId: null,
176+
selectedSplitIds: [],
177+
},
178+
evaluatorMappingSource: EVALUATOR_MAPPING_SOURCE_DEFAULT,
179+
showPromptPreview: false,
180+
};
149181

150182
const onSubmit = (
151183
store: EvaluatorStoreInstance,
152184
payload: {
153185
language: "PYTHON" | "TYPESCRIPT";
154186
sourceCode: string;
155-
sandboxConfigId: number | null;
187+
sandboxConfigId?: string | null;
156188
}
157189
) => {
158190
setError(undefined);
@@ -198,6 +230,7 @@ const CreateCodeEvaluatorDialog = ({
198230
title: "Evaluator created",
199231
message: "The code evaluator has been added to the dataset.",
200232
});
233+
onDirtyChange?.(false);
201234
onClose();
202235
},
203236
onError: (mutationError) => {
@@ -223,6 +256,8 @@ const CreateCodeEvaluatorDialog = ({
223256
{({ store }) => (
224257
<EditCodeEvaluatorDialogContent
225258
onSubmit={(payload) => onSubmit(store, payload)}
259+
onCancel={onClose}
260+
onDirtyChange={onDirtyChange}
226261
isSubmitting={
227262
isCreatingCodeEvaluator || isCreatingDatasetCodeEvaluator
228263
}

0 commit comments

Comments
 (0)