@axiom-lattice/gateway 2.1.21 → 2.1.23

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @axiom-lattice/gateway@2.1.21 build /home/runner/work/agentic/agentic/packages/gateway
2
+ > @axiom-lattice/gateway@2.1.23 build /home/runner/work/agentic/agentic/packages/gateway
3
3
  > tsup src/index.ts --format cjs,esm --dts --clean --sourcemap
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -9,13 +9,13 @@
9
9
  CLI Cleaning output folder
10
10
  CJS Build start
11
11
  ESM Build start
12
- CJS dist/index.js 70.95 KB
13
- CJS dist/index.js.map 160.39 KB
14
- CJS ⚡️ Build success in 170ms
15
- ESM dist/index.mjs 68.37 KB
16
- ESM dist/index.mjs.map 160.33 KB
17
- ESM ⚡️ Build success in 170ms
12
+ ESM dist/index.mjs 83.88 KB
13
+ ESM dist/index.mjs.map 200.51 KB
14
+ ESM ⚡️ Build success in 221ms
15
+ CJS dist/index.js 86.51 KB
16
+ CJS dist/index.js.map 200.54 KB
17
+ CJS ⚡️ Build success in 223ms
18
18
  DTS Build start
19
- DTS ⚡️ Build success in 7886ms
19
+ DTS ⚡️ Build success in 9197ms
20
20
  DTS dist/index.d.ts 3.72 KB
21
21
  DTS dist/index.d.mts 3.72 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @axiom-lattice/gateway
2
2
 
3
+ ## 2.1.23
4
+
5
+ ### Patch Changes
6
+
7
+ - e0a5f54: enhance file
8
+ - Updated dependencies [e0a5f54]
9
+ - @axiom-lattice/core@2.1.18
10
+
11
+ ## 2.1.22
12
+
13
+ ### Patch Changes
14
+
15
+ - 2422cbf: add sandbox and mcp
16
+ - Updated dependencies [2422cbf]
17
+ - @axiom-lattice/protocols@2.1.11
18
+ - @axiom-lattice/core@2.1.17
19
+ - @axiom-lattice/queue-redis@1.0.10
20
+
3
21
  ## 2.1.21
4
22
 
5
23
  ### Patch Changes
package/dist/index.js CHANGED
@@ -35,7 +35,9 @@ __export(index_exports, {
35
35
  module.exports = __toCommonJS(index_exports);
36
36
  var import_fastify = __toESM(require("fastify"));
37
37
  var import_cors = __toESM(require("@fastify/cors"));
38
+ var import_multipart = __toESM(require("@fastify/multipart"));
38
39
  var import_sensible = __toESM(require("@fastify/sensible"));
40
+ var import_websocket = __toESM(require("@fastify/websocket"));
39
41
 
40
42
  // src/services/agent_service.ts
41
43
  var import_messages = require("@langchain/core/messages");
@@ -70,7 +72,11 @@ async function agent_invoke({
70
72
  if (!runnable_agent) {
71
73
  throw new Error(`Agent ${assistant_id} not found`);
72
74
  }
73
- const runConfig = agentLattice?.config?.runConfig || {};
75
+ const runConfig = {
76
+ ...agentLattice?.config?.runConfig || {},
77
+ assistant_id,
78
+ sandboxConfig: agentLattice?.config?.connectedSandbox
79
+ };
74
80
  const result = await runnable_agent.invoke(
75
81
  command ? new import_langgraph.Command(command) : { ...rest, messages, "x-tenant-id": tenant_id },
76
82
  {
@@ -80,6 +86,7 @@ async function agent_invoke({
80
86
  "x-tenant-id": tenant_id,
81
87
  "x-request-id": run_id,
82
88
  "x-thread-id": thread_id,
89
+ "x-assistant-id": assistant_id,
83
90
  runConfig
84
91
  // Inject runConfig for tools to access
85
92
  },
@@ -112,7 +119,11 @@ async function agent_stream({
112
119
  messages = [humanMessage];
113
120
  }
114
121
  const chunkBuffer = getOrCreateChunkBuffer();
115
- const runConfig = agentLattice?.config?.runConfig || {};
122
+ const runConfig = {
123
+ ...agentLattice?.config?.runConfig || {},
124
+ assistant_id,
125
+ sandboxConfig: agentLattice?.config?.connectedSandbox
126
+ };
116
127
  try {
117
128
  if (!runnable_agent) {
118
129
  throw new Error(`Agent ${assistant_id} not found`);
@@ -130,6 +141,7 @@ async function agent_stream({
130
141
  "x-tenant-id": tenant_id,
131
142
  "x-request-id": run_id,
132
143
  "x-thread-id": thread_id,
144
+ "x-assistant-id": assistant_id,
133
145
  runConfig
134
146
  // Inject runConfig for tools to access
135
147
  },
@@ -1644,6 +1656,88 @@ async function filterSkillsByLicense(request, reply) {
1644
1656
  }
1645
1657
  }
1646
1658
 
1659
+ // src/controllers/tools.ts
1660
+ var import_core11 = require("@axiom-lattice/core");
1661
+ function serializeSchema(schema) {
1662
+ if (!schema) {
1663
+ return void 0;
1664
+ }
1665
+ try {
1666
+ if (schema._def) {
1667
+ const def = schema._def;
1668
+ if (def.typeName === "ZodObject") {
1669
+ const shape = def.shape();
1670
+ const properties = {};
1671
+ const required = [];
1672
+ for (const [key, value] of Object.entries(shape)) {
1673
+ const fieldDef = value._def;
1674
+ if (fieldDef) {
1675
+ properties[key] = {
1676
+ type: fieldDef.typeName === "ZodString" ? "string" : fieldDef.typeName === "ZodNumber" ? "number" : fieldDef.typeName === "ZodBoolean" ? "boolean" : fieldDef.typeName === "ZodArray" ? "array" : fieldDef.typeName === "ZodObject" ? "object" : "unknown",
1677
+ description: fieldDef.description
1678
+ };
1679
+ if (!value.isOptional()) {
1680
+ required.push(key);
1681
+ }
1682
+ }
1683
+ }
1684
+ return {
1685
+ type: "object",
1686
+ properties,
1687
+ required: required.length > 0 ? required : void 0
1688
+ };
1689
+ }
1690
+ }
1691
+ return {
1692
+ type: "object",
1693
+ description: schema.description || "Schema definition"
1694
+ };
1695
+ } catch (error) {
1696
+ return {
1697
+ type: "object",
1698
+ description: "Schema definition"
1699
+ };
1700
+ }
1701
+ }
1702
+ async function getToolConfigs(request, reply) {
1703
+ try {
1704
+ const allLattices = import_core11.toolLatticeManager.getAllLattices();
1705
+ const toolConfigs = allLattices.map((lattice) => {
1706
+ const config = { ...lattice.config };
1707
+ const serializedSchema = config.schema ? serializeSchema(config.schema) : void 0;
1708
+ return {
1709
+ id: lattice.key,
1710
+ name: config.name,
1711
+ description: config.description,
1712
+ schema: serializedSchema,
1713
+ returnDirect: config.returnDirect,
1714
+ needUserApprove: config.needUserApprove
1715
+ };
1716
+ });
1717
+ return reply.send({
1718
+ success: true,
1719
+ message: "Successfully retrieved tool configs",
1720
+ data: {
1721
+ records: toolConfigs,
1722
+ total: toolConfigs.length
1723
+ }
1724
+ });
1725
+ } catch (error) {
1726
+ console.error("Failed to get tool configs", {
1727
+ error: error.message,
1728
+ stack: error.stack
1729
+ });
1730
+ return reply.status(500).send({
1731
+ success: false,
1732
+ message: `Failed to retrieve tool configs: ${error.message}`,
1733
+ data: {
1734
+ records: [],
1735
+ total: 0
1736
+ }
1737
+ });
1738
+ }
1739
+ }
1740
+
1647
1741
  // src/schemas/index.ts
1648
1742
  var getAllMemoryItemsSchema = {
1649
1743
  description: "Get all memory items for an assistant thread",
@@ -1915,6 +2009,332 @@ var getHealthSchema = {
1915
2009
  }
1916
2010
  };
1917
2011
 
2012
+ // src/controllers/sandbox.ts
2013
+ var import_stream = require("stream");
2014
+
2015
+ // src/services/sandbox_service.ts
2016
+ var import_core12 = require("@axiom-lattice/core");
2017
+ var ERROR_HTML = `<!DOCTYPE html>
2018
+ <html lang="zh-CN">
2019
+ <head>
2020
+ <meta charset="UTF-8">
2021
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
2022
+ <title>Sandbox \u8FDE\u63A5\u9519\u8BEF</title>
2023
+ <style>
2024
+ * { box-sizing: border-box; margin: 0; padding: 0; }
2025
+ body {
2026
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
2027
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
2028
+ min-height: 100vh;
2029
+ display: flex;
2030
+ align-items: center;
2031
+ justify-content: center;
2032
+ padding: 20px;
2033
+ }
2034
+ .container {
2035
+ background: white;
2036
+ border-radius: 16px;
2037
+ padding: 40px;
2038
+ max-width: 500px;
2039
+ width: 100%;
2040
+ box-shadow: 0 20px 60px rgba(0,0,0,0.3);
2041
+ }
2042
+ .error-icon {
2043
+ width: 80px;
2044
+ height: 80px;
2045
+ background: #fee2e2;
2046
+ border-radius: 50%;
2047
+ display: flex;
2048
+ align-items: center;
2049
+ justify-content: center;
2050
+ margin: 0 auto 24px;
2051
+ }
2052
+ .error-icon svg {
2053
+ width: 40px;
2054
+ height: 40px;
2055
+ color: #dc2626;
2056
+ }
2057
+ h1 { color: #1f2937; margin-bottom: 16px; text-align: center; }
2058
+ p { color: #6b7280; margin-bottom: 12px; line-height: 1.6; }
2059
+ .info {
2060
+ background: #f3f4f6;
2061
+ border-radius: 8px;
2062
+ padding: 16px;
2063
+ margin: 20px 0;
2064
+ }
2065
+ .info-item {
2066
+ display: flex;
2067
+ justify-content: space-between;
2068
+ padding: 8px 0;
2069
+ border-bottom: 1px solid #e5e7eb;
2070
+ }
2071
+ .info-item:last-child { border-bottom: none; }
2072
+ .label { color: #6b7280; font-size: 14px; }
2073
+ .value { color: #1f2937; font-weight: 500; font-family: monospace; }
2074
+ .retry-btn {
2075
+ width: 100%;
2076
+ padding: 14px;
2077
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
2078
+ color: white;
2079
+ border: none;
2080
+ border-radius: 8px;
2081
+ font-size: 16px;
2082
+ cursor: pointer;
2083
+ transition: transform 0.2s;
2084
+ }
2085
+ .retry-btn:hover { transform: translateY(-2px); }
2086
+ </style>
2087
+ </head>
2088
+ <body>
2089
+ <div class="container">
2090
+ <div class="error-icon">
2091
+ <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
2092
+ <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"/>
2093
+ </svg>
2094
+ </div>
2095
+ <h1>\u65E0\u6CD5\u8FDE\u63A5\u5230 Sandbox</h1>
2096
+ <p>\u65E0\u6CD5\u8FDE\u63A5\u5230\u6C99\u7BB1\u73AF\u5883\uFF0C\u8BF7\u68C0\u67E5\u914D\u7F6E\u540E\u91CD\u8BD5\u3002</p>
2097
+ <div class="info">
2098
+ <div class="info-item">
2099
+ <span class="label">Assistant ID</span>
2100
+ <span class="value" id="assistantId">-</span>
2101
+ </div>
2102
+ <div class="info-item">
2103
+ <span class="label">Thread ID</span>
2104
+ <span class="value" id="threadId">-</span>
2105
+ </div>
2106
+ <div class="info-item">
2107
+ <span class="label">\u9694\u79BB\u7EA7\u522B</span>
2108
+ <span class="value" id="isolatedLevel">-</span>
2109
+ </div>
2110
+ <div class="info-item">
2111
+ <span class="label">\u9519\u8BEF\u4FE1\u606F</span>
2112
+ <span class="value" id="errorMsg">-</span>
2113
+ </div>
2114
+ </div>
2115
+ <button class="retry-btn" onclick="window.location.reload()">\u91CD\u65B0\u8FDE\u63A5</button>
2116
+ </div>
2117
+ <script>
2118
+ const params = new URLSearchParams(window.location.search);
2119
+ document.getElementById('assistantId').textContent = params.get('assistantId') || '-';
2120
+ document.getElementById('threadId').textContent = params.get('threadId') || '-';
2121
+ document.getElementById('isolatedLevel').textContent = params.get('isolatedLevel') || '-';
2122
+ document.getElementById('errorMsg').textContent = params.get('error') || '\u672A\u77E5\u9519\u8BEF';
2123
+ </script>
2124
+ </body>
2125
+ </html>`;
2126
+ var SandboxService = class {
2127
+ getSandboxConfig(assistantId) {
2128
+ const agentConfig = (0, import_core12.getAgentConfig)(assistantId);
2129
+ if (!agentConfig) {
2130
+ return null;
2131
+ }
2132
+ const agentLattice = (0, import_core12.getAgentLattice)(assistantId);
2133
+ return agentLattice?.config?.connectedSandbox || null;
2134
+ }
2135
+ computeSandboxName(assistantId, threadId, isolatedLevel) {
2136
+ let sandboxName;
2137
+ switch (isolatedLevel) {
2138
+ case "agent":
2139
+ sandboxName = assistantId;
2140
+ break;
2141
+ case "thread":
2142
+ sandboxName = threadId;
2143
+ break;
2144
+ case "global":
2145
+ default:
2146
+ sandboxName = "global";
2147
+ break;
2148
+ }
2149
+ return (0, import_core12.normalizeSandboxName)(sandboxName);
2150
+ }
2151
+ getTargetUrl(sandboxName) {
2152
+ const sandboxManager = (0, import_core12.getSandBoxManager)("default");
2153
+ return `${sandboxManager.getBaseURL()}/sandbox/${sandboxName}`;
2154
+ }
2155
+ async getVncHtml(sandboxName) {
2156
+ const response = await fetch(`${this.getTargetUrl(sandboxName)}/vnc/index.html`);
2157
+ if (!response.ok) {
2158
+ throw new Error(`Failed to fetch VNC HTML: ${response.statusText}`);
2159
+ }
2160
+ return response.text();
2161
+ }
2162
+ rewriteHtml(html, assistantId, threadId) {
2163
+ const prefix = `/api/assistants/${assistantId}/threads/${threadId}/sandbox/vnc`;
2164
+ let rewritten = html;
2165
+ rewritten = rewritten.replace(
2166
+ /(src|href)=["']([^"']*)["']/g,
2167
+ (match, attr, url) => {
2168
+ if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//")) {
2169
+ return match;
2170
+ }
2171
+ const rewrittenUrl = url.startsWith("/") ? `${prefix}${url}` : `${prefix}/${url}`;
2172
+ return `${attr}="${rewrittenUrl}"`;
2173
+ }
2174
+ );
2175
+ rewritten = rewritten.replace(
2176
+ /path=sandbox\/[^&"']+/g,
2177
+ (match) => {
2178
+ return `path=${prefix}/websockify`;
2179
+ }
2180
+ );
2181
+ rewritten = rewritten.replace(
2182
+ /new WebSocket\([^)]*\?path=sandbox[^)]*\)/g,
2183
+ (match) => {
2184
+ return match.replace(/path=sandbox[^)]+/, `path=${prefix}/websockify`);
2185
+ }
2186
+ );
2187
+ return rewritten;
2188
+ }
2189
+ generateErrorHtml(assistantId, threadId, isolatedLevel, errorMessage) {
2190
+ const encodedError = encodeURIComponent(errorMessage);
2191
+ return ERROR_HTML.replace("{assistantId}", assistantId).replace("{threadId}", threadId).replace("{isolatedLevel}", isolatedLevel).replace("{errorMessage}", errorMessage);
2192
+ }
2193
+ };
2194
+ var sandboxService = new SandboxService();
2195
+
2196
+ // src/controllers/sandbox.ts
2197
+ var import_core13 = require("@axiom-lattice/core");
2198
+ function getFilenameFromPath(path) {
2199
+ const segments = path.replace(/\/+$/, "").split("/");
2200
+ return segments[segments.length - 1] || "download";
2201
+ }
2202
+ var EXT_TO_MIME = {
2203
+ ".txt": "text/plain",
2204
+ ".html": "text/html",
2205
+ ".css": "text/css",
2206
+ ".js": "application/javascript",
2207
+ ".json": "application/json",
2208
+ ".pdf": "application/pdf",
2209
+ ".png": "image/png",
2210
+ ".jpg": "image/jpeg",
2211
+ ".jpeg": "image/jpeg",
2212
+ ".gif": "image/gif",
2213
+ ".webp": "image/webp",
2214
+ ".svg": "image/svg+xml",
2215
+ ".zip": "application/zip",
2216
+ ".csv": "text/csv",
2217
+ ".xml": "application/xml"
2218
+ };
2219
+ function getContentTypeFromFilename(filename) {
2220
+ const ext = filename.includes(".") ? filename.slice(filename.lastIndexOf(".")).toLowerCase() : "";
2221
+ return EXT_TO_MIME[ext] ?? "application/octet-stream";
2222
+ }
2223
+ function registerSandboxProxyRoutes(app2) {
2224
+ app2.post(
2225
+ "/api/assistants/:assistantId/threads/:threadId/sandbox/uploadfile",
2226
+ async (request, reply) => {
2227
+ console.log("[Sandbox Upload] Route matched:", request.url);
2228
+ const { assistantId, threadId } = request.params;
2229
+ const sandboxConfig = sandboxService.getSandboxConfig(assistantId);
2230
+ if (!sandboxConfig) {
2231
+ return reply.status(500).send({ error: "Assistant sandbox config not found" });
2232
+ }
2233
+ const { isolatedLevel } = sandboxConfig;
2234
+ const sandboxName = sandboxService.computeSandboxName(
2235
+ assistantId,
2236
+ threadId,
2237
+ isolatedLevel
2238
+ );
2239
+ const sandboxManager = (0, import_core13.getSandBoxManager)("default");
2240
+ const sandbox = await sandboxManager.createSandbox(sandboxName);
2241
+ try {
2242
+ const data = await request.file();
2243
+ if (!data) {
2244
+ return reply.status(400).send({ error: "No file in request" });
2245
+ }
2246
+ const buffer = await data.toBuffer();
2247
+ const pathEntry = data.fields?.path;
2248
+ const pathValue = pathEntry && typeof pathEntry === "object" && "value" in pathEntry ? String(pathEntry.value) : typeof pathEntry === "string" ? pathEntry : void 0;
2249
+ const formData = new FormData();
2250
+ formData.append("file", new Blob([buffer]), data.filename ?? "file");
2251
+ const path = `/home/gem/uploads/${pathValue ? pathValue : ""}${data.filename}`;
2252
+ const uploadResult = await sandbox.file.uploadFile({
2253
+ file: buffer,
2254
+ path
2255
+ });
2256
+ if (!uploadResult.ok) {
2257
+ return reply.status(502).send({ error: `Upload error: ${uploadResult.error}` });
2258
+ }
2259
+ const relativePath = uploadResult.body?.data?.file_path.replace(`/home/gem`, "");
2260
+ const result = { id: relativePath, name: data.filename, size: buffer.length };
2261
+ return reply.status(200).send({ message: "File uploaded successfully", ...result });
2262
+ } catch (error) {
2263
+ const message = error instanceof Error ? error.message : String(error);
2264
+ return reply.status(502).send({ error: `Upload proxy error: ${message}` });
2265
+ }
2266
+ }
2267
+ );
2268
+ app2.get(
2269
+ "/api/assistants/:assistantId/threads/:threadId/sandbox/downloadfile",
2270
+ async (request, reply) => {
2271
+ const { assistantId, threadId } = request.params;
2272
+ const { path: filePath } = request.query;
2273
+ if (!filePath || typeof filePath !== "string") {
2274
+ return reply.status(400).send({ error: "Query parameter 'path' is required" });
2275
+ }
2276
+ const sandboxConfig = sandboxService.getSandboxConfig(assistantId);
2277
+ if (!sandboxConfig) {
2278
+ return reply.status(404).send({ error: "Assistant sandbox config not found" });
2279
+ }
2280
+ const { isolatedLevel } = sandboxConfig;
2281
+ const sandboxName = sandboxService.computeSandboxName(
2282
+ assistantId,
2283
+ threadId,
2284
+ isolatedLevel
2285
+ );
2286
+ const sandboxManager = (0, import_core13.getSandBoxManager)("default");
2287
+ const sandbox = await sandboxManager.createSandbox(sandboxName);
2288
+ try {
2289
+ const resolvedPath = filePath.startsWith("/home/gem") ? filePath : `/home/gem/${filePath.replace(/^\//, "")}`;
2290
+ const filename = getFilenameFromPath(resolvedPath);
2291
+ const inferredContentType = getContentTypeFromFilename(filename);
2292
+ const downloadResult = await sandbox.file.downloadFile({
2293
+ path: resolvedPath
2294
+ });
2295
+ if (!downloadResult.ok) {
2296
+ return reply.status(502).send({
2297
+ error: `Download error: ${JSON.stringify(downloadResult.error)}`
2298
+ });
2299
+ }
2300
+ const body = downloadResult.body;
2301
+ if (typeof body?.stream === "function") {
2302
+ const webStream = body.stream();
2303
+ const nodeStream = import_stream.Readable.fromWeb(webStream);
2304
+ const contentType2 = body.contentType ?? inferredContentType;
2305
+ const contentDisposition2 = body.contentDisposition ?? `inline; filename="${filename.replace(/"/g, '\\"')}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
2306
+ reply = reply.status(200).type(contentType2).header("Content-Disposition", contentDisposition2).send(nodeStream);
2307
+ return reply;
2308
+ }
2309
+ const bodyUnknown = downloadResult.body;
2310
+ let buf;
2311
+ let contentType = inferredContentType;
2312
+ let contentDisposition = `inline; filename="${filename.replace(/"/g, '\\"')}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
2313
+ if (bodyUnknown instanceof ArrayBuffer) {
2314
+ buf = Buffer.from(bodyUnknown);
2315
+ } else if (bodyUnknown instanceof Buffer) {
2316
+ buf = bodyUnknown;
2317
+ } else if (bodyUnknown && typeof bodyUnknown.arrayBuffer === "function") {
2318
+ const res = bodyUnknown;
2319
+ buf = Buffer.from(await res.arrayBuffer());
2320
+ if (res.headers?.get("content-type")) contentType = res.headers.get("content-type");
2321
+ if (res.headers?.get("content-disposition")) contentDisposition = res.headers.get("content-disposition");
2322
+ } else if (bodyUnknown && typeof bodyUnknown.blob === "function") {
2323
+ const blob = await bodyUnknown.blob();
2324
+ buf = Buffer.from(await blob.arrayBuffer());
2325
+ } else {
2326
+ return reply.status(502).send({ error: "Unexpected download response format" });
2327
+ }
2328
+ reply = reply.status(200).type(contentType).header("Content-Disposition", contentDisposition).send(buf);
2329
+ return reply;
2330
+ } catch (error) {
2331
+ const message = error instanceof Error ? error.message : String(error);
2332
+ return reply.status(502).send({ error: `Download proxy error: ${message}` });
2333
+ }
2334
+ }
2335
+ );
2336
+ }
2337
+
1918
2338
  // src/routes/index.ts
1919
2339
  var registerLatticeRoutes = (app2) => {
1920
2340
  app2.post("/api/runs", createRun);
@@ -1990,6 +2410,7 @@ var registerLatticeRoutes = (app2) => {
1990
2410
  );
1991
2411
  app2.get("/api/models", getModels);
1992
2412
  app2.put("/api/models", updateModels);
2413
+ app2.get("/api/tools", getToolConfigs);
1993
2414
  app2.get(
1994
2415
  "/health",
1995
2416
  { schema: getHealthSchema },
@@ -2032,6 +2453,7 @@ var registerLatticeRoutes = (app2) => {
2032
2453
  "/api/skills/filter/license",
2033
2454
  filterSkillsByLicense
2034
2455
  );
2456
+ registerSandboxProxyRoutes(app2);
2035
2457
  };
2036
2458
 
2037
2459
  // src/swagger.ts
@@ -2097,7 +2519,7 @@ var configureSwagger = async (app2, customSwaggerConfig, customSwaggerUiConfig)
2097
2519
  };
2098
2520
 
2099
2521
  // src/services/agent_task_consumer.ts
2100
- var import_core11 = require("@axiom-lattice/core");
2522
+ var import_core14 = require("@axiom-lattice/core");
2101
2523
  var handleAgentTask = async (taskRequest, retryCount = 0) => {
2102
2524
  const {
2103
2525
  assistant_id,
@@ -2161,7 +2583,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
2161
2583
  }
2162
2584
  if (callback_event) {
2163
2585
  const state = await agent_state({ assistant_id, thread_id });
2164
- import_core11.eventBus.publish(callback_event, {
2586
+ import_core14.eventBus.publish(callback_event, {
2165
2587
  success: true,
2166
2588
  state,
2167
2589
  config: { assistant_id, thread_id, tenant_id }
@@ -2175,7 +2597,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
2175
2597
  await response.text();
2176
2598
  if (callback_event) {
2177
2599
  const state = await agent_state({ assistant_id, thread_id });
2178
- import_core11.eventBus.publish(callback_event, {
2600
+ import_core14.eventBus.publish(callback_event, {
2179
2601
  success: true,
2180
2602
  state,
2181
2603
  config: { assistant_id, thread_id, tenant_id }
@@ -2202,7 +2624,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
2202
2624
  return handleAgentTask(taskRequest, nextRetryCount);
2203
2625
  }
2204
2626
  if (callback_event) {
2205
- import_core11.eventBus.publish(callback_event, {
2627
+ import_core14.eventBus.publish(callback_event, {
2206
2628
  success: false,
2207
2629
  error: error instanceof Error ? error.message : String(error),
2208
2630
  config: { assistant_id, thread_id, tenant_id }
@@ -2240,7 +2662,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
2240
2662
  * 初始化事件监听和队列轮询
2241
2663
  */
2242
2664
  initialize() {
2243
- import_core11.eventBus.subscribe(import_core11.AGENT_TASK_EVENT, this.trigger_agent_task.bind(this));
2665
+ import_core14.eventBus.subscribe(import_core14.AGENT_TASK_EVENT, this.trigger_agent_task.bind(this));
2244
2666
  this.startPollingQueue();
2245
2667
  console.log("Agent\u4EFB\u52A1\u6D88\u8D39\u8005\u5DF2\u542F\u52A8\u5E76\u76D1\u542C\u4EFB\u52A1\u4E8B\u4EF6\u548C\u961F\u5217");
2246
2668
  }
@@ -2359,7 +2781,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
2359
2781
  handleAgentTask(taskRequest).catch((error) => {
2360
2782
  console.error("\u5904\u7406Agent\u4EFB\u52A1\u65F6\u53D1\u751F\u672A\u6355\u83B7\u7684\u9519\u8BEF:", error);
2361
2783
  if (taskRequest.callback_event) {
2362
- import_core11.eventBus.publish(taskRequest.callback_event, {
2784
+ import_core14.eventBus.publish(taskRequest.callback_event, {
2363
2785
  success: false,
2364
2786
  error: error instanceof Error ? error.message : String(error),
2365
2787
  config: {
@@ -2379,7 +2801,7 @@ _AgentTaskConsumer.agent_run_endpoint = "http://localhost:4001/api/runs";
2379
2801
  var AgentTaskConsumer = _AgentTaskConsumer;
2380
2802
 
2381
2803
  // src/index.ts
2382
- var import_core12 = require("@axiom-lattice/core");
2804
+ var import_core15 = require("@axiom-lattice/core");
2383
2805
  var import_protocols2 = require("@axiom-lattice/protocols");
2384
2806
  process.on("unhandledRejection", (reason, promise) => {
2385
2807
  console.error("\u672A\u5904\u7406\u7684Promise\u62D2\u7EDD:", reason);
@@ -2394,11 +2816,11 @@ var DEFAULT_LOGGER_CONFIG = {
2394
2816
  var loggerLattice = initializeLogger(DEFAULT_LOGGER_CONFIG);
2395
2817
  var logger = loggerLattice.client;
2396
2818
  function initializeLogger(config) {
2397
- if (import_core12.loggerLatticeManager.hasLattice("default")) {
2398
- import_core12.loggerLatticeManager.removeLattice("default");
2819
+ if (import_core15.loggerLatticeManager.hasLattice("default")) {
2820
+ import_core15.loggerLatticeManager.removeLattice("default");
2399
2821
  }
2400
- (0, import_core12.registerLoggerLattice)("default", config);
2401
- return (0, import_core12.getLoggerLattice)("default");
2822
+ (0, import_core15.registerLoggerLattice)("default", config);
2823
+ return (0, import_core15.getLoggerLattice)("default");
2402
2824
  }
2403
2825
  var app = (0, import_fastify.default)({
2404
2826
  logger: false,
@@ -2444,12 +2866,20 @@ app.register(import_cors.default, {
2444
2866
  "Authorization",
2445
2867
  "X-Requested-With",
2446
2868
  "x-tenant-id",
2447
- "x-request-id"
2869
+ "x-request-id",
2870
+ "x-assistant-id",
2871
+ "x-thread-id"
2448
2872
  ],
2449
2873
  exposedHeaders: ["Content-Type"],
2450
2874
  credentials: true
2451
2875
  });
2452
2876
  app.register(import_sensible.default);
2877
+ app.register(import_multipart.default, {
2878
+ limits: {
2879
+ fileSize: Number(process.env.BODY_LIMIT) || 50 * 1024 * 1024
2880
+ }
2881
+ });
2882
+ app.register(import_websocket.default);
2453
2883
  app.setErrorHandler((error, request, reply) => {
2454
2884
  const getHeaderValue = (header) => {
2455
2885
  if (Array.isArray(header)) {