@browserlessapi/inferlo 0.4.0 → 0.6.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 (142) hide show
  1. package/README.md +21 -3
  2. package/dist/adonisjs.d.ts +33 -0
  3. package/dist/adonisjs.js +30 -0
  4. package/dist/adonisjs.js.map +1 -0
  5. package/dist/ai/index.d.ts +22 -8
  6. package/dist/ai/index.js +107 -15
  7. package/dist/ai/index.js.map +1 -1
  8. package/dist/ai/providers.js +5 -4
  9. package/dist/ai/providers.js.map +1 -1
  10. package/dist/ai/public.d.ts +21 -0
  11. package/dist/ai/public.js +17 -0
  12. package/dist/ai/public.js.map +1 -0
  13. package/dist/ai/tool.d.ts +47 -0
  14. package/dist/ai/tool.js +85 -0
  15. package/dist/ai/tool.js.map +1 -0
  16. package/dist/ai-client.d.ts +3 -0
  17. package/dist/ai-client.js +8 -0
  18. package/dist/ai-client.js.map +1 -0
  19. package/dist/api-version.d.ts +32 -0
  20. package/dist/api-version.js +45 -0
  21. package/dist/api-version.js.map +1 -0
  22. package/dist/app.d.ts +117 -5
  23. package/dist/app.js +667 -156
  24. package/dist/app.js.map +1 -1
  25. package/dist/audit.d.ts +50 -0
  26. package/dist/audit.js +92 -0
  27. package/dist/audit.js.map +1 -0
  28. package/dist/cache.d.ts +92 -0
  29. package/dist/cache.js +245 -0
  30. package/dist/cache.js.map +1 -0
  31. package/dist/cli/main.js +45 -5
  32. package/dist/cli/main.js.map +1 -1
  33. package/dist/config.d.ts +16 -0
  34. package/dist/config.js +101 -0
  35. package/dist/config.js.map +1 -0
  36. package/dist/db/table.d.ts +31 -0
  37. package/dist/db/table.js +140 -1
  38. package/dist/db/table.js.map +1 -1
  39. package/dist/deprecation.d.ts +23 -0
  40. package/dist/deprecation.js +70 -0
  41. package/dist/deprecation.js.map +1 -0
  42. package/dist/describe.d.ts +68 -5
  43. package/dist/describe.js +38 -3
  44. package/dist/describe.js.map +1 -1
  45. package/dist/elysia.d.ts +49 -0
  46. package/dist/elysia.js +10 -0
  47. package/dist/elysia.js.map +1 -0
  48. package/dist/env.d.ts +2 -0
  49. package/dist/env.js +5 -4
  50. package/dist/env.js.map +1 -1
  51. package/dist/express.d.ts +38 -0
  52. package/dist/express.js +18 -0
  53. package/dist/express.js.map +1 -0
  54. package/dist/fastify.d.ts +52 -0
  55. package/dist/fastify.js +65 -0
  56. package/dist/fastify.js.map +1 -0
  57. package/dist/h3.d.ts +76 -0
  58. package/dist/h3.js +61 -0
  59. package/dist/h3.js.map +1 -0
  60. package/dist/hapi.d.ts +45 -0
  61. package/dist/hapi.js +57 -0
  62. package/dist/hapi.js.map +1 -0
  63. package/dist/hono.d.ts +26 -0
  64. package/dist/hono.js +10 -0
  65. package/dist/hono.js.map +1 -0
  66. package/dist/index.d.ts +27 -5
  67. package/dist/index.js +9 -2
  68. package/dist/index.js.map +1 -1
  69. package/dist/jobs.d.ts +24 -0
  70. package/dist/jobs.js +35 -6
  71. package/dist/jobs.js.map +1 -1
  72. package/dist/koa.d.ts +51 -0
  73. package/dist/koa.js +45 -0
  74. package/dist/koa.js.map +1 -0
  75. package/dist/lambda.d.ts +110 -0
  76. package/dist/lambda.js +169 -0
  77. package/dist/lambda.js.map +1 -0
  78. package/dist/logging.d.ts +23 -0
  79. package/dist/logging.js +87 -0
  80. package/dist/logging.js.map +1 -0
  81. package/dist/mcp.d.ts +1 -7
  82. package/dist/mcp.js +18 -4
  83. package/dist/mcp.js.map +1 -1
  84. package/dist/metrics.d.ts +48 -0
  85. package/dist/metrics.js +184 -0
  86. package/dist/metrics.js.map +1 -0
  87. package/dist/module.d.ts +52 -0
  88. package/dist/module.js +152 -0
  89. package/dist/module.js.map +1 -0
  90. package/dist/nestjs.d.ts +43 -0
  91. package/dist/nestjs.js +47 -0
  92. package/dist/nestjs.js.map +1 -0
  93. package/dist/nextjs.d.ts +35 -0
  94. package/dist/nextjs.js +33 -0
  95. package/dist/nextjs.js.map +1 -0
  96. package/dist/openapi.d.ts +3 -1
  97. package/dist/openapi.js +16 -3
  98. package/dist/openapi.js.map +1 -1
  99. package/dist/permissions.d.ts +26 -0
  100. package/dist/permissions.js +78 -0
  101. package/dist/permissions.js.map +1 -0
  102. package/dist/react-router.d.ts +41 -0
  103. package/dist/react-router.js +42 -0
  104. package/dist/react-router.js.map +1 -0
  105. package/dist/redact.d.ts +19 -0
  106. package/dist/redact.js +150 -0
  107. package/dist/redact.js.map +1 -0
  108. package/dist/request-matcher.d.ts +4 -0
  109. package/dist/request-matcher.js +14 -0
  110. package/dist/request-matcher.js.map +1 -0
  111. package/dist/route.d.ts +54 -1
  112. package/dist/route.js +24 -0
  113. package/dist/route.js.map +1 -1
  114. package/dist/secure-headers.d.ts +8 -0
  115. package/dist/secure-headers.js +61 -0
  116. package/dist/secure-headers.js.map +1 -0
  117. package/dist/serve.d.ts +72 -1
  118. package/dist/serve.js +201 -61
  119. package/dist/serve.js.map +1 -1
  120. package/dist/sessions.d.ts +72 -0
  121. package/dist/sessions.js +171 -0
  122. package/dist/sessions.js.map +1 -0
  123. package/dist/sveltekit.d.ts +72 -0
  124. package/dist/sveltekit.js +68 -0
  125. package/dist/sveltekit.js.map +1 -0
  126. package/dist/tracing.d.ts +118 -0
  127. package/dist/tracing.js +204 -0
  128. package/dist/tracing.js.map +1 -0
  129. package/dist/trpc.d.ts +57 -0
  130. package/dist/trpc.js +142 -0
  131. package/dist/trpc.js.map +1 -0
  132. package/dist/tsed.d.ts +32 -0
  133. package/dist/tsed.js +13 -0
  134. package/dist/tsed.js.map +1 -0
  135. package/llms.txt +15 -5
  136. package/package.json +99 -3
  137. package/templates/app/AGENTS.md +12 -6
  138. package/templates/app/_env.example +2 -0
  139. package/templates/app/src/app.ts +15 -8
  140. package/templates/app/src/config.ts +17 -0
  141. package/templates/app/src/server.ts +9 -9
  142. package/templates/app/src/routes/health.ts +0 -3
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Inferlo inside ElysiaJS (1.0 and later), without a runtime dependency on Elysia:
3
+ *
4
+ * import { Elysia } from "elysia";
5
+ * import { createAI, anthropic } from "@browserlessapi/inferlo/ai";
6
+ * import { inferloAI } from "@browserlessapi/inferlo/elysia";
7
+ *
8
+ * const server = new Elysia()
9
+ * .use(inferloAI(ai)) // ({ ai }) in every handler, typed
10
+ * .mount("/api", inferloApp.fetch); // or a whole Inferlo app under a path
11
+ *
12
+ * This entry point never loads the router, database or jobs code.
13
+ */
14
+ import type { Elysia } from "elysia";
15
+ import type { AI } from "./ai/index.ts";
16
+ /**
17
+ * An Elysia plugin that decorates the context with an AI client (createAI(...) or an Inferlo app's app.ai):
18
+ * new Elysia().use(inferloAI(ai)).post("/classify", ({ ai, body }) => ...).
19
+ */
20
+ export declare function inferloAI(ai: AI): (app: Elysia) => Elysia<"", {
21
+ decorator: {
22
+ ai: AI;
23
+ };
24
+ store: {};
25
+ derive: {};
26
+ resolve: {};
27
+ }, {
28
+ typebox: {};
29
+ error: {};
30
+ }, {
31
+ schema: {};
32
+ standaloneSchema: {};
33
+ macro: {};
34
+ macroFn: {};
35
+ parser: {};
36
+ response: {};
37
+ }, {}, {
38
+ derive: {};
39
+ resolve: {};
40
+ schema: {};
41
+ standaloneSchema: {};
42
+ response: {};
43
+ }, {
44
+ derive: {};
45
+ resolve: {};
46
+ schema: {};
47
+ standaloneSchema: {};
48
+ response: {};
49
+ }>;
package/dist/elysia.js ADDED
@@ -0,0 +1,10 @@
1
+ import { assertAIClient } from "./ai-client.js";
2
+ /**
3
+ * An Elysia plugin that decorates the context with an AI client (createAI(...) or an Inferlo app's app.ai):
4
+ * new Elysia().use(inferloAI(ai)).post("/classify", ({ ai, body }) => ...).
5
+ */
6
+ export function inferloAI(ai) {
7
+ assertAIClient(ai, 'Pass createAI({ providers, models }) from "@browserlessapi/inferlo/ai", or an Inferlo app\'s app.ai: new Elysia().use(inferloAI(ai)).');
8
+ return (app) => app.decorate("ai", ai);
9
+ }
10
+ //# sourceMappingURL=elysia.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elysia.js","sourceRoot":"","sources":["../src/elysia.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,EAAM;IAC9B,cAAc,CAAC,EAAE,EAAE,uIAAuI,CAAC,CAAC;IAC5J,OAAO,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACjD,CAAC"}
package/dist/env.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  /** Use a fixed set of variables (tests, Cloudflare Workers bindings). */
2
2
  export declare function setEnv(values: Record<string, string | undefined> | undefined): void;
3
+ /** The raw value of an environment variable (or of setEnv overrides). */
4
+ export declare function readEnv(name: string): string | undefined;
3
5
  interface EnvFn {
4
6
  (name: string): string;
5
7
  (name: string, options: {
package/dist/env.js CHANGED
@@ -12,7 +12,8 @@ let overrides;
12
12
  export function setEnv(values) {
13
13
  overrides = values;
14
14
  }
15
- function read(name) {
15
+ /** The raw value of an environment variable (or of setEnv overrides). */
16
+ export function readEnv(name) {
16
17
  if (overrides && name in overrides)
17
18
  return overrides[name];
18
19
  const g = globalThis;
@@ -34,7 +35,7 @@ function missing(name) {
34
35
  });
35
36
  }
36
37
  export const env = Object.assign((name, options = {}) => {
37
- const value = read(name);
38
+ const value = readEnv(name);
38
39
  if (value !== undefined && value !== "")
39
40
  return value;
40
41
  if (options.default !== undefined)
@@ -44,7 +45,7 @@ export const env = Object.assign((name, options = {}) => {
44
45
  throw missing(name);
45
46
  }, {
46
47
  int(name, options = {}) {
47
- const value = read(name);
48
+ const value = readEnv(name);
48
49
  if (value === undefined || value === "") {
49
50
  if (options.default !== undefined)
50
51
  return options.default;
@@ -56,7 +57,7 @@ export const env = Object.assign((name, options = {}) => {
56
57
  return n;
57
58
  },
58
59
  bool(name, options = {}) {
59
- const value = read(name)?.toLowerCase();
60
+ const value = readEnv(name)?.toLowerCase();
60
61
  if (value === undefined || value === "") {
61
62
  if (options.default !== undefined)
62
63
  return options.default;
package/dist/env.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Inferlo inside Express (4 and 5), without a runtime dependency on Express:
3
+ *
4
+ * import express from "express";
5
+ * import { createAI, anthropic } from "@browserlessapi/inferlo/ai";
6
+ * import { toNodeHandler } from "@browserlessapi/inferlo";
7
+ * import { inferloAI, sendResponse } from "@browserlessapi/inferlo/express";
8
+ *
9
+ * const server = express();
10
+ * server.use(inferloAI(ai)); // req.ai in every handler
11
+ * server.get("/chat", (req, res) => sendResponse(res, req.ai.stream({ prompt: "Hi" }).toResponse()));
12
+ * server.use("/api", toNodeHandler(inferloApp)); // or a whole Inferlo app under a path
13
+ *
14
+ * Importing this entry point adds `ai` to Express's Request type. It never loads the router, database or jobs code.
15
+ */
16
+ import type { AI } from "./ai/index.ts";
17
+ import { type NodeResponse } from "./serve.ts";
18
+ declare global {
19
+ namespace Express {
20
+ interface Request {
21
+ /** The AI client set by inferloAI() from @browserlessapi/inferlo/express. */
22
+ ai: AI;
23
+ }
24
+ }
25
+ }
26
+ /** The part of an Express request that inferloAI() uses. */
27
+ export interface ExpressRequestLike {
28
+ ai?: AI;
29
+ }
30
+ /** An Express middleware: server.use(inferloAI(ai)) or server.use("/chat", inferloAI(ai)). */
31
+ export type InferloAIMiddleware = (req: ExpressRequestLike, res: unknown, next: (error?: unknown) => void) => void;
32
+ /** Puts an AI client (createAI(...) or an Inferlo app's app.ai) on every Express request as req.ai. */
33
+ export declare function inferloAI(ai: AI): InferloAIMiddleware;
34
+ /**
35
+ * Send a Web Response from an Express (or node:http) handler: status, headers (every Set-Cookie) and the
36
+ * body, streamed. Use it for AI streams: sendResponse(res, req.ai.stream({ prompt }).toResponse()).
37
+ */
38
+ export declare function sendResponse(res: NodeResponse, response: Response): Promise<void>;
@@ -0,0 +1,18 @@
1
+ import { assertAIClient } from "./ai-client.js";
2
+ import { writeResponse } from "./serve.js";
3
+ /** Puts an AI client (createAI(...) or an Inferlo app's app.ai) on every Express request as req.ai. */
4
+ export function inferloAI(ai) {
5
+ assertAIClient(ai, 'Pass createAI({ providers, models }) from "@browserlessapi/inferlo/ai", or an Inferlo app\'s app.ai: server.use(inferloAI(ai)).');
6
+ return (req, _res, next) => {
7
+ req.ai = ai;
8
+ next();
9
+ };
10
+ }
11
+ /**
12
+ * Send a Web Response from an Express (or node:http) handler: status, headers (every Set-Cookie) and the
13
+ * body, streamed. Use it for AI streams: sendResponse(res, req.ai.stream({ prompt }).toResponse()).
14
+ */
15
+ export function sendResponse(res, response) {
16
+ return writeResponse(res, response, "GET");
17
+ }
18
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAqB,MAAM,YAAY,CAAC;AAoB9D,uGAAuG;AACvG,MAAM,UAAU,SAAS,CAAC,EAAM;IAC9B,cAAc,CAAC,EAAE,EAAE,iIAAiI,CAAC,CAAC;IACtJ,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QACzB,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;QACZ,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,GAAiB,EAAE,QAAkB;IAChE,OAAO,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Inferlo inside Fastify (5 and later), without a runtime dependency on Fastify:
3
+ *
4
+ * import Fastify from "fastify";
5
+ * import { createAI, anthropic } from "@browserlessapi/inferlo/ai";
6
+ * import { inferloPlugin } from "@browserlessapi/inferlo/fastify";
7
+ *
8
+ * const fastify = Fastify();
9
+ * await fastify.register(inferloPlugin, { ai }); // fastify.ai and request.ai
10
+ * await fastify.register(inferloPlugin, { app: inferloApp, prefix: "/api" }); // or a whole Inferlo app under /api
11
+ * await fastify.register(inferloPlugin, { app: inferloApp, fallthrough: true }); // or only the app's routes, at their own URLs
12
+ *
13
+ * Importing this entry point adds `ai` to Fastify's instance and request types. It never loads the router,
14
+ * database or jobs code.
15
+ */
16
+ import type { FastifyPluginAsync } from "fastify";
17
+ import type { AI } from "./ai/index.ts";
18
+ declare module "fastify" {
19
+ interface FastifyInstance {
20
+ /** The AI client registered with inferloPlugin from @browserlessapi/inferlo/fastify. */
21
+ ai: AI;
22
+ }
23
+ interface FastifyRequest {
24
+ /** The AI client registered with inferloPlugin from @browserlessapi/inferlo/fastify. */
25
+ ai: AI;
26
+ }
27
+ }
28
+ export interface InferloPluginOptions {
29
+ /** AI client for fastify.ai and request.ai: createAI(...) or an Inferlo app's app.ai. Default: app.ai, unless fastify.ai is already set. */
30
+ ai?: AI;
31
+ /** A whole Inferlo app (routes, auth, OpenAPI, MCP) to serve under prefix. */
32
+ app?: {
33
+ fetch(req: Request, ...rest: unknown[]): Promise<Response>;
34
+ ai?: AI;
35
+ };
36
+ /** Path the app is served under, for example "/api". Required with app, unless fallthrough is true. */
37
+ prefix?: string;
38
+ /**
39
+ * Answer only the requests the app has a route for (method and path) and its own endpoints (OpenAPI, MCP,
40
+ * health, metrics, CORS preflights), and leave every other request to Fastify's routes and 404 handler.
41
+ * With it, routes move from Fastify to Inferlo one at a time at the same URLs. Default false.
42
+ */
43
+ fallthrough?: boolean;
44
+ }
45
+ /** A Fastify plugin, registered with fastify.register(inferloPlugin, options). */
46
+ export type InferloPlugin = FastifyPluginAsync<InferloPluginOptions>;
47
+ /**
48
+ * Fastify plugin. { ai } decorates fastify.ai and request.ai everywhere in the Fastify app; { app, prefix }
49
+ * serves a whole Inferlo app (routes, auth, validation, OpenAPI, MCP) under prefix; { app, fallthrough: true }
50
+ * answers only the app's routes and leaves every other request to Fastify. They can be combined.
51
+ */
52
+ export declare const inferloPlugin: InferloPlugin;
@@ -0,0 +1,65 @@
1
+ import { assertAIClient } from "./ai-client.js";
2
+ import { InferloError } from "./errors.js";
3
+ import { answersNodeRequest, toNodeHandler } from "./serve.js";
4
+ const bad = (message, fix) => new InferloError("IL5015", message, { fix });
5
+ async function plugin(fastify, options) {
6
+ const { app, prefix } = options ?? {};
7
+ if (app !== undefined && (typeof app !== "object" || app === null || typeof app.fetch !== "function")) {
8
+ throw bad("inferloPlugin's app must be an Inferlo app (createApp(...)).", 'Use fastify.register(inferloPlugin, { app: inferloApp, prefix: "/api" }).');
9
+ }
10
+ // app.ai is the default, unless an earlier register(inferloPlugin, { ai }) already set fastify.ai.
11
+ const ai = options?.ai ?? (fastify.hasDecorator("ai") ? undefined : app?.ai);
12
+ if (!app && !options?.ai)
13
+ throw bad("inferloPlugin needs ai, app or both.", 'Use fastify.register(inferloPlugin, { ai }) for fastify.ai and request.ai, or { app, prefix: "/api" } to serve an Inferlo app.');
14
+ if (ai !== undefined) {
15
+ assertAIClient(ai, 'Pass createAI({ providers, models }) from "@browserlessapi/inferlo/ai", or an Inferlo app\'s app.ai: fastify.register(inferloPlugin, { ai }).');
16
+ fastify.decorate("ai", ai);
17
+ fastify.decorateRequest("ai", { getter: () => ai });
18
+ }
19
+ if (!app)
20
+ return;
21
+ const { fallthrough } = options;
22
+ if (fallthrough !== undefined && typeof fallthrough !== "boolean") {
23
+ throw bad("inferloPlugin's fallthrough must be true or false.", "Use fastify.register(inferloPlugin, { app, fallthrough: true }).");
24
+ }
25
+ const validPrefix = typeof prefix === "string" && /^\/[^*?#]*[^/*?#]$/.test(prefix);
26
+ if (fallthrough ? prefix !== undefined && !validPrefix : !validPrefix) {
27
+ throw bad(`inferloPlugin needs a prefix such as "/api" to serve an app, got ${JSON.stringify(prefix)}.`, 'Use fastify.register(inferloPlugin, { app, prefix: "/api" }), or { app, fallthrough: true } to serve the app\'s routes at their own URLs.');
28
+ }
29
+ if (fallthrough) {
30
+ const handler = toNodeHandler(app, { prefix, fallthrough: true }); // also checks that app comes from createApp
31
+ // onRequest runs before Fastify reads the body, for Fastify's routes and its 404 handler alike, so the app
32
+ // can take over the requests it answers and Fastify keeps everything else, also other methods on a path.
33
+ fastify.addHook("onRequest", async (request, reply) => {
34
+ if (!answersNodeRequest(app, request.raw, prefix))
35
+ return;
36
+ reply.hijack();
37
+ await handler(request.raw, reply.raw);
38
+ });
39
+ return;
40
+ }
41
+ const handler = toNodeHandler(app, { prefix });
42
+ // In a child context, so the catch-all body parser applies to the app's routes only: Inferlo reads the
43
+ // body stream itself (JSON, forms, any size limit), and Fastify answers nothing for these paths.
44
+ await fastify.register(async (child) => {
45
+ child.removeAllContentTypeParsers();
46
+ child.addContentTypeParser("*", (_request, _payload, done) => done(null));
47
+ const mount = async (request, reply) => {
48
+ reply.hijack();
49
+ await handler(request.raw, reply.raw);
50
+ };
51
+ child.all(prefix, mount);
52
+ child.all(`${prefix}/*`, mount);
53
+ });
54
+ }
55
+ /**
56
+ * Fastify plugin. { ai } decorates fastify.ai and request.ai everywhere in the Fastify app; { app, prefix }
57
+ * serves a whole Inferlo app (routes, auth, validation, OpenAPI, MCP) under prefix; { app, fallthrough: true }
58
+ * answers only the app's routes and leaves every other request to Fastify. They can be combined.
59
+ */
60
+ export const inferloPlugin = Object.assign(plugin, {
61
+ // Like fastify-plugin: the decorators are visible to the whole Fastify app, not only inside this plugin.
62
+ [Symbol.for("skip-override")]: true,
63
+ [Symbol.for("fastify.display-name")]: "inferlo",
64
+ });
65
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../src/fastify.ts"],"names":[],"mappings":"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"}
package/dist/h3.d.ts ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Inferlo inside h3 (1 and 2), Nitro and Nuxt server routes, without a runtime dependency on h3:
3
+ *
4
+ * // server/routes/api/[...path].ts (Nitro or Nuxt)
5
+ * import { toH3Handler } from "@browserlessapi/inferlo/h3";
6
+ * import { app } from "../../inferlo/app";
7
+ *
8
+ * export default toH3Handler(app, { prefix: "/api" });
9
+ *
10
+ * // server/plugins/ai.ts: event.context.ai in every server route
11
+ * import { inferloAI } from "@browserlessapi/inferlo/h3";
12
+ * export default defineNitroPlugin(inferloAI(ai));
13
+ *
14
+ * It never loads the router, database or jobs code.
15
+ */
16
+ import type { H3EventContext } from "h3";
17
+ import type { AI } from "./ai/index.ts";
18
+ import type { App } from "./app.ts";
19
+ declare module "h3" {
20
+ interface H3EventContext {
21
+ /** The AI client from the inferloAI() Nitro plugin of @browserlessapi/inferlo/h3. */
22
+ ai: AI;
23
+ }
24
+ }
25
+ /** The parts of an h3 1 or h3 2 event Inferlo uses. */
26
+ export interface H3EventLike {
27
+ /** h3 2: the Web request (and event.url, the parsed URL). */
28
+ req?: {
29
+ url: string;
30
+ method: string;
31
+ headers: HeadersInit;
32
+ body?: ReadableStream<Uint8Array> | null;
33
+ signal?: AbortSignal;
34
+ ip?: string;
35
+ };
36
+ url?: URL;
37
+ /** h3 1: the Node request and response, and event.path (after an app.use() prefix). h3 2 has node on Node.js too. */
38
+ node?: {
39
+ req: unknown;
40
+ res: {
41
+ on(event: "close", listener: () => void): unknown;
42
+ writableFinished?: boolean;
43
+ };
44
+ };
45
+ path?: string;
46
+ /** event.context, where the inferloAI() plugin puts ai. */
47
+ context: H3EventContext | Record<string, unknown>;
48
+ }
49
+ /** An h3 event handler: export it from a Nitro server route, or pass it to app.use() or router.add(). */
50
+ export type H3Handler = ((event: H3EventLike) => Promise<Response>) & {
51
+ readonly __is_handler__: true;
52
+ };
53
+ export interface H3HandlerOptions {
54
+ /**
55
+ * The path the handler is served under, removed before the app routes the request: "/api" for
56
+ * server/routes/api/[...path].ts. Requests outside it keep their path. Leave it out when h3 already removed the
57
+ * path (h3 1 app.use("/api", handler)).
58
+ */
59
+ prefix?: string;
60
+ }
61
+ /** A Nitro plugin: export default defineNitroPlugin(inferloAI(ai)). */
62
+ export type NitroPlugin = (nitroApp: {
63
+ hooks: {
64
+ hook(name: "request", fn: (event: H3EventLike) => void): unknown;
65
+ };
66
+ }) => void;
67
+ /**
68
+ * An h3 event handler that runs a whole Inferlo app (routes, auth, validation, rate limits, OpenAPI and MCP), for
69
+ * Nitro and Nuxt server routes and h3 apps, on h3 1 (Nuxt 3 and 4, Nitro 2) and h3 2 (Nitro 3).
70
+ */
71
+ export declare function toH3Handler(app: Pick<App<any>, "fetch">, options?: H3HandlerOptions): H3Handler;
72
+ /**
73
+ * A Nitro plugin that puts an AI client (createAI(...) or an Inferlo app's app.ai) on every request as
74
+ * event.context.ai: export default defineNitroPlugin(inferloAI(ai)) in server/plugins/ai.ts.
75
+ */
76
+ export declare function inferloAI(ai: AI): NitroPlugin;
package/dist/h3.js ADDED
@@ -0,0 +1,61 @@
1
+ import { assertAIClient } from "./ai-client.js";
2
+ import { clientIps } from "./client-ip.js";
3
+ import { InferloError } from "./errors.js";
4
+ import { buildRequest, normalizePrefix, stripPrefix } from "./serve.js";
5
+ const fix = 'Pass the app from createApp and the route\'s path: export default toH3Handler(app, { prefix: "/api" }).';
6
+ /**
7
+ * An h3 event handler that runs a whole Inferlo app (routes, auth, validation, rate limits, OpenAPI and MCP), for
8
+ * Nitro and Nuxt server routes and h3 apps, on h3 1 (Nuxt 3 and 4, Nitro 2) and h3 2 (Nitro 3).
9
+ */
10
+ export function toH3Handler(app, options = {}) {
11
+ if (!app || typeof app.fetch !== "function") {
12
+ throw new InferloError("IL5021", "toH3Handler() needs an Inferlo app (the value returned by createApp).", { fix });
13
+ }
14
+ if (options === null || typeof options !== "object" || (options.prefix !== undefined && (typeof options.prefix !== "string" || !options.prefix.startsWith("/")))) {
15
+ throw new InferloError("IL5021", 'toH3Handler() prefix must be a path that starts with /, such as "/api".', { fix });
16
+ }
17
+ const prefix = normalizePrefix(options.prefix);
18
+ const handler = async (event) => {
19
+ const e = event;
20
+ // h3 2: the event carries a Web request.
21
+ if (e?.req && e.url instanceof URL) {
22
+ const url = new URL(e.url.href);
23
+ url.pathname = stripPrefix(url.pathname, prefix) ?? url.pathname;
24
+ const method = e.req.method.toUpperCase();
25
+ const hasBody = e.req.body != null && method !== "GET" && method !== "HEAD";
26
+ const init = { method, headers: e.req.headers, body: hasBody ? e.req.body : undefined, signal: e.req.signal };
27
+ if (hasBody)
28
+ init.duplex = "half";
29
+ const request = new Request(url, init);
30
+ if (typeof e.req.ip === "string" && e.req.ip)
31
+ clientIps.set(request, e.req.ip);
32
+ return app.fetch(request);
33
+ }
34
+ // h3 1: the event carries Node's request and response.
35
+ if (e?.node?.req) {
36
+ const raw = typeof e.path === "string" ? e.path : (e.node.req.url ?? "/");
37
+ const controller = new AbortController();
38
+ e.node.res.on("close", () => {
39
+ if (!e.node.res.writableFinished)
40
+ controller.abort();
41
+ });
42
+ return app.fetch(buildRequest(e.node.req, stripPrefix(raw, prefix) ?? raw, controller.signal));
43
+ }
44
+ throw new InferloError("IL5021", "toH3Handler()'s handler was called with something that is not an h3 event.", { fix: "Export it from a Nitro server route or pass it to an h3 app: app.use(\"/api/**\", toH3Handler(inferlo, { prefix: \"/api\" }))." });
45
+ };
46
+ // Marks it as an event handler for h3 1 (what defineEventHandler does); h3 2 takes plain functions.
47
+ return Object.assign(handler, { __is_handler__: true });
48
+ }
49
+ /**
50
+ * A Nitro plugin that puts an AI client (createAI(...) or an Inferlo app's app.ai) on every request as
51
+ * event.context.ai: export default defineNitroPlugin(inferloAI(ai)) in server/plugins/ai.ts.
52
+ */
53
+ export function inferloAI(ai) {
54
+ assertAIClient(ai, 'Pass createAI({ providers, models }) from "@browserlessapi/inferlo/ai", or an Inferlo app\'s app.ai: export default defineNitroPlugin(inferloAI(ai)).');
55
+ return (nitroApp) => {
56
+ nitroApp.hooks.hook("request", (event) => {
57
+ event.context.ai = ai;
58
+ });
59
+ };
60
+ }
61
+ //# sourceMappingURL=h3.js.map
package/dist/h3.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"h3.js","sourceRoot":"","sources":["../src/h3.ts"],"names":[],"mappings":"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"}
package/dist/hapi.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Inferlo inside hapi (21 and later), without a runtime dependency on hapi:
3
+ *
4
+ * import Hapi from "@hapi/hapi";
5
+ * import { createAI, anthropic } from "@browserlessapi/inferlo/ai";
6
+ * import { inferloPlugin } from "@browserlessapi/inferlo/hapi";
7
+ *
8
+ * const server = Hapi.server({ port: 3000 });
9
+ * await server.register({ plugin: inferloPlugin, options: { ai } }); // server.ai and request.ai
10
+ * await server.register({ plugin: inferloPlugin, options: { app: inferloApp }, routes: { prefix: "/api" } }); // a whole Inferlo app under /api
11
+ *
12
+ * Importing this entry point adds `ai` to hapi's server and request types. It never loads the router,
13
+ * database or jobs code.
14
+ */
15
+ import type { Plugin } from "@hapi/hapi";
16
+ import type { AI } from "./ai/index.ts";
17
+ declare module "@hapi/hapi" {
18
+ interface Server {
19
+ /** The AI client registered with inferloPlugin from @browserlessapi/inferlo/hapi. */
20
+ ai: AI;
21
+ }
22
+ interface Request {
23
+ /** The AI client registered with inferloPlugin from @browserlessapi/inferlo/hapi. */
24
+ ai: AI;
25
+ }
26
+ }
27
+ export interface InferloPluginOptions {
28
+ /** AI client for server.ai and request.ai: createAI(...) or an Inferlo app's app.ai. Default: app.ai, unless server.ai is already set. */
29
+ ai?: AI;
30
+ /**
31
+ * A whole Inferlo app (routes, auth, validation, OpenAPI, MCP) to serve. It is served under the prefix you
32
+ * register the plugin with (routes: { prefix: "/api" }), or, without one, for every path hapi has no route for.
33
+ */
34
+ app?: {
35
+ fetch(req: Request, ...rest: unknown[]): Promise<Response>;
36
+ ai?: AI;
37
+ };
38
+ }
39
+ /** A hapi plugin, registered with server.register({ plugin: inferloPlugin, options }). */
40
+ export type InferloPlugin = Plugin<InferloPluginOptions>;
41
+ /**
42
+ * hapi plugin. options: { ai } decorates server.ai and request.ai; options: { app } serves a whole Inferlo app
43
+ * (routes, auth, validation, OpenAPI, MCP) under the prefix the plugin is registered with (routes: { prefix }).
44
+ */
45
+ export declare const inferloPlugin: InferloPlugin;
package/dist/hapi.js ADDED
@@ -0,0 +1,57 @@
1
+ import { assertAIClient } from "./ai-client.js";
2
+ import { InferloError } from "./errors.js";
3
+ import { toNodeHandler } from "./serve.js";
4
+ const bad = (message, fix) => new InferloError("IL5025", message, { fix });
5
+ async function register(server, options) {
6
+ if (options === null || typeof options !== "object") {
7
+ throw bad("inferloPlugin options must be an object with ai, app or both.", "Use server.register({ plugin: inferloPlugin, options: { ai } }).");
8
+ }
9
+ if ("prefix" in options) {
10
+ throw bad("inferloPlugin takes the path prefix from hapi, not from its options.", 'Use server.register({ plugin: inferloPlugin, options: { app }, routes: { prefix: "/api" } }).');
11
+ }
12
+ const { app } = options;
13
+ if (app !== undefined && (typeof app !== "object" || app === null || typeof app.fetch !== "function")) {
14
+ throw bad("inferloPlugin's app must be an Inferlo app (createApp(...)).", 'Use server.register({ plugin: inferloPlugin, options: { app: inferloApp }, routes: { prefix: "/api" } }).');
15
+ }
16
+ if (!app && !options.ai) {
17
+ throw bad("inferloPlugin needs ai, app or both.", 'Use options: { ai } for server.ai and request.ai, or options: { app } with routes: { prefix: "/api" } to serve an Inferlo app.');
18
+ }
19
+ const decorated = server.decorations.server.includes("ai");
20
+ // app.ai is the default, unless an earlier registration with { ai } already set server.ai.
21
+ const ai = options.ai ?? (decorated ? undefined : app?.ai);
22
+ if (ai !== undefined) {
23
+ assertAIClient(ai, 'Pass createAI({ providers, models }) from "@browserlessapi/inferlo/ai", or an Inferlo app\'s app.ai: server.register({ plugin: inferloPlugin, options: { ai } }).');
24
+ if (decorated) {
25
+ throw bad("server.ai is already set by an earlier inferloPlugin registration.", "Register inferloPlugin with { ai } once, and with { app } (without ai) for each app you serve.");
26
+ }
27
+ // A value, not a method (older hapi types only describe method decorations).
28
+ server.decorate("server", "ai", ai);
29
+ // A getter, so every request reads the one client.
30
+ server.decorate("request", "ai", () => ai, { apply: true });
31
+ }
32
+ if (!app)
33
+ return;
34
+ const prefix = server.realm.modifiers.route.prefix;
35
+ const handler = toNodeHandler(app, { prefix });
36
+ // Inferlo reads the body stream itself (JSON, forms, its own size limits) and writes the answer, streams
37
+ // included, to the Node response; hapi's own routes stay more specific than this catch-all.
38
+ server.route({
39
+ method: "*",
40
+ path: "/{path*}",
41
+ options: { payload: { output: "stream", parse: false }, description: "Inferlo app" },
42
+ handler: async (request, h) => {
43
+ await handler(request.raw.req, request.raw.res);
44
+ return h.abandon;
45
+ },
46
+ });
47
+ }
48
+ /**
49
+ * hapi plugin. options: { ai } decorates server.ai and request.ai; options: { app } serves a whole Inferlo app
50
+ * (routes, auth, validation, OpenAPI, MCP) under the prefix the plugin is registered with (routes: { prefix }).
51
+ */
52
+ export const inferloPlugin = {
53
+ name: "@browserlessapi/inferlo",
54
+ multiple: true,
55
+ register,
56
+ };
57
+ //# sourceMappingURL=hapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hapi.js","sourceRoot":"","sources":["../src/hapi.ts"],"names":[],"mappings":"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"}
package/dist/hono.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Inferlo inside Hono (4.0 and later), without a runtime dependency on Hono:
3
+ *
4
+ * import { Hono } from "hono";
5
+ * import { createAI, anthropic } from "@browserlessapi/inferlo/ai";
6
+ * import { inferloAI, type InferloVariables } from "@browserlessapi/inferlo/hono";
7
+ *
8
+ * const hono = new Hono<{ Variables: InferloVariables }>();
9
+ * hono.use(inferloAI(ai)); // c.var.ai in every handler
10
+ * hono.mount("/api", inferloApp.fetch); // or a whole Inferlo app under a path
11
+ *
12
+ * This entry point never loads the router, database or jobs code.
13
+ */
14
+ import type { AI } from "./ai/index.ts";
15
+ /** Context variables set by inferloAI(): new Hono<{ Variables: InferloVariables }>(). */
16
+ export type InferloVariables = {
17
+ ai: AI;
18
+ };
19
+ /** The part of Hono's Context that inferloAI() uses. */
20
+ export interface HonoContextLike {
21
+ set(key: "ai", value: AI): void;
22
+ }
23
+ /** A Hono middleware: hono.use(inferloAI(ai)) or hono.use("/chat/*", inferloAI(ai)). */
24
+ export type InferloAIMiddleware = (c: HonoContextLike, next: () => Promise<void>) => Promise<void>;
25
+ /** Puts an AI client (createAI(...) or an Inferlo app's app.ai) on the Hono context as c.var.ai. */
26
+ export declare function inferloAI(ai: AI): InferloAIMiddleware;
package/dist/hono.js ADDED
@@ -0,0 +1,10 @@
1
+ import { assertAIClient } from "./ai-client.js";
2
+ /** Puts an AI client (createAI(...) or an Inferlo app's app.ai) on the Hono context as c.var.ai. */
3
+ export function inferloAI(ai) {
4
+ assertAIClient(ai, 'Pass createAI({ providers, models }) from "@browserlessapi/inferlo/ai", or an Inferlo app\'s app.ai: hono.use(inferloAI(ai)).');
5
+ return async (c, next) => {
6
+ c.set("ai", ai);
7
+ await next();
8
+ };
9
+ }
10
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.js","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAahD,oGAAoG;AACpG,MAAM,UAAU,SAAS,CAAC,EAAM;IAC9B,cAAc,CAAC,EAAE,EAAE,+HAA+H,CAAC,CAAC;IACpJ,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAChB,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}