hono-agents 0.0.0-00ba881
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 +109 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
- package/src/index.ts +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
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 agents hono hono-agents
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { Hono } from "hono";
|
|
17
|
+
import { Agent } from "agents";
|
|
18
|
+
import { agentsMiddleware } from "hono-agents";
|
|
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, add bindings to your `wrangler.jsonc` file:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"durable_objects": {
|
|
74
|
+
"bindings": [
|
|
75
|
+
{ "name": "ChatAgent", "class_name": "ChatAgent" },
|
|
76
|
+
{ "name": "AssistantAgent", "class_name": "AssistantAgent" }
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"migrations": [
|
|
80
|
+
{
|
|
81
|
+
"tag": "v1",
|
|
82
|
+
"new_sqlite_classes": ["ChatAgent", "AssistantAgent"]
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## How It Works
|
|
89
|
+
|
|
90
|
+
The `agentsMiddleware` function:
|
|
91
|
+
|
|
92
|
+
1. Detects whether the incoming request is a WebSocket connection or standard HTTP request
|
|
93
|
+
2. Routes the request to the appropriate agent
|
|
94
|
+
3. Handles WebSocket upgrades for persistent connections
|
|
95
|
+
4. Provides error handling and custom routing options
|
|
96
|
+
|
|
97
|
+
Agents can:
|
|
98
|
+
|
|
99
|
+
- Maintain state across requests
|
|
100
|
+
- Handle both HTTP and WebSocket connections
|
|
101
|
+
- Schedule tasks for future execution
|
|
102
|
+
- Communicate with AI services
|
|
103
|
+
- Integrate seamlessly with React applications
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
Learn more about Cloudflare Agents at https://www.npmjs.com/package/agents
|
|
108
|
+
|
|
109
|
+
ISC
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as hono from "hono";
|
|
2
|
+
import { Env } from "hono";
|
|
3
|
+
import { AgentOptions } from "agents";
|
|
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<Env, string, {}>;
|
|
21
|
+
|
|
22
|
+
export { agentsMiddleware };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { routeAgentRequest } from "agents";
|
|
3
|
+
import { env } from "hono/adapter";
|
|
4
|
+
import { createMiddleware } from "hono/factory";
|
|
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
|
+
async function handleWebSocketUpgrade(c, options) {
|
|
24
|
+
const response = await routeAgentRequest(
|
|
25
|
+
c.req.raw,
|
|
26
|
+
env(c),
|
|
27
|
+
options
|
|
28
|
+
);
|
|
29
|
+
if (!response?.webSocket) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return new Response(null, {
|
|
33
|
+
status: 101,
|
|
34
|
+
webSocket: response.webSocket
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async function handleHttpRequest(c, options) {
|
|
38
|
+
return routeAgentRequest(c.req.raw, env(c), options);
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
agentsMiddleware
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { AgentOptions } from \"agents\";\nimport { routeAgentRequest } from \"agents\";\nimport type { Context, Env } from \"hono\";\nimport { env } from \"hono/adapter\";\nimport { createMiddleware } from \"hono/factory\";\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<Env>(async (c, next) => {\n try {\n const handler = isWebSocketUpgrade(c)\n ? handleWebSocketUpgrade\n : handleHttpRequest;\n\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 * 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 response = await routeAgentRequest(\n c.req.raw,\n env(c) satisfies Env,\n options\n );\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 return routeAgentRequest(c.req.raw, env(c) satisfies Env, options);\n}\n"],"mappings":";AACA,SAAS,yBAAyB;AAElC,SAAS,WAAW;AACpB,SAAS,wBAAwB;AAgB1B,SAAS,iBACd,KACA;AACA,SAAO,iBAAsB,OAAO,GAAG,SAAS;AAC9C,QAAI;AACF,YAAM,UAAU,mBAAmB,CAAC,IAChC,yBACA;AAEJ,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,eAAe,uBACb,GACA,SACA;AACA,QAAM,WAAW,MAAM;AAAA,IACrB,EAAE,IAAI;AAAA,IACN,IAAI,CAAC;AAAA,IACL;AAAA,EACF;AAEA,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,SAAO,kBAAkB,EAAE,IAAI,KAAK,IAAI,CAAC,GAAiB,OAAO;AACnE;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "Cloudflare Inc.",
|
|
3
|
+
"bugs": {
|
|
4
|
+
"url": "https://github.com/cloudflare/agents/issues"
|
|
5
|
+
},
|
|
6
|
+
"description": "Add Cloudflare Agents to your Hono app",
|
|
7
|
+
"devDependencies": {
|
|
8
|
+
"agents": "0.0.0-00ba881",
|
|
9
|
+
"hono": "^4.9.7"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
|
+
"require": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"cloudflare",
|
|
27
|
+
"agents",
|
|
28
|
+
"hono"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"main": "src/index.ts",
|
|
32
|
+
"name": "hono-agents",
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"agents": "0.0.0-00ba881",
|
|
35
|
+
"hono": "^4.6.17"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"directory": "packages/hono-agents",
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/cloudflare/agents.git"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsx ./scripts/build.ts",
|
|
44
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
45
|
+
},
|
|
46
|
+
"type": "module",
|
|
47
|
+
"types": "dist/index.d.ts",
|
|
48
|
+
"version": "0.0.0-00ba881"
|
|
49
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { AgentOptions } from "agents";
|
|
2
|
+
import { routeAgentRequest } from "agents";
|
|
3
|
+
import type { Context, Env } from "hono";
|
|
4
|
+
import { env } from "hono/adapter";
|
|
5
|
+
import { createMiddleware } from "hono/factory";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Configuration options for the Cloudflare Agents middleware
|
|
9
|
+
*/
|
|
10
|
+
type AgentMiddlewareContext<E extends Env> = {
|
|
11
|
+
/** Cloudflare Agents-specific configuration options */
|
|
12
|
+
options?: AgentOptions<E>;
|
|
13
|
+
/** Optional error handler for caught errors */
|
|
14
|
+
onError?: (error: Error) => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Creates a middleware for handling Cloudflare Agents WebSocket and HTTP requests
|
|
19
|
+
* Processes both WebSocket upgrades and standard HTTP requests, delegating them to Cloudflare Agents
|
|
20
|
+
*/
|
|
21
|
+
export function agentsMiddleware<E extends Env = Env>(
|
|
22
|
+
ctx?: AgentMiddlewareContext<E>
|
|
23
|
+
) {
|
|
24
|
+
return createMiddleware<Env>(async (c, next) => {
|
|
25
|
+
try {
|
|
26
|
+
const handler = isWebSocketUpgrade(c)
|
|
27
|
+
? handleWebSocketUpgrade
|
|
28
|
+
: handleHttpRequest;
|
|
29
|
+
|
|
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
|
+
* Handles WebSocket upgrade requests
|
|
53
|
+
* Returns a WebSocket upgrade response if successful, null otherwise
|
|
54
|
+
*/
|
|
55
|
+
async function handleWebSocketUpgrade<E extends Env>(
|
|
56
|
+
c: Context<E>,
|
|
57
|
+
options?: AgentOptions<E>
|
|
58
|
+
) {
|
|
59
|
+
const response = await routeAgentRequest(
|
|
60
|
+
c.req.raw,
|
|
61
|
+
env(c) satisfies Env,
|
|
62
|
+
options
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
if (!response?.webSocket) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return new Response(null, {
|
|
70
|
+
status: 101,
|
|
71
|
+
webSocket: response.webSocket
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Handles standard HTTP requests
|
|
77
|
+
* Forwards the request to Cloudflare Agents and returns the response
|
|
78
|
+
*/
|
|
79
|
+
async function handleHttpRequest<E extends Env>(
|
|
80
|
+
c: Context<E>,
|
|
81
|
+
options?: AgentOptions<E>
|
|
82
|
+
) {
|
|
83
|
+
return routeAgentRequest(c.req.raw, env(c) satisfies Env, options);
|
|
84
|
+
}
|