mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-29 06:38:50 +01:00
🚧 chore: merge latest dev build to main repo (#3844)
* agents - phase 1 (#30) * chore: copy assistant files * feat: frontend and data-provider * feat: backend get endpoint test * fix(MessageEndpointIcon): switched to AgentName and AgentAvatar * fix: small fixes * fix: agent endpoint config * fix: show Agent Builder * chore: install agentus * chore: initial scaffolding for agents * fix: updated Assistant logic to Agent Logic for some Agent components * WIP first pass, demo of agent package * WIP: initial backend infra for agents * fix: agent list error * wip: agents routing * chore: Refactor useSSE hook to handle different data events * wip: correctly emit events * chore: Update @librechat/agentus npm dependency to version 1.0.9 * remove comment * first pass: streaming agent text * chore: Remove @librechat/agentus root-level workspace npm dependency * feat: Agent Schema and Model * fix: content handling fixes * fix: content message save * WIP: new content data * fix: run step issue with tool calls * chore: Update @librechat/agentus npm dependency to version 1.1.5 * feat: update controller and agent routes * wip: initial backend tool and tool error handling support * wip: tool chunks * chore: Update @librechat/agentus npm dependency to version 1.1.7 * chore: update tool_call typing, add test conditions and logs * fix: create agent * fix: create agent * first pass: render completed content parts * fix: remove logging, fix step handler typing * chore: Update @librechat/agentus npm dependency to version 1.1.9 * refactor: cleanup maps on unmount * chore: Update BaseClient.js to safely count tokens for string, number, and boolean values * fix: support subsequent messages with tool_calls * chore: export order * fix: select agent * fix: tool call types and handling * chore: switch to anthropic for testing * fix: AgentSelect * refactor: experimental: OpenAIClient to use array for intermediateReply * fix(useSSE): revert old condition for streaming legacy client tokens * fix: lint * revert `agent_id` to `id` * chore: update localization keys for agent-related components * feat: zod schema handling for actions * refactor(actions): if no params, no zodSchema * chore: Update @librechat/agentus npm dependency to version 1.2.1 * feat: first pass, actions * refactor: empty schema for actions without params * feat: Update createRun function to accept additional options * fix: message payload formatting; feat: add more client options * fix: ToolCall component rendering when action has no args but has output * refactor(ToolCall): allow non-stringy args * WIP: first pass, correctly formatted tool_calls between providers * refactor: Remove duplicate import of 'roles' module * refactor: Exclude 'vite.config.ts' from TypeScript compilation * refactor: fix agent related types > - no need to use endpoint/model fields for identifying agent metadata > - add `provider` distinction for agent-configured 'endpoint' - no need for agent-endpoint map - reduce complexity of tools as functions into tools as string[] - fix types related to above changes - reduce unnecessary variables for queries/mutations and corresponding react-query keys * refactor: Add tools and tool_kwargs fields to agent schema * refactor: Remove unused code and update dependencies * refactor: Update updateAgentHandler to use req.body directly * refactor: Update AgentSelect component to use localized hooks * refactor: Update agent schema to include tools and provider fields * refactor(AgentPanel): add scrollbar gutter, add provider field to form, fix agent schema required values * refactor: Update AgentSwitcher component to use selectedAgentId instead of selectedAgent * refactor: Update AgentPanel component to include alternateName import and defaultAgentFormValues * refactor(SelectDropDown): allow setting value as option while still supporting legacy usage (string values only) * refactor: SelectDropdown changes - Only necessary when the available values are objects with label/value fields and the selected value is expected to be a string. * refactor: TypeError issues and handle provider as option * feat: Add placeholder for provider selection in AgentPanel component * refactor: Update agent schema to include author and provider fields * fix: show expected 'create agent' placeholder when creating agent * chore: fix localization strings, hide capabilities form for now * chore: typing * refactor: import order and use compact agents schema for now * chore: typing * refactor: Update AgentForm type to use AgentCapabilities * fix agent form agent selection issues * feat: responsive agent selection * fix: Handle cancelled fetch in useSelectAgent hook * fix: reset agent form on accordion close/open * feat: Add agent_id to default conversation for agents endpoint * feat: agents endpoint request handling * refactor: reset conversation model on agent select * refactor: add `additional_instructions` to conversation schema, organize other fields * chore: casing * chore: types * refactor(loadAgentTools): explicitly pass agent_id, do not pass `model` to loadAgentTools for now, load action sets by agent_id * WIP: initial draft of real agent client initialization * WIP: first pass, anthropic agent requests * feat: remember last selected agent * feat: openai and azure connected * fix: prioritize agent model for runs unless an explicit override model is passed from client * feat: Agent Actions * fix: save agent id to convo * feat: model panel (#29) * feat: model panel * bring back comments * fix: method still null * fix: AgentPanel FormContext * feat: add more parameters * fix: style issues; refactor: Agent Controller * fix: cherry-pick * fix: Update AgentAvatar component to use AssistantIcon instead of BrainCircuit * feat: OGDialog for delete agent; feat(assistant): update Agent types, introduced `model_parameters` * feat: icon and general `model_parameters` update * feat: use react-hook-form better * fix: agent builder form reset issue when switching panels * refactor: modularize agent builder form --------- Co-authored-by: Danny Avila <danny@librechat.ai> * fix: AgentPanel and ModelPanel type issues and use `useFormContext` and `watch` instead of `methods` directly and `useWatch`. * fix: tool call issues due to invalid input (anthropic) of empty string * fix: handle empty text in Part component --------- Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com> * refactor: remove form ModelPanel and fixed nested ternary expressions in AgentConfig * fix: Model Parameters not saved correctly * refactor: remove console log * feat: avatar upload and get for Agents (#36) Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com> * chore: update to public package * fix: typing, optional chaining * fix: cursor not showing for content parts * chore: conditionally enable agents * ci: fix azure test * ci: fix frontend tests, fix eslint api * refactor: Remove unused errorContentPart variable * continue of the agent message PR (#40) * last fixes * fix: agentMap * pr merge test (#41) * fix: model icon not fetching correctly * remove console logs * feat: agent name * refactor: pass documentsMap as a prop to allow re-render of assistant form * refactor: pass documentsMap as a prop to allow re-render of assistant form * chore: Bump version to 0.7.419 * fix: TypeError: Cannot read properties of undefined (reading 'id') * refactor: update AgentSwitcher component to use ControlCombobox instead of Combobox --------- Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
This commit is contained in:
parent
618be4bf2b
commit
a0291ed155
141 changed files with 14473 additions and 5714 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "librechat-data-provider",
|
||||
"version": "0.7.418",
|
||||
"version": "0.7.419",
|
||||
"description": "data services for librechat apps",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.es.js",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import axios from 'axios';
|
||||
import { z } from 'zod';
|
||||
import { OpenAPIV3 } from 'openapi-types';
|
||||
import {
|
||||
createURL,
|
||||
|
|
@ -8,7 +9,12 @@ import {
|
|||
FunctionSignature,
|
||||
validateAndParseOpenAPISpec,
|
||||
} from '../src/actions';
|
||||
import { getWeatherOpenapiSpec, whimsicalOpenapiSpec, scholarAIOpenapiSpec } from './openapiSpecs';
|
||||
import {
|
||||
getWeatherOpenapiSpec,
|
||||
whimsicalOpenapiSpec,
|
||||
scholarAIOpenapiSpec,
|
||||
swapidev,
|
||||
} from './openapiSpecs';
|
||||
import { AuthorizationTypeEnum, AuthTypeEnum } from '../src/types/assistants';
|
||||
import type { FlowchartSchema } from './openapiSpecs';
|
||||
import type { ParametersSchema } from '../src/actions';
|
||||
|
|
@ -548,4 +554,273 @@ describe('createURL', () => {
|
|||
'https://example.com/subdirectory/api/v1/users',
|
||||
);
|
||||
});
|
||||
|
||||
describe('openapiToFunction zodSchemas', () => {
|
||||
describe('getWeatherOpenapiSpec', () => {
|
||||
const { zodSchemas } = openapiToFunction(getWeatherOpenapiSpec, true);
|
||||
|
||||
it('generates correct Zod schema for GetCurrentWeather', () => {
|
||||
expect(zodSchemas).toBeDefined();
|
||||
expect(zodSchemas?.GetCurrentWeather).toBeDefined();
|
||||
|
||||
const GetCurrentWeatherSchema = zodSchemas?.GetCurrentWeather;
|
||||
|
||||
expect(GetCurrentWeatherSchema instanceof z.ZodObject).toBe(true);
|
||||
|
||||
if (!(GetCurrentWeatherSchema instanceof z.ZodObject)) {
|
||||
throw new Error('GetCurrentWeatherSchema is not a ZodObject');
|
||||
}
|
||||
|
||||
const shape = GetCurrentWeatherSchema.shape;
|
||||
expect(shape.location instanceof z.ZodString).toBe(true);
|
||||
|
||||
// Check locations property
|
||||
expect(shape.locations).toBeDefined();
|
||||
expect(shape.locations instanceof z.ZodOptional).toBe(true);
|
||||
|
||||
if (!(shape.locations instanceof z.ZodOptional)) {
|
||||
throw new Error('locations is not a ZodOptional');
|
||||
}
|
||||
|
||||
const locationsInnerType = shape.locations._def.innerType;
|
||||
expect(locationsInnerType instanceof z.ZodArray).toBe(true);
|
||||
|
||||
if (!(locationsInnerType instanceof z.ZodArray)) {
|
||||
throw new Error('locationsInnerType is not a ZodArray');
|
||||
}
|
||||
|
||||
const locationsItemSchema = locationsInnerType.element;
|
||||
expect(locationsItemSchema instanceof z.ZodObject).toBe(true);
|
||||
|
||||
if (!(locationsItemSchema instanceof z.ZodObject)) {
|
||||
throw new Error('locationsItemSchema is not a ZodObject');
|
||||
}
|
||||
|
||||
// Validate the structure of locationsItemSchema
|
||||
expect(locationsItemSchema.shape.city instanceof z.ZodString).toBe(true);
|
||||
expect(locationsItemSchema.shape.state instanceof z.ZodString).toBe(true);
|
||||
expect(locationsItemSchema.shape.countryCode instanceof z.ZodString).toBe(true);
|
||||
|
||||
// Check if time is optional
|
||||
const timeSchema = locationsItemSchema.shape.time;
|
||||
expect(timeSchema instanceof z.ZodOptional).toBe(true);
|
||||
|
||||
if (!(timeSchema instanceof z.ZodOptional)) {
|
||||
throw new Error('timeSchema is not a ZodOptional');
|
||||
}
|
||||
|
||||
expect(timeSchema._def.innerType instanceof z.ZodString).toBe(true);
|
||||
|
||||
// Check the description
|
||||
expect(shape.locations._def.description).toBe(
|
||||
'A list of locations to retrieve the weather for.',
|
||||
);
|
||||
});
|
||||
|
||||
it('validates correct data for GetCurrentWeather', () => {
|
||||
const GetCurrentWeatherSchema = zodSchemas?.GetCurrentWeather as z.ZodTypeAny;
|
||||
const validData = {
|
||||
location: 'New York',
|
||||
locations: [
|
||||
{ city: 'New York', state: 'NY', countryCode: 'US', time: '2023-12-04T14:00:00Z' },
|
||||
],
|
||||
};
|
||||
expect(() => GetCurrentWeatherSchema.parse(validData)).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws error for invalid data for GetCurrentWeather', () => {
|
||||
const GetCurrentWeatherSchema = zodSchemas?.GetCurrentWeather as z.ZodTypeAny;
|
||||
const invalidData = {
|
||||
location: 123,
|
||||
locations: [{ city: 'New York', state: 'NY', countryCode: 'US', time: 'invalid-time' }],
|
||||
};
|
||||
expect(() => GetCurrentWeatherSchema.parse(invalidData)).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('whimsicalOpenapiSpec', () => {
|
||||
const { zodSchemas } = openapiToFunction(whimsicalOpenapiSpec, true);
|
||||
|
||||
it('generates correct Zod schema for postRenderFlowchart', () => {
|
||||
expect(zodSchemas).toBeDefined();
|
||||
expect(zodSchemas?.postRenderFlowchart).toBeDefined();
|
||||
|
||||
const PostRenderFlowchartSchema = zodSchemas?.postRenderFlowchart;
|
||||
expect(PostRenderFlowchartSchema).toBeInstanceOf(z.ZodObject);
|
||||
|
||||
if (!(PostRenderFlowchartSchema instanceof z.ZodObject)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shape = PostRenderFlowchartSchema.shape;
|
||||
expect(shape.mermaid).toBeInstanceOf(z.ZodString);
|
||||
expect(shape.title).toBeInstanceOf(z.ZodOptional);
|
||||
expect((shape.title as z.ZodOptional<z.ZodString>)._def.innerType).toBeInstanceOf(
|
||||
z.ZodString,
|
||||
);
|
||||
});
|
||||
|
||||
it('validates correct data for postRenderFlowchart', () => {
|
||||
const PostRenderFlowchartSchema = zodSchemas?.postRenderFlowchart;
|
||||
const validData = {
|
||||
mermaid: 'graph TD; A-->B; B-->C; C-->D;',
|
||||
title: 'Test Flowchart',
|
||||
};
|
||||
expect(() => PostRenderFlowchartSchema?.parse(validData)).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws error for invalid data for postRenderFlowchart', () => {
|
||||
const PostRenderFlowchartSchema = zodSchemas?.postRenderFlowchart;
|
||||
const invalidData = {
|
||||
mermaid: 123,
|
||||
title: 42,
|
||||
};
|
||||
expect(() => PostRenderFlowchartSchema?.parse(invalidData)).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('scholarAIOpenapiSpec', () => {
|
||||
const result = validateAndParseOpenAPISpec(scholarAIOpenapiSpec);
|
||||
const spec = result.spec as OpenAPIV3.Document;
|
||||
const { zodSchemas } = openapiToFunction(spec, true);
|
||||
|
||||
it('generates correct Zod schema for searchAbstracts', () => {
|
||||
expect(zodSchemas).toBeDefined();
|
||||
expect(zodSchemas?.searchAbstracts).toBeDefined();
|
||||
|
||||
const SearchAbstractsSchema = zodSchemas?.searchAbstracts;
|
||||
expect(SearchAbstractsSchema).toBeInstanceOf(z.ZodObject);
|
||||
|
||||
if (!(SearchAbstractsSchema instanceof z.ZodObject)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shape = SearchAbstractsSchema.shape;
|
||||
expect(shape.keywords).toBeInstanceOf(z.ZodString);
|
||||
expect(shape.sort).toBeInstanceOf(z.ZodOptional);
|
||||
expect(
|
||||
(shape.sort as z.ZodOptional<z.ZodEnum<[string, ...string[]]>>)._def.innerType,
|
||||
).toBeInstanceOf(z.ZodEnum);
|
||||
expect(shape.query).toBeInstanceOf(z.ZodString);
|
||||
expect(shape.peer_reviewed_only).toBeInstanceOf(z.ZodOptional);
|
||||
expect(shape.start_year).toBeInstanceOf(z.ZodOptional);
|
||||
expect(shape.end_year).toBeInstanceOf(z.ZodOptional);
|
||||
expect(shape.offset).toBeInstanceOf(z.ZodOptional);
|
||||
});
|
||||
|
||||
it('validates correct data for searchAbstracts', () => {
|
||||
const SearchAbstractsSchema = zodSchemas?.searchAbstracts;
|
||||
const validData = {
|
||||
keywords: 'machine learning',
|
||||
sort: 'cited_by_count',
|
||||
query: 'AI applications',
|
||||
peer_reviewed_only: 'true',
|
||||
start_year: '2020',
|
||||
end_year: '2023',
|
||||
offset: '0',
|
||||
};
|
||||
expect(() => SearchAbstractsSchema?.parse(validData)).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws error for invalid data for searchAbstracts', () => {
|
||||
const SearchAbstractsSchema = zodSchemas?.searchAbstracts;
|
||||
const invalidData = {
|
||||
keywords: 123,
|
||||
sort: 'invalid_sort',
|
||||
query: 42,
|
||||
peer_reviewed_only: 'maybe',
|
||||
start_year: 2020,
|
||||
end_year: 2023,
|
||||
offset: 0,
|
||||
};
|
||||
expect(() => SearchAbstractsSchema?.parse(invalidData)).toThrow();
|
||||
});
|
||||
|
||||
it('generates correct Zod schema for getFullText', () => {
|
||||
expect(zodSchemas?.getFullText).toBeDefined();
|
||||
|
||||
const GetFullTextSchema = zodSchemas?.getFullText;
|
||||
expect(GetFullTextSchema).toBeInstanceOf(z.ZodObject);
|
||||
|
||||
if (!(GetFullTextSchema instanceof z.ZodObject)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shape = GetFullTextSchema.shape;
|
||||
expect(shape.pdf_url).toBeInstanceOf(z.ZodString);
|
||||
expect(shape.chunk).toBeInstanceOf(z.ZodOptional);
|
||||
expect((shape.chunk as z.ZodOptional<z.ZodNumber>)._def.innerType).toBeInstanceOf(
|
||||
z.ZodNumber,
|
||||
);
|
||||
});
|
||||
|
||||
it('generates correct Zod schema for saveCitation', () => {
|
||||
expect(zodSchemas?.saveCitation).toBeDefined();
|
||||
|
||||
const SaveCitationSchema = zodSchemas?.saveCitation;
|
||||
expect(SaveCitationSchema).toBeInstanceOf(z.ZodObject);
|
||||
|
||||
if (!(SaveCitationSchema instanceof z.ZodObject)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shape = SaveCitationSchema.shape;
|
||||
expect(shape.doi).toBeInstanceOf(z.ZodString);
|
||||
expect(shape.zotero_user_id).toBeInstanceOf(z.ZodString);
|
||||
expect(shape.zotero_api_key).toBeInstanceOf(z.ZodString);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('openapiToFunction zodSchemas for SWAPI', () => {
|
||||
const result = validateAndParseOpenAPISpec(swapidev);
|
||||
const spec = result.spec as OpenAPIV3.Document;
|
||||
const { zodSchemas } = openapiToFunction(spec, true);
|
||||
|
||||
describe('getPeople schema', () => {
|
||||
it('does not generate Zod schema for getPeople (no parameters)', () => {
|
||||
expect(zodSchemas).toBeDefined();
|
||||
expect(zodSchemas?.getPeople).toBeUndefined();
|
||||
});
|
||||
|
||||
it('validates correct data for getPeople', () => {
|
||||
const GetPeopleSchema = zodSchemas?.getPeople;
|
||||
expect(GetPeopleSchema).toBeUndefined();
|
||||
});
|
||||
|
||||
it('does not throw for invalid data for getPeople', () => {
|
||||
const GetPeopleSchema = zodSchemas?.getPeople;
|
||||
expect(GetPeopleSchema).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPersonById schema', () => {
|
||||
it('generates correct Zod schema for getPersonById', () => {
|
||||
expect(zodSchemas).toBeDefined();
|
||||
expect(zodSchemas?.getPersonById).toBeDefined();
|
||||
|
||||
const GetPersonByIdSchema = zodSchemas?.getPersonById;
|
||||
expect(GetPersonByIdSchema).toBeInstanceOf(z.ZodObject);
|
||||
|
||||
if (!(GetPersonByIdSchema instanceof z.ZodObject)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shape = GetPersonByIdSchema.shape;
|
||||
expect(shape.id).toBeInstanceOf(z.ZodString);
|
||||
});
|
||||
|
||||
it('validates correct data for getPersonById', () => {
|
||||
const GetPersonByIdSchema = zodSchemas?.getPersonById;
|
||||
const validData = { id: '1' };
|
||||
expect(() => GetPersonByIdSchema?.parse(validData)).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws error for invalid data for getPersonById', () => {
|
||||
const GetPersonByIdSchema = zodSchemas?.getPersonById;
|
||||
const invalidData = { id: 1 }; // should be string
|
||||
expect(() => GetPersonByIdSchema?.parse(invalidData)).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -348,3 +348,130 @@ components:
|
|||
message:
|
||||
type: string
|
||||
description: Confirmation of successful save or error message.`;
|
||||
|
||||
export const swapidev = `
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Star Wars API
|
||||
description: This is a simple API that provides information about the Star Wars universe.
|
||||
version: 1.0.0
|
||||
servers:
|
||||
- url: https://swapi.dev
|
||||
|
||||
paths:
|
||||
/api/people:
|
||||
get:
|
||||
summary: List all people
|
||||
operationId: getPeople
|
||||
tags:
|
||||
- People
|
||||
responses:
|
||||
'200':
|
||||
description: A list of people
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
count:
|
||||
type: integer
|
||||
example: 82
|
||||
next:
|
||||
type: string
|
||||
nullable: true
|
||||
example: https://swapi.dev/api/people/?page=2
|
||||
previous:
|
||||
type: string
|
||||
nullable: true
|
||||
example: null
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Person'
|
||||
|
||||
/api/people/{id}:
|
||||
get:
|
||||
summary: Get a person by ID
|
||||
operationId: getPersonById
|
||||
tags:
|
||||
- People
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The ID of the person to retrieve
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: A single person
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Person'
|
||||
'404':
|
||||
description: Person not found
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Person:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: Luke Skywalker
|
||||
height:
|
||||
type: string
|
||||
example: "172"
|
||||
mass:
|
||||
type: string
|
||||
example: "77"
|
||||
hair_color:
|
||||
type: string
|
||||
example: blond
|
||||
skin_color:
|
||||
type: string
|
||||
example: fair
|
||||
eye_color:
|
||||
type: string
|
||||
example: blue
|
||||
birth_year:
|
||||
type: string
|
||||
example: "19BBY"
|
||||
gender:
|
||||
type: string
|
||||
example: male
|
||||
homeworld:
|
||||
type: string
|
||||
example: https://swapi.dev/api/planets/1/
|
||||
films:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: https://swapi.dev/api/films/1/
|
||||
species:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: https://swapi.dev/api/species/1/
|
||||
vehicles:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: https://swapi.dev/api/vehicles/14/
|
||||
starships:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: https://swapi.dev/api/starships/12/
|
||||
created:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2014-12-09T13:50:51.644000Z
|
||||
edited:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2014-12-20T21:17:56.891000Z
|
||||
url:
|
||||
type: string
|
||||
example: https://swapi.dev/api/people/1/`;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { z } from 'zod';
|
||||
import axios from 'axios';
|
||||
import { URL } from 'url';
|
||||
import crypto from 'crypto';
|
||||
|
|
@ -12,6 +13,11 @@ export type ParametersSchema = {
|
|||
required: string[];
|
||||
};
|
||||
|
||||
export type OpenAPISchema = OpenAPIV3.SchemaObject &
|
||||
ParametersSchema & {
|
||||
items?: OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject;
|
||||
};
|
||||
|
||||
export type ApiKeyCredentials = {
|
||||
api_key: string;
|
||||
custom_auth_header?: string;
|
||||
|
|
@ -38,6 +44,70 @@ export function createURL(domain: string, path: string) {
|
|||
return new URL(fullURL).toString();
|
||||
}
|
||||
|
||||
const schemaTypeHandlers: Record<string, (schema: OpenAPISchema) => z.ZodTypeAny> = {
|
||||
string: (schema) => {
|
||||
if (schema.enum) {
|
||||
return z.enum(schema.enum as [string, ...string[]]);
|
||||
}
|
||||
|
||||
let stringSchema = z.string();
|
||||
if (schema.minLength !== undefined) {
|
||||
stringSchema = stringSchema.min(schema.minLength);
|
||||
}
|
||||
if (schema.maxLength !== undefined) {
|
||||
stringSchema = stringSchema.max(schema.maxLength);
|
||||
}
|
||||
return stringSchema;
|
||||
},
|
||||
number: (schema) => {
|
||||
let numberSchema = z.number();
|
||||
if (schema.minimum !== undefined) {
|
||||
numberSchema = numberSchema.min(schema.minimum);
|
||||
}
|
||||
if (schema.maximum !== undefined) {
|
||||
numberSchema = numberSchema.max(schema.maximum);
|
||||
}
|
||||
return numberSchema;
|
||||
},
|
||||
integer: (schema) => (schemaTypeHandlers.number(schema) as z.ZodNumber).int(),
|
||||
boolean: () => z.boolean(),
|
||||
array: (schema) => {
|
||||
if (schema.items) {
|
||||
const zodSchema = openAPISchemaToZod(schema.items as OpenAPISchema);
|
||||
if (zodSchema) {
|
||||
return z.array(zodSchema);
|
||||
}
|
||||
|
||||
return z.array(z.unknown());
|
||||
}
|
||||
return z.array(z.unknown());
|
||||
},
|
||||
object: (schema) => {
|
||||
const shape: { [key: string]: z.ZodTypeAny } = {};
|
||||
if (schema.properties) {
|
||||
Object.entries(schema.properties).forEach(([key, value]) => {
|
||||
const zodSchema = openAPISchemaToZod(value as OpenAPISchema);
|
||||
shape[key] = zodSchema || z.unknown();
|
||||
if (schema.required && schema.required.includes(key)) {
|
||||
shape[key] = shape[key].describe(value.description || '');
|
||||
} else {
|
||||
shape[key] = shape[key].optional().describe(value.description || '');
|
||||
}
|
||||
});
|
||||
}
|
||||
return z.object(shape);
|
||||
},
|
||||
};
|
||||
|
||||
function openAPISchemaToZod(schema: OpenAPISchema): z.ZodTypeAny | undefined {
|
||||
if (schema.type === 'object' && Object.keys(schema.properties || {}).length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const handler = schemaTypeHandlers[schema.type as string] || (() => z.unknown());
|
||||
return handler(schema);
|
||||
}
|
||||
|
||||
export class FunctionSignature {
|
||||
name: string;
|
||||
description: string;
|
||||
|
|
@ -46,11 +116,7 @@ export class FunctionSignature {
|
|||
constructor(name: string, description: string, parameters: ParametersSchema) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
if (parameters.properties?.['requestBody']) {
|
||||
this.parameters = parameters.properties?.['requestBody'] as ParametersSchema;
|
||||
} else {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
toObjectTool(): FunctionTool {
|
||||
|
|
@ -219,14 +285,17 @@ function sanitizeOperationId(input: string) {
|
|||
}
|
||||
|
||||
/** Function to convert OpenAPI spec to function signatures and request builders */
|
||||
export function openapiToFunction(openapiSpec: OpenAPIV3.Document): {
|
||||
export function openapiToFunction(
|
||||
openapiSpec: OpenAPIV3.Document,
|
||||
generateZodSchemas = false,
|
||||
): {
|
||||
functionSignatures: FunctionSignature[];
|
||||
requestBuilders: Record<string, ActionRequest>;
|
||||
zodSchemas?: Record<string, z.ZodTypeAny>;
|
||||
} {
|
||||
const functionSignatures: FunctionSignature[] = [];
|
||||
const requestBuilders: Record<string, ActionRequest> = {};
|
||||
|
||||
// Base URL from OpenAPI spec servers
|
||||
const zodSchemas: Record<string, z.ZodTypeAny> = {};
|
||||
const baseUrl = openapiSpec.servers?.[0]?.url ?? '';
|
||||
|
||||
// Iterate over each path and method in the OpenAPI spec
|
||||
|
|
@ -241,19 +310,11 @@ export function openapiToFunction(openapiSpec: OpenAPIV3.Document): {
|
|||
const operationId = operationObj.operationId || sanitizeOperationId(defaultOperationId);
|
||||
const description = operationObj.summary || operationObj.description || '';
|
||||
|
||||
const parametersSchema: ParametersSchema = { type: 'object', properties: {}, required: [] };
|
||||
|
||||
if (operationObj.requestBody) {
|
||||
const requestBody = operationObj.requestBody as OpenAPIV3.RequestBodyObject;
|
||||
const content = requestBody.content;
|
||||
const contentType = Object.keys(content)[0];
|
||||
const schema = content[contentType]?.schema;
|
||||
const resolvedSchema = resolveRef(
|
||||
schema as OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject,
|
||||
openapiSpec.components,
|
||||
);
|
||||
parametersSchema.properties['requestBody'] = resolvedSchema;
|
||||
}
|
||||
const parametersSchema: OpenAPISchema = {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
required: [],
|
||||
};
|
||||
|
||||
if (operationObj.parameters) {
|
||||
for (const param of operationObj.parameters) {
|
||||
|
|
@ -266,9 +327,24 @@ export function openapiToFunction(openapiSpec: OpenAPIV3.Document): {
|
|||
if (paramObj.required) {
|
||||
parametersSchema.required.push(paramObj.name);
|
||||
}
|
||||
if (paramObj.description && !('$$ref' in parametersSchema.properties[paramObj.name])) {
|
||||
parametersSchema.properties[paramObj.name].description = paramObj.description;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operationObj.requestBody) {
|
||||
const requestBody = operationObj.requestBody as OpenAPIV3.RequestBodyObject;
|
||||
const content = requestBody.content;
|
||||
const contentType = Object.keys(content)[0];
|
||||
const schema = content[contentType]?.schema;
|
||||
const resolvedSchema = resolveRef(
|
||||
schema as OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject,
|
||||
openapiSpec.components,
|
||||
);
|
||||
parametersSchema.properties = {
|
||||
...parametersSchema.properties,
|
||||
...resolvedSchema.properties,
|
||||
};
|
||||
if (resolvedSchema.required) {
|
||||
parametersSchema.required.push(...resolvedSchema.required);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -285,10 +361,17 @@ export function openapiToFunction(openapiSpec: OpenAPIV3.Document): {
|
|||
);
|
||||
|
||||
requestBuilders[operationId] = actionRequest;
|
||||
|
||||
if (generateZodSchemas && Object.keys(parametersSchema.properties).length > 0) {
|
||||
const schema = openAPISchemaToZod(parametersSchema);
|
||||
if (schema) {
|
||||
zodSchemas[operationId] = schema;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { functionSignatures, requestBuilders };
|
||||
return { functionSignatures, requestBuilders, zodSchemas };
|
||||
}
|
||||
|
||||
export type ValidationResult = {
|
||||
|
|
|
|||
|
|
@ -125,6 +125,21 @@ export const assistants = ({
|
|||
return url;
|
||||
};
|
||||
|
||||
export const agents = ({ path, options }: { path?: string; options?: object }) => {
|
||||
let url = '/api/agents';
|
||||
|
||||
if (path) {
|
||||
url += `/${path}`;
|
||||
}
|
||||
|
||||
if (options && Object.keys(options).length > 0) {
|
||||
const queryParams = new URLSearchParams(options as Record<string, string>).toString();
|
||||
url += `?${queryParams}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
};
|
||||
|
||||
export const files = () => '/api/files';
|
||||
|
||||
export const images = () => `${files()}/images`;
|
||||
|
|
|
|||
|
|
@ -186,6 +186,48 @@ export const assistantEndpointSchema = baseEndpointSchema.merge(
|
|||
|
||||
export type TAssistantEndpoint = z.infer<typeof assistantEndpointSchema>;
|
||||
|
||||
export const agentsEndpointSChema = baseEndpointSchema.merge(
|
||||
baseEndpointSchema.merge(
|
||||
z.object({
|
||||
/* assistants specific */
|
||||
disableBuilder: z.boolean().optional(),
|
||||
pollIntervalMs: z.number().optional(),
|
||||
timeoutMs: z.number().optional(),
|
||||
version: z.union([z.string(), z.number()]).default(2),
|
||||
supportedIds: z.array(z.string()).min(1).optional(),
|
||||
excludedIds: z.array(z.string()).min(1).optional(),
|
||||
privateAssistants: z.boolean().optional(),
|
||||
retrievalModels: z.array(z.string()).min(1).optional().default(defaultRetrievalModels),
|
||||
capabilities: z
|
||||
.array(z.nativeEnum(Capabilities))
|
||||
.optional()
|
||||
.default([
|
||||
Capabilities.code_interpreter,
|
||||
Capabilities.image_vision,
|
||||
Capabilities.retrieval,
|
||||
Capabilities.actions,
|
||||
Capabilities.tools,
|
||||
]),
|
||||
/* general */
|
||||
apiKey: z.string().optional(),
|
||||
baseURL: z.string().optional(),
|
||||
models: z
|
||||
.object({
|
||||
default: z.array(z.string()).min(1),
|
||||
fetch: z.boolean().optional(),
|
||||
userIdQuery: z.boolean().optional(),
|
||||
})
|
||||
.optional(),
|
||||
titleConvo: z.boolean().optional(),
|
||||
titleMethod: z.union([z.literal('completion'), z.literal('functions')]).optional(),
|
||||
titleModel: z.string().optional(),
|
||||
headers: z.record(z.any()).optional(),
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
export type TAgentsEndpoint = z.infer<typeof agentsEndpointSChema>;
|
||||
|
||||
export const endpointSchema = baseEndpointSchema.merge(
|
||||
z.object({
|
||||
name: z.string().refine((value) => !eModelEndpointSchema.safeParse(value).success, {
|
||||
|
|
@ -456,6 +498,7 @@ export const configSchema = z.object({
|
|||
[EModelEndpoint.azureOpenAI]: azureEndpointSchema.optional(),
|
||||
[EModelEndpoint.azureAssistants]: assistantEndpointSchema.optional(),
|
||||
[EModelEndpoint.assistants]: assistantEndpointSchema.optional(),
|
||||
[EModelEndpoint.agents]: agentsEndpointSChema.optional(),
|
||||
[EModelEndpoint.custom]: z.array(endpointSchema.partial()).optional(),
|
||||
})
|
||||
.strict()
|
||||
|
|
@ -502,6 +545,7 @@ export const defaultEndpoints: EModelEndpoint[] = [
|
|||
EModelEndpoint.assistants,
|
||||
EModelEndpoint.azureAssistants,
|
||||
EModelEndpoint.azureOpenAI,
|
||||
EModelEndpoint.agents,
|
||||
EModelEndpoint.bingAI,
|
||||
EModelEndpoint.chatGPTBrowser,
|
||||
EModelEndpoint.gptPlugins,
|
||||
|
|
@ -513,6 +557,7 @@ export const defaultEndpoints: EModelEndpoint[] = [
|
|||
export const alternateName = {
|
||||
[EModelEndpoint.openAI]: 'OpenAI',
|
||||
[EModelEndpoint.assistants]: 'Assistants',
|
||||
[EModelEndpoint.agents]: 'Agents',
|
||||
[EModelEndpoint.azureAssistants]: 'Azure Assistants',
|
||||
[EModelEndpoint.azureOpenAI]: 'Azure OpenAI',
|
||||
[EModelEndpoint.bingAI]: 'Bing',
|
||||
|
|
@ -546,6 +591,7 @@ const sharedOpenAIModels = [
|
|||
export const defaultModels = {
|
||||
[EModelEndpoint.azureAssistants]: sharedOpenAIModels,
|
||||
[EModelEndpoint.assistants]: ['chatgpt-4o-latest', ...sharedOpenAIModels],
|
||||
[EModelEndpoint.agents]: sharedOpenAIModels, // TODO: Add agent models (agentsModels)
|
||||
[EModelEndpoint.google]: [
|
||||
'gemini-pro',
|
||||
'gemini-pro-vision',
|
||||
|
|
@ -592,6 +638,7 @@ export const initialModelsConfig: TModelsConfig = {
|
|||
initial: [],
|
||||
[EModelEndpoint.openAI]: openAIModels,
|
||||
[EModelEndpoint.assistants]: openAIModels.filter(fitlerAssistantModels),
|
||||
[EModelEndpoint.agents]: openAIModels, // TODO: Add agent models (agentsModels)
|
||||
[EModelEndpoint.gptPlugins]: openAIModels,
|
||||
[EModelEndpoint.azureOpenAI]: openAIModels,
|
||||
[EModelEndpoint.bingAI]: ['BingAI', 'Sydney'],
|
||||
|
|
@ -611,6 +658,7 @@ export const EndpointURLs: { [key in EModelEndpoint]: string } = {
|
|||
[EModelEndpoint.chatGPTBrowser]: `/api/ask/${EModelEndpoint.chatGPTBrowser}`,
|
||||
[EModelEndpoint.azureAssistants]: '/api/assistants/v1/chat',
|
||||
[EModelEndpoint.assistants]: '/api/assistants/v2/chat',
|
||||
[EModelEndpoint.agents]: '/api/agents/chat',
|
||||
};
|
||||
|
||||
export const modularEndpoints = new Set<EModelEndpoint | string>([
|
||||
|
|
@ -628,6 +676,7 @@ export const supportsBalanceCheck = {
|
|||
[EModelEndpoint.anthropic]: true,
|
||||
[EModelEndpoint.gptPlugins]: true,
|
||||
[EModelEndpoint.assistants]: true,
|
||||
[EModelEndpoint.agents]: true,
|
||||
[EModelEndpoint.azureAssistants]: true,
|
||||
[EModelEndpoint.azureOpenAI]: true,
|
||||
};
|
||||
|
|
@ -996,6 +1045,8 @@ export enum LocalStorageKeys {
|
|||
FILES_TO_DELETE = 'filesToDelete',
|
||||
/** Prefix key for the last selected assistant ID by index */
|
||||
ASST_ID_PREFIX = 'assistant_id__',
|
||||
/** Prefix key for the last selected agent ID by index */
|
||||
AGENT_ID_PREFIX = 'agent_id__',
|
||||
/** Key for the last selected fork setting */
|
||||
FORK_SETTING = 'forkSetting',
|
||||
/** Key for remembering the last selected option, instead of manually selecting */
|
||||
|
|
@ -1051,3 +1102,9 @@ export enum SystemCategories {
|
|||
NO_CATEGORY = 'sys__no__category__sys',
|
||||
SHARED_PROMPTS = 'sys__shared__prompts__sys',
|
||||
}
|
||||
|
||||
export const providerEndpointMap = {
|
||||
[EModelEndpoint.openAI]: EModelEndpoint.openAI,
|
||||
[EModelEndpoint.azureOpenAI]: EModelEndpoint.openAI,
|
||||
[EModelEndpoint.anthropic]: EModelEndpoint.anthropic,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import type { AxiosResponse } from 'axios';
|
||||
import * as f from './types/files';
|
||||
import * as q from './types/queries';
|
||||
import * as m from './types/mutations';
|
||||
import * as a from './types/assistants';
|
||||
import * as r from './roles';
|
||||
import * as t from './types';
|
||||
import * as s from './schemas';
|
||||
import request from './request';
|
||||
import type * as t from './types';
|
||||
import * as endpoints from './api-endpoints';
|
||||
import * as a from './types/assistants';
|
||||
import * as m from './types/mutations';
|
||||
import * as q from './types/queries';
|
||||
import * as f from './types/files';
|
||||
import * as config from './config';
|
||||
import request from './request';
|
||||
import * as s from './schemas';
|
||||
import * as r from './roles';
|
||||
|
||||
export function abortRequestWithMessage(
|
||||
endpoint: string,
|
||||
|
|
@ -274,16 +275,24 @@ export function getAssistantDocs({
|
|||
/* Tools */
|
||||
|
||||
export const getAvailableTools = (
|
||||
version: number | string,
|
||||
endpoint: s.AssistantsEndpoint,
|
||||
_endpoint: s.AssistantsEndpoint | s.EModelEndpoint.agents,
|
||||
version?: number | string,
|
||||
): Promise<s.TPlugin[]> => {
|
||||
return request.get(
|
||||
endpoints.assistants({
|
||||
let path = '';
|
||||
if (s.isAssistantsEndpoint(_endpoint)) {
|
||||
const endpoint = _endpoint as s.AssistantsEndpoint;
|
||||
path = endpoints.assistants({
|
||||
path: 'tools',
|
||||
endpoint,
|
||||
version,
|
||||
}),
|
||||
);
|
||||
endpoint: endpoint,
|
||||
version: version ?? config.defaultAssistantsVersion[endpoint],
|
||||
});
|
||||
} else {
|
||||
path = endpoints.agents({
|
||||
path: 'tools',
|
||||
});
|
||||
}
|
||||
|
||||
return request.get(path);
|
||||
};
|
||||
|
||||
/* Files */
|
||||
|
|
@ -304,6 +313,123 @@ export const uploadFile = (data: FormData): Promise<f.TFileUpload> => {
|
|||
return request.postMultiPart(endpoints.files(), data);
|
||||
};
|
||||
|
||||
/* actions */
|
||||
|
||||
export const updateAction = (data: m.UpdateActionVariables): Promise<m.UpdateActionResponse> => {
|
||||
const { assistant_id, version, ...body } = data;
|
||||
return request.post(
|
||||
endpoints.assistants({
|
||||
path: `actions/${assistant_id}`,
|
||||
version,
|
||||
}),
|
||||
body,
|
||||
);
|
||||
};
|
||||
|
||||
export function getActions(): Promise<a.Action[]> {
|
||||
return request.get(
|
||||
endpoints.agents({
|
||||
path: 'actions',
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export const deleteAction = async ({
|
||||
assistant_id,
|
||||
action_id,
|
||||
model,
|
||||
version,
|
||||
endpoint,
|
||||
}: m.DeleteActionVariables & { version: number | string }): Promise<void> =>
|
||||
request.delete(
|
||||
endpoints.assistants({
|
||||
path: `actions/${assistant_id}/${action_id}/${model}`,
|
||||
version,
|
||||
endpoint,
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* Agents
|
||||
*/
|
||||
|
||||
export const createAgent = ({ ...data }: a.AgentCreateParams): Promise<a.Agent> => {
|
||||
return request.post(endpoints.agents({}), data);
|
||||
};
|
||||
|
||||
export const getAgentById = ({ agent_id }: { agent_id: string }): Promise<a.Agent> => {
|
||||
return request.get(
|
||||
endpoints.agents({
|
||||
path: agent_id,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
export const updateAgent = ({
|
||||
agent_id,
|
||||
data,
|
||||
}: {
|
||||
agent_id: string;
|
||||
data: a.AgentUpdateParams;
|
||||
}): Promise<a.Agent> => {
|
||||
return request.patch(
|
||||
endpoints.agents({
|
||||
path: agent_id,
|
||||
}),
|
||||
data,
|
||||
);
|
||||
};
|
||||
|
||||
export const deleteAgent = ({ agent_id }: m.DeleteAgentBody): Promise<void> => {
|
||||
return request.delete(
|
||||
endpoints.agents({
|
||||
path: agent_id,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
export const listAgents = (params: a.AgentListParams): Promise<a.AgentListResponse> => {
|
||||
return request.get(
|
||||
endpoints.agents({
|
||||
options: params,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
/* Tools */
|
||||
|
||||
export const getAvailableAgentTools = (): Promise<s.TPlugin[]> => {
|
||||
return request.get(
|
||||
endpoints.agents({
|
||||
path: 'tools',
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
/* Actions */
|
||||
|
||||
export const updateAgentAction = (
|
||||
data: m.UpdateAgentActionVariables,
|
||||
): Promise<m.UpdateAgentActionResponse> => {
|
||||
const { agent_id, ...body } = data;
|
||||
return request.post(
|
||||
endpoints.agents({
|
||||
path: `actions/${agent_id}`,
|
||||
}),
|
||||
body,
|
||||
);
|
||||
};
|
||||
|
||||
export const deleteAgentAction = async ({
|
||||
agent_id,
|
||||
action_id,
|
||||
}: m.DeleteAgentActionVariables): Promise<void> =>
|
||||
request.delete(
|
||||
endpoints.agents({
|
||||
path: `actions/${agent_id}/${action_id}`,
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* Imports a conversations file.
|
||||
*
|
||||
|
|
@ -329,6 +455,15 @@ export const uploadAssistantAvatar = (data: m.AssistantAvatarVariables): Promise
|
|||
);
|
||||
};
|
||||
|
||||
export const uploadAgentAvatar = (data: m.AgentAvatarVariables): Promise<a.Agent> => {
|
||||
return request.postMultiPart(
|
||||
endpoints.agents({
|
||||
path: `avatar/${data.agent_id}`,
|
||||
}),
|
||||
data.formData,
|
||||
);
|
||||
};
|
||||
|
||||
export const getFileDownload = async (userId: string, file_id: string): Promise<AxiosResponse> => {
|
||||
return request.getResponse(`${endpoints.files()}/download/${userId}/${file_id}`, {
|
||||
responseType: 'blob',
|
||||
|
|
@ -347,6 +482,8 @@ export const deleteFiles = async (
|
|||
data: { files, assistant_id, tool_resource },
|
||||
});
|
||||
|
||||
/* Speech */
|
||||
|
||||
export const speechToText = (data: FormData): Promise<f.SpeechToTextResponse> => {
|
||||
return request.postMultiPart(endpoints.speechToText(), data);
|
||||
};
|
||||
|
|
@ -363,50 +500,6 @@ export const getCustomConfigSpeech = (): Promise<t.TCustomConfigSpeechResponse>
|
|||
return request.get(endpoints.getCustomConfigSpeech());
|
||||
};
|
||||
|
||||
/* actions */
|
||||
|
||||
export const updateAction = (data: m.UpdateActionVariables): Promise<m.UpdateActionResponse> => {
|
||||
const { assistant_id, version, ...body } = data;
|
||||
return request.post(
|
||||
endpoints.assistants({
|
||||
path: `actions/${assistant_id}`,
|
||||
version,
|
||||
}),
|
||||
body,
|
||||
);
|
||||
};
|
||||
|
||||
export function getActions({
|
||||
endpoint,
|
||||
version,
|
||||
}: {
|
||||
endpoint: s.AssistantsEndpoint;
|
||||
version: number | string;
|
||||
}): Promise<a.Action[]> {
|
||||
return request.get(
|
||||
endpoints.assistants({
|
||||
path: 'actions',
|
||||
version,
|
||||
endpoint,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export const deleteAction = async ({
|
||||
assistant_id,
|
||||
action_id,
|
||||
model,
|
||||
version,
|
||||
endpoint,
|
||||
}: m.DeleteActionVariables & { version: number | string }): Promise<void> =>
|
||||
request.delete(
|
||||
endpoints.assistants({
|
||||
path: `actions/${assistant_id}/${action_id}/${model}`,
|
||||
version,
|
||||
endpoint,
|
||||
}),
|
||||
);
|
||||
|
||||
/* conversations */
|
||||
|
||||
export function forkConversation(payload: t.TForkConvoRequest): Promise<t.TForkConvoResponse> {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export const supportsFiles = {
|
|||
[EModelEndpoint.google]: true,
|
||||
[EModelEndpoint.assistants]: true,
|
||||
[EModelEndpoint.azureAssistants]: true,
|
||||
[EModelEndpoint.agents]: true,
|
||||
[EModelEndpoint.azureOpenAI]: true,
|
||||
[EModelEndpoint.anthropic]: true,
|
||||
[EModelEndpoint.custom]: true,
|
||||
|
|
|
|||
|
|
@ -13,10 +13,12 @@ export * from './generate';
|
|||
export * from './roles';
|
||||
/* types (exports schemas from `./types` as they contain needed in other defs) */
|
||||
export * from './types';
|
||||
export * from './types/agents';
|
||||
export * from './types/assistants';
|
||||
export * from './types/queries';
|
||||
export * from './types/files';
|
||||
export * from './types/mutations';
|
||||
export * from './types/runs';
|
||||
/* query/mutation keys */
|
||||
export * from './keys';
|
||||
/* api call helpers */
|
||||
|
|
|
|||
|
|
@ -19,12 +19,16 @@ export enum QueryKeys {
|
|||
startupConfig = 'startupConfig',
|
||||
assistants = 'assistants',
|
||||
assistant = 'assistant',
|
||||
agents = 'agents',
|
||||
agent = 'agent',
|
||||
endpointsConfigOverride = 'endpointsConfigOverride',
|
||||
files = 'files',
|
||||
fileConfig = 'fileConfig',
|
||||
tools = 'tools',
|
||||
agentTools = 'agentTools',
|
||||
actions = 'actions',
|
||||
assistantDocs = 'assistantDocs',
|
||||
agentDocs = 'agentDocs',
|
||||
fileDownload = 'fileDownload',
|
||||
voices = 'voices',
|
||||
customConfigSpeech = 'customConfigSpeech',
|
||||
|
|
@ -51,8 +55,11 @@ export enum MutationKeys {
|
|||
speechToText = 'speechToText',
|
||||
textToSpeech = 'textToSpeech',
|
||||
assistantAvatarUpload = 'assistantAvatarUpload',
|
||||
agentAvatarUpload = 'agentAvatarUpload',
|
||||
updateAction = 'updateAction',
|
||||
updateAgentAction = 'updateAgentAction',
|
||||
deleteAction = 'deleteAction',
|
||||
deleteAgentAction = 'deleteAgentAction',
|
||||
deleteUser = 'deleteUser',
|
||||
updateRole = 'updateRole',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,22 +2,24 @@ import type { ZodIssue } from 'zod';
|
|||
import type * as a from './types/assistants';
|
||||
import type * as s from './schemas';
|
||||
import type * as t from './types';
|
||||
import { ContentTypes } from './types/assistants';
|
||||
import { ContentTypes } from './types/runs';
|
||||
import {
|
||||
EModelEndpoint,
|
||||
openAISchema,
|
||||
googleSchema,
|
||||
bingAISchema,
|
||||
EModelEndpoint,
|
||||
anthropicSchema,
|
||||
chatGPTBrowserSchema,
|
||||
gptPluginsSchema,
|
||||
assistantSchema,
|
||||
gptPluginsSchema,
|
||||
// agentsSchema,
|
||||
compactAgentsSchema,
|
||||
compactOpenAISchema,
|
||||
compactGoogleSchema,
|
||||
compactAnthropicSchema,
|
||||
compactChatGPTSchema,
|
||||
chatGPTBrowserSchema,
|
||||
compactPluginsSchema,
|
||||
compactAssistantSchema,
|
||||
compactAnthropicSchema,
|
||||
} from './schemas';
|
||||
import { alternateName } from './config';
|
||||
|
||||
|
|
@ -28,7 +30,8 @@ type EndpointSchema =
|
|||
| typeof anthropicSchema
|
||||
| typeof chatGPTBrowserSchema
|
||||
| typeof gptPluginsSchema
|
||||
| typeof assistantSchema;
|
||||
| typeof assistantSchema
|
||||
| typeof compactAgentsSchema;
|
||||
|
||||
const endpointSchemas: Record<EModelEndpoint, EndpointSchema> = {
|
||||
[EModelEndpoint.openAI]: openAISchema,
|
||||
|
|
@ -41,6 +44,7 @@ const endpointSchemas: Record<EModelEndpoint, EndpointSchema> = {
|
|||
[EModelEndpoint.gptPlugins]: gptPluginsSchema,
|
||||
[EModelEndpoint.assistants]: assistantSchema,
|
||||
[EModelEndpoint.azureAssistants]: assistantSchema,
|
||||
[EModelEndpoint.agents]: compactAgentsSchema,
|
||||
};
|
||||
|
||||
// const schemaCreators: Record<EModelEndpoint, (customSchema: DefaultSchemaValues) => EndpointSchema> = {
|
||||
|
|
@ -51,6 +55,7 @@ const endpointSchemas: Record<EModelEndpoint, EndpointSchema> = {
|
|||
export function getEnabledEndpoints() {
|
||||
const defaultEndpoints: string[] = [
|
||||
EModelEndpoint.openAI,
|
||||
EModelEndpoint.agents,
|
||||
EModelEndpoint.assistants,
|
||||
EModelEndpoint.azureAssistants,
|
||||
EModelEndpoint.azureOpenAI,
|
||||
|
|
@ -61,7 +66,7 @@ export function getEnabledEndpoints() {
|
|||
EModelEndpoint.anthropic,
|
||||
];
|
||||
|
||||
const endpointsEnv = process.env.ENDPOINTS || '';
|
||||
const endpointsEnv = process.env.ENDPOINTS ?? '';
|
||||
let enabledEndpoints = defaultEndpoints;
|
||||
if (endpointsEnv) {
|
||||
enabledEndpoints = endpointsEnv
|
||||
|
|
@ -125,6 +130,7 @@ export const envVarRegex = /^\${(.+)}$/;
|
|||
export function extractEnvVariable(value: string) {
|
||||
const envVarMatch = value.match(envVarRegex);
|
||||
if (envVarMatch) {
|
||||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
||||
return process.env[envVarMatch[1]] || value;
|
||||
}
|
||||
return value;
|
||||
|
|
@ -154,6 +160,15 @@ export function getFirstDefinedValue(possibleValues: string[]) {
|
|||
return returnValue;
|
||||
}
|
||||
|
||||
export function getNonEmptyValue(possibleValues: string[]) {
|
||||
for (const value of possibleValues) {
|
||||
if (value && value.trim() !== '') {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export type TPossibleValues = {
|
||||
models: string[];
|
||||
secondaryModels?: string[];
|
||||
|
|
@ -266,6 +281,7 @@ export const getResponseSender = (endpointOption: t.TEndpointOption): string =>
|
|||
type CompactEndpointSchema =
|
||||
| typeof compactOpenAISchema
|
||||
| typeof compactAssistantSchema
|
||||
| typeof compactAgentsSchema
|
||||
| typeof compactGoogleSchema
|
||||
| typeof bingAISchema
|
||||
| typeof compactAnthropicSchema
|
||||
|
|
@ -278,6 +294,7 @@ const compactEndpointSchemas: Record<string, CompactEndpointSchema> = {
|
|||
[EModelEndpoint.custom]: compactOpenAISchema,
|
||||
[EModelEndpoint.assistants]: compactAssistantSchema,
|
||||
[EModelEndpoint.azureAssistants]: compactAssistantSchema,
|
||||
[EModelEndpoint.agents]: compactAgentsSchema,
|
||||
[EModelEndpoint.google]: compactGoogleSchema,
|
||||
/* BingAI needs all fields */
|
||||
[EModelEndpoint.bingAI]: bingAISchema,
|
||||
|
|
@ -331,7 +348,7 @@ export function parseTextParts(contentParts: a.TMessageContentParts[]): string {
|
|||
|
||||
for (const part of contentParts) {
|
||||
if (part.type === ContentTypes.TEXT) {
|
||||
const textValue = part.text.value;
|
||||
const textValue = typeof part.text === 'string' ? part.text : part.text.value;
|
||||
|
||||
if (
|
||||
result.length > 0 &&
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export enum EModelEndpoint {
|
|||
anthropic = 'anthropic',
|
||||
assistants = 'assistants',
|
||||
azureAssistants = 'azureAssistants',
|
||||
agents = 'agents',
|
||||
custom = 'custom',
|
||||
}
|
||||
|
||||
|
|
@ -35,6 +36,15 @@ export const isAssistantsEndpoint = (endpoint?: AssistantsEndpoint | null | stri
|
|||
return endpoint.toLowerCase().endsWith(EModelEndpoint.assistants);
|
||||
};
|
||||
|
||||
export type AgentProvider = Exclude<keyof typeof EModelEndpoint, EModelEndpoint.agents> | string;
|
||||
|
||||
export const isAgentsEndpoint = (endpoint?: EModelEndpoint.agents | null | string): boolean => {
|
||||
if (!endpoint) {
|
||||
return false;
|
||||
}
|
||||
return endpoint === EModelEndpoint.agents;
|
||||
};
|
||||
|
||||
export enum ImageDetail {
|
||||
low = 'low',
|
||||
auto = 'auto',
|
||||
|
|
@ -69,6 +79,21 @@ export const defaultAssistantFormValues = {
|
|||
retrieval: false,
|
||||
};
|
||||
|
||||
export const defaultAgentFormValues = {
|
||||
agent: {},
|
||||
id: '',
|
||||
name: '',
|
||||
description: '',
|
||||
instructions: '',
|
||||
model: '',
|
||||
model_parameters: {},
|
||||
tools: [],
|
||||
provider: {},
|
||||
code_interpreter: false,
|
||||
image_vision: false,
|
||||
retrieval: false,
|
||||
};
|
||||
|
||||
export const ImageVisionTool: FunctionTool = {
|
||||
type: Tools.function,
|
||||
[Tools.function]: {
|
||||
|
|
@ -223,10 +248,53 @@ export const anthropicSettings = {
|
|||
},
|
||||
};
|
||||
|
||||
export const agentsSettings = {
|
||||
model: {
|
||||
default: 'gpt-3.5-turbo-test',
|
||||
},
|
||||
temperature: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
default: 1,
|
||||
},
|
||||
top_p: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
default: 1,
|
||||
},
|
||||
presence_penalty: {
|
||||
min: 0,
|
||||
max: 2,
|
||||
step: 0.01,
|
||||
default: 0,
|
||||
},
|
||||
frequency_penalty: {
|
||||
min: 0,
|
||||
max: 2,
|
||||
step: 0.01,
|
||||
default: 0,
|
||||
},
|
||||
resendFiles: {
|
||||
default: true,
|
||||
},
|
||||
maxContextTokens: {
|
||||
default: undefined,
|
||||
},
|
||||
max_tokens: {
|
||||
default: undefined,
|
||||
},
|
||||
imageDetail: {
|
||||
default: ImageDetail.auto,
|
||||
},
|
||||
};
|
||||
|
||||
export const endpointSettings = {
|
||||
[EModelEndpoint.openAI]: openAISettings,
|
||||
[EModelEndpoint.google]: googleSettings,
|
||||
[EModelEndpoint.anthropic]: anthropicSettings,
|
||||
[EModelEndpoint.agents]: agentsSettings,
|
||||
};
|
||||
|
||||
const google = endpointSettings[EModelEndpoint.google];
|
||||
|
|
@ -367,46 +435,49 @@ export const coerceNumber = z.union([z.number(), z.string()]).transform((val) =>
|
|||
|
||||
export const tConversationSchema = z.object({
|
||||
conversationId: z.string().nullable(),
|
||||
title: z.string().nullable().or(z.literal('New Chat')).default('New Chat'),
|
||||
user: z.string().optional(),
|
||||
endpoint: eModelEndpointSchema.nullable(),
|
||||
endpointType: eModelEndpointSchema.optional(),
|
||||
suggestions: z.array(z.string()).optional(),
|
||||
title: z.string().nullable().or(z.literal('New Chat')).default('New Chat'),
|
||||
user: z.string().optional(),
|
||||
messages: z.array(z.string()).optional(),
|
||||
tools: z.union([z.array(tPluginSchema), z.array(z.string())]).optional(),
|
||||
createdAt: z.string(),
|
||||
updatedAt: z.string(),
|
||||
modelLabel: z.string().nullable().optional(),
|
||||
examples: z.array(tExampleSchema).optional(),
|
||||
tags: z.array(z.string()).optional(),
|
||||
/* Prefer modelLabel over chatGptLabel */
|
||||
chatGptLabel: z.string().nullable().optional(),
|
||||
userLabel: z.string().optional(),
|
||||
model: z.string().nullable().optional(),
|
||||
promptPrefix: z.string().nullable().optional(),
|
||||
temperature: z.number().optional(),
|
||||
topP: z.number().optional(),
|
||||
topK: z.number().optional(),
|
||||
context: z.string().nullable().optional(),
|
||||
top_p: z.number().optional(),
|
||||
frequency_penalty: z.number().optional(),
|
||||
presence_penalty: z.number().optional(),
|
||||
parentMessageId: z.string().optional(),
|
||||
maxOutputTokens: z.number().optional(),
|
||||
agentOptions: tAgentOptionsSchema.nullable().optional(),
|
||||
file_ids: z.array(z.string()).optional(),
|
||||
maxContextTokens: coerceNumber.optional(),
|
||||
max_tokens: coerceNumber.optional(),
|
||||
/* Anthropic */
|
||||
promptCache: z.boolean().optional(),
|
||||
/* artifacts */
|
||||
artifacts: z.string().optional(),
|
||||
/* google */
|
||||
context: z.string().nullable().optional(),
|
||||
examples: z.array(tExampleSchema).optional(),
|
||||
/* DB */
|
||||
tags: z.array(z.string()).optional(),
|
||||
createdAt: z.string(),
|
||||
updatedAt: z.string(),
|
||||
/* Files */
|
||||
file_ids: z.array(z.string()).optional(),
|
||||
/* vision */
|
||||
resendFiles: z.boolean().optional(),
|
||||
imageDetail: eImageDetailSchema.optional(),
|
||||
/* assistant */
|
||||
assistant_id: z.string().optional(),
|
||||
/* agents */
|
||||
agent_id: z.string().optional(),
|
||||
/* assistant + agents */
|
||||
instructions: z.string().optional(),
|
||||
additional_instructions: z.string().optional(),
|
||||
/** Used to overwrite active conversation settings when saving a Preset */
|
||||
presetOverride: z.record(z.unknown()).optional(),
|
||||
stop: z.array(z.string()).optional(),
|
||||
|
|
@ -418,6 +489,8 @@ export const tConversationSchema = z.object({
|
|||
Deprecated fields
|
||||
*/
|
||||
/** @deprecated */
|
||||
suggestions: z.array(z.string()).optional(),
|
||||
/** @deprecated */
|
||||
systemMessage: z.string().nullable().optional(),
|
||||
/** @deprecated */
|
||||
jailbreak: z.boolean().optional(),
|
||||
|
|
@ -433,6 +506,10 @@ export const tConversationSchema = z.object({
|
|||
toneStyle: z.string().nullable().optional(),
|
||||
/** @deprecated */
|
||||
resendImages: z.boolean().optional(),
|
||||
/** @deprecated */
|
||||
agentOptions: tAgentOptionsSchema.nullable().optional(),
|
||||
/** @deprecated Prefer `modelLabel` over `chatGptLabel` */
|
||||
chatGptLabel: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
export const tPresetSchema = tConversationSchema
|
||||
|
|
@ -844,6 +921,71 @@ export const compactAssistantSchema = tConversationSchema
|
|||
.transform(removeNullishValues)
|
||||
.catch(() => ({}));
|
||||
|
||||
export const agentsSchema = tConversationSchema
|
||||
.pick({
|
||||
model: true,
|
||||
modelLabel: true,
|
||||
temperature: true,
|
||||
top_p: true,
|
||||
presence_penalty: true,
|
||||
frequency_penalty: true,
|
||||
resendFiles: true,
|
||||
imageDetail: true,
|
||||
agent_id: true,
|
||||
instructions: true,
|
||||
promptPrefix: true,
|
||||
iconURL: true,
|
||||
greeting: true,
|
||||
maxContextTokens: true,
|
||||
})
|
||||
.transform((obj) => ({
|
||||
...obj,
|
||||
model: obj.model ?? agentsSettings.model.default,
|
||||
modelLabel: obj.modelLabel ?? null,
|
||||
temperature: obj.temperature ?? 1,
|
||||
top_p: obj.top_p ?? 1,
|
||||
presence_penalty: obj.presence_penalty ?? 0,
|
||||
frequency_penalty: obj.frequency_penalty ?? 0,
|
||||
resendFiles:
|
||||
typeof obj.resendFiles === 'boolean' ? obj.resendFiles : agentsSettings.resendFiles.default,
|
||||
imageDetail: obj.imageDetail ?? ImageDetail.auto,
|
||||
agent_id: obj.agent_id ?? undefined,
|
||||
instructions: obj.instructions ?? undefined,
|
||||
promptPrefix: obj.promptPrefix ?? null,
|
||||
iconURL: obj.iconURL ?? undefined,
|
||||
greeting: obj.greeting ?? undefined,
|
||||
maxContextTokens: obj.maxContextTokens ?? undefined,
|
||||
}))
|
||||
.catch(() => ({
|
||||
model: agentsSettings.model.default,
|
||||
modelLabel: null,
|
||||
temperature: 1,
|
||||
top_p: 1,
|
||||
presence_penalty: 0,
|
||||
frequency_penalty: 0,
|
||||
resendFiles: agentsSettings.resendFiles.default,
|
||||
imageDetail: ImageDetail.auto,
|
||||
agent_id: undefined,
|
||||
instructions: undefined,
|
||||
promptPrefix: null,
|
||||
iconURL: undefined,
|
||||
greeting: undefined,
|
||||
maxContextTokens: undefined,
|
||||
}));
|
||||
|
||||
export const compactAgentsSchema = tConversationSchema
|
||||
.pick({
|
||||
model: true,
|
||||
agent_id: true,
|
||||
instructions: true,
|
||||
promptPrefix: true,
|
||||
iconURL: true,
|
||||
greeting: true,
|
||||
spec: true,
|
||||
})
|
||||
.transform(removeNullishValues)
|
||||
.catch(() => ({}));
|
||||
|
||||
export const compactOpenAISchema = tConversationSchema
|
||||
.pick({
|
||||
model: true,
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ export type GroupedConversations = [key: string, TConversation[]][];
|
|||
|
||||
export type TUpdateUserPlugins = {
|
||||
isAssistantTool?: boolean;
|
||||
isAgentTool?: boolean;
|
||||
pluginKey: string;
|
||||
action: string;
|
||||
auth?: unknown;
|
||||
|
|
|
|||
219
packages/data-provider/src/types/agents.ts
Normal file
219
packages/data-provider/src/types/agents.ts
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
import { StepTypes, ContentTypes, ToolCallTypes } from './runs';
|
||||
import type { FunctionToolCall } from './assistants';
|
||||
|
||||
export namespace Agents {
|
||||
export type MessageType = 'human' | 'ai' | 'generic' | 'system' | 'function' | 'tool' | 'remove';
|
||||
|
||||
export type ImageDetail = 'auto' | 'low' | 'high';
|
||||
|
||||
export type MessageContentText = {
|
||||
type: ContentTypes.TEXT;
|
||||
text: string;
|
||||
};
|
||||
|
||||
export type MessageContentImageUrl = {
|
||||
type: 'image_url';
|
||||
image_url: string | { url: string; detail?: ImageDetail };
|
||||
};
|
||||
|
||||
export type MessageContentComplex =
|
||||
| MessageContentText
|
||||
| MessageContentImageUrl
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| (Record<string, any> & { type?: ContentTypes | 'image_url' | 'text_delta' | string })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| (Record<string, any> & { type?: never });
|
||||
|
||||
export type MessageContent = string | MessageContentComplex[];
|
||||
|
||||
/**
|
||||
* A call to a tool.
|
||||
*/
|
||||
export type ToolCall = {
|
||||
/** Type ("tool_call") according to Assistants Tool Call Structure */
|
||||
type: ToolCallTypes.TOOL_CALL;
|
||||
/** The name of the tool to be called */
|
||||
name: string;
|
||||
|
||||
/** The arguments to the tool call */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
args: string | Record<string, any>;
|
||||
|
||||
/** If provided, an identifier associated with the tool call */
|
||||
id?: string;
|
||||
/** If provided, the output of the tool call */
|
||||
output?: string;
|
||||
};
|
||||
|
||||
export type ToolEndEvent = {
|
||||
/** The Step Id of the Tool Call */
|
||||
id: string;
|
||||
/** The Completed Tool Call */
|
||||
tool_call: ToolCall;
|
||||
/** The content index of the tool call */
|
||||
index: number;
|
||||
};
|
||||
|
||||
export type ToolCallContent = {
|
||||
type: ContentTypes.TOOL_CALL;
|
||||
tool_call: ToolCall;
|
||||
};
|
||||
|
||||
/**
|
||||
* A chunk of a tool call (e.g., as part of a stream).
|
||||
* When merging ToolCallChunks (e.g., via AIMessageChunk.__add__),
|
||||
* all string attributes are concatenated. Chunks are only merged if their
|
||||
* values of `index` are equal and not None.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const leftChunks = [
|
||||
* {
|
||||
* name: "foo",
|
||||
* args: '{"a":',
|
||||
* index: 0
|
||||
* }
|
||||
* ];
|
||||
*
|
||||
* const leftAIMessageChunk = new AIMessageChunk({
|
||||
* content: "",
|
||||
* tool_call_chunks: leftChunks
|
||||
* });
|
||||
*
|
||||
* const rightChunks = [
|
||||
* {
|
||||
* name: undefined,
|
||||
* args: '1}',
|
||||
* index: 0
|
||||
* }
|
||||
* ];
|
||||
*
|
||||
* const rightAIMessageChunk = new AIMessageChunk({
|
||||
* content: "",
|
||||
* tool_call_chunks: rightChunks
|
||||
* });
|
||||
*
|
||||
* const result = leftAIMessageChunk.concat(rightAIMessageChunk);
|
||||
* // result.tool_call_chunks is equal to:
|
||||
* // [
|
||||
* // {
|
||||
* // name: "foo",
|
||||
* // args: '{"a":1}'
|
||||
* // index: 0
|
||||
* // }
|
||||
* // ]
|
||||
* ```
|
||||
*
|
||||
* @property {string} [name] - If provided, a substring of the name of the tool to be called
|
||||
* @property {string} [args] - If provided, a JSON substring of the arguments to the tool call
|
||||
* @property {string} [id] - If provided, a substring of an identifier for the tool call
|
||||
* @property {number} [index] - If provided, the index of the tool call in a sequence
|
||||
*/
|
||||
export type ToolCallChunk = {
|
||||
name?: string;
|
||||
|
||||
args?: string;
|
||||
|
||||
id?: string;
|
||||
|
||||
index?: number;
|
||||
|
||||
type?: 'tool_call_chunk';
|
||||
};
|
||||
|
||||
/** Event names are of the format: on_[runnable_type]_(start|stream|end).
|
||||
|
||||
Runnable types are one of:
|
||||
|
||||
llm - used by non chat models
|
||||
chat_model - used by chat models
|
||||
prompt -- e.g., ChatPromptTemplate
|
||||
tool -- LangChain tools
|
||||
chain - most Runnables are of this type
|
||||
Further, the events are categorized as one of:
|
||||
|
||||
start - when the runnable starts
|
||||
stream - when the runnable is streaming
|
||||
end - when the runnable ends
|
||||
start, stream and end are associated with slightly different data payload.
|
||||
|
||||
Please see the documentation for EventData for more details. */
|
||||
export type EventName = string;
|
||||
export type RunStep = {
|
||||
type: StepTypes;
|
||||
id: string; // #new
|
||||
runId?: string; // #new
|
||||
index: number; // #new
|
||||
stepIndex?: number; // #new
|
||||
stepDetails: StepDetails;
|
||||
usage: null | {
|
||||
// Define usage structure if it's ever non-null
|
||||
// prompt_tokens: number; // #new
|
||||
// completion_tokens: number; // #new
|
||||
// total_tokens: number; // #new
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Represents a run step delta i.e. any changed fields on a run step during
|
||||
* streaming.
|
||||
*/
|
||||
export interface RunStepDeltaEvent {
|
||||
/**
|
||||
* The identifier of the run step, which can be referenced in API endpoints.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The delta containing the fields that have changed on the run step.
|
||||
*/
|
||||
delta: ToolCallDelta;
|
||||
}
|
||||
export type StepDetails = MessageCreationDetails | ToolCallsDetails;
|
||||
export type MessageCreationDetails = {
|
||||
type: StepTypes.MESSAGE_CREATION;
|
||||
message_creation: {
|
||||
message_id: string;
|
||||
};
|
||||
};
|
||||
export type ToolCallsDetails = {
|
||||
type: StepTypes.TOOL_CALLS;
|
||||
tool_calls: AgentToolCall[];
|
||||
};
|
||||
export type ToolCallDelta = {
|
||||
type: StepTypes.TOOL_CALLS;
|
||||
tool_calls: ToolCallChunk[];
|
||||
};
|
||||
export type AgentToolCall = FunctionToolCall | ToolCall;
|
||||
export interface ExtendedMessageContent {
|
||||
type?: string;
|
||||
text?: string;
|
||||
input?: string;
|
||||
index?: number;
|
||||
id?: string;
|
||||
name?: string;
|
||||
}
|
||||
/**
|
||||
* Represents a message delta i.e. any changed fields on a message during
|
||||
* streaming.
|
||||
*/
|
||||
export interface MessageDeltaEvent {
|
||||
/**
|
||||
* The identifier of the message, which can be referenced in API endpoints.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The delta containing the fields that have changed on the Message.
|
||||
*/
|
||||
delta: MessageDelta;
|
||||
}
|
||||
/**
|
||||
* The delta containing the fields that have changed on the Message.
|
||||
*/
|
||||
export interface MessageDelta {
|
||||
/**
|
||||
* The content of the message in array of text and/or images.
|
||||
*/
|
||||
content?: MessageContentComplex[];
|
||||
}
|
||||
export type ContentType = ContentTypes.TEXT | 'image_url' | string;
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import type { OpenAPIV3 } from 'openapi-types';
|
||||
import type { AssistantsEndpoint } from 'src/schemas';
|
||||
import type { AssistantsEndpoint, AgentProvider } from 'src/schemas';
|
||||
import type { ContentTypes } from './runs';
|
||||
import type { Agents } from './agents';
|
||||
import type { TFile } from './files';
|
||||
|
||||
export type Schema = OpenAPIV3.SchemaObject & { description?: string };
|
||||
|
|
@ -66,6 +68,8 @@ export interface FileSearchResource {
|
|||
vector_store_ids?: Array<string>;
|
||||
}
|
||||
|
||||
/* Assistant types */
|
||||
|
||||
export type Assistant = {
|
||||
id: string;
|
||||
created_at: number;
|
||||
|
|
@ -136,6 +140,89 @@ export type File = {
|
|||
purpose: 'fine-tune' | 'fine-tune-results' | 'assistants' | 'assistants_output';
|
||||
};
|
||||
|
||||
/* Agent types */
|
||||
|
||||
export type AgentModelParameters = {
|
||||
temperature: number | null;
|
||||
max_context_tokens: number | null;
|
||||
max_output_tokens: number | null;
|
||||
top_p: number | null;
|
||||
frequency_penalty: number | null;
|
||||
presence_penalty: number | null;
|
||||
};
|
||||
|
||||
export type Agent = {
|
||||
id: string;
|
||||
name: string | null;
|
||||
description: string | null;
|
||||
created_at: number;
|
||||
avatar: AgentAvatar | null;
|
||||
file_ids: string[];
|
||||
instructions: string | null;
|
||||
tools?: string[];
|
||||
tool_kwargs?: Record<string, unknown>;
|
||||
tool_resources?: ToolResources;
|
||||
metadata?: Record<string, unknown>;
|
||||
provider: AgentProvider;
|
||||
model: string | null;
|
||||
model_parameters: AgentModelParameters;
|
||||
object: string;
|
||||
};
|
||||
|
||||
export type TAgentsMap = Record<string, Agent | undefined>;
|
||||
|
||||
export type AgentCreateParams = {
|
||||
name?: string | null;
|
||||
description?: string | null;
|
||||
avatar?: AgentAvatar | null;
|
||||
file_ids?: string[];
|
||||
instructions?: string | null;
|
||||
tools?: Array<FunctionTool | string>;
|
||||
provider: AgentProvider;
|
||||
model: string | null;
|
||||
model_parameters: AgentModelParameters;
|
||||
};
|
||||
|
||||
export type AgentUpdateParams = {
|
||||
name?: string | null;
|
||||
description?: string | null;
|
||||
avatar?: AgentAvatar | null;
|
||||
file_ids?: string[];
|
||||
instructions?: string | null;
|
||||
tools?: Array<FunctionTool | string>;
|
||||
tool_resources?: ToolResources;
|
||||
provider?: AgentProvider;
|
||||
model: string | null;
|
||||
model_parameters: AgentModelParameters;
|
||||
};
|
||||
|
||||
export type AgentListParams = {
|
||||
limit?: number;
|
||||
before?: string | null;
|
||||
after?: string | null;
|
||||
order?: 'asc' | 'desc';
|
||||
provider?: AgentProvider;
|
||||
};
|
||||
|
||||
export type AgentListResponse = {
|
||||
object: string;
|
||||
data: Agent[];
|
||||
first_id: string;
|
||||
last_id: string;
|
||||
has_more: boolean;
|
||||
};
|
||||
|
||||
export type AgentFile = {
|
||||
file_id: string;
|
||||
id?: string;
|
||||
temp_file_id?: string;
|
||||
bytes: number;
|
||||
created_at: number;
|
||||
filename: string;
|
||||
object: string;
|
||||
purpose: 'fine-tune' | 'fine-tune-results' | 'agents' | 'agents_output';
|
||||
};
|
||||
|
||||
/**
|
||||
* Details of the Code Interpreter tool call the run step was involved in.
|
||||
* Includes the tool call ID, the code interpreter definition, and the type of tool call.
|
||||
|
|
@ -248,25 +335,6 @@ export enum AnnotationTypes {
|
|||
FILE_PATH = 'file_path',
|
||||
}
|
||||
|
||||
export enum ContentTypes {
|
||||
TEXT = 'text',
|
||||
TOOL_CALL = 'tool_call',
|
||||
IMAGE_FILE = 'image_file',
|
||||
ERROR = 'error',
|
||||
}
|
||||
|
||||
export enum StepTypes {
|
||||
TOOL_CALLS = 'tool_calls',
|
||||
MESSAGE_CREATION = 'message_creation',
|
||||
}
|
||||
|
||||
export enum ToolCallTypes {
|
||||
FUNCTION = 'function',
|
||||
RETRIEVAL = 'retrieval',
|
||||
FILE_SEARCH = 'file_search',
|
||||
CODE_INTERPRETER = 'code_interpreter',
|
||||
}
|
||||
|
||||
export enum StepStatus {
|
||||
IN_PROGRESS = 'in_progress',
|
||||
CANCELLED = 'cancelled',
|
||||
|
|
@ -305,6 +373,7 @@ export type ContentPart = (
|
|||
| RetrievalToolCall
|
||||
| FileSearchToolCall
|
||||
| FunctionToolCall
|
||||
| Agents.AgentToolCall
|
||||
| ImageFile
|
||||
| Text
|
||||
) &
|
||||
|
|
@ -312,13 +381,20 @@ export type ContentPart = (
|
|||
|
||||
export type TMessageContentParts =
|
||||
| { type: ContentTypes.ERROR; text: Text & PartMetadata }
|
||||
| { type: ContentTypes.TEXT; text: Text & PartMetadata }
|
||||
| { type: ContentTypes.TEXT; text: string | (Text & PartMetadata) }
|
||||
| {
|
||||
type: ContentTypes.TOOL_CALL;
|
||||
tool_call: (CodeToolCall | RetrievalToolCall | FileSearchToolCall | FunctionToolCall) &
|
||||
tool_call: (
|
||||
| CodeToolCall
|
||||
| RetrievalToolCall
|
||||
| FileSearchToolCall
|
||||
| FunctionToolCall
|
||||
| Agents.AgentToolCall
|
||||
) &
|
||||
PartMetadata;
|
||||
}
|
||||
| { type: ContentTypes.IMAGE_FILE; image_file: ImageFile & PartMetadata };
|
||||
| { type: ContentTypes.IMAGE_FILE; image_file: ImageFile & PartMetadata }
|
||||
| Agents.MessageContentImageUrl;
|
||||
|
||||
export type StreamContentData = TMessageContentParts & {
|
||||
/** The index of the current content part */
|
||||
|
|
@ -378,14 +454,15 @@ export type ActionMetadata = {
|
|||
oauth_client_secret?: string;
|
||||
};
|
||||
|
||||
/* Assistant types */
|
||||
|
||||
export type Action = {
|
||||
action_id: string;
|
||||
assistant_id: string;
|
||||
type?: string;
|
||||
settings?: Record<string, unknown>;
|
||||
metadata: ActionMetadata;
|
||||
version: number | string;
|
||||
};
|
||||
} & ({ assistant_id: string; agent_id?: never } | { assistant_id?: never; agent_id: string });
|
||||
|
||||
export type AssistantAvatar = {
|
||||
filepath: string;
|
||||
|
|
@ -404,6 +481,13 @@ export type AssistantDocument = {
|
|||
updatedAt?: Date;
|
||||
};
|
||||
|
||||
/* Agent types */
|
||||
|
||||
export type AgentAvatar = {
|
||||
filepath: string;
|
||||
source: string;
|
||||
};
|
||||
|
||||
export enum FilePurpose {
|
||||
Vision = 'vision',
|
||||
FineTune = 'fine-tune',
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import {
|
|||
FunctionTool,
|
||||
AssistantDocument,
|
||||
Action,
|
||||
Agent,
|
||||
AgentCreateParams,
|
||||
AgentUpdateParams,
|
||||
} from './assistants';
|
||||
|
||||
export type MutationOptions<
|
||||
|
|
@ -41,6 +44,8 @@ export type DeletePresetOptions = MutationOptions<PresetDeleteResponse, types.TP
|
|||
|
||||
export type LogoutOptions = MutationOptions<unknown, undefined>;
|
||||
|
||||
/* Assistant mutations */
|
||||
|
||||
export type AssistantAvatarVariables = {
|
||||
assistant_id: string;
|
||||
model: string;
|
||||
|
|
@ -94,6 +99,51 @@ export type DeleteActionVariables = {
|
|||
|
||||
export type DeleteActionOptions = MutationOptions<void, DeleteActionVariables>;
|
||||
|
||||
/* Agent mutations */
|
||||
|
||||
export type AgentAvatarVariables = {
|
||||
agent_id: string;
|
||||
formData: FormData;
|
||||
postCreation?: boolean;
|
||||
};
|
||||
|
||||
export type UpdateAgentActionVariables = {
|
||||
agent_id: string;
|
||||
action_id?: string;
|
||||
metadata: ActionMetadata;
|
||||
functions: FunctionTool[];
|
||||
};
|
||||
|
||||
export type UploadAgentAvatarOptions = MutationOptions<Agent, AgentAvatarVariables>;
|
||||
|
||||
export type CreateAgentMutationOptions = MutationOptions<Agent, AgentCreateParams>;
|
||||
|
||||
export type UpdateAgentVariables = {
|
||||
agent_id: string;
|
||||
data: AgentUpdateParams;
|
||||
};
|
||||
|
||||
export type UpdateAgentMutationOptions = MutationOptions<Agent, UpdateAgentVariables>;
|
||||
|
||||
export type DeleteAgentBody = {
|
||||
agent_id: string;
|
||||
};
|
||||
|
||||
export type DeleteAgentMutationOptions = MutationOptions<void, Pick<DeleteAgentBody, 'agent_id'>>;
|
||||
|
||||
export type UpdateAgentActionResponse = [Agent, Action];
|
||||
export type UpdateAgentActionOptions = MutationOptions<
|
||||
UpdateAgentActionResponse,
|
||||
UpdateAgentActionVariables
|
||||
>;
|
||||
|
||||
export type DeleteAgentActionVariables = {
|
||||
agent_id: string;
|
||||
action_id: string;
|
||||
};
|
||||
|
||||
export type DeleteAgentActionOptions = MutationOptions<void, DeleteAgentActionVariables>;
|
||||
|
||||
export type DeleteConversationOptions = MutationOptions<
|
||||
types.TDeleteConversationResponse,
|
||||
types.TDeleteConversationRequest
|
||||
|
|
|
|||
21
packages/data-provider/src/types/runs.ts
Normal file
21
packages/data-provider/src/types/runs.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
export enum ContentTypes {
|
||||
TEXT = 'text',
|
||||
TOOL_CALL = 'tool_call',
|
||||
IMAGE_FILE = 'image_file',
|
||||
IMAGE_URL = 'image_url',
|
||||
ERROR = 'error',
|
||||
}
|
||||
|
||||
export enum StepTypes {
|
||||
TOOL_CALLS = 'tool_calls',
|
||||
MESSAGE_CREATION = 'message_creation',
|
||||
}
|
||||
|
||||
export enum ToolCallTypes {
|
||||
FUNCTION = 'function',
|
||||
RETRIEVAL = 'retrieval',
|
||||
FILE_SEARCH = 'file_search',
|
||||
CODE_INTERPRETER = 'code_interpreter',
|
||||
/* Agents Tool Call */
|
||||
TOOL_CALL = 'tool_call',
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue