@axiom-lattice/gateway 2.1.53 → 2.1.55
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 +19 -0
- package/dist/index.js +1043 -526
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +977 -449
- package/dist/index.mjs.map +1 -1
- package/jest.config.js +5 -0
- package/package.json +6 -5
- package/src/__tests__/__mocks__/e2b.ts +1 -0
- package/src/__tests__/channel-installations.test.ts +199 -0
- package/src/__tests__/sandbox-provider-registration.test.ts +74 -0
- package/src/__tests__/workspace.test.ts +119 -8
- package/src/channels/__tests__/routes.test.ts +71 -0
- package/src/channels/lark/README.md +187 -0
- package/src/channels/lark/__tests__/aggregator.test.ts +23 -0
- package/src/channels/lark/__tests__/controller.test.ts +270 -0
- package/src/channels/lark/__tests__/mapping-service.test.ts +118 -0
- package/src/channels/lark/__tests__/parser.test.ts +72 -0
- package/src/channels/lark/__tests__/sender.test.ts +37 -0
- package/src/channels/lark/__tests__/verification.test.ts +157 -0
- package/src/channels/lark/aggregator.ts +16 -0
- package/src/channels/lark/config.ts +44 -0
- package/src/channels/lark/controller.ts +189 -0
- package/src/channels/lark/mapping-service.ts +138 -0
- package/src/channels/lark/parser.ts +68 -0
- package/src/channels/lark/routes.ts +121 -0
- package/src/channels/lark/runner.ts +37 -0
- package/src/channels/lark/sender.ts +58 -0
- package/src/channels/lark/types.ts +33 -0
- package/src/channels/lark/verification.ts +67 -0
- package/src/channels/routes.ts +25 -0
- package/src/controllers/channel-installations.ts +354 -0
- package/src/controllers/sandbox.ts +30 -80
- package/src/controllers/skills.ts +71 -321
- package/src/controllers/threads.ts +8 -6
- package/src/controllers/workspace.ts +64 -179
- package/src/index.ts +28 -5
- package/src/routes/channel-installations.ts +33 -0
- package/src/routes/index.ts +6 -0
- package/src/schemas/index.ts +2 -2
- package/src/services/sandbox_service.ts +21 -21
- package/src/services/skill_service.ts +97 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Readable } from "stream";
|
|
2
1
|
import { FastifyInstance } from "fastify";
|
|
3
2
|
import { sandboxService } from "../services/sandbox_service";
|
|
4
3
|
import { getSandBoxManager } from "@axiom-lattice/core";
|
|
@@ -55,15 +54,15 @@ export function registerSandboxProxyRoutes(app: FastifyInstance): void {
|
|
|
55
54
|
const { assistantId, threadId } = request.params;
|
|
56
55
|
const tenantId = (request.headers["x-tenant-id"] as string) || "default";
|
|
57
56
|
|
|
58
|
-
const
|
|
59
|
-
if (!
|
|
57
|
+
const vmIsolation = sandboxService.getFilesystemVmIsolation(tenantId, assistantId);
|
|
58
|
+
if (!vmIsolation) {
|
|
60
59
|
return reply.status(500).send({ error: "Assistant sandbox config not found" });
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
const sandboxName = sandboxService.computeSandboxName(
|
|
64
63
|
assistantId,
|
|
65
64
|
threadId,
|
|
66
|
-
|
|
65
|
+
vmIsolation
|
|
67
66
|
);
|
|
68
67
|
|
|
69
68
|
const sandboxManager = getSandBoxManager()
|
|
@@ -84,20 +83,15 @@ export function registerSandboxProxyRoutes(app: FastifyInstance): void {
|
|
|
84
83
|
? pathEntry
|
|
85
84
|
: undefined;
|
|
86
85
|
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
path: path,
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
if (!uploadResult.ok) {
|
|
97
|
-
return reply.status(502).send({ error: `Upload error: ${uploadResult.error}` });
|
|
86
|
+
const filePath = `~/uploads/${pathValue ? pathValue : ""}${data.filename}`;
|
|
87
|
+
try {
|
|
88
|
+
await sandbox.file.uploadFile({ file: filePath, data: buffer });
|
|
89
|
+
} catch (err) {
|
|
90
|
+
reply.status(500).send({ error: String(err) });
|
|
91
|
+
return;
|
|
98
92
|
}
|
|
99
93
|
|
|
100
|
-
const relativePath =
|
|
94
|
+
const relativePath = filePath.replace(`~/`, "");
|
|
101
95
|
const result = { id: relativePath, name: data.filename, size: buffer.length };
|
|
102
96
|
|
|
103
97
|
return reply.status(200).send({ message: "File uploaded successfully", ...result });
|
|
@@ -123,79 +117,35 @@ export function registerSandboxProxyRoutes(app: FastifyInstance): void {
|
|
|
123
117
|
return reply.status(400).send({ error: "Query parameter 'path' is required" });
|
|
124
118
|
}
|
|
125
119
|
|
|
126
|
-
const
|
|
127
|
-
if (!
|
|
128
|
-
return reply.status(500).send({ error: "Assistant filesystem
|
|
120
|
+
const vmIsolation = sandboxService.getFilesystemVmIsolation(tenantId, assistantId);
|
|
121
|
+
if (!vmIsolation) {
|
|
122
|
+
return reply.status(500).send({ error: "Assistant filesystem vmIsolation not found" });
|
|
129
123
|
}
|
|
130
124
|
|
|
131
125
|
const sandboxName = sandboxService.computeSandboxName(
|
|
132
126
|
assistantId,
|
|
133
127
|
threadId,
|
|
134
|
-
|
|
128
|
+
vmIsolation
|
|
135
129
|
);
|
|
136
130
|
|
|
137
131
|
const sandboxManager = getSandBoxManager();
|
|
138
132
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
139
133
|
|
|
140
134
|
try {
|
|
141
|
-
// Resolve path:
|
|
142
|
-
const resolvedPath = filePath.startsWith("
|
|
135
|
+
// Resolve path: convert ~/ prefix or relative path to sandbox path
|
|
136
|
+
const resolvedPath = filePath.startsWith("~/") ? filePath : `~/${filePath.replace(/^\//, "")}`;
|
|
143
137
|
const filename = getFilenameFromPath(resolvedPath);
|
|
144
138
|
const inferredContentType = getContentTypeFromFilename(filename);
|
|
145
139
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (!downloadResult.ok) {
|
|
151
|
-
return reply.status(502).send({
|
|
152
|
-
error: `Download error: ${JSON.stringify(downloadResult.error)}`,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Use body.stream() to get ReadableStream and pipe directly (no buffering)
|
|
157
|
-
const body = downloadResult.body as unknown as {
|
|
158
|
-
stream?: () => ReadableStream<Uint8Array>;
|
|
159
|
-
contentType?: string;
|
|
160
|
-
contentDisposition?: string;
|
|
161
|
-
};
|
|
162
|
-
if (typeof body?.stream === "function") {
|
|
163
|
-
const webStream = body.stream();
|
|
164
|
-
const nodeStream = Readable.fromWeb(webStream);
|
|
165
|
-
const contentType = body.contentType ?? inferredContentType;
|
|
166
|
-
const contentDisposition =
|
|
167
|
-
body.contentDisposition ?? `inline; filename="${filename.replace(/"/g, '\\"')}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
|
|
168
|
-
reply = reply.status(200).type(contentType).header("Content-Disposition", contentDisposition).send(nodeStream);
|
|
140
|
+
try {
|
|
141
|
+
const buf = await sandbox.file.downloadFile({ file: resolvedPath });
|
|
142
|
+
const contentDisposition = `inline; filename="${filename.replace(/"/g, '\\"')}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
|
|
143
|
+
reply = reply.status(200).type(inferredContentType).header("Content-Disposition", contentDisposition).send(buf);
|
|
169
144
|
return reply;
|
|
145
|
+
} catch (err) {
|
|
146
|
+
reply.status(500).send({ error: String(err) });
|
|
147
|
+
return;
|
|
170
148
|
}
|
|
171
|
-
|
|
172
|
-
// Fallback: buffer body when stream is not available
|
|
173
|
-
const bodyUnknown = downloadResult.body as unknown;
|
|
174
|
-
let buf: Buffer;
|
|
175
|
-
let contentType = inferredContentType;
|
|
176
|
-
let contentDisposition = `inline; filename="${filename.replace(/"/g, '\\"')}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
|
|
177
|
-
|
|
178
|
-
if (bodyUnknown instanceof ArrayBuffer) {
|
|
179
|
-
buf = Buffer.from(bodyUnknown);
|
|
180
|
-
} else if (bodyUnknown instanceof Buffer) {
|
|
181
|
-
buf = bodyUnknown;
|
|
182
|
-
} else if (
|
|
183
|
-
bodyUnknown &&
|
|
184
|
-
typeof (bodyUnknown as { arrayBuffer?: () => Promise<ArrayBuffer> }).arrayBuffer === "function"
|
|
185
|
-
) {
|
|
186
|
-
const res = bodyUnknown as { arrayBuffer: () => Promise<ArrayBuffer>; headers?: Headers };
|
|
187
|
-
buf = Buffer.from(await res.arrayBuffer());
|
|
188
|
-
if (res.headers?.get("content-type")) contentType = res.headers.get("content-type")!;
|
|
189
|
-
if (res.headers?.get("content-disposition")) contentDisposition = res.headers.get("content-disposition")!;
|
|
190
|
-
} else if (bodyUnknown && typeof (bodyUnknown as { blob?: () => Promise<Blob> }).blob === "function") {
|
|
191
|
-
const blob = await (bodyUnknown as { blob: () => Promise<Blob> }).blob();
|
|
192
|
-
buf = Buffer.from(await blob.arrayBuffer());
|
|
193
|
-
} else {
|
|
194
|
-
return reply.status(502).send({ error: "Unexpected download response format" });
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
reply = reply.status(200).type(contentType).header("Content-Disposition", contentDisposition).send(buf);
|
|
198
|
-
return reply;
|
|
199
149
|
} catch (error: unknown) {
|
|
200
150
|
const message = error instanceof Error ? error.message : String(error);
|
|
201
151
|
return reply.status(502).send({ error: `Download proxy error: ${message}` });
|
|
@@ -219,11 +169,11 @@ export function registerSandboxProxyRoutes(app: FastifyInstance): void {
|
|
|
219
169
|
// return reply.status(404).type("text/html").send(errorHtml);
|
|
220
170
|
// }
|
|
221
171
|
|
|
222
|
-
// const {
|
|
172
|
+
// const { vmIsolation } = sandboxConfig;
|
|
223
173
|
// const sandboxName = sandboxService.computeSandboxName(
|
|
224
174
|
// assistantId,
|
|
225
175
|
// threadId,
|
|
226
|
-
//
|
|
176
|
+
// vmIsolation
|
|
227
177
|
// );
|
|
228
178
|
|
|
229
179
|
// try {
|
|
@@ -234,7 +184,7 @@ export function registerSandboxProxyRoutes(app: FastifyInstance): void {
|
|
|
234
184
|
// const errorHtml = sandboxService.generateErrorHtml(
|
|
235
185
|
// assistantId,
|
|
236
186
|
// threadId,
|
|
237
|
-
//
|
|
187
|
+
// vmIsolation,
|
|
238
188
|
// error.message || "Failed to connect to sandbox"
|
|
239
189
|
// );
|
|
240
190
|
// return reply.status(502).type("text/html").send(errorHtml);
|
|
@@ -270,11 +220,11 @@ export function registerSandboxProxyRoutes(app: FastifyInstance): void {
|
|
|
270
220
|
// return;
|
|
271
221
|
// }
|
|
272
222
|
|
|
273
|
-
// const {
|
|
223
|
+
// const { vmIsolation } = sandboxConfig;
|
|
274
224
|
// const sandboxName = sandboxService.computeSandboxName(
|
|
275
225
|
// assistantId,
|
|
276
226
|
// threadId,
|
|
277
|
-
//
|
|
227
|
+
// vmIsolation
|
|
278
228
|
// );
|
|
279
229
|
|
|
280
230
|
// const targetUrl = sandboxService.getTargetUrl(sandboxName);
|
|
@@ -308,11 +258,11 @@ export function registerSandboxProxyRoutes(app: FastifyInstance): void {
|
|
|
308
258
|
// return reply.status(404).send("Assistant not found");
|
|
309
259
|
// }
|
|
310
260
|
|
|
311
|
-
// const {
|
|
261
|
+
// const { vmIsolation } = sandboxConfig;
|
|
312
262
|
// const sandboxName = sandboxService.computeSandboxName(
|
|
313
263
|
// assistantId,
|
|
314
264
|
// threadId,
|
|
315
|
-
//
|
|
265
|
+
// vmIsolation
|
|
316
266
|
// );
|
|
317
267
|
|
|
318
268
|
// const targetPath = restPath ? `/vnc/${restPath}` : "/vnc/";
|