mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-01 09:43:14 +00:00
parent
b3bcc46c59
commit
1c12f6f754
5 changed files with 63 additions and 70 deletions
|
|
@ -13,12 +13,13 @@ import {
|
|||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { useConfigStore } from "@/hooks/use-config-store";
|
||||
import { DEFAULT_CONFIG_KEY, useConfigStore } from "@/hooks/use-config-store";
|
||||
import { AlertCircle } from "lucide-react";
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import _ from "lodash";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useQueryState } from "nuqs";
|
||||
|
||||
interface Option {
|
||||
label: string;
|
||||
|
|
@ -62,6 +63,8 @@ export function ConfigField({
|
|||
value: externalValue, // TODO: Rename to avoid conflict
|
||||
setValue: externalSetValue, // TODO: Rename to avoid conflict
|
||||
}: ConfigFieldProps) {
|
||||
const [threadId] = useQueryState("threadId");
|
||||
const configKey = threadId || DEFAULT_CONFIG_KEY;
|
||||
const store = useConfigStore();
|
||||
const [jsonError, setJsonError] = useState<string | null>(null);
|
||||
|
||||
|
|
@ -70,14 +73,14 @@ export function ConfigField({
|
|||
|
||||
const currentValue = isExternallyManaged
|
||||
? externalValue
|
||||
: store.configs[id]?.[id];
|
||||
: store.configs[configKey]?.[id];
|
||||
|
||||
const handleChange = (newValue: any) => {
|
||||
setJsonError(null);
|
||||
if (isExternallyManaged && externalSetValue) {
|
||||
externalSetValue(newValue);
|
||||
} else {
|
||||
store.updateConfig(id, newValue);
|
||||
store.updateConfig(configKey, id, newValue);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -97,7 +100,7 @@ export function ConfigField({
|
|||
if (isExternallyManaged && externalSetValue) {
|
||||
externalSetValue(jsonString);
|
||||
} else {
|
||||
store.updateConfig(id, jsonString);
|
||||
store.updateConfig(configKey, id, jsonString);
|
||||
}
|
||||
setJsonError("Invalid JSON format");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { forwardRef, ForwardedRef, useState, useEffect } from "react";
|
|||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { ConfigField } from "@/components/configuration-sidebar/config-field";
|
||||
import { ConfigSection } from "@/components/configuration-sidebar/config-section";
|
||||
import { useConfigStore } from "@/hooks/use-config-store";
|
||||
import { useConfigStore, DEFAULT_CONFIG_KEY } from "@/hooks/use-config-store";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
|
|
@ -12,11 +12,15 @@ import type { ConfigurableFieldUIMetadata } from "@open-swe/shared/configurable-
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { PanelRightOpen } from "lucide-react";
|
||||
import { GraphConfigurationMetadata } from "@open-swe/shared/open-swe/types";
|
||||
import { useQueryState } from "nuqs";
|
||||
import { useStreamContext } from "@/providers/Stream";
|
||||
|
||||
/**
|
||||
* Extract configuration metadata from the GraphConfiguration Zod schema
|
||||
*/
|
||||
function extractConfigurationsFromSchema(): ConfigurableFieldUIMetadata[] {
|
||||
function extractConfigurationsFromSchema(
|
||||
configurable: Record<string, any>,
|
||||
): ConfigurableFieldUIMetadata[] {
|
||||
const configurations: ConfigurableFieldUIMetadata[] = [];
|
||||
|
||||
for (const [label, { x_open_swe_ui_config: metadata }] of Object.entries(
|
||||
|
|
@ -28,7 +32,7 @@ function extractConfigurationsFromSchema(): ConfigurableFieldUIMetadata[] {
|
|||
configurations.push({
|
||||
label,
|
||||
type: metadata.type,
|
||||
default: metadata.default,
|
||||
default: configurable[label] || metadata.default,
|
||||
description: metadata.description,
|
||||
placeholder: metadata.placeholder,
|
||||
options: metadata.options,
|
||||
|
|
@ -52,6 +56,9 @@ export const ConfigurationSidebar = forwardRef<
|
|||
AIConfigPanelProps
|
||||
>(({ className, open, onClose }, ref: ForwardedRef<HTMLDivElement>) => {
|
||||
const { configs, updateConfig } = useConfigStore();
|
||||
const stream = useStreamContext();
|
||||
|
||||
const [threadId] = useQueryState("threadId");
|
||||
|
||||
const [configurations, setConfigurations] = useState<
|
||||
ConfigurableFieldUIMetadata[]
|
||||
|
|
@ -60,17 +67,38 @@ export const ConfigurationSidebar = forwardRef<
|
|||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
const configKey = threadId || DEFAULT_CONFIG_KEY;
|
||||
|
||||
const actualConfigs = extractConfigurationsFromSchema();
|
||||
actualConfigs.forEach((config) => {
|
||||
if (configs[config.label] === undefined && config.default !== undefined) {
|
||||
updateConfig(config.label, config.default);
|
||||
}
|
||||
});
|
||||
if (threadId) {
|
||||
stream.client.threads.get(threadId).then((t) => {
|
||||
if (
|
||||
!("config" in t) ||
|
||||
!(t as any).config ||
|
||||
!(t as any).config.configurable
|
||||
) {
|
||||
console.error("Thread does not have config key", t);
|
||||
return;
|
||||
}
|
||||
|
||||
setConfigurations(actualConfigs);
|
||||
const actualConfigs = extractConfigurationsFromSchema(
|
||||
(t.config as any).configurable,
|
||||
);
|
||||
actualConfigs.forEach((c) => {
|
||||
// Always update the config store with either the default values, or the values from the thread.
|
||||
updateConfig(configKey, c.label, c.default);
|
||||
});
|
||||
|
||||
setConfigurations(actualConfigs);
|
||||
});
|
||||
} else {
|
||||
const actualConfigs = extractConfigurationsFromSchema({});
|
||||
actualConfigs.forEach((c) => {
|
||||
updateConfig(configKey, c.label, c.default);
|
||||
});
|
||||
setConfigurations(actualConfigs);
|
||||
}
|
||||
setLoading(false);
|
||||
}, [configs, updateConfig]);
|
||||
}, [threadId]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import { GitHubOAuthButton } from "../github/github-oauth-button";
|
|||
import { useGitHubApp } from "@/hooks/useGitHubApp";
|
||||
import TaskList from "../task-list";
|
||||
import { ConfigurationSidebar } from "../configuration-sidebar";
|
||||
import { useConfigStore } from "@/hooks/use-config-store";
|
||||
import { DEFAULT_CONFIG_KEY, useConfigStore } from "@/hooks/use-config-store";
|
||||
import { RepositoryBranchSelectors } from "../github/repo-branch-selectors";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
|
|
@ -101,7 +101,7 @@ export function Thread() {
|
|||
const [artifactContext, setArtifactContext] = useArtifactContext();
|
||||
const [artifactOpen, closeArtifact] = useArtifactOpen();
|
||||
const { selectedRepository } = useGitHubApp();
|
||||
const { getConfigs } = useConfigStore();
|
||||
const { getConfig } = useConfigStore();
|
||||
const {
|
||||
taskPlan,
|
||||
handleTaskChange,
|
||||
|
|
@ -269,7 +269,7 @@ export function Thread() {
|
|||
config: {
|
||||
recursion_limit: 400,
|
||||
configurable: {
|
||||
...getConfigs(),
|
||||
...getConfig(threadId || DEFAULT_CONFIG_KEY),
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
|
|
@ -294,7 +294,7 @@ export function Thread() {
|
|||
config: {
|
||||
recursion_limit: 400,
|
||||
configurable: {
|
||||
...getConfigs(),
|
||||
...getConfig(threadId || DEFAULT_CONFIG_KEY),
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
|
|
|
|||
|
|
@ -114,8 +114,6 @@ export function AssistantMessage({
|
|||
return null;
|
||||
}
|
||||
|
||||
console.log("returning");
|
||||
|
||||
return (
|
||||
<div className="group mr-auto flex w-full max-w-3xl items-start gap-2">
|
||||
<div className="flex w-full flex-col gap-2">
|
||||
|
|
|
|||
|
|
@ -2,21 +2,16 @@
|
|||
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import type { ConfigurableFieldUIMetadata } from "@open-swe/shared/configurable-metadata";
|
||||
|
||||
export const DEFAULT_CONFIG_KEY = "open_swe_default_config";
|
||||
|
||||
interface ConfigState {
|
||||
configs: Record<string, any>;
|
||||
getConfig: (key: string) => Record<string, any>;
|
||||
getConfig: (namespace: string) => Record<string, any>;
|
||||
getConfigs: () => Record<string, any>;
|
||||
updateConfig: (key: string, value: any) => void;
|
||||
resetConfig: (key: string) => void;
|
||||
setDefaultConfig: (
|
||||
key: string,
|
||||
configurations: ConfigurableFieldUIMetadata[],
|
||||
) => void;
|
||||
resetStore: (key: string) => void;
|
||||
updateConfig: (namespace: string, key: string, value: any) => void;
|
||||
resetConfig: (namespace: string) => void;
|
||||
resetStore: (namespace: string) => void;
|
||||
}
|
||||
|
||||
export const useConfigStore = create<ConfigState>()(
|
||||
|
|
@ -24,9 +19,9 @@ export const useConfigStore = create<ConfigState>()(
|
|||
(set, get) => ({
|
||||
configs: {},
|
||||
|
||||
getConfig: (key: string) => {
|
||||
getConfig: (namespace: string) => {
|
||||
const state = get();
|
||||
const baseConfig = state.configs[key];
|
||||
const baseConfig = state.configs[namespace];
|
||||
const configObj = {
|
||||
...baseConfig,
|
||||
};
|
||||
|
|
@ -36,33 +31,23 @@ export const useConfigStore = create<ConfigState>()(
|
|||
|
||||
getConfigs: () => {
|
||||
const state = get();
|
||||
const flatConfigs: Record<string, any> = {};
|
||||
Object.entries(state.configs).forEach(([key, configObj]) => {
|
||||
if (
|
||||
configObj &&
|
||||
typeof configObj === "object" &&
|
||||
configObj[key] !== undefined
|
||||
) {
|
||||
flatConfigs[key] = configObj[key];
|
||||
}
|
||||
});
|
||||
return flatConfigs;
|
||||
return state.configs;
|
||||
},
|
||||
|
||||
updateConfig: (key, value) =>
|
||||
updateConfig: (namespace: string, key: string, value: any) =>
|
||||
set((state) => ({
|
||||
configs: {
|
||||
...state.configs,
|
||||
[key]: {
|
||||
...(state.configs[key] || {}),
|
||||
[namespace]: {
|
||||
...(state.configs[namespace] || {}),
|
||||
[key]: value,
|
||||
},
|
||||
},
|
||||
})),
|
||||
|
||||
resetConfig: (key: string) => {
|
||||
resetConfig: (namespace: string) => {
|
||||
set((state) => {
|
||||
const config = state.configs[key];
|
||||
const config = state.configs[namespace];
|
||||
if (!config || !config.__defaultValues) {
|
||||
return state;
|
||||
}
|
||||
|
|
@ -70,33 +55,12 @@ export const useConfigStore = create<ConfigState>()(
|
|||
return {
|
||||
configs: {
|
||||
...state.configs,
|
||||
[key]: defaultsToUse,
|
||||
[namespace]: defaultsToUse,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
setDefaultConfig: (
|
||||
key: string,
|
||||
configurations: ConfigurableFieldUIMetadata[],
|
||||
) => {
|
||||
const defaultConfig: Record<string, any> = {};
|
||||
configurations.forEach((config: ConfigurableFieldUIMetadata) => {
|
||||
if (config.default !== undefined) {
|
||||
defaultConfig[config.label] = config.default;
|
||||
}
|
||||
});
|
||||
|
||||
defaultConfig.__defaultValues = { ...defaultConfig };
|
||||
|
||||
set((currentState) => ({
|
||||
configs: {
|
||||
...currentState.configs,
|
||||
[key]: defaultConfig,
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
resetStore: () => set({ configs: {} }),
|
||||
}),
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue