From 7efe0b3d18f316e3f428ec9193347dc05f6269de Mon Sep 17 00:00:00 2001 From: RoyHEyono Date: Tue, 15 Jul 2025 10:44:41 -0400 Subject: [PATCH 1/8] Added Weights and Bias API Key field in settings --- chainforge/react-server/eslint.config.mjs | 96 ++++++++++++++ chainforge/react-server/package-lock.json | 119 +++++++++++++----- chainforge/react-server/package.json | 2 + .../react-server/src/GlobalSettingsModal.tsx | 8 ++ 4 files changed, 194 insertions(+), 31 deletions(-) create mode 100644 chainforge/react-server/eslint.config.mjs diff --git a/chainforge/react-server/eslint.config.mjs b/chainforge/react-server/eslint.config.mjs new file mode 100644 index 00000000..9c3ca54a --- /dev/null +++ b/chainforge/react-server/eslint.config.mjs @@ -0,0 +1,96 @@ +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import js from "@eslint/js"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default [ + { + ignores: [ + "node_modules/**/*", + "build/**/*", + "**/craco.config.js", + "src/backend/pyodide/**/*", + "src/backend/__test__/**/*", + ], + }, + ...compat.extends( + "semistandard", + "plugin:react/recommended", + "plugin:prettier/recommended", + "plugin:@typescript-eslint/recommended", + ), + { + settings: { + react: { + createClass: "createReactClass", + pragma: "React", + fragment: "Fragment", + version: "detect", + flowVersion: "0.53", + }, + + propWrapperFunctions: [ + "forbidExtraProps", + { + property: "freeze", + object: "Object", + }, + { + property: "myFavoriteWrapper", + }, + { + property: "forbidExtraProps", + exact: true, + }, + ], + + componentWrapperFunctions: [ + "observer", + { + property: "styled", + }, + { + property: "observer", + object: "Mobx", + }, + { + property: "observer", + object: "", + }, + ], + + formComponents: [ + "CustomForm", + { + name: "Form", + formAttribute: "endpoint", + }, + ], + + linkComponents: [ + "Hyperlink", + { + name: "Link", + linkAttribute: "to", + }, + ], + }, + + rules: { + semi: ["error", "always"], + camelcase: ["off"], + "react/prop-types": ["off"], + "@typescript-eslint/no-explicit-any": ["off"], + "@typescript-eslint/no-empty-function": ["off"], + "no-control-regex": ["off"], + }, + }, +]; diff --git a/chainforge/react-server/package-lock.json b/chainforge/react-server/package-lock.json index 64621179..7c569308 100644 --- a/chainforge/react-server/package-lock.json +++ b/chainforge/react-server/package-lock.json @@ -109,6 +109,8 @@ }, "devDependencies": { "@craco/craco": "^7.1.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.31.0", "@types/lodash": "^4.17.0", "@types/papaparse": "^5.3.14", "@types/react-beautiful-dnd": "^13.1.8", @@ -3625,14 +3627,15 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -3640,7 +3643,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -3650,6 +3653,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3664,17 +3668,45 @@ "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3684,6 +3716,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -3694,25 +3727,19 @@ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@eslint/js": { + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz", + "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==", + "dev": true, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "url": "https://eslint.org/donate" } }, "node_modules/@floating-ui/core": { @@ -7707,9 +7734,9 @@ "integrity": "sha512-wkJp+Wz8MRHtCVdt65L/jPFLAQ0iqJZ2EeD2XWOvKGbIi4mZNwHlpHRLRB8ZnQ07VoiB0TLFWwIjjm2FL9gUcQ==" }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "bin": { "acorn": "bin/acorn" }, @@ -12218,6 +12245,36 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/eslint/node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", diff --git a/chainforge/react-server/package.json b/chainforge/react-server/package.json index 229a6768..71a63695 100644 --- a/chainforge/react-server/package.json +++ b/chainforge/react-server/package.json @@ -135,6 +135,8 @@ }, "devDependencies": { "@craco/craco": "^7.1.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.31.0", "@types/lodash": "^4.17.0", "@types/papaparse": "^5.3.14", "@types/react-beautiful-dnd": "^13.1.8", diff --git a/chainforge/react-server/src/GlobalSettingsModal.tsx b/chainforge/react-server/src/GlobalSettingsModal.tsx index 3ad75656..0ac6d070 100644 --- a/chainforge/react-server/src/GlobalSettingsModal.tsx +++ b/chainforge/react-server/src/GlobalSettingsModal.tsx @@ -204,6 +204,7 @@ const GlobalSettingsModal = forwardRef( AWS_Region: "us-east-1", AmazonBedrock: JSON.stringify({ credentials: {}, region: "us-east-1" }), Together: "", + WandB: "", // Added Weights & Biases API key }, validate: { @@ -562,6 +563,13 @@ const GlobalSettingsModal = forwardRef( />
+ +
+ {IS_RUNNING_LOCALLY && ( <> Date: Tue, 15 Jul 2025 12:13:46 -0400 Subject: [PATCH 2/8] Added dropdown on the Export button --- chainforge/react-server/src/App.tsx | 55 +++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/chainforge/react-server/src/App.tsx b/chainforge/react-server/src/App.tsx index ffb2dbde..5252f1fe 100644 --- a/chainforge/react-server/src/App.tsx +++ b/chainforge/react-server/src/App.tsx @@ -24,6 +24,7 @@ import { Tooltip, Flex, useMantineColorScheme, + Menu, } from "@mantine/core"; import { useClipboard } from "@mantine/hooks"; import { useContextMenu } from "mantine-contextmenu"; @@ -226,6 +227,8 @@ const nodeEmojis = { join: , split: , media: "📺", + exportCforge: "💾", + exportWandB: "📊", }; const edgeTypes = { @@ -330,6 +333,26 @@ const App = () => { // Context menu for "Add Node +" list const { hideContextMenu } = useContextMenu(); + const exportMenuItems = useMemo(() => { + // All initial nodes available in ChainForge + const initNodes = [ + { + key: "cforge", + title: ".cforge File", + icon: nodeEmojis.exportCforge, + tooltip: "Export to .cforge file", + onClick: () => exportFlow(), + }, + { + key: "wandb", + title: "Weave W&B", + icon: nodeEmojis.exportWandB, + tooltip: "Export to weights and biases weave platform", + onClick: () => handleExportToWandB(), + }, + ] as NestedMenuItemProps[]; + return initNodes; + }, []); // Add Nodes list const addNodesMenuItems = useMemo(() => { // All initial nodes available in ChainForge @@ -1477,6 +1500,12 @@ const App = () => { ); }, [flowFileName, importFlowFromJSON, showAlert, setFlowFileNameAndCache]); + // Export to Weights & Biases handler (stub for now) + const handleExportToWandB = useCallback(() => { + // TODO: Implement actual export logic to Weights & Biases + alert("Export to Weights & Biases is not yet implemented."); + }, []); + if (!IS_ACCEPTED_BROWSER) { return ( @@ -1562,17 +1591,21 @@ const App = () => { )} /> - + ( + + )} + />