@axiom-lattice/gateway 2.1.21 → 2.1.22
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +10 -0
- package/dist/index.js +357 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +346 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -4
- package/src/controllers/sandbox.ts +150 -0
- package/src/controllers/tools.ts +410 -0
- package/src/index.ts +4 -0
- package/src/routes/index.ts +8 -0
- package/src/schemas/index.ts +42 -0
- package/src/services/agent_service.ts +14 -6
- package/src/services/sandbox_service.ts +222 -0
|
@@ -59,7 +59,11 @@ export async function agent_invoke({
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// Get runConfig from agent config and merge into configurable
|
|
62
|
-
const runConfig =
|
|
62
|
+
const runConfig = {
|
|
63
|
+
...agentLattice?.config?.runConfig || {},
|
|
64
|
+
assistant_id,
|
|
65
|
+
sandboxConfig: agentLattice?.config?.connectedSandbox,
|
|
66
|
+
}
|
|
63
67
|
|
|
64
68
|
const result = await runnable_agent.invoke(
|
|
65
69
|
command
|
|
@@ -116,7 +120,11 @@ export async function agent_stream({
|
|
|
116
120
|
const chunkBuffer = getOrCreateChunkBuffer();
|
|
117
121
|
|
|
118
122
|
// Get runConfig from agent config and merge into configurable
|
|
119
|
-
const runConfig =
|
|
123
|
+
const runConfig = {
|
|
124
|
+
...agentLattice?.config?.runConfig || {},
|
|
125
|
+
assistant_id,
|
|
126
|
+
sandboxConfig: agentLattice?.config?.connectedSandbox,
|
|
127
|
+
}
|
|
120
128
|
|
|
121
129
|
try {
|
|
122
130
|
if (!runnable_agent) {
|
|
@@ -126,10 +134,10 @@ export async function agent_stream({
|
|
|
126
134
|
command
|
|
127
135
|
? new Command(command)
|
|
128
136
|
: {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
...rest,
|
|
138
|
+
messages,
|
|
139
|
+
"x-tenant-id": tenant_id,
|
|
140
|
+
},
|
|
133
141
|
|
|
134
142
|
{
|
|
135
143
|
configurable: {
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { getAgentConfig, getAgentLattice, normalizeSandboxName } from "@axiom-lattice/core";
|
|
2
|
+
import { ConnectedSandboxConfig } from "@axiom-lattice/protocols";
|
|
3
|
+
|
|
4
|
+
const SANDBOX_BASE_URL = process.env.SANDBOX_BASE_URL || "http://localhost:8080";
|
|
5
|
+
|
|
6
|
+
const ERROR_HTML = `<!DOCTYPE html>
|
|
7
|
+
<html lang="zh-CN">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="UTF-8">
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
11
|
+
<title>Sandbox 连接错误</title>
|
|
12
|
+
<style>
|
|
13
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
14
|
+
body {
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
16
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
17
|
+
min-height: 100vh;
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
padding: 20px;
|
|
22
|
+
}
|
|
23
|
+
.container {
|
|
24
|
+
background: white;
|
|
25
|
+
border-radius: 16px;
|
|
26
|
+
padding: 40px;
|
|
27
|
+
max-width: 500px;
|
|
28
|
+
width: 100%;
|
|
29
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
|
30
|
+
}
|
|
31
|
+
.error-icon {
|
|
32
|
+
width: 80px;
|
|
33
|
+
height: 80px;
|
|
34
|
+
background: #fee2e2;
|
|
35
|
+
border-radius: 50%;
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
margin: 0 auto 24px;
|
|
40
|
+
}
|
|
41
|
+
.error-icon svg {
|
|
42
|
+
width: 40px;
|
|
43
|
+
height: 40px;
|
|
44
|
+
color: #dc2626;
|
|
45
|
+
}
|
|
46
|
+
h1 { color: #1f2937; margin-bottom: 16px; text-align: center; }
|
|
47
|
+
p { color: #6b7280; margin-bottom: 12px; line-height: 1.6; }
|
|
48
|
+
.info {
|
|
49
|
+
background: #f3f4f6;
|
|
50
|
+
border-radius: 8px;
|
|
51
|
+
padding: 16px;
|
|
52
|
+
margin: 20px 0;
|
|
53
|
+
}
|
|
54
|
+
.info-item {
|
|
55
|
+
display: flex;
|
|
56
|
+
justify-content: space-between;
|
|
57
|
+
padding: 8px 0;
|
|
58
|
+
border-bottom: 1px solid #e5e7eb;
|
|
59
|
+
}
|
|
60
|
+
.info-item:last-child { border-bottom: none; }
|
|
61
|
+
.label { color: #6b7280; font-size: 14px; }
|
|
62
|
+
.value { color: #1f2937; font-weight: 500; font-family: monospace; }
|
|
63
|
+
.retry-btn {
|
|
64
|
+
width: 100%;
|
|
65
|
+
padding: 14px;
|
|
66
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
67
|
+
color: white;
|
|
68
|
+
border: none;
|
|
69
|
+
border-radius: 8px;
|
|
70
|
+
font-size: 16px;
|
|
71
|
+
cursor: pointer;
|
|
72
|
+
transition: transform 0.2s;
|
|
73
|
+
}
|
|
74
|
+
.retry-btn:hover { transform: translateY(-2px); }
|
|
75
|
+
</style>
|
|
76
|
+
</head>
|
|
77
|
+
<body>
|
|
78
|
+
<div class="container">
|
|
79
|
+
<div class="error-icon">
|
|
80
|
+
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
81
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
|
82
|
+
</svg>
|
|
83
|
+
</div>
|
|
84
|
+
<h1>无法连接到 Sandbox</h1>
|
|
85
|
+
<p>无法连接到沙箱环境,请检查配置后重试。</p>
|
|
86
|
+
<div class="info">
|
|
87
|
+
<div class="info-item">
|
|
88
|
+
<span class="label">Assistant ID</span>
|
|
89
|
+
<span class="value" id="assistantId">-</span>
|
|
90
|
+
</div>
|
|
91
|
+
<div class="info-item">
|
|
92
|
+
<span class="label">Thread ID</span>
|
|
93
|
+
<span class="value" id="threadId">-</span>
|
|
94
|
+
</div>
|
|
95
|
+
<div class="info-item">
|
|
96
|
+
<span class="label">隔离级别</span>
|
|
97
|
+
<span class="value" id="isolatedLevel">-</span>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="info-item">
|
|
100
|
+
<span class="label">错误信息</span>
|
|
101
|
+
<span class="value" id="errorMsg">-</span>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
<button class="retry-btn" onclick="window.location.reload()">重新连接</button>
|
|
105
|
+
</div>
|
|
106
|
+
<script>
|
|
107
|
+
const params = new URLSearchParams(window.location.search);
|
|
108
|
+
document.getElementById('assistantId').textContent = params.get('assistantId') || '-';
|
|
109
|
+
document.getElementById('threadId').textContent = params.get('threadId') || '-';
|
|
110
|
+
document.getElementById('isolatedLevel').textContent = params.get('isolatedLevel') || '-';
|
|
111
|
+
document.getElementById('errorMsg').textContent = params.get('error') || '未知错误';
|
|
112
|
+
</script>
|
|
113
|
+
</body>
|
|
114
|
+
</html>`;
|
|
115
|
+
|
|
116
|
+
export class SandboxService {
|
|
117
|
+
private baseUrl: string;
|
|
118
|
+
|
|
119
|
+
constructor(baseUrl?: string) {
|
|
120
|
+
this.baseUrl = baseUrl || SANDBOX_BASE_URL;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
getSandboxConfig(assistantId: string): ConnectedSandboxConfig | null {
|
|
124
|
+
const agentConfig = getAgentConfig(assistantId);
|
|
125
|
+
if (!agentConfig) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const agentLattice = getAgentLattice(assistantId);
|
|
130
|
+
return agentLattice?.config?.connectedSandbox || null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
computeSandboxName(
|
|
134
|
+
assistantId: string,
|
|
135
|
+
threadId: string,
|
|
136
|
+
isolatedLevel: string
|
|
137
|
+
): string {
|
|
138
|
+
let sandboxName: string;
|
|
139
|
+
|
|
140
|
+
switch (isolatedLevel) {
|
|
141
|
+
case "agent":
|
|
142
|
+
sandboxName = assistantId;
|
|
143
|
+
break;
|
|
144
|
+
case "thread":
|
|
145
|
+
sandboxName = threadId;
|
|
146
|
+
break;
|
|
147
|
+
case "global":
|
|
148
|
+
default:
|
|
149
|
+
sandboxName = "global";
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return normalizeSandboxName(sandboxName);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
getTargetUrl(sandboxName: string): string {
|
|
157
|
+
return `${this.baseUrl}/sandbox/${sandboxName}`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async getVncHtml(sandboxName: string): Promise<string> {
|
|
161
|
+
const response = await fetch(`${this.getTargetUrl(sandboxName)}/vnc/index.html`);
|
|
162
|
+
|
|
163
|
+
if (!response.ok) {
|
|
164
|
+
throw new Error(`Failed to fetch VNC HTML: ${response.statusText}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return response.text();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
rewriteHtml(
|
|
171
|
+
html: string,
|
|
172
|
+
assistantId: string,
|
|
173
|
+
threadId: string
|
|
174
|
+
): string {
|
|
175
|
+
const prefix = `/api/assistants/${assistantId}/threads/${threadId}/sandbox/vnc`;
|
|
176
|
+
|
|
177
|
+
let rewritten = html;
|
|
178
|
+
|
|
179
|
+
rewritten = rewritten.replace(
|
|
180
|
+
/(src|href)=["']([^"']*)["']/g,
|
|
181
|
+
(match, attr, url) => {
|
|
182
|
+
if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//")) {
|
|
183
|
+
return match;
|
|
184
|
+
}
|
|
185
|
+
const rewrittenUrl = url.startsWith("/") ? `${prefix}${url}` : `${prefix}/${url}`;
|
|
186
|
+
return `${attr}="${rewrittenUrl}"`;
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
rewritten = rewritten.replace(
|
|
191
|
+
/path=sandbox\/[^&"']+/g,
|
|
192
|
+
(match) => {
|
|
193
|
+
return `path=${prefix}/websockify`;
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
rewritten = rewritten.replace(
|
|
198
|
+
/new WebSocket\([^)]*\?path=sandbox[^)]*\)/g,
|
|
199
|
+
(match) => {
|
|
200
|
+
return match.replace(/path=sandbox[^)]+/, `path=${prefix}/websockify`);
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
return rewritten;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
generateErrorHtml(
|
|
208
|
+
assistantId: string,
|
|
209
|
+
threadId: string,
|
|
210
|
+
isolatedLevel: string,
|
|
211
|
+
errorMessage: string
|
|
212
|
+
): string {
|
|
213
|
+
const encodedError = encodeURIComponent(errorMessage);
|
|
214
|
+
return ERROR_HTML
|
|
215
|
+
.replace("{assistantId}", assistantId)
|
|
216
|
+
.replace("{threadId}", threadId)
|
|
217
|
+
.replace("{isolatedLevel}", isolatedLevel)
|
|
218
|
+
.replace("{errorMessage}", errorMessage);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export const sandboxService = new SandboxService();
|