@hugex/ai 2.8.12 → 2.8.13
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 +132 -100
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
# @hugex/ai
|
|
2
2
|
|
|
3
|
-
HugeX Agent runtime
|
|
3
|
+
HugeX Agent runtime — a React client hook (`useAgent`) plus optional server handlers for hosting the agent backend on Cloudflare Workers.
|
|
4
4
|
|
|
5
|
-
Flows are **designed** in the [HugeX platform](https://hugex.co/) (**Agent Design**) and **saved** to HX Core.
|
|
5
|
+
Flows are **designed** in the [HugeX platform](https://hugex.co/) (**Agent Design**) and **saved** to HX Core. Most integrations only need the **client** half: install `@hugex/ai`, point `useAgent` at an already-deployed WebSocket endpoint, and render chat UI from the agent store.
|
|
6
|
+
|
|
7
|
+
## Two parts
|
|
8
|
+
|
|
9
|
+
| Part | Import | Runs in | When you need it |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| **Client** | `@hugex/ai/client` | Your React app (browser) | **Always** — connect UI to an agent session |
|
|
12
|
+
| **Server** | `@hugex/ai` | Cloudflare Worker | **Only if you host the agent runtime** (tenant Worker deployment) |
|
|
13
|
+
| **Shared types** | `@hugex/ai/common` | Either | Wire-protocol and flow types |
|
|
14
|
+
|
|
15
|
+
**You do not run `useAgent` on Cloudflare Workers.** The hook is frontend-only. It opens a WebSocket to a session endpoint; that endpoint is usually served by a HugeX tenant Worker you or HugeX already deployed. Your SPA can run anywhere — same origin, a separate frontend host, or a local dev server — as long as it can reach the WebSocket URL.
|
|
6
16
|
|
|
7
17
|
## Install
|
|
8
18
|
|
|
@@ -10,77 +20,43 @@ Flows are **designed** in the [HugeX platform](https://hugex.co/) (**Agent Desig
|
|
|
10
20
|
pnpm add @hugex/ai
|
|
11
21
|
```
|
|
12
22
|
|
|
13
|
-
Peer dependencies are declared in the package — align versions with your
|
|
23
|
+
Peer dependencies are declared in the package — align versions with your app.
|
|
14
24
|
|
|
15
|
-
##
|
|
25
|
+
## Integration paths
|
|
16
26
|
|
|
17
|
-
|
|
18
|
-
|---|---|
|
|
19
|
-
| `@hugex/ai` | Server: `handleAgentsRoutes`, `handleAuthRoutes`, `handleCommonRoutes`, `handleIntancesRoutes`, `AgentDO` |
|
|
20
|
-
| `@hugex/ai/client` | Client: `useAgent`, `useAgentStore`, `getAgentStore` |
|
|
21
|
-
| `@hugex/ai/common` | Shared types: `NodeType`, WS `messageTypes`, flow/message types |
|
|
27
|
+
### Frontend only (most common)
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
Use `@hugex/ai/client` in your React app. You need:
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
1. **flowId** — the agent graph id from Agent Design
|
|
32
|
+
2. **sessionId** — a stable id for this chat session (UUID recommended)
|
|
33
|
+
3. **WebSocket endpoint** — URL of a deployed agent server (see [WebSocket paths](#websocket-paths))
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
// workers/app.ts
|
|
29
|
-
import {
|
|
30
|
-
handleAgentsRoutes,
|
|
31
|
-
handleAuthRoutes,
|
|
32
|
-
handleCommonRoutes,
|
|
33
|
-
handleIntancesRoutes,
|
|
34
|
-
} from '@hugex/ai';
|
|
35
|
+
No Worker code, wrangler config, or server imports required in your frontend repo.
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const auth = await handleAuthRoutes(request, env, ctx);
|
|
42
|
-
if (auth instanceof Response) return auth;
|
|
43
|
-
|
|
44
|
-
const agent = await handleAgentsRoutes(request, env, ctx);
|
|
45
|
-
if (agent instanceof Response) return agent;
|
|
46
|
-
|
|
47
|
-
const instances = await handleIntancesRoutes(request, env, ctx);
|
|
48
|
-
if (instances instanceof Response) return instances;
|
|
49
|
-
|
|
50
|
-
// Then delegate to your app's SSR/router handler.
|
|
51
|
-
return yourAppHandler(request, { cloudflare: { env, ctx }, state: { ...auth } });
|
|
52
|
-
},
|
|
53
|
-
} satisfies ExportedHandler<Env>;
|
|
54
|
-
|
|
55
|
-
export { AgentDO } from '@hugex/ai';
|
|
56
|
-
```
|
|
37
|
+
| Scenario | `host` | Notes |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| App and agent server share a domain | omit | `basePath` is relative to the page origin |
|
|
40
|
+
| App on a different host (SPA, mobile web, local dev) | set to agent server host | e.g. `tenant.data.ora.socketServer` |
|
|
41
|
+
| Multiple agents on one screen | + `storeKey` | Isolates chat state per agent |
|
|
57
42
|
|
|
58
|
-
|
|
43
|
+
### Self-hosted runtime (tenant Worker)
|
|
59
44
|
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
"durable_objects": {
|
|
63
|
-
"bindings": [{ "class_name": "AgentDO", "name": "AGENT" }]
|
|
64
|
-
},
|
|
65
|
-
"migrations": [{ "tag": "v2", "new_sqlite_classes": ["AgentDO"] }]
|
|
66
|
-
}
|
|
67
|
-
```
|
|
45
|
+
Only needed when **your** Cloudflare Worker must serve agent WebSocket routes (`/api/agent/flow/...`, `/api/ora/connect/...`) and run `AgentDO` sessions. See [Cloudflare Workers (optional)](#cloudflare-workers-optional--host-the-runtime).
|
|
68
46
|
|
|
69
|
-
|
|
47
|
+
HugeX-managed tenant deployments already include this — frontend teams typically skip this section.
|
|
70
48
|
|
|
71
49
|
## Flow IDs and agent configuration
|
|
72
50
|
|
|
73
|
-
A **flow** is the graph you edit in
|
|
74
|
-
|
|
75
|
-
At runtime:
|
|
51
|
+
A **flow** is the graph you edit in **Agent Design** (`/ai/agents/:id`). The URL param `id` is the **flowId** (e.g. `1rShqGMrANRGmXTN1mjTJB`).
|
|
76
52
|
|
|
77
53
|
| Concept | Value | Notes |
|
|
78
54
|
|---|---|---|
|
|
79
|
-
| **flowId** | Agent Design `:id` | Identifies which flow graph to run
|
|
80
|
-
| **sessionId** | UUID (or stable string) | One chat session; maps to
|
|
81
|
-
| **
|
|
55
|
+
| **flowId** | Agent Design `:id` | Identifies which flow graph to run |
|
|
56
|
+
| **sessionId** | UUID (or stable string) | One chat session; server maps this to session state |
|
|
57
|
+
| **Session key** | `` `${flowId}::${sessionId}` `` | Server-side identifier (used when hosting the runtime) |
|
|
82
58
|
|
|
83
|
-
Flow metadata (tenant, visibility, status) lives in HX Core
|
|
59
|
+
Flow metadata (tenant, visibility, status) lives in HX Core. The runtime loads flow **state** (nodes/edges) from HX Core on WebSocket connect.
|
|
84
60
|
|
|
85
61
|
### Node types (flow graph)
|
|
86
62
|
|
|
@@ -97,9 +73,9 @@ Design-time node data (configured in Agent Design panels):
|
|
|
97
73
|
|
|
98
74
|
Rules: exactly one Start, at least one Answer, all paths connected.
|
|
99
75
|
|
|
100
|
-
## `useAgent` — client
|
|
76
|
+
## `useAgent` — client integration
|
|
101
77
|
|
|
102
|
-
`useAgent` opens a WebSocket to the session
|
|
78
|
+
`useAgent` opens a WebSocket to the agent session, decodes the `TYPE::CONTENT` wire protocol, and writes conversation state into the agent store. UI components subscribe to the store and call `send`, `clearHistory`, etc.
|
|
103
79
|
|
|
104
80
|
### Options
|
|
105
81
|
|
|
@@ -119,16 +95,16 @@ Returns `{ connection, store, send, clearHistory, sendAuth, setIdentity, approve
|
|
|
119
95
|
|
|
120
96
|
### WebSocket paths
|
|
121
97
|
|
|
122
|
-
|
|
98
|
+
These routes are served by the **agent backend** (typically a deployed tenant Worker). Your frontend connects to them; it does not implement them.
|
|
123
99
|
|
|
124
100
|
| Route | Auth | Typical use |
|
|
125
101
|
|---|---|---|
|
|
126
102
|
| `/api/agent/flow/{flowId}/{sessionId}` | JWT / `access_token` query | Tenant chat UIs, Run panel |
|
|
127
|
-
| `/api/ora/connect/{flowId}/{sessionId}` | Agent API key (`authorization` query/header) |
|
|
103
|
+
| `/api/ora/connect/{flowId}/{sessionId}` | Agent API key (`authorization` query/header) | Design assistant, tooling |
|
|
128
104
|
|
|
129
|
-
### Pattern 1 —
|
|
105
|
+
### Pattern 1 — same-origin chat
|
|
130
106
|
|
|
131
|
-
|
|
107
|
+
Frontend and agent server share a domain. No `host` needed. Uses the global store (`useAgentStore`).
|
|
132
108
|
|
|
133
109
|
```tsx
|
|
134
110
|
import { useAgent, useAgentStore } from '@hugex/ai/client';
|
|
@@ -146,19 +122,19 @@ function Chat({ flowId, sessionId }: { flowId: string; sessionId: string }) {
|
|
|
146
122
|
}
|
|
147
123
|
```
|
|
148
124
|
|
|
149
|
-
|
|
125
|
+
### Pattern 2 — cross-origin chat
|
|
150
126
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
Flow under design in Agent Design; `flowId` from route params; session from run store; JWT via `query`:
|
|
127
|
+
Frontend runs on a different host (SPA, local dev, separate deployment). Set `host` to the deployed agent server.
|
|
154
128
|
|
|
155
129
|
```tsx
|
|
130
|
+
import { useAgent, useAgentStore } from '@hugex/ai/client';
|
|
131
|
+
|
|
156
132
|
const flowId = '…'; // from your route or config
|
|
157
|
-
const sessionId = '…'; // from
|
|
158
|
-
const
|
|
133
|
+
const sessionId = '…'; // from session store
|
|
134
|
+
const socketHost = '…'; // deployed agent server host (no path)
|
|
159
135
|
|
|
160
136
|
const { send, sendAuth, clearHistory } = useAgent({
|
|
161
|
-
host:
|
|
137
|
+
host: socketHost,
|
|
162
138
|
basePath: `api/agent/flow/${flowId}/${sessionId}`,
|
|
163
139
|
agent: flowId,
|
|
164
140
|
name: sessionId,
|
|
@@ -168,38 +144,36 @@ const { send, sendAuth, clearHistory } = useAgent({
|
|
|
168
144
|
const messages = useAgentStore((s) => s.messages);
|
|
169
145
|
```
|
|
170
146
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
Start-node flags (`allow_images`, `allow_documents`, `memory_enabled`) are read from the canvas nodes to drive the Run UI.
|
|
147
|
+
Start-node flags (`allow_images`, `allow_documents`, `memory_enabled`) can be read from flow config (`flowConfig` in the store) or from your design metadata to drive the UI.
|
|
174
148
|
|
|
175
149
|
### Pattern 3 — multiple agents on one screen (`storeKey`)
|
|
176
150
|
|
|
177
|
-
When two agents mount together
|
|
151
|
+
When two agents mount together, pass a stable `storeKey` so their chat state does not collide:
|
|
178
152
|
|
|
179
153
|
```tsx
|
|
180
154
|
const { send, sendAuth, store } = useAgent({
|
|
181
|
-
host:
|
|
182
|
-
basePath: `api/ora/connect/${
|
|
183
|
-
agent:
|
|
155
|
+
host: AGENT_SERVER_HOST,
|
|
156
|
+
basePath: `api/ora/connect/${FLOW_ID}/${sessionId}`,
|
|
157
|
+
agent: FLOW_ID,
|
|
184
158
|
name: sessionId,
|
|
185
|
-
query: { authorization:
|
|
159
|
+
query: { authorization: AGENT_API_KEY },
|
|
186
160
|
user: email ?? undefined,
|
|
187
|
-
storeKey: '
|
|
161
|
+
storeKey: 'my-panel', // stable for this component's lifetime
|
|
188
162
|
});
|
|
189
163
|
|
|
190
164
|
const messages = store((s) => s.messages);
|
|
191
165
|
const status = store((s) => s.status);
|
|
192
166
|
```
|
|
193
167
|
|
|
194
|
-
|
|
168
|
+
Child components that need the same isolated state must use the **same** `storeKey` via `getAgentStore('my-panel')`.
|
|
195
169
|
|
|
196
170
|
**Rule:** `storeKey` must be constant for the component lifetime (do not derive from per-render state).
|
|
197
171
|
|
|
198
|
-
|
|
172
|
+
### Runtime credentials (`sendAuth`)
|
|
199
173
|
|
|
200
174
|
Tools may reference `{{ auth.NAME }}` placeholders. Push credentials with `sendAuth(name, value)` — they never appear in chat history.
|
|
201
175
|
|
|
202
|
-
**Important:** re-push credentials **before every `send`**, not once on connect.
|
|
176
|
+
**Important:** re-push credentials **before every `send`**, not once on connect. Server-side session hibernation can clear in-memory auth mid-connection without disconnecting the WebSocket.
|
|
203
177
|
|
|
204
178
|
```ts
|
|
205
179
|
const sendTurn = async (text: string) => {
|
|
@@ -211,13 +185,13 @@ const sendTurn = async (text: string) => {
|
|
|
211
185
|
|
|
212
186
|
`clearHistory()` wipes server auth too — re-push after clearing.
|
|
213
187
|
|
|
214
|
-
|
|
188
|
+
### Store fields (reactive UI)
|
|
215
189
|
|
|
216
190
|
Subscribe via `useAgentStore` (global) or `store` (isolated):
|
|
217
191
|
|
|
218
192
|
| Field | Use |
|
|
219
193
|
|---|---|
|
|
220
|
-
| `messages` | Chat history (replayed
|
|
194
|
+
| `messages` | Chat history (replayed on connect via `HIS::`) |
|
|
221
195
|
| `typingMessage` | Streaming assistant text (`TS` / `TSC`) |
|
|
222
196
|
| `reasoningMessage` | Streaming reasoning (`RS` / `RSC`) |
|
|
223
197
|
| `status` | `'connecting' \| 'connected' \| 'disconnected'` — gate input on `'connected'` |
|
|
@@ -226,7 +200,7 @@ Subscribe via `useAgentStore` (global) or `store` (isolated):
|
|
|
226
200
|
| `composioAuth` | OAuth redirect when a connected tool requires manual authorization |
|
|
227
201
|
| `approvals` | Human-in-the-loop tool approvals |
|
|
228
202
|
|
|
229
|
-
|
|
203
|
+
### Wire protocol (summary)
|
|
230
204
|
|
|
231
205
|
Inbound frames use `TYPE::CONTENT`:
|
|
232
206
|
|
|
@@ -241,7 +215,64 @@ Inbound frames use `TYPE::CONTENT`:
|
|
|
241
215
|
|
|
242
216
|
Outbound: `M:` user message, `CH:` clear history, `AUT:` runtime credential, `UID:` session identity.
|
|
243
217
|
|
|
244
|
-
|
|
218
|
+
## Cloudflare Workers (optional — host the runtime)
|
|
219
|
+
|
|
220
|
+
Use this section only when **you** deploy the agent backend on Cloudflare Workers (e.g. a tenant Worker). Frontend-only integrations can skip it entirely.
|
|
221
|
+
|
|
222
|
+
### Exports (server)
|
|
223
|
+
|
|
224
|
+
| Import | Purpose |
|
|
225
|
+
|---|---|
|
|
226
|
+
| `@hugex/ai` | `handleAgentsRoutes`, `handleAuthRoutes`, `handleCommonRoutes`, `handleIntancesRoutes`, `AgentDO` |
|
|
227
|
+
|
|
228
|
+
### Worker setup
|
|
229
|
+
|
|
230
|
+
Chain the route handlers and re-export the Durable Object:
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
// workers/app.ts
|
|
234
|
+
import {
|
|
235
|
+
handleAgentsRoutes,
|
|
236
|
+
handleAuthRoutes,
|
|
237
|
+
handleCommonRoutes,
|
|
238
|
+
handleIntancesRoutes,
|
|
239
|
+
} from '@hugex/ai';
|
|
240
|
+
|
|
241
|
+
export default {
|
|
242
|
+
async fetch(request, env, ctx) {
|
|
243
|
+
const common = await handleCommonRoutes(request, env, ctx);
|
|
244
|
+
if (common instanceof Response) return common;
|
|
245
|
+
|
|
246
|
+
const auth = await handleAuthRoutes(request, env, ctx);
|
|
247
|
+
if (auth instanceof Response) return auth;
|
|
248
|
+
|
|
249
|
+
const agent = await handleAgentsRoutes(request, env, ctx);
|
|
250
|
+
if (agent instanceof Response) return agent;
|
|
251
|
+
|
|
252
|
+
const instances = await handleIntancesRoutes(request, env, ctx);
|
|
253
|
+
if (instances instanceof Response) return instances;
|
|
254
|
+
|
|
255
|
+
return yourAppHandler(request, { cloudflare: { env, ctx }, state: { ...auth } });
|
|
256
|
+
},
|
|
257
|
+
} satisfies ExportedHandler<Env>;
|
|
258
|
+
|
|
259
|
+
export { AgentDO } from '@hugex/ai';
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`wrangler.jsonc` must bind the Durable Object:
|
|
263
|
+
|
|
264
|
+
```jsonc
|
|
265
|
+
{
|
|
266
|
+
"durable_objects": {
|
|
267
|
+
"bindings": [{ "class_name": "AgentDO", "name": "AGENT" }]
|
|
268
|
+
},
|
|
269
|
+
"migrations": [{ "tag": "v2", "new_sqlite_classes": ["AgentDO"] }]
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Required env vars (typical): `HX_CORE_URL`, `HX_ORA_URL`, `HX_API_KEY`, tenant Vectorize binding `VDB_<tenant>_1024`, `AI` (Workers AI).
|
|
274
|
+
|
|
275
|
+
Session memory, secrets (`{{ secrets.NAME }}`), Vectorize memo, and tool execution run inside `AgentDO`; shared data is fetched from HX Core / hx-ora APIs.
|
|
245
276
|
|
|
246
277
|
## Bundler
|
|
247
278
|
|
|
@@ -253,6 +284,21 @@ optimizeDeps: {
|
|
|
253
284
|
},
|
|
254
285
|
```
|
|
255
286
|
|
|
287
|
+
## Architecture (high level)
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
Agent Design ──save──► HX Core (flow state + KV metadata)
|
|
291
|
+
▲
|
|
292
|
+
Agent backend (optional) ──fetch──┘
|
|
293
|
+
WebSocket routes → session runtime (per flowId::sessionId)
|
|
294
|
+
FlowEngine runs Start → … → Answer
|
|
295
|
+
|
|
296
|
+
React app (useAgent) ◄──WebSocket TYPE::CONTENT──► Agent backend
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
- **Frontend:** any React host — imports `@hugex/ai/client`, connects via WebSocket.
|
|
300
|
+
- **Backend:** Cloudflare Worker with `@hugex/ai` server exports — only when you host the runtime.
|
|
301
|
+
|
|
256
302
|
## Release (maintainers)
|
|
257
303
|
|
|
258
304
|
From the `ora/` source repo:
|
|
@@ -263,20 +309,6 @@ task publish:ai -- --dry-run # build + npm pack only
|
|
|
263
309
|
task build:ai # build to ../ai without publish
|
|
264
310
|
```
|
|
265
311
|
|
|
266
|
-
## Architecture (high level)
|
|
267
|
-
|
|
268
|
-
```
|
|
269
|
-
hx-ai Agent Design ──save──► HX Core (flow state + KV metadata)
|
|
270
|
-
▲
|
|
271
|
-
Tenant Worker (@hugex/ai) ──fetch──┘
|
|
272
|
-
├ handleAgentsRoutes → WebSocket → AgentDO (per flowId::sessionId)
|
|
273
|
-
└ FlowEngine runs Start → … → Answer
|
|
274
|
-
|
|
275
|
-
Client (useAgent) ◄──WebSocket TYPE::CONTENT──► AgentDO
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
Session memory, secrets (`{{ secrets.NAME }}`), Vectorize memo, and tool execution run inside the DO; shared data is fetched from HX Core / hx-ora APIs.
|
|
279
|
-
|
|
280
312
|
## License
|
|
281
313
|
|
|
282
314
|
Included with your HugeX deployment — install and use this package as documented in this README. Full terms are in the `LICENSE` file included in this npm package (also listed under **License** on this page).
|