Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

Allows for automatic generation of Hono API compatible with GPTs. Endpoints' inputs and outputs need to be specified via types from which the Open API spec is generated automatically and available via /gpt/schema endpoint.

⚠️ Breaking changes introduced in v23 & 24:

  • nothingToJson doesn't take the generic TResponse anymore. The type is inferred from the endpoint definition. The endpoint definition doesn't need the requestSchema, requestDesc and responseDesc defined anymore. The descriptions are inferred from the schema description.
  • jsonToJson doesn't take the generic TRequest and TResponse anymore. Types are inferred from the endpoint definition. The endpoint definition doesn't need the requestDesc and responseDesc defined anymore. The descriptions are inferred from the schema description.

Usage example:

import { GptApi } from "https://esm.town/v/xkonti/gptApiFramework"; import { z } from "npm:zod"; /** * COMMON TYPES */ const ResponseCommandSchema = z.object({ feedback: z.string().describe("Feedback regarding submitted action"), command: z.string().describe("The command for the Mediator AI to follow strictly"), data: z.string().optional().describe("Additional data related to the given command"), }).describe("Contains feedback and further instructions to follow"); /** * INITIALIZE API */ const api = new GptApi({ url: "https://xkonti-planoverseerai.web.val.run", title: "Overseer AI API", description: "The API for interacting with the Overseer AI", version: "1.0.0", policyGetter: async () => { const { markdownToPrettyPage } = await import("https://esm.town/v/xkonti/markdownToHtmlPage?v=5"); return await markdownToPrettyPage("# Privacy Policy\n\n## Section 1..."); }, }); /** * REQUIREMENTS GATHERING ENDPOINTS */ api.nothingToJson({ verb: "POST", path: "/newproblem", operationId: "new-problem", desc: "Endpoint for informing Overseer AI about a new problem presented by the User", responseSchema: ResponseCommandSchema, responseDesc: "Instruction on how to proceed with the new problem", }, async (ctx) => { return { feedback: "User input downloaded. Problem analysis is required.", command: await getPrompt("analyze-problem"), data: "", }; }); export default api.serve();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import type { Context } from "npm:hono@3";
import { Hono } from "npm:hono@3";
import { z } from "npm:zod";
import { zodToJsonSchema } from "npm:zod-to-json-schema";
export type HttpVerb = "get" | "post" | "put" | "delete" | "patch";
/**
* Base interface for defining an endpoint.
* This does not include request or response schemas.
*/
export interface EndpointDefBase {
verb: HttpVerb;
path: string;
desc: string;
operationId: string;
}
/**
* Used o define an endpoint with request and response schemas
* along with descriptions for each.
*/
export interface EndpointDefinition extends EndpointDefBase {
requestSchema: z.Schema | null;
requestDesc: string | null;
responseSchema: z.Schema | null;
responseDesc: string | null;
}
/**
* Used to define an input-only endpoint with a request schema,
* but no response schema.
*/
export interface InEndpointDefinition<TRequestSchema extends z.Schema> extends EndpointDefBase {
requestSchema: TRequestSchema;
}
/**
* Used to define an output-only endpoint with a response schema,
* but no request schema.
*/
export interface OutEndpointDefinition<TResponseSchema extends z.Schema> extends EndpointDefBase {
responseSchema: TResponseSchema;
}
/**
* Used to define an input/output endpoint with both a request and
* response schema.
*/
export interface InOutEndpointDefinition<TRequestSchema extends z.Schema, TResponseSchema extends z.Schema>
extends EndpointDefBase {
requestSchema: TRequestSchema;
responseSchema: TResponseSchema;
}
/**
* The API info object that is used to describe the API to the GPT.
*/
export interface ApiInfo {
/**
* The URL of the API. This should match the URL of your Val.
*/
url: string;
/**
* The name of the API. It gives the GPT an idea about the purpose of the API.
*/
title: string;
/**
* A short description of the API. It gives the GPT an idea about the purpose of the API.
*/
description: string;
/**
* The version of the API. Required by the OpenAPI spec.
*/
version: string;
/**
* An optional function that returns the policy to be used available at `/privacypolicy`.
*/
policyGetter?: (() => string) | (() => Promise<string>);
}
/**
* Returns the JSON schema for a Zod schema.
* @param schema The Zod schema to convert.
* @returns The generated JSON schema.
*/
function getSchemaDesc(schema: z.Schema | null) {
if (!schema) return null;
return zodToJsonSchema(schema, {
name: "schema",
target: "openApi3",
}).definitions?.schema ?? null;
}
/**
* Describes the schema of an endpoint.
May 29, 2024