@clawos-dev/clawd 0.2.297 → 0.2.298
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/cli.cjs +42 -128
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -52021,15 +52021,14 @@ function createLarkBotCloudClient(opts) {
|
|
|
52021
52021
|
const json = await request("POST", "/api/lark-bot/events/claim");
|
|
52022
52022
|
return json.items ?? [];
|
|
52023
52023
|
},
|
|
52024
|
-
async fetchResource(appId, messageId, fileKey, maxBytes
|
|
52024
|
+
async fetchResource(appId, messageId, fileKey, maxBytes) {
|
|
52025
52025
|
const ac = new AbortController();
|
|
52026
52026
|
const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? 15e3);
|
|
52027
52027
|
const qs = new URLSearchParams({
|
|
52028
52028
|
appId,
|
|
52029
52029
|
messageId,
|
|
52030
52030
|
fileKey,
|
|
52031
|
-
...maxBytes ? { maxBytes: String(maxBytes) } : {}
|
|
52032
|
-
...type ? { type } : {}
|
|
52031
|
+
...maxBytes ? { maxBytes: String(maxBytes) } : {}
|
|
52033
52032
|
}).toString();
|
|
52034
52033
|
let res;
|
|
52035
52034
|
try {
|
|
@@ -52064,7 +52063,6 @@ var import_node_path28 = __toESM(require("path"), 1);
|
|
|
52064
52063
|
init_protocol();
|
|
52065
52064
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
52066
52065
|
var DEFAULT_TURN_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
52067
|
-
var DEBOUNCE_MS = 1e3;
|
|
52068
52066
|
var MAX_IMAGE_BYTES = 8 * 1024 * 1024;
|
|
52069
52067
|
var EXT_BY_MIME = {
|
|
52070
52068
|
"image/png": "png",
|
|
@@ -52074,35 +52072,27 @@ var EXT_BY_MIME = {
|
|
|
52074
52072
|
};
|
|
52075
52073
|
var IMAGE_OVERSIZE_TEXT = "[\u56FE\u7247\u6D88\u606F\uFF0C\u8D85\u51FA\u5927\u5C0F\u9650\u5236]";
|
|
52076
52074
|
var IMAGE_UNAVAILABLE_TEXT = "[\u56FE\u7247\u6D88\u606F\uFF0C\u6682\u4E0D\u652F\u6301\u67E5\u770B]";
|
|
52077
|
-
var MAX_FILE_BYTES = 20 * 1024 * 1024;
|
|
52078
|
-
var FILE_OVERSIZE_TEXT = (name) => `[\u6587\u4EF6: ${name}\uFF0C\u8D85\u51FA\u5927\u5C0F\u9650\u5236]`;
|
|
52079
|
-
var FILE_UNAVAILABLE_TEXT = (name) => `[\u6587\u4EF6: ${name}\uFF0C\u62C9\u53D6\u5931\u8D25]`;
|
|
52080
52075
|
function safeMediaName(raw) {
|
|
52081
52076
|
const cleaned = raw.replace(/[^a-zA-Z0-9_\-.]/g, "_").replace(/^\.+/, (d) => "_".repeat(d.length));
|
|
52082
52077
|
return (cleaned || "msg").replace(/\.\./g, "__");
|
|
52083
52078
|
}
|
|
52084
|
-
function safeAttachmentName(raw) {
|
|
52085
|
-
const cleaned = raw.replace(/[/\\\u0000-\u001f]/g, "_").replace(/\.\./g, "__").replace(/^\.+/, (d) => "_".repeat(d.length));
|
|
52086
|
-
if (!cleaned) return "file";
|
|
52087
|
-
if (cleaned.length <= 100) return cleaned;
|
|
52088
|
-
const dot = cleaned.lastIndexOf(".");
|
|
52089
|
-
const ext = dot > 0 && cleaned.length - dot <= 20 ? cleaned.slice(dot) : "";
|
|
52090
|
-
return cleaned.slice(0, 100 - ext.length) + ext;
|
|
52091
|
-
}
|
|
52092
52079
|
function createLarkChatRouter(deps) {
|
|
52093
52080
|
const timeoutMs = deps.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;
|
|
52094
52081
|
const replyDelays = deps.replyRetryDelaysMs ?? [2e3, 8e3, 3e4];
|
|
52095
52082
|
const sleep2 = deps.sleepImpl ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
52096
|
-
const debounceMs = deps.debounceMs ?? DEBOUNCE_MS;
|
|
52097
52083
|
const queues = /* @__PURE__ */ new Map();
|
|
52098
52084
|
const activity = /* @__PURE__ */ new Map();
|
|
52099
|
-
const
|
|
52100
|
-
|
|
52085
|
+
const runOne = async (env) => {
|
|
52086
|
+
if (!env.messageId) {
|
|
52087
|
+
deps.logger?.warn(`larkBot chat-router: message envelope missing messageId, drop ${env.eventId}`);
|
|
52088
|
+
return;
|
|
52089
|
+
}
|
|
52090
|
+
const speaker = env.senderName || env.senderOpenId || "\u672A\u77E5\u6210\u5458";
|
|
52101
52091
|
const imageLines = [];
|
|
52102
52092
|
for (const [i, key] of (env.imageKeys ?? []).entries()) {
|
|
52103
52093
|
try {
|
|
52104
52094
|
if (!deps.fetchResource || !deps.mediaRootFor) throw new Error("resource pipeline not wired");
|
|
52105
|
-
const r = await deps.fetchResource(env.appId, env.messageId, key, MAX_IMAGE_BYTES
|
|
52095
|
+
const r = await deps.fetchResource(env.appId, env.messageId, key, MAX_IMAGE_BYTES);
|
|
52106
52096
|
if (r.data.byteLength > MAX_IMAGE_BYTES) {
|
|
52107
52097
|
deps.logger?.warn(`larkBot image oversize ${key}: ${r.data.byteLength}B`);
|
|
52108
52098
|
imageLines.push(IMAGE_OVERSIZE_TEXT);
|
|
@@ -52124,69 +52114,25 @@ function createLarkChatRouter(deps) {
|
|
|
52124
52114
|
imageLines.push(IMAGE_UNAVAILABLE_TEXT);
|
|
52125
52115
|
}
|
|
52126
52116
|
}
|
|
52127
|
-
const
|
|
52128
|
-
|
|
52129
|
-
try {
|
|
52130
|
-
if (!deps.fetchResource || !deps.mediaRootFor) throw new Error("resource pipeline not wired");
|
|
52131
|
-
const r = await deps.fetchResource(env.appId, env.messageId, f.key, MAX_FILE_BYTES, "file");
|
|
52132
|
-
if (r.data.byteLength > MAX_FILE_BYTES) {
|
|
52133
|
-
deps.logger?.warn(`larkBot file oversize ${f.key}: ${r.data.byteLength}B`);
|
|
52134
|
-
fileLines.push(FILE_OVERSIZE_TEXT(f.name));
|
|
52135
|
-
continue;
|
|
52136
|
-
}
|
|
52137
|
-
const dir = deps.mediaRootFor(env.chatId);
|
|
52138
|
-
import_node_fs27.default.mkdirSync(dir, { recursive: true });
|
|
52139
|
-
const p2 = import_node_path28.default.join(dir, `${safeMediaName(env.messageId)}-${i}-${safeAttachmentName(f.name)}`);
|
|
52140
|
-
import_node_fs27.default.writeFileSync(p2, r.data);
|
|
52141
|
-
fileLines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
52142
|
-
} catch (err) {
|
|
52143
|
-
deps.logger?.warn(`larkBot file fetch failed ${f.key}: ${err.message}`);
|
|
52144
|
-
fileLines.push(FILE_UNAVAILABLE_TEXT(f.name));
|
|
52145
|
-
}
|
|
52146
|
-
}
|
|
52147
|
-
return [env.text?.trim(), ...imageLines, ...fileLines].filter(Boolean).join("\n");
|
|
52148
|
-
};
|
|
52149
|
-
const quoteAnnotation = (env, i, idxByMessageId) => {
|
|
52150
|
-
if (!env.parentMessageId) return void 0;
|
|
52151
|
-
const j = idxByMessageId.get(env.parentMessageId);
|
|
52152
|
-
if (j === void 0) return "[\u56DE\u590D\u66F4\u65E9\u7684\u4E00\u6761\u6D88\u606F]";
|
|
52153
|
-
if (j === i - 1) return void 0;
|
|
52154
|
-
return `[\u56DE\u590D\u7B2C${j + 1}\u6761]`;
|
|
52155
|
-
};
|
|
52156
|
-
const runBatch = async (batchEnvs) => {
|
|
52157
|
-
const envs = batchEnvs.filter((e) => {
|
|
52158
|
-
if (e.messageId) return true;
|
|
52159
|
-
deps.logger?.warn(`larkBot chat-router: message envelope missing messageId, drop ${e.eventId}`);
|
|
52160
|
-
return false;
|
|
52161
|
-
});
|
|
52162
|
-
if (envs.length === 0) return;
|
|
52163
|
-
const last = envs[envs.length - 1];
|
|
52164
|
-
const speaker = last.senderName || last.senderOpenId || "\u672A\u77E5\u6210\u5458";
|
|
52165
|
-
const idxByMessageId = new Map(envs.map((e, i) => [e.messageId, i]));
|
|
52166
|
-
const sections = [];
|
|
52167
|
-
for (const [i, env] of envs.entries()) {
|
|
52168
|
-
const body2 = await buildSection(env);
|
|
52169
|
-
const section = [quoteAnnotation(env, i, idxByMessageId), body2].filter(Boolean).join("\n");
|
|
52170
|
-
if (section) sections.push(section);
|
|
52171
|
-
}
|
|
52172
|
-
const body = sections.join("\n") || "[\u975E\u6587\u672C\u6D88\u606F]";
|
|
52117
|
+
const rawBody = [env.text?.trim(), ...imageLines].filter(Boolean).join("\n");
|
|
52118
|
+
const body = rawBody || "[\u975E\u6587\u672C\u6D88\u606F]";
|
|
52173
52119
|
const text = `${body}
|
|
52174
52120
|
|
|
52175
52121
|
${formatLarkSpeakerReminder(speaker)}`;
|
|
52176
52122
|
const turn = deps.manager.runLarkChatTurn({
|
|
52177
|
-
personaId:
|
|
52178
|
-
chatId:
|
|
52179
|
-
chatName:
|
|
52180
|
-
chatType:
|
|
52181
|
-
senderOpenId:
|
|
52182
|
-
senderName:
|
|
52123
|
+
personaId: env.personaId,
|
|
52124
|
+
chatId: env.chatId,
|
|
52125
|
+
chatName: env.chatName,
|
|
52126
|
+
chatType: env.chatType ?? "group",
|
|
52127
|
+
senderOpenId: env.senderOpenId ?? "",
|
|
52128
|
+
senderName: env.senderName ?? env.senderOpenId ?? "\u672A\u77E5\u6210\u5458",
|
|
52183
52129
|
text
|
|
52184
52130
|
});
|
|
52185
|
-
activity.set(
|
|
52186
|
-
chatId:
|
|
52187
|
-
chatName:
|
|
52131
|
+
activity.set(env.chatId, {
|
|
52132
|
+
chatId: env.chatId,
|
|
52133
|
+
chatName: env.chatName,
|
|
52188
52134
|
lastActiveAt: Date.now(),
|
|
52189
|
-
personaId:
|
|
52135
|
+
personaId: env.personaId
|
|
52190
52136
|
});
|
|
52191
52137
|
let timedOut = false;
|
|
52192
52138
|
let timer;
|
|
@@ -52206,78 +52152,46 @@ ${formatLarkSpeakerReminder(speaker)}`;
|
|
|
52206
52152
|
const replyText = "ok" in result && result.ok ? result.replyText : ERROR_REPLY_TEXT;
|
|
52207
52153
|
if (!("ok" in result)) {
|
|
52208
52154
|
deps.logger?.warn(
|
|
52209
|
-
`larkBot turn ${timedOut ? "timeout" : "error"} (${
|
|
52155
|
+
`larkBot turn ${timedOut ? "timeout" : "error"} (${env.chatId}): ${result.error}`
|
|
52210
52156
|
);
|
|
52211
52157
|
}
|
|
52212
|
-
const absorbed = envs.slice(0, -1).map((e) => e.eventId);
|
|
52213
52158
|
for (let attempt = 0; attempt <= replyDelays.length; attempt++) {
|
|
52214
52159
|
if (attempt > 0) await sleep2(replyDelays[attempt - 1]);
|
|
52215
52160
|
try {
|
|
52216
52161
|
await deps.cloud.reply({
|
|
52217
|
-
appId:
|
|
52218
|
-
chatId:
|
|
52219
|
-
replyToMessageId:
|
|
52162
|
+
appId: env.appId,
|
|
52163
|
+
chatId: env.chatId,
|
|
52164
|
+
replyToMessageId: env.messageId,
|
|
52220
52165
|
text: replyText,
|
|
52221
|
-
eventId:
|
|
52222
|
-
...absorbed.length > 0 ? { absorbedEventIds: absorbed } : {}
|
|
52166
|
+
eventId: env.eventId
|
|
52223
52167
|
});
|
|
52224
52168
|
return;
|
|
52225
52169
|
} catch (err) {
|
|
52226
52170
|
deps.logger?.warn(
|
|
52227
|
-
`larkBot reply attempt ${attempt + 1} failed (${
|
|
52171
|
+
`larkBot reply attempt ${attempt + 1} failed (${env.chatId}): ${err.message}`
|
|
52228
52172
|
);
|
|
52229
52173
|
}
|
|
52230
52174
|
}
|
|
52231
52175
|
};
|
|
52232
|
-
const enqueueBatch = (batchEnvs) => {
|
|
52233
|
-
const chatId = batchEnvs[0].chatId;
|
|
52234
|
-
const prev = queues.get(chatId) ?? Promise.resolve();
|
|
52235
|
-
const next = prev.then(
|
|
52236
|
-
() => runBatch(batchEnvs).catch(
|
|
52237
|
-
(err) => deps.logger?.warn(`larkBot chat-router runBatch failed: ${err.message}`)
|
|
52238
|
-
)
|
|
52239
|
-
);
|
|
52240
|
-
queues.set(chatId, next);
|
|
52241
|
-
void next.finally(() => {
|
|
52242
|
-
if (queues.get(chatId) === next) queues.delete(chatId);
|
|
52243
|
-
});
|
|
52244
|
-
};
|
|
52245
|
-
const flushPending = (chatId) => {
|
|
52246
|
-
const batch = pending.get(chatId);
|
|
52247
|
-
if (!batch) return;
|
|
52248
|
-
clearTimeout(batch.timer);
|
|
52249
|
-
pending.delete(chatId);
|
|
52250
|
-
enqueueBatch(batch.envelopes);
|
|
52251
|
-
};
|
|
52252
52176
|
return {
|
|
52253
52177
|
handleEnvelope(env) {
|
|
52254
52178
|
if (env.type === "bot_removed") {
|
|
52255
52179
|
deps.store.addRemovedChat(env.personaId, env.chatId);
|
|
52256
52180
|
activity.delete(env.chatId);
|
|
52257
52181
|
queues.delete(env.chatId);
|
|
52258
|
-
const p2 = pending.get(env.chatId);
|
|
52259
|
-
if (p2) {
|
|
52260
|
-
clearTimeout(p2.timer);
|
|
52261
|
-
pending.delete(env.chatId);
|
|
52262
|
-
}
|
|
52263
52182
|
deps.logger?.info(`larkBot removed from chat ${env.chatId} (persona ${env.personaId})`);
|
|
52264
52183
|
return;
|
|
52265
52184
|
}
|
|
52266
|
-
const
|
|
52267
|
-
const
|
|
52268
|
-
|
|
52269
|
-
|
|
52270
|
-
|
|
52271
|
-
|
|
52272
|
-
|
|
52273
|
-
|
|
52274
|
-
|
|
52275
|
-
|
|
52276
|
-
envelopes: [env],
|
|
52277
|
-
senderOpenId: sender,
|
|
52278
|
-
timer: setTimeout(() => flushPending(env.chatId), debounceMs)
|
|
52279
|
-
});
|
|
52280
|
-
}
|
|
52185
|
+
const prev = queues.get(env.chatId) ?? Promise.resolve();
|
|
52186
|
+
const next = prev.then(
|
|
52187
|
+
() => runOne(env).catch(
|
|
52188
|
+
(err) => deps.logger?.warn(`larkBot chat-router runOne failed: ${err.message}`)
|
|
52189
|
+
)
|
|
52190
|
+
);
|
|
52191
|
+
queues.set(env.chatId, next);
|
|
52192
|
+
void next.finally(() => {
|
|
52193
|
+
if (queues.get(env.chatId) === next) queues.delete(env.chatId);
|
|
52194
|
+
});
|
|
52281
52195
|
},
|
|
52282
52196
|
listLarkSessions(personaId2) {
|
|
52283
52197
|
return [...activity.values()].filter((a) => a.personaId === personaId2).map((a) => ({ chatId: a.chatId, chatName: a.chatName, lastActiveAt: a.lastActiveAt }));
|
|
@@ -53020,7 +52934,7 @@ var import_node_fs28 = __toESM(require("fs"), 1);
|
|
|
53020
52934
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
53021
52935
|
var import_node_path30 = __toESM(require("path"), 1);
|
|
53022
52936
|
init_protocol();
|
|
53023
|
-
var
|
|
52937
|
+
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
53024
52938
|
function resolveInsideCwd(cwd, subpath) {
|
|
53025
52939
|
const absCwd = import_node_path30.default.resolve(cwd);
|
|
53026
52940
|
const joined = import_node_path30.default.resolve(absCwd, subpath ?? ".");
|
|
@@ -53076,8 +52990,8 @@ var WorkspaceBrowser = class {
|
|
|
53076
52990
|
if (!st.isFile()) {
|
|
53077
52991
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
53078
52992
|
}
|
|
53079
|
-
if (st.size >
|
|
53080
|
-
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${
|
|
52993
|
+
if (st.size > MAX_FILE_BYTES) {
|
|
52994
|
+
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
53081
52995
|
}
|
|
53082
52996
|
const buf = import_node_fs28.default.readFileSync(full);
|
|
53083
52997
|
const isBinary = buf.includes(0);
|
|
@@ -59036,7 +58950,7 @@ function computeMethodAccess(args) {
|
|
|
59036
58950
|
}
|
|
59037
58951
|
|
|
59038
58952
|
// src/version.ts
|
|
59039
|
-
var version = "0.2.
|
|
58953
|
+
var version = "0.2.298".length > 0 ? "0.2.298" : "dev";
|
|
59040
58954
|
|
|
59041
58955
|
// src/cli-probe/probe.ts
|
|
59042
58956
|
var fs56 = __toESM(require("fs"), 1);
|
|
@@ -63054,7 +62968,7 @@ async function startDaemon(config) {
|
|
|
63054
62968
|
manager,
|
|
63055
62969
|
cloud: larkBotCloud,
|
|
63056
62970
|
store: larkBotStore,
|
|
63057
|
-
fetchResource: (appId, messageId, fileKey, maxBytes
|
|
62971
|
+
fetchResource: (appId, messageId, fileKey, maxBytes) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes),
|
|
63058
62972
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
63059
62973
|
mediaRootFor: (chatId) => import_node_path65.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
63060
62974
|
logger: {
|