@workclaw/openclaw-workchat 1.0.4 → 1.1.0
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/index.js +819 -282
- package/index.ts +7 -0
- package/package.json +1 -1
- package/src/api/api.ts +74 -7
- package/src/api/session-guard.ts +84 -0
- package/src/api/types.ts +18 -3
- package/src/auth/accounts.ts +108 -28
- package/src/auth/login-qr.ts +15 -22
- package/src/channel.ts +87 -11
- package/src/messaging/inbound.ts +56 -2
- package/src/messaging/process-message.ts +135 -29
- package/src/messaging/send-media.ts +201 -0
- package/src/messaging/send.ts +5 -0
- package/src/storage/seen-msgids.ts +79 -0
package/index.js
CHANGED
|
@@ -46,7 +46,8 @@ var init_types = __esm({
|
|
|
46
46
|
DEFAULT_WS_URL = "wss://workbrain.cn/backend-api/open-apis/connect";
|
|
47
47
|
WorkChatMsgType = {
|
|
48
48
|
Text: "1",
|
|
49
|
-
|
|
49
|
+
Image: "2",
|
|
50
|
+
Audio: "110"
|
|
50
51
|
};
|
|
51
52
|
RequestDefaults = {
|
|
52
53
|
TimeoutMs: 3e4
|
|
@@ -279,7 +280,8 @@ __export(accounts_exports, {
|
|
|
279
280
|
listIndexedWorkChatAccountIds: () => listIndexedWorkChatAccountIds,
|
|
280
281
|
listWorkChatAccountIds: () => listWorkChatAccountIds,
|
|
281
282
|
loadWorkChatAccount: () => loadWorkChatAccount,
|
|
282
|
-
|
|
283
|
+
migrateLegacyDefaultWorkChatAccount: () => migrateLegacyDefaultWorkChatAccount,
|
|
284
|
+
pruneOtherWorkChatAccounts: () => pruneOtherWorkChatAccounts,
|
|
283
285
|
registerWorkChatAccountId: () => registerWorkChatAccountId,
|
|
284
286
|
removeWorkChatAccountBinding: () => removeWorkChatAccountBinding,
|
|
285
287
|
resolveWorkChatAccount: () => resolveWorkChatAccount,
|
|
@@ -296,6 +298,9 @@ function resolveAccountIndexPath() {
|
|
|
296
298
|
return path4.join(resolveWorkChatStateDir(), "accounts.json");
|
|
297
299
|
}
|
|
298
300
|
function listIndexedWorkChatAccountIds() {
|
|
301
|
+
return readAccountIndex();
|
|
302
|
+
}
|
|
303
|
+
function readAccountIndex() {
|
|
299
304
|
const filePath = resolveAccountIndexPath();
|
|
300
305
|
try {
|
|
301
306
|
if (!fs3.existsSync(filePath)) return [];
|
|
@@ -306,19 +311,23 @@ function listIndexedWorkChatAccountIds() {
|
|
|
306
311
|
return [];
|
|
307
312
|
}
|
|
308
313
|
}
|
|
309
|
-
function
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
314
|
+
async function updateAccountIndex(mutator) {
|
|
315
|
+
const run = indexUpdateChain.then(() => {
|
|
316
|
+
const filePath = resolveAccountIndexPath();
|
|
317
|
+
fs3.mkdirSync(path4.dirname(filePath), { recursive: true });
|
|
318
|
+
const updated = mutator(readAccountIndex());
|
|
319
|
+
fs3.writeFileSync(filePath, JSON.stringify(updated, null, 2), "utf-8");
|
|
320
|
+
});
|
|
321
|
+
indexUpdateChain = run.then(() => void 0, () => void 0);
|
|
322
|
+
await run;
|
|
315
323
|
}
|
|
316
|
-
function
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
324
|
+
async function registerWorkChatAccountId(accountId) {
|
|
325
|
+
await updateAccountIndex(
|
|
326
|
+
(ids) => ids.includes(accountId) ? ids : [...ids, accountId]
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
async function unregisterWorkChatAccountId(accountId) {
|
|
330
|
+
await updateAccountIndex((ids) => ids.filter((id) => id !== accountId));
|
|
322
331
|
}
|
|
323
332
|
function resolveAccountsDir() {
|
|
324
333
|
return path4.join(resolveWorkChatStateDir(), "accounts");
|
|
@@ -355,14 +364,14 @@ function saveWorkChatAccount(accountId, update) {
|
|
|
355
364
|
} catch {
|
|
356
365
|
}
|
|
357
366
|
}
|
|
358
|
-
function clearWorkChatAccount(accountId) {
|
|
367
|
+
async function clearWorkChatAccount(accountId) {
|
|
359
368
|
const filePath = resolveAccountPath(accountId);
|
|
360
369
|
try {
|
|
361
370
|
if (fs3.existsSync(filePath)) fs3.unlinkSync(filePath);
|
|
362
371
|
} catch (err) {
|
|
363
372
|
logger.warn(`clearWorkChatAccount: failed to remove ${filePath}: ${String(err)}`);
|
|
364
373
|
}
|
|
365
|
-
unregisterWorkChatAccountId(accountId);
|
|
374
|
+
await unregisterWorkChatAccountId(accountId);
|
|
366
375
|
}
|
|
367
376
|
async function removeWorkChatAccountBinding(accountId) {
|
|
368
377
|
clearWorkChatAccount(accountId);
|
|
@@ -378,21 +387,57 @@ async function removeWorkChatAccountBinding(accountId) {
|
|
|
378
387
|
logger.warn(`removeWorkChatAccountBinding: channel reload trigger failed: ${String(err)}`);
|
|
379
388
|
}
|
|
380
389
|
}
|
|
381
|
-
async function
|
|
390
|
+
async function pruneOtherWorkChatAccounts(keepAccountId) {
|
|
391
|
+
const keep = keepAccountId.trim();
|
|
382
392
|
const removed = [];
|
|
383
393
|
for (const accountId of listIndexedWorkChatAccountIds()) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
removed
|
|
389
|
-
|
|
390
|
-
`pruneStaleWorkChatAccounts: removed account=${accountId} agent=${storedAgentId} (superseded by agent=${keepAgentId})`
|
|
391
|
-
);
|
|
392
|
-
}
|
|
394
|
+
if (accountId === keep) continue;
|
|
395
|
+
await removeWorkChatAccountBinding(accountId);
|
|
396
|
+
removed.push(accountId);
|
|
397
|
+
logger.info(
|
|
398
|
+
`pruneOtherWorkChatAccounts: removed account=${accountId} (superseded by ${keep})`
|
|
399
|
+
);
|
|
393
400
|
}
|
|
394
401
|
return removed;
|
|
395
402
|
}
|
|
403
|
+
async function migrateLegacyDefaultWorkChatAccount() {
|
|
404
|
+
const ids = listIndexedWorkChatAccountIds();
|
|
405
|
+
if (!ids.includes("default")) return false;
|
|
406
|
+
const data = loadWorkChatAccount("default");
|
|
407
|
+
const agentId = data?.agentId?.trim();
|
|
408
|
+
if (!agentId) return false;
|
|
409
|
+
const targetId = `agent-${agentId}`;
|
|
410
|
+
if (!ids.includes(targetId)) {
|
|
411
|
+
saveWorkChatAccount(targetId, { ...data });
|
|
412
|
+
}
|
|
413
|
+
try {
|
|
414
|
+
const { readFrameworkAllowFromList: readFrameworkAllowFromList2, registerUserInFrameworkStore: registerUserInFrameworkStore2 } = await Promise.resolve().then(() => (init_pairing(), pairing_exports));
|
|
415
|
+
for (const userId of readFrameworkAllowFromList2("default")) {
|
|
416
|
+
await registerUserInFrameworkStore2({ accountId: targetId, userId });
|
|
417
|
+
}
|
|
418
|
+
} catch (err) {
|
|
419
|
+
logger.warn(`migrateLegacyDefaultWorkChatAccount: allowFrom move failed: ${String(err)}`);
|
|
420
|
+
}
|
|
421
|
+
await updateAccountIndex((existing) => {
|
|
422
|
+
const next = existing.filter((id) => id !== "default" && id !== targetId);
|
|
423
|
+
next.push(targetId);
|
|
424
|
+
return next;
|
|
425
|
+
});
|
|
426
|
+
try {
|
|
427
|
+
fs3.rmSync(path4.join(resolveWorkChatStateDir(), "accounts", "default.json"), { force: true });
|
|
428
|
+
} catch {
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
const { clearFrameworkAllowFromList: clearFrameworkAllowFromList2 } = await Promise.resolve().then(() => (init_pairing(), pairing_exports));
|
|
432
|
+
clearFrameworkAllowFromList2("default");
|
|
433
|
+
} catch (err) {
|
|
434
|
+
logger.warn(`migrateLegacyDefaultWorkChatAccount: allowFrom cleanup failed: ${String(err)}`);
|
|
435
|
+
}
|
|
436
|
+
logger.info(
|
|
437
|
+
`migrateLegacyDefaultWorkChatAccount: renamed default -> ${targetId} (agent=${agentId})`
|
|
438
|
+
);
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
396
441
|
function listWorkChatAccountIds(_cfg) {
|
|
397
442
|
return listIndexedWorkChatAccountIds();
|
|
398
443
|
}
|
|
@@ -442,12 +487,14 @@ async function triggerWorkChatChannelReload() {
|
|
|
442
487
|
logger.warn(`triggerWorkChatChannelReload: failed to update config: ${String(err)}`);
|
|
443
488
|
}
|
|
444
489
|
}
|
|
490
|
+
var indexUpdateChain;
|
|
445
491
|
var init_accounts = __esm({
|
|
446
492
|
"src/auth/accounts.ts"() {
|
|
447
493
|
"use strict";
|
|
448
494
|
init_types();
|
|
449
495
|
init_state_dir();
|
|
450
496
|
init_logger();
|
|
497
|
+
indexUpdateChain = Promise.resolve();
|
|
451
498
|
}
|
|
452
499
|
});
|
|
453
500
|
|
|
@@ -1559,14 +1606,14 @@ var require_util = __commonJS({
|
|
|
1559
1606
|
}
|
|
1560
1607
|
const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
|
|
1561
1608
|
let origin = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
|
|
1562
|
-
let
|
|
1609
|
+
let path8 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
|
|
1563
1610
|
if (origin[origin.length - 1] === "/") {
|
|
1564
1611
|
origin = origin.slice(0, origin.length - 1);
|
|
1565
1612
|
}
|
|
1566
|
-
if (
|
|
1567
|
-
|
|
1613
|
+
if (path8 && path8[0] !== "/") {
|
|
1614
|
+
path8 = `/${path8}`;
|
|
1568
1615
|
}
|
|
1569
|
-
return new URL(`${origin}${
|
|
1616
|
+
return new URL(`${origin}${path8}`);
|
|
1570
1617
|
}
|
|
1571
1618
|
if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
|
|
1572
1619
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -2387,9 +2434,9 @@ var require_diagnostics = __commonJS({
|
|
|
2387
2434
|
"undici:client:sendHeaders",
|
|
2388
2435
|
(evt) => {
|
|
2389
2436
|
const {
|
|
2390
|
-
request: { method, path:
|
|
2437
|
+
request: { method, path: path8, origin }
|
|
2391
2438
|
} = evt;
|
|
2392
|
-
debugLog("sending request to %s %s%s", method, origin,
|
|
2439
|
+
debugLog("sending request to %s %s%s", method, origin, path8);
|
|
2393
2440
|
}
|
|
2394
2441
|
);
|
|
2395
2442
|
}
|
|
@@ -2407,14 +2454,14 @@ var require_diagnostics = __commonJS({
|
|
|
2407
2454
|
"undici:request:headers",
|
|
2408
2455
|
(evt) => {
|
|
2409
2456
|
const {
|
|
2410
|
-
request: { method, path:
|
|
2457
|
+
request: { method, path: path8, origin },
|
|
2411
2458
|
response: { statusCode }
|
|
2412
2459
|
} = evt;
|
|
2413
2460
|
debugLog(
|
|
2414
2461
|
"received response to %s %s%s - HTTP %d",
|
|
2415
2462
|
method,
|
|
2416
2463
|
origin,
|
|
2417
|
-
|
|
2464
|
+
path8,
|
|
2418
2465
|
statusCode
|
|
2419
2466
|
);
|
|
2420
2467
|
}
|
|
@@ -2423,23 +2470,23 @@ var require_diagnostics = __commonJS({
|
|
|
2423
2470
|
"undici:request:trailers",
|
|
2424
2471
|
(evt) => {
|
|
2425
2472
|
const {
|
|
2426
|
-
request: { method, path:
|
|
2473
|
+
request: { method, path: path8, origin }
|
|
2427
2474
|
} = evt;
|
|
2428
|
-
debugLog("trailers received from %s %s%s", method, origin,
|
|
2475
|
+
debugLog("trailers received from %s %s%s", method, origin, path8);
|
|
2429
2476
|
}
|
|
2430
2477
|
);
|
|
2431
2478
|
diagnosticsChannel.subscribe(
|
|
2432
2479
|
"undici:request:error",
|
|
2433
2480
|
(evt) => {
|
|
2434
2481
|
const {
|
|
2435
|
-
request: { method, path:
|
|
2482
|
+
request: { method, path: path8, origin },
|
|
2436
2483
|
error: error62
|
|
2437
2484
|
} = evt;
|
|
2438
2485
|
debugLog(
|
|
2439
2486
|
"request to %s %s%s errored - %s",
|
|
2440
2487
|
method,
|
|
2441
2488
|
origin,
|
|
2442
|
-
|
|
2489
|
+
path8,
|
|
2443
2490
|
error62.message
|
|
2444
2491
|
);
|
|
2445
2492
|
}
|
|
@@ -2554,7 +2601,7 @@ var require_request = __commonJS({
|
|
|
2554
2601
|
var kHandler = Symbol("handler");
|
|
2555
2602
|
var Request = class {
|
|
2556
2603
|
constructor(origin, {
|
|
2557
|
-
path:
|
|
2604
|
+
path: path8,
|
|
2558
2605
|
method,
|
|
2559
2606
|
body,
|
|
2560
2607
|
headers,
|
|
@@ -2571,11 +2618,11 @@ var require_request = __commonJS({
|
|
|
2571
2618
|
maxRedirections,
|
|
2572
2619
|
typeOfService
|
|
2573
2620
|
}, handler) {
|
|
2574
|
-
if (typeof
|
|
2621
|
+
if (typeof path8 !== "string") {
|
|
2575
2622
|
throw new InvalidArgumentError("path must be a string");
|
|
2576
|
-
} else if (
|
|
2623
|
+
} else if (path8[0] !== "/" && !(path8.startsWith("http://") || path8.startsWith("https://")) && method !== "CONNECT") {
|
|
2577
2624
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
2578
|
-
} else if (invalidPathRegex.test(
|
|
2625
|
+
} else if (invalidPathRegex.test(path8)) {
|
|
2579
2626
|
throw new InvalidArgumentError("invalid request path");
|
|
2580
2627
|
}
|
|
2581
2628
|
if (typeof method !== "string") {
|
|
@@ -2650,7 +2697,7 @@ var require_request = __commonJS({
|
|
|
2650
2697
|
this.completed = false;
|
|
2651
2698
|
this.aborted = false;
|
|
2652
2699
|
this.upgrade = upgrade || null;
|
|
2653
|
-
this.path = query ? serializePathWithQuery(
|
|
2700
|
+
this.path = query ? serializePathWithQuery(path8, query) : path8;
|
|
2654
2701
|
this.origin = origin;
|
|
2655
2702
|
this.protocol = getProtocolFromUrlString(origin);
|
|
2656
2703
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
@@ -6219,7 +6266,7 @@ var require_formdata = __commonJS({
|
|
|
6219
6266
|
var { kEnumerableProperty } = require_util();
|
|
6220
6267
|
var { webidl } = require_webidl();
|
|
6221
6268
|
var nodeUtil = __require("util");
|
|
6222
|
-
var
|
|
6269
|
+
var FormData2 = class _FormData {
|
|
6223
6270
|
#state = [];
|
|
6224
6271
|
constructor(form = void 0) {
|
|
6225
6272
|
webidl.util.markAsUncloneable(this);
|
|
@@ -6336,11 +6383,11 @@ var require_formdata = __commonJS({
|
|
|
6336
6383
|
formData.#state = newState;
|
|
6337
6384
|
}
|
|
6338
6385
|
};
|
|
6339
|
-
var { getFormDataState, setFormDataState } =
|
|
6340
|
-
Reflect.deleteProperty(
|
|
6341
|
-
Reflect.deleteProperty(
|
|
6342
|
-
iteratorMixin("FormData",
|
|
6343
|
-
Object.defineProperties(
|
|
6386
|
+
var { getFormDataState, setFormDataState } = FormData2;
|
|
6387
|
+
Reflect.deleteProperty(FormData2, "getFormDataState");
|
|
6388
|
+
Reflect.deleteProperty(FormData2, "setFormDataState");
|
|
6389
|
+
iteratorMixin("FormData", FormData2, getFormDataState, "name", "value");
|
|
6390
|
+
Object.defineProperties(FormData2.prototype, {
|
|
6344
6391
|
append: kEnumerableProperty,
|
|
6345
6392
|
delete: kEnumerableProperty,
|
|
6346
6393
|
get: kEnumerableProperty,
|
|
@@ -6368,8 +6415,8 @@ var require_formdata = __commonJS({
|
|
|
6368
6415
|
}
|
|
6369
6416
|
return { name, value };
|
|
6370
6417
|
}
|
|
6371
|
-
webidl.is.FormData = webidl.util.MakeTypeAssertion(
|
|
6372
|
-
module.exports = { FormData, makeEntry, setFormDataState };
|
|
6418
|
+
webidl.is.FormData = webidl.util.MakeTypeAssertion(FormData2);
|
|
6419
|
+
module.exports = { FormData: FormData2, makeEntry, setFormDataState };
|
|
6373
6420
|
}
|
|
6374
6421
|
});
|
|
6375
6422
|
|
|
@@ -6733,7 +6780,7 @@ var require_body = __commonJS({
|
|
|
6733
6780
|
fullyReadBody,
|
|
6734
6781
|
extractMimeType
|
|
6735
6782
|
} = require_util2();
|
|
6736
|
-
var { FormData, setFormDataState } = require_formdata();
|
|
6783
|
+
var { FormData: FormData2, setFormDataState } = require_formdata();
|
|
6737
6784
|
var { webidl } = require_webidl();
|
|
6738
6785
|
var assert2 = __require("assert");
|
|
6739
6786
|
var { isErrored, isDisturbed } = __require("stream");
|
|
@@ -6926,13 +6973,13 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
6926
6973
|
switch (mimeType.essence) {
|
|
6927
6974
|
case "multipart/form-data": {
|
|
6928
6975
|
const parsed = multipartFormDataParser(value, mimeType);
|
|
6929
|
-
const fd = new
|
|
6976
|
+
const fd = new FormData2();
|
|
6930
6977
|
setFormDataState(fd, parsed);
|
|
6931
6978
|
return fd;
|
|
6932
6979
|
}
|
|
6933
6980
|
case "application/x-www-form-urlencoded": {
|
|
6934
6981
|
const entries = new URLSearchParams(value.toString());
|
|
6935
|
-
const fd = new
|
|
6982
|
+
const fd = new FormData2();
|
|
6936
6983
|
for (const [name, value2] of entries) {
|
|
6937
6984
|
fd.append(name, value2);
|
|
6938
6985
|
}
|
|
@@ -7856,7 +7903,7 @@ var require_client_h1 = __commonJS({
|
|
|
7856
7903
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
7857
7904
|
}
|
|
7858
7905
|
function writeH1(client, request) {
|
|
7859
|
-
const { method, path:
|
|
7906
|
+
const { method, path: path8, host, upgrade, blocking, reset } = request;
|
|
7860
7907
|
let { body, headers, contentLength } = request;
|
|
7861
7908
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
7862
7909
|
if (util.isFormDataLike(body)) {
|
|
@@ -7934,7 +7981,7 @@ var require_client_h1 = __commonJS({
|
|
|
7934
7981
|
if (socket.setTypeOfService) {
|
|
7935
7982
|
socket.setTypeOfService(request.typeOfService);
|
|
7936
7983
|
}
|
|
7937
|
-
let header = `${method} ${
|
|
7984
|
+
let header = `${method} ${path8} HTTP/1.1\r
|
|
7938
7985
|
`;
|
|
7939
7986
|
if (typeof host === "string") {
|
|
7940
7987
|
header += `host: ${host}\r
|
|
@@ -8613,7 +8660,7 @@ var require_client_h2 = __commonJS({
|
|
|
8613
8660
|
const headersTimeout = request.headersTimeout ?? client[kHeadersTimeout];
|
|
8614
8661
|
const bodyTimeout = request.bodyTimeout ?? client[kBodyTimeout];
|
|
8615
8662
|
const session = client[kHTTP2Session];
|
|
8616
|
-
const { method, path:
|
|
8663
|
+
const { method, path: path8, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request;
|
|
8617
8664
|
let { body } = request;
|
|
8618
8665
|
if (upgrade != null && upgrade !== "websocket") {
|
|
8619
8666
|
util.errorRequest(client, request, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
@@ -8682,7 +8729,7 @@ var require_client_h2 = __commonJS({
|
|
|
8682
8729
|
}
|
|
8683
8730
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
8684
8731
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
8685
|
-
headers[HTTP2_HEADER_PATH] =
|
|
8732
|
+
headers[HTTP2_HEADER_PATH] = path8;
|
|
8686
8733
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
8687
8734
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
8688
8735
|
} else {
|
|
@@ -8734,7 +8781,7 @@ var require_client_h2 = __commonJS({
|
|
|
8734
8781
|
stream.setTimeout(headersTimeout);
|
|
8735
8782
|
return true;
|
|
8736
8783
|
}
|
|
8737
|
-
headers[HTTP2_HEADER_PATH] =
|
|
8784
|
+
headers[HTTP2_HEADER_PATH] = path8;
|
|
8738
8785
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
8739
8786
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
8740
8787
|
if (body && typeof body.read === "function") {
|
|
@@ -10215,7 +10262,7 @@ var require_agent = __commonJS({
|
|
|
10215
10262
|
function defaultFactory(origin, opts) {
|
|
10216
10263
|
return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts);
|
|
10217
10264
|
}
|
|
10218
|
-
var
|
|
10265
|
+
var Agent3 = class extends DispatcherBase {
|
|
10219
10266
|
constructor({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) {
|
|
10220
10267
|
if (typeof factory !== "function") {
|
|
10221
10268
|
throw new InvalidArgumentError("factory must be a function.");
|
|
@@ -10324,7 +10371,7 @@ var require_agent = __commonJS({
|
|
|
10324
10371
|
return allClientStats;
|
|
10325
10372
|
}
|
|
10326
10373
|
};
|
|
10327
|
-
module.exports =
|
|
10374
|
+
module.exports = Agent3;
|
|
10328
10375
|
}
|
|
10329
10376
|
});
|
|
10330
10377
|
|
|
@@ -11030,7 +11077,7 @@ var require_proxy_agent = __commonJS({
|
|
|
11030
11077
|
"node_modules/undici/lib/dispatcher/proxy-agent.js"(exports, module) {
|
|
11031
11078
|
"use strict";
|
|
11032
11079
|
var { kProxy, kClose, kDestroy, kDispatch } = require_symbols();
|
|
11033
|
-
var
|
|
11080
|
+
var Agent3 = require_agent();
|
|
11034
11081
|
var Pool = require_pool();
|
|
11035
11082
|
var DispatcherBase = require_dispatcher_base();
|
|
11036
11083
|
var { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError } = require_errors();
|
|
@@ -11086,10 +11133,10 @@ var require_proxy_agent = __commonJS({
|
|
|
11086
11133
|
};
|
|
11087
11134
|
const {
|
|
11088
11135
|
origin,
|
|
11089
|
-
path:
|
|
11136
|
+
path: path8 = "/",
|
|
11090
11137
|
headers = {}
|
|
11091
11138
|
} = opts;
|
|
11092
|
-
opts.path = origin +
|
|
11139
|
+
opts.path = origin + path8;
|
|
11093
11140
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
11094
11141
|
const { host } = new URL(origin);
|
|
11095
11142
|
headers.host = host;
|
|
@@ -11161,7 +11208,7 @@ var require_proxy_agent = __commonJS({
|
|
|
11161
11208
|
} else {
|
|
11162
11209
|
this[kClient] = clientFactory(url2, { connect });
|
|
11163
11210
|
}
|
|
11164
|
-
this[kAgent] = new
|
|
11211
|
+
this[kAgent] = new Agent3({
|
|
11165
11212
|
...opts,
|
|
11166
11213
|
factory,
|
|
11167
11214
|
connect: async (opts2, callback) => {
|
|
@@ -11289,7 +11336,7 @@ var require_env_http_proxy_agent = __commonJS({
|
|
|
11289
11336
|
var DispatcherBase = require_dispatcher_base();
|
|
11290
11337
|
var { kClose, kDestroy, kClosed, kDestroyed, kDispatch, kNoProxyAgent, kHttpProxyAgent, kHttpsProxyAgent } = require_symbols();
|
|
11291
11338
|
var ProxyAgent = require_proxy_agent();
|
|
11292
|
-
var
|
|
11339
|
+
var Agent3 = require_agent();
|
|
11293
11340
|
var DEFAULT_PORTS = {
|
|
11294
11341
|
"http:": 80,
|
|
11295
11342
|
"https:": 443
|
|
@@ -11302,7 +11349,7 @@ var require_env_http_proxy_agent = __commonJS({
|
|
|
11302
11349
|
super();
|
|
11303
11350
|
this.#opts = opts;
|
|
11304
11351
|
const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts;
|
|
11305
|
-
this[kNoProxyAgent] = new
|
|
11352
|
+
this[kNoProxyAgent] = new Agent3(agentOpts);
|
|
11306
11353
|
const HTTP_PROXY = httpProxy ?? process.env.http_proxy ?? process.env.HTTP_PROXY;
|
|
11307
11354
|
if (HTTP_PROXY) {
|
|
11308
11355
|
this[kHttpProxyAgent] = new ProxyAgent({ ...agentOpts, uri: HTTP_PROXY });
|
|
@@ -13249,20 +13296,20 @@ var require_mock_utils = __commonJS({
|
|
|
13249
13296
|
}
|
|
13250
13297
|
return normalizedQp;
|
|
13251
13298
|
}
|
|
13252
|
-
function safeUrl(
|
|
13253
|
-
if (typeof
|
|
13254
|
-
return
|
|
13299
|
+
function safeUrl(path8) {
|
|
13300
|
+
if (typeof path8 !== "string") {
|
|
13301
|
+
return path8;
|
|
13255
13302
|
}
|
|
13256
|
-
const pathSegments =
|
|
13303
|
+
const pathSegments = path8.split("?", 3);
|
|
13257
13304
|
if (pathSegments.length !== 2) {
|
|
13258
|
-
return
|
|
13305
|
+
return path8;
|
|
13259
13306
|
}
|
|
13260
13307
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
13261
13308
|
qp.sort();
|
|
13262
13309
|
return [...pathSegments, qp.toString()].join("?");
|
|
13263
13310
|
}
|
|
13264
|
-
function matchKey(mockDispatch2, { path:
|
|
13265
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
13311
|
+
function matchKey(mockDispatch2, { path: path8, method, body, headers }) {
|
|
13312
|
+
const pathMatch = matchValue(mockDispatch2.path, path8);
|
|
13266
13313
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
13267
13314
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
13268
13315
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -13287,8 +13334,8 @@ var require_mock_utils = __commonJS({
|
|
|
13287
13334
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
13288
13335
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
13289
13336
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
13290
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
13291
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
13337
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path8, ignoreTrailingSlash }) => {
|
|
13338
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path8)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path8), resolvedPath);
|
|
13292
13339
|
});
|
|
13293
13340
|
if (matchedMockDispatches.length === 0) {
|
|
13294
13341
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -13327,19 +13374,19 @@ var require_mock_utils = __commonJS({
|
|
|
13327
13374
|
mockDispatches.splice(index, 1);
|
|
13328
13375
|
}
|
|
13329
13376
|
}
|
|
13330
|
-
function removeTrailingSlash(
|
|
13331
|
-
while (
|
|
13332
|
-
|
|
13377
|
+
function removeTrailingSlash(path8) {
|
|
13378
|
+
while (path8.endsWith("/")) {
|
|
13379
|
+
path8 = path8.slice(0, -1);
|
|
13333
13380
|
}
|
|
13334
|
-
if (
|
|
13335
|
-
|
|
13381
|
+
if (path8.length === 0) {
|
|
13382
|
+
path8 = "/";
|
|
13336
13383
|
}
|
|
13337
|
-
return
|
|
13384
|
+
return path8;
|
|
13338
13385
|
}
|
|
13339
13386
|
function buildKey(opts) {
|
|
13340
|
-
const { path:
|
|
13387
|
+
const { path: path8, method, body, headers, query } = opts;
|
|
13341
13388
|
return {
|
|
13342
|
-
path:
|
|
13389
|
+
path: path8,
|
|
13343
13390
|
method,
|
|
13344
13391
|
body,
|
|
13345
13392
|
headers,
|
|
@@ -14029,10 +14076,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
14029
14076
|
}
|
|
14030
14077
|
format(pendingInterceptors) {
|
|
14031
14078
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
14032
|
-
({ method, path:
|
|
14079
|
+
({ method, path: path8, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
14033
14080
|
Method: method,
|
|
14034
14081
|
Origin: origin,
|
|
14035
|
-
Path:
|
|
14082
|
+
Path: path8,
|
|
14036
14083
|
"Status code": statusCode,
|
|
14037
14084
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
14038
14085
|
Invocations: timesInvoked,
|
|
@@ -14051,7 +14098,7 @@ var require_mock_agent = __commonJS({
|
|
|
14051
14098
|
"node_modules/undici/lib/mock/mock-agent.js"(exports, module) {
|
|
14052
14099
|
"use strict";
|
|
14053
14100
|
var { kClients } = require_symbols();
|
|
14054
|
-
var
|
|
14101
|
+
var Agent3 = require_agent();
|
|
14055
14102
|
var {
|
|
14056
14103
|
kAgent,
|
|
14057
14104
|
kMockAgentSet,
|
|
@@ -14089,7 +14136,7 @@ var require_mock_agent = __commonJS({
|
|
|
14089
14136
|
if (opts?.agent && typeof opts.agent.dispatch !== "function") {
|
|
14090
14137
|
throw new InvalidArgumentError("Argument opts.agent must implement Agent");
|
|
14091
14138
|
}
|
|
14092
|
-
const agent = opts?.agent ? opts.agent : new
|
|
14139
|
+
const agent = opts?.agent ? opts.agent : new Agent3(opts);
|
|
14093
14140
|
this[kAgent] = agent;
|
|
14094
14141
|
this[kClients] = agent[kClients];
|
|
14095
14142
|
this[kOptions] = mockOptions;
|
|
@@ -14114,9 +14161,9 @@ var require_mock_agent = __commonJS({
|
|
|
14114
14161
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
14115
14162
|
const dispatchOpts = { ...opts };
|
|
14116
14163
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
14117
|
-
const [
|
|
14164
|
+
const [path8, searchParams] = dispatchOpts.path.split("?");
|
|
14118
14165
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
14119
|
-
dispatchOpts.path = `${
|
|
14166
|
+
dispatchOpts.path = `${path8}?${normalizedSearchParams}`;
|
|
14120
14167
|
}
|
|
14121
14168
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
14122
14169
|
}
|
|
@@ -14320,7 +14367,7 @@ var require_snapshot_utils = __commonJS({
|
|
|
14320
14367
|
var require_snapshot_recorder = __commonJS({
|
|
14321
14368
|
"node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
|
|
14322
14369
|
"use strict";
|
|
14323
|
-
var { writeFile, readFile, mkdir } = __require("fs/promises");
|
|
14370
|
+
var { writeFile: writeFile2, readFile, mkdir: mkdir2 } = __require("fs/promises");
|
|
14324
14371
|
var { dirname, resolve } = __require("path");
|
|
14325
14372
|
var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("timers");
|
|
14326
14373
|
var { InvalidArgumentError, UndiciError } = require_errors();
|
|
@@ -14517,12 +14564,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
14517
14564
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
14518
14565
|
*/
|
|
14519
14566
|
async loadSnapshots(filePath) {
|
|
14520
|
-
const
|
|
14521
|
-
if (!
|
|
14567
|
+
const path8 = filePath || this.#snapshotPath;
|
|
14568
|
+
if (!path8) {
|
|
14522
14569
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
14523
14570
|
}
|
|
14524
14571
|
try {
|
|
14525
|
-
const data = await readFile(resolve(
|
|
14572
|
+
const data = await readFile(resolve(path8), "utf8");
|
|
14526
14573
|
const parsed = JSON.parse(data);
|
|
14527
14574
|
if (Array.isArray(parsed)) {
|
|
14528
14575
|
this.#snapshots.clear();
|
|
@@ -14536,7 +14583,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
14536
14583
|
if (error62.code === "ENOENT") {
|
|
14537
14584
|
this.#snapshots.clear();
|
|
14538
14585
|
} else {
|
|
14539
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
14586
|
+
throw new UndiciError(`Failed to load snapshots from ${path8}`, { cause: error62 });
|
|
14540
14587
|
}
|
|
14541
14588
|
}
|
|
14542
14589
|
}
|
|
@@ -14547,17 +14594,17 @@ var require_snapshot_recorder = __commonJS({
|
|
|
14547
14594
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
14548
14595
|
*/
|
|
14549
14596
|
async saveSnapshots(filePath) {
|
|
14550
|
-
const
|
|
14551
|
-
if (!
|
|
14597
|
+
const path8 = filePath || this.#snapshotPath;
|
|
14598
|
+
if (!path8) {
|
|
14552
14599
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
14553
14600
|
}
|
|
14554
|
-
const resolvedPath = resolve(
|
|
14555
|
-
await
|
|
14601
|
+
const resolvedPath = resolve(path8);
|
|
14602
|
+
await mkdir2(dirname(resolvedPath), { recursive: true });
|
|
14556
14603
|
const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
|
|
14557
14604
|
hash: hash2,
|
|
14558
14605
|
snapshot
|
|
14559
14606
|
}));
|
|
14560
|
-
await
|
|
14607
|
+
await writeFile2(resolvedPath, JSON.stringify(data, null, 2), { flush: true });
|
|
14561
14608
|
}
|
|
14562
14609
|
/**
|
|
14563
14610
|
* Clears all recorded snapshots
|
|
@@ -14696,7 +14743,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
14696
14743
|
var require_snapshot_agent = __commonJS({
|
|
14697
14744
|
"node_modules/undici/lib/mock/snapshot-agent.js"(exports, module) {
|
|
14698
14745
|
"use strict";
|
|
14699
|
-
var
|
|
14746
|
+
var Agent3 = require_agent();
|
|
14700
14747
|
var MockAgent = require_mock_agent();
|
|
14701
14748
|
var { SnapshotRecorder } = require_snapshot_recorder();
|
|
14702
14749
|
var WrapHandler = require_wrap_handler();
|
|
@@ -14747,7 +14794,7 @@ var require_snapshot_agent = __commonJS({
|
|
|
14747
14794
|
});
|
|
14748
14795
|
this[kSnapshotLoaded] = false;
|
|
14749
14796
|
if (this[kSnapshotMode] === "record" || this[kSnapshotMode] === "update" || this[kSnapshotMode] === "playback" && opts.excludeUrls && opts.excludeUrls.length > 0) {
|
|
14750
|
-
this[kRealAgent] = new
|
|
14797
|
+
this[kRealAgent] = new Agent3(opts);
|
|
14751
14798
|
}
|
|
14752
14799
|
if ((this[kSnapshotMode] === "playback" || this[kSnapshotMode] === "update") && this[kSnapshotPath]) {
|
|
14753
14800
|
this.loadSnapshots().catch(() => {
|
|
@@ -14986,9 +15033,9 @@ var require_global2 = __commonJS({
|
|
|
14986
15033
|
var globalDispatcher = Symbol.for("undici.globalDispatcher.2");
|
|
14987
15034
|
var legacyGlobalDispatcher = Symbol.for("undici.globalDispatcher.1");
|
|
14988
15035
|
var { InvalidArgumentError } = require_errors();
|
|
14989
|
-
var
|
|
15036
|
+
var Agent3 = require_agent();
|
|
14990
15037
|
if (getGlobalDispatcher() === void 0) {
|
|
14991
|
-
setGlobalDispatcher(new
|
|
15038
|
+
setGlobalDispatcher(new Agent3());
|
|
14992
15039
|
}
|
|
14993
15040
|
function setGlobalDispatcher(agent) {
|
|
14994
15041
|
if (!agent || typeof agent.dispatch !== "function") {
|
|
@@ -15183,15 +15230,15 @@ var require_redirect_handler = __commonJS({
|
|
|
15183
15230
|
return;
|
|
15184
15231
|
}
|
|
15185
15232
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
15186
|
-
const
|
|
15187
|
-
const redirectUrlString = `${origin}${
|
|
15233
|
+
const path8 = search ? `${pathname}${search}` : pathname;
|
|
15234
|
+
const redirectUrlString = `${origin}${path8}`;
|
|
15188
15235
|
for (const historyUrl of this.history) {
|
|
15189
15236
|
if (historyUrl.toString() === redirectUrlString) {
|
|
15190
15237
|
throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
|
|
15191
15238
|
}
|
|
15192
15239
|
}
|
|
15193
15240
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
15194
|
-
this.opts.path =
|
|
15241
|
+
this.opts.path = path8;
|
|
15195
15242
|
this.opts.origin = origin;
|
|
15196
15243
|
this.opts.query = null;
|
|
15197
15244
|
}
|
|
@@ -16950,10 +16997,10 @@ var require_cache_handler = __commonJS({
|
|
|
16950
16997
|
}
|
|
16951
16998
|
return locationUrl.pathname + locationUrl.search;
|
|
16952
16999
|
}
|
|
16953
|
-
function deleteCachedUri(store, cacheKey,
|
|
17000
|
+
function deleteCachedUri(store, cacheKey, path8) {
|
|
16954
17001
|
deleteCachedValue(store, {
|
|
16955
17002
|
...cacheKey,
|
|
16956
|
-
path:
|
|
17003
|
+
path: path8
|
|
16957
17004
|
});
|
|
16958
17005
|
for (let i = 0; i < util.safeHTTPMethods.length; i++) {
|
|
16959
17006
|
const method = util.safeHTTPMethods[i];
|
|
@@ -16961,7 +17008,7 @@ var require_cache_handler = __commonJS({
|
|
|
16961
17008
|
deleteCachedValue(store, {
|
|
16962
17009
|
...cacheKey,
|
|
16963
17010
|
method,
|
|
16964
|
-
path:
|
|
17011
|
+
path: path8
|
|
16965
17012
|
});
|
|
16966
17013
|
}
|
|
16967
17014
|
}
|
|
@@ -16972,9 +17019,9 @@ var require_cache_handler = __commonJS({
|
|
|
16972
17019
|
}
|
|
16973
17020
|
const values = Array.isArray(headerValue) ? headerValue : [headerValue];
|
|
16974
17021
|
for (let i = 0; i < values.length; i++) {
|
|
16975
|
-
const
|
|
16976
|
-
if (
|
|
16977
|
-
deleteCachedUri(store, cacheKey,
|
|
17022
|
+
const path8 = getSameOriginPath(cacheKey, values[i]);
|
|
17023
|
+
if (path8 !== void 0) {
|
|
17024
|
+
deleteCachedUri(store, cacheKey, path8);
|
|
16978
17025
|
}
|
|
16979
17026
|
}
|
|
16980
17027
|
}
|
|
@@ -22121,11 +22168,11 @@ var require_fetch = __commonJS({
|
|
|
22121
22168
|
function dispatch({ body }) {
|
|
22122
22169
|
const url2 = requestCurrentURL(request);
|
|
22123
22170
|
const agent = fetchParams.controller.dispatcher;
|
|
22124
|
-
const
|
|
22171
|
+
const path8 = url2.pathname + url2.search;
|
|
22125
22172
|
const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?";
|
|
22126
22173
|
return new Promise((resolve, reject) => agent.dispatch(
|
|
22127
22174
|
{
|
|
22128
|
-
path: hasTrailingQuestionMark ? `${
|
|
22175
|
+
path: hasTrailingQuestionMark ? `${path8}?` : path8,
|
|
22129
22176
|
origin: url2.origin,
|
|
22130
22177
|
method: request.method,
|
|
22131
22178
|
body: agent.isMockActive ? request.body && (request.body.source || request.body.stream) : body,
|
|
@@ -22675,8 +22722,8 @@ var require_cache3 = __commonJS({
|
|
|
22675
22722
|
* @returns {requestResponseList}
|
|
22676
22723
|
*/
|
|
22677
22724
|
#batchCacheOperations(operations) {
|
|
22678
|
-
const
|
|
22679
|
-
const backupCache = [...
|
|
22725
|
+
const cache2 = this.#relevantRequestResponseList;
|
|
22726
|
+
const backupCache = [...cache2];
|
|
22680
22727
|
const addedItems = [];
|
|
22681
22728
|
const resultList = [];
|
|
22682
22729
|
try {
|
|
@@ -22703,9 +22750,9 @@ var require_cache3 = __commonJS({
|
|
|
22703
22750
|
return [];
|
|
22704
22751
|
}
|
|
22705
22752
|
for (const requestResponse of requestResponses) {
|
|
22706
|
-
const idx =
|
|
22753
|
+
const idx = cache2.indexOf(requestResponse);
|
|
22707
22754
|
assert2(idx !== -1);
|
|
22708
|
-
|
|
22755
|
+
cache2.splice(idx, 1);
|
|
22709
22756
|
}
|
|
22710
22757
|
} else if (operation.type === "put") {
|
|
22711
22758
|
if (operation.response == null) {
|
|
@@ -22735,11 +22782,11 @@ var require_cache3 = __commonJS({
|
|
|
22735
22782
|
}
|
|
22736
22783
|
requestResponses = this.#queryCache(operation.request);
|
|
22737
22784
|
for (const requestResponse of requestResponses) {
|
|
22738
|
-
const idx =
|
|
22785
|
+
const idx = cache2.indexOf(requestResponse);
|
|
22739
22786
|
assert2(idx !== -1);
|
|
22740
|
-
|
|
22787
|
+
cache2.splice(idx, 1);
|
|
22741
22788
|
}
|
|
22742
|
-
|
|
22789
|
+
cache2.push([operation.request, operation.response]);
|
|
22743
22790
|
addedItems.push([operation.request, operation.response]);
|
|
22744
22791
|
}
|
|
22745
22792
|
resultList.push([operation.request, operation.response]);
|
|
@@ -22916,13 +22963,13 @@ var require_cachestorage = __commonJS({
|
|
|
22916
22963
|
if (options.cacheName != null) {
|
|
22917
22964
|
if (this.#caches.has(options.cacheName)) {
|
|
22918
22965
|
const cacheList = this.#caches.get(options.cacheName);
|
|
22919
|
-
const
|
|
22920
|
-
return await
|
|
22966
|
+
const cache2 = new Cache(kConstruct, cacheList);
|
|
22967
|
+
return await cache2.match(request, options);
|
|
22921
22968
|
}
|
|
22922
22969
|
} else {
|
|
22923
22970
|
for (const cacheList of this.#caches.values()) {
|
|
22924
|
-
const
|
|
22925
|
-
const response = await
|
|
22971
|
+
const cache2 = new Cache(kConstruct, cacheList);
|
|
22972
|
+
const response = await cache2.match(request, options);
|
|
22926
22973
|
if (response !== void 0) {
|
|
22927
22974
|
return response;
|
|
22928
22975
|
}
|
|
@@ -22952,12 +22999,12 @@ var require_cachestorage = __commonJS({
|
|
|
22952
22999
|
webidl.argumentLengthCheck(arguments, 1, prefix);
|
|
22953
23000
|
cacheName = webidl.converters.DOMString(cacheName, prefix, "cacheName");
|
|
22954
23001
|
if (this.#caches.has(cacheName)) {
|
|
22955
|
-
const
|
|
22956
|
-
return new Cache(kConstruct,
|
|
23002
|
+
const cache3 = this.#caches.get(cacheName);
|
|
23003
|
+
return new Cache(kConstruct, cache3);
|
|
22957
23004
|
}
|
|
22958
|
-
const
|
|
22959
|
-
this.#caches.set(cacheName,
|
|
22960
|
-
return new Cache(kConstruct,
|
|
23005
|
+
const cache2 = [];
|
|
23006
|
+
this.#caches.set(cacheName, cache2);
|
|
23007
|
+
return new Cache(kConstruct, cache2);
|
|
22961
23008
|
}
|
|
22962
23009
|
/**
|
|
22963
23010
|
* @see https://w3c.github.io/ServiceWorker/#cache-storage-delete
|
|
@@ -23072,9 +23119,9 @@ var require_util4 = __commonJS({
|
|
|
23072
23119
|
}
|
|
23073
23120
|
}
|
|
23074
23121
|
}
|
|
23075
|
-
function validateCookiePath(
|
|
23076
|
-
for (let i = 0; i <
|
|
23077
|
-
const code =
|
|
23122
|
+
function validateCookiePath(path8) {
|
|
23123
|
+
for (let i = 0; i < path8.length; ++i) {
|
|
23124
|
+
const code = path8.charCodeAt(i);
|
|
23078
23125
|
if (code < 32 || // exclude CTLs (0-31)
|
|
23079
23126
|
code > 126 || // exclude DEL and non-ascii
|
|
23080
23127
|
code === 59) {
|
|
@@ -26355,7 +26402,7 @@ var require_undici = __commonJS({
|
|
|
26355
26402
|
var Pool = require_pool();
|
|
26356
26403
|
var BalancedPool = require_balanced_pool();
|
|
26357
26404
|
var RoundRobinPool = require_round_robin_pool();
|
|
26358
|
-
var
|
|
26405
|
+
var Agent3 = require_agent();
|
|
26359
26406
|
var ProxyAgent = require_proxy_agent();
|
|
26360
26407
|
var Socks5ProxyAgent = require_socks5_proxy_agent();
|
|
26361
26408
|
var EnvHttpProxyAgent = require_env_http_proxy_agent();
|
|
@@ -26382,7 +26429,7 @@ var require_undici = __commonJS({
|
|
|
26382
26429
|
module.exports.Pool = Pool;
|
|
26383
26430
|
module.exports.BalancedPool = BalancedPool;
|
|
26384
26431
|
module.exports.RoundRobinPool = RoundRobinPool;
|
|
26385
|
-
module.exports.Agent =
|
|
26432
|
+
module.exports.Agent = Agent3;
|
|
26386
26433
|
module.exports.ProxyAgent = ProxyAgent;
|
|
26387
26434
|
module.exports.Socks5ProxyAgent = Socks5ProxyAgent;
|
|
26388
26435
|
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent;
|
|
@@ -26428,11 +26475,11 @@ var require_undici = __commonJS({
|
|
|
26428
26475
|
if (typeof opts.path !== "string") {
|
|
26429
26476
|
throw new InvalidArgumentError("invalid opts.path");
|
|
26430
26477
|
}
|
|
26431
|
-
let
|
|
26478
|
+
let path8 = opts.path;
|
|
26432
26479
|
if (!opts.path.startsWith("/")) {
|
|
26433
|
-
|
|
26480
|
+
path8 = `/${path8}`;
|
|
26434
26481
|
}
|
|
26435
|
-
url2 = new URL(util.parseOrigin(url2).origin +
|
|
26482
|
+
url2 = new URL(util.parseOrigin(url2).origin + path8);
|
|
26436
26483
|
} else {
|
|
26437
26484
|
if (!opts) {
|
|
26438
26485
|
opts = typeof url2 === "object" ? url2 : {};
|
|
@@ -26576,8 +26623,7 @@ var init_redact = __esm({
|
|
|
26576
26623
|
// src/api/api.ts
|
|
26577
26624
|
async function fetchJson(params) {
|
|
26578
26625
|
const { url: url2, init, timeoutMs, allowInsecureTls } = params;
|
|
26579
|
-
const
|
|
26580
|
-
const fetcher = allowInsecureTls ? import_undici.fetch : globalThis.fetch;
|
|
26626
|
+
const fetcher = globalThis.fetch;
|
|
26581
26627
|
const controller = new AbortController();
|
|
26582
26628
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
26583
26629
|
let response;
|
|
@@ -26585,8 +26631,7 @@ async function fetchJson(params) {
|
|
|
26585
26631
|
try {
|
|
26586
26632
|
response = await fetcher(url2, {
|
|
26587
26633
|
...init,
|
|
26588
|
-
signal: controller.signal
|
|
26589
|
-
...dispatcher ? { dispatcher } : {}
|
|
26634
|
+
signal: controller.signal
|
|
26590
26635
|
});
|
|
26591
26636
|
text = await response.text().catch(() => "");
|
|
26592
26637
|
} finally {
|
|
@@ -26728,6 +26773,42 @@ async function sendWorkChatReplyMessage(params) {
|
|
|
26728
26773
|
if (!data?.msgId) throw new Error("workchat: msgId missing in reply response");
|
|
26729
26774
|
return { msgId: String(data.msgId) };
|
|
26730
26775
|
}
|
|
26776
|
+
async function uploadWorkChatFile(params) {
|
|
26777
|
+
const { opts, filePath, userId } = params;
|
|
26778
|
+
const token = await getAccessToken(opts);
|
|
26779
|
+
const { readFile } = await import("fs/promises");
|
|
26780
|
+
const pathMod = await import("path");
|
|
26781
|
+
const content = await readFile(filePath);
|
|
26782
|
+
const fileName = pathMod.basename(filePath);
|
|
26783
|
+
const ext = pathMod.extname(fileName).replace(/^\./, "").toLowerCase();
|
|
26784
|
+
const mime = ext === "mp3" || ext === "m4a" ? "audio/mpeg" : ext === "wav" ? "audio/wav" : `image/${ext === "jpg" ? "jpeg" : ext || "png"}`;
|
|
26785
|
+
const form = new FormData();
|
|
26786
|
+
form.set("file", new Blob([new Uint8Array(content)], { type: mime }), fileName);
|
|
26787
|
+
const ownerUserId = userId !== void 0 && String(userId).trim() !== "" ? String(userId) : "0";
|
|
26788
|
+
form.set("userId", ownerUserId);
|
|
26789
|
+
const resp = await fetchJson({
|
|
26790
|
+
url: `${normalizeBaseUrl(opts.baseUrl)}/open-apis/v1/files/upload`,
|
|
26791
|
+
timeoutMs: opts.timeoutMs ?? RequestDefaults.TimeoutMs,
|
|
26792
|
+
allowInsecureTls: opts.allowInsecureTls,
|
|
26793
|
+
init: {
|
|
26794
|
+
method: "POST",
|
|
26795
|
+
headers: {
|
|
26796
|
+
Authorization: `Bearer ${token}`,
|
|
26797
|
+
"x-user-id": ownerUserId
|
|
26798
|
+
},
|
|
26799
|
+
body: form
|
|
26800
|
+
}
|
|
26801
|
+
});
|
|
26802
|
+
const data = unwrapEnvelope(resp);
|
|
26803
|
+
const url2 = typeof data?.url === "string" ? data.url.trim() : "";
|
|
26804
|
+
if (!url2) throw new Error("workchat: url missing in file upload response");
|
|
26805
|
+
return {
|
|
26806
|
+
url: url2,
|
|
26807
|
+
fileName: typeof data?.fileName === "string" ? data.fileName : void 0,
|
|
26808
|
+
suffix: typeof data?.suffix === "string" ? data.suffix : void 0,
|
|
26809
|
+
fileSize: typeof data?.fileSize === "number" ? data.fileSize : void 0
|
|
26810
|
+
};
|
|
26811
|
+
}
|
|
26731
26812
|
async function notifyAgentCreatedStatus(opts, agentId) {
|
|
26732
26813
|
try {
|
|
26733
26814
|
const token = await getAccessToken(opts);
|
|
@@ -26742,11 +26823,10 @@ async function notifyAgentCreatedStatus(opts, agentId) {
|
|
|
26742
26823
|
logger.error(`agent-created/status failed: ${String(err)}`);
|
|
26743
26824
|
}
|
|
26744
26825
|
}
|
|
26745
|
-
var
|
|
26826
|
+
var tokenCache;
|
|
26746
26827
|
var init_api = __esm({
|
|
26747
26828
|
"src/api/api.ts"() {
|
|
26748
26829
|
"use strict";
|
|
26749
|
-
import_undici = __toESM(require_undici(), 1);
|
|
26750
26830
|
init_types();
|
|
26751
26831
|
init_logger();
|
|
26752
26832
|
init_redact();
|
|
@@ -26807,7 +26887,17 @@ function parseWorkChatFrame(data) {
|
|
|
26807
26887
|
if (type === "CALLBACK" && String(envelope?.metadata?.topic || "").trim().toUpperCase() === "AGENT_MESSAGE") {
|
|
26808
26888
|
const payload = parseMaybeJson(envelope?.data) ?? {};
|
|
26809
26889
|
const message = payload?.message;
|
|
26810
|
-
const
|
|
26890
|
+
const messageType = typeof message === "object" && message !== null ? String(message.type ?? "").trim().toLowerCase() : "";
|
|
26891
|
+
const rawContent = typeof message === "string" ? message : typeof message?.content === "string" ? message.content : "";
|
|
26892
|
+
let mediaUrl;
|
|
26893
|
+
let text = rawContent;
|
|
26894
|
+
if (messageType === "image" || messageType === "audio") {
|
|
26895
|
+
mediaUrl = extractMediaUrl(rawContent) ?? firstFileUrl(payload);
|
|
26896
|
+
text = messageType === "image" ? "[\u7528\u6237\u53D1\u9001\u4E86\u4E00\u5F20\u56FE\u7247]" : "[\u7528\u6237\u53D1\u9001\u4E86\u4E00\u6761\u8BED\u97F3]";
|
|
26897
|
+
} else if (!text.trim()) {
|
|
26898
|
+
mediaUrl = firstFileUrl(payload);
|
|
26899
|
+
if (mediaUrl) text = "[\u7528\u6237\u53D1\u9001\u4E86\u4E00\u4E2A\u6587\u4EF6]";
|
|
26900
|
+
}
|
|
26811
26901
|
return {
|
|
26812
26902
|
type: "agent_message",
|
|
26813
26903
|
message: {
|
|
@@ -26815,12 +26905,26 @@ function parseWorkChatFrame(data) {
|
|
|
26815
26905
|
userId: String(payload?.userId ?? ""),
|
|
26816
26906
|
openConversationId: String(payload?.conversationId ?? ""),
|
|
26817
26907
|
messageId: String(payload?.msgId ?? ""),
|
|
26818
|
-
...payload?.agentId !== void 0 ? { agentId: String(payload.agentId) } : {}
|
|
26908
|
+
...payload?.agentId !== void 0 ? { agentId: String(payload.agentId) } : {},
|
|
26909
|
+
...mediaUrl ? { mediaUrl, mediaType: messageType || "file" } : {}
|
|
26819
26910
|
}
|
|
26820
26911
|
};
|
|
26821
26912
|
}
|
|
26822
26913
|
return { type: "ignored", ignoredKind: `${type}/${topicLower || "(no topic)"}` };
|
|
26823
26914
|
}
|
|
26915
|
+
function extractMediaUrl(content) {
|
|
26916
|
+
if (!content.trim()) return void 0;
|
|
26917
|
+
try {
|
|
26918
|
+
const parsed = JSON.parse(content);
|
|
26919
|
+
return typeof parsed?.url === "string" && parsed.url.trim() ? parsed.url.trim() : void 0;
|
|
26920
|
+
} catch {
|
|
26921
|
+
return void 0;
|
|
26922
|
+
}
|
|
26923
|
+
}
|
|
26924
|
+
function firstFileUrl(payload) {
|
|
26925
|
+
const url2 = Array.isArray(payload?.fileUrl) ? payload.fileUrl[0] : void 0;
|
|
26926
|
+
return typeof url2 === "string" && url2.trim() ? url2.trim() : void 0;
|
|
26927
|
+
}
|
|
26824
26928
|
function buildPongFrame(pongData) {
|
|
26825
26929
|
return JSON.stringify({
|
|
26826
26930
|
code: 200,
|
|
@@ -26834,8 +26938,10 @@ function generateMessageSid() {
|
|
|
26834
26938
|
}
|
|
26835
26939
|
function workChatMessageToMsgContext(message, accountId) {
|
|
26836
26940
|
const fromUserId = message.userId ?? "";
|
|
26941
|
+
const body = message.mediaUrl ? `${message.text ?? ""}
|
|
26942
|
+
[media] ${message.mediaUrl}` : message.text ?? "";
|
|
26837
26943
|
const ctx = {
|
|
26838
|
-
Body:
|
|
26944
|
+
Body: body,
|
|
26839
26945
|
From: fromUserId,
|
|
26840
26946
|
To: fromUserId,
|
|
26841
26947
|
AccountId: accountId,
|
|
@@ -26853,6 +26959,10 @@ function workChatMessageToMsgContext(message, accountId) {
|
|
|
26853
26959
|
if (message.agentId) {
|
|
26854
26960
|
ctx.AgentId = message.agentId;
|
|
26855
26961
|
}
|
|
26962
|
+
if (message.mediaUrl) {
|
|
26963
|
+
ctx.MediaUrl = message.mediaUrl;
|
|
26964
|
+
ctx.MediaType = message.mediaType ?? "file";
|
|
26965
|
+
}
|
|
26856
26966
|
return ctx;
|
|
26857
26967
|
}
|
|
26858
26968
|
var init_inbound = __esm({
|
|
@@ -27059,8 +27169,8 @@ function startBindingListener(sessionKey, opts, timeoutMs) {
|
|
|
27059
27169
|
clearWorkChatTokenCache(opts.appKey || "default");
|
|
27060
27170
|
const { endpoint, ticket } = await openConnection(opts);
|
|
27061
27171
|
const url2 = `${endpoint}?ticket=${encodeURIComponent(ticket)}`;
|
|
27062
|
-
const dispatcher = opts.allowInsecureTls ? new
|
|
27063
|
-
ws = new
|
|
27172
|
+
const dispatcher = opts.allowInsecureTls ? new import_undici.Agent({ connect: { rejectUnauthorized: false } }) : void 0;
|
|
27173
|
+
ws = new import_undici.WebSocket(url2, dispatcher ? { dispatcher } : void 0);
|
|
27064
27174
|
const entryNow = bindingListeners.get(sessionKey);
|
|
27065
27175
|
if (!entryNow || entryNow.done) {
|
|
27066
27176
|
try {
|
|
@@ -27127,28 +27237,27 @@ async function handleListenerFrame(sessionKey, data, ws) {
|
|
|
27127
27237
|
if (result.type !== "init_agent") return;
|
|
27128
27238
|
const eventData = result.eventData;
|
|
27129
27239
|
if (!eventData) return;
|
|
27130
|
-
const agentId = String(eventData.id ?? eventData.agentId ?? "");
|
|
27240
|
+
const agentId = String(eventData.id ?? eventData.agentId ?? "").trim();
|
|
27131
27241
|
if (!agentId) return;
|
|
27132
|
-
const userId = String(eventData.futureId ?? eventData.userId ?? "");
|
|
27242
|
+
const userId = String(eventData.futureId ?? eventData.userId ?? "").trim();
|
|
27133
27243
|
const entry = bindingListeners.get(sessionKey);
|
|
27134
27244
|
if (entry) entry.done = true;
|
|
27135
|
-
const
|
|
27245
|
+
const accountId = `agent-${agentId}`;
|
|
27136
27246
|
try {
|
|
27137
|
-
const {
|
|
27138
|
-
const removed = await
|
|
27247
|
+
const { pruneOtherWorkChatAccounts: pruneOtherWorkChatAccounts2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
27248
|
+
const removed = await pruneOtherWorkChatAccounts2(accountId);
|
|
27139
27249
|
if (removed.length > 0) {
|
|
27140
|
-
logger.info(`binding listener: pruned
|
|
27250
|
+
logger.info(`binding listener: pruned previous account(s): ${removed.join(", ")}`);
|
|
27141
27251
|
}
|
|
27142
27252
|
} catch (err) {
|
|
27143
27253
|
logger.error(`binding listener: rebind cleanup failed: ${String(err)}`);
|
|
27144
27254
|
}
|
|
27145
|
-
const accountId = isRebind ? `agent-${agentId}` : "default";
|
|
27146
27255
|
try {
|
|
27147
27256
|
saveWorkChatAccount(accountId, {
|
|
27148
27257
|
agentId,
|
|
27149
27258
|
...userId ? { userId } : {}
|
|
27150
27259
|
});
|
|
27151
|
-
registerWorkChatAccountId(accountId);
|
|
27260
|
+
await registerWorkChatAccountId(accountId);
|
|
27152
27261
|
const { bindAgentToAccountFromBinding: bindAgentToAccountFromBinding2 } = await Promise.resolve().then(() => (init_bind_agent(), bind_agent_exports));
|
|
27153
27262
|
await bindAgentToAccountFromBinding2(accountId, agentId, userId);
|
|
27154
27263
|
logger.info(`binding listener: account=${accountId} agent=${agentId} persisted`);
|
|
@@ -27187,12 +27296,12 @@ function completeWorkChatBinding(completion) {
|
|
|
27187
27296
|
);
|
|
27188
27297
|
return true;
|
|
27189
27298
|
}
|
|
27190
|
-
var
|
|
27299
|
+
var import_undici, BIND_CMD, BIND_TYPE, BIND_NAME, ACTIVE_BINDING_TTL_MS, activeBindings, pendingWaiters, bindingListeners;
|
|
27191
27300
|
var init_login_qr = __esm({
|
|
27192
27301
|
"src/auth/login-qr.ts"() {
|
|
27193
27302
|
"use strict";
|
|
27194
27303
|
init_logger();
|
|
27195
|
-
|
|
27304
|
+
import_undici = __toESM(require_undici(), 1);
|
|
27196
27305
|
init_api();
|
|
27197
27306
|
init_inbound();
|
|
27198
27307
|
init_inbound();
|
|
@@ -27207,9 +27316,74 @@ var init_login_qr = __esm({
|
|
|
27207
27316
|
}
|
|
27208
27317
|
});
|
|
27209
27318
|
|
|
27319
|
+
// src/api/session-guard.ts
|
|
27320
|
+
function pauseSession(accountId) {
|
|
27321
|
+
const until = Date.now() + SESSION_PAUSE_DURATION_MS;
|
|
27322
|
+
pauseUntilMap.set(accountId, until);
|
|
27323
|
+
logger.info(
|
|
27324
|
+
`session-guard: paused accountId=${accountId} until=${new Date(until).toISOString()} (${SESSION_PAUSE_DURATION_MS / 1e3}s)`
|
|
27325
|
+
);
|
|
27326
|
+
}
|
|
27327
|
+
function isSessionPaused(accountId) {
|
|
27328
|
+
const until = pauseUntilMap.get(accountId);
|
|
27329
|
+
if (until === void 0) return false;
|
|
27330
|
+
if (Date.now() >= until) {
|
|
27331
|
+
pauseUntilMap.delete(accountId);
|
|
27332
|
+
return false;
|
|
27333
|
+
}
|
|
27334
|
+
return true;
|
|
27335
|
+
}
|
|
27336
|
+
function getRemainingPauseMs(accountId) {
|
|
27337
|
+
const until = pauseUntilMap.get(accountId);
|
|
27338
|
+
if (until === void 0) return 0;
|
|
27339
|
+
const remaining = until - Date.now();
|
|
27340
|
+
if (remaining <= 0) {
|
|
27341
|
+
pauseUntilMap.delete(accountId);
|
|
27342
|
+
return 0;
|
|
27343
|
+
}
|
|
27344
|
+
return remaining;
|
|
27345
|
+
}
|
|
27346
|
+
function assertSessionActive(accountId) {
|
|
27347
|
+
if (isSessionPaused(accountId)) {
|
|
27348
|
+
const remainingMin = Math.ceil(getRemainingPauseMs(accountId) / 6e4);
|
|
27349
|
+
throw new Error(
|
|
27350
|
+
`session paused for accountId=${accountId}, ${remainingMin} min remaining \u2014 the WorkChat binding is invalid, re-scan the QR code to fix`
|
|
27351
|
+
);
|
|
27352
|
+
}
|
|
27353
|
+
}
|
|
27354
|
+
function isPermanentBindingError(errMsg) {
|
|
27355
|
+
return PERMANENT_ERROR_PATTERNS.some((p) => errMsg.includes(p));
|
|
27356
|
+
}
|
|
27357
|
+
function pauseOnPermanentError(accountId, errMsg) {
|
|
27358
|
+
if (!isPermanentBindingError(errMsg)) return false;
|
|
27359
|
+
if (!isSessionPaused(accountId)) {
|
|
27360
|
+
pauseSession(accountId);
|
|
27361
|
+
logger.warn(
|
|
27362
|
+
`session-guard: permanent binding error, pausing accountId=${accountId} err="${errMsg.slice(0, 120)}" \u2014 re-scan required`
|
|
27363
|
+
);
|
|
27364
|
+
}
|
|
27365
|
+
return true;
|
|
27366
|
+
}
|
|
27367
|
+
var SESSION_PAUSE_DURATION_MS, PERMANENT_ERROR_PATTERNS, pauseUntilMap;
|
|
27368
|
+
var init_session_guard = __esm({
|
|
27369
|
+
"src/api/session-guard.ts"() {
|
|
27370
|
+
"use strict";
|
|
27371
|
+
init_logger();
|
|
27372
|
+
SESSION_PAUSE_DURATION_MS = 60 * 60 * 1e3;
|
|
27373
|
+
PERMANENT_ERROR_PATTERNS = [
|
|
27374
|
+
"\u667A\u80FD\u4F53\u4E0D\u80FD\u4E3A\u7A7A",
|
|
27375
|
+
"\u667A\u80FD\u4F53\u4E0D\u662F\u63A5\u6536\u4EBA\u7684\u667A\u80FD\u4F53",
|
|
27376
|
+
"\u8BBE\u5907\u94FE\u63A5\u5F02\u5E38",
|
|
27377
|
+
"\u7533\u8BF7\u7ED1\u5B9A\u7684AppKey\u4E0D\u5B58\u5728"
|
|
27378
|
+
];
|
|
27379
|
+
pauseUntilMap = /* @__PURE__ */ new Map();
|
|
27380
|
+
}
|
|
27381
|
+
});
|
|
27382
|
+
|
|
27210
27383
|
// src/messaging/send.ts
|
|
27211
27384
|
var send_exports = {};
|
|
27212
27385
|
__export(send_exports, {
|
|
27386
|
+
buildApiOptions: () => buildApiOptions,
|
|
27213
27387
|
pushWorkChatMessage: () => pushWorkChatMessage,
|
|
27214
27388
|
replyWorkChatMessage: () => replyWorkChatMessage
|
|
27215
27389
|
});
|
|
@@ -27255,6 +27429,7 @@ async function replyWorkChatMessage(params) {
|
|
|
27255
27429
|
logger.info(`reply sent to=${to} messageId=${result.msgId}`);
|
|
27256
27430
|
return { messageId: result.msgId };
|
|
27257
27431
|
} catch (err) {
|
|
27432
|
+
pauseOnPermanentError(account.accountId, err instanceof Error ? err.message : String(err));
|
|
27258
27433
|
logger.error(`replyWorkChatMessage: failed to=${to} err=${String(err)}`);
|
|
27259
27434
|
throw err;
|
|
27260
27435
|
}
|
|
@@ -27280,6 +27455,7 @@ async function pushWorkChatMessage(params) {
|
|
|
27280
27455
|
logger.info(`push sent to=${to} messageId=${result.msgId}`);
|
|
27281
27456
|
return { messageId: result.msgId };
|
|
27282
27457
|
} catch (err) {
|
|
27458
|
+
pauseOnPermanentError(account.accountId, err instanceof Error ? err.message : String(err));
|
|
27283
27459
|
logger.error(`pushWorkChatMessage: failed to=${to} err=${String(err)}`);
|
|
27284
27460
|
throw err;
|
|
27285
27461
|
}
|
|
@@ -27289,15 +27465,230 @@ var init_send = __esm({
|
|
|
27289
27465
|
"use strict";
|
|
27290
27466
|
init_types();
|
|
27291
27467
|
init_api();
|
|
27468
|
+
init_session_guard();
|
|
27292
27469
|
init_logger();
|
|
27293
27470
|
}
|
|
27294
27471
|
});
|
|
27295
27472
|
|
|
27473
|
+
// src/messaging/send-media.ts
|
|
27474
|
+
var send_media_exports = {};
|
|
27475
|
+
__export(send_media_exports, {
|
|
27476
|
+
downloadRemoteMediaToTemp: () => downloadRemoteMediaToTemp,
|
|
27477
|
+
isLocalMediaSource: () => isLocalMediaSource,
|
|
27478
|
+
resolveLocalMediaPath: () => resolveLocalMediaPath,
|
|
27479
|
+
sendWorkChatMediaFile: () => sendWorkChatMediaFile
|
|
27480
|
+
});
|
|
27481
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
27482
|
+
import os4 from "os";
|
|
27483
|
+
import path5 from "path";
|
|
27484
|
+
function isLocalMediaSource(mediaUrl) {
|
|
27485
|
+
const trimmed = mediaUrl.trim();
|
|
27486
|
+
if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) return false;
|
|
27487
|
+
return trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith("~") || trimmed.startsWith("file://") || path5.isAbsolute(trimmed);
|
|
27488
|
+
}
|
|
27489
|
+
function resolveLocalMediaPath(mediaUrl) {
|
|
27490
|
+
if (mediaUrl.startsWith("file://")) {
|
|
27491
|
+
const parsed = new URL(mediaUrl);
|
|
27492
|
+
return process.platform === "win32" ? parsed.pathname.replace(/^\/([A-Za-z]:)/, "$1") : parsed.pathname;
|
|
27493
|
+
}
|
|
27494
|
+
if (mediaUrl.startsWith("~")) {
|
|
27495
|
+
return path5.join(os4.homedir(), mediaUrl.slice(1));
|
|
27496
|
+
}
|
|
27497
|
+
return path5.resolve(mediaUrl);
|
|
27498
|
+
}
|
|
27499
|
+
function resolveMediaMsgType(filePath) {
|
|
27500
|
+
const ext = path5.extname(filePath).replace(/^\./, "").toLowerCase();
|
|
27501
|
+
return AUDIO_EXTENSIONS.has(ext) ? "audio" : "image";
|
|
27502
|
+
}
|
|
27503
|
+
function requireAgentId(account, agentId) {
|
|
27504
|
+
const resolved = agentId ?? account.agentId;
|
|
27505
|
+
if (!resolved) {
|
|
27506
|
+
throw new Error("workchat: agentId is required \u2014 complete the binding QR flow first");
|
|
27507
|
+
}
|
|
27508
|
+
return resolved;
|
|
27509
|
+
}
|
|
27510
|
+
async function sendMediaRequest(params) {
|
|
27511
|
+
const agentId = requireAgentId(params.account, params.agentId);
|
|
27512
|
+
assertSessionActive(params.account.accountId);
|
|
27513
|
+
const opts = buildApiOptions(params.account);
|
|
27514
|
+
const body = {
|
|
27515
|
+
agentId,
|
|
27516
|
+
receiveId: params.account.userId ?? params.to,
|
|
27517
|
+
msgType: params.msgType,
|
|
27518
|
+
content: params.content,
|
|
27519
|
+
...params.conversationId ? { conversationId: params.conversationId } : {}
|
|
27520
|
+
};
|
|
27521
|
+
if (params.replyToMessageId) body.is_last = true;
|
|
27522
|
+
try {
|
|
27523
|
+
if (params.replyToMessageId) {
|
|
27524
|
+
const result2 = await sendWorkChatReplyMessage({ opts, messageId: params.replyToMessageId, body });
|
|
27525
|
+
logger.info(`reply media sent to=${params.to} messageId=${result2.msgId}`);
|
|
27526
|
+
return { messageId: result2.msgId };
|
|
27527
|
+
}
|
|
27528
|
+
const result = await sendWorkChatMessage({ opts, body });
|
|
27529
|
+
logger.info(`push media sent to=${params.to} messageId=${result.msgId}`);
|
|
27530
|
+
return { messageId: result.msgId };
|
|
27531
|
+
} catch (err) {
|
|
27532
|
+
pauseOnPermanentError(params.account.accountId, err instanceof Error ? err.message : String(err));
|
|
27533
|
+
throw err;
|
|
27534
|
+
}
|
|
27535
|
+
}
|
|
27536
|
+
async function sendWorkChatMediaFile(params) {
|
|
27537
|
+
const { account, to, filePath } = params;
|
|
27538
|
+
const opts = buildApiOptions(account);
|
|
27539
|
+
logger.info(`sendMedia: uploading filePath=${filePath} to=${to}`);
|
|
27540
|
+
const uploaded = await uploadWorkChatFile({ opts, filePath, userId: account.userId ?? to });
|
|
27541
|
+
logger.info(`sendMedia: upload done urlLen=${uploaded.url.length} suffix=${uploaded.suffix ?? "(none)"}`);
|
|
27542
|
+
const caption = params.text?.trim() ?? "";
|
|
27543
|
+
if (caption) {
|
|
27544
|
+
await pushWorkChatMessage({
|
|
27545
|
+
account,
|
|
27546
|
+
to,
|
|
27547
|
+
text: caption,
|
|
27548
|
+
conversationId: params.conversationId,
|
|
27549
|
+
agentId: params.agentId
|
|
27550
|
+
});
|
|
27551
|
+
}
|
|
27552
|
+
const msgType = resolveMediaMsgType(filePath) === "audio" ? WorkChatMsgType.Audio : WorkChatMsgType.Image;
|
|
27553
|
+
return sendMediaRequest({
|
|
27554
|
+
account,
|
|
27555
|
+
to,
|
|
27556
|
+
msgType,
|
|
27557
|
+
content: JSON.stringify({ url: uploaded.url }),
|
|
27558
|
+
replyToMessageId: params.replyToMessageId,
|
|
27559
|
+
conversationId: params.conversationId,
|
|
27560
|
+
agentId: params.agentId
|
|
27561
|
+
});
|
|
27562
|
+
}
|
|
27563
|
+
function tempMediaPath(ext) {
|
|
27564
|
+
return path5.join(REMOTE_MEDIA_DIR, `${generateId("remote").replace(/:/g, "-")}${ext}`);
|
|
27565
|
+
}
|
|
27566
|
+
function extensionFromUrlOrContentType(contentType, url2) {
|
|
27567
|
+
const fromUrl = path5.extname(new URL(url2).pathname).toLowerCase();
|
|
27568
|
+
if (fromUrl) return fromUrl;
|
|
27569
|
+
if (contentType?.startsWith("audio/mpeg")) return ".mp3";
|
|
27570
|
+
if (contentType?.startsWith("audio/wav")) return ".wav";
|
|
27571
|
+
if (contentType?.startsWith("audio/mp4")) return ".m4a";
|
|
27572
|
+
if (contentType?.startsWith("image/")) return ".png";
|
|
27573
|
+
return ".bin";
|
|
27574
|
+
}
|
|
27575
|
+
async function downloadRemoteMediaToTemp(url2) {
|
|
27576
|
+
const controller = new AbortController();
|
|
27577
|
+
const timeoutId = setTimeout(() => controller.abort(), REMOTE_MEDIA_DOWNLOAD_TIMEOUT_MS);
|
|
27578
|
+
let response;
|
|
27579
|
+
try {
|
|
27580
|
+
response = await globalThis.fetch(url2, { signal: controller.signal });
|
|
27581
|
+
} finally {
|
|
27582
|
+
clearTimeout(timeoutId);
|
|
27583
|
+
}
|
|
27584
|
+
if (!response.ok) {
|
|
27585
|
+
throw new Error(
|
|
27586
|
+
`remote media download failed: ${response.status} ${response.statusText} url=${url2.slice(0, 80)}`
|
|
27587
|
+
);
|
|
27588
|
+
}
|
|
27589
|
+
const buf = Buffer.from(await response.arrayBuffer());
|
|
27590
|
+
const ext = extensionFromUrlOrContentType(response.headers.get("content-type"), url2);
|
|
27591
|
+
await mkdir(REMOTE_MEDIA_DIR, { recursive: true });
|
|
27592
|
+
const filePath = tempMediaPath(ext);
|
|
27593
|
+
await writeFile(filePath, buf);
|
|
27594
|
+
logger.debug(`downloadRemoteMediaToTemp: saved ${buf.length} bytes to ${filePath}`);
|
|
27595
|
+
return filePath;
|
|
27596
|
+
}
|
|
27597
|
+
var AUDIO_EXTENSIONS, REMOTE_MEDIA_DIR, REMOTE_MEDIA_DOWNLOAD_TIMEOUT_MS;
|
|
27598
|
+
var init_send_media = __esm({
|
|
27599
|
+
"src/messaging/send-media.ts"() {
|
|
27600
|
+
"use strict";
|
|
27601
|
+
init_api();
|
|
27602
|
+
init_session_guard();
|
|
27603
|
+
init_types();
|
|
27604
|
+
init_logger();
|
|
27605
|
+
init_random();
|
|
27606
|
+
init_send();
|
|
27607
|
+
AUDIO_EXTENSIONS = /* @__PURE__ */ new Set(["wav", "m4a", "mp3"]);
|
|
27608
|
+
REMOTE_MEDIA_DIR = path5.join(os4.tmpdir(), "openclaw", "workchat", "media");
|
|
27609
|
+
REMOTE_MEDIA_DOWNLOAD_TIMEOUT_MS = 6e4;
|
|
27610
|
+
}
|
|
27611
|
+
});
|
|
27612
|
+
|
|
27613
|
+
// src/messaging/outbound-hooks.ts
|
|
27614
|
+
var outbound_hooks_exports = {};
|
|
27615
|
+
__export(outbound_hooks_exports, {
|
|
27616
|
+
applyWorkChatMessageSendingHook: () => applyWorkChatMessageSendingHook,
|
|
27617
|
+
emitWorkChatMessageSent: () => emitWorkChatMessageSent
|
|
27618
|
+
});
|
|
27619
|
+
import {
|
|
27620
|
+
fireAndForgetHook,
|
|
27621
|
+
buildCanonicalSentMessageHookContext,
|
|
27622
|
+
toPluginMessageContext,
|
|
27623
|
+
toPluginMessageSentEvent
|
|
27624
|
+
} from "openclaw/plugin-sdk/hook-runtime";
|
|
27625
|
+
import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
|
|
27626
|
+
async function applyWorkChatMessageSendingHook(params) {
|
|
27627
|
+
const hookRunner = getGlobalHookRunner();
|
|
27628
|
+
if (!hookRunner?.hasHooks("message_sending")) {
|
|
27629
|
+
return { cancelled: false, text: params.text };
|
|
27630
|
+
}
|
|
27631
|
+
try {
|
|
27632
|
+
const hookResult = await hookRunner.runMessageSending(
|
|
27633
|
+
{
|
|
27634
|
+
to: params.to,
|
|
27635
|
+
content: params.text,
|
|
27636
|
+
metadata: {
|
|
27637
|
+
channel: CHANNEL_ID,
|
|
27638
|
+
accountId: params.accountId,
|
|
27639
|
+
...params.mediaUrl ? { mediaUrls: [params.mediaUrl] } : {}
|
|
27640
|
+
}
|
|
27641
|
+
},
|
|
27642
|
+
{ channelId: CHANNEL_ID, accountId: params.accountId }
|
|
27643
|
+
);
|
|
27644
|
+
if (hookResult?.cancel) {
|
|
27645
|
+
return { cancelled: true, text: params.text };
|
|
27646
|
+
}
|
|
27647
|
+
return {
|
|
27648
|
+
cancelled: false,
|
|
27649
|
+
text: hookResult?.content ?? params.text
|
|
27650
|
+
};
|
|
27651
|
+
} catch (err) {
|
|
27652
|
+
logger.warn(`message_sending hook error, proceeding with send: ${String(err)}`);
|
|
27653
|
+
return { cancelled: false, text: params.text };
|
|
27654
|
+
}
|
|
27655
|
+
}
|
|
27656
|
+
function emitWorkChatMessageSent(params) {
|
|
27657
|
+
const hookRunner = getGlobalHookRunner();
|
|
27658
|
+
if (!hookRunner?.hasHooks("message_sent")) return;
|
|
27659
|
+
const canonical = buildCanonicalSentMessageHookContext({
|
|
27660
|
+
to: params.to,
|
|
27661
|
+
content: params.content,
|
|
27662
|
+
success: params.success,
|
|
27663
|
+
error: params.error,
|
|
27664
|
+
channelId: CHANNEL_ID,
|
|
27665
|
+
accountId: params.accountId,
|
|
27666
|
+
conversationId: params.to
|
|
27667
|
+
});
|
|
27668
|
+
fireAndForgetHook(
|
|
27669
|
+
Promise.resolve(
|
|
27670
|
+
hookRunner.runMessageSent(
|
|
27671
|
+
toPluginMessageSentEvent(canonical),
|
|
27672
|
+
toPluginMessageContext(canonical)
|
|
27673
|
+
)
|
|
27674
|
+
),
|
|
27675
|
+
"workchat: message_sent plugin hook failed"
|
|
27676
|
+
);
|
|
27677
|
+
}
|
|
27678
|
+
var CHANNEL_ID;
|
|
27679
|
+
var init_outbound_hooks = __esm({
|
|
27680
|
+
"src/messaging/outbound-hooks.ts"() {
|
|
27681
|
+
"use strict";
|
|
27682
|
+
init_logger();
|
|
27683
|
+
CHANNEL_ID = "openclaw-workchat";
|
|
27684
|
+
}
|
|
27685
|
+
});
|
|
27686
|
+
|
|
27296
27687
|
// src/messaging/debug-mode.ts
|
|
27297
27688
|
import fs5 from "fs";
|
|
27298
|
-
import
|
|
27689
|
+
import path6 from "path";
|
|
27299
27690
|
function resolveDebugModePath() {
|
|
27300
|
-
return
|
|
27691
|
+
return path6.join(resolveStateDir(), "openclaw-workchat", "debug-mode.json");
|
|
27301
27692
|
}
|
|
27302
27693
|
function loadState() {
|
|
27303
27694
|
try {
|
|
@@ -27310,7 +27701,7 @@ function loadState() {
|
|
|
27310
27701
|
}
|
|
27311
27702
|
function saveState(state) {
|
|
27312
27703
|
const filePath = resolveDebugModePath();
|
|
27313
|
-
fs5.mkdirSync(
|
|
27704
|
+
fs5.mkdirSync(path6.dirname(filePath), { recursive: true });
|
|
27314
27705
|
fs5.writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
|
|
27315
27706
|
}
|
|
27316
27707
|
function toggleDebugMode(accountId) {
|
|
@@ -27420,77 +27811,73 @@ var init_slash_commands = __esm({
|
|
|
27420
27811
|
}
|
|
27421
27812
|
});
|
|
27422
27813
|
|
|
27423
|
-
// src/
|
|
27424
|
-
var
|
|
27425
|
-
__export(
|
|
27426
|
-
|
|
27427
|
-
|
|
27428
|
-
|
|
27429
|
-
|
|
27430
|
-
|
|
27431
|
-
|
|
27432
|
-
|
|
27433
|
-
|
|
27434
|
-
|
|
27435
|
-
|
|
27436
|
-
|
|
27437
|
-
const
|
|
27438
|
-
if (
|
|
27439
|
-
|
|
27440
|
-
}
|
|
27814
|
+
// src/storage/seen-msgids.ts
|
|
27815
|
+
var seen_msgids_exports = {};
|
|
27816
|
+
__export(seen_msgids_exports, {
|
|
27817
|
+
_resetSeenMsgIdsForTest: () => _resetSeenMsgIdsForTest,
|
|
27818
|
+
isDuplicateMessage: () => isDuplicateMessage,
|
|
27819
|
+
recordMessageProcessed: () => recordMessageProcessed
|
|
27820
|
+
});
|
|
27821
|
+
import fs6 from "fs";
|
|
27822
|
+
import path7 from "path";
|
|
27823
|
+
function resolveSeenFilePath(accountId) {
|
|
27824
|
+
const safe = accountId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
27825
|
+
return path7.join(resolveStateDir(), "openclaw-workchat", "accounts", `${safe}.seen-msgids.json`);
|
|
27826
|
+
}
|
|
27827
|
+
function loadSeen(accountId) {
|
|
27828
|
+
const cached2 = cache.get(accountId);
|
|
27829
|
+
if (cached2) return cached2;
|
|
27830
|
+
let ids = [];
|
|
27441
27831
|
try {
|
|
27442
|
-
const
|
|
27443
|
-
|
|
27444
|
-
|
|
27445
|
-
|
|
27446
|
-
metadata: {
|
|
27447
|
-
channel: CHANNEL_ID,
|
|
27448
|
-
accountId: params.accountId,
|
|
27449
|
-
...params.mediaUrl ? { mediaUrls: [params.mediaUrl] } : {}
|
|
27450
|
-
}
|
|
27451
|
-
},
|
|
27452
|
-
{ channelId: CHANNEL_ID, accountId: params.accountId }
|
|
27453
|
-
);
|
|
27454
|
-
if (hookResult?.cancel) {
|
|
27455
|
-
return { cancelled: true, text: params.text };
|
|
27832
|
+
const raw = fs6.readFileSync(resolveSeenFilePath(accountId), "utf-8");
|
|
27833
|
+
const parsed = JSON.parse(raw);
|
|
27834
|
+
if (Array.isArray(parsed.msgIds)) {
|
|
27835
|
+
ids = parsed.msgIds.filter((x) => typeof x === "string" && x !== "");
|
|
27456
27836
|
}
|
|
27457
|
-
|
|
27458
|
-
|
|
27459
|
-
|
|
27460
|
-
|
|
27837
|
+
} catch {
|
|
27838
|
+
}
|
|
27839
|
+
const entry = { ids, index: new Set(ids) };
|
|
27840
|
+
cache.set(accountId, entry);
|
|
27841
|
+
return entry;
|
|
27842
|
+
}
|
|
27843
|
+
function persistSeen(accountId, seen) {
|
|
27844
|
+
try {
|
|
27845
|
+
const filePath = resolveSeenFilePath(accountId);
|
|
27846
|
+
fs6.mkdirSync(path7.dirname(filePath), { recursive: true });
|
|
27847
|
+
fs6.writeFileSync(filePath, JSON.stringify({ msgIds: seen.ids }), "utf-8");
|
|
27461
27848
|
} catch (err) {
|
|
27462
|
-
logger.warn(`
|
|
27463
|
-
return { cancelled: false, text: params.text };
|
|
27849
|
+
logger.warn(`seen-msgids persist failed accountId=${accountId}: ${String(err)}`);
|
|
27464
27850
|
}
|
|
27465
27851
|
}
|
|
27466
|
-
function
|
|
27467
|
-
|
|
27468
|
-
|
|
27469
|
-
|
|
27470
|
-
to: params.to,
|
|
27471
|
-
content: params.content,
|
|
27472
|
-
success: params.success,
|
|
27473
|
-
error: params.error,
|
|
27474
|
-
channelId: CHANNEL_ID,
|
|
27475
|
-
accountId: params.accountId,
|
|
27476
|
-
conversationId: params.to
|
|
27477
|
-
});
|
|
27478
|
-
fireAndForgetHook(
|
|
27479
|
-
Promise.resolve(
|
|
27480
|
-
hookRunner.runMessageSent(
|
|
27481
|
-
toPluginMessageSentEvent(canonical),
|
|
27482
|
-
toPluginMessageContext(canonical)
|
|
27483
|
-
)
|
|
27484
|
-
),
|
|
27485
|
-
"workchat: message_sent plugin hook failed"
|
|
27486
|
-
);
|
|
27852
|
+
function isDuplicateMessage(accountId, msgId) {
|
|
27853
|
+
if (!msgId) return false;
|
|
27854
|
+
const seen = loadSeen(accountId);
|
|
27855
|
+
return seen.index.has(msgId);
|
|
27487
27856
|
}
|
|
27488
|
-
|
|
27489
|
-
|
|
27490
|
-
|
|
27857
|
+
function recordMessageProcessed(accountId, msgId) {
|
|
27858
|
+
if (!msgId) return true;
|
|
27859
|
+
const seen = loadSeen(accountId);
|
|
27860
|
+
if (seen.index.has(msgId)) return false;
|
|
27861
|
+
seen.index.add(msgId);
|
|
27862
|
+
seen.ids.push(msgId);
|
|
27863
|
+
if (seen.ids.length > SEEN_LIMIT) {
|
|
27864
|
+
const drop = seen.ids.length - SEEN_LIMIT;
|
|
27865
|
+
for (const old of seen.ids.splice(0, drop)) seen.index.delete(old);
|
|
27866
|
+
}
|
|
27867
|
+
persistSeen(accountId, seen);
|
|
27868
|
+
return true;
|
|
27869
|
+
}
|
|
27870
|
+
function _resetSeenMsgIdsForTest() {
|
|
27871
|
+
cache.clear();
|
|
27872
|
+
}
|
|
27873
|
+
var SEEN_LIMIT, cache;
|
|
27874
|
+
var init_seen_msgids = __esm({
|
|
27875
|
+
"src/storage/seen-msgids.ts"() {
|
|
27491
27876
|
"use strict";
|
|
27877
|
+
init_state_dir();
|
|
27492
27878
|
init_logger();
|
|
27493
|
-
|
|
27879
|
+
SEEN_LIMIT = 500;
|
|
27880
|
+
cache = /* @__PURE__ */ new Map();
|
|
27494
27881
|
}
|
|
27495
27882
|
});
|
|
27496
27883
|
|
|
@@ -27828,6 +28215,28 @@ function loadWorkChatOutboundHooks() {
|
|
|
27828
28215
|
workchatOutboundHooksPromise ??= Promise.resolve().then(() => (init_outbound_hooks(), outbound_hooks_exports));
|
|
27829
28216
|
return workchatOutboundHooksPromise;
|
|
27830
28217
|
}
|
|
28218
|
+
async function downloadInboundMedia(url2, deps) {
|
|
28219
|
+
try {
|
|
28220
|
+
if (deps.channelRuntime?.media?.fetchRemoteMedia) {
|
|
28221
|
+
const fetched = await deps.channelRuntime.media.fetchRemoteMedia({
|
|
28222
|
+
url: url2,
|
|
28223
|
+
maxBytes: WORKCHAT_MEDIA_MAX_BYTES
|
|
28224
|
+
});
|
|
28225
|
+
return { buffer: fetched.buffer, contentType: fetched.contentType };
|
|
28226
|
+
}
|
|
28227
|
+
} catch (err) {
|
|
28228
|
+
logger.warn(`fetchRemoteMedia failed, trying plain fetch: ${String(err)}`);
|
|
28229
|
+
}
|
|
28230
|
+
const res = await globalThis.fetch(url2);
|
|
28231
|
+
if (!res.ok) {
|
|
28232
|
+
throw new Error(`inbound media download failed: HTTP ${res.status}`);
|
|
28233
|
+
}
|
|
28234
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
28235
|
+
if (buffer.length > WORKCHAT_MEDIA_MAX_BYTES) {
|
|
28236
|
+
throw new Error(`inbound media exceeds limit (${buffer.length} bytes)`);
|
|
28237
|
+
}
|
|
28238
|
+
return { buffer, contentType: res.headers.get("content-type") ?? void 0 };
|
|
28239
|
+
}
|
|
27831
28240
|
async function applyWorkChatMessageSendingHook2(params) {
|
|
27832
28241
|
try {
|
|
27833
28242
|
const hooks = await loadWorkChatOutboundHooks();
|
|
@@ -27843,31 +28252,30 @@ function emitWorkChatMessageSent2(params) {
|
|
|
27843
28252
|
async function handleAgentLifecycleEvent(frameType, result, deps) {
|
|
27844
28253
|
const eventData = result.eventData;
|
|
27845
28254
|
if (!eventData) return;
|
|
27846
|
-
const agentId = String(eventData.id ?? eventData.agentId ?? "");
|
|
28255
|
+
const agentId = String(eventData.id ?? eventData.agentId ?? "").trim();
|
|
27847
28256
|
if (!agentId) {
|
|
27848
28257
|
logger.warn(`${frameType}: missing agent id, ignoring`);
|
|
27849
28258
|
return;
|
|
27850
28259
|
}
|
|
27851
|
-
const userId = String(eventData.futureId ?? eventData.userId ?? "");
|
|
28260
|
+
const userId = String(eventData.futureId ?? eventData.userId ?? "").trim();
|
|
27852
28261
|
logger.info(`${frameType}: agentId=${agentId} userId=${userId ? "present" : "missing"}`);
|
|
27853
28262
|
deps.log(`${frameType}: agentId=${agentId}`);
|
|
27854
|
-
const
|
|
28263
|
+
const { completeWorkChatBinding: completeWorkChatBinding2 } = await Promise.resolve().then(() => (init_login_qr(), login_qr_exports));
|
|
28264
|
+
const accountId = frameType === "init_agent" ? `agent-${agentId}` : deps.accountId;
|
|
27855
28265
|
try {
|
|
27856
|
-
const removed = await
|
|
28266
|
+
const removed = await pruneOtherWorkChatAccounts(accountId);
|
|
27857
28267
|
if (removed.length > 0) {
|
|
27858
|
-
deps.log(`rebind: removed
|
|
28268
|
+
deps.log(`rebind: removed previous account(s): ${removed.join(", ")}`);
|
|
27859
28269
|
}
|
|
27860
28270
|
} catch (err) {
|
|
27861
28271
|
logger.error(`rebind cleanup failed: ${String(err)}`);
|
|
27862
28272
|
}
|
|
27863
|
-
const { completeWorkChatBinding: completeWorkChatBinding2 } = await Promise.resolve().then(() => (init_login_qr(), login_qr_exports));
|
|
27864
|
-
const accountId = frameType === "init_agent" ? isRebind ? `agent-${agentId}` : "default" : deps.accountId;
|
|
27865
28273
|
try {
|
|
27866
28274
|
saveWorkChatAccount(accountId, {
|
|
27867
28275
|
agentId,
|
|
27868
28276
|
...userId ? { userId } : {}
|
|
27869
28277
|
});
|
|
27870
|
-
registerWorkChatAccountId(accountId);
|
|
28278
|
+
await registerWorkChatAccountId(accountId);
|
|
27871
28279
|
const { bindAgentToAccount: bindAgentToAccount2 } = await Promise.resolve().then(() => (init_bind_agent(), bind_agent_exports));
|
|
27872
28280
|
await bindAgentToAccount2(accountId, agentId, userId);
|
|
27873
28281
|
logger.info(`${frameType}: bound agent to account accountId=${accountId}`);
|
|
@@ -27889,9 +28297,6 @@ async function handleAgentLifecycleEvent(frameType, result, deps) {
|
|
|
27889
28297
|
void notifyAgentCreatedStatus(deps.apiOpts, agentId);
|
|
27890
28298
|
}
|
|
27891
28299
|
}
|
|
27892
|
-
function listWorkChatAccountIdsCount() {
|
|
27893
|
-
return listIndexedWorkChatAccountIds().length;
|
|
27894
|
-
}
|
|
27895
28300
|
function loadCreateTypingCallbacks() {
|
|
27896
28301
|
createTypingCallbacksPromise ??= (async () => {
|
|
27897
28302
|
for (const specifier of ["openclaw/plugin-sdk/channel-runtime", "openclaw/plugin-sdk/channel-message"]) {
|
|
@@ -27975,13 +28380,21 @@ async function processOneFrame(result, rawFrame, deps) {
|
|
|
27975
28380
|
logger.debug("inbound: empty body, ignoring");
|
|
27976
28381
|
return;
|
|
27977
28382
|
}
|
|
28383
|
+
if (message.messageId) {
|
|
28384
|
+
const { isDuplicateMessage: isDuplicateMessage2, recordMessageProcessed: recordMessageProcessed2 } = await Promise.resolve().then(() => (init_seen_msgids(), seen_msgids_exports));
|
|
28385
|
+
if (isDuplicateMessage2(deps.accountId, message.messageId)) {
|
|
28386
|
+
logger.info(`inbound: duplicate msgId=${message.messageId}, dropping`);
|
|
28387
|
+
return;
|
|
28388
|
+
}
|
|
28389
|
+
recordMessageProcessed2(deps.accountId, message.messageId);
|
|
28390
|
+
}
|
|
27978
28391
|
const receivedAt = Date.now();
|
|
27979
28392
|
const debug = isDebugMode(deps.accountId);
|
|
27980
28393
|
const debugTrace = [];
|
|
27981
28394
|
const debugTs = { received: receivedAt };
|
|
27982
28395
|
const ctx = workChatMessageToMsgContext(message, deps.accountId);
|
|
27983
28396
|
logger.info(
|
|
27984
|
-
`inbound: from=${ctx.From} to=${ctx.To} bodyLen=${ctx.Body.length} conversationId=${ctx.ConversationId ?? "(none)"}`
|
|
28397
|
+
`inbound: from=${ctx.From} to=${ctx.To} bodyLen=${ctx.Body.length} conversationId=${ctx.ConversationId ?? "(none)"} hasMedia=${Boolean(ctx.MediaUrl)}`
|
|
27985
28398
|
);
|
|
27986
28399
|
logger.debug(`inbound raw frame: ${rawFrame.slice(0, 200)}`);
|
|
27987
28400
|
if (ctx.Body.trim().startsWith("/")) {
|
|
@@ -27996,6 +28409,24 @@ async function processOneFrame(result, rawFrame, deps) {
|
|
|
27996
28409
|
return;
|
|
27997
28410
|
}
|
|
27998
28411
|
}
|
|
28412
|
+
if (ctx.MediaUrl && deps.channelRuntime?.media?.saveMediaBuffer) {
|
|
28413
|
+
try {
|
|
28414
|
+
const media = await downloadInboundMedia(ctx.MediaUrl, deps);
|
|
28415
|
+
if (media) {
|
|
28416
|
+
const saved = await deps.channelRuntime.media.saveMediaBuffer(
|
|
28417
|
+
media.buffer,
|
|
28418
|
+
media.contentType,
|
|
28419
|
+
"inbound",
|
|
28420
|
+
WORKCHAT_MEDIA_MAX_BYTES
|
|
28421
|
+
);
|
|
28422
|
+
ctx.MediaPath = saved.path;
|
|
28423
|
+
ctx.MediaType = media.contentType ?? ctx.MediaType;
|
|
28424
|
+
logger.info(`inbound media saved: path=${saved.path} type=${media.contentType}`);
|
|
28425
|
+
}
|
|
28426
|
+
} catch (err) {
|
|
28427
|
+
deps.errLog(`inbound media download failed url=${redactBody(ctx.MediaUrl)}: ${String(err)}`);
|
|
28428
|
+
}
|
|
28429
|
+
}
|
|
27999
28430
|
const rawBody = ctx.Body?.trim() ?? "";
|
|
28000
28431
|
ctx.CommandBody = rawBody;
|
|
28001
28432
|
const senderId = ctx.From;
|
|
@@ -28096,7 +28527,10 @@ async function processOneFrame(result, rawFrame, deps) {
|
|
|
28096
28527
|
const rawText = String(payload.text ?? "");
|
|
28097
28528
|
const f = new StreamingMarkdownFilter2();
|
|
28098
28529
|
let text = f.feed(rawText) + f.flush();
|
|
28099
|
-
|
|
28530
|
+
const mediaUrl = payload.mediaUrl ?? payload.mediaUrls?.[0];
|
|
28531
|
+
logger.info(
|
|
28532
|
+
`outbound: to=${ctx.To} textLen=${text.length} mediaUrl=${mediaUrl ? "present" : "none"}`
|
|
28533
|
+
);
|
|
28100
28534
|
if (debug) {
|
|
28101
28535
|
debugDeliveries.push({
|
|
28102
28536
|
textLen: text.length,
|
|
@@ -28107,7 +28541,8 @@ async function processOneFrame(result, rawFrame, deps) {
|
|
|
28107
28541
|
const sendingResult = await applyWorkChatMessageSendingHook2({
|
|
28108
28542
|
to: ctx.To,
|
|
28109
28543
|
text,
|
|
28110
|
-
accountId: deps.accountId
|
|
28544
|
+
accountId: deps.accountId,
|
|
28545
|
+
mediaUrl
|
|
28111
28546
|
});
|
|
28112
28547
|
if (sendingResult.cancelled) {
|
|
28113
28548
|
logger.info(`outbound: cancelled by message_sending hook to=${ctx.To}`);
|
|
@@ -28115,6 +28550,40 @@ async function processOneFrame(result, rawFrame, deps) {
|
|
|
28115
28550
|
}
|
|
28116
28551
|
text = sendingResult.text;
|
|
28117
28552
|
try {
|
|
28553
|
+
if (mediaUrl) {
|
|
28554
|
+
const { isLocalMediaSource: isLocalMediaSource2, resolveLocalMediaPath: resolveLocalMediaPath2, downloadRemoteMediaToTemp: downloadRemoteMediaToTemp2, sendWorkChatMediaFile: sendWorkChatMediaFile2 } = await Promise.resolve().then(() => (init_send_media(), send_media_exports));
|
|
28555
|
+
let filePath;
|
|
28556
|
+
if (isLocalMediaSource2(mediaUrl)) {
|
|
28557
|
+
filePath = resolveLocalMediaPath2(mediaUrl);
|
|
28558
|
+
logger.debug(`outbound: local media resolved filePath=${filePath}`);
|
|
28559
|
+
} else if (mediaUrl.startsWith("http://") || mediaUrl.startsWith("https://")) {
|
|
28560
|
+
logger.debug(`outbound: downloading remote mediaUrl=${mediaUrl.slice(0, 80)}...`);
|
|
28561
|
+
filePath = await downloadRemoteMediaToTemp2(mediaUrl);
|
|
28562
|
+
} else {
|
|
28563
|
+
logger.warn(
|
|
28564
|
+
`outbound: unrecognized mediaUrl scheme, sending text only mediaUrl=${mediaUrl.slice(0, 80)}`
|
|
28565
|
+
);
|
|
28566
|
+
filePath = "";
|
|
28567
|
+
}
|
|
28568
|
+
if (filePath) {
|
|
28569
|
+
await sendWorkChatMediaFile2({
|
|
28570
|
+
account: {
|
|
28571
|
+
...deps.account,
|
|
28572
|
+
agentId: ctx.AgentId ?? deps.account.agentId,
|
|
28573
|
+
userId: ctx.From || deps.account.userId
|
|
28574
|
+
},
|
|
28575
|
+
to: ctx.To,
|
|
28576
|
+
filePath,
|
|
28577
|
+
text,
|
|
28578
|
+
replyToMessageId: ctx.MessageSid,
|
|
28579
|
+
conversationId: ctx.ConversationId,
|
|
28580
|
+
agentId: ctx.AgentId
|
|
28581
|
+
});
|
|
28582
|
+
emitWorkChatMessageSent2({ to: ctx.To, content: text, success: true, accountId: deps.accountId });
|
|
28583
|
+
logger.info(`outbound: media reply sent OK to=${ctx.To}`);
|
|
28584
|
+
return;
|
|
28585
|
+
}
|
|
28586
|
+
}
|
|
28118
28587
|
const result2 = await replyWorkChatMessage2({
|
|
28119
28588
|
account: {
|
|
28120
28589
|
...deps.account,
|
|
@@ -28139,7 +28608,14 @@ async function processOneFrame(result, rawFrame, deps) {
|
|
|
28139
28608
|
onError: (err, info) => {
|
|
28140
28609
|
deps.errLog(`workchat reply ${info.kind}: ${String(err)}`);
|
|
28141
28610
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
28142
|
-
|
|
28611
|
+
let notice;
|
|
28612
|
+
if (errMsg.includes("remote media download failed")) {
|
|
28613
|
+
notice = `\u26A0\uFE0F \u5A92\u4F53\u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u94FE\u63A5\u662F\u5426\u53EF\u8BBF\u95EE\u3002`;
|
|
28614
|
+
} else if (errMsg.includes("file upload response") || errMsg.includes("upload failed")) {
|
|
28615
|
+
notice = `\u26A0\uFE0F \u5A92\u4F53\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`;
|
|
28616
|
+
} else {
|
|
28617
|
+
notice = `\u26A0\uFE0F \u6D88\u606F\u53D1\u9001\u5931\u8D25\uFF1A${errMsg}`;
|
|
28618
|
+
}
|
|
28143
28619
|
void sendWorkChatErrorNotice({
|
|
28144
28620
|
account: deps.account,
|
|
28145
28621
|
to: ctx.To,
|
|
@@ -28209,7 +28685,7 @@ ${debugTrace.join("\n")}`;
|
|
|
28209
28685
|
}
|
|
28210
28686
|
}
|
|
28211
28687
|
}
|
|
28212
|
-
var workchatOutboundHooksPromise, createTypingCallbacksPromise;
|
|
28688
|
+
var workchatOutboundHooksPromise, WORKCHAT_MEDIA_MAX_BYTES, createTypingCallbacksPromise;
|
|
28213
28689
|
var init_process_message = __esm({
|
|
28214
28690
|
"src/messaging/process-message.ts"() {
|
|
28215
28691
|
"use strict";
|
|
@@ -28223,6 +28699,7 @@ var init_process_message = __esm({
|
|
|
28223
28699
|
init_inbound();
|
|
28224
28700
|
init_slash_commands();
|
|
28225
28701
|
workchatOutboundHooksPromise = null;
|
|
28702
|
+
WORKCHAT_MEDIA_MAX_BYTES = 100 * 1024 * 1024;
|
|
28226
28703
|
}
|
|
28227
28704
|
});
|
|
28228
28705
|
|
|
@@ -28277,8 +28754,8 @@ async function monitorWorkChatProvider(opts) {
|
|
|
28277
28754
|
localIp: opts.localIp
|
|
28278
28755
|
});
|
|
28279
28756
|
const url2 = `${endpoint}?ticket=${encodeURIComponent(ticket)}`;
|
|
28280
|
-
const dispatcher = apiOpts.allowInsecureTls ? new
|
|
28281
|
-
ws = new
|
|
28757
|
+
const dispatcher = apiOpts.allowInsecureTls ? new import_undici2.Agent({ connect: { rejectUnauthorized: false } }) : void 0;
|
|
28758
|
+
ws = new import_undici2.WebSocket(url2, dispatcher ? { dispatcher } : void 0);
|
|
28282
28759
|
await new Promise((resolve, reject) => {
|
|
28283
28760
|
const timer = setTimeout(
|
|
28284
28761
|
() => reject(new Error("workchat websocket connection timeout")),
|
|
@@ -28411,11 +28888,11 @@ async function monitorWorkChatProvider(opts) {
|
|
|
28411
28888
|
}
|
|
28412
28889
|
}
|
|
28413
28890
|
}
|
|
28414
|
-
var
|
|
28891
|
+
var import_undici2, WS_CONNECT_TIMEOUT_MS, RECONNECT_BACKOFF_BASE_MS, RECONNECT_BACKOFF_MAX_MS, RATE_LIMIT_BACKOFF_MS;
|
|
28415
28892
|
var init_monitor = __esm({
|
|
28416
28893
|
"src/monitor/monitor.ts"() {
|
|
28417
28894
|
"use strict";
|
|
28418
|
-
|
|
28895
|
+
import_undici2 = __toESM(require_undici(), 1);
|
|
28419
28896
|
init_api();
|
|
28420
28897
|
init_api();
|
|
28421
28898
|
init_inbound();
|
|
@@ -29529,8 +30006,10 @@ import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-sch
|
|
|
29529
30006
|
|
|
29530
30007
|
// src/channel.ts
|
|
29531
30008
|
init_accounts();
|
|
30009
|
+
init_types();
|
|
29532
30010
|
init_login_qr();
|
|
29533
30011
|
init_send();
|
|
30012
|
+
init_send_media();
|
|
29534
30013
|
init_logger();
|
|
29535
30014
|
function resolveOutboundAccount(cfg, accountId) {
|
|
29536
30015
|
const allIds = listWorkChatAccountIds(cfg);
|
|
@@ -29583,7 +30062,8 @@ var workchatPlugin = {
|
|
|
29583
30062
|
messageToolHints: () => [
|
|
29584
30063
|
"To send a message to the current WorkChat user, use the message tool with action='send'. You do not need to specify 'to' \u2014 the current conversation recipient is used automatically.",
|
|
29585
30064
|
"IMPORTANT: When creating a cron job (scheduled task) for the current WorkChat user, you MUST set delivery.to to the user's WorkChat ID (the numeric ID from the current conversation) AND set delivery.accountId to the current AccountId. Without an explicit 'to', the cron delivery will fail with 'requires target'. Without an explicit 'accountId', the message may be sent from the wrong bot account. Example: delivery: { mode: 'announce', channel: 'openclaw-workchat', to: '<current_user_id>', accountId: '<current_AccountId>' }.",
|
|
29586
|
-
"
|
|
30065
|
+
"To send an image or audio file to the current user, use the message tool with action='send' and set 'media' to a local file path or a remote HTTPS URL. Supported audio formats: wav, m4a, mp3; supported image formats: bmp, gif, jpg, jpeg, png, webp. Remote URLs are downloaded and re-uploaded to WorkChat storage automatically \u2014 the client renders image/audio cards, never bare links.",
|
|
30066
|
+
"IMPORTANT: When generating or saving a file to send, always use an absolute path (e.g. /tmp/photo.png or C:\\tmp\\photo.png on Windows), never a relative path like ./photo.png. Relative paths cannot be resolved and the file will not be delivered."
|
|
29587
30067
|
]
|
|
29588
30068
|
},
|
|
29589
30069
|
reload: { configPrefixes: ["channels.openclaw-workchat"] },
|
|
@@ -29618,13 +30098,62 @@ var workchatPlugin = {
|
|
|
29618
30098
|
},
|
|
29619
30099
|
sendMedia: async (ctx) => {
|
|
29620
30100
|
const account = resolveOutboundAccount(ctx.cfg, ctx.accountId);
|
|
29621
|
-
const
|
|
29622
|
-
const
|
|
29623
|
-
|
|
30101
|
+
const aLog = logger.withAccount(account.accountId);
|
|
30102
|
+
const mediaUrl = ctx.mediaUrl?.trim();
|
|
30103
|
+
let text = ctx.text ?? "";
|
|
30104
|
+
const { applyWorkChatMessageSendingHook: applyWorkChatMessageSendingHook3, emitWorkChatMessageSent: emitWorkChatMessageSent3 } = await Promise.resolve().then(() => (init_outbound_hooks(), outbound_hooks_exports));
|
|
30105
|
+
const sendingResult = await applyWorkChatMessageSendingHook3({
|
|
29624
30106
|
to: ctx.to,
|
|
29625
|
-
text
|
|
30107
|
+
text,
|
|
30108
|
+
accountId: account.accountId,
|
|
30109
|
+
mediaUrl
|
|
30110
|
+
}).catch((err) => {
|
|
30111
|
+
aLog.warn(`message_sending hook error, proceeding: ${String(err)}`);
|
|
30112
|
+
return { cancelled: false, text };
|
|
29626
30113
|
});
|
|
29627
|
-
|
|
30114
|
+
if (sendingResult.cancelled) {
|
|
30115
|
+
aLog.info(`sendMedia: cancelled by message_sending hook to=${ctx.to}`);
|
|
30116
|
+
return { channel: "openclaw-workchat", messageId: "" };
|
|
30117
|
+
}
|
|
30118
|
+
text = sendingResult.text;
|
|
30119
|
+
if (!mediaUrl) {
|
|
30120
|
+
try {
|
|
30121
|
+
const result = await pushWorkChatMessage({ account, to: ctx.to, text });
|
|
30122
|
+
emitWorkChatMessageSent3({ to: ctx.to, content: text, success: true, accountId: account.accountId });
|
|
30123
|
+
return { channel: "openclaw-workchat", messageId: result.messageId };
|
|
30124
|
+
} catch (err) {
|
|
30125
|
+
emitWorkChatMessageSent3({ to: ctx.to, content: text, success: false, error: String(err), accountId: account.accountId });
|
|
30126
|
+
throw err;
|
|
30127
|
+
}
|
|
30128
|
+
}
|
|
30129
|
+
let filePath;
|
|
30130
|
+
try {
|
|
30131
|
+
if (isLocalMediaSource(mediaUrl)) {
|
|
30132
|
+
filePath = resolveLocalMediaPath(mediaUrl);
|
|
30133
|
+
aLog.debug(`sendMedia: uploading local file ${filePath}`);
|
|
30134
|
+
} else {
|
|
30135
|
+
aLog.debug(`sendMedia: downloading remote mediaUrl=${mediaUrl.slice(0, 80)}...`);
|
|
30136
|
+
filePath = await downloadRemoteMediaToTemp(mediaUrl);
|
|
30137
|
+
aLog.debug(`sendMedia: remote media downloaded to ${filePath}`);
|
|
30138
|
+
}
|
|
30139
|
+
} catch (err) {
|
|
30140
|
+
emitWorkChatMessageSent3({ to: ctx.to, content: text, success: false, error: String(err), accountId: account.accountId });
|
|
30141
|
+
throw err;
|
|
30142
|
+
}
|
|
30143
|
+
try {
|
|
30144
|
+
const result = await sendWorkChatMediaFile({
|
|
30145
|
+
account,
|
|
30146
|
+
to: ctx.to,
|
|
30147
|
+
filePath,
|
|
30148
|
+
text,
|
|
30149
|
+
replyToMessageId: ctx.replyToId?.trim() || void 0
|
|
30150
|
+
});
|
|
30151
|
+
emitWorkChatMessageSent3({ to: ctx.to, content: text, success: true, accountId: account.accountId });
|
|
30152
|
+
return { channel: "openclaw-workchat", messageId: result.messageId };
|
|
30153
|
+
} catch (err) {
|
|
30154
|
+
emitWorkChatMessageSent3({ to: ctx.to, content: text, success: false, error: String(err), accountId: account.accountId });
|
|
30155
|
+
throw err;
|
|
30156
|
+
}
|
|
29628
30157
|
}
|
|
29629
30158
|
},
|
|
29630
30159
|
status: {
|
|
@@ -29705,11 +30234,13 @@ var workchatPlugin = {
|
|
|
29705
30234
|
loginWithQrStart: async ({ accountId, force, verbose }) => {
|
|
29706
30235
|
const { loadConfig } = await import("openclaw/plugin-sdk/config-runtime");
|
|
29707
30236
|
const cfg = loadConfig();
|
|
29708
|
-
const
|
|
30237
|
+
const requestedAccountId = accountId?.trim() || listWorkChatAccountIds(cfg)[0];
|
|
30238
|
+
const existing = requestedAccountId ? resolveWorkChatAccount(cfg, requestedAccountId) : void 0;
|
|
30239
|
+
const section = cfg.channels?.["openclaw-workchat"];
|
|
29709
30240
|
const result = await startWorkChatLoginWithQr({
|
|
29710
|
-
baseUrl:
|
|
29711
|
-
appKey:
|
|
29712
|
-
appSecret:
|
|
30241
|
+
baseUrl: existing?.baseUrl || section?.baseUrl || DEFAULT_BASE_URL,
|
|
30242
|
+
appKey: existing?.appKey || section?.appKey?.trim() || void 0,
|
|
30243
|
+
appSecret: existing?.appSecret || section?.appSecret?.trim() || void 0
|
|
29713
30244
|
});
|
|
29714
30245
|
return {
|
|
29715
30246
|
qrDataUrl: result.qrcodeUrl,
|
|
@@ -29816,6 +30347,9 @@ function assertHostCompatibility(hostVersion) {
|
|
|
29816
30347
|
);
|
|
29817
30348
|
}
|
|
29818
30349
|
|
|
30350
|
+
// index.ts
|
|
30351
|
+
init_accounts();
|
|
30352
|
+
|
|
29819
30353
|
// node_modules/zod/v4/classic/external.js
|
|
29820
30354
|
var external_exports = {};
|
|
29821
30355
|
__export(external_exports, {
|
|
@@ -30633,10 +31167,10 @@ function mergeDefs(...defs) {
|
|
|
30633
31167
|
function cloneDef(schema) {
|
|
30634
31168
|
return mergeDefs(schema._zod.def);
|
|
30635
31169
|
}
|
|
30636
|
-
function getElementAtPath(obj,
|
|
30637
|
-
if (!
|
|
31170
|
+
function getElementAtPath(obj, path8) {
|
|
31171
|
+
if (!path8)
|
|
30638
31172
|
return obj;
|
|
30639
|
-
return
|
|
31173
|
+
return path8.reduce((acc, key) => acc?.[key], obj);
|
|
30640
31174
|
}
|
|
30641
31175
|
function promiseAllObject(promisesObj) {
|
|
30642
31176
|
const keys = Object.keys(promisesObj);
|
|
@@ -30976,11 +31510,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
30976
31510
|
}
|
|
30977
31511
|
return false;
|
|
30978
31512
|
}
|
|
30979
|
-
function prefixIssues(
|
|
31513
|
+
function prefixIssues(path8, issues) {
|
|
30980
31514
|
return issues.map((iss) => {
|
|
30981
31515
|
var _a3;
|
|
30982
31516
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
30983
|
-
iss.path.unshift(
|
|
31517
|
+
iss.path.unshift(path8);
|
|
30984
31518
|
return iss;
|
|
30985
31519
|
});
|
|
30986
31520
|
}
|
|
@@ -31442,16 +31976,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
|
|
|
31442
31976
|
}
|
|
31443
31977
|
function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
31444
31978
|
const fieldErrors = { _errors: [] };
|
|
31445
|
-
const processError = (error63,
|
|
31979
|
+
const processError = (error63, path8 = []) => {
|
|
31446
31980
|
for (const issue2 of error63.issues) {
|
|
31447
31981
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
31448
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
31982
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
31449
31983
|
} else if (issue2.code === "invalid_key") {
|
|
31450
|
-
processError({ issues: issue2.issues }, [...
|
|
31984
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
31451
31985
|
} else if (issue2.code === "invalid_element") {
|
|
31452
|
-
processError({ issues: issue2.issues }, [...
|
|
31986
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
31453
31987
|
} else {
|
|
31454
|
-
const fullpath = [...
|
|
31988
|
+
const fullpath = [...path8, ...issue2.path];
|
|
31455
31989
|
if (fullpath.length === 0) {
|
|
31456
31990
|
fieldErrors._errors.push(mapper(issue2));
|
|
31457
31991
|
} else {
|
|
@@ -31490,17 +32024,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
|
31490
32024
|
}
|
|
31491
32025
|
function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
31492
32026
|
const result = { errors: [] };
|
|
31493
|
-
const processError = (error63,
|
|
32027
|
+
const processError = (error63, path8 = []) => {
|
|
31494
32028
|
var _a3;
|
|
31495
32029
|
for (const issue2 of error63.issues) {
|
|
31496
32030
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
31497
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
32031
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
31498
32032
|
} else if (issue2.code === "invalid_key") {
|
|
31499
|
-
processError({ issues: issue2.issues }, [...
|
|
32033
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
31500
32034
|
} else if (issue2.code === "invalid_element") {
|
|
31501
|
-
processError({ issues: issue2.issues }, [...
|
|
32035
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
31502
32036
|
} else {
|
|
31503
|
-
const fullpath = [...
|
|
32037
|
+
const fullpath = [...path8, ...issue2.path];
|
|
31504
32038
|
if (fullpath.length === 0) {
|
|
31505
32039
|
result.errors.push(mapper(issue2));
|
|
31506
32040
|
continue;
|
|
@@ -31539,8 +32073,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
|
31539
32073
|
}
|
|
31540
32074
|
function toDotPath(_path) {
|
|
31541
32075
|
const segs = [];
|
|
31542
|
-
const
|
|
31543
|
-
for (const seg of
|
|
32076
|
+
const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
32077
|
+
for (const seg of path8) {
|
|
31544
32078
|
if (typeof seg === "number")
|
|
31545
32079
|
segs.push(`[${seg}]`);
|
|
31546
32080
|
else if (typeof seg === "symbol")
|
|
@@ -48669,13 +49203,13 @@ function resolveRef(ref, ctx) {
|
|
|
48669
49203
|
if (!ref.startsWith("#")) {
|
|
48670
49204
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
48671
49205
|
}
|
|
48672
|
-
const
|
|
48673
|
-
if (
|
|
49206
|
+
const path8 = ref.slice(1).split("/").filter(Boolean);
|
|
49207
|
+
if (path8.length === 0) {
|
|
48674
49208
|
return ctx.rootSchema;
|
|
48675
49209
|
}
|
|
48676
49210
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
48677
|
-
if (
|
|
48678
|
-
const key =
|
|
49211
|
+
if (path8[0] === defsKey) {
|
|
49212
|
+
const key = path8[1] === void 0 ? void 0 : decodeJSONPointerSegment(path8[1]);
|
|
48679
49213
|
if (!key || !ctx.defs[key]) {
|
|
48680
49214
|
throw new Error(`Reference not found: ${ref}`);
|
|
48681
49215
|
}
|
|
@@ -49309,21 +49843,21 @@ function visit(schema, fnOrHandlers) {
|
|
|
49309
49843
|
const h = fnOrHandlers[node2._zod.def.type];
|
|
49310
49844
|
return h ? h(node2, rewritten) : node2;
|
|
49311
49845
|
};
|
|
49312
|
-
const
|
|
49846
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
49313
49847
|
function run(s) {
|
|
49314
|
-
const cached2 =
|
|
49848
|
+
const cached2 = cache2.get(s);
|
|
49315
49849
|
if (cached2 === RESOLVING) {
|
|
49316
49850
|
return new $ZodLazy({
|
|
49317
49851
|
type: "lazy",
|
|
49318
|
-
getter: () =>
|
|
49852
|
+
getter: () => cache2.get(s)
|
|
49319
49853
|
});
|
|
49320
49854
|
}
|
|
49321
49855
|
if (cached2 !== void 0)
|
|
49322
49856
|
return cached2;
|
|
49323
|
-
|
|
49857
|
+
cache2.set(s, RESOLVING);
|
|
49324
49858
|
const inner = mapInner(s);
|
|
49325
49859
|
const mapped = fn(inner, inner !== s);
|
|
49326
|
-
|
|
49860
|
+
cache2.set(s, mapped);
|
|
49327
49861
|
return mapped;
|
|
49328
49862
|
}
|
|
49329
49863
|
function mapInner(s) {
|
|
@@ -49552,6 +50086,9 @@ var openclaw_workchat_default = {
|
|
|
49552
50086
|
configSchema: buildChannelConfigSchema(WorkChatConfigSchema),
|
|
49553
50087
|
register(api) {
|
|
49554
50088
|
assertHostCompatibility(api.runtime?.version);
|
|
50089
|
+
void migrateLegacyDefaultWorkChatAccount().catch((err) => {
|
|
50090
|
+
console.error("[openclaw-workchat] legacy default account migration failed:", err);
|
|
50091
|
+
});
|
|
49555
50092
|
api.registerChannel({ plugin: workchatPlugin });
|
|
49556
50093
|
}
|
|
49557
50094
|
};
|