diff --git a/drizzle-templates/0010_tranquil_squirrel_girl.sql b/drizzle-templates/0010_tranquil_squirrel_girl.sql new file mode 100644 index 00000000..b6998ecb --- /dev/null +++ b/drizzle-templates/0010_tranquil_squirrel_girl.sql @@ -0,0 +1,2 @@ +ALTER TABLE `agents` ADD `llmProvider` text;--> statement-breakpoint +ALTER TABLE `agents` ADD `llmModel` text; \ No newline at end of file diff --git a/drizzle-templates/meta/0010_snapshot.json b/drizzle-templates/meta/0010_snapshot.json new file mode 100644 index 00000000..101d616f --- /dev/null +++ b/drizzle-templates/meta/0010_snapshot.json @@ -0,0 +1,182 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "72edd5be-dee7-4479-9081-c6dcb39e81db", + "prevId": "32dafa3e-fb56-4423-b94d-875ae02b80db", + "tables": { + "agents": { + "name": "agents", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "displayName": { + "name": "displayName", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "events": { + "name": "events", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tools": { + "name": "tools", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "prompt": { + "name": "prompt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "flows": { + "name": "flows", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "published": { + "name": "published", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "defaultFlow": { + "name": "defaultFlow", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "inputs": { + "name": "inputs", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "agents": { + "name": "agents", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expectedResult": { + "name": "expectedResult", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "safetyRules": { + "name": "safetyRules", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "locale": { + "name": "locale", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "agentType": { + "name": "agentType", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "llmProvider": { + "name": "llmProvider", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "llmModel": { + "name": "llmModel", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updatedAt": { + "name": "updatedAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "extra": { + "name": "extra", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/drizzle-templates/meta/_journal.json b/drizzle-templates/meta/_journal.json index 4050c6b4..e03eccd9 100644 --- a/drizzle-templates/meta/_journal.json +++ b/drizzle-templates/meta/_journal.json @@ -71,6 +71,13 @@ "when": 1741281961082, "tag": "0009_worried_lockheed", "breakpoints": true + }, + { + "idx": 10, + "version": "6", + "when": 1745831549017, + "tag": "0010_tranquil_squirrel_girl", + "breakpoints": true } ] } \ No newline at end of file diff --git a/drizzle/meta/0023_snapshot.json b/drizzle/meta/0023_snapshot.json new file mode 100644 index 00000000..7b92b009 --- /dev/null +++ b/drizzle/meta/0023_snapshot.json @@ -0,0 +1,796 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "1fb6f1af-220d-43a4-8723-7cddfddae4ba", + "prevId": "435aa0a1-c1dc-45cd-8dc8-d77f248d4e3c", + "tables": { + "agents": { + "name": "agents", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "displayName": { + "name": "displayName", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "events": { + "name": "events", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tools": { + "name": "tools", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "prompt": { + "name": "prompt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "flows": { + "name": "flows", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "published": { + "name": "published", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "defaultFlow": { + "name": "defaultFlow", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "inputs": { + "name": "inputs", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "agents": { + "name": "agents", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expectedResult": { + "name": "expectedResult", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "safetyRules": { + "name": "safetyRules", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "locale": { + "name": "locale", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "agentType": { + "name": "agentType", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "llmProvider": { + "name": "llmProvider", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "llmModel": { + "name": "llmModel", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updatedAt": { + "name": "updatedAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "extra": { + "name": "extra", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "attachments": { + "name": "attachments", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "displayName": { + "name": "displayName", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "safeNameIdentifier": { + "name": "safeNameIdentifier", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "mimeType": { + "name": "mimeType", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "assignedTo": { + "name": "assignedTo", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "json": { + "name": "json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "extra": { + "name": "extra", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "storageKey": { + "name": "storageKey", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updatedAt": { + "name": "updatedAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "calendarEvents": { + "name": "calendarEvents", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "start": { + "name": "start", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "end": { + "name": "end", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "exclusive": { + "name": "exclusive", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "agentId": { + "name": "agentId", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "participants": { + "name": "participants", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updatedAt": { + "name": "updatedAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "sessionId": { + "name": "sessionId", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "calendarEvents_agentId_agents_id_fk": { + "name": "calendarEvents_agentId_agents_id_fk", + "tableFrom": "calendarEvents", + "tableTo": "agents", + "columnsFrom": [ + "agentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "config": { + "name": "config", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updatedAt": { + "name": "updatedAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "keys": { + "name": "keys", + "columns": { + "keyLocatorHash": { + "name": "keyLocatorHash", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "displayName": { + "name": "displayName", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "databaseIdHash": { + "name": "databaseIdHash", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "keyHash": { + "name": "keyHash", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "keyHashParams": { + "name": "keyHashParams", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "encryptedMasterKey": { + "name": "encryptedMasterKey", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "acl": { + "name": "acl", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "extra": { + "name": "extra", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expiryDate": { + "name": "expiryDate", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updatedAt": { + "name": "updatedAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "results": { + "name": "results", + "columns": { + "agentId": { + "name": "agentId", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sessionId": { + "name": "sessionId", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "userName": { + "name": "userName", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "userEmail": { + "name": "userEmail", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "format": { + "name": "format", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updatedAt": { + "name": "updatedAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "finalizedAt": { + "name": "finalizedAt", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "results_agentId_agents_id_fk": { + "name": "results_agentId_agents_id_fk", + "tableFrom": "results", + "tableTo": "agents", + "columnsFrom": [ + "agentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "results_sessionId_sessions_id_fk": { + "name": "results_sessionId_sessions_id_fk", + "tableFrom": "results", + "tableTo": "sessions", + "columnsFrom": [ + "sessionId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "sessions": { + "name": "sessions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "agentId": { + "name": "agentId", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "userName": { + "name": "userName", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "userEmail": { + "name": "userEmail", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "acceptTerms": { + "name": "acceptTerms", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "completionTokens": { + "name": "completionTokens", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "promptTokens": { + "name": "promptTokens", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "messages": { + "name": "messages", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updatedAt": { + "name": "updatedAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "finalizedAt": { + "name": "finalizedAt", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_agentId_agents_id_fk": { + "name": "sessions_agentId_agents_id_fk", + "tableFrom": "sessions", + "tableTo": "agents", + "columnsFrom": [ + "agentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "terms": { + "name": "terms", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "signature": { + "name": "signature", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ua": { + "name": "ua", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "signedAt": { + "name": "signedAt", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/src/app/[locale]/admin/agent/[id]/general/page.tsx b/src/app/[locale]/admin/agent/[id]/general/page.tsx index 20a9bb01..8d68cccc 100644 --- a/src/app/[locale]/admin/agent/[id]/general/page.tsx +++ b/src/app/[locale]/admin/agent/[id]/general/page.tsx @@ -1,32 +1,51 @@ -'use client' -import { Input } from '@/components/ui/input'; -import { Textarea } from '@/components/ui/textarea'; -import { Button } from '@/components/ui/button'; -import { useTranslation } from 'react-i18next'; -import { useAgentContext } from '@/contexts/agent-context'; -import { use, useContext, useEffect, useState } from 'react'; -import { FormProvider, useForm, UseFormGetValues, UseFormSetValue, UseFormWatch } from 'react-hook-form'; -import { Agent } from '@/data/client/models'; -import { toast } from 'sonner'; -import { useParams, useRouter } from 'next/navigation'; -import { sha256 } from '@/lib/crypto'; -import { TFunction } from 'i18next'; -import { AgentStatus } from '@/components/layout/agent-status'; -import { MarkdownEditor } from '@/components/markdown-editor'; -import React from 'react'; -import { MDXEditorMethods } from '@mdxeditor/editor'; -import { LocaleSelect } from '@/components/locale-select'; -import { AgentTypeSelect } from '@/components/agent-type-select'; -import { SaveAgentAsTemplateButton } from '@/components/save-agent-as-template-button'; -import DataLoader from '@/components/data-loader'; -import { InfoIcon, TrashIcon } from 'lucide-react'; -import { AgentTypeDescriptor, agentTypesRegistry } from '@/agent-types/registry'; -import { AttachmentUploader } from '@/components/attachment-uploader'; -import { DatabaseContext } from '@/contexts/db-context'; -import { SaaSContext } from '@/contexts/saas-context'; -import ZoomableImage from '@/components/zoomable-image'; - -export function onAgentSubmit(agent: Agent | null, watch: UseFormWatch>, setValue: UseFormSetValue>, getValues: UseFormGetValues>, updateAgent: (agent: Agent, setAsCurrent: boolean) => Promise, t: TFunction<"translation", undefined>, router: any, editors: Record>) { +"use client"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Button } from "@/components/ui/button"; +import { useTranslation } from "react-i18next"; +import { useAgentContext } from "@/contexts/agent-context"; +import { use, useContext, useEffect, useState } from "react"; +import { + FormProvider, + useForm, + UseFormGetValues, + UseFormSetValue, + UseFormWatch, +} from "react-hook-form"; +import { Agent } from "@/data/client/models"; +import { toast } from "sonner"; +import { useParams, useRouter } from "next/navigation"; +import { sha256 } from "@/lib/crypto"; +import { TFunction } from "i18next"; +import { AgentStatus } from "@/components/layout/agent-status"; +import { MarkdownEditor } from "@/components/markdown-editor"; +import React from "react"; +import { MDXEditorMethods } from "@mdxeditor/editor"; +import { LocaleSelect } from "@/components/locale-select"; +import { AgentTypeSelect } from "@/components/agent-type-select"; +import { SaveAgentAsTemplateButton } from "@/components/save-agent-as-template-button"; +import DataLoader from "@/components/data-loader"; +import { InfoIcon, TrashIcon } from "lucide-react"; +import { + AgentTypeDescriptor, + agentTypesRegistry, +} from "@/agent-types/registry"; +import { AttachmentUploader } from "@/components/attachment-uploader"; +import { DatabaseContext } from "@/contexts/db-context"; +import { SaaSContext } from "@/contexts/saas-context"; +import ZoomableImage from "@/components/zoomable-image"; +import { LLMConfigSelect } from "@/components/llm-config-select"; + +export function onAgentSubmit( + agent: Agent | null, + watch: UseFormWatch>, + setValue: UseFormSetValue>, + getValues: UseFormGetValues>, + updateAgent: (agent: Agent, setAsCurrent: boolean) => Promise, + t: TFunction<"translation", undefined>, + router: any, + editors: Record> +) { // eslint-disable-next-line const [isDirty, setIsDirty] = useState(false); // eslint-disable-next-line @@ -34,46 +53,70 @@ export function onAgentSubmit(agent: Agent | null, watch: UseFormWatch void } | null>(null); + const watchSubscription = React.useRef<{ unsubscribe: () => void } | null>( + null + ); // eslint-disable-next-line useEffect(() => { - if (agentContext.agents && agentContext.agents.length > 0 && !agent && params.id) { // agent does not exist, but id is provided + if ( + agentContext.agents && + agentContext.agents.length > 0 && + !agent && + params.id + ) { + // agent does not exist, but id is provided router.push(`/admin/agent/new/general`); } }, [agentContext.agents]); // eslint-disable-next-line useEffect(() => { - if (agent && agent.id === params.id) { // bind the tracking changes only for the currently selected agent + if (agent && agent.id === params.id) { + // bind the tracking changes only for the currently selected agent //agent.toForm(setValue); // load the database values - const dirtyCheck = (async (originalRecord: Record, value: Record) => { - const compareForms = async (editableForm: Record, savedForm: Record) => { - const sortedSavedState: Record = {} - const sortedEditableState = Object.keys(editableForm).sort().reduce((acc: Record, key: string) => { - acc[key] = editableForm[key]; - sortedSavedState[key] = savedForm[key]; - return acc; - }, {}); - - const editableEntriesString = Object.entries(sortedEditableState).map(([key, value]) => `${key}:${JSON.stringify(value)}`).join(','); - const savedEntriesString = Object.entries(sortedSavedState).map(([key, value]) => `${key}:${JSON.stringify(value)}`).join(','); + const dirtyCheck = async ( + originalRecord: Record, + value: Record + ) => { + const compareForms = async ( + editableForm: Record, + savedForm: Record + ) => { + const sortedSavedState: Record = {}; + const sortedEditableState = Object.keys(editableForm) + .sort() + .reduce((acc: Record, key: string) => { + acc[key] = editableForm[key]; + sortedSavedState[key] = savedForm[key]; + return acc; + }, {}); + + const editableEntriesString = Object.entries(sortedEditableState) + .map(([key, value]) => `${key}:${JSON.stringify(value)}`) + .join(","); + const savedEntriesString = Object.entries(sortedSavedState) + .map(([key, value]) => `${key}:${JSON.stringify(value)}`) + .join(","); const [editableEntriesHash, savedEntriesHash] = await Promise.all([ - sha256(editableEntriesString, ''), - sha256(savedEntriesString, '') + sha256(editableEntriesString, ""), + sha256(savedEntriesString, ""), ]); return editableEntriesHash === savedEntriesHash; }; - const formChanged = !await compareForms(getValues(), originalRecord); + const formChanged = !(await compareForms(getValues(), originalRecord)); if (formChanged) { - sessionStorage.setItem(`agent-${value['id']}`, JSON.stringify(getValues())); // save form values + sessionStorage.setItem( + `agent-${value["id"]}`, + JSON.stringify(getValues()) + ); // save form values } else { - sessionStorage.removeItem(`agent-${value['id']}`); + sessionStorage.removeItem(`agent-${value["id"]}`); } setIsDirty(formChanged); - }) + }; const subscribeChanges = (originalRecord: Record) => { // if there is already an active watcher – remove it before creating a new one @@ -81,11 +124,15 @@ export function onAgentSubmit(agent: Agent | null, watch: UseFormWatch { - agentContext.setDirtyAgent(Agent.fromForm(getValues(), agentContext.current)); + agentContext.setDirtyAgent( + Agent.fromForm(getValues(), agentContext.current) + ); dirtyCheck(originalRecord, value); }); @@ -96,7 +143,8 @@ export function onAgentSubmit(agent: Agent | null, watch: UseFormWatch { setValue(key, parsedState[key]); @@ -106,36 +154,44 @@ export function onAgentSubmit(agent: Agent | null, watch: UseFormWatch { - if (editors && editors.hasOwnProperty(field) && editors[field].current) { + if ( + editors && + editors.hasOwnProperty(field) && + editors[field].current + ) { editors[field].current?.setMarkdown(value); } setValue(field, value); - }) + }); } subscribeChanges(agent.toForm(null)); - } }, [agent]); const onSubmit = async (data: Record) => { - - const newAgent = agent?.id === 'new'; + const newAgent = agent?.id === "new"; const updatedAgent = Agent.fromForm(data, agent); - const agentTypeDescriptor = agentTypesRegistry.find(at => at.type === updatedAgent.agentType); + const agentTypeDescriptor = agentTypesRegistry.find( + (at) => at.type === updatedAgent.agentType + ); if (agentTypeDescriptor) { for (const requiredField of agentTypeDescriptor.requiredTabs) { const valToCheck = updatedAgent.toForm()[requiredField]; - if (!valToCheck || (Array.isArray(valToCheck) && valToCheck.length === 0)) { - router.push(`/admin/agent/${updatedAgent.id}/${requiredField.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`)}`); - toast.error(t('Field ') + t(requiredField) + t(' is required')); + if ( + !valToCheck || + (Array.isArray(valToCheck) && valToCheck.length === 0) + ) { + router.push( + `/admin/agent/${updatedAgent.id}/${requiredField.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)}` + ); + toast.error(t("Field ") + t(requiredField) + t(" is required")); agentContext.setStatus({ - id: requiredField + '-required', - message: t('Field ') + t(requiredField) + t(' is required'), - type: 'error' + id: requiredField + "-required", + message: t("Field ") + t(requiredField) + t(" is required"), + type: "error", }); return; - } } } @@ -145,85 +201,116 @@ export function onAgentSubmit(agent: Agent | null, watch: UseFormWatch({}); + const { + setStatus, + status, + removeStatus, + current: agent, + updateAgent, + loaderStatus, + } = useAgentContext(); + const [agentDescriptor, setAgentDescriptor] = useState( + {} + ); const dbContext = useContext(DatabaseContext); const saasContext = useContext(SaaSContext); const methods = useForm({ defaultValues: agent ? agent.toForm(null) : {}, }); - const { register, handleSubmit, setValue, getValues, formState: { errors }, watch } = methods; + const { + register, + handleSubmit, + setValue, + getValues, + formState: { errors }, + watch, + } = methods; const editors = { welcomeInfo: React.useRef(null), - termsConditions: React.useRef(null) - } - register('icon'); - register('welcomeInfo'); - register('termsConditions', { + termsConditions: React.useRef(null), + }; + register("icon"); + register("welcomeInfo"); + register("termsConditions", { validate: { - termsConditions: (v) => (getValues('confirmTerms') === true && !v) ? false : true - } + termsConditions: (v) => + getValues("confirmTerms") === true && !v ? false : true, + }, }); - const { onSubmit, isDirty } = onAgentSubmit(agent, watch, setValue, getValues, updateAgent, t, router, editors); + const { onSubmit, isDirty } = onAgentSubmit( + agent, + watch, + setValue, + getValues, + updateAgent, + t, + router, + editors + ); - const agentTypeValue = watch('agentType'); + const agentTypeValue = watch("agentType"); useEffect(() => { if (agentTypeValue) { - const agentTypeDescriptor = agentTypesRegistry.find(at => at.type === agentTypeValue); - if (agentDescriptor) setAgentDescriptor(agentTypeDescriptor as AgentTypeDescriptor); + const agentTypeDescriptor = agentTypesRegistry.find( + (at) => at.type === agentTypeValue + ); + if (agentDescriptor) + setAgentDescriptor(agentTypeDescriptor as AgentTypeDescriptor); } }, [agentTypeValue]); - useEffect(() => { if (isDirty) { - setStatus({ id: 'dirty', message: t('You have unsaved changes'), type: 'warning' }); + setStatus({ + id: "dirty", + message: t("You have unsaved changes"), + type: "warning", + }); } else { - removeStatus('dirty'); + removeStatus("dirty"); } }, [isDirty]); return (
- {loaderStatus === 'loading' ? ( - + {loaderStatus === "loading" ? (
- - ) : (null)} + ) : null} {isDirty ? ( - + ) : ( )} @@ -231,107 +318,177 @@ export default function GeneralPage() {
- + - {errors.displayName &&

{errors.displayName.message}

} + {errors.displayName && ( +

+ {errors.displayName.message} +

+ )}
- +
+
- setValue('welcomeInfo', e)} diffMarkdown={agent?.options?.welcomeMessage ?? ''} /> - {errors.welcomeInfo &&

{errors.welcomeInfo.message}

} + setValue("welcomeInfo", e)} + diffMarkdown={agent?.options?.welcomeMessage ?? ""} + /> + {errors.welcomeInfo && ( +

+ {errors.welcomeInfo.message} +

+ )}
{agentDescriptor?.supportsUserFacingUI && (
-
)} {agentDescriptor?.supportsUserFacingUI && (
-
-
{t('Important note on GDPR and Terms: ')} {t('if your agent is about to process the personal data of the users, you SHOULD provide the terms and conditions and ask for the user consent. If you offer a commerce service you SHOULD also apply the Consumer Laws and provide the user with the right to return the product.')} +
+ +
+
+ {t("Important note on GDPR and Terms: ")}{" "} + {t( + "if your agent is about to process the personal data of the users, you SHOULD provide the terms and conditions and ask for the user consent. If you offer a commerce service you SHOULD also apply the Consumer Laws and provide the user with the right to return the product." + )}
)} {agentDescriptor?.supportsUserFacingUI && (
-
)} {agentDescriptor?.supportsUserFacingUI && (
-
)} {agentDescriptor?.supportsUserFacingUI && (
-
)} {agentDescriptor?.supportsUserFacingUI && (
- +
)} - {agentDescriptor?.supportsUserFacingUI && (
@@ -339,12 +496,15 @@ export default function GeneralPage() { {agentDescriptor?.supportsUserFacingUI && (
-