@browserlessapi/inferlo 0.0.0-stage → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +130 -2
  3. package/dist/ai/index.d.ts +138 -0
  4. package/dist/ai/index.js +450 -0
  5. package/dist/ai/index.js.map +1 -0
  6. package/dist/ai/providers.d.ts +150 -0
  7. package/dist/ai/providers.js +294 -0
  8. package/dist/ai/providers.js.map +1 -0
  9. package/dist/app.d.ts +109 -0
  10. package/dist/app.js +419 -0
  11. package/dist/app.js.map +1 -0
  12. package/dist/auth.d.ts +29 -0
  13. package/dist/auth.js +61 -0
  14. package/dist/auth.js.map +1 -0
  15. package/dist/cli/main.d.ts +2 -0
  16. package/dist/cli/main.js +520 -0
  17. package/dist/cli/main.js.map +1 -0
  18. package/dist/client-ip.d.ts +7 -0
  19. package/dist/client-ip.js +27 -0
  20. package/dist/client-ip.js.map +1 -0
  21. package/dist/cron.d.ts +17 -0
  22. package/dist/cron.js +143 -0
  23. package/dist/cron.js.map +1 -0
  24. package/dist/db/memory.d.ts +2 -0
  25. package/dist/db/memory.js +128 -0
  26. package/dist/db/memory.js.map +1 -0
  27. package/dist/db/migrate.d.ts +87 -0
  28. package/dist/db/migrate.js +471 -0
  29. package/dist/db/migrate.js.map +1 -0
  30. package/dist/db/postgres.d.ts +37 -0
  31. package/dist/db/postgres.js +338 -0
  32. package/dist/db/postgres.js.map +1 -0
  33. package/dist/db/table.d.ts +117 -0
  34. package/dist/db/table.js +274 -0
  35. package/dist/db/table.js.map +1 -0
  36. package/dist/db/types.d.ts +36 -0
  37. package/dist/db/types.js +2 -0
  38. package/dist/db/types.js.map +1 -0
  39. package/dist/describe.d.ts +74 -0
  40. package/dist/describe.js +69 -0
  41. package/dist/describe.js.map +1 -0
  42. package/dist/env.d.ts +19 -0
  43. package/dist/env.js +72 -0
  44. package/dist/env.js.map +1 -0
  45. package/dist/errors.d.ts +40 -0
  46. package/dist/errors.js +99 -0
  47. package/dist/errors.js.map +1 -0
  48. package/dist/index.d.ts +31 -0
  49. package/dist/index.js +20 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/jobs.d.ts +177 -0
  52. package/dist/jobs.js +374 -0
  53. package/dist/jobs.js.map +1 -0
  54. package/dist/mcp.d.ts +22 -0
  55. package/dist/mcp.js +171 -0
  56. package/dist/mcp.js.map +1 -0
  57. package/dist/model.d.ts +36 -0
  58. package/dist/model.js +76 -0
  59. package/dist/model.js.map +1 -0
  60. package/dist/openapi.d.ts +6 -0
  61. package/dist/openapi.js +74 -0
  62. package/dist/openapi.js.map +1 -0
  63. package/dist/rate-limit.d.ts +45 -0
  64. package/dist/rate-limit.js +93 -0
  65. package/dist/rate-limit.js.map +1 -0
  66. package/dist/route.d.ts +131 -0
  67. package/dist/route.js +28 -0
  68. package/dist/route.js.map +1 -0
  69. package/dist/schema.d.ts +164 -0
  70. package/dist/schema.js +442 -0
  71. package/dist/schema.js.map +1 -0
  72. package/dist/serve.d.ts +11 -0
  73. package/dist/serve.js +86 -0
  74. package/dist/serve.js.map +1 -0
  75. package/dist/testing.d.ts +16 -0
  76. package/dist/testing.js +30 -0
  77. package/dist/testing.js.map +1 -0
  78. package/llms.txt +27 -0
  79. package/package.json +82 -4
  80. package/templates/app/AGENTS.md +55 -0
  81. package/templates/app/CLAUDE.md +1 -0
  82. package/templates/app/README.md +16 -0
  83. package/templates/app/_env.example +5 -0
  84. package/templates/app/_gitignore +3 -0
  85. package/templates/app/package.json.tpl +32 -0
  86. package/templates/app/src/app.ts +38 -0
  87. package/templates/app/src/models.ts +31 -0
  88. package/templates/app/src/routes/health.ts +3 -0
  89. package/templates/app/src/routes/notes.ts +56 -0
  90. package/templates/app/src/server.ts +26 -0
  91. package/templates/app/test/notes.test.ts +50 -0
  92. package/templates/app/tsconfig.json +17 -0
@@ -0,0 +1,294 @@
1
+ /**
2
+ * AI providers. Each one turns a provider-neutral request into an HTTP call.
3
+ * openaiCompatible() covers OpenAI, DeepSeek, Qwen (DashScope), Groq, Together, OpenRouter,
4
+ * Ollama, vLLM, LM Studio and any other server that speaks the Chat Completions API.
5
+ */
6
+ import { InferloError } from "../errors.js";
7
+ /** Base64 data and media type of an image given as base64 or a data: URL, or null for a remote URL. */
8
+ export function imageData(image) {
9
+ if ("base64" in image)
10
+ return { base64: image.base64, mediaType: image.mediaType };
11
+ const match = /^data:([^;,]+);base64,(.*)$/s.exec(image.url);
12
+ return match ? { mediaType: match[1], base64: match[2] } : null;
13
+ }
14
+ /** The URL to send to Chat Completions servers: the URL itself, or a data: URL for base64. */
15
+ function imageUrl(image) {
16
+ return "base64" in image ? `data:${image.mediaType};base64,${image.base64}` : image.url;
17
+ }
18
+ /** Raised when a provider call fails. retryable errors move on to the next fallback model. */
19
+ export class ProviderError extends InferloError {
20
+ retryable;
21
+ constructor(provider, status, body) {
22
+ const retryable = status === 0 || status === 408 || status === 409 || status === 429 || status >= 500;
23
+ super("IL5006", `${provider} returned ${status || "a network error"}: ${body.slice(0, 300)}`, {
24
+ status: 502,
25
+ expose: false,
26
+ fix: status === 401 || status === 403 ? `Check the API key for ${provider}.` : retryable ? "Add a fallback model to the alias in createApp({ ai })." : undefined,
27
+ });
28
+ this.retryable = retryable;
29
+ }
30
+ }
31
+ async function post(provider, fetchImpl, url, headers, body, signal) {
32
+ let response;
33
+ try {
34
+ response = await fetchImpl(url, { method: "POST", headers: { "content-type": "application/json", ...headers }, body: JSON.stringify(body), signal });
35
+ }
36
+ catch (error) {
37
+ if (error.name === "AbortError")
38
+ throw error;
39
+ throw new ProviderError(provider, 0, String(error.message ?? error));
40
+ }
41
+ if (!response.ok)
42
+ throw new ProviderError(provider, response.status, await response.text().catch(() => ""));
43
+ return response;
44
+ }
45
+ /** Parse a server-sent events stream into data payloads. */
46
+ export async function* sseData(body) {
47
+ const reader = body.getReader();
48
+ const decoder = new TextDecoder();
49
+ let buffer = "";
50
+ while (true) {
51
+ const { value, done } = await reader.read();
52
+ if (done)
53
+ break;
54
+ buffer += decoder.decode(value, { stream: true }).replace(/\r\n/g, "\n");
55
+ let index;
56
+ while ((index = buffer.indexOf("\n\n")) !== -1) {
57
+ const event = buffer.slice(0, index);
58
+ buffer = buffer.slice(index + 2);
59
+ const data = event
60
+ .split("\n")
61
+ .filter((line) => line.startsWith("data:"))
62
+ .map((line) => line.slice(5).trimStart())
63
+ .join("\n");
64
+ if (data)
65
+ yield data;
66
+ }
67
+ }
68
+ }
69
+ export function openaiCompatible(options) {
70
+ const name = options.name ?? "openai-compatible";
71
+ const base = options.baseURL.replace(/\/+$/, "");
72
+ const fetchImpl = options.fetch ?? fetch;
73
+ const headers = { ...(options.apiKey ? { authorization: `Bearer ${options.apiKey}` } : {}), ...options.headers };
74
+ const body = (r, stream) => {
75
+ const out = { model: r.model, messages: r.messages.map(openaiMessage), stream };
76
+ if (r.tools?.length)
77
+ out.tools = r.tools.map((tool) => ({ type: "function", function: { name: tool.name, description: tool.description, parameters: tool.inputSchema } }));
78
+ if (r.temperature !== undefined)
79
+ out.temperature = r.temperature;
80
+ if (r.maxTokens !== undefined)
81
+ out.max_tokens = r.maxTokens;
82
+ if (r.json) {
83
+ out.response_format =
84
+ options.nativeStructuredOutput && r.jsonSchema
85
+ ? { type: "json_schema", json_schema: { name: "output", schema: r.jsonSchema, strict: false } }
86
+ : { type: "json_object" };
87
+ }
88
+ if (stream)
89
+ out.stream_options = { include_usage: true };
90
+ return out;
91
+ };
92
+ return {
93
+ name,
94
+ async generate(r) {
95
+ const response = await post(name, fetchImpl, `${base}/chat/completions`, headers, body(r, false), r.signal);
96
+ const data = (await response.json());
97
+ const message = data.choices?.[0]?.message;
98
+ const toolCalls = (message?.tool_calls ?? []).map((call) => ({ id: call.id, name: call.function?.name ?? "", input: parseArguments(call.function?.arguments) }));
99
+ return {
100
+ text: message?.content ?? "",
101
+ usage: { inputTokens: data.usage?.prompt_tokens ?? 0, outputTokens: data.usage?.completion_tokens ?? 0 },
102
+ ...(toolCalls.length ? { toolCalls } : {}),
103
+ };
104
+ },
105
+ async *stream(r) {
106
+ const response = await post(name, fetchImpl, `${base}/chat/completions`, headers, body(r, true), r.signal);
107
+ for await (const data of sseData(response.body)) {
108
+ if (data === "[DONE]")
109
+ break;
110
+ const chunk = JSON.parse(data);
111
+ const text = chunk.choices?.[0]?.delta?.content;
112
+ if (text)
113
+ yield text;
114
+ if (chunk.usage)
115
+ yield { usage: { inputTokens: chunk.usage.prompt_tokens ?? 0, outputTokens: chunk.usage.completion_tokens ?? 0 } };
116
+ }
117
+ },
118
+ async embed({ model, input, signal }) {
119
+ const response = await post(name, fetchImpl, `${base}/embeddings`, headers, { model, input }, signal);
120
+ const data = (await response.json());
121
+ const embeddings = [...data.data].sort((a, b) => a.index - b.index).map((d) => d.embedding);
122
+ return { embeddings, usage: { inputTokens: data.usage?.prompt_tokens ?? 0, outputTokens: 0 } };
123
+ },
124
+ };
125
+ }
126
+ /** Chat Completions message shape, including tool calls and tool results. */
127
+ function openaiMessage(m) {
128
+ if (m.role === "tool")
129
+ return { role: "tool", tool_call_id: m.toolCallId, content: m.content };
130
+ if (m.role === "assistant" && m.toolCalls?.length) {
131
+ return {
132
+ role: "assistant",
133
+ content: m.content || null,
134
+ tool_calls: m.toolCalls.map((call) => ({ id: call.id, type: "function", function: { name: call.name, arguments: JSON.stringify(call.input ?? {}) } })),
135
+ };
136
+ }
137
+ if (m.images?.length) {
138
+ return {
139
+ role: m.role,
140
+ content: [...(m.content ? [{ type: "text", text: m.content }] : []), ...m.images.map((image) => ({ type: "image_url", image_url: { url: imageUrl(image) } }))],
141
+ };
142
+ }
143
+ return { role: m.role, content: m.content };
144
+ }
145
+ /** Tool arguments arrive as a JSON string. Invalid JSON is passed on as the raw string, so the tool reports the problem to the model. */
146
+ function parseArguments(text) {
147
+ if (!text)
148
+ return {};
149
+ try {
150
+ return JSON.parse(text);
151
+ }
152
+ catch {
153
+ return text;
154
+ }
155
+ }
156
+ /** Messages API shape: tool calls are tool_use blocks, and consecutive tool results become one user message. */
157
+ function anthropicMessages(messages) {
158
+ const out = [];
159
+ for (const m of messages) {
160
+ if (m.role === "system")
161
+ continue;
162
+ if (m.role === "tool") {
163
+ const block = { type: "tool_result", tool_use_id: m.toolCallId, content: m.content, ...(m.isError ? { is_error: true } : {}) };
164
+ const last = out.at(-1);
165
+ if (last && last.role === "user" && Array.isArray(last.content) && last.content.every((b) => b.type === "tool_result")) {
166
+ last.content.push(block);
167
+ }
168
+ else
169
+ out.push({ role: "user", content: [block] });
170
+ continue;
171
+ }
172
+ if (m.role === "assistant" && m.toolCalls?.length) {
173
+ out.push({
174
+ role: "assistant",
175
+ content: [...(m.content ? [{ type: "text", text: m.content }] : []), ...m.toolCalls.map((call) => ({ type: "tool_use", id: call.id, name: call.name, input: call.input ?? {} }))],
176
+ });
177
+ continue;
178
+ }
179
+ if (m.images?.length) {
180
+ // Images first, then the text: Anthropic recommends this order.
181
+ const images = m.images.map((image) => {
182
+ const data = imageData(image);
183
+ return { type: "image", source: data ? { type: "base64", media_type: data.mediaType, data: data.base64 } : { type: "url", url: image.url } };
184
+ });
185
+ out.push({ role: m.role, content: [...images, ...(m.content ? [{ type: "text", text: m.content }] : [])] });
186
+ continue;
187
+ }
188
+ out.push({ role: m.role, content: m.content });
189
+ }
190
+ return out;
191
+ }
192
+ export function openai(options) {
193
+ return openaiCompatible({
194
+ name: "openai",
195
+ baseURL: options.baseURL ?? "https://api.openai.com/v1",
196
+ apiKey: options.apiKey,
197
+ headers: options.organization ? { "openai-organization": options.organization } : undefined,
198
+ nativeStructuredOutput: true,
199
+ fetch: options.fetch,
200
+ });
201
+ }
202
+ /** Local models through Ollama's OpenAI-compatible endpoint. */
203
+ export function ollama(options = {}) {
204
+ return openaiCompatible({ name: "ollama", baseURL: options.baseURL ?? "http://127.0.0.1:11434/v1", fetch: options.fetch });
205
+ }
206
+ export function anthropic(options) {
207
+ const name = "anthropic";
208
+ const base = (options.baseURL ?? "https://api.anthropic.com").replace(/\/+$/, "");
209
+ const fetchImpl = options.fetch ?? fetch;
210
+ const headers = { "x-api-key": options.apiKey, "anthropic-version": options.version ?? "2023-06-01" };
211
+ const body = (r, stream) => {
212
+ const system = r.messages.filter((m) => m.role === "system").map((m) => m.content).join("\n\n");
213
+ const out = {
214
+ model: r.model,
215
+ max_tokens: r.maxTokens ?? 4096,
216
+ messages: anthropicMessages(r.messages),
217
+ stream,
218
+ };
219
+ if (system)
220
+ out.system = system;
221
+ if (r.tools?.length)
222
+ out.tools = r.tools.map((tool) => ({ name: tool.name, description: tool.description, input_schema: tool.inputSchema }));
223
+ if (r.temperature !== undefined)
224
+ out.temperature = r.temperature;
225
+ return out;
226
+ };
227
+ return {
228
+ name,
229
+ async generate(r) {
230
+ const response = await post(name, fetchImpl, `${base}/v1/messages`, headers, body(r, false), r.signal);
231
+ const data = (await response.json());
232
+ const text = (data.content ?? []).filter((c) => c.type === "text").map((c) => c.text ?? "").join("");
233
+ const toolCalls = (data.content ?? []).filter((c) => c.type === "tool_use").map((c) => ({ id: c.id ?? "", name: c.name ?? "", input: c.input ?? {} }));
234
+ return { text, usage: { inputTokens: data.usage?.input_tokens ?? 0, outputTokens: data.usage?.output_tokens ?? 0 }, ...(toolCalls.length ? { toolCalls } : {}) };
235
+ },
236
+ async *stream(r) {
237
+ const response = await post(name, fetchImpl, `${base}/v1/messages`, headers, body(r, true), r.signal);
238
+ const usage = { inputTokens: 0, outputTokens: 0 };
239
+ for await (const data of sseData(response.body)) {
240
+ const event = JSON.parse(data);
241
+ if (event.type === "content_block_delta" && event.delta?.type === "text_delta" && event.delta.text)
242
+ yield event.delta.text;
243
+ if (event.type === "message_start")
244
+ usage.inputTokens = event.message?.usage?.input_tokens ?? 0;
245
+ if (event.type === "message_delta")
246
+ usage.outputTokens = event.usage?.output_tokens ?? 0;
247
+ }
248
+ yield { usage };
249
+ },
250
+ };
251
+ }
252
+ /** Gemini through Google's OpenAI-compatible endpoint. */
253
+ export function gemini(options) {
254
+ return openaiCompatible({ name: "gemini", baseURL: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: options.apiKey, fetch: options.fetch });
255
+ }
256
+ /**
257
+ * Deterministic provider for tests. respond receives the request and returns the text,
258
+ * or { toolCalls } to call tools (see request.tools and the "tool" messages for results).
259
+ *
260
+ * mockProvider({ respond: () => JSON.stringify({ priority: "urgent", summary: "Server down" }) })
261
+ * mockProvider({ respond: (r) => (r.messages.at(-1)!.role === "tool" ? "Done" : { toolCalls: [{ name: "createTicket", input: { title: "Hi" } }] }) })
262
+ */
263
+ export function mockProvider(options) {
264
+ const calls = [];
265
+ const tokens = (s) => Math.ceil(s.length / 4);
266
+ return {
267
+ name: options.name ?? "mock",
268
+ calls,
269
+ async generate(r) {
270
+ calls.push(r);
271
+ const reply = await options.respond(r);
272
+ const text = typeof reply === "string" ? reply : (reply.text ?? "");
273
+ const toolCalls = typeof reply === "string" ? [] : (reply.toolCalls ?? []).map((call, i) => ({ id: call.id ?? `call_${calls.length}_${i + 1}`, name: call.name, input: call.input ?? {} }));
274
+ const usage = { inputTokens: tokens(r.messages.map((m) => m.content).join("")), outputTokens: tokens(text + (toolCalls.length ? JSON.stringify(toolCalls) : "")) };
275
+ return { text, usage, ...(toolCalls.length ? { toolCalls } : {}) };
276
+ },
277
+ async *stream(r) {
278
+ const { text, usage } = await this.generate(r);
279
+ for (const part of text.match(/.{1,8}/gs) ?? [])
280
+ yield part;
281
+ yield { usage };
282
+ },
283
+ async embed({ input }) {
284
+ const embeddings = input.map((s) => {
285
+ const v = new Array(8).fill(0);
286
+ for (let i = 0; i < s.length; i++)
287
+ v[i % 8] += s.charCodeAt(i) / 1000;
288
+ return v;
289
+ });
290
+ return { embeddings, usage: { inputTokens: tokens(input.join("")), outputTokens: 0 } };
291
+ },
292
+ };
293
+ }
294
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/ai/providers.ts"],"names":[],"mappings":"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"}
package/dist/app.d.ts ADDED
@@ -0,0 +1,109 @@
1
+ /**
2
+ * createApp wires models, routes, database, auth and AI together and gives you a standard
3
+ * fetch(Request) => Response handler that runs on Node, Bun, Deno and edge runtimes.
4
+ */
5
+ import { type AI, type AIConfig } from "./ai/index.ts";
6
+ import { type Db } from "./db/table.ts";
7
+ import type { Adapter } from "./db/types.ts";
8
+ import { type AppDescription } from "./describe.ts";
9
+ import type { AnyModel } from "./model.ts";
10
+ import { type AppDb, type AppUser, type Method, type RouteDef } from "./route.ts";
11
+ import { type RateLimitConfig } from "./rate-limit.ts";
12
+ import { type AppJobs, type JobQueueConfig, type JobSource } from "./jobs.ts";
13
+ export interface AuthConfig {
14
+ /** Return the signed-in user for this request, or null. */
15
+ resolve(req: Request, ctx: {
16
+ db: AppDb;
17
+ url: URL;
18
+ }): AppUser | null | undefined | Promise<AppUser | null | undefined>;
19
+ /** Roles of a user, checked when a route uses auth: "<role>". Default: user.roles ?? []. */
20
+ roles?(user: AppUser): string[];
21
+ }
22
+ export interface CorsConfig {
23
+ /** Allowed origins, or "*". */
24
+ origin: string | string[];
25
+ credentials?: boolean;
26
+ headers?: string[];
27
+ maxAge?: number;
28
+ }
29
+ export interface MiddlewareContext {
30
+ req: Request;
31
+ url: URL;
32
+ state: Record<string, unknown>;
33
+ }
34
+ export type Middleware = (ctx: MiddlewareContext, next: () => Promise<Response>) => Promise<Response>;
35
+ export interface Logger {
36
+ info(message: string, data?: unknown): void;
37
+ error(message: string, data?: unknown): void;
38
+ }
39
+ /** Anything that contains routes: a route, an array, or a module (import * as tickets from "./routes/tickets.ts"). */
40
+ export type RouteSource = RouteDef | readonly RouteSource[] | {
41
+ readonly [name: string]: unknown;
42
+ };
43
+ export interface AppConfig<Models extends readonly AnyModel[]> {
44
+ /** Shown in OpenAPI, MCP and describe. */
45
+ name?: string;
46
+ version?: string;
47
+ description?: string;
48
+ models?: Models;
49
+ routes?: RouteSource[];
50
+ /** Background jobs and crons: jobs, cron(schedule, job) values, arrays or modules (import * as jobs from "./jobs.ts"). */
51
+ jobs?: JobSource[];
52
+ /** Where queued jobs are kept: { store: "memory" } (default) or { store: "database" } (Postgres table inferlo_jobs, shared by every instance). */
53
+ jobQueue?: JobQueueConfig;
54
+ /** Database adapter. Default: memory(). Use postgres() from "@browserlessapi/inferlo/postgres" in production. */
55
+ db?: Adapter;
56
+ auth?: AuthConfig;
57
+ ai?: AIConfig;
58
+ cors?: boolean | CorsConfig;
59
+ middleware?: Middleware[];
60
+ /** Path for the OpenAPI document, or false to disable. Default "/openapi.json". */
61
+ openapi?: string | false;
62
+ /** Path for the MCP endpoint, or false to disable. Default "/mcp" when any route sets tool. */
63
+ mcp?: string | false;
64
+ /** Maximum request body in bytes. Default 1 MiB. */
65
+ maxBodySize?: number;
66
+ /** Where route rateLimit counts are kept: { store: "memory" } (default) or { store: "database" } (Postgres, shared by every instance). */
67
+ rateLimit?: RateLimitConfig;
68
+ /**
69
+ * Behind a load balancer or proxy that sets X-Forwarded-For: true uses its first address as the client IP
70
+ * (for rateLimit by "ip"). Default false, because clients can send that header themselves.
71
+ */
72
+ trustProxy?: boolean;
73
+ /** Include error messages of unexpected (500) errors in responses. Default false. */
74
+ exposeErrors?: boolean;
75
+ logger?: Logger;
76
+ }
77
+ export interface RequestOptions {
78
+ method?: Method | Lowercase<Method> | "OPTIONS" | "HEAD";
79
+ headers?: Record<string, string>;
80
+ /** JSON body. */
81
+ json?: unknown;
82
+ body?: BodyInit;
83
+ query?: Record<string, string | number | boolean | undefined>;
84
+ /** Run as this user, skipping auth.resolve (tests only, never reachable over HTTP). */
85
+ as?: AppUser | null;
86
+ }
87
+ export interface App<Models extends readonly AnyModel[]> {
88
+ readonly name: string;
89
+ readonly version: string;
90
+ readonly routes: readonly RouteDef[];
91
+ readonly models: Models;
92
+ readonly db: Db<Models>;
93
+ readonly ai: AI;
94
+ /** Background jobs: app.jobs.enqueue(job, input), app.jobs.start() to run them, app.jobs.runDue() in tests. */
95
+ readonly jobs: AppJobs;
96
+ /** Standard fetch handler: export default app works on Bun, Deno and Cloudflare Workers. */
97
+ fetch(req: Request, ...rest: unknown[]): Promise<Response>;
98
+ /** In-process request for tests: await app.request("/tickets", { method: "POST", json: {...}, as: user }). */
99
+ request(path: string, options?: RequestOptions): Promise<Response>;
100
+ /** Start an HTTP server (Node, Bun or Deno). */
101
+ listen(port?: number, hostname?: string): Promise<{
102
+ port: number;
103
+ close(): Promise<void>;
104
+ }>;
105
+ /** Machine-readable map of the whole app: routes, models, auth and AI. */
106
+ describe(): AppDescription;
107
+ openapi(): Record<string, unknown>;
108
+ }
109
+ export declare function createApp<const Models extends readonly AnyModel[] = []>(config?: AppConfig<Models>): App<Models>;