@axiom-lattice/gateway 2.1.97 → 2.1.99

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/dist/index.mjs CHANGED
@@ -1,3 +1,9 @@
1
+ import {
2
+ Logger,
3
+ getQrCode,
4
+ getQrCodeStatus
5
+ } from "./chunk-6CUQGDJI.mjs";
6
+
1
7
  // src/index.ts
2
8
  import fastify from "fastify";
3
9
  import cors from "@fastify/cors";
@@ -3487,7 +3493,7 @@ var WorkspaceController = class {
3487
3493
  }
3488
3494
  const inferredContentType = this.getMimeType(filename2);
3489
3495
  try {
3490
- let contentType = inferredContentType;
3496
+ const contentType = inferredContentType;
3491
3497
  const isHtml = contentType?.toLowerCase().includes("text/html") || filename2.toLowerCase().endsWith(".html") || filename2.toLowerCase().endsWith(".htm");
3492
3498
  let outputBuf = buf;
3493
3499
  if (isHtml) {
@@ -3599,7 +3605,7 @@ var WorkspaceController = class {
3599
3605
  const filename = data.filename || "file";
3600
3606
  const pathEntry = data.fields?.path;
3601
3607
  const pathValue = pathEntry && typeof pathEntry === "object" && "value" in pathEntry ? String(pathEntry.value) : typeof pathEntry === "string" ? pathEntry : void 0;
3602
- if (pathValue && !/^[a-zA-Z0-9_./~\-]+$/.test(pathValue)) {
3608
+ if (pathValue && !/^[a-zA-Z0-9_./~-]+$/.test(pathValue)) {
3603
3609
  return reply.status(400).send({ success: false, error: "Invalid path parameter" });
3604
3610
  }
3605
3611
  if (workspace.storageType === "sandbox") {
@@ -6167,144 +6173,6 @@ function normalizeChatType(chatType) {
6167
6173
  return chatType === "p2p" ? "direct" : "group";
6168
6174
  }
6169
6175
 
6170
- // src/logger/Logger.ts
6171
- import pino from "pino";
6172
- import "pino-pretty";
6173
- import "pino-roll";
6174
- var PinoLoggerFactory = class _PinoLoggerFactory {
6175
- constructor() {
6176
- const isProd = process.env.NODE_ENV === "production";
6177
- const loggerConfig = {
6178
- // 自定义时间戳格式
6179
- timestamp: () => `,"@timestamp":"${(/* @__PURE__ */ new Date()).toISOString()}"`,
6180
- // 关闭默认的时间戳键
6181
- base: {
6182
- "@version": "1",
6183
- app_name: "lattice",
6184
- service_name: "lattice/graph-server",
6185
- thread_name: "main",
6186
- logger_name: "lattice-graph-logger"
6187
- },
6188
- formatters: {
6189
- level: (label, number) => {
6190
- return {
6191
- level: label.toUpperCase(),
6192
- level_value: number * 1e3
6193
- };
6194
- }
6195
- }
6196
- };
6197
- if (isProd) {
6198
- try {
6199
- this.pinoLogger = pino(
6200
- loggerConfig,
6201
- pino.transport({
6202
- target: "pino-roll",
6203
- options: {
6204
- file: "./logs/fin_ai_graph_server",
6205
- frequency: "daily",
6206
- mkdir: true
6207
- }
6208
- })
6209
- );
6210
- } catch (error) {
6211
- console.error(
6212
- "\u65E0\u6CD5\u521D\u59CB\u5316 pino-roll \u65E5\u5FD7\u8BB0\u5F55\u5668\uFF0C\u56DE\u9000\u5230\u63A7\u5236\u53F0\u65E5\u5FD7",
6213
- error
6214
- );
6215
- this.pinoLogger = pino({
6216
- ...loggerConfig,
6217
- transport: {
6218
- target: "pino-pretty",
6219
- options: {
6220
- colorize: true
6221
- }
6222
- }
6223
- });
6224
- }
6225
- } else {
6226
- this.pinoLogger = pino({
6227
- ...loggerConfig,
6228
- transport: {
6229
- target: "pino-pretty",
6230
- options: {
6231
- colorize: true
6232
- }
6233
- }
6234
- });
6235
- }
6236
- }
6237
- static getInstance() {
6238
- if (!_PinoLoggerFactory.instance) {
6239
- _PinoLoggerFactory.instance = new _PinoLoggerFactory();
6240
- }
6241
- return _PinoLoggerFactory.instance;
6242
- }
6243
- getPinoLogger() {
6244
- return this.pinoLogger;
6245
- }
6246
- };
6247
- var Logger = class _Logger {
6248
- constructor(options) {
6249
- this.context = options?.context || {};
6250
- this.name = options?.name || "lattice-graph-logger";
6251
- this.serviceName = options?.serviceName || "lattice/graph-server";
6252
- }
6253
- /**
6254
- * 获取合并了上下文的日志对象
6255
- * @param additionalContext 额外的上下文数据
6256
- * @returns 带有上下文的pino日志对象
6257
- */
6258
- getContextualLogger(additionalContext) {
6259
- const pinoLogger = PinoLoggerFactory.getInstance().getPinoLogger();
6260
- const contextObj = {
6261
- "x-user-id": this.context["x-user-id"] || "",
6262
- "x-tenant-id": this.context["x-tenant-id"] || "",
6263
- "x-request-id": this.context["x-request-id"] || "",
6264
- "x-task-id": this.context["x-task-id"] || "",
6265
- "x-thread-id": this.context["x-thread-id"] || "",
6266
- service_name: this.serviceName,
6267
- logger_name: this.name,
6268
- ...additionalContext
6269
- };
6270
- return pinoLogger.child(contextObj);
6271
- }
6272
- info(msg, obj) {
6273
- this.getContextualLogger(obj).info(msg);
6274
- }
6275
- error(msg, obj) {
6276
- this.getContextualLogger(obj).error(msg);
6277
- }
6278
- warn(msg, obj) {
6279
- this.getContextualLogger(obj).warn(msg);
6280
- }
6281
- debug(msg, obj) {
6282
- this.getContextualLogger(obj).debug(msg);
6283
- }
6284
- /**
6285
- * 更新Logger实例的上下文
6286
- */
6287
- updateContext(context) {
6288
- this.context = {
6289
- ...this.context,
6290
- ...context
6291
- };
6292
- }
6293
- /**
6294
- * 创建一个新的Logger实例,继承当前Logger的上下文
6295
- */
6296
- child(options) {
6297
- return new _Logger({
6298
- name: options.name || this.name,
6299
- serviceName: options.serviceName || this.serviceName,
6300
- context: {
6301
- ...this.context,
6302
- ...options.context
6303
- }
6304
- });
6305
- }
6306
- };
6307
-
6308
6176
  // src/channels/lark/LarkChannelAdapter.ts
6309
6177
  import * as Lark from "@larksuiteoapi/node-sdk";
6310
6178
  var logger = new Logger({ serviceName: "lattice/gateway/lark" });
@@ -6437,6 +6305,24 @@ var larkChannelAdapter = {
6437
6305
  await client.start({ eventDispatcher });
6438
6306
  activeConnections.set(installationId, client);
6439
6307
  logger.info("Lark WS client connected", { installationId });
6308
+ },
6309
+ async disconnect(installationId) {
6310
+ const client = activeConnections.get(installationId);
6311
+ if (!client) {
6312
+ logger.warn("Lark WS not connected, nothing to disconnect", { installationId });
6313
+ return;
6314
+ }
6315
+ logger.info("Lark WS client disconnecting", { installationId });
6316
+ try {
6317
+ client.close({ force: true });
6318
+ } catch (err) {
6319
+ logger.error("Lark WS client stop error", {
6320
+ installationId,
6321
+ error: err instanceof Error ? err.message : String(err)
6322
+ });
6323
+ }
6324
+ activeConnections.delete(installationId);
6325
+ logger.info("Lark WS client disconnected", { installationId });
6440
6326
  }
6441
6327
  };
6442
6328
 
@@ -6504,9 +6390,62 @@ function registerLarkChannelRoutes(app2, deps) {
6504
6390
  );
6505
6391
  }
6506
6392
 
6393
+ // src/channels/wechat/controller.ts
6394
+ var qrSessions = /* @__PURE__ */ new Map();
6395
+ var SESSION_TTL_MS = 5 * 60 * 1e3;
6396
+ function cleanupExpiredSessions() {
6397
+ const now = Date.now();
6398
+ for (const [key, session] of qrSessions) {
6399
+ if (now - session.createdAt > SESSION_TTL_MS) {
6400
+ qrSessions.delete(key);
6401
+ }
6402
+ }
6403
+ }
6404
+ async function handleGetQrCode(_request, reply) {
6405
+ try {
6406
+ cleanupExpiredSessions();
6407
+ const { qrcode, qrcodeImgUrl } = await getQrCode();
6408
+ qrSessions.set(qrcode, { qrcode, createdAt: Date.now() });
6409
+ reply.send({ success: true, data: { qrcode, qrcodeImgUrl } });
6410
+ } catch (err) {
6411
+ reply.status(500).send({
6412
+ success: false,
6413
+ message: err instanceof Error ? err.message : "Failed to get QR code"
6414
+ });
6415
+ }
6416
+ }
6417
+ async function handleGetQrCodeStatus(request, reply) {
6418
+ const { qrcode } = request.query;
6419
+ if (!qrcode) {
6420
+ reply.status(400).send({ success: false, message: "qrcode is required" });
6421
+ return;
6422
+ }
6423
+ const session = qrSessions.get(qrcode);
6424
+ if (!session) {
6425
+ reply.status(404).send({ success: false, message: "Session not found or expired" });
6426
+ return;
6427
+ }
6428
+ try {
6429
+ const result = await getQrCodeStatus(qrcode);
6430
+ reply.send({ success: true, data: result });
6431
+ } catch (err) {
6432
+ reply.status(500).send({
6433
+ success: false,
6434
+ message: err instanceof Error ? err.message : "Failed to check QR status"
6435
+ });
6436
+ }
6437
+ }
6438
+
6439
+ // src/channels/wechat/routes.ts
6440
+ function registerWechatChannelRoutes(app2) {
6441
+ app2.get("/api/channels/wechat/setup/qrcode", handleGetQrCode);
6442
+ app2.get("/api/channels/wechat/setup/status", handleGetQrCodeStatus);
6443
+ }
6444
+
6507
6445
  // src/channels/routes.ts
6508
6446
  var channelRouteRegistrars = [
6509
- (app2, deps) => registerLarkChannelRoutes(app2, deps)
6447
+ (app2, deps) => registerLarkChannelRoutes(app2, deps),
6448
+ (app2, _deps) => registerWechatChannelRoutes(app2)
6510
6449
  ];
6511
6450
  function registerChannelRoutes(app2, dependencies) {
6512
6451
  if (!dependencies) return;
@@ -6517,6 +6456,12 @@ function registerChannelRoutes(app2, dependencies) {
6517
6456
 
6518
6457
  // src/controllers/channel-installations.ts
6519
6458
  import { randomUUID as randomUUID7 } from "crypto";
6459
+ var _adapterRegistry;
6460
+ var _router;
6461
+ function setChannelControllerDeps(deps) {
6462
+ _adapterRegistry = deps.adapterRegistry;
6463
+ _router = deps.router;
6464
+ }
6520
6465
  function getTenantId13(request) {
6521
6466
  const userTenantId = request.user?.tenantId;
6522
6467
  if (userTenantId) {
@@ -6638,6 +6583,16 @@ async function createChannelInstallation(request, reply) {
6638
6583
  installationId,
6639
6584
  body
6640
6585
  );
6586
+ if (body.enabled !== false && _adapterRegistry) {
6587
+ const adapter = _adapterRegistry.get(body.channel);
6588
+ if (adapter?.connect) {
6589
+ try {
6590
+ await adapter.connect(installation, { router: _router });
6591
+ } catch (err) {
6592
+ console.error("Failed to start channel connection after creation:", err);
6593
+ }
6594
+ }
6595
+ }
6641
6596
  reply.code(201);
6642
6597
  return {
6643
6598
  success: true,
@@ -6692,6 +6647,14 @@ async function updateChannelInstallation(request, reply) {
6692
6647
  message: "Channel installation not found"
6693
6648
  };
6694
6649
  }
6650
+ if (body.enabled !== void 0 && body.enabled !== existing.enabled) {
6651
+ const adapter = _adapterRegistry?.get(existing.channel);
6652
+ if (body.enabled && adapter?.connect) {
6653
+ await adapter.connect(installation, { router: _router });
6654
+ } else if (!body.enabled && adapter?.disconnect) {
6655
+ await adapter.disconnect(installationId);
6656
+ }
6657
+ }
6695
6658
  return {
6696
6659
  success: true,
6697
6660
  message: "Channel installation updated successfully",
@@ -6725,6 +6688,16 @@ async function deleteChannelInstallation(request, reply) {
6725
6688
  message: "Access denied"
6726
6689
  };
6727
6690
  }
6691
+ if (_adapterRegistry) {
6692
+ const adapter = _adapterRegistry.get(existing.channel);
6693
+ if (adapter?.disconnect) {
6694
+ try {
6695
+ await adapter.disconnect(installationId);
6696
+ } catch (err) {
6697
+ console.error("Failed to disconnect channel adapter:", err);
6698
+ }
6699
+ }
6700
+ }
6728
6701
  const deleted = await store.deleteInstallation(tenantId, installationId);
6729
6702
  if (!deleted) {
6730
6703
  reply.code(404);
@@ -8337,12 +8310,12 @@ var start = async (config) => {
8337
8310
  let channelDeps;
8338
8311
  const adapterRegistry = new ChannelAdapterRegistry();
8339
8312
  adapterRegistry.register(larkChannelAdapter);
8313
+ const { wechatChannelAdapter } = await import("./WechatChannelAdapter-QQYOHZTL.mjs");
8314
+ adapterRegistry.register(wechatChannelAdapter);
8340
8315
  try {
8341
8316
  const { getStoreLattice: getStore2 } = await import("@axiom-lattice/core");
8342
- let bindingStore;
8343
- let installationStore;
8344
- bindingStore = getStore2("default", "channelBinding").store;
8345
- installationStore = getStore2("default", "channelInstallation").store;
8317
+ const bindingStore = getStore2("default", "channelBinding").store;
8318
+ const installationStore = getStore2("default", "channelInstallation").store;
8346
8319
  setBindingRegistry(bindingStore);
8347
8320
  const router = new MessageRouter({
8348
8321
  middlewares: [
@@ -8374,6 +8347,9 @@ var start = async (config) => {
8374
8347
  logger4.info("Menu registry initialized");
8375
8348
  } catch {
8376
8349
  }
8350
+ if (channelDeps?.router) {
8351
+ setChannelControllerDeps({ adapterRegistry, router: channelDeps.router });
8352
+ }
8377
8353
  registerLatticeRoutes(app, channelDeps);
8378
8354
  if (!sandboxLatticeManager2.hasLattice("default")) {
8379
8355
  sandboxLatticeManager2.registerLattice("default", getConfiguredSandboxProvider());