hono-agents 0.0.0 → 0.0.5

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 ADDED
@@ -0,0 +1,104 @@
1
+ # hono-agents
2
+
3
+ 🔥 Hono ⨉ 🧠 Cloudflare Agents
4
+
5
+ Add intelligent, stateful AI agents to your Hono app. Create persistent AI agents that can think, communicate, and evolve over time, all integrated seamlessly with your Hono application.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install hono-agents hono agents-sdk
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```ts
16
+ import { Hono } from "hono";
17
+ import { agentsMiddleware } from "hono-agents";
18
+ import { Agent } from "agents-sdk";
19
+
20
+ // Define your agent classes
21
+ export class ChatAgent extends Agent {
22
+ async onRequest(request) {
23
+ return new Response("Ready to assist with chat.");
24
+ }
25
+ }
26
+
27
+ export class AssistantAgent extends Agent {
28
+ async onRequest(request) {
29
+ return new Response("I'm your AI assistant.");
30
+ }
31
+ }
32
+
33
+ // Basic setup
34
+ const app = new Hono();
35
+ app.use("*", agentsMiddleware());
36
+
37
+ // or with authentication
38
+ app.use(
39
+ "*",
40
+ agentsMiddleware({
41
+ options: {
42
+ onBeforeConnect: async (req) => {
43
+ const token = req.headers.get("authorization");
44
+ // validate token
45
+ if (!token) return new Response("Unauthorized", { status: 401 });
46
+ },
47
+ },
48
+ })
49
+ );
50
+
51
+ // With error handling
52
+ app.use("*", agentsMiddleware({ onError: (error) => console.error(error) }));
53
+
54
+ // With custom routing
55
+ app.use(
56
+ "*",
57
+ agentsMiddleware({
58
+ options: {
59
+ prefix: "/agents", // Handles /agents/* routes only
60
+ },
61
+ })
62
+ );
63
+
64
+ export default app;
65
+ ```
66
+
67
+ ## Configuration
68
+
69
+ To properly configure your Cloudflare Workers project to use agents, update your `wrangler.toml` file:
70
+
71
+ ```toml
72
+ [durable_objects]
73
+ bindings = [
74
+ { name = "ChatAgent", class_name = "ChatAgent" },
75
+ { name = "AssistantAgent", class_name = "AssistantAgent" }
76
+ ]
77
+
78
+ [[migrations]]
79
+ tag = "v1"
80
+ new_sqlite_classes = ["ChatAgent", "AssistantAgent"]
81
+ ```
82
+
83
+ ## How It Works
84
+
85
+ The `agentsMiddleware` function:
86
+
87
+ 1. Detects whether the incoming request is a WebSocket connection or standard HTTP request
88
+ 2. Routes the request to the appropriate agent
89
+ 3. Handles WebSocket upgrades for persistent connections
90
+ 4. Provides error handling and custom routing options
91
+
92
+ Agents can:
93
+
94
+ - Maintain state across requests
95
+ - Handle both HTTP and WebSocket connections
96
+ - Schedule tasks for future execution
97
+ - Communicate with AI services
98
+ - Integrate seamlessly with React applications
99
+
100
+ ## License
101
+
102
+ Learn more about Cloudflare Agents at https://www.npmjs.com/package/agents-sdk
103
+
104
+ ISC
@@ -0,0 +1,22 @@
1
+ import * as hono from "hono";
2
+ import { Env } from "hono";
3
+ import { AgentOptions } from "agents-sdk";
4
+
5
+ /**
6
+ * Configuration options for the Cloudflare Agents middleware
7
+ */
8
+ type AgentMiddlewareContext<E extends Env> = {
9
+ /** Cloudflare Agents-specific configuration options */
10
+ options?: AgentOptions<E>;
11
+ /** Optional error handler for caught errors */
12
+ onError?: (error: Error) => void;
13
+ };
14
+ /**
15
+ * Creates a middleware for handling Cloudflare Agents WebSocket and HTTP requests
16
+ * Processes both WebSocket upgrades and standard HTTP requests, delegating them to Cloudflare Agents
17
+ */
18
+ declare function agentsMiddleware<E extends Env = Env>(
19
+ ctx?: AgentMiddlewareContext<E>
20
+ ): hono.MiddlewareHandler<any, string, {}>;
21
+
22
+ export { agentsMiddleware };
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ // src/index.ts
2
+ import { env } from "hono/adapter";
3
+ import { createMiddleware } from "hono/factory";
4
+ import { routeAgentRequest } from "agents-sdk";
5
+ function agentsMiddleware(ctx) {
6
+ return createMiddleware(async (c, next) => {
7
+ try {
8
+ const handler = isWebSocketUpgrade(c) ? handleWebSocketUpgrade : handleHttpRequest;
9
+ const response = await handler(c, ctx?.options);
10
+ return response === null ? await next() : response;
11
+ } catch (error) {
12
+ if (ctx?.onError) {
13
+ ctx.onError(error);
14
+ return next();
15
+ }
16
+ throw error;
17
+ }
18
+ });
19
+ }
20
+ function isWebSocketUpgrade(c) {
21
+ return c.req.header("upgrade")?.toLowerCase() === "websocket";
22
+ }
23
+ function createRequestFromContext(c) {
24
+ return new Request(c.req.url, {
25
+ method: c.req.method,
26
+ headers: c.req.header(),
27
+ body: c.req.raw.body
28
+ });
29
+ }
30
+ async function handleWebSocketUpgrade(c, options) {
31
+ const req = createRequestFromContext(c);
32
+ const response = await routeAgentRequest(req, env(c), options);
33
+ if (!response?.webSocket) {
34
+ return null;
35
+ }
36
+ return new Response(null, {
37
+ status: 101,
38
+ webSocket: response.webSocket
39
+ });
40
+ }
41
+ async function handleHttpRequest(c, options) {
42
+ const req = createRequestFromContext(c);
43
+ return routeAgentRequest(req, env(c), options);
44
+ }
45
+ export {
46
+ agentsMiddleware
47
+ };
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { env } from \"hono/adapter\";\nimport { createMiddleware } from \"hono/factory\";\nimport { routeAgentRequest } from \"agents-sdk\";\n\nimport type { Context, Env } from \"hono\";\nimport type { AgentOptions } from \"agents-sdk\";\n\n/**\n * Configuration options for the Cloudflare Agents middleware\n */\ntype AgentMiddlewareContext<E extends Env> = {\n /** Cloudflare Agents-specific configuration options */\n options?: AgentOptions<E>;\n /** Optional error handler for caught errors */\n onError?: (error: Error) => void;\n};\n\n/**\n * Creates a middleware for handling Cloudflare Agents WebSocket and HTTP requests\n * Processes both WebSocket upgrades and standard HTTP requests, delegating them to Cloudflare Agents\n */\nexport function agentsMiddleware<E extends Env = Env>(\n ctx?: AgentMiddlewareContext<E>\n) {\n return createMiddleware(async (c, next) => {\n try {\n const handler = isWebSocketUpgrade(c)\n ? handleWebSocketUpgrade\n : handleHttpRequest;\n const response = await handler(c, ctx?.options);\n\n return response === null ? await next() : response;\n } catch (error) {\n if (ctx?.onError) {\n ctx.onError(error as Error);\n return next();\n }\n throw error;\n }\n });\n}\n\n/**\n * Checks if the incoming request is a WebSocket upgrade request\n * Looks for the 'upgrade' header with a value of 'websocket' (case-insensitive)\n */\nfunction isWebSocketUpgrade(c: Context): boolean {\n return c.req.header(\"upgrade\")?.toLowerCase() === \"websocket\";\n}\n\n/**\n * Creates a new Request object from the Hono context\n * Preserves the original request's URL, method, headers, and body\n */\nfunction createRequestFromContext(c: Context) {\n return new Request(c.req.url, {\n method: c.req.method,\n headers: c.req.header(),\n body: c.req.raw.body,\n });\n}\n\n/**\n * Handles WebSocket upgrade requests\n * Returns a WebSocket upgrade response if successful, null otherwise\n */\nasync function handleWebSocketUpgrade<E extends Env>(\n c: Context<E>,\n options?: AgentOptions<E>\n) {\n const req = createRequestFromContext(c);\n const response = await routeAgentRequest(req, env(c), options);\n\n if (!response?.webSocket) {\n return null;\n }\n\n return new Response(null, {\n status: 101,\n webSocket: response.webSocket,\n });\n}\n\n/**\n * Handles standard HTTP requests\n * Forwards the request to Cloudflare Agents and returns the response\n */\nasync function handleHttpRequest<E extends Env>(\n c: Context<E>,\n options?: AgentOptions<E>\n) {\n const req = createRequestFromContext(c);\n return routeAgentRequest(req, env(c), options);\n}\n"],"mappings":";AAAA,SAAS,WAAW;AACpB,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAmB3B,SAAS,iBACd,KACA;AACA,SAAO,iBAAiB,OAAO,GAAG,SAAS;AACzC,QAAI;AACF,YAAM,UAAU,mBAAmB,CAAC,IAChC,yBACA;AACJ,YAAM,WAAW,MAAM,QAAQ,GAAG,KAAK,OAAO;AAE9C,aAAO,aAAa,OAAO,MAAM,KAAK,IAAI;AAAA,IAC5C,SAAS,OAAO;AACd,UAAI,KAAK,SAAS;AAChB,YAAI,QAAQ,KAAc;AAC1B,eAAO,KAAK;AAAA,MACd;AACA,YAAM;AAAA,IACR;AAAA,EACF,CAAC;AACH;AAMA,SAAS,mBAAmB,GAAqB;AAC/C,SAAO,EAAE,IAAI,OAAO,SAAS,GAAG,YAAY,MAAM;AACpD;AAMA,SAAS,yBAAyB,GAAY;AAC5C,SAAO,IAAI,QAAQ,EAAE,IAAI,KAAK;AAAA,IAC5B,QAAQ,EAAE,IAAI;AAAA,IACd,SAAS,EAAE,IAAI,OAAO;AAAA,IACtB,MAAM,EAAE,IAAI,IAAI;AAAA,EAClB,CAAC;AACH;AAMA,eAAe,uBACb,GACA,SACA;AACA,QAAM,MAAM,yBAAyB,CAAC;AACtC,QAAM,WAAW,MAAM,kBAAkB,KAAK,IAAI,CAAC,GAAG,OAAO;AAE7D,MAAI,CAAC,UAAU,WAAW;AACxB,WAAO;AAAA,EACT;AAEA,SAAO,IAAI,SAAS,MAAM;AAAA,IACxB,QAAQ;AAAA,IACR,WAAW,SAAS;AAAA,EACtB,CAAC;AACH;AAMA,eAAe,kBACb,GACA,SACA;AACA,QAAM,MAAM,yBAAyB,CAAC;AACtC,SAAO,kBAAkB,KAAK,IAAI,CAAC,GAAG,OAAO;AAC/C;","names":[]}
package/package.json CHANGED
@@ -1,12 +1,37 @@
1
1
  {
2
2
  "name": "hono-agents",
3
- "version": "0.0.0",
4
- "main": "index.js",
3
+ "version": "0.0.5",
4
+ "main": "src/index.ts",
5
+ "type": "module",
5
6
  "scripts": {
6
- "test": "echo \"Error: no test specified\" && exit 1"
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "build": "tsx ./scripts/build.ts"
7
9
  },
8
- "keywords": [],
9
- "author": "",
10
- "license": "ISC",
11
- "description": ""
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "require": "./dist/index.js",
18
+ "import": "./dist/index.js"
19
+ }
20
+ },
21
+ "keywords": [
22
+ "cloudflare",
23
+ "agents",
24
+ "hono"
25
+ ],
26
+ "author": "Cloudflare Inc.",
27
+ "license": "MIT",
28
+ "description": "Add Cloudflare Agents to your Hono app",
29
+ "peerDependencies": {
30
+ "agents-sdk": "^0.0.17",
31
+ "hono": "^4.6.17"
32
+ },
33
+ "devDependencies": {
34
+ "agents-sdk": "^0.0.17",
35
+ "hono": "^4.6.17"
36
+ }
12
37
  }
package/src/index.ts ADDED
@@ -0,0 +1,94 @@
1
+ import { env } from "hono/adapter";
2
+ import { createMiddleware } from "hono/factory";
3
+ import { routeAgentRequest } from "agents-sdk";
4
+
5
+ import type { Context, Env } from "hono";
6
+ import type { AgentOptions } from "agents-sdk";
7
+
8
+ /**
9
+ * Configuration options for the Cloudflare Agents middleware
10
+ */
11
+ type AgentMiddlewareContext<E extends Env> = {
12
+ /** Cloudflare Agents-specific configuration options */
13
+ options?: AgentOptions<E>;
14
+ /** Optional error handler for caught errors */
15
+ onError?: (error: Error) => void;
16
+ };
17
+
18
+ /**
19
+ * Creates a middleware for handling Cloudflare Agents WebSocket and HTTP requests
20
+ * Processes both WebSocket upgrades and standard HTTP requests, delegating them to Cloudflare Agents
21
+ */
22
+ export function agentsMiddleware<E extends Env = Env>(
23
+ ctx?: AgentMiddlewareContext<E>
24
+ ) {
25
+ return createMiddleware(async (c, next) => {
26
+ try {
27
+ const handler = isWebSocketUpgrade(c)
28
+ ? handleWebSocketUpgrade
29
+ : handleHttpRequest;
30
+ const response = await handler(c, ctx?.options);
31
+
32
+ return response === null ? await next() : response;
33
+ } catch (error) {
34
+ if (ctx?.onError) {
35
+ ctx.onError(error as Error);
36
+ return next();
37
+ }
38
+ throw error;
39
+ }
40
+ });
41
+ }
42
+
43
+ /**
44
+ * Checks if the incoming request is a WebSocket upgrade request
45
+ * Looks for the 'upgrade' header with a value of 'websocket' (case-insensitive)
46
+ */
47
+ function isWebSocketUpgrade(c: Context): boolean {
48
+ return c.req.header("upgrade")?.toLowerCase() === "websocket";
49
+ }
50
+
51
+ /**
52
+ * Creates a new Request object from the Hono context
53
+ * Preserves the original request's URL, method, headers, and body
54
+ */
55
+ function createRequestFromContext(c: Context) {
56
+ return new Request(c.req.url, {
57
+ method: c.req.method,
58
+ headers: c.req.header(),
59
+ body: c.req.raw.body,
60
+ });
61
+ }
62
+
63
+ /**
64
+ * Handles WebSocket upgrade requests
65
+ * Returns a WebSocket upgrade response if successful, null otherwise
66
+ */
67
+ async function handleWebSocketUpgrade<E extends Env>(
68
+ c: Context<E>,
69
+ options?: AgentOptions<E>
70
+ ) {
71
+ const req = createRequestFromContext(c);
72
+ const response = await routeAgentRequest(req, env(c), options);
73
+
74
+ if (!response?.webSocket) {
75
+ return null;
76
+ }
77
+
78
+ return new Response(null, {
79
+ status: 101,
80
+ webSocket: response.webSocket,
81
+ });
82
+ }
83
+
84
+ /**
85
+ * Handles standard HTTP requests
86
+ * Forwards the request to Cloudflare Agents and returns the response
87
+ */
88
+ async function handleHttpRequest<E extends Env>(
89
+ c: Context<E>,
90
+ options?: AgentOptions<E>
91
+ ) {
92
+ const req = createRequestFromContext(c);
93
+ return routeAgentRequest(req, env(c), options);
94
+ }