Skip to content

Commit

Permalink
Merge pull request #33 from njhale/enhance/export-ui-server
Browse files Browse the repository at this point in the history
enhance: export custom nextjs/socket.io server
  • Loading branch information
njhale authored Jul 23, 2024
2 parents cc90b3e + 9b50bdd commit 0b2066f
Show file tree
Hide file tree
Showing 73 changed files with 13,826 additions and 12,779 deletions.
2 changes: 1 addition & 1 deletion actions/models.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use server"

import { gpt } from '@/config/env';
import {gpt} from '@/config/env';

export const getModels = async (): Promise<string[]> => {
return (await gpt().listModels()).split('\n');
Expand Down
11 changes: 6 additions & 5 deletions actions/scripts/fetch.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use server"
import { Tool, Block } from '@gptscript-ai/gptscript';
import { SCRIPTS_PATH, gpt } from '@/config/env';

import {Tool, Block} from '@gptscript-ai/gptscript';
import {SCRIPTS_PATH, gpt} from '@/config/env';
import fs from 'fs/promises';

const external = (file: string): boolean => {
Expand Down Expand Up @@ -33,9 +34,9 @@ export const fetchScript = async (file: string): Promise<Tool> => {
}
return {} as Tool;
} catch (e) {
if (`${e}`.includes('no such file')){
if (`${e}`.includes('no such file')) {
return {} as Tool;
}
}
throw e;
}
}
Expand All @@ -44,7 +45,7 @@ export const fetchScripts = async (): Promise<Record<string, string>> => {
try {
const files = await fs.readdir(SCRIPTS_PATH());
const gptFiles = files.filter(file => file.endsWith('.gpt'));

if (gptFiles.length === 0) return {} as Record<string, string>;

const scripts: Record<string, string> = {};
Expand Down
3 changes: 1 addition & 2 deletions actions/scripts/new.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use server"

import { SCRIPTS_PATH } from '@/config/env';
import {SCRIPTS_PATH} from '@/config/env';
import fs from 'fs/promises';

export async function newFile(name: string, instructions: string, fileName: string) {
Expand All @@ -9,7 +9,6 @@ export async function newFile(name: string, instructions: string, fileName: stri

const files = await fs.readdir(scriptsPath);
const gptFiles = files.filter(file => file.endsWith('.gpt'));

if (gptFiles.includes(fileName)) throw new Error('file already exists');
if (!fileName.endsWith('.gpt')) {
throw new Error('file cannot be empty and must end with .gpt');
Expand Down
4 changes: 2 additions & 2 deletions actions/scripts/update.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use server"

import { Tool, GPTScript, Block } from '@gptscript-ai/gptscript';
import { SCRIPTS_PATH, gpt} from '@/config/env';
import {Tool, GPTScript, Block} from '@gptscript-ai/gptscript';
import {SCRIPTS_PATH, gpt} from '@/config/env';
import fs from 'fs/promises';

const external = (file: string): boolean => {
Expand Down
20 changes: 10 additions & 10 deletions actions/threads.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use server"

import { THREADS_DIR } from "@/config/env";
import { gpt } from "@/config/env";
import {THREADS_DIR} from "@/config/env";
import {gpt} from "@/config/env";
import fs from "fs/promises";
import path from 'path';

Expand All @@ -27,14 +27,14 @@ export async function init() {
try {
await fs.access(threadsDir);
} catch (error) {
await fs.mkdir(threadsDir, { recursive: true });
await fs.mkdir(threadsDir, {recursive: true});
}
}

export async function getThreads() {
const threads: Thread[] = [];
const threadsDir = THREADS_DIR();

let threadDirs: void | string[] = [];
try {
threadDirs = await fs.readdir(threadsDir);
Expand All @@ -44,7 +44,7 @@ export async function getThreads() {

if (!threadDirs) return [];

for(let threadDir of threadDirs) {
for (let threadDir of threadDirs) {
const threadPath = path.join(threadsDir, threadDir);
const files = await fs.readdir(threadPath);

Expand Down Expand Up @@ -72,7 +72,7 @@ export async function getThread(id: string) {

async function newThreadName(): Promise<string> {
const threads = await getThreads();
return `New Thread${threads.length ? ' ' + (threads.length+1): '' }`;
return `New Thread${threads.length ? ' ' + (threads.length + 1) : ''}`;
}

export async function generateThreadName(firstMessage: string): Promise<string> {
Expand All @@ -89,7 +89,7 @@ export async function createThread(script: string, firstMessage?: string): Promi
// will probably want something else for this
const id = Math.random().toString(36).substring(7);
const threadPath = path.join(threadsDir, id);
await fs.mkdir(threadPath, { recursive: true });
await fs.mkdir(threadPath, {recursive: true});

const threadMeta = {
name: await newThreadName(),
Expand Down Expand Up @@ -117,13 +117,13 @@ export async function createThread(script: string, firstMessage?: string): Promi

export async function deleteThread(id: string) {
const threadsDir = THREADS_DIR();
const threadPath = path.join(threadsDir,id);
await fs.rm(threadPath, { recursive: true });
const threadPath = path.join(threadsDir, id);
await fs.rm(threadPath, {recursive: true});
}

export async function renameThread(id: string, name: string) {
const threadsDir = THREADS_DIR();
const threadPath = path.join(threadsDir,id);
const threadPath = path.join(threadsDir, id);
const meta = await fs.readFile(path.join(threadPath, META_FILE), "utf-8");
const threadMeta = JSON.parse(meta) as ThreadMeta;
threadMeta.name = name;
Expand Down
10 changes: 5 additions & 5 deletions actions/upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import fs from "node:fs/promises";
import path from "node:path";
import { revalidatePath } from "next/cache";
import { WORKSPACE_DIR } from '@/config/env';
import { Dirent } from 'fs';
import {revalidatePath} from "next/cache";
import {WORKSPACE_DIR} from '@/config/env';
import {Dirent} from 'fs';

export async function uploadFile(formData: FormData) {
const workspaceDir = WORKSPACE_DIR()
await fs.mkdir(workspaceDir, { recursive: true })
await fs.mkdir(workspaceDir, {recursive: true})

const file = formData.get("file") as File;
const arrayBuffer = await file.arrayBuffer();
Expand All @@ -30,7 +30,7 @@ export async function deleteFile(path: string) {
export async function lsWorkspaceFiles(): Promise<string> {
let files: Dirent[] = []
try {
const dirents = await fs.readdir(WORKSPACE_DIR(), { withFileTypes: true });
const dirents = await fs.readdir(WORKSPACE_DIR(), {withFileTypes: true});
files = dirents.filter((dirent: Dirent) => !dirent.isDirectory());
} catch (e) {
if ((e as NodeJS.ErrnoException).code !== 'ENOENT') {
Expand Down
2 changes: 1 addition & 1 deletion actions/workspace.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use server"

import { WORKSPACE_DIR, set_WORKSPACE_DIR } from '@/config/env';
import {WORKSPACE_DIR, set_WORKSPACE_DIR} from '@/config/env';

export const getWorkspaceDir = async () => WORKSPACE_DIR();
export const setWorkspaceDir = async (dir: string) => set_WORKSPACE_DIR(dir);
33 changes: 17 additions & 16 deletions app/api/file/[name]/[tool]/route.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
export const dynamic = 'force-dynamic' // defaults to autover'
import {NextResponse} from "next/server";
import {type Block, Tool} from '@gptscript-ai/gptscript'
import { Positions } from '../route';
import { promises as fs } from 'fs';
import {Positions} from '../route';
import {promises as fs} from 'fs';
import path from 'path';
import { SCRIPTS_PATH, gpt} from '@/config/env';
import {SCRIPTS_PATH, gpt} from '@/config/env';

// Create a datastructure for the tool bindings in the UI
export async function PUT(
req: Request,
{ params }: { params: { slug: string } }
) {
{params}: { params: { slug: string } }
) {
try {
const { name, tool } = params as any;
// @ts-disable
const {name, tool} = params as any;

const script = await gpt().parse(path.join(SCRIPTS_PATH(),`${name}.gpt`));
const script = await gpt().parse(path.join(SCRIPTS_PATH(), `${name}.gpt`));
const updatedScript = updateScript(script, tool, (await req.json()) as Tool);

await fs.writeFile(path.join(SCRIPTS_PATH(),`${name}.gpt`), await gpt().stringify(updatedScript));
return NextResponse.json(await gpt().parse(path.join(SCRIPTS_PATH(),`${name}.gpt`)));
await fs.writeFile(path.join(SCRIPTS_PATH(), `${name}.gpt`), await gpt().stringify(updatedScript));
return NextResponse.json(await gpt().parse(path.join(SCRIPTS_PATH(), `${name}.gpt`)));
} catch (e) {
if (`${e}`.includes('no such file')){
return NextResponse.json({ error: '.gpt file not found' }, { status: 404 });
if (`${e}`.includes('no such file')) {
return NextResponse.json({error: '.gpt file not found'}, {status: 404});
}
console.error(e)
return NextResponse.json({ error: e }, {status: 500});
return NextResponse.json({error: e}, {status: 500});
}
}

Expand All @@ -43,13 +44,13 @@ const updateScript = (script: Block[], tool: string, updatedTool: Tool) => {
const positions = JSON.parse(block.content) as Positions
block.content = JSON.stringify(
Object.fromEntries(Object.entries(positions).map(
([key, value]) => [key === tool ? updatedTool.name : key, value]
)
))+ '\n';
([key, value]) => [key === tool ? updatedTool.name : key, value]
)
)) + '\n';
}
return block;
});
}
updatedScript[toolIndex] = updatedTool;
return updatedScript;
}
}
90 changes: 45 additions & 45 deletions app/api/file/[name]/route.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,64 @@
export const dynamic = 'force-dynamic' // defaults to auto
import { NextRequest, NextResponse } from 'next/server'
import { type Block, Text } from '@gptscript-ai/gptscript'
import { promises as fs } from 'fs';
import {NextRequest, NextResponse} from 'next/server'
import {type Block, Text} from '@gptscript-ai/gptscript'
import {promises as fs} from 'fs';
import path from 'path';
import { SCRIPTS_PATH, gpt } from '@/config/env';
import {SCRIPTS_PATH, gpt} from '@/config/env';
import type {
Node as RFNode,
Node as RFNode,
Edge as RFEdge,
XYPosition,
} from 'reactflow';

export async function DELETE(
_: NextRequest,
{ params }: { params: { slug: string } }
) {
{params}: { params: { slug: string } }
) {
try {
const { name } = params as any;
const {name} = params as any;
await fs.unlink(path.join(`${SCRIPTS_PATH()}/${name}.gpt`));
return NextResponse.json({ success: true });
return NextResponse.json({success: true});
} catch (e) {
return NextResponse.json({ error: e }, { status: 500 });
return NextResponse.json({error: e}, {status: 500});
}
}

export async function GET(
req: NextRequest,
{ params }: { params: { slug: string } }
) {
{params}: { params: { slug: string } }
) {
try {
const { name } = params as any;
const script = await gpt().parse(path.join(SCRIPTS_PATH(),`${name}.gpt`));
const {name} = params as any;
const script = await gpt().parse(path.join(SCRIPTS_PATH(), `${name}.gpt`));
if (req.nextUrl.searchParams.get('nodeify') === 'true') {
const { nodes, edges } = await nodeify(script);
return NextResponse.json({ nodes: nodes, edges: edges });
const {nodes, edges} = await nodeify(script);
return NextResponse.json({nodes: nodes, edges: edges});
}
return NextResponse.json(script);
} catch (e) {
if (`${e}`.includes('no such file')){
return NextResponse.json({ error: '.gpt file not found' }, { status: 404 });
}
return NextResponse.json({ error: e }, {status: 500});
if (`${e}`.includes('no such file')) {
return NextResponse.json({error: '.gpt file not found'}, {status: 404});
}
return NextResponse.json({error: e}, {status: 500});
}
}

export async function PUT(
req: Request,
{ params }: { params: { slug: string } }
) {
req: NextRequest,
{params}: { params: { slug: string } }
) {
try {
const { name } = params as any;
const {name} = params as any;
const nodes = (await req.json()) as RFNode[];
const script = denodeify(nodes);

await fs.writeFile(path.join(SCRIPTS_PATH(),`${name}.gpt`), await gpt().stringify(script));
return NextResponse.json(await gpt().parse(path.join(SCRIPTS_PATH(),`${name}.gpt`)));
await fs.writeFile(path.join(SCRIPTS_PATH(), `${name}.gpt`), await gpt().stringify(script));
return NextResponse.json(await gpt().parse(path.join(SCRIPTS_PATH(), `${name}.gpt`)));
} catch (e) {
if (`${e}`.includes('no such file')){
return NextResponse.json({ error: '.gpt file not found' }, { status: 404 });
}
return NextResponse.json({ error: e }, {status: 500});
if (`${e}`.includes('no such file')) {
return NextResponse.json({error: '.gpt file not found'}, {status: 404});
}
return NextResponse.json({error: e}, {status: 500});
}
}

Expand All @@ -76,19 +76,19 @@ const nodeify = async (script: Block[]) => {
const nodeGraphText = script[nodeGraphIndex] as Text;
const positions = nodeGraphText.content ? JSON.parse(nodeGraphText.content) as Positions : {};

for (let block of script) {
for (const block of script) {
if (block.type === 'text') continue;
const name = block.name ? block.name : 'main';
nodes.push({
id: name,
position: positions[name] ? positions[name] : { x: 0, y: 0 },
position: positions[name] ? positions[name] : {x: 0, y: 0},
data: block,
type: 'customTool',
})

if (!block.tools || !block.tools.length) continue;

for (let tool of block.tools) {
if (!block.tools?.length) continue;

for (const tool of block.tools) {
edges.push({
id: `${name}-${tool}`,
source: name,
Expand All @@ -97,7 +97,7 @@ const nodeify = async (script: Block[]) => {
})
}
}
return { nodes: nodes, edges: edges };
return {nodes: nodes, edges: edges};
} catch (e) {
console.error(e);
throw e;
Expand All @@ -106,20 +106,20 @@ const nodeify = async (script: Block[]) => {

const denodeify = (nodes: RFNode[]): Block[] => {
try {
let script: Block[] = [];
let positions: Positions = {};
const script: Block[] = [];
const positions: Positions = {};

if (nodes.length === 0) return script;
for (let node of nodes) {
const { id, position, data } = node;
for (const node of nodes) {
const {id, position, data} = node;
positions[id] = position
script.push(data as Block);
}
script.unshift({
id: 'nodeGraph',
format:'nodeGraph',
type: 'text',
content: JSON.stringify(positions)+'\n'
script.unshift({
id: 'nodeGraph',
format: 'nodeGraph',
type: 'text',
content: JSON.stringify(positions) + '\n'
});
return script;
} catch (e) {
Expand Down
Loading

0 comments on commit 0b2066f

Please sign in to comment.