Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions actions/auth/auth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use server"

import {cookies} from "next/headers"
import {create, get, list } from "@/actions/common"

export interface AuthProvider {
id?: string
type: string
serviceName?: string
slug?: string
clientID?: string
clientSecret?: string
oauthURL?: string
tokenURL?: string
scopes?: string
redirectURL?: string
disabled?: boolean
}

export async function setCookie(token: string): Promise<void> {
cookies().set("gateway_token", token, {domain: "localhost"})
}

export async function logout(): Promise<void> {
cookies().delete("gateway_token")
}

export async function getAuthProviders(): Promise<AuthProvider[]> {
return await list("auth-providers")
}

export async function createTokenRequest(id: string, oauthServiceName: string): Promise<string> {
return (await create({id: id, serviceName: oauthServiceName} as any, "token-request"))["token-path"]
}

export async function pollForToken(id: string): Promise<string> {
while (true) {
const token = (await get<any>("token-request", id)).token || ""
if (token != "") {
return token
}

await new Promise(r => setTimeout(r, 1000))
}
}
45 changes: 45 additions & 0 deletions actions/common.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use server"

import {cookies} from "next/headers"
import { GATEWAY_URL } from "@/config/env"

export async function list<T>(path: string): Promise<T> {
return request(undefined, path, "GET")
}

export async function get<T>(path: string, id: string): Promise<T> {
if (id !== "") {
path = `${path}/${id}`
}
return request(undefined, path, "GET")
}

export async function update<T>(obj: T, path: string): Promise<T> {
return request(obj, path, "PATCH")
}

export async function create<T>(obj: T, path: string): Promise<T> {
return request(obj, path, "POST")
}

export async function del<T>(id: string, path: string): Promise<any> {
return request(undefined, `${path}/${id}`, "DELETE")
}

export async function request<T>(obj: T, path: string, method: string): Promise<any> {
const resp = await fetch(`${GATEWAY_URL()}/api/${path}`, {
method: method,
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${(cookies().get("gateway_token") || {}).value || ""}`
},
body: obj ? JSON.stringify(obj) : undefined
})

const res = await resp.json()
if (resp.status < 200 || resp.status >= 400) {
throw Error(`Unexpected status ${resp.status}: ${res.error}`)
}

return res
}
5 changes: 5 additions & 0 deletions actions/gateway.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"use server"

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

export const getGatewayUrl = async () => GATEWAY_URL();
21 changes: 21 additions & 0 deletions actions/gptscript.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"use server"

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

export const rootTool = async (toolContent: string): Promise<Tool> => {
const parsedTool = await gpt().parseTool(toolContent);
for (let block of parsedTool) {
if (block.type === 'tool') return block;
}
return {} as Tool;
}

export const parse = async (toolContent: string): Promise<Tool[]> => {
const parsedTool = await gpt().parseTool(toolContent);
return parsedTool.filter((block) => block.type === 'tool') as Tool[];
}

export const stringify = async (script: Block[]): Promise<string> => {
return gpt().stringify(script);
}
10 changes: 10 additions & 0 deletions actions/me/me.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { get } from "@/actions/common"

export interface Me {
username: string
email: string
}

export async function getMe(): Promise<Me> {
return await get("me", "")
}
105 changes: 105 additions & 0 deletions actions/me/scripts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"use server"

import {create, del, get, list, update} from "@/actions/common"
import { GATEWAY_URL, gpt } from "@/config/env"
import { Block } from "@gptscript-ai/gptscript"

export interface ParsedScript extends Script {
agentName?: string
description?: string
script: Block[];
}

export interface Script {
displayName?: string
createdAt?: string
updatedAt?: string
content?: string
id?: number
owner?: string
tags?: string[]
visibility?: string
publicURL?: string
slug?: string
}

export interface ScriptsQuery {
owner?: string
filter?: string
limit?: number
continue?: string
search?: string
}

export interface ScriptsQueryResponse {
continue?: string
scripts?: Script[]
}

export interface ParsedScriptsQueryResponse {
continue?: string
scripts?: ParsedScript[]
}

// note: can combine these two functions into one to save cycles
function getDescription(script: Block[]): string {
for (let tool of script) {
if (tool.type === 'text') continue;
return tool.description || '';
}
return '';
}
function getName(script: Block[]): string {
for (let tool of script) {
if (tool.type === 'text') continue;
return tool.name || '';
}
return '';
}

export async function getScripts(query?: ScriptsQuery): Promise<ParsedScriptsQueryResponse> {
let scripts: ScriptsQueryResponse = {};
if (!query) scripts = await list("scripts");
else scripts = await list("scripts?" + new URLSearchParams(query as any).toString());

let parsedScripts: ParsedScript[] = [];
for (const script of scripts.scripts || []) {
const parsedScript = await gpt().parseTool(script.content || '');

parsedScripts.push({ ...script,
script: parsedScript,
description: getDescription(parsedScript),
agentName: getName(parsedScript)
});
}

return { continue: scripts.continue, scripts: parsedScripts };

}

export async function getScript(id: string): Promise<ParsedScript> {
const scripts = await get("scripts", id.replace(`${GATEWAY_URL()}/`, '')) as Script
const parsedScript = await gpt().parseTool(scripts.content || '')
return { ...scripts,
script: parsedScript,
description: getDescription(parsedScript),
agentName: getName(parsedScript)
}
}

export async function createScript(script: Script) {
return await create(script, `scripts`)
}

export async function updateScript(script: Script) {
return await update(script, `scripts/${script.id}`)
}

export async function deleteScript(script: Script) {
return await del(`${script.id}`, "scripts")
}

export async function getScriptContent(scriptURL: string) {
const script = await gpt().parse(scriptURL);
return gpt().stringify(script);
}
7 changes: 4 additions & 3 deletions actions/threads.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use server"

import {THREADS_DIR, WORKSPACE_DIR} from "@/config/env";
import {GATEWAY_URL, THREADS_DIR, WORKSPACE_DIR} from "@/config/env";
import {gpt} from "@/config/env";
import fs from "fs/promises";
import path from 'path';
Expand All @@ -19,6 +19,7 @@ export type ThreadMeta = {
created: Date;
updated: Date;
id: string;
scriptId?: string;
script: string;
workspace: string;
}
Expand Down Expand Up @@ -87,9 +88,8 @@ export async function generateThreadName(firstMessage: string): Promise<string>
return summary.text();
}

export async function createThread(script: string, firstMessage?: string): Promise<Thread> {
export async function createThread(script: string, firstMessage?: string, scriptId?: string): Promise<Thread> {
const threadsDir = THREADS_DIR();
script = script.replace('.gpt', '');

// will probably want something else for this
const id = Math.random().toString(36).substring(7);
Expand All @@ -103,6 +103,7 @@ export async function createThread(script: string, firstMessage?: string): Promi
updated: new Date(),
workspace: WORKSPACE_DIR(),
id,
scriptId: scriptId || '',
script,
}
const threadState = '';
Expand Down
56 changes: 0 additions & 56 deletions app/api/file/[name]/[tool]/route.ts

This file was deleted.

Loading