mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-07-02 03:02:19 +08:00
Merge branch '2.0' of github.com:nocobase/nocobase into 2.0
This commit is contained in:
commit
151bc938a3
@ -14,15 +14,15 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ant-design/x": "^1.1.0",
|
"@ant-design/x": "^1.1.0",
|
||||||
"@langchain/core": "^0.3.55",
|
"@langchain/core": "^0.3.61",
|
||||||
"@langchain/deepseek": "^0.0.1",
|
"@langchain/deepseek": "^0.0.2",
|
||||||
"@langchain/openai": "^0.4.3",
|
"@langchain/openai": "^0.5.16",
|
||||||
"nodejs-snowflake": "^2.0.1",
|
"nodejs-snowflake": "^2.0.1",
|
||||||
"use-context-selector": "^2.0.0",
|
"use-context-selector": "^2.0.0",
|
||||||
"react-markdown": "^10.1.0",
|
"react-markdown": "^10.1.0",
|
||||||
"react-syntax-highlighter": "^15.6.1",
|
"react-syntax-highlighter": "^15.6.1",
|
||||||
"@langchain/google-genai": "^0.2.5",
|
"@langchain/google-genai": "^0.2.14",
|
||||||
"@langchain/anthropic": "^0.3.20",
|
"@langchain/anthropic": "^0.3.23",
|
||||||
"echarts": "^5.5.0",
|
"echarts": "^5.5.0",
|
||||||
"echarts-for-react": "3.0.2",
|
"echarts-for-react": "3.0.2",
|
||||||
"rehype-raw": "^7.0.0",
|
"rehype-raw": "^7.0.0",
|
||||||
|
@ -7,13 +7,14 @@
|
|||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// @ts-nocheck
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Button, Dropdown } from 'antd';
|
import { Button, Dropdown } from 'antd';
|
||||||
import { useT } from '../locale';
|
import { useT } from '../locale';
|
||||||
import { AppstoreAddOutlined } from '@ant-design/icons';
|
import { AppstoreAddOutlined } from '@ant-design/icons';
|
||||||
import { Schema } from '@formily/react';
|
import { Schema } from '@formily/react';
|
||||||
import { usePlugin } from '@nocobase/client';
|
import { usePlugin } from '@nocobase/client';
|
||||||
import PluginAIClient from '../';
|
import PluginAIClient from '..';
|
||||||
import { ContextItem } from './types';
|
import { ContextItem } from './types';
|
||||||
|
|
||||||
export const AddContextButton: React.FC<{
|
export const AddContextButton: React.FC<{
|
||||||
|
@ -17,7 +17,6 @@ import { UserAddOutlined, CloseCircleOutlined } from '@ant-design/icons';
|
|||||||
import { AIEmployeeListItem } from '../AIEmployeeListItem';
|
import { AIEmployeeListItem } from '../AIEmployeeListItem';
|
||||||
import { avatars } from '../avatars';
|
import { avatars } from '../avatars';
|
||||||
import { ProfileCard } from '../ProfileCard';
|
import { ProfileCard } from '../ProfileCard';
|
||||||
import { AddContextButton } from './AddContextButton';
|
|
||||||
import { AttachmentsHeader } from './AttachmentsHeader';
|
import { AttachmentsHeader } from './AttachmentsHeader';
|
||||||
import { ContextItemsHeader } from './ContextItemsHeader';
|
import { ContextItemsHeader } from './ContextItemsHeader';
|
||||||
|
|
||||||
|
@ -55,7 +55,9 @@ const layoutElements = async (nodes: Node[], edges: Edge[]) => {
|
|||||||
edges: edges,
|
edges: edges,
|
||||||
};
|
};
|
||||||
|
|
||||||
return elk
|
return (
|
||||||
|
elk
|
||||||
|
// @ts-ignore
|
||||||
.layout(graph)
|
.layout(graph)
|
||||||
.then((layoutedGraph) => ({
|
.then((layoutedGraph) => ({
|
||||||
nodes: layoutedGraph.children.map((node) => ({
|
nodes: layoutedGraph.children.map((node) => ({
|
||||||
@ -67,7 +69,8 @@ const layoutElements = async (nodes: Node[], edges: Edge[]) => {
|
|||||||
|
|
||||||
edges: layoutedGraph.edges,
|
edges: layoutedGraph.edges,
|
||||||
}))
|
}))
|
||||||
.catch(console.error);
|
.catch(console.error)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDiagramData = (collections: any[]) => {
|
const getDiagramData = (collections: any[]) => {
|
||||||
@ -226,6 +229,7 @@ export const Diagram: React.FC<{
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getDiagramData(collections)
|
getDiagramData(collections)
|
||||||
|
// @ts-ignore
|
||||||
.then(({ nodes, edges }) => {
|
.then(({ nodes, edges }) => {
|
||||||
setNodes(nodes);
|
setNodes(nodes);
|
||||||
setEdges(edges);
|
setEdges(edges);
|
||||||
|
@ -1,259 +0,0 @@
|
|||||||
/**
|
|
||||||
* This file is part of the NocoBase (R) project.
|
|
||||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
||||||
* Authors: NocoBase Team.
|
|
||||||
*
|
|
||||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export interface CollectionOptions extends Omit<SequelizeModelOptions, 'name' | 'hooks'> {
|
|
||||||
/** The unique identifier of the collection, must be unique across the database */
|
|
||||||
name: string;
|
|
||||||
/** The display title of the collection, used for UI presentation */
|
|
||||||
title?: string;
|
|
||||||
/** The description of the collection */
|
|
||||||
description?: string;
|
|
||||||
/** Whether this collection is a through table for many-to-many relationships */
|
|
||||||
isThrough?: boolean;
|
|
||||||
/** The target key(s) used for filtering operations, can be a single key or array of keys */
|
|
||||||
filterTargetKey?: string | string[];
|
|
||||||
/** Array of field definitions for the collection */
|
|
||||||
fields?: FieldOptions[];
|
|
||||||
/**
|
|
||||||
* Whether to automatically generate an 'id' field
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
autoGenId?: boolean;
|
|
||||||
/**
|
|
||||||
* Whether to automatically generate a 'createdAt' timestamp field
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
createdAt?: boolean;
|
|
||||||
/** Whether to automatically generate an 'updatedAt' timestamp field
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
updatedAt?: boolean;
|
|
||||||
/**
|
|
||||||
* Whether to automatically generate a 'createdById' field for record ownership
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
createdBy?: boolean;
|
|
||||||
/**
|
|
||||||
* Whether to automatically generate an 'updatedById' field for tracking updates
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
updatedBy?: boolean;
|
|
||||||
/** The template identifier used to create this collection */
|
|
||||||
template: 'general' | 'tree' | 'file' | 'calendar' | 'expression';
|
|
||||||
/** The field name used for tree structure functionality */
|
|
||||||
tree?: 'adjacencyList';
|
|
||||||
}
|
|
||||||
|
|
||||||
export type FieldOptions =
|
|
||||||
| BaseFieldOptions
|
|
||||||
| StringFieldOptions
|
|
||||||
| IntegerFieldOptions
|
|
||||||
| FloatFieldOptions
|
|
||||||
| DecimalFieldOptions
|
|
||||||
| DoubleFieldOptions
|
|
||||||
| JsonFieldOptions
|
|
||||||
| JsonbFieldOptions
|
|
||||||
| BooleanFieldOptions
|
|
||||||
| RadioFieldOptions
|
|
||||||
| TextFieldOptions
|
|
||||||
| TimeFieldOptions
|
|
||||||
| DateFieldOptions
|
|
||||||
| DatetimeTzFieldOptions
|
|
||||||
| DatetimeNoTzFieldOptions
|
|
||||||
| DateOnlyFieldOptions
|
|
||||||
| UnixTimestampFieldOptions
|
|
||||||
| UidFieldOptions
|
|
||||||
| UUIDFieldOptions
|
|
||||||
| NanoidFieldOptions
|
|
||||||
| PasswordFieldOptions
|
|
||||||
| BelongsToFieldOptions
|
|
||||||
| HasOneFieldOptions
|
|
||||||
| HasManyFieldOptions
|
|
||||||
| BelongsToManyFieldOptions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base options for all field types
|
|
||||||
* Provides common properties that are available to all field configurations
|
|
||||||
*/
|
|
||||||
export interface BaseFieldOptions {
|
|
||||||
/** The name of the field, used as the column name in the database */
|
|
||||||
name: string;
|
|
||||||
/** The title of the field, used for display in the UI */
|
|
||||||
title: string;
|
|
||||||
/** The description of the field */
|
|
||||||
description?: string;
|
|
||||||
/** Whether the field should be hidden from API responses and UI */
|
|
||||||
hidden?: boolean;
|
|
||||||
/** Required. The user interface component type for this field */
|
|
||||||
interface:
|
|
||||||
| 'id'
|
|
||||||
| 'input'
|
|
||||||
| 'integer'
|
|
||||||
| 'checkbox'
|
|
||||||
| 'checkboxGroup'
|
|
||||||
| 'color'
|
|
||||||
| 'createdAt'
|
|
||||||
| 'updatedAt'
|
|
||||||
| 'createdBy'
|
|
||||||
| 'updatedBy'
|
|
||||||
| 'date'
|
|
||||||
| 'datetime'
|
|
||||||
| 'datetimeNoTz'
|
|
||||||
| 'email'
|
|
||||||
| 'icon'
|
|
||||||
| 'json'
|
|
||||||
| 'markdown'
|
|
||||||
| 'multipleSelect'
|
|
||||||
| 'nanoid'
|
|
||||||
| 'number'
|
|
||||||
| 'password'
|
|
||||||
| 'percent'
|
|
||||||
| 'phone'
|
|
||||||
| 'radioGroup'
|
|
||||||
| 'richText'
|
|
||||||
| 'select'
|
|
||||||
| 'textarea'
|
|
||||||
| 'time'
|
|
||||||
| 'unixTimestamp'
|
|
||||||
| 'url'
|
|
||||||
| 'uuid'
|
|
||||||
| 'm2m'
|
|
||||||
| 'm2o'
|
|
||||||
| 'o2m'
|
|
||||||
| 'o2o';
|
|
||||||
/** enumeration options for the field, used for select/radio/checkbox interfaces */
|
|
||||||
enum?: {
|
|
||||||
label: string;
|
|
||||||
value: string | number | boolean;
|
|
||||||
}[];
|
|
||||||
/** Additional properties for extensibility */
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Base options for column-based field types
|
|
||||||
* Extends BaseFieldOptions and includes Sequelize column-specific options
|
|
||||||
* Excludes the 'type' property as it's handled by the specific field implementations
|
|
||||||
*/
|
|
||||||
export interface BaseColumnFieldOptions extends BaseFieldOptions, Omit<ModelAttributeColumnOptions, 'type'> {
|
|
||||||
/** The Sequelize data type for the column */
|
|
||||||
dataType?: DataType;
|
|
||||||
|
|
||||||
/** Index configuration for the column, can be boolean or detailed index options */
|
|
||||||
index?: boolean | ModelIndexesOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface StringFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'string';
|
|
||||||
length?: number;
|
|
||||||
trim?: boolean;
|
|
||||||
}
|
|
||||||
export interface IntegerFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'integer';
|
|
||||||
}
|
|
||||||
export interface FloatFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'float';
|
|
||||||
}
|
|
||||||
export interface DecimalFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'decimal';
|
|
||||||
precision: number;
|
|
||||||
scale: number;
|
|
||||||
}
|
|
||||||
export interface DoubleFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'double';
|
|
||||||
}
|
|
||||||
export interface JsonFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'json';
|
|
||||||
}
|
|
||||||
export interface JsonbFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'jsonb';
|
|
||||||
}
|
|
||||||
export interface BooleanFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'boolean';
|
|
||||||
}
|
|
||||||
export interface RadioFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'radio';
|
|
||||||
}
|
|
||||||
export interface TextFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'text';
|
|
||||||
length?: 'tiny' | 'medium' | 'long';
|
|
||||||
trim?: boolean;
|
|
||||||
}
|
|
||||||
export interface TimeFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'time';
|
|
||||||
}
|
|
||||||
export interface DateFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'date';
|
|
||||||
}
|
|
||||||
export interface DatetimeTzFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'datetimeTz';
|
|
||||||
}
|
|
||||||
export interface DatetimeNoTzFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'datetimeNoTz';
|
|
||||||
}
|
|
||||||
export interface DateOnlyFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'dateOnly';
|
|
||||||
}
|
|
||||||
export interface UnixTimestampFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'unixTimestamp';
|
|
||||||
}
|
|
||||||
export interface UidFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'uid';
|
|
||||||
prefix?: string;
|
|
||||||
pattern?: string;
|
|
||||||
}
|
|
||||||
export interface UUIDFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'uuid';
|
|
||||||
autoFill?: boolean;
|
|
||||||
}
|
|
||||||
export interface NanoidFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'nanoid';
|
|
||||||
size?: number;
|
|
||||||
customAlphabet?: string;
|
|
||||||
autoFill?: boolean;
|
|
||||||
}
|
|
||||||
export interface PasswordFieldOptions extends BaseColumnFieldOptions {
|
|
||||||
type: 'password';
|
|
||||||
/**
|
|
||||||
* @default 64
|
|
||||||
*/
|
|
||||||
length?: number;
|
|
||||||
/**
|
|
||||||
* @default 8
|
|
||||||
*/
|
|
||||||
randomBytesSize?: number;
|
|
||||||
}
|
|
||||||
export interface BelongsToFieldOptions extends BaseRelationFieldOptions, SequelizeBelongsToOptions {
|
|
||||||
type: 'belongsTo';
|
|
||||||
foreignKey: string;
|
|
||||||
target: string;
|
|
||||||
targetKey: string;
|
|
||||||
}
|
|
||||||
export interface HasOneFieldOptions extends BaseRelationFieldOptions, SequelizeHasOneOptions {
|
|
||||||
type: 'hasOne';
|
|
||||||
sourceKey: string;
|
|
||||||
target: string;
|
|
||||||
foreignKey: string;
|
|
||||||
}
|
|
||||||
export interface HasManyFieldOptions extends MultipleRelationFieldOptions, SequelizeHasManyOptions {
|
|
||||||
type: 'hasMany';
|
|
||||||
sourceKey: string;
|
|
||||||
target: string;
|
|
||||||
foreignKey: string;
|
|
||||||
}
|
|
||||||
export interface BelongsToManyFieldOptions
|
|
||||||
extends MultipleRelationFieldOptions,
|
|
||||||
Omit<SequelizeBelongsToManyOptions, 'through'> {
|
|
||||||
type: 'belongsToMany';
|
|
||||||
target: string;
|
|
||||||
through: string;
|
|
||||||
sourceKey: string;
|
|
||||||
foreignKey: string;
|
|
||||||
otherKey: string;
|
|
||||||
targetKey: string;
|
|
||||||
}
|
|
@ -120,7 +120,7 @@ export type ActionOptions = {
|
|||||||
|
|
||||||
export type WorkContextOptions = {
|
export type WorkContextOptions = {
|
||||||
name?: string;
|
name?: string;
|
||||||
menu: {
|
menu?: {
|
||||||
icon?: React.ReactNode;
|
icon?: React.ReactNode;
|
||||||
label?: React.ReactNode;
|
label?: React.ReactNode;
|
||||||
Component?: ComponentType<{
|
Component?: ComponentType<{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Markdown } from '../../ai-employees/chatbox/Markdown';
|
import { Markdown } from '../../ai-employees/chatbox/markdown/Markdown';
|
||||||
import { ToolCard } from '../../ai-employees/chatbox/ToolCard';
|
import { ToolCard } from '../../ai-employees/chatbox/ToolCard';
|
||||||
|
|
||||||
export const MessageRenderer: React.FC<{
|
export const MessageRenderer: React.FC<{
|
||||||
@ -41,7 +41,15 @@ export const MessageRenderer: React.FC<{
|
|||||||
gap: 16,
|
gap: 16,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{typeof content === 'string' && <Markdown markdown={content} />}
|
{typeof content === 'string' && (
|
||||||
|
<Markdown
|
||||||
|
message={{
|
||||||
|
...msg,
|
||||||
|
// @ts-ignore
|
||||||
|
content,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{msg.tool_calls?.length && <ToolCard tools={msg.tool_calls} messageId={msg.messageId} />}
|
{msg.tool_calls?.length && <ToolCard tools={msg.tool_calls} messageId={msg.messageId} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -7,4 +7,114 @@
|
|||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const defineCollections = () => {};
|
import { Context, Next } from '@nocobase/actions';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
export const defineCollections = async (ctx: Context, next: Next) => {
|
||||||
|
const { collections } = ctx.action.params.values || {};
|
||||||
|
const id = {
|
||||||
|
name: 'id',
|
||||||
|
type: 'bigInt',
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
allowNull: false,
|
||||||
|
uiSchema: {
|
||||||
|
type: 'number',
|
||||||
|
title: '{{t("ID")}}',
|
||||||
|
'x-component': 'InputNumber',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
interface: 'integer',
|
||||||
|
};
|
||||||
|
const createdAt = {
|
||||||
|
name: 'createdAt',
|
||||||
|
interface: 'createdAt',
|
||||||
|
type: 'date',
|
||||||
|
field: 'createdAt',
|
||||||
|
uiSchema: {
|
||||||
|
type: 'datetime',
|
||||||
|
title: '{{t("Created at")}}',
|
||||||
|
'x-component': 'DatePicker',
|
||||||
|
'x-component-props': {},
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const updatedAt = {
|
||||||
|
type: 'date',
|
||||||
|
field: 'updatedAt',
|
||||||
|
name: 'updatedAt',
|
||||||
|
interface: 'updatedAt',
|
||||||
|
uiSchema: {
|
||||||
|
type: 'datetime',
|
||||||
|
title: '{{t("Last updated at")}}',
|
||||||
|
'x-component': 'DatePicker',
|
||||||
|
'x-component-props': {},
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
for (const options of collections) {
|
||||||
|
if (options.name === 'users') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (options.autoGenId !== false && !options.isThrough) {
|
||||||
|
options.autoGenId = false;
|
||||||
|
options.fields.unshift(id);
|
||||||
|
}
|
||||||
|
if (options.createdAt !== false) {
|
||||||
|
options.fields.push(createdAt);
|
||||||
|
}
|
||||||
|
if (options.updatedAt !== false) {
|
||||||
|
options.fields.push(updatedAt);
|
||||||
|
}
|
||||||
|
const primaryKey = options.fields.find((field: any) => field.primaryKey);
|
||||||
|
if (!options.filterTargetKey) {
|
||||||
|
options.filterTargetKey = primaryKey?.name || 'id';
|
||||||
|
}
|
||||||
|
// omit defaultValue
|
||||||
|
options.fields = options.fields.map((field: any) => {
|
||||||
|
return _.omit(field, ['defaultValue']);
|
||||||
|
});
|
||||||
|
const transaction = await ctx.app.db.sequelize.transaction();
|
||||||
|
try {
|
||||||
|
const repo = ctx.db.getRepository('collections');
|
||||||
|
const collection = await repo.findOne({
|
||||||
|
filter: {
|
||||||
|
name: options.name,
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
if (!collection) {
|
||||||
|
const collection = await repo.create({
|
||||||
|
values: options,
|
||||||
|
transaction,
|
||||||
|
context: ctx,
|
||||||
|
});
|
||||||
|
// await collection.load({ transaction });
|
||||||
|
await transaction.commit();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
await repo.update({
|
||||||
|
filterByTk: collection.name,
|
||||||
|
values: {
|
||||||
|
...options,
|
||||||
|
fields: options.fields?.map((f: any) => {
|
||||||
|
delete f.key;
|
||||||
|
return f;
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
updateAssociationValues: ['fields'],
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
await collection.loadFields({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
await collection.load({ transaction, resetFields: true });
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (e) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
};
|
||||||
|
@ -81,7 +81,13 @@ export class AIManager {
|
|||||||
|
|
||||||
const processSchema = (schema: any) => {
|
const processSchema = (schema: any) => {
|
||||||
if (!schema) return undefined;
|
if (!schema) return undefined;
|
||||||
return schema instanceof ZodObject && raw ? zodToJsonSchema(schema) : schema;
|
try {
|
||||||
|
// Use type assertion to break the recursive type checking
|
||||||
|
return (schema as any) instanceof ZodObject && raw ? zodToJsonSchema(schema as any) : schema;
|
||||||
|
} catch (error) {
|
||||||
|
// Fallback if zodToJsonSchema fails
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (tool.type === 'group' && child) {
|
if (tool.type === 'group' && child) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user