@hugex/ai 2.8.11 → 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/LICENSE +1 -1
- package/README.md +137 -110
- package/package.json +2 -2
package/LICENSE
CHANGED
|
@@ -4,7 +4,7 @@ Copyright (c) HugeX. All rights reserved.
|
|
|
4
4
|
|
|
5
5
|
Permission is granted to HugeX customers and authorized partners to install,
|
|
6
6
|
use, and integrate @hugex packages (@hugex/ai, @hugex/ui, @hugex/shared, and
|
|
7
|
-
related scoped packages) solely in connection with a HugeX
|
|
7
|
+
related scoped packages) solely in connection with a HugeX or Ora deployment
|
|
8
8
|
you are licensed to operate.
|
|
9
9
|
|
|
10
10
|
You may not copy, modify, merge, publish, distribute, sublicense, or sell
|
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 [
|
|
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,82 +20,43 @@ Flows are **designed** in [hx-ai](https://hugex.co/) (`AgentDesign.tsx`, React F
|
|
|
10
20
|
pnpm add @hugex/ai
|
|
11
21
|
```
|
|
12
22
|
|
|
13
|
-
Peer
|
|
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
|
-
import { createRequestHandler } from 'react-router';
|
|
36
|
-
|
|
37
|
-
const requestHandler = createRequestHandler(
|
|
38
|
-
() => import('virtual:react-router/server-build'),
|
|
39
|
-
import.meta.env.MODE,
|
|
40
|
-
);
|
|
35
|
+
No Worker code, wrangler config, or server imports required in your frontend repo.
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const auth = await handleAuthRoutes(request, env, ctx);
|
|
48
|
-
if (auth instanceof Response) return auth;
|
|
49
|
-
|
|
50
|
-
const agent = await handleAgentsRoutes(request, env, ctx);
|
|
51
|
-
if (agent instanceof Response) return agent;
|
|
52
|
-
|
|
53
|
-
const instances = await handleIntancesRoutes(request, env, ctx);
|
|
54
|
-
if (instances instanceof Response) return instances;
|
|
55
|
-
|
|
56
|
-
return requestHandler(request, { cloudflare: { env, ctx }, state: { ...auth } });
|
|
57
|
-
},
|
|
58
|
-
} satisfies ExportedHandler<Env>;
|
|
59
|
-
|
|
60
|
-
export { AgentDO } from '@hugex/ai';
|
|
61
|
-
```
|
|
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 |
|
|
62
42
|
|
|
63
|
-
|
|
43
|
+
### Self-hosted runtime (tenant Worker)
|
|
64
44
|
|
|
65
|
-
|
|
66
|
-
{
|
|
67
|
-
"durable_objects": {
|
|
68
|
-
"bindings": [{ "class_name": "AgentDO", "name": "AGENT" }]
|
|
69
|
-
},
|
|
70
|
-
"migrations": [{ "tag": "v2", "new_sqlite_classes": ["AgentDO"] }]
|
|
71
|
-
}
|
|
72
|
-
```
|
|
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).
|
|
73
46
|
|
|
74
|
-
|
|
47
|
+
HugeX-managed tenant deployments already include this — frontend teams typically skip this section.
|
|
75
48
|
|
|
76
49
|
## Flow IDs and agent configuration
|
|
77
50
|
|
|
78
|
-
A **flow** is the graph you edit in
|
|
79
|
-
|
|
80
|
-
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`).
|
|
81
52
|
|
|
82
53
|
| Concept | Value | Notes |
|
|
83
54
|
|---|---|---|
|
|
84
|
-
| **flowId** | Agent Design `:id` | Identifies which flow graph to run
|
|
85
|
-
| **sessionId** | UUID (or stable string) | One chat session; maps to
|
|
86
|
-
| **
|
|
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) |
|
|
87
58
|
|
|
88
|
-
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.
|
|
89
60
|
|
|
90
61
|
### Node types (flow graph)
|
|
91
62
|
|
|
@@ -102,9 +73,9 @@ Design-time node data (configured in Agent Design panels):
|
|
|
102
73
|
|
|
103
74
|
Rules: exactly one Start, at least one Answer, all paths connected.
|
|
104
75
|
|
|
105
|
-
## `useAgent` — client
|
|
76
|
+
## `useAgent` — client integration
|
|
106
77
|
|
|
107
|
-
`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.
|
|
108
79
|
|
|
109
80
|
### Options
|
|
110
81
|
|
|
@@ -124,16 +95,16 @@ Returns `{ connection, store, send, clearHistory, sendAuth, setIdentity, approve
|
|
|
124
95
|
|
|
125
96
|
### WebSocket paths
|
|
126
97
|
|
|
127
|
-
|
|
98
|
+
These routes are served by the **agent backend** (typically a deployed tenant Worker). Your frontend connects to them; it does not implement them.
|
|
128
99
|
|
|
129
100
|
| Route | Auth | Typical use |
|
|
130
101
|
|---|---|---|
|
|
131
102
|
| `/api/agent/flow/{flowId}/{sessionId}` | JWT / `access_token` query | Tenant chat UIs, Run panel |
|
|
132
|
-
| `/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 |
|
|
133
104
|
|
|
134
|
-
### Pattern 1 —
|
|
105
|
+
### Pattern 1 — same-origin chat
|
|
135
106
|
|
|
136
|
-
|
|
107
|
+
Frontend and agent server share a domain. No `host` needed. Uses the global store (`useAgentStore`).
|
|
137
108
|
|
|
138
109
|
```tsx
|
|
139
110
|
import { useAgent, useAgentStore } from '@hugex/ai/client';
|
|
@@ -151,19 +122,19 @@ function Chat({ flowId, sessionId }: { flowId: string; sessionId: string }) {
|
|
|
151
122
|
}
|
|
152
123
|
```
|
|
153
124
|
|
|
154
|
-
|
|
125
|
+
### Pattern 2 — cross-origin chat
|
|
155
126
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
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.
|
|
159
128
|
|
|
160
129
|
```tsx
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const
|
|
130
|
+
import { useAgent, useAgentStore } from '@hugex/ai/client';
|
|
131
|
+
|
|
132
|
+
const flowId = '…'; // from your route or config
|
|
133
|
+
const sessionId = '…'; // from session store
|
|
134
|
+
const socketHost = '…'; // deployed agent server host (no path)
|
|
164
135
|
|
|
165
136
|
const { send, sendAuth, clearHistory } = useAgent({
|
|
166
|
-
host:
|
|
137
|
+
host: socketHost,
|
|
167
138
|
basePath: `api/agent/flow/${flowId}/${sessionId}`,
|
|
168
139
|
agent: flowId,
|
|
169
140
|
name: sessionId,
|
|
@@ -173,38 +144,36 @@ const { send, sendAuth, clearHistory } = useAgent({
|
|
|
173
144
|
const messages = useAgentStore((s) => s.messages);
|
|
174
145
|
```
|
|
175
146
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
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.
|
|
179
148
|
|
|
180
149
|
### Pattern 3 — multiple agents on one screen (`storeKey`)
|
|
181
150
|
|
|
182
|
-
When two agents mount together
|
|
151
|
+
When two agents mount together, pass a stable `storeKey` so their chat state does not collide:
|
|
183
152
|
|
|
184
153
|
```tsx
|
|
185
154
|
const { send, sendAuth, store } = useAgent({
|
|
186
|
-
host:
|
|
187
|
-
basePath: `api/ora/connect/${
|
|
188
|
-
agent:
|
|
155
|
+
host: AGENT_SERVER_HOST,
|
|
156
|
+
basePath: `api/ora/connect/${FLOW_ID}/${sessionId}`,
|
|
157
|
+
agent: FLOW_ID,
|
|
189
158
|
name: sessionId,
|
|
190
|
-
query: { authorization:
|
|
159
|
+
query: { authorization: AGENT_API_KEY },
|
|
191
160
|
user: email ?? undefined,
|
|
192
|
-
storeKey: '
|
|
161
|
+
storeKey: 'my-panel', // stable for this component's lifetime
|
|
193
162
|
});
|
|
194
163
|
|
|
195
164
|
const messages = store((s) => s.messages);
|
|
196
165
|
const status = store((s) => s.status);
|
|
197
166
|
```
|
|
198
167
|
|
|
199
|
-
|
|
168
|
+
Child components that need the same isolated state must use the **same** `storeKey` via `getAgentStore('my-panel')`.
|
|
200
169
|
|
|
201
170
|
**Rule:** `storeKey` must be constant for the component lifetime (do not derive from per-render state).
|
|
202
171
|
|
|
203
|
-
|
|
172
|
+
### Runtime credentials (`sendAuth`)
|
|
204
173
|
|
|
205
174
|
Tools may reference `{{ auth.NAME }}` placeholders. Push credentials with `sendAuth(name, value)` — they never appear in chat history.
|
|
206
175
|
|
|
207
|
-
**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.
|
|
208
177
|
|
|
209
178
|
```ts
|
|
210
179
|
const sendTurn = async (text: string) => {
|
|
@@ -216,29 +185,29 @@ const sendTurn = async (text: string) => {
|
|
|
216
185
|
|
|
217
186
|
`clearHistory()` wipes server auth too — re-push after clearing.
|
|
218
187
|
|
|
219
|
-
|
|
188
|
+
### Store fields (reactive UI)
|
|
220
189
|
|
|
221
190
|
Subscribe via `useAgentStore` (global) or `store` (isolated):
|
|
222
191
|
|
|
223
192
|
| Field | Use |
|
|
224
193
|
|---|---|
|
|
225
|
-
| `messages` | Chat history (replayed
|
|
194
|
+
| `messages` | Chat history (replayed on connect via `HIS::`) |
|
|
226
195
|
| `typingMessage` | Streaming assistant text (`TS` / `TSC`) |
|
|
227
196
|
| `reasoningMessage` | Streaming reasoning (`RS` / `RSC`) |
|
|
228
197
|
| `status` | `'connecting' \| 'connected' \| 'disconnected'` — gate input on `'connected'` |
|
|
229
198
|
| `flowConfig` | Start-node config from server (`CFG::`: greeting, attachments) |
|
|
230
199
|
| `events` | Tool/info events from `SE::` stream |
|
|
231
|
-
| `composioAuth` | OAuth redirect when
|
|
200
|
+
| `composioAuth` | OAuth redirect when a connected tool requires manual authorization |
|
|
232
201
|
| `approvals` | Human-in-the-loop tool approvals |
|
|
233
202
|
|
|
234
|
-
|
|
203
|
+
### Wire protocol (summary)
|
|
235
204
|
|
|
236
205
|
Inbound frames use `TYPE::CONTENT`:
|
|
237
206
|
|
|
238
207
|
| Code | Meaning |
|
|
239
208
|
|---|---|
|
|
240
209
|
| `HIS` | Full history replay |
|
|
241
|
-
| `SE` | Server event (tools, memory,
|
|
210
|
+
| `SE` | Server event (tools, memory, external integrations, …) |
|
|
242
211
|
| `TS` / `TSC` | Assistant text stream / complete |
|
|
243
212
|
| `RS` / `RSC` | Reasoning stream / complete |
|
|
244
213
|
| `CFG` | Flow config (attachments, greeting) |
|
|
@@ -246,11 +215,68 @@ Inbound frames use `TYPE::CONTENT`:
|
|
|
246
215
|
|
|
247
216
|
Outbound: `M:` user message, `CH:` clear history, `AUT:` runtime credential, `UID:` session identity.
|
|
248
217
|
|
|
249
|
-
|
|
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.
|
|
250
221
|
|
|
251
|
-
|
|
222
|
+
### Exports (server)
|
|
252
223
|
|
|
253
|
-
|
|
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.
|
|
276
|
+
|
|
277
|
+
## Bundler
|
|
278
|
+
|
|
279
|
+
Exclude `@hugex/ai` from dependency pre-bundling in your dev server:
|
|
254
280
|
|
|
255
281
|
```ts
|
|
256
282
|
optimizeDeps: {
|
|
@@ -258,6 +284,21 @@ optimizeDeps: {
|
|
|
258
284
|
},
|
|
259
285
|
```
|
|
260
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
|
+
|
|
261
302
|
## Release (maintainers)
|
|
262
303
|
|
|
263
304
|
From the `ora/` source repo:
|
|
@@ -268,20 +309,6 @@ task publish:ai -- --dry-run # build + npm pack only
|
|
|
268
309
|
task build:ai # build to ../ai without publish
|
|
269
310
|
```
|
|
270
311
|
|
|
271
|
-
## Architecture (high level)
|
|
272
|
-
|
|
273
|
-
```
|
|
274
|
-
hx-ai Agent Design ──save──► HX Core (flow state + KV metadata)
|
|
275
|
-
▲
|
|
276
|
-
Tenant Worker (@hugex/ai) ──fetch──┘
|
|
277
|
-
├ handleAgentsRoutes → WebSocket → AgentDO (per flowId::sessionId)
|
|
278
|
-
└ FlowEngine runs Start → … → Answer
|
|
279
|
-
|
|
280
|
-
Client (useAgent) ◄──WebSocket TYPE::CONTENT──► AgentDO
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
Session memory, secrets (`{{ secrets.NAME }}`), Vectorize memo, and tool execution run inside the DO; shared data is fetched from HX Core / hx-ora APIs.
|
|
284
|
-
|
|
285
312
|
## License
|
|
286
313
|
|
|
287
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).
|
package/package.json
CHANGED