@hugex/ai 2.8.7 → 2.8.9
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 +18 -0
- package/README.md +287 -0
- package/package.json +5 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
HugeX Proprietary Software License
|
|
2
|
+
|
|
3
|
+
Copyright (c) HugeX. All rights reserved.
|
|
4
|
+
|
|
5
|
+
Permission is granted to HugeX customers and authorized partners to install,
|
|
6
|
+
use, and integrate @hugex packages (@hugex/ai, @hugex/ui, @hugex/shared, and
|
|
7
|
+
related scoped packages) solely in connection with a HugeX or Ora deployment
|
|
8
|
+
you are licensed to operate.
|
|
9
|
+
|
|
10
|
+
You may not copy, modify, merge, publish, distribute, sublicense, or sell
|
|
11
|
+
copies of this software except as expressly permitted by HugeX in writing.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
16
|
+
HUGEX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
17
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
18
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# @hugex/ai
|
|
2
|
+
|
|
3
|
+
Ora agent runtime for Cloudflare Workers — flow execution (`FlowEngine`), session state (`AgentDO`), server route handlers, and the React client hook (`useAgent`).
|
|
4
|
+
|
|
5
|
+
Flows are **designed** in [hx-ai](https://hugex.co/) (`AgentDesign.tsx`, React Flow canvas) and **saved** to HX Core. Tenant apps install this package, wire the worker routes, and connect the UI with `useAgent`.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @hugex/ai
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Peer/runtime deps (React 19, `react-router` 7, `zod`, `zustand`, `ai`, etc.) are declared in the package — align versions with your tenant app.
|
|
14
|
+
|
|
15
|
+
## Exports
|
|
16
|
+
|
|
17
|
+
| Import | Purpose |
|
|
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 |
|
|
22
|
+
|
|
23
|
+
## Worker setup (required)
|
|
24
|
+
|
|
25
|
+
Each tenant Worker chains the route handlers and re-exports the Durable Object:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
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
|
+
);
|
|
41
|
+
|
|
42
|
+
export default {
|
|
43
|
+
async fetch(request, env, ctx) {
|
|
44
|
+
const common = await handleCommonRoutes(request, env, ctx);
|
|
45
|
+
if (common instanceof Response) return common;
|
|
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
|
+
```
|
|
62
|
+
|
|
63
|
+
`wrangler.jsonc` must bind the Durable Object:
|
|
64
|
+
|
|
65
|
+
```jsonc
|
|
66
|
+
{
|
|
67
|
+
"durable_objects": {
|
|
68
|
+
"bindings": [{ "class_name": "AgentDO", "name": "AGENT" }]
|
|
69
|
+
},
|
|
70
|
+
"migrations": [{ "tag": "v2", "new_sqlite_classes": ["AgentDO"] }]
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Required env vars (typical): `HX_CORE_URL`, `HX_ORA_URL`, `HX_API_KEY`, tenant Vectorize binding `VDB_<tenant>_1024`, `AI` (Workers AI).
|
|
75
|
+
|
|
76
|
+
## Flow IDs and agent configuration
|
|
77
|
+
|
|
78
|
+
A **flow** is the graph you edit in hx-ai **Agent Design** (`/ai/agents/:id`). The URL param `id` is the **flowId** (e.g. `1rShqGMrANRGmXTN1mjTJB`).
|
|
79
|
+
|
|
80
|
+
At runtime:
|
|
81
|
+
|
|
82
|
+
| Concept | Value | Notes |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| **flowId** | Agent Design `:id` | Identifies which flow graph to run; also used as the Cloudflare `agent` name |
|
|
85
|
+
| **sessionId** | UUID (or stable string) | One chat session; maps to one `AgentDO` instance |
|
|
86
|
+
| **DO name** | `` `${flowId}::${sessionId}` `` | Server-side session key |
|
|
87
|
+
|
|
88
|
+
Flow metadata (tenant, visibility, status) lives in HX Core KV. The DO loads flow **state** (nodes/edges) from `GET {HX_CORE_URL}/ora/flow/{flowId}/state` on WebSocket connect.
|
|
89
|
+
|
|
90
|
+
### Node types (flow graph)
|
|
91
|
+
|
|
92
|
+
Design-time node data (configured in Agent Design panels):
|
|
93
|
+
|
|
94
|
+
| Node | Key data |
|
|
95
|
+
|---|---|
|
|
96
|
+
| **Start** | `greeting`, `allow_images`, `allow_documents`, `memory_*` toggles |
|
|
97
|
+
| **LLM** | `template`, `model`, `tools`, `varMapping`, `outVars` |
|
|
98
|
+
| **Memo** | `rag_id`, `query_key`, `topk` |
|
|
99
|
+
| **Classifier** | `input_variable`, `items[]` |
|
|
100
|
+
| **API** | `url`, `method`, `headers`, `body`, `varMapping` |
|
|
101
|
+
| **Answer** | Required flow terminus |
|
|
102
|
+
|
|
103
|
+
Rules: exactly one Start, at least one Answer, all paths connected.
|
|
104
|
+
|
|
105
|
+
## `useAgent` — client hook
|
|
106
|
+
|
|
107
|
+
`useAgent` opens a WebSocket to the session DO, decodes the `TYPE::CONTENT` wire protocol, and writes conversation state into a Zustand store. UI components subscribe to the store and call `send`, `clearHistory`, etc.
|
|
108
|
+
|
|
109
|
+
### Options
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
useAgent({
|
|
113
|
+
host?: string; // WS host; omit when same origin as the page
|
|
114
|
+
basePath?: string; // path segment under host (see below)
|
|
115
|
+
agent?: string; // flowId
|
|
116
|
+
name?: string; // sessionId
|
|
117
|
+
query?: Record<string, string | null> | (() => Promise<Record<string, string | null>>);
|
|
118
|
+
user?: string; // anonymous session label; sent as UID on connect
|
|
119
|
+
storeKey?: string; // isolate store when multiple agents on one screen
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Returns `{ connection, store, send, clearHistory, sendAuth, setIdentity, approve, reject, ... }`.
|
|
124
|
+
|
|
125
|
+
### WebSocket paths
|
|
126
|
+
|
|
127
|
+
Two server routes exist in `@hugex/ai`:
|
|
128
|
+
|
|
129
|
+
| Route | Auth | Typical use |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| `/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) | hx-ai design assistant |
|
|
133
|
+
|
|
134
|
+
### Pattern 1 — tenant chat (single agent)
|
|
135
|
+
|
|
136
|
+
Same-origin tenant app; no `host` needed. Uses the global store (`useAgentStore`).
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
import { useAgent, useAgentStore } from '@hugex/ai/client';
|
|
140
|
+
|
|
141
|
+
function Chat({ flowId, sessionId }: { flowId: string; sessionId: string }) {
|
|
142
|
+
const { messages, typingMessage } = useAgentStore();
|
|
143
|
+
|
|
144
|
+
const { send, clearHistory } = useAgent({
|
|
145
|
+
basePath: `api/agent/flow/${flowId}/${sessionId}`,
|
|
146
|
+
agent: flowId,
|
|
147
|
+
name: sessionId,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// render messages, call send(text) on submit
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Reference: `ora-base/app/secure/chat/components/ChatView.tsx`.
|
|
155
|
+
|
|
156
|
+
### Pattern 2 — Run panel (design-time test)
|
|
157
|
+
|
|
158
|
+
Flow under design in Agent Design; `flowId` from route params; session from run store; JWT via `query`:
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
const { id: flowId } = useParams<{ id: string }>();
|
|
162
|
+
const sessionId = '…'; // from run session store
|
|
163
|
+
const socketUrl = tenant.data.ora.socketServer; // e.g. tenant worker host
|
|
164
|
+
|
|
165
|
+
const { send, sendAuth, clearHistory } = useAgent({
|
|
166
|
+
host: socketUrl,
|
|
167
|
+
basePath: `api/agent/flow/${flowId}/${sessionId}`,
|
|
168
|
+
agent: flowId,
|
|
169
|
+
name: sessionId,
|
|
170
|
+
query: async () => ({ access_token: await readAccessToken() }),
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const messages = useAgentStore((s) => s.messages);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Reference: `hx-ai/.../RunStatusPanel.tsx` (opened from `AgentDesign.tsx`).
|
|
177
|
+
|
|
178
|
+
Start-node flags (`allow_images`, `allow_documents`, `memory_enabled`) are read from the canvas nodes to drive the Run UI.
|
|
179
|
+
|
|
180
|
+
### Pattern 3 — multiple agents on one screen (`storeKey`)
|
|
181
|
+
|
|
182
|
+
When two agents mount together (e.g. **Run panel** + **design assistant** in Agent Design), pass a stable `storeKey` so their chat state does not collide:
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
const { send, sendAuth, store } = useAgent({
|
|
186
|
+
host: ORA_SOCKET_HOST,
|
|
187
|
+
basePath: `api/ora/connect/${ORA_FLOW_ID}/${sessionId}`,
|
|
188
|
+
agent: ORA_FLOW_ID,
|
|
189
|
+
name: sessionId,
|
|
190
|
+
query: { authorization: ORA_AUTH_KEY },
|
|
191
|
+
user: email ?? undefined,
|
|
192
|
+
storeKey: 'agent-design', // stable for this component's lifetime
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const messages = store((s) => s.messages);
|
|
196
|
+
const status = store((s) => s.status);
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Reference: `hx-ai/.../AgentPanel.tsx`. Child components that need the same isolated state must use the **same** `storeKey` via `getAgentStore('agent-design')`.
|
|
200
|
+
|
|
201
|
+
**Rule:** `storeKey` must be constant for the component lifetime (do not derive from per-render state).
|
|
202
|
+
|
|
203
|
+
## Runtime credentials (`sendAuth`)
|
|
204
|
+
|
|
205
|
+
Tools may reference `{{ auth.NAME }}` placeholders. Push credentials with `sendAuth(name, value)` — they never appear in chat history.
|
|
206
|
+
|
|
207
|
+
**Important:** re-push credentials **before every `send`**, not once on connect. Durable Object hibernation clears in-memory auth mid-connection without disconnecting the WebSocket.
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
const sendTurn = async (text: string) => {
|
|
211
|
+
const token = await readAccessToken();
|
|
212
|
+
if (token) sendAuth('ACCESS_TOKEN', token);
|
|
213
|
+
send(text);
|
|
214
|
+
};
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`clearHistory()` wipes server auth too — re-push after clearing.
|
|
218
|
+
|
|
219
|
+
## Store fields (reactive UI)
|
|
220
|
+
|
|
221
|
+
Subscribe via `useAgentStore` (global) or `store` (isolated):
|
|
222
|
+
|
|
223
|
+
| Field | Use |
|
|
224
|
+
|---|---|
|
|
225
|
+
| `messages` | Chat history (replayed from DO on connect via `HIS::`) |
|
|
226
|
+
| `typingMessage` | Streaming assistant text (`TS` / `TSC`) |
|
|
227
|
+
| `reasoningMessage` | Streaming reasoning (`RS` / `RSC`) |
|
|
228
|
+
| `status` | `'connecting' \| 'connected' \| 'disconnected'` — gate input on `'connected'` |
|
|
229
|
+
| `flowConfig` | Start-node config from server (`CFG::`: greeting, attachments) |
|
|
230
|
+
| `events` | Tool/info events from `SE::` stream |
|
|
231
|
+
| `composioAuth` | OAuth redirect when Composio manual auth is required |
|
|
232
|
+
| `approvals` | Human-in-the-loop tool approvals |
|
|
233
|
+
|
|
234
|
+
## Wire protocol (summary)
|
|
235
|
+
|
|
236
|
+
Inbound frames use `TYPE::CONTENT`:
|
|
237
|
+
|
|
238
|
+
| Code | Meaning |
|
|
239
|
+
|---|---|
|
|
240
|
+
| `HIS` | Full history replay |
|
|
241
|
+
| `SE` | Server event (tools, memory, Composio, …) |
|
|
242
|
+
| `TS` / `TSC` | Assistant text stream / complete |
|
|
243
|
+
| `RS` / `RSC` | Reasoning stream / complete |
|
|
244
|
+
| `CFG` | Flow config (attachments, greeting) |
|
|
245
|
+
| `ERR` | Error string |
|
|
246
|
+
|
|
247
|
+
Outbound: `M:` user message, `CH:` clear history, `AUT:` runtime credential, `UID:` session identity.
|
|
248
|
+
|
|
249
|
+
Full reference: Ora `WEBSOCKET_EVENTS.md` (in the `ora/` source repo).
|
|
250
|
+
|
|
251
|
+
## Vite
|
|
252
|
+
|
|
253
|
+
Exclude `@hugex/ai` from `optimizeDeps` in tenant apps:
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
optimizeDeps: {
|
|
257
|
+
exclude: ['@hugex/ai'],
|
|
258
|
+
},
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Release (maintainers)
|
|
262
|
+
|
|
263
|
+
From the `ora/` source repo:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
task publish:ai # bump patch, build, publish
|
|
267
|
+
task publish:ai -- --dry-run # build + npm pack only
|
|
268
|
+
task build:ai # build to ../ai without publish
|
|
269
|
+
```
|
|
270
|
+
|
|
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
|
+
## License
|
|
286
|
+
|
|
287
|
+
Included with your HugeX deployment — install and use this package as documented in this README. See [LICENSE](LICENSE) for terms.
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hugex/ai",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.9",
|
|
4
4
|
"description": "Ora AI Agent Framework",
|
|
5
5
|
"author": "a@hugex.co",
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"scripts": {},
|
|
9
9
|
"dependencies": {
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"files": [
|
|
48
|
-
"dist"
|
|
48
|
+
"dist",
|
|
49
|
+
"README.md",
|
|
50
|
+
"LICENSE"
|
|
49
51
|
],
|
|
50
52
|
"main": "./dist/index.js",
|
|
51
53
|
"module": "./dist/index.js",
|