@browserlessapi/inferlo 0.4.0 → 0.5.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.
- package/README.md +15 -3
- package/dist/adonisjs.d.ts +33 -0
- package/dist/adonisjs.js +30 -0
- package/dist/adonisjs.js.map +1 -0
- package/dist/ai/index.d.ts +15 -8
- package/dist/ai/index.js +39 -13
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/providers.js +5 -4
- package/dist/ai/providers.js.map +1 -1
- package/dist/ai/public.d.ts +20 -0
- package/dist/ai/public.js +17 -0
- package/dist/ai/public.js.map +1 -0
- package/dist/ai/tool.d.ts +47 -0
- package/dist/ai/tool.js +85 -0
- package/dist/ai/tool.js.map +1 -0
- package/dist/ai-client.d.ts +3 -0
- package/dist/ai-client.js +8 -0
- package/dist/ai-client.js.map +1 -0
- package/dist/app.d.ts +87 -2
- package/dist/app.js +471 -127
- package/dist/app.js.map +1 -1
- package/dist/cli/main.js +21 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/config.d.ts +16 -0
- package/dist/config.js +101 -0
- package/dist/config.js.map +1 -0
- package/dist/db/table.d.ts +31 -0
- package/dist/db/table.js +140 -1
- package/dist/db/table.js.map +1 -1
- package/dist/deprecation.d.ts +23 -0
- package/dist/deprecation.js +70 -0
- package/dist/deprecation.js.map +1 -0
- package/dist/describe.d.ts +27 -5
- package/dist/describe.js +14 -2
- package/dist/describe.js.map +1 -1
- package/dist/elysia.d.ts +49 -0
- package/dist/elysia.js +10 -0
- package/dist/elysia.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.js +5 -4
- package/dist/env.js.map +1 -1
- package/dist/express.d.ts +38 -0
- package/dist/express.js +18 -0
- package/dist/express.js.map +1 -0
- package/dist/fastify.d.ts +44 -0
- package/dist/fastify.js +47 -0
- package/dist/fastify.js.map +1 -0
- package/dist/hono.d.ts +26 -0
- package/dist/hono.js +10 -0
- package/dist/hono.js.map +1 -0
- package/dist/index.d.ts +13 -4
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts +4 -0
- package/dist/jobs.js +18 -1
- package/dist/jobs.js.map +1 -1
- package/dist/logging.d.ts +23 -0
- package/dist/logging.js +87 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp.d.ts +0 -6
- package/dist/mcp.js +11 -1
- package/dist/mcp.js.map +1 -1
- package/dist/metrics.d.ts +48 -0
- package/dist/metrics.js +184 -0
- package/dist/metrics.js.map +1 -0
- package/dist/nestjs.d.ts +43 -0
- package/dist/nestjs.js +47 -0
- package/dist/nestjs.js.map +1 -0
- package/dist/openapi.d.ts +0 -1
- package/dist/openapi.js +4 -0
- package/dist/openapi.js.map +1 -1
- package/dist/redact.d.ts +19 -0
- package/dist/redact.js +150 -0
- package/dist/redact.js.map +1 -0
- package/dist/route.d.ts +18 -0
- package/dist/route.js.map +1 -1
- package/dist/secure-headers.d.ts +8 -0
- package/dist/secure-headers.js +61 -0
- package/dist/secure-headers.js.map +1 -0
- package/dist/serve.d.ts +53 -1
- package/dist/serve.js +157 -61
- package/dist/serve.js.map +1 -1
- package/dist/trpc.d.ts +57 -0
- package/dist/trpc.js +142 -0
- package/dist/trpc.js.map +1 -0
- package/dist/tsed.d.ts +32 -0
- package/dist/tsed.js +13 -0
- package/dist/tsed.js.map +1 -0
- package/llms.txt +10 -4
- package/package.json +57 -3
- package/templates/app/AGENTS.md +8 -4
- package/templates/app/_env.example +2 -0
- package/templates/app/src/app.ts +15 -8
- package/templates/app/src/config.ts +17 -0
- package/templates/app/src/server.ts +9 -9
- package/templates/app/src/routes/health.ts +0 -3
package/dist/ai/tool.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tools made from plain functions, for ai.generate({ tools }) anywhere (createAI or ctx.ai):
|
|
3
|
+
*
|
|
4
|
+
* export const getWeather = tool("getWeather", {
|
|
5
|
+
* description: "Current weather for a city",
|
|
6
|
+
* input: t.object({ city: t.string() }),
|
|
7
|
+
* }).handle(async ({ input }) => fetchWeather(input.city))
|
|
8
|
+
*
|
|
9
|
+
* The model's arguments are validated against input before the function runs.
|
|
10
|
+
*/
|
|
11
|
+
import { InferloError } from "../errors.js";
|
|
12
|
+
import { ObjectSchema, ValidationError } from "../schema.js";
|
|
13
|
+
export class ToolBuilder {
|
|
14
|
+
name;
|
|
15
|
+
options;
|
|
16
|
+
constructor(name, options) {
|
|
17
|
+
this.name = name;
|
|
18
|
+
this.options = options;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The tool's work. Return any JSON value (or a string) for the model. Throw httpError(404, "...")
|
|
22
|
+
* to send a failed tool result to the model; any other error rejects ai.generate.
|
|
23
|
+
*/
|
|
24
|
+
handle(handler) {
|
|
25
|
+
if (typeof handler !== "function")
|
|
26
|
+
throw invalid(this.name, ["handle() needs a function"]);
|
|
27
|
+
return { kind: "inferlo.tool", name: this.name, description: this.options.description, input: this.options.input, handler: handler };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Provider limit for tool names (Anthropic, OpenAI and Gemini). */
|
|
31
|
+
const TOOL_NAME = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;
|
|
32
|
+
/** Define a tool the model can call: tool("getWeather", { description, input: t.object({ ... }) }).handle(fn). */
|
|
33
|
+
export function tool(name, options) {
|
|
34
|
+
const problems = [];
|
|
35
|
+
if (typeof name !== "string" || !TOOL_NAME.test(name))
|
|
36
|
+
problems.push("the name must be letters, digits, _ and -, starting with a letter, at most 64 characters");
|
|
37
|
+
if (!options || typeof options !== "object")
|
|
38
|
+
problems.push("options must be an object with a description and an input schema");
|
|
39
|
+
else {
|
|
40
|
+
if (typeof options.description !== "string" || !options.description.trim())
|
|
41
|
+
problems.push("description must say what the tool does");
|
|
42
|
+
if (!(options.input instanceof ObjectSchema))
|
|
43
|
+
problems.push("input must be a t.object({ ... }) schema");
|
|
44
|
+
}
|
|
45
|
+
if (problems.length)
|
|
46
|
+
throw invalid(name, problems);
|
|
47
|
+
return new ToolBuilder(name, options);
|
|
48
|
+
}
|
|
49
|
+
function invalid(name, problems) {
|
|
50
|
+
return new InferloError("IL5013", `Invalid tool "${String(name)}": ${problems.join(", ")}.`, {
|
|
51
|
+
fix: 'Use tool("getWeather", { description: "Current weather for a city", input: t.object({ city: t.string() }) }).handle(async ({ input }) => { ... }).',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export function isTool(value) {
|
|
55
|
+
return typeof value === "object" && value !== null && value.kind === "inferlo.tool";
|
|
56
|
+
}
|
|
57
|
+
/** What the model is offered for a function tool. Internal. */
|
|
58
|
+
export function functionToolSpec(def) {
|
|
59
|
+
return { name: def.name, description: def.description, inputSchema: def.input.toJSONSchema() };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Runs one call of a function tool. Validation errors and InferloErrors with a status below 500
|
|
63
|
+
* (httpError, notFound, forbidden) become failed tool results for the model; other errors are rethrown.
|
|
64
|
+
* Internal.
|
|
65
|
+
*/
|
|
66
|
+
export async function runFunctionTool(def, input, signal) {
|
|
67
|
+
try {
|
|
68
|
+
const parsed = def.input.safeParse(input);
|
|
69
|
+
if (!parsed.ok)
|
|
70
|
+
throw new ValidationError(parsed.issues, "tool input");
|
|
71
|
+
const output = await def.handler({ input: parsed.value, ...(signal ? { signal } : {}) });
|
|
72
|
+
if (typeof output === "string")
|
|
73
|
+
return { status: 200, output, text: output };
|
|
74
|
+
const text = JSON.stringify(output ?? null);
|
|
75
|
+
return { status: 200, output: output ?? null, text };
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (error instanceof InferloError && error.status < 500) {
|
|
79
|
+
const output = error.toJSON();
|
|
80
|
+
return { status: error.status, output, text: JSON.stringify(output) };
|
|
81
|
+
}
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/ai/tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { InferloError } from "./errors.js";
|
|
2
|
+
export function assertAIClient(ai, fix) {
|
|
3
|
+
const candidate = ai;
|
|
4
|
+
if (!candidate || typeof candidate.generate !== "function" || typeof candidate.stream !== "function" || typeof candidate.embed !== "function") {
|
|
5
|
+
throw new InferloError("IL5014", "inferloAI() needs an AI client.", { fix });
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=ai-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-client.js","sourceRoot":"","sources":["../src/ai-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,UAAU,cAAc,CAAC,EAAW,EAAE,GAAW;IACrD,MAAM,SAAS,GAAG,EAA6B,CAAC;IAChD,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,CAAC,QAAQ,KAAK,UAAU,IAAI,OAAO,SAAS,CAAC,MAAM,KAAK,UAAU,IAAI,OAAO,SAAS,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAC9I,MAAM,IAAI,YAAY,CAAC,QAAQ,EAAE,iCAAiC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC"}
|
package/dist/app.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ import type { AnyModel } from "./model.ts";
|
|
|
10
10
|
import { type AppDb, type AppUser, type Method, type RouteDef } from "./route.ts";
|
|
11
11
|
import { type RateLimitConfig } from "./rate-limit.ts";
|
|
12
12
|
import { type AppJobs, type JobQueueConfig, type JobSource } from "./jobs.ts";
|
|
13
|
+
import { type LogFields, type LoggingConfig } from "./logging.ts";
|
|
14
|
+
import { type MetricsConfig } from "./metrics.ts";
|
|
15
|
+
import { type SecureHeadersConfig } from "./secure-headers.ts";
|
|
13
16
|
export interface AuthConfig {
|
|
14
17
|
/** Return the signed-in user for this request, or null. */
|
|
15
18
|
resolve(req: Request, ctx: {
|
|
@@ -30,11 +33,48 @@ export interface MiddlewareContext {
|
|
|
30
33
|
req: Request;
|
|
31
34
|
url: URL;
|
|
32
35
|
state: Record<string, unknown>;
|
|
36
|
+
/** This request's id, sent back in the X-Request-Id header and added to its log entries. */
|
|
37
|
+
requestId: string;
|
|
33
38
|
}
|
|
34
39
|
export type Middleware = (ctx: MiddlewareContext, next: () => Promise<Response>) => Promise<Response>;
|
|
40
|
+
/**
|
|
41
|
+
* Where the app writes logs. fields holds structured values such as requestId (a request's log entries)
|
|
42
|
+
* or method, path, status and durationMs (request logs); loggers that only take two arguments ignore them.
|
|
43
|
+
*/
|
|
35
44
|
export interface Logger {
|
|
36
|
-
info(message: string, data?: unknown): void;
|
|
37
|
-
error(message: string, data?: unknown): void;
|
|
45
|
+
info(message: string, data?: unknown, fields?: LogFields): void;
|
|
46
|
+
error(message: string, data?: unknown, fields?: LogFields): void;
|
|
47
|
+
}
|
|
48
|
+
/** A readiness check: resolve (or return) when the dependency is usable, throw when it is not. */
|
|
49
|
+
export type HealthCheck = () => unknown | Promise<unknown>;
|
|
50
|
+
export interface HealthConfig {
|
|
51
|
+
/** Liveness endpoint: 200 while the process can answer requests. Default "/health". */
|
|
52
|
+
path?: string;
|
|
53
|
+
/** Readiness endpoint: 200 when every check passes, 503 otherwise. Default "/ready". */
|
|
54
|
+
readyPath?: string;
|
|
55
|
+
/** Your own checks, by name ("database" and "ai" are built in): { redis: () => redis.ping() }. */
|
|
56
|
+
checks?: Record<string, HealthCheck>;
|
|
57
|
+
/** Time each check may take before it fails. Default 5000 ms. */
|
|
58
|
+
timeoutMs?: number;
|
|
59
|
+
}
|
|
60
|
+
export interface CheckResult {
|
|
61
|
+
status: "ok" | "error";
|
|
62
|
+
durationMs: number;
|
|
63
|
+
/** "Check failed." unless the check threw an exposed InferloError (httpError) or exposeErrors is on. */
|
|
64
|
+
error?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface CloseOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Keep serving requests for this long after /ready starts answering 503, so load balancers stop sending
|
|
69
|
+
* traffic first (for example a few seconds more than the readiness probe period). Default 0.
|
|
70
|
+
*/
|
|
71
|
+
delayMs?: number;
|
|
72
|
+
/** Longest wait for in-flight requests, waitUntil tasks and the running job before closing anyway. Default 10000. */
|
|
73
|
+
timeoutMs?: number;
|
|
74
|
+
}
|
|
75
|
+
export interface ReadinessReport {
|
|
76
|
+
status: "ready" | "not_ready";
|
|
77
|
+
checks: Record<string, CheckResult>;
|
|
38
78
|
}
|
|
39
79
|
/** Anything that contains routes: a route, an array, or a module (import * as tickets from "./routes/tickets.ts"). */
|
|
40
80
|
export type RouteSource = RouteDef | readonly RouteSource[] | {
|
|
@@ -70,9 +110,44 @@ export interface AppConfig<Models extends readonly AnyModel[]> {
|
|
|
70
110
|
* (for rateLimit by "ip"). Default false, because clients can send that header themselves.
|
|
71
111
|
*/
|
|
72
112
|
trustProxy?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Health endpoints for load balancers and orchestrators: GET /health (liveness) and GET /ready (readiness:
|
|
115
|
+
* the database, the AI configuration and your checks). Public, never cached. Off by default.
|
|
116
|
+
*/
|
|
117
|
+
health?: boolean | HealthConfig;
|
|
118
|
+
/**
|
|
119
|
+
* Security headers sent on every response that does not set them itself: Content-Security-Policy,
|
|
120
|
+
* Cross-Origin-Opener-Policy, Cross-Origin-Resource-Policy, Referrer-Policy, X-Content-Type-Options,
|
|
121
|
+
* X-Frame-Options, and Strict-Transport-Security over HTTPS. Change one by name, false leaves it out:
|
|
122
|
+
* { "X-Frame-Options": "SAMEORIGIN", "Content-Security-Policy": false }. false sends none. Default true.
|
|
123
|
+
*/
|
|
124
|
+
secureHeaders?: boolean | SecureHeadersConfig;
|
|
125
|
+
/**
|
|
126
|
+
* Longest time in milliseconds a route may take (reading the body and running the handler) before it answers
|
|
127
|
+
* 503 IL2007 and ctx.signal is aborted. Routes can set their own timeoutMs. false turns it off. Default 60000.
|
|
128
|
+
*/
|
|
129
|
+
requestTimeoutMs?: number | false;
|
|
130
|
+
/**
|
|
131
|
+
* More values to hide from logs, besides credentials Inferlo finds itself (authorization and cookie headers,
|
|
132
|
+
* tokens, API keys, passwords in URLs) and the AI provider keys: your config() result (its secrets) or
|
|
133
|
+
* strings: redact: [settings, process.env.WEBHOOK_SECRET]. They are replaced with "[redacted]".
|
|
134
|
+
*/
|
|
135
|
+
redact?: readonly (string | object | undefined | null)[];
|
|
73
136
|
/** Include error messages of unexpected (500) errors in responses. Default false. */
|
|
74
137
|
exposeErrors?: boolean;
|
|
138
|
+
/** Your own logger (for example pino or winston): { info(message, data, fields), error(message, data, fields) }. */
|
|
75
139
|
logger?: Logger;
|
|
140
|
+
/**
|
|
141
|
+
* The built-in logger's format ("text" or "json", one object per line) and request logs (requests: true logs
|
|
142
|
+
* each request's id, method, path, status and duration). Every response has an X-Request-Id header.
|
|
143
|
+
*/
|
|
144
|
+
logging?: LoggingConfig;
|
|
145
|
+
/**
|
|
146
|
+
* Prometheus metrics at GET /metrics: requests by route and status with durations, job runs, and AI calls,
|
|
147
|
+
* tokens and cost per alias. { token } requires Authorization: Bearer <token>; without it the endpoint is
|
|
148
|
+
* public, so keep it off the internet. Off by default.
|
|
149
|
+
*/
|
|
150
|
+
metrics?: boolean | MetricsConfig;
|
|
76
151
|
}
|
|
77
152
|
export interface RequestOptions {
|
|
78
153
|
method?: Method | Lowercase<Method> | "OPTIONS" | "HEAD";
|
|
@@ -102,6 +177,16 @@ export interface App<Models extends readonly AnyModel[]> {
|
|
|
102
177
|
port: number;
|
|
103
178
|
close(): Promise<void>;
|
|
104
179
|
}>;
|
|
180
|
+
/** Run the readiness checks (the same report as GET /ready, also when health is off). */
|
|
181
|
+
checkReady(): Promise<ReadinessReport>;
|
|
182
|
+
/** True once app.close() was called: /ready answers 503. */
|
|
183
|
+
readonly closing: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Graceful shutdown, for SIGTERM: /ready answers 503, then (after delayMs) new requests get 503 IL2006,
|
|
186
|
+
* in-flight requests, waitUntil tasks and the job workers from app.jobs.start() finish (up to timeoutMs),
|
|
187
|
+
* servers from app.listen() close, then the database. Calling it again returns the same promise.
|
|
188
|
+
*/
|
|
189
|
+
close(options?: CloseOptions): Promise<void>;
|
|
105
190
|
/** Machine-readable map of the whole app: routes, models, auth and AI. */
|
|
106
191
|
describe(): AppDescription;
|
|
107
192
|
openapi(): Record<string, unknown>;
|