vanilla-agent-proxy 0.1.0
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 +106 -0
- package/dist/index.cjs +203 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +177 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
- package/src/index.ts +235 -0
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
## Vanilla Agent Proxy
|
|
2
|
+
|
|
3
|
+
Proxy server library for `vanilla-agent` widget. Handles flow configuration and forwards requests to Travrse or other AI backends.
|
|
4
|
+
|
|
5
|
+
### Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install vanilla-agent-proxy
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Usage
|
|
12
|
+
|
|
13
|
+
The proxy server handles flow configuration and forwards requests to Travrse. You can configure it in three ways:
|
|
14
|
+
|
|
15
|
+
**Option 1: Use default flow (recommended for getting started)**
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// api/chat.ts
|
|
19
|
+
import { createChatProxyApp } from 'vanilla-agent-proxy';
|
|
20
|
+
|
|
21
|
+
export default createChatProxyApp({
|
|
22
|
+
path: '/api/chat/dispatch',
|
|
23
|
+
allowedOrigins: ['https://www.example.com']
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Option 2: Reference a Travrse flow ID**
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { createChatProxyApp } from 'vanilla-agent-proxy';
|
|
31
|
+
|
|
32
|
+
export default createChatProxyApp({
|
|
33
|
+
path: '/api/chat/dispatch',
|
|
34
|
+
allowedOrigins: ['https://www.example.com'],
|
|
35
|
+
flowId: 'flow_abc123' // Flow created in Travrse dashboard or API
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Option 3: Define a custom flow**
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { createChatProxyApp } from 'vanilla-agent-proxy';
|
|
43
|
+
|
|
44
|
+
export default createChatProxyApp({
|
|
45
|
+
path: '/api/chat/dispatch',
|
|
46
|
+
allowedOrigins: ['https://www.example.com'],
|
|
47
|
+
flowConfig: {
|
|
48
|
+
name: "Custom Chat Flow",
|
|
49
|
+
description: "Specialized assistant flow",
|
|
50
|
+
steps: [
|
|
51
|
+
{
|
|
52
|
+
id: "custom_prompt",
|
|
53
|
+
name: "Custom Prompt",
|
|
54
|
+
type: "prompt",
|
|
55
|
+
enabled: true,
|
|
56
|
+
config: {
|
|
57
|
+
model: "meta/llama3.1-8b-instruct-free",
|
|
58
|
+
responseFormat: "markdown",
|
|
59
|
+
outputVariable: "prompt_result",
|
|
60
|
+
userPrompt: "{{user_message}}",
|
|
61
|
+
systemPrompt: "you are a helpful assistant, chatting with a user",
|
|
62
|
+
previousMessages: "{{messages}}"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Hosting on Vercel:**
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { createVercelHandler } from 'vanilla-agent-proxy';
|
|
74
|
+
|
|
75
|
+
export default createVercelHandler({
|
|
76
|
+
allowedOrigins: ['https://www.example.com'],
|
|
77
|
+
flowId: 'flow_abc123' // Optional
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Configuration Options
|
|
82
|
+
|
|
83
|
+
| Option | Type | Description |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| `upstreamUrl` | `string` | Travrse API endpoint (defaults to `https://api.travrse.ai/v1/dispatch`) |
|
|
86
|
+
| `apiKey` | `string` | Travrse API key (defaults to `TRAVRSE_API_KEY` environment variable) |
|
|
87
|
+
| `path` | `string` | Proxy endpoint path (defaults to `/api/chat/dispatch`) |
|
|
88
|
+
| `allowedOrigins` | `string[]` | CORS allowed origins |
|
|
89
|
+
| `flowId` | `string` | Travrse flow ID to use |
|
|
90
|
+
| `flowConfig` | `TravrseFlowConfig` | Custom flow configuration |
|
|
91
|
+
|
|
92
|
+
### Environment Setup
|
|
93
|
+
|
|
94
|
+
Add `TRAVRSE_API_KEY` to your environment. The proxy constructs the Travrse payload (including flow configuration) and streams the response back to the client.
|
|
95
|
+
|
|
96
|
+
### Building
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pnpm build
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This generates:
|
|
103
|
+
- `dist/index.js` (ESM)
|
|
104
|
+
- `dist/index.cjs` (CJS)
|
|
105
|
+
- Type definitions in `dist/index.d.ts`
|
|
106
|
+
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
createChatProxyApp: () => createChatProxyApp,
|
|
24
|
+
createVercelHandler: () => createVercelHandler,
|
|
25
|
+
default: () => index_default
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
var import_hono = require("hono");
|
|
29
|
+
var import_vercel = require("hono/vercel");
|
|
30
|
+
var DEFAULT_ENDPOINT = "https://api.travrse.ai/v1/dispatch";
|
|
31
|
+
var DEFAULT_PATH = "/api/chat/dispatch";
|
|
32
|
+
var DEFAULT_FLOW = {
|
|
33
|
+
name: "Streaming Prompt Flow",
|
|
34
|
+
description: "Streaming chat generated by the widget",
|
|
35
|
+
steps: [
|
|
36
|
+
{
|
|
37
|
+
id: "widget_prompt",
|
|
38
|
+
name: "Prompt",
|
|
39
|
+
type: "prompt",
|
|
40
|
+
enabled: true,
|
|
41
|
+
config: {
|
|
42
|
+
model: "meta/llama3.1-8b-instruct-free",
|
|
43
|
+
// model: "gpt-4o",
|
|
44
|
+
response_format: "markdown",
|
|
45
|
+
output_variable: "prompt_result",
|
|
46
|
+
user_prompt: "{{user_message}}",
|
|
47
|
+
system_prompt: "you are a helpful assistant, chatting with a user",
|
|
48
|
+
// tools: {
|
|
49
|
+
// tool_ids: [
|
|
50
|
+
// "builtin:dalle"
|
|
51
|
+
// ]
|
|
52
|
+
// },
|
|
53
|
+
previous_messages: "{{messages}}"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
};
|
|
58
|
+
var withCors = (allowedOrigins) => async (c, next) => {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
const origin = (_a = c.req.header("origin")) != null ? _a : "*";
|
|
61
|
+
const headers = {
|
|
62
|
+
"Access-Control-Allow-Origin": allowedOrigins && allowedOrigins.length ? allowedOrigins.includes(origin) ? origin : allowedOrigins[0] : origin,
|
|
63
|
+
"Access-Control-Allow-Headers": (_b = c.req.header("access-control-request-headers")) != null ? _b : "Content-Type, Authorization",
|
|
64
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
65
|
+
Vary: "Origin"
|
|
66
|
+
};
|
|
67
|
+
if (c.req.method === "OPTIONS") {
|
|
68
|
+
return new Response(null, { status: 204, headers });
|
|
69
|
+
}
|
|
70
|
+
await next();
|
|
71
|
+
Object.entries(headers).forEach(
|
|
72
|
+
([key, value]) => c.header(key, value, { append: false })
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
var createChatProxyApp = (options = {}) => {
|
|
76
|
+
var _a, _b;
|
|
77
|
+
const app = new import_hono.Hono();
|
|
78
|
+
const path = (_a = options.path) != null ? _a : DEFAULT_PATH;
|
|
79
|
+
const upstream = (_b = options.upstreamUrl) != null ? _b : DEFAULT_ENDPOINT;
|
|
80
|
+
app.use("*", withCors(options.allowedOrigins));
|
|
81
|
+
app.post(path, async (c) => {
|
|
82
|
+
var _a2, _b2, _c, _d, _e;
|
|
83
|
+
const apiKey = (_a2 = options.apiKey) != null ? _a2 : process.env.TRAVRSE_API_KEY;
|
|
84
|
+
if (!apiKey) {
|
|
85
|
+
return c.json(
|
|
86
|
+
{ error: "Missing API key. Set TRAVRSE_API_KEY." },
|
|
87
|
+
401
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
let clientPayload;
|
|
91
|
+
try {
|
|
92
|
+
clientPayload = await c.req.json();
|
|
93
|
+
} catch (error) {
|
|
94
|
+
return c.json(
|
|
95
|
+
{ error: "Invalid JSON body", details: error },
|
|
96
|
+
400
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
const messages = (_b2 = clientPayload.messages) != null ? _b2 : [];
|
|
100
|
+
const sortedMessages = [...messages].sort((a, b) => {
|
|
101
|
+
const timeA = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
102
|
+
const timeB = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
103
|
+
return timeA - timeB;
|
|
104
|
+
});
|
|
105
|
+
const formattedMessages = sortedMessages.map((message) => ({
|
|
106
|
+
role: message.role,
|
|
107
|
+
content: message.content
|
|
108
|
+
}));
|
|
109
|
+
const flowId = (_c = clientPayload.flowId) != null ? _c : options.flowId;
|
|
110
|
+
const flowConfig = (_d = options.flowConfig) != null ? _d : DEFAULT_FLOW;
|
|
111
|
+
const travrsePayload = {
|
|
112
|
+
record: {
|
|
113
|
+
name: "Streaming Chat Widget",
|
|
114
|
+
type: "standalone",
|
|
115
|
+
metadata: {}
|
|
116
|
+
},
|
|
117
|
+
messages: formattedMessages,
|
|
118
|
+
options: {
|
|
119
|
+
stream_response: true,
|
|
120
|
+
record_mode: "virtual",
|
|
121
|
+
flow_mode: flowId ? "existing" : "virtual",
|
|
122
|
+
auto_append_metadata: false
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
if (flowId) {
|
|
126
|
+
travrsePayload.flow = {
|
|
127
|
+
"name": "Chat with 8b",
|
|
128
|
+
"description": "Flow with 1 step",
|
|
129
|
+
"steps": [
|
|
130
|
+
{
|
|
131
|
+
"id": "step_01k8wnwpdcferbrq79tzj49aec",
|
|
132
|
+
"name": "Prompt 1",
|
|
133
|
+
"type": "prompt",
|
|
134
|
+
"order": 0,
|
|
135
|
+
"enabled": true,
|
|
136
|
+
"config": {
|
|
137
|
+
"text": "{{user_message}}",
|
|
138
|
+
"model": "qwen/qwen3-8b",
|
|
139
|
+
// "tools": {
|
|
140
|
+
// "tool_ids": [
|
|
141
|
+
// "tool_01k8ky2xpjfzybye5ywcmjr379",
|
|
142
|
+
// "builtin:firecrawl"
|
|
143
|
+
// ]
|
|
144
|
+
// },
|
|
145
|
+
"reasoning": false,
|
|
146
|
+
"user_prompt": "{{user_message}}",
|
|
147
|
+
"output_variable": "prompt_result",
|
|
148
|
+
"response_format": "JSON"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
};
|
|
153
|
+
} else {
|
|
154
|
+
travrsePayload.flow = flowConfig;
|
|
155
|
+
}
|
|
156
|
+
const isDevelopment = process.env.NODE_ENV === "development" || !process.env.NODE_ENV;
|
|
157
|
+
if (isDevelopment) {
|
|
158
|
+
console.log("\n=== Travrse Proxy Request ===");
|
|
159
|
+
console.log("URL:", upstream);
|
|
160
|
+
console.log("API Key Used:", apiKey ? "Yes" : "No");
|
|
161
|
+
console.log("API Key (first 12 chars):", apiKey ? apiKey.substring(0, 12) : "N/A");
|
|
162
|
+
console.log("Request Payload:", JSON.stringify(travrsePayload, null, 2));
|
|
163
|
+
}
|
|
164
|
+
const response = await fetch(upstream, {
|
|
165
|
+
method: "POST",
|
|
166
|
+
headers: {
|
|
167
|
+
Authorization: `Bearer ${apiKey}`,
|
|
168
|
+
"Content-Type": "application/json"
|
|
169
|
+
},
|
|
170
|
+
body: JSON.stringify(travrsePayload)
|
|
171
|
+
});
|
|
172
|
+
if (isDevelopment) {
|
|
173
|
+
console.log("Response Status:", response.status);
|
|
174
|
+
console.log("Response Status Text:", response.statusText);
|
|
175
|
+
if (!response.ok) {
|
|
176
|
+
const clonedResponse = response.clone();
|
|
177
|
+
try {
|
|
178
|
+
const errorBody = await clonedResponse.text();
|
|
179
|
+
console.log("Error Response Body:", errorBody);
|
|
180
|
+
} catch (e) {
|
|
181
|
+
console.log("Could not read error response body:", e);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
console.log("=== End Travrse Proxy Request ===\n");
|
|
185
|
+
}
|
|
186
|
+
return new Response(response.body, {
|
|
187
|
+
status: response.status,
|
|
188
|
+
headers: {
|
|
189
|
+
"Content-Type": (_e = response.headers.get("content-type")) != null ? _e : "application/json",
|
|
190
|
+
"Cache-Control": "no-store"
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
return app;
|
|
195
|
+
};
|
|
196
|
+
var createVercelHandler = (options) => (0, import_vercel.handle)(createChatProxyApp(options));
|
|
197
|
+
var index_default = createChatProxyApp;
|
|
198
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
199
|
+
0 && (module.exports = {
|
|
200
|
+
createChatProxyApp,
|
|
201
|
+
createVercelHandler
|
|
202
|
+
});
|
|
203
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Hono } from \"hono\";\nimport type { Context } from \"hono\";\nimport { handle } from \"hono/vercel\";\n\nexport type TravrseFlowStep = {\n id: string;\n name: string;\n type: string;\n enabled: boolean;\n config: Record<string, unknown>;\n};\n\nexport type TravrseFlowConfig = {\n name: string;\n description: string;\n steps: TravrseFlowStep[];\n};\n\nexport type ChatProxyOptions = {\n upstreamUrl?: string;\n apiKey?: string;\n path?: string;\n allowedOrigins?: string[];\n flowId?: string;\n flowConfig?: TravrseFlowConfig;\n};\n\nconst DEFAULT_ENDPOINT = \"https://api.travrse.ai/v1/dispatch\";\nconst DEFAULT_PATH = \"/api/chat/dispatch\";\n\nconst DEFAULT_FLOW: TravrseFlowConfig = {\n name: \"Streaming Prompt Flow\",\n description: \"Streaming chat generated by the widget\",\n steps: [\n {\n id: \"widget_prompt\",\n name: \"Prompt\",\n type: \"prompt\",\n enabled: true,\n config: {\n model: \"meta/llama3.1-8b-instruct-free\",\n // model: \"gpt-4o\",\n response_format: \"markdown\",\n output_variable: \"prompt_result\",\n user_prompt: \"{{user_message}}\",\n system_prompt: \"you are a helpful assistant, chatting with a user\",\n // tools: {\n // tool_ids: [\n // \"builtin:dalle\"\n // ]\n // },\n previous_messages: \"{{messages}}\"\n }\n }\n ]\n};\n\nconst withCors =\n (allowedOrigins: string[] | undefined) =>\n async (c: Context, next: () => Promise<void>) => {\n const origin = c.req.header(\"origin\") ?? \"*\";\n const headers: Record<string, string> = {\n \"Access-Control-Allow-Origin\":\n allowedOrigins && allowedOrigins.length\n ? allowedOrigins.includes(origin)\n ? origin\n : allowedOrigins[0]\n : origin,\n \"Access-Control-Allow-Headers\":\n c.req.header(\"access-control-request-headers\") ??\n \"Content-Type, Authorization\",\n \"Access-Control-Allow-Methods\": \"POST, OPTIONS\",\n Vary: \"Origin\"\n };\n\n if (c.req.method === \"OPTIONS\") {\n return new Response(null, { status: 204, headers });\n }\n\n await next();\n Object.entries(headers).forEach(([key, value]) =>\n c.header(key, value, { append: false })\n );\n };\n\nexport const createChatProxyApp = (options: ChatProxyOptions = {}) => {\n const app = new Hono();\n const path = options.path ?? DEFAULT_PATH;\n const upstream = options.upstreamUrl ?? DEFAULT_ENDPOINT;\n\n app.use(\"*\", withCors(options.allowedOrigins));\n\n app.post(path, async (c) => {\n const apiKey = options.apiKey ?? process.env.TRAVRSE_API_KEY;\n if (!apiKey) {\n return c.json(\n { error: \"Missing API key. Set TRAVRSE_API_KEY.\" },\n 401\n );\n }\n\n let clientPayload: {\n messages?: Array<{ role: string; content: string; createdAt?: string }>;\n flowId?: string;\n };\n try {\n clientPayload = await c.req.json();\n } catch (error) {\n return c.json(\n { error: \"Invalid JSON body\", details: error },\n 400\n );\n }\n\n // Build the Travrse payload\n const messages = clientPayload.messages ?? [];\n // Sort messages by timestamp to ensure correct order\n const sortedMessages = [...messages].sort((a, b) => {\n const timeA = a.createdAt ? new Date(a.createdAt).getTime() : 0;\n const timeB = b.createdAt ? new Date(b.createdAt).getTime() : 0;\n return timeA - timeB;\n });\n const formattedMessages = sortedMessages.map((message) => ({\n role: message.role,\n content: message.content\n }));\n\n // Determine which flow to use\n const flowId = clientPayload.flowId ?? options.flowId;\n const flowConfig = options.flowConfig ?? DEFAULT_FLOW;\n\n const travrsePayload: Record<string, unknown> = {\n record: {\n name: \"Streaming Chat Widget\",\n type: \"standalone\",\n metadata: {}\n },\n messages: formattedMessages,\n options: {\n stream_response: true,\n record_mode: \"virtual\",\n flow_mode: flowId ? \"existing\" : \"virtual\",\n auto_append_metadata: false\n }\n };\n\n // Use flow ID if provided, otherwise use flow config\n if (flowId) {\n travrsePayload.flow = {\n \"name\": \"Chat with 8b\",\n \"description\": \"Flow with 1 step\",\n \"steps\": [\n {\n \"id\": \"step_01k8wnwpdcferbrq79tzj49aec\",\n \"name\": \"Prompt 1\",\n \"type\": \"prompt\",\n \"order\": 0,\n \"enabled\": true,\n \"config\": {\n \"text\": \"{{user_message}}\",\n \"model\": \"qwen/qwen3-8b\",\n // \"tools\": {\n // \"tool_ids\": [\n // \"tool_01k8ky2xpjfzybye5ywcmjr379\",\n // \"builtin:firecrawl\"\n // ]\n // },\n \"reasoning\": false,\n \"user_prompt\": \"{{user_message}}\",\n \"output_variable\": \"prompt_result\",\n \"response_format\": \"JSON\"\n }\n }\n ]\n }\n } else {\n travrsePayload.flow = flowConfig;\n }\n\n // Development logging\n const isDevelopment = process.env.NODE_ENV === \"development\" || !process.env.NODE_ENV;\n\n if (isDevelopment) {\n console.log(\"\\n=== Travrse Proxy Request ===\");\n console.log(\"URL:\", upstream);\n console.log(\"API Key Used:\", apiKey ? \"Yes\" : \"No\");\n console.log(\"API Key (first 12 chars):\", apiKey ? apiKey.substring(0, 12) : \"N/A\");\n console.log(\"Request Payload:\", JSON.stringify(travrsePayload, null, 2));\n }\n\n const response = await fetch(upstream, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(travrsePayload)\n });\n\n if (isDevelopment) {\n console.log(\"Response Status:\", response.status);\n console.log(\"Response Status Text:\", response.statusText);\n\n // If there's an error, try to read and log the response body\n if (!response.ok) {\n const clonedResponse = response.clone();\n try {\n const errorBody = await clonedResponse.text();\n console.log(\"Error Response Body:\", errorBody);\n } catch (e) {\n console.log(\"Could not read error response body:\", e);\n }\n }\n console.log(\"=== End Travrse Proxy Request ===\\n\");\n }\n\n return new Response(response.body, {\n status: response.status,\n headers: {\n \"Content-Type\":\n response.headers.get(\"content-type\") ?? \"application/json\",\n \"Cache-Control\": \"no-store\"\n }\n });\n });\n\n return app;\n};\n\nexport const createVercelHandler = (options?: ChatProxyOptions) =>\n handle(createChatProxyApp(options));\n\n\nexport default createChatProxyApp;\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAqB;AAErB,oBAAuB;AAyBvB,IAAM,mBAAmB;AACzB,IAAM,eAAe;AAErB,IAAM,eAAkC;AAAA,EACtC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,OAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,QACN,OAAO;AAAA;AAAA,QAEP,iBAAiB;AAAA,QACjB,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMf,mBAAmB;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,WACJ,CAAC,mBACC,OAAO,GAAY,SAA8B;AA3DrD;AA4DM,QAAM,UAAS,OAAE,IAAI,OAAO,QAAQ,MAArB,YAA0B;AACzC,QAAM,UAAkC;AAAA,IACtC,+BACE,kBAAkB,eAAe,SAC7B,eAAe,SAAS,MAAM,IAC5B,SACA,eAAe,CAAC,IAClB;AAAA,IACN,iCACE,OAAE,IAAI,OAAO,gCAAgC,MAA7C,YACA;AAAA,IACF,gCAAgC;AAAA,IAChC,MAAM;AAAA,EACR;AAEA,MAAI,EAAE,IAAI,WAAW,WAAW;AAC9B,WAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,QAAQ,CAAC;AAAA,EACpD;AAEA,QAAM,KAAK;AACX,SAAO,QAAQ,OAAO,EAAE;AAAA,IAAQ,CAAC,CAAC,KAAK,KAAK,MAC1C,EAAE,OAAO,KAAK,OAAO,EAAE,QAAQ,MAAM,CAAC;AAAA,EACxC;AACF;AAEG,IAAM,qBAAqB,CAAC,UAA4B,CAAC,MAAM;AArFtE;AAsFE,QAAM,MAAM,IAAI,iBAAK;AACrB,QAAM,QAAO,aAAQ,SAAR,YAAgB;AAC7B,QAAM,YAAW,aAAQ,gBAAR,YAAuB;AAExC,MAAI,IAAI,KAAK,SAAS,QAAQ,cAAc,CAAC;AAE7C,MAAI,KAAK,MAAM,OAAO,MAAM;AA5F9B,QAAAA,KAAAC,KAAA;AA6FI,UAAM,UAASD,MAAA,QAAQ,WAAR,OAAAA,MAAkB,QAAQ,IAAI;AAC7C,QAAI,CAAC,QAAQ;AACX,aAAO,EAAE;AAAA,QACP,EAAE,OAAO,wCAAwC;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AAIJ,QAAI;AACF,sBAAgB,MAAM,EAAE,IAAI,KAAK;AAAA,IACnC,SAAS,OAAO;AACd,aAAO,EAAE;AAAA,QACP,EAAE,OAAO,qBAAqB,SAAS,MAAM;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAGA,UAAM,YAAWC,MAAA,cAAc,aAAd,OAAAA,MAA0B,CAAC;AAE5C,UAAM,iBAAiB,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM;AAClD,YAAM,QAAQ,EAAE,YAAY,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI;AAC9D,YAAM,QAAQ,EAAE,YAAY,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI;AAC9D,aAAO,QAAQ;AAAA,IACjB,CAAC;AACD,UAAM,oBAAoB,eAAe,IAAI,CAAC,aAAa;AAAA,MACzD,MAAM,QAAQ;AAAA,MACd,SAAS,QAAQ;AAAA,IACnB,EAAE;AAGF,UAAM,UAAS,mBAAc,WAAd,YAAwB,QAAQ;AAC/C,UAAM,cAAa,aAAQ,eAAR,YAAsB;AAEzC,UAAM,iBAA0C;AAAA,MAC9C,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU,CAAC;AAAA,MACb;AAAA,MACA,UAAU;AAAA,MACV,SAAS;AAAA,QACP,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,WAAW,SAAS,aAAa;AAAA,QACjC,sBAAsB;AAAA,MACxB;AAAA,IACF;AAGA,QAAI,QAAQ;AACV,qBAAe,OAAO;AAAA,QACpB,QAAQ;AAAA,QACR,eAAe;AAAA,QACf,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,WAAW;AAAA,YACX,UAAU;AAAA,cACR,QAAQ;AAAA,cACR,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAOT,aAAa;AAAA,cACb,eAAe;AAAA,cACf,mBAAmB;AAAA,cACnB,mBAAmB;AAAA,YACrB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,qBAAe,OAAO;AAAA,IACxB;AAGA,UAAM,gBAAgB,QAAQ,IAAI,aAAa,iBAAiB,CAAC,QAAQ,IAAI;AAE7E,QAAI,eAAe;AACjB,cAAQ,IAAI,iCAAiC;AAC7C,cAAQ,IAAI,QAAQ,QAAQ;AAC5B,cAAQ,IAAI,iBAAiB,SAAS,QAAQ,IAAI;AAClD,cAAQ,IAAI,6BAA6B,SAAS,OAAO,UAAU,GAAG,EAAE,IAAI,KAAK;AACjF,cAAQ,IAAI,oBAAoB,KAAK,UAAU,gBAAgB,MAAM,CAAC,CAAC;AAAA,IACzE;AAEA,UAAM,WAAW,MAAM,MAAM,UAAU;AAAA,MACrC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU,MAAM;AAAA,QAC/B,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,cAAc;AAAA,IACrC,CAAC;AAED,QAAI,eAAe;AACjB,cAAQ,IAAI,oBAAoB,SAAS,MAAM;AAC/C,cAAQ,IAAI,yBAAyB,SAAS,UAAU;AAGxD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,iBAAiB,SAAS,MAAM;AACtC,YAAI;AACF,gBAAM,YAAY,MAAM,eAAe,KAAK;AAC5C,kBAAQ,IAAI,wBAAwB,SAAS;AAAA,QAC/C,SAAS,GAAG;AACV,kBAAQ,IAAI,uCAAuC,CAAC;AAAA,QACtD;AAAA,MACF;AACA,cAAQ,IAAI,qCAAqC;AAAA,IACnD;AAEA,WAAO,IAAI,SAAS,SAAS,MAAM;AAAA,MACjC,QAAQ,SAAS;AAAA,MACjB,SAAS;AAAA,QACP,iBACE,cAAS,QAAQ,IAAI,cAAc,MAAnC,YAAwC;AAAA,QAC1C,iBAAiB;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AACT;AAEO,IAAM,sBAAsB,CAAC,gBAClC,sBAAO,mBAAmB,OAAO,CAAC;AAGpC,IAAO,gBAAQ;","names":["_a","_b"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as hono_types from 'hono/types';
|
|
2
|
+
import { Hono } from 'hono';
|
|
3
|
+
|
|
4
|
+
type TravrseFlowStep = {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
config: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
type TravrseFlowConfig = {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
steps: TravrseFlowStep[];
|
|
15
|
+
};
|
|
16
|
+
type ChatProxyOptions = {
|
|
17
|
+
upstreamUrl?: string;
|
|
18
|
+
apiKey?: string;
|
|
19
|
+
path?: string;
|
|
20
|
+
allowedOrigins?: string[];
|
|
21
|
+
flowId?: string;
|
|
22
|
+
flowConfig?: TravrseFlowConfig;
|
|
23
|
+
};
|
|
24
|
+
declare const createChatProxyApp: (options?: ChatProxyOptions) => Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
25
|
+
declare const createVercelHandler: (options?: ChatProxyOptions) => (req: Request) => Response | Promise<Response>;
|
|
26
|
+
|
|
27
|
+
export { type ChatProxyOptions, type TravrseFlowConfig, type TravrseFlowStep, createChatProxyApp, createVercelHandler, createChatProxyApp as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as hono_types from 'hono/types';
|
|
2
|
+
import { Hono } from 'hono';
|
|
3
|
+
|
|
4
|
+
type TravrseFlowStep = {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
config: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
type TravrseFlowConfig = {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
steps: TravrseFlowStep[];
|
|
15
|
+
};
|
|
16
|
+
type ChatProxyOptions = {
|
|
17
|
+
upstreamUrl?: string;
|
|
18
|
+
apiKey?: string;
|
|
19
|
+
path?: string;
|
|
20
|
+
allowedOrigins?: string[];
|
|
21
|
+
flowId?: string;
|
|
22
|
+
flowConfig?: TravrseFlowConfig;
|
|
23
|
+
};
|
|
24
|
+
declare const createChatProxyApp: (options?: ChatProxyOptions) => Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
25
|
+
declare const createVercelHandler: (options?: ChatProxyOptions) => (req: Request) => Response | Promise<Response>;
|
|
26
|
+
|
|
27
|
+
export { type ChatProxyOptions, type TravrseFlowConfig, type TravrseFlowStep, createChatProxyApp, createVercelHandler, createChatProxyApp as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
import { handle } from "hono/vercel";
|
|
4
|
+
var DEFAULT_ENDPOINT = "https://api.travrse.ai/v1/dispatch";
|
|
5
|
+
var DEFAULT_PATH = "/api/chat/dispatch";
|
|
6
|
+
var DEFAULT_FLOW = {
|
|
7
|
+
name: "Streaming Prompt Flow",
|
|
8
|
+
description: "Streaming chat generated by the widget",
|
|
9
|
+
steps: [
|
|
10
|
+
{
|
|
11
|
+
id: "widget_prompt",
|
|
12
|
+
name: "Prompt",
|
|
13
|
+
type: "prompt",
|
|
14
|
+
enabled: true,
|
|
15
|
+
config: {
|
|
16
|
+
model: "meta/llama3.1-8b-instruct-free",
|
|
17
|
+
// model: "gpt-4o",
|
|
18
|
+
response_format: "markdown",
|
|
19
|
+
output_variable: "prompt_result",
|
|
20
|
+
user_prompt: "{{user_message}}",
|
|
21
|
+
system_prompt: "you are a helpful assistant, chatting with a user",
|
|
22
|
+
// tools: {
|
|
23
|
+
// tool_ids: [
|
|
24
|
+
// "builtin:dalle"
|
|
25
|
+
// ]
|
|
26
|
+
// },
|
|
27
|
+
previous_messages: "{{messages}}"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
var withCors = (allowedOrigins) => async (c, next) => {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
const origin = (_a = c.req.header("origin")) != null ? _a : "*";
|
|
35
|
+
const headers = {
|
|
36
|
+
"Access-Control-Allow-Origin": allowedOrigins && allowedOrigins.length ? allowedOrigins.includes(origin) ? origin : allowedOrigins[0] : origin,
|
|
37
|
+
"Access-Control-Allow-Headers": (_b = c.req.header("access-control-request-headers")) != null ? _b : "Content-Type, Authorization",
|
|
38
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
39
|
+
Vary: "Origin"
|
|
40
|
+
};
|
|
41
|
+
if (c.req.method === "OPTIONS") {
|
|
42
|
+
return new Response(null, { status: 204, headers });
|
|
43
|
+
}
|
|
44
|
+
await next();
|
|
45
|
+
Object.entries(headers).forEach(
|
|
46
|
+
([key, value]) => c.header(key, value, { append: false })
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
var createChatProxyApp = (options = {}) => {
|
|
50
|
+
var _a, _b;
|
|
51
|
+
const app = new Hono();
|
|
52
|
+
const path = (_a = options.path) != null ? _a : DEFAULT_PATH;
|
|
53
|
+
const upstream = (_b = options.upstreamUrl) != null ? _b : DEFAULT_ENDPOINT;
|
|
54
|
+
app.use("*", withCors(options.allowedOrigins));
|
|
55
|
+
app.post(path, async (c) => {
|
|
56
|
+
var _a2, _b2, _c, _d, _e;
|
|
57
|
+
const apiKey = (_a2 = options.apiKey) != null ? _a2 : process.env.TRAVRSE_API_KEY;
|
|
58
|
+
if (!apiKey) {
|
|
59
|
+
return c.json(
|
|
60
|
+
{ error: "Missing API key. Set TRAVRSE_API_KEY." },
|
|
61
|
+
401
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
let clientPayload;
|
|
65
|
+
try {
|
|
66
|
+
clientPayload = await c.req.json();
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return c.json(
|
|
69
|
+
{ error: "Invalid JSON body", details: error },
|
|
70
|
+
400
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
const messages = (_b2 = clientPayload.messages) != null ? _b2 : [];
|
|
74
|
+
const sortedMessages = [...messages].sort((a, b) => {
|
|
75
|
+
const timeA = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
76
|
+
const timeB = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
77
|
+
return timeA - timeB;
|
|
78
|
+
});
|
|
79
|
+
const formattedMessages = sortedMessages.map((message) => ({
|
|
80
|
+
role: message.role,
|
|
81
|
+
content: message.content
|
|
82
|
+
}));
|
|
83
|
+
const flowId = (_c = clientPayload.flowId) != null ? _c : options.flowId;
|
|
84
|
+
const flowConfig = (_d = options.flowConfig) != null ? _d : DEFAULT_FLOW;
|
|
85
|
+
const travrsePayload = {
|
|
86
|
+
record: {
|
|
87
|
+
name: "Streaming Chat Widget",
|
|
88
|
+
type: "standalone",
|
|
89
|
+
metadata: {}
|
|
90
|
+
},
|
|
91
|
+
messages: formattedMessages,
|
|
92
|
+
options: {
|
|
93
|
+
stream_response: true,
|
|
94
|
+
record_mode: "virtual",
|
|
95
|
+
flow_mode: flowId ? "existing" : "virtual",
|
|
96
|
+
auto_append_metadata: false
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
if (flowId) {
|
|
100
|
+
travrsePayload.flow = {
|
|
101
|
+
"name": "Chat with 8b",
|
|
102
|
+
"description": "Flow with 1 step",
|
|
103
|
+
"steps": [
|
|
104
|
+
{
|
|
105
|
+
"id": "step_01k8wnwpdcferbrq79tzj49aec",
|
|
106
|
+
"name": "Prompt 1",
|
|
107
|
+
"type": "prompt",
|
|
108
|
+
"order": 0,
|
|
109
|
+
"enabled": true,
|
|
110
|
+
"config": {
|
|
111
|
+
"text": "{{user_message}}",
|
|
112
|
+
"model": "qwen/qwen3-8b",
|
|
113
|
+
// "tools": {
|
|
114
|
+
// "tool_ids": [
|
|
115
|
+
// "tool_01k8ky2xpjfzybye5ywcmjr379",
|
|
116
|
+
// "builtin:firecrawl"
|
|
117
|
+
// ]
|
|
118
|
+
// },
|
|
119
|
+
"reasoning": false,
|
|
120
|
+
"user_prompt": "{{user_message}}",
|
|
121
|
+
"output_variable": "prompt_result",
|
|
122
|
+
"response_format": "JSON"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
};
|
|
127
|
+
} else {
|
|
128
|
+
travrsePayload.flow = flowConfig;
|
|
129
|
+
}
|
|
130
|
+
const isDevelopment = process.env.NODE_ENV === "development" || !process.env.NODE_ENV;
|
|
131
|
+
if (isDevelopment) {
|
|
132
|
+
console.log("\n=== Travrse Proxy Request ===");
|
|
133
|
+
console.log("URL:", upstream);
|
|
134
|
+
console.log("API Key Used:", apiKey ? "Yes" : "No");
|
|
135
|
+
console.log("API Key (first 12 chars):", apiKey ? apiKey.substring(0, 12) : "N/A");
|
|
136
|
+
console.log("Request Payload:", JSON.stringify(travrsePayload, null, 2));
|
|
137
|
+
}
|
|
138
|
+
const response = await fetch(upstream, {
|
|
139
|
+
method: "POST",
|
|
140
|
+
headers: {
|
|
141
|
+
Authorization: `Bearer ${apiKey}`,
|
|
142
|
+
"Content-Type": "application/json"
|
|
143
|
+
},
|
|
144
|
+
body: JSON.stringify(travrsePayload)
|
|
145
|
+
});
|
|
146
|
+
if (isDevelopment) {
|
|
147
|
+
console.log("Response Status:", response.status);
|
|
148
|
+
console.log("Response Status Text:", response.statusText);
|
|
149
|
+
if (!response.ok) {
|
|
150
|
+
const clonedResponse = response.clone();
|
|
151
|
+
try {
|
|
152
|
+
const errorBody = await clonedResponse.text();
|
|
153
|
+
console.log("Error Response Body:", errorBody);
|
|
154
|
+
} catch (e) {
|
|
155
|
+
console.log("Could not read error response body:", e);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
console.log("=== End Travrse Proxy Request ===\n");
|
|
159
|
+
}
|
|
160
|
+
return new Response(response.body, {
|
|
161
|
+
status: response.status,
|
|
162
|
+
headers: {
|
|
163
|
+
"Content-Type": (_e = response.headers.get("content-type")) != null ? _e : "application/json",
|
|
164
|
+
"Cache-Control": "no-store"
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
return app;
|
|
169
|
+
};
|
|
170
|
+
var createVercelHandler = (options) => handle(createChatProxyApp(options));
|
|
171
|
+
var index_default = createChatProxyApp;
|
|
172
|
+
export {
|
|
173
|
+
createChatProxyApp,
|
|
174
|
+
createVercelHandler,
|
|
175
|
+
index_default as default
|
|
176
|
+
};
|
|
177
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Hono } from \"hono\";\nimport type { Context } from \"hono\";\nimport { handle } from \"hono/vercel\";\n\nexport type TravrseFlowStep = {\n id: string;\n name: string;\n type: string;\n enabled: boolean;\n config: Record<string, unknown>;\n};\n\nexport type TravrseFlowConfig = {\n name: string;\n description: string;\n steps: TravrseFlowStep[];\n};\n\nexport type ChatProxyOptions = {\n upstreamUrl?: string;\n apiKey?: string;\n path?: string;\n allowedOrigins?: string[];\n flowId?: string;\n flowConfig?: TravrseFlowConfig;\n};\n\nconst DEFAULT_ENDPOINT = \"https://api.travrse.ai/v1/dispatch\";\nconst DEFAULT_PATH = \"/api/chat/dispatch\";\n\nconst DEFAULT_FLOW: TravrseFlowConfig = {\n name: \"Streaming Prompt Flow\",\n description: \"Streaming chat generated by the widget\",\n steps: [\n {\n id: \"widget_prompt\",\n name: \"Prompt\",\n type: \"prompt\",\n enabled: true,\n config: {\n model: \"meta/llama3.1-8b-instruct-free\",\n // model: \"gpt-4o\",\n response_format: \"markdown\",\n output_variable: \"prompt_result\",\n user_prompt: \"{{user_message}}\",\n system_prompt: \"you are a helpful assistant, chatting with a user\",\n // tools: {\n // tool_ids: [\n // \"builtin:dalle\"\n // ]\n // },\n previous_messages: \"{{messages}}\"\n }\n }\n ]\n};\n\nconst withCors =\n (allowedOrigins: string[] | undefined) =>\n async (c: Context, next: () => Promise<void>) => {\n const origin = c.req.header(\"origin\") ?? \"*\";\n const headers: Record<string, string> = {\n \"Access-Control-Allow-Origin\":\n allowedOrigins && allowedOrigins.length\n ? allowedOrigins.includes(origin)\n ? origin\n : allowedOrigins[0]\n : origin,\n \"Access-Control-Allow-Headers\":\n c.req.header(\"access-control-request-headers\") ??\n \"Content-Type, Authorization\",\n \"Access-Control-Allow-Methods\": \"POST, OPTIONS\",\n Vary: \"Origin\"\n };\n\n if (c.req.method === \"OPTIONS\") {\n return new Response(null, { status: 204, headers });\n }\n\n await next();\n Object.entries(headers).forEach(([key, value]) =>\n c.header(key, value, { append: false })\n );\n };\n\nexport const createChatProxyApp = (options: ChatProxyOptions = {}) => {\n const app = new Hono();\n const path = options.path ?? DEFAULT_PATH;\n const upstream = options.upstreamUrl ?? DEFAULT_ENDPOINT;\n\n app.use(\"*\", withCors(options.allowedOrigins));\n\n app.post(path, async (c) => {\n const apiKey = options.apiKey ?? process.env.TRAVRSE_API_KEY;\n if (!apiKey) {\n return c.json(\n { error: \"Missing API key. Set TRAVRSE_API_KEY.\" },\n 401\n );\n }\n\n let clientPayload: {\n messages?: Array<{ role: string; content: string; createdAt?: string }>;\n flowId?: string;\n };\n try {\n clientPayload = await c.req.json();\n } catch (error) {\n return c.json(\n { error: \"Invalid JSON body\", details: error },\n 400\n );\n }\n\n // Build the Travrse payload\n const messages = clientPayload.messages ?? [];\n // Sort messages by timestamp to ensure correct order\n const sortedMessages = [...messages].sort((a, b) => {\n const timeA = a.createdAt ? new Date(a.createdAt).getTime() : 0;\n const timeB = b.createdAt ? new Date(b.createdAt).getTime() : 0;\n return timeA - timeB;\n });\n const formattedMessages = sortedMessages.map((message) => ({\n role: message.role,\n content: message.content\n }));\n\n // Determine which flow to use\n const flowId = clientPayload.flowId ?? options.flowId;\n const flowConfig = options.flowConfig ?? DEFAULT_FLOW;\n\n const travrsePayload: Record<string, unknown> = {\n record: {\n name: \"Streaming Chat Widget\",\n type: \"standalone\",\n metadata: {}\n },\n messages: formattedMessages,\n options: {\n stream_response: true,\n record_mode: \"virtual\",\n flow_mode: flowId ? \"existing\" : \"virtual\",\n auto_append_metadata: false\n }\n };\n\n // Use flow ID if provided, otherwise use flow config\n if (flowId) {\n travrsePayload.flow = {\n \"name\": \"Chat with 8b\",\n \"description\": \"Flow with 1 step\",\n \"steps\": [\n {\n \"id\": \"step_01k8wnwpdcferbrq79tzj49aec\",\n \"name\": \"Prompt 1\",\n \"type\": \"prompt\",\n \"order\": 0,\n \"enabled\": true,\n \"config\": {\n \"text\": \"{{user_message}}\",\n \"model\": \"qwen/qwen3-8b\",\n // \"tools\": {\n // \"tool_ids\": [\n // \"tool_01k8ky2xpjfzybye5ywcmjr379\",\n // \"builtin:firecrawl\"\n // ]\n // },\n \"reasoning\": false,\n \"user_prompt\": \"{{user_message}}\",\n \"output_variable\": \"prompt_result\",\n \"response_format\": \"JSON\"\n }\n }\n ]\n }\n } else {\n travrsePayload.flow = flowConfig;\n }\n\n // Development logging\n const isDevelopment = process.env.NODE_ENV === \"development\" || !process.env.NODE_ENV;\n\n if (isDevelopment) {\n console.log(\"\\n=== Travrse Proxy Request ===\");\n console.log(\"URL:\", upstream);\n console.log(\"API Key Used:\", apiKey ? \"Yes\" : \"No\");\n console.log(\"API Key (first 12 chars):\", apiKey ? apiKey.substring(0, 12) : \"N/A\");\n console.log(\"Request Payload:\", JSON.stringify(travrsePayload, null, 2));\n }\n\n const response = await fetch(upstream, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(travrsePayload)\n });\n\n if (isDevelopment) {\n console.log(\"Response Status:\", response.status);\n console.log(\"Response Status Text:\", response.statusText);\n\n // If there's an error, try to read and log the response body\n if (!response.ok) {\n const clonedResponse = response.clone();\n try {\n const errorBody = await clonedResponse.text();\n console.log(\"Error Response Body:\", errorBody);\n } catch (e) {\n console.log(\"Could not read error response body:\", e);\n }\n }\n console.log(\"=== End Travrse Proxy Request ===\\n\");\n }\n\n return new Response(response.body, {\n status: response.status,\n headers: {\n \"Content-Type\":\n response.headers.get(\"content-type\") ?? \"application/json\",\n \"Cache-Control\": \"no-store\"\n }\n });\n });\n\n return app;\n};\n\nexport const createVercelHandler = (options?: ChatProxyOptions) =>\n handle(createChatProxyApp(options));\n\n\nexport default createChatProxyApp;\n\n"],"mappings":"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","names":["_a","_b"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vanilla-agent-proxy",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Proxy server for vanilla-agent widget - handles flow configuration and forwards requests to Travrse or other AI backends.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"src"
|
|
19
|
+
],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"hono": "^4.4.9"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^20.12.7",
|
|
25
|
+
"eslint": "^8.57.0",
|
|
26
|
+
"eslint-config-prettier": "^9.1.0",
|
|
27
|
+
"rimraf": "^5.0.5",
|
|
28
|
+
"tsup": "^8.0.1",
|
|
29
|
+
"typescript": "^5.4.5"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.17.0"
|
|
33
|
+
},
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"keywords": [
|
|
36
|
+
"proxy",
|
|
37
|
+
"server",
|
|
38
|
+
"travrse",
|
|
39
|
+
"chat",
|
|
40
|
+
"typescript"
|
|
41
|
+
],
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/becomevocal/chaty.git"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "rimraf dist && tsup src/index.ts --format esm,cjs --dts --sourcemap",
|
|
48
|
+
"lint": "eslint . --ext .ts",
|
|
49
|
+
"typecheck": "tsc --noEmit"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import type { Context } from "hono";
|
|
3
|
+
import { handle } from "hono/vercel";
|
|
4
|
+
|
|
5
|
+
export type TravrseFlowStep = {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
type: string;
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
config: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type TravrseFlowConfig = {
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
steps: TravrseFlowStep[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type ChatProxyOptions = {
|
|
20
|
+
upstreamUrl?: string;
|
|
21
|
+
apiKey?: string;
|
|
22
|
+
path?: string;
|
|
23
|
+
allowedOrigins?: string[];
|
|
24
|
+
flowId?: string;
|
|
25
|
+
flowConfig?: TravrseFlowConfig;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const DEFAULT_ENDPOINT = "https://api.travrse.ai/v1/dispatch";
|
|
29
|
+
const DEFAULT_PATH = "/api/chat/dispatch";
|
|
30
|
+
|
|
31
|
+
const DEFAULT_FLOW: TravrseFlowConfig = {
|
|
32
|
+
name: "Streaming Prompt Flow",
|
|
33
|
+
description: "Streaming chat generated by the widget",
|
|
34
|
+
steps: [
|
|
35
|
+
{
|
|
36
|
+
id: "widget_prompt",
|
|
37
|
+
name: "Prompt",
|
|
38
|
+
type: "prompt",
|
|
39
|
+
enabled: true,
|
|
40
|
+
config: {
|
|
41
|
+
model: "meta/llama3.1-8b-instruct-free",
|
|
42
|
+
// model: "gpt-4o",
|
|
43
|
+
response_format: "markdown",
|
|
44
|
+
output_variable: "prompt_result",
|
|
45
|
+
user_prompt: "{{user_message}}",
|
|
46
|
+
system_prompt: "you are a helpful assistant, chatting with a user",
|
|
47
|
+
// tools: {
|
|
48
|
+
// tool_ids: [
|
|
49
|
+
// "builtin:dalle"
|
|
50
|
+
// ]
|
|
51
|
+
// },
|
|
52
|
+
previous_messages: "{{messages}}"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const withCors =
|
|
59
|
+
(allowedOrigins: string[] | undefined) =>
|
|
60
|
+
async (c: Context, next: () => Promise<void>) => {
|
|
61
|
+
const origin = c.req.header("origin") ?? "*";
|
|
62
|
+
const headers: Record<string, string> = {
|
|
63
|
+
"Access-Control-Allow-Origin":
|
|
64
|
+
allowedOrigins && allowedOrigins.length
|
|
65
|
+
? allowedOrigins.includes(origin)
|
|
66
|
+
? origin
|
|
67
|
+
: allowedOrigins[0]
|
|
68
|
+
: origin,
|
|
69
|
+
"Access-Control-Allow-Headers":
|
|
70
|
+
c.req.header("access-control-request-headers") ??
|
|
71
|
+
"Content-Type, Authorization",
|
|
72
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
73
|
+
Vary: "Origin"
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
if (c.req.method === "OPTIONS") {
|
|
77
|
+
return new Response(null, { status: 204, headers });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await next();
|
|
81
|
+
Object.entries(headers).forEach(([key, value]) =>
|
|
82
|
+
c.header(key, value, { append: false })
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const createChatProxyApp = (options: ChatProxyOptions = {}) => {
|
|
87
|
+
const app = new Hono();
|
|
88
|
+
const path = options.path ?? DEFAULT_PATH;
|
|
89
|
+
const upstream = options.upstreamUrl ?? DEFAULT_ENDPOINT;
|
|
90
|
+
|
|
91
|
+
app.use("*", withCors(options.allowedOrigins));
|
|
92
|
+
|
|
93
|
+
app.post(path, async (c) => {
|
|
94
|
+
const apiKey = options.apiKey ?? process.env.TRAVRSE_API_KEY;
|
|
95
|
+
if (!apiKey) {
|
|
96
|
+
return c.json(
|
|
97
|
+
{ error: "Missing API key. Set TRAVRSE_API_KEY." },
|
|
98
|
+
401
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let clientPayload: {
|
|
103
|
+
messages?: Array<{ role: string; content: string; createdAt?: string }>;
|
|
104
|
+
flowId?: string;
|
|
105
|
+
};
|
|
106
|
+
try {
|
|
107
|
+
clientPayload = await c.req.json();
|
|
108
|
+
} catch (error) {
|
|
109
|
+
return c.json(
|
|
110
|
+
{ error: "Invalid JSON body", details: error },
|
|
111
|
+
400
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Build the Travrse payload
|
|
116
|
+
const messages = clientPayload.messages ?? [];
|
|
117
|
+
// Sort messages by timestamp to ensure correct order
|
|
118
|
+
const sortedMessages = [...messages].sort((a, b) => {
|
|
119
|
+
const timeA = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
120
|
+
const timeB = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
121
|
+
return timeA - timeB;
|
|
122
|
+
});
|
|
123
|
+
const formattedMessages = sortedMessages.map((message) => ({
|
|
124
|
+
role: message.role,
|
|
125
|
+
content: message.content
|
|
126
|
+
}));
|
|
127
|
+
|
|
128
|
+
// Determine which flow to use
|
|
129
|
+
const flowId = clientPayload.flowId ?? options.flowId;
|
|
130
|
+
const flowConfig = options.flowConfig ?? DEFAULT_FLOW;
|
|
131
|
+
|
|
132
|
+
const travrsePayload: Record<string, unknown> = {
|
|
133
|
+
record: {
|
|
134
|
+
name: "Streaming Chat Widget",
|
|
135
|
+
type: "standalone",
|
|
136
|
+
metadata: {}
|
|
137
|
+
},
|
|
138
|
+
messages: formattedMessages,
|
|
139
|
+
options: {
|
|
140
|
+
stream_response: true,
|
|
141
|
+
record_mode: "virtual",
|
|
142
|
+
flow_mode: flowId ? "existing" : "virtual",
|
|
143
|
+
auto_append_metadata: false
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Use flow ID if provided, otherwise use flow config
|
|
148
|
+
if (flowId) {
|
|
149
|
+
travrsePayload.flow = {
|
|
150
|
+
"name": "Chat with 8b",
|
|
151
|
+
"description": "Flow with 1 step",
|
|
152
|
+
"steps": [
|
|
153
|
+
{
|
|
154
|
+
"id": "step_01k8wnwpdcferbrq79tzj49aec",
|
|
155
|
+
"name": "Prompt 1",
|
|
156
|
+
"type": "prompt",
|
|
157
|
+
"order": 0,
|
|
158
|
+
"enabled": true,
|
|
159
|
+
"config": {
|
|
160
|
+
"text": "{{user_message}}",
|
|
161
|
+
"model": "qwen/qwen3-8b",
|
|
162
|
+
// "tools": {
|
|
163
|
+
// "tool_ids": [
|
|
164
|
+
// "tool_01k8ky2xpjfzybye5ywcmjr379",
|
|
165
|
+
// "builtin:firecrawl"
|
|
166
|
+
// ]
|
|
167
|
+
// },
|
|
168
|
+
"reasoning": false,
|
|
169
|
+
"user_prompt": "{{user_message}}",
|
|
170
|
+
"output_variable": "prompt_result",
|
|
171
|
+
"response_format": "JSON"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
travrsePayload.flow = flowConfig;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Development logging
|
|
181
|
+
const isDevelopment = process.env.NODE_ENV === "development" || !process.env.NODE_ENV;
|
|
182
|
+
|
|
183
|
+
if (isDevelopment) {
|
|
184
|
+
console.log("\n=== Travrse Proxy Request ===");
|
|
185
|
+
console.log("URL:", upstream);
|
|
186
|
+
console.log("API Key Used:", apiKey ? "Yes" : "No");
|
|
187
|
+
console.log("API Key (first 12 chars):", apiKey ? apiKey.substring(0, 12) : "N/A");
|
|
188
|
+
console.log("Request Payload:", JSON.stringify(travrsePayload, null, 2));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const response = await fetch(upstream, {
|
|
192
|
+
method: "POST",
|
|
193
|
+
headers: {
|
|
194
|
+
Authorization: `Bearer ${apiKey}`,
|
|
195
|
+
"Content-Type": "application/json"
|
|
196
|
+
},
|
|
197
|
+
body: JSON.stringify(travrsePayload)
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
if (isDevelopment) {
|
|
201
|
+
console.log("Response Status:", response.status);
|
|
202
|
+
console.log("Response Status Text:", response.statusText);
|
|
203
|
+
|
|
204
|
+
// If there's an error, try to read and log the response body
|
|
205
|
+
if (!response.ok) {
|
|
206
|
+
const clonedResponse = response.clone();
|
|
207
|
+
try {
|
|
208
|
+
const errorBody = await clonedResponse.text();
|
|
209
|
+
console.log("Error Response Body:", errorBody);
|
|
210
|
+
} catch (e) {
|
|
211
|
+
console.log("Could not read error response body:", e);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
console.log("=== End Travrse Proxy Request ===\n");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return new Response(response.body, {
|
|
218
|
+
status: response.status,
|
|
219
|
+
headers: {
|
|
220
|
+
"Content-Type":
|
|
221
|
+
response.headers.get("content-type") ?? "application/json",
|
|
222
|
+
"Cache-Control": "no-store"
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
return app;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
export const createVercelHandler = (options?: ChatProxyOptions) =>
|
|
231
|
+
handle(createChatProxyApp(options));
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
export default createChatProxyApp;
|
|
235
|
+
|