Skip to content

Commit

Permalink
add quick-tools schema, api, saving, etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
cztomsik committed Mar 20, 2024
1 parent d723038 commit d95f582
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 57 deletions.
1 change: 1 addition & 0 deletions src/api.zig
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ pub usingnamespace @import("api/log.zig");
pub usingnamespace @import("api/models.zig");
pub usingnamespace @import("api/prompts.zig");
pub usingnamespace @import("api/proxy.zig");
pub usingnamespace @import("api/quick-tools.zig");
pub usingnamespace @import("api/system-info.zig");
23 changes: 23 additions & 0 deletions src/api/quick-tools.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const std = @import("std");
const fr = @import("fridge");
const schema = @import("../schema.zig");

pub fn @"GET /quick-tools"(db: *fr.Session) ![]const schema.QuickTool {
return db.findAll(fr.query(schema.QuickTool).orderBy(.id, .asc));
}

pub fn @"GET /quick-tools/:id"(db: *fr.Session, id: u32) !schema.QuickTool {
return try db.find(schema.QuickTool, id) orelse error.NotFound;
}

pub fn @"POST /quick-tools"(db: *fr.Session, data: schema.QuickTool) !schema.QuickTool {
return db.create(schema.QuickTool, data);
}

pub fn @"PUT /quick-tools/:id"(db: *fr.Session, id: u32, data: schema.QuickTool) !schema.QuickTool {
return try db.update(schema.QuickTool, id, data) orelse error.NotFound;
}

pub fn @"DELETE /quick-tools/:id"(db: *fr.Session, id: u32) !void {
try db.delete(schema.QuickTool, id);
}
6 changes: 6 additions & 0 deletions src/app/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ export const api = {
createPrompt: data => client.post("prompts", data),
deletePrompt: id => client.delete(`prompts/${id}`),

listQuickTools: () => client.query("quick-tools"),
createQuickTool: data => client.post("quick-tools", data),
getQuickTool: id => client.query(`quick-tools/${id}`),
updateQuickTool: (id, data) => client.put(`quick-tools/${id}`, data),
deleteQuickTool: id => client.delete(`quick-tools/${id}`),

getSystemInfo: () => client.query("system-info"),
getLog: () => client.query("log"),
}
8 changes: 4 additions & 4 deletions src/app/quick-tools/CreateTool.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Page } from "../_components"
import { api } from "../api"
import { router } from "../router"
import { ToolForm } from "./ToolForm"
import { examples } from "./_examples"

export const CreateTool = () => {
const tool = {
name: "New Tool",
description: "",
prompt: "",
}

const createTool = async (tool: any) => {
const id = examples.length + 1
examples.push({ id, ...tool })
const createTool = async data => {
const { id } = await api.createQuickTool(data)
router.navigate(`/quick-tools/${id}`)
}

Expand Down
24 changes: 16 additions & 8 deletions src/app/quick-tools/EditTool.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
import { Page } from "../_components"
import { IconButton, Modal, Page } from "../_components"
import { ToolForm } from "./ToolForm"
import { err } from "../_util"
import { examples } from "./_examples"
import { useQuery } from "../_hooks"
import { api } from "../api"
import { router } from "../router"
import { Trash2 } from "lucide"

export const EditTool = ({ params: { id } }) => {
const tool = examples.find(t => t.id === +id) ?? err("Tool not found")
const { data: tool } = useQuery(id && api.getQuickTool(id))

const handleSubmit = data => {
Object.assign(tool, data)
const handleGenerate = async data => {
await api.updateQuickTool(id, data)
router.navigate(`/quick-tools/${id}`)
}

const handleDelete = () =>
Modal.confirm("Are you sure you want to delete this tool?")
.then(() => api.deleteQuickTool(id))
.then(() => router.navigate("/quick-tools", true))

return (
<Page>
<Page.Header title="Edit Tool"></Page.Header>
<Page.Header title="Edit Tool">
<IconButton title="Delete" icon={Trash2} onClick={handleDelete} />
</Page.Header>

<Page.Content>
<ToolForm tool={tool} onSubmit={handleSubmit} />
<ToolForm tool={tool} onSubmit={handleGenerate} />
</Page.Content>
</Page>
)
Expand Down
83 changes: 42 additions & 41 deletions src/app/quick-tools/QuickTool.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,55 @@
import { SquarePen } from "lucide"
import { AutoScroll, Button, Form, FormGrid, GenerationProgress, IconButton, Markdown, Page, Field } from "../_components"
import { useGenerate } from "../_hooks"
import { err, parseVars, template, humanize } from "../_util"
import { examples } from "./_examples"
import { useGenerate, useQuery } from "../_hooks"
import { parseVars, template, humanize } from "../_util"
import { api } from "../api"

export const QuickTool = ({ params: { id } }) => {
const { generate, result, ...progress } = useGenerate()

const tool = examples.find(t => t.id === +id) ?? err("Tool not found")
const variableNames = parseVars(tool.prompt)
const { data: tool } = useQuery(id && api.getQuickTool(id))

const handleSubmit = data => generate({ prompt: template(tool.prompt, data) })

return (
<Page>
<Page.Header title={tool.name}>
<IconButton title="Edit" icon={SquarePen} href={`/quick-tools/${id}/edit`} />
</Page.Header>

<Page.Content class="bg-neutral-2">
<Form class="vstack" onSubmit={handleSubmit}>
<p class="py-4 text-neutral-11 text-center">{tool.description}</p>

<FormGrid class="mt-4 w-full max-w-lg self-center">
{variableNames.map(name => (
<>
<label>{humanize(name)}</label>
{name.endsWith("text") ? <Field as="textarea" name={name} rows={10} /> : <Field name={name} />}
</>
))}

<div />
<Button submit>Generate</Button>
</FormGrid>
</Form>
</Page.Content>

<Page.DetailsPane sizes={[400, 500, 800]}>
<div class="vstack overflow-hidden">
<h3 class="px-4 py-2 uppercase font-medium text(sm neutral-11)">Result</h3>
<div class="px-4 py-2 overflow-auto">
{/* TODO: This will trigger a re-render on every token */}
{result.value === "" && <p class="text-neutral-11">Click generate to see the result</p>}

<Markdown input={result} class="mb-2" />
<GenerationProgress {...progress} />
<AutoScroll />
tool && (
<Page>
<Page.Header title={tool.name}>
<IconButton title="Edit" icon={SquarePen} href={`/quick-tools/${id}/edit`} />
</Page.Header>

<Page.Content class="bg-neutral-2">
<Form class="vstack" onSubmit={handleSubmit}>
<p class="py-4 text-neutral-11 text-center">{tool.description}</p>

<FormGrid class="mt-4 w-full max-w-lg self-center">
{parseVars(tool.prompt).map(name => (
<>
<label>{humanize(name)}</label>
{name.endsWith("text") ? <Field as="textarea" name={name} rows={10} /> : <Field name={name} />}
</>
))}

<div />
<Button submit>Generate</Button>
</FormGrid>
</Form>
</Page.Content>

<Page.DetailsPane sizes={[400, 500, 800]}>
<div class="vstack overflow-hidden">
<h3 class="px-4 py-2 uppercase font-medium text(sm neutral-11)">Result</h3>
<div class="px-4 py-2 overflow-auto">
{/* TODO: This will trigger a re-render on every token */}
{result.value === "" && <p class="text-neutral-11">Click generate to see the result</p>}

<Markdown input={result} class="mb-2" />
<GenerationProgress {...progress} />
<AutoScroll />
</div>
</div>
</div>
</Page.DetailsPane>
</Page>
</Page.DetailsPane>
</Page>
)
)
}
15 changes: 12 additions & 3 deletions src/app/quick-tools/QuickTools.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Plus } from "lucide"
import { Alert, Button, IconButton, Link, Page, Table } from "../_components"
import { examples } from "./_examples"
import { useQuery } from "../_hooks"
import { api } from "../api"

export const QuickTools = () => {
const { data: tools = [] } = useQuery(api.listQuickTools())

return (
<Page>
<Page.Header title="Quick Tools">
Expand All @@ -12,7 +15,7 @@ export const QuickTools = () => {
<Page.Content>
<Alert class="mb-8">
<strong>This feature is experimental.</strong> <br />
No changes are saved to the database
The database schema and API may change without notice.
</Alert>

<Table class="max-w-5xl">
Expand All @@ -24,7 +27,13 @@ export const QuickTools = () => {
</tr>
</thead>
<tbody>
{examples.map(t => (
{!tools.length && (
<tr>
<td colSpan={3}>No tools found</td>
</tr>
)}

{tools.map(t => (
<tr>
<td>
<Link class="text-blue-11" href={`/quick-tools/${t.id}`}>
Expand Down
9 changes: 8 additions & 1 deletion src/db_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,11 @@ CREATE TABLE "ChatMessage" (
role TEXT NOT NULL,
content TEXT NOT NULL,
FOREIGN KEY (chat_id) REFERENCES Chat(id) ON DELETE CASCADE
) STRICT;
) STRICT;

CREATE TABLE "QuickTool" (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT NOT NULL,
prompt TEXT NOT NULL
) STRICT;
7 changes: 7 additions & 0 deletions src/schema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,10 @@ pub const ChatMessage = struct {
role: []const u8,
content: []const u8,
};

pub const QuickTool = struct {
id: ?u32 = null,
name: []const u8,
description: []const u8,
prompt: []const u8,
};

0 comments on commit d95f582

Please sign in to comment.