Skip to content

Commit 35cdab9

Browse files
committed
feat: add support for interacting with the gateway
This commit adds and refactors many things. - Deletes the old build flow which was no longer used. - Adds actions for interacting with the gateway such as: * scripts * me * auth - Adds a new explore page which allows users to view and interact with scripts stored on the gateway. - Many updated styles and components. Signed-off-by: tylerslaton <[email protected]>
1 parent d9c9925 commit 35cdab9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1530
-3856
lines changed

actions/auth/auth.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"use server"
2+
3+
import {cookies} from "next/headers"
4+
import {create, get, list } from "@/actions/common"
5+
6+
export interface AuthProvider {
7+
id?: string
8+
type: string
9+
serviceName?: string
10+
slug?: string
11+
clientID?: string
12+
clientSecret?: string
13+
oauthURL?: string
14+
tokenURL?: string
15+
scopes?: string
16+
redirectURL?: string
17+
disabled?: boolean
18+
}
19+
20+
export async function setCookie(token: string): Promise<void> {
21+
cookies().set("gateway_token", token, {domain: "localhost"})
22+
}
23+
24+
export async function logout(): Promise<void> {
25+
cookies().delete("gateway_token")
26+
}
27+
28+
export async function getAuthProviders(): Promise<AuthProvider[]> {
29+
return await list("auth-providers")
30+
}
31+
32+
export async function createTokenRequest(id: string, oauthServiceName: string): Promise<string> {
33+
return (await create({id: id, serviceName: oauthServiceName} as any, "token-request"))["token-path"]
34+
}
35+
36+
export async function pollForToken(id: string): Promise<string> {
37+
while (true) {
38+
const token = (await get<any>("token-request", id)).token || ""
39+
if (token != "") {
40+
return token
41+
}
42+
43+
await new Promise(r => setTimeout(r, 1000))
44+
}
45+
}

actions/common.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"use server"
2+
3+
import {cookies} from "next/headers"
4+
import { GATEWAY_URL } from "@/config/env"
5+
6+
export async function list<T>(path: string): Promise<T> {
7+
return request(undefined, path, "GET")
8+
}
9+
10+
export async function get<T>(path: string, id: string): Promise<T> {
11+
if (id !== "") {
12+
path = `${path}/${id}`
13+
}
14+
return request(undefined, path, "GET")
15+
}
16+
17+
export async function update<T>(obj: T, path: string): Promise<T> {
18+
return request(obj, path, "PATCH")
19+
}
20+
21+
export async function create<T>(obj: T, path: string): Promise<T> {
22+
return request(obj, path, "POST")
23+
}
24+
25+
export async function del<T>(id: string, path: string): Promise<any> {
26+
return request(undefined, `${path}/${id}`, "DELETE")
27+
}
28+
29+
export async function request<T>(obj: T, path: string, method: string): Promise<any> {
30+
const resp = await fetch(`${GATEWAY_URL()}/api/${path}`, {
31+
method: method,
32+
headers: {
33+
"Content-type": "application/json",
34+
Authorization: `Bearer ${(cookies().get("gateway_token") || {}).value || ""}`
35+
},
36+
body: obj ? JSON.stringify(obj) : undefined
37+
})
38+
39+
const res = await resp.json()
40+
if (resp.status < 200 || resp.status >= 400) {
41+
throw Error(`Unexpected status ${resp.status}: ${res.error}`)
42+
}
43+
44+
return res
45+
}

actions/gateway.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"use server"
2+
3+
import { GATEWAY_URL } from '@/config/env';
4+
5+
export const getGatewayUrl = async () => GATEWAY_URL();

actions/gptscript.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use server"
2+
3+
import { Tool, Block } from '@gptscript-ai/gptscript';
4+
import { gpt } from '@/config/env';
5+
6+
export const rootTool = async (toolContent: string): Promise<Tool> => {
7+
const parsedTool = await gpt().parseTool(toolContent);
8+
for (let block of parsedTool) {
9+
if (block.type === 'tool') return block;
10+
}
11+
return {} as Tool;
12+
}
13+
14+
export const parse = async (toolContent: string): Promise<Tool[]> => {
15+
const parsedTool = await gpt().parseTool(toolContent);
16+
return parsedTool.filter((block) => block.type === 'tool') as Tool[];
17+
}
18+
19+
export const stringify = async (script: Block[]): Promise<string> => {
20+
return gpt().stringify(script);
21+
}

actions/me/me.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { get } from "@/actions/common"
2+
3+
export interface Me {
4+
username: string
5+
email: string
6+
}
7+
8+
export async function getMe(): Promise<Me> {
9+
return await get("me", "")
10+
}

actions/me/scripts.tsx

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"use server"
2+
3+
import {create, del, get, list, update} from "@/actions/common"
4+
import { GATEWAY_URL, gpt } from "@/config/env"
5+
import { Block } from "@gptscript-ai/gptscript"
6+
7+
export interface ParsedScript extends Script {
8+
agentName?: string
9+
description?: string
10+
script: Block[];
11+
}
12+
13+
export interface Script {
14+
displayName?: string
15+
createdAt?: string
16+
updatedAt?: string
17+
content?: string
18+
id?: number
19+
owner?: string
20+
tags?: string[]
21+
visibility?: string
22+
publicURL?: string
23+
slug?: string
24+
}
25+
26+
export interface ScriptsQuery {
27+
owner?: string
28+
filter?: string
29+
limit?: number
30+
continue?: string
31+
search?: string
32+
}
33+
34+
export interface ScriptsQueryResponse {
35+
continue?: string
36+
scripts?: Script[]
37+
}
38+
39+
export interface ParsedScriptsQueryResponse {
40+
continue?: string
41+
scripts?: ParsedScript[]
42+
}
43+
44+
// note: can combine these two functions into one to save cycles
45+
function getDescription(script: Block[]): string {
46+
for (let tool of script) {
47+
if (tool.type === 'text') continue;
48+
return tool.description || '';
49+
}
50+
return '';
51+
}
52+
function getName(script: Block[]): string {
53+
for (let tool of script) {
54+
if (tool.type === 'text') continue;
55+
return tool.name || '';
56+
}
57+
return '';
58+
}
59+
60+
export async function getScripts(query?: ScriptsQuery): Promise<ParsedScriptsQueryResponse> {
61+
let scripts: ScriptsQueryResponse = {};
62+
if (!query) scripts = await list("scripts");
63+
else scripts = await list("scripts?" + new URLSearchParams(query as any).toString());
64+
65+
let parsedScripts: ParsedScript[] = [];
66+
for (const script of scripts.scripts || []) {
67+
const parsedScript = await gpt().parseTool(script.content || '');
68+
69+
parsedScripts.push({ ...script,
70+
script: parsedScript,
71+
description: getDescription(parsedScript),
72+
agentName: getName(parsedScript)
73+
});
74+
}
75+
76+
return { continue: scripts.continue, scripts: parsedScripts };
77+
78+
}
79+
80+
export async function getScript(id: string): Promise<ParsedScript> {
81+
const scripts = await get("scripts", id.replace(`${GATEWAY_URL()}/`, '')) as Script
82+
const parsedScript = await gpt().parseTool(scripts.content || '')
83+
return { ...scripts,
84+
script: parsedScript,
85+
description: getDescription(parsedScript),
86+
agentName: getName(parsedScript)
87+
}
88+
}
89+
90+
export async function createScript(script: Script) {
91+
return await create(script, `scripts`)
92+
}
93+
94+
export async function updateScript(script: Script) {
95+
return await update(script, `scripts/${script.id}`)
96+
}
97+
98+
export async function deleteScript(script: Script) {
99+
return await del(`${script.id}`, "scripts")
100+
}
101+
102+
export async function getScriptContent(scriptURL: string) {
103+
const script = await gpt().parse(scriptURL);
104+
return gpt().stringify(script);
105+
}

actions/threads.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use server"
22

3-
import {THREADS_DIR, WORKSPACE_DIR} from "@/config/env";
3+
import {GATEWAY_URL, THREADS_DIR, WORKSPACE_DIR} from "@/config/env";
44
import {gpt} from "@/config/env";
55
import fs from "fs/promises";
66
import path from 'path';
@@ -19,6 +19,7 @@ export type ThreadMeta = {
1919
created: Date;
2020
updated: Date;
2121
id: string;
22+
scriptId?: string;
2223
script: string;
2324
workspace: string;
2425
}
@@ -87,9 +88,8 @@ export async function generateThreadName(firstMessage: string): Promise<string>
8788
return summary.text();
8889
}
8990

90-
export async function createThread(script: string, firstMessage?: string): Promise<Thread> {
91+
export async function createThread(script: string, firstMessage?: string, scriptId?: string): Promise<Thread> {
9192
const threadsDir = THREADS_DIR();
92-
script = script.replace('.gpt', '');
9393

9494
// will probably want something else for this
9595
const id = Math.random().toString(36).substring(7);
@@ -103,6 +103,7 @@ export async function createThread(script: string, firstMessage?: string): Promi
103103
updated: new Date(),
104104
workspace: WORKSPACE_DIR(),
105105
id,
106+
scriptId: scriptId || '',
106107
script,
107108
}
108109
const threadState = '';

app/api/file/[name]/[tool]/route.ts

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)