@vibe-lark/larkpal 0.1.79 → 0.1.81

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.
Files changed (2) hide show
  1. package/dist/main.mjs +34 -3
  2. package/package.json +1 -1
package/dist/main.mjs CHANGED
@@ -22,7 +22,6 @@ import { pipeline } from "node:stream/promises";
22
22
  import { PassThrough, Readable, Transform } from "node:stream";
23
23
  import express, { Router } from "express";
24
24
  import Busboy from "busboy";
25
- import { EventEmitter as EventEmitter$1 } from "events";
26
25
  import cron from "node-cron";
27
26
  import * as Lark from "@larksuiteoapi/node-sdk";
28
27
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
@@ -4583,6 +4582,8 @@ async function handleSessionFileUpload(req, res, messageStore) {
4583
4582
  traceId,
4584
4583
  runtimeEventType: "session-file-attached",
4585
4584
  fileName: file.fileName,
4585
+ originalName: file.originalName,
4586
+ displayName: file.displayName,
4586
4587
  relativePath: file.relativePath,
4587
4588
  mimeType: file.mimeType,
4588
4589
  size: file.size,
@@ -4613,6 +4614,7 @@ function parseSessionFileUpload(req, sessionId) {
4613
4614
  return new Promise((resolvePromise, rejectPromise) => {
4614
4615
  const busboy = Busboy({
4615
4616
  headers: req.headers,
4617
+ defParamCharset: "utf8",
4616
4618
  limits: {
4617
4619
  fileSize: getSessionFileUploadMaxBytes(),
4618
4620
  files: 1
@@ -4676,6 +4678,7 @@ function writeSessionFile(sessionId, params) {
4676
4678
  return new Promise((resolvePromise, rejectPromise) => {
4677
4679
  const uploadsDir = resolve(resolveAgentCwd(sessionId), "uploads");
4678
4680
  const fileName = buildSafeUploadFileName(params.originalName);
4681
+ const originalName = buildDisplayUploadFileName(params.originalName);
4679
4682
  const destination = resolve(uploadsDir, fileName);
4680
4683
  const relativePath = `uploads/${fileName}`;
4681
4684
  const maxBytes = getSessionFileUploadMaxBytes();
@@ -4713,6 +4716,8 @@ function writeSessionFile(sessionId, params) {
4713
4716
  sessionId,
4714
4717
  kind: "session-file",
4715
4718
  fileName,
4719
+ originalName,
4720
+ displayName: originalName,
4716
4721
  relativePath,
4717
4722
  uri: `session-file://${relativePath}`,
4718
4723
  mimeType: params.mimeType,
@@ -4737,6 +4742,9 @@ function buildSafeUploadFileName(originalName) {
4737
4742
  const stem = basename(base, extname(base)).replace(/[^A-Za-z0-9._-]/g, "_").replace(/^\.+$/, "").slice(0, 80) || "upload";
4738
4743
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}-${stem}${extension}`;
4739
4744
  }
4745
+ function buildDisplayUploadFileName(originalName) {
4746
+ return basename(originalName).replace(/[\0\r\n]/g, "_").trim() || "upload.bin";
4747
+ }
4740
4748
  function isPathInside(parent, child) {
4741
4749
  const path = relative(parent, child);
4742
4750
  return path !== "" && !path.startsWith("..") && !isAbsolute(path);
@@ -7785,13 +7793,17 @@ const sessionNoReplyFlags = /* @__PURE__ */ new Map();
7785
7793
  /** TTL: 30 分钟 */
7786
7794
  const TTL_MS = 1800 * 1e3;
7787
7795
  /** 定期清理过期的 pending requests(每 5 分钟检查一次) */
7788
- setInterval(() => {
7796
+ function cleanupExpiredPendingRequests() {
7789
7797
  const now = Date.now();
7790
7798
  let cleaned = 0;
7791
7799
  for (const [id, req] of pendingRequests) if (now - req.createdAt > TTL_MS) {
7792
7800
  pendingRequests.delete(id);
7793
7801
  cleaned++;
7794
7802
  }
7803
+ return cleaned;
7804
+ }
7805
+ setInterval(() => {
7806
+ const cleaned = cleanupExpiredPendingRequests();
7795
7807
  if (cleaned > 0) logger$4.info("TTL cleanup completed", {
7796
7808
  cleaned,
7797
7809
  remaining: pendingRequests.size
@@ -7802,7 +7814,7 @@ setInterval(() => {
7802
7814
  * 事件名: `callback:${sessionId}`,payload 为 PendingMcpRequest。
7803
7815
  * 用于 dispatch-cc 订阅并在收到 ask_user/request_permission 回调时发送飞书卡片。
7804
7816
  */
7805
- const onMcpCallback = new EventEmitter$1();
7817
+ const onMcpCallback = new EventEmitter();
7806
7818
  onMcpCallback.setMaxListeners(100);
7807
7819
  /**
7808
7820
  * 将 result 存入对应的 pending request
@@ -7934,6 +7946,25 @@ function createMcpCallbackRouter() {
7934
7946
  requestId
7935
7947
  });
7936
7948
  });
7949
+ router.get("/pending", (req, res) => {
7950
+ const sessionId = typeof req.query.session_id === "string" ? req.query.session_id : typeof req.query.sessionId === "string" ? req.query.sessionId : void 0;
7951
+ const cleaned = cleanupExpiredPendingRequests();
7952
+ const now = Date.now();
7953
+ const requests = [...pendingRequests.values()].filter((pending) => pending.result === void 0).filter((pending) => !sessionId || pending.sessionId === sessionId).map((pending) => ({
7954
+ requestId: pending.requestId,
7955
+ tool: pending.tool,
7956
+ sessionId: pending.sessionId,
7957
+ params: pending.params,
7958
+ createdAt: pending.createdAt,
7959
+ waitingMs: now - pending.createdAt
7960
+ }));
7961
+ logger$4.debug("pending requests listed", {
7962
+ sessionId,
7963
+ count: requests.length,
7964
+ cleaned
7965
+ });
7966
+ res.json({ requests });
7967
+ });
7937
7968
  router.get("/resolve/:requestId", (req, res) => {
7938
7969
  const requestId = req.params.requestId;
7939
7970
  logger$4.debug("resolve poll", { requestId });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-lark/larkpal",
3
- "version": "0.1.79",
3
+ "version": "0.1.81",
4
4
  "description": "LarkPal - Lark/Feishu bot service",
5
5
  "type": "module",
6
6
  "main": "./dist/main.mjs",