Skip to content

Commit

Permalink
Merge pull request #58 from Callgent/feature/sandbox-service
Browse files Browse the repository at this point in the history
Feature/sandbox service
  • Loading branch information
Jamesp918 authored Aug 30, 2024
2 parents aeba935 + ef176a2 commit 8a2bd99
Show file tree
Hide file tree
Showing 22 changed files with 255 additions and 134 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@prisma/client": "5.18.0",
"axios": "^1.7.5",
"bcrypt": "^5.1.1",
"braces": "^3.0.3",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dot": "^1.1.3",
Expand All @@ -74,7 +75,8 @@
"prisma-soft-delete-middleware": "^1.3.1",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"v8-sandbox": "^3.2.10"
"v8-sandbox": "^3.2.10",
"yaml": "^2.5.0"
},
"devDependencies": {
"@chax-at/transactional-prisma-testing": "^1.1.0",
Expand Down
26 changes: 19 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Warnings:
- You are about to drop the column `content` on the `CallgentFunction` table. All the data in the column will be lost.
- You are about to drop the column `documents` on the `CallgentFunction` table. All the data in the column will be lost.
- You are about to drop the column `fullCode` on the `CallgentFunction` table. All the data in the column will be lost.
- You are about to drop the column `funName` on the `CallgentFunction` table. All the data in the column will be lost.
- You are about to drop the column `params` on the `CallgentFunction` table. All the data in the column will be lost.
- Added the required column `method` to the `CallgentFunction` table without a default value. This is not possible if the table is not empty.
- Added the required column `path` to the `CallgentFunction` table without a default value. This is not possible if the table is not empty.
- Added the required column `signature` to the `CallgentFunction` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "Callgent" ALTER COLUMN "tenantPk" SET DEFAULT (current_setting('tenancy.tenantPk')::int);

-- AlterTable
ALTER TABLE "CallgentFunction" DROP COLUMN "content",
DROP COLUMN "documents",
DROP COLUMN "fullCode",
DROP COLUMN "funName",
DROP COLUMN "params",
ADD COLUMN "method" VARCHAR(15) NOT NULL,
ADD COLUMN "path" VARCHAR(1000) NOT NULL,
ADD COLUMN "signature" JSON NOT NULL,
ADD COLUMN "summary" VARCHAR(511) NOT NULL DEFAULT '',
ADD COLUMN "summary" VARCHAR(1023) NOT NULL DEFAULT '',
ALTER COLUMN "tenantPk" SET DEFAULT (current_setting('tenancy.tenantPk')::int),
ALTER COLUMN "name" SET DATA TYPE VARCHAR(1023);

-- AlterTable
ALTER TABLE "Endpoint" ALTER COLUMN "tenantPk" SET DEFAULT (current_setting('tenancy.tenantPk')::int);

-- AlterTable
ALTER TABLE "EndpointAuth" ALTER COLUMN "tenantPk" SET DEFAULT (current_setting('tenancy.tenantPk')::int);

-- AlterTable
ALTER TABLE "EventListener" ALTER COLUMN "tenantPk" SET DEFAULT (current_setting('tenancy.tenantPk')::int);

-- AlterTable
ALTER TABLE "Task" ALTER COLUMN "tenantPk" SET DEFAULT (current_setting('tenancy.tenantPk')::int);

-- AlterTable
ALTER TABLE "TaskAction" ALTER COLUMN "tenantPk" SET DEFAULT (current_setting('tenancy.tenantPk')::int);

-- AlterTable
ALTER TABLE "User" ALTER COLUMN "tenantPk" SET DEFAULT (current_setting('tenancy.tenantPk')::int);

-- AlterTable
ALTER TABLE "UserIdentity" ALTER COLUMN "tenantPk" SET DEFAULT (current_setting('tenancy.tenantPk')::int);
20 changes: 10 additions & 10 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ model Callgent {
@@index([tenantPk])
}

/// @description callgent function in openAPI.json format
model CallgentFunction {
/// @DtoEntityHidden
pk Int @id @default(autoincrement())
Expand All @@ -186,16 +187,15 @@ model CallgentFunction {
// add to migration.sql
tenantPk Int @default(dbgenerated("(current_setting('tenancy.tenantPk')::int)"))
name String @db.VarChar(255)
/// @description js function name to invoke this callgent function
funName String @db.VarChar(255)
params String[] @db.VarChar(31)
/// @description js function api docs
documents String @db.VarChar(4095)
/// @description js actual code to invoke this callgent function
fullCode String @db.VarChar(1023)
/// @description endpoint id or command or code
content Json @db.Json
/// @DtoCreateApiResponse
/// @DtoUpdateApiResponse
/// @DtoPlainApiResponse
name String @db.VarChar(1023) /// @description `${method} ${path}`
path String @db.VarChar(1000) /// @description openAPI path
method String @db.VarChar(15) /// @description openAPI method
summary String @default("") @db.VarChar(511)
description String @default("") @db.VarChar(1023)
signature Json @db.Json /// @description declaration of API params and responses
// @DtoReadOnly
/// @CustomValidator(EntityIdExists, 'callgent', 'id', ../../infra/repo/validators/entity-exists.validator)
Expand Down
16 changes: 7 additions & 9 deletions prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,23 +144,21 @@ please generate the js function with **full implementation and error handling**!
{
pk: 2,
name: 'map2Function',
prompt: `given below service functions:
class {{=it.callgentName}} {{{~ it.callgentFunctions :fun }}
"function name: {{=fun.name}}": {"params":[{{=fun.params}}], "documents":"{{=fun.documents}}"},
{{~}}
}
and an service \`invoker\` function.
prompt: `given below service APIs:
service {{=it.callgentName}} {{{~ it.callgentFunctions :fun }}
"API: {{=fun.name}}": {"endpoint": "{{=fun.name}}", "summary":"{{=fun.summary}}", {{=fun.description ? '"description":"'+fun.description+'", ':''}}"signature":{{=JSON.stringify(fun.signature)}} },
{{~}}}
Please choose one function to fulfill below request:
Please choose one API to fulfill below request:
{
{{ if (it.funName) { }}"requesting function": "{{=it.funName}}",
{{ if (it.funName) { }}"requesting endpoint": "{{=it.funName}}",
{{ } }}"request from": "{{=it.cepAdaptor}}",
"request_object": {{=JSON.stringify(it.req)}},
}
and code for request_object to chosen function args mapping. if any data missing/unclear/ambiguous from request_object to invocation args, please ask question to the caller in below json.question field.
output a single-line json object:
{ "funName": "the function name to be invoked", "params":"param names of the chosen function", "mapping": "the js function (invoker, request_object)=>{...;return functionArgsArray;}, full implementation to return the **real** args from request_object to invoke the chosen service function. don't use data not exist or ambiguous in request", "question": "question to ask the caller if anything not sure or missing for request to args mapping, *no* guess or assumption of the mapping. null if the mapping is crystal clear." }"}`,
{ "endpoint": "the chosen API endpoint to be invoked", "args":"request params/body/headers/..., with same structure as the signature JSON object(no more args than it), or null if no args needed", "mapping": "if the the request_object is structured (or null if unstructured), generate the js function (request_object)=>{...;return API_signature_args;}, full implementation to return the **real** args from request_object to invoke the API. don't use data not exist or ambiguous in request", "question": "question to ask the caller if anything not sure or missing for request to args mapping, *no* guess or assumption of the mapping. null if the mapping is crystal clear." }"}`,
},
];

Expand Down
38 changes: 20 additions & 18 deletions src/agents/agents.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,25 @@ export class AgentsService {
private readonly eventListenersService: EventListenersService,
) {}

async api2Function(
format: string,
handle: string,
args: { [key: string]: string },
) {
return this.llmService.template(
'api2Function',
{
format,
handle,
...args,
},
{ funName: '', params: [''], documents: '', fullCode: '' },
);
}
// async api2Function(
// format: string,
// handle: string,
// args: { [key: string]: string },
// ) {
// return this.llmService.template(
// 'api2Function',
// {
// format,
// handle,
// ...args,
// },
// { funName: '', params: [''], documents: '', fullCode: '' },
// );
// }

/** args mapping to a single invocation, w/o vars/flows/functions */
/**
* map req to an API function, generate args(with vars/conversations), argsMapping function if applicable
*/
async map2Function(
reqEvent: ClientRequestEvent,
): Promise<void | { event: ClientRequestEvent; callbackName?: string }> {
Expand Down Expand Up @@ -59,7 +61,7 @@ export class AgentsService {
cepAdaptor,
callgentFunctions,
},
{ funName: '', mapping: '', question: '' },
{ endpoint: '', args: '', mapping: '', question: '' },
); // TODO check `funName` exists in callgentFunctions, validating `mapping`
reqEvent.context.map2Function = mapped;

Expand All @@ -83,7 +85,7 @@ export class AgentsService {
throw new HttpException(prEvent.message, statusCode);
} else {
const functions = reqEvent.context.functions.filter(
(f) => f.name == mapped.funName,
(f) => f.name == mapped.endpoint,
);
if (functions?.length != 1)
throw new BadRequestException('Failed to map to function: ' + mapped);
Expand Down
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { TasksModule } from './tasks/tasks.module';
import { UsersModule } from './users/users.module';
import { CallgentTreeModule } from './bff/bff-callgent-tree/callgent-tree.module';
import { BffCallgentFunctionsModule } from './bff/callgent-functions/bff-callgent-functions.module';
import { SandboxModule } from './sandbox/sandbox.module';

@Module({
imports: [
Expand All @@ -45,6 +46,7 @@ import { BffCallgentFunctionsModule } from './bff/callgent-functions/bff-callgen
EmailsModule,
CallgentTreeModule,
BffCallgentFunctionsModule,
SandboxModule,
],
controllers: [AppController],
providers: [AppService],
Expand Down
9 changes: 2 additions & 7 deletions src/bff/bff-callgent-tree/callgent-tree.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,10 @@ export class CallgentTreeController {
if (ep.type == 'CLIENT') {
CEP.push(ep);
} else if (ep.type == 'SERVER') {
const funcs = await this.callgentFunctionsService.findMany({
select: { fullCode: false, callgentId: false, content: false },
ep.children = await this.callgentFunctionsService.findMany({
select: { pk: false, signature: false, callgentId: false },
where: { endpointId: ep.id },
});
ep.children = funcs.map((f) => ({
...f,
id: f.id,
pk: undefined,
}));
SEP.push(ep);
} else if (ep.type == 'EVENT') {
EEP.push(ep);
Expand Down
11 changes: 10 additions & 1 deletion src/bff/callgent-functions/bff-callgent-functions.controller.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { Body, Controller, Inject, Post, Req, UseGuards } from '@nestjs/common';
import {
BadRequestException,
Body,
Controller,
Inject,
Post,
Req,
UseGuards,
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { CallgentApiText } from '../../callgent-functions/callgent-functions.controller';
import { CallgentFunctionsService } from '../../callgent-functions/callgent-functions.service';
import { EndpointDto } from '../../endpoints/dto/endpoint.dto';
import { JwtGuard } from '../../infra/auth/jwt/jwt.guard';
import { EntityIdExists } from '../../infra/repo/validators/entity-exists.validator';
import { EndpointType } from '@prisma/client';

@ApiTags('bff')
@UseGuards(JwtGuard)
Expand Down
5 changes: 3 additions & 2 deletions src/callgent-functions/callgent-functions.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ export class CallgentApiText {

@ApiProperty({
required: false,
description: 'The format of the api content text',
description: 'The format of the api content: json, yaml, text',
enum: ['json', 'yaml', 'text'],
})
@IsOptional()
format?: string;
format?: 'json' | 'yaml' | 'text';
}

@ApiTags('CallgentFunctions')
Expand Down
Loading

0 comments on commit 8a2bd99

Please sign in to comment.