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
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
convex_local_backend.sqlite3
convex_local_storage/

# Local OpenAPI sources service state
sources/data/*.sqlite
sources/data/*.sqlite-shm
sources/data/*.sqlite-wal

# Cloudflare Workers local state
.wrangler/
.dev.vars

# Generated push env file
executor/.env.executor-push

Expand Down
153 changes: 151 additions & 2 deletions bun.lock

Large diffs are not rendered by default.

30 changes: 24 additions & 6 deletions dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
* Reads all configuration from the root .env file (auto-loaded by Bun).
*
* Starts:
* 1. Convex cloud dev function watcher ─┐
* 2. Executor web UI (port 4312) ├─ all started concurrently
* 3. Assistant server (port 3000) │
* 4. Discord bot ─┘
* 1. Sources catalog API (port 4343) ─┐
* 2. Convex cloud dev function watcher │
* 3. CF sandbox host worker (port 8787) ├─ all started concurrently
* 4. Executor web UI (port 4312) │
* 5. Assistant server (port 3000) │
* 6. Discord bot ─┘
*
* All processes are killed when this script exits (Ctrl+C).
* PIDs are written to .dev.pids for use with `bun run kill:all`.
Expand All @@ -21,8 +23,10 @@ import { unlinkSync } from "node:fs";
const PID_FILE = join(import.meta.dir, ".dev.pids");

const colors = {
sources: "\x1b[33m", // yellow
convex: "\x1b[36m", // cyan
web: "\x1b[34m", // blue
sandbox: "\x1b[91m", // bright red
assistant: "\x1b[32m", // green
bot: "\x1b[35m", // magenta
reset: "\x1b[0m",
Expand Down Expand Up @@ -117,7 +121,8 @@ process.on("SIGTERM", shutdown);
// ── Kill stale processes from a previous run ──

const EXECUTOR_WEB_PORT = Number(Bun.env.EXECUTOR_WEB_PORT ?? 4312);
const DEV_PORTS = [3000, EXECUTOR_WEB_PORT];
const SANDBOX_PORT = Number(Bun.env.SANDBOX_PORT ?? 8787);
const DEV_PORTS = [3000, EXECUTOR_WEB_PORT, SANDBOX_PORT];

async function killStaleProcesses() {
let killed = 0;
Expand Down Expand Up @@ -164,6 +169,11 @@ const urls = resolveExecutorUrls();
console.log(prefix("convex", `Using Convex URL: ${urls.convexUrl}`));
console.log(prefix("convex", `Using executor HTTP URL: ${urls.executorUrl}`));

// 1. Sources catalog API
spawnService("sources", ["bun", "--hot", "server.ts"], {
cwd: "./sources",
});

// 2. Start Convex file watcher (non-blocking — repushes on changes)
spawnService("convex", [
"bunx", "convex", "dev",
Expand All @@ -172,7 +182,15 @@ spawnService("convex", [
cwd: "./executor",
});

// 3. Everything else in parallel
// 3. CF sandbox host worker (local wrangler dev for iterating on the worker)
spawnService("sandbox", [
"bunx", "wrangler", "dev",
"--port", String(SANDBOX_PORT),
], {
cwd: "./executor/packages/sandbox-host",
});

// 4. Everything else in parallel
spawnService("web", ["bun", "run", "dev"], {
cwd: "./executor/apps/web",
});
Expand Down
64 changes: 53 additions & 11 deletions executor/apps/web/src/components/code-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,62 @@ function countAllTools(node: NamespaceNode): number {

/** TS helper types for OpenAPI indexed access (same as typechecker.ts) */
const OPENAPI_HELPER_TYPES = `
type _OrEmpty<T> = [T] extends [never] ? {} : T;
type _Normalize<T> = Exclude<T, undefined | null>;
type _OrEmpty<T> = [_Normalize<T>] extends [never] ? {} : _Normalize<T>;
type _Simplify<T> = { [K in keyof T]: T[K] } & {};
type _ParamsOf<Op> =
Op extends { parameters: infer P } ? P :
Op extends { parameters?: infer P } ? P :
never;
type _ParamAt<Op, K extends "query" | "path" | "header" | "cookie"> =
_ParamsOf<Op> extends { [P in K]?: infer V } ? V : never;
type _BodyOf<Op> =
Op extends { requestBody?: infer B } ? B :
Op extends { requestBody: infer B } ? B :
never;
type _BodyContent<B> =
B extends { content: infer C }
? C extends Record<string, infer V> ? V : never
: never;
type ToolInput<Op> = _Simplify<
_OrEmpty<Op extends { parameters: { query: infer Q } } ? { [K in keyof Q]: Q[K] } : never> &
_OrEmpty<Op extends { parameters: { path: infer P } } ? { [K in keyof P]: P[K] } : never> &
_OrEmpty<Op extends { requestBody: { content: { "application/json": infer B } } } ? B : never>
_OrEmpty<_ParamAt<Op, "query">> &
_OrEmpty<_ParamAt<Op, "path">> &
_OrEmpty<_ParamAt<Op, "header">> &
_OrEmpty<_ParamAt<Op, "cookie">> &
_OrEmpty<_BodyContent<_BodyOf<Op>>>
>;
type ToolOutput<Op> =
Op extends { responses: { 200: { content: { "application/json": infer R } } } } ? R :
Op extends { responses: { 201: { content: { "application/json": infer R } } } } ? R :
Op extends { responses: { 202: { content: { "application/json": infer R } } } } ? R :
Op extends { responses: { 204: unknown } } ? void :
Op extends { responses: { 205: unknown } } ? void :
unknown;
type _ResponsesOf<Op> = Op extends { responses: infer R } ? R : never;
type _RespAt<Op, Code extends PropertyKey> =
_ResponsesOf<Op> extends { [K in Code]?: infer R } ? R : never;
type _ResponsePayload<R> =
[R] extends [never] ? never :
R extends { content: infer C }
? C extends Record<string, infer V> ? V : unknown
: R extends { schema: infer S } ? S : unknown;
type _HasStatus<Op, Code extends PropertyKey> =
[_RespAt<Op, Code>] extends [never] ? false : true;
type _PayloadAt<Op, Code extends PropertyKey> =
Code extends 204 | 205
? (_HasStatus<Op, Code> extends true ? void : never)
: _ResponsePayload<_RespAt<Op, Code>>;
type _FirstKnown<T extends readonly unknown[]> =
T extends readonly [infer H, ...infer Rest]
? [H] extends [never] ? _FirstKnown<Rest> : H
: unknown;
type ToolOutput<Op> = _FirstKnown<[
_PayloadAt<Op, 200>,
_PayloadAt<Op, 201>,
_PayloadAt<Op, 202>,
_PayloadAt<Op, 203>,
_PayloadAt<Op, 204>,
_PayloadAt<Op, 205>,
_PayloadAt<Op, 206>,
_PayloadAt<Op, 207>,
_PayloadAt<Op, 208>,
_PayloadAt<Op, 226>,
_PayloadAt<Op, "default">,
unknown
]>;
`;

function generateToolsDts(tools: ToolDescriptor[], dtsSources: Set<string>): string {
Expand Down
Loading