@ycodium-ai/plugin-im 0.2.2968 → 0.2.2974
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/README.md +61 -3
- package/dist/index.js +1409 -739
- package/locales/en.json +30 -4
- package/locales/zh-CN.json +30 -4
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -24,9 +24,9 @@ var __commonJS = (cb, mod) => function __require2() {
|
|
|
24
24
|
throw mod = 0, e;
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
|
-
var __export = (
|
|
27
|
+
var __export = (target2, all) => {
|
|
28
28
|
for (var name in all)
|
|
29
|
-
__defProp(
|
|
29
|
+
__defProp(target2, name, { get: all[name], enumerable: true });
|
|
30
30
|
};
|
|
31
31
|
var __copyProps = (to, from, except, desc) => {
|
|
32
32
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -36,12 +36,12 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
36
36
|
}
|
|
37
37
|
return to;
|
|
38
38
|
};
|
|
39
|
-
var __toESM = (mod, isNodeMode,
|
|
39
|
+
var __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
40
40
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
41
41
|
// file that has been converted to a CommonJS file using a Babel-
|
|
42
42
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
43
43
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
44
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(
|
|
44
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target2, "default", { value: mod, enumerable: true }) : target2,
|
|
45
45
|
mod
|
|
46
46
|
));
|
|
47
47
|
|
|
@@ -9683,15 +9683,15 @@ var require_implementation = __commonJS({
|
|
|
9683
9683
|
return str2;
|
|
9684
9684
|
};
|
|
9685
9685
|
module.exports = function bind(that) {
|
|
9686
|
-
var
|
|
9687
|
-
if (typeof
|
|
9688
|
-
throw new TypeError(ERROR_MESSAGE +
|
|
9686
|
+
var target2 = this;
|
|
9687
|
+
if (typeof target2 !== "function" || toStr.apply(target2) !== funcType) {
|
|
9688
|
+
throw new TypeError(ERROR_MESSAGE + target2);
|
|
9689
9689
|
}
|
|
9690
9690
|
var args = slicy(arguments, 1);
|
|
9691
9691
|
var bound;
|
|
9692
9692
|
var binder = function() {
|
|
9693
9693
|
if (this instanceof bound) {
|
|
9694
|
-
var result =
|
|
9694
|
+
var result = target2.apply(
|
|
9695
9695
|
this,
|
|
9696
9696
|
concatty(args, arguments)
|
|
9697
9697
|
);
|
|
@@ -9700,21 +9700,21 @@ var require_implementation = __commonJS({
|
|
|
9700
9700
|
}
|
|
9701
9701
|
return this;
|
|
9702
9702
|
}
|
|
9703
|
-
return
|
|
9703
|
+
return target2.apply(
|
|
9704
9704
|
that,
|
|
9705
9705
|
concatty(args, arguments)
|
|
9706
9706
|
);
|
|
9707
9707
|
};
|
|
9708
|
-
var boundLength = max(0,
|
|
9708
|
+
var boundLength = max(0, target2.length - args.length);
|
|
9709
9709
|
var boundArgs = [];
|
|
9710
9710
|
for (var i = 0; i < boundLength; i++) {
|
|
9711
9711
|
boundArgs[i] = "$" + i;
|
|
9712
9712
|
}
|
|
9713
9713
|
bound = Function("binder", "return function (" + joiny(boundArgs, ",") + "){ return binder.apply(this,arguments); }")(binder);
|
|
9714
|
-
if (
|
|
9714
|
+
if (target2.prototype) {
|
|
9715
9715
|
var Empty = function Empty2() {
|
|
9716
9716
|
};
|
|
9717
|
-
Empty.prototype =
|
|
9717
|
+
Empty.prototype = target2.prototype;
|
|
9718
9718
|
bound.prototype = new Empty();
|
|
9719
9719
|
Empty.prototype = null;
|
|
9720
9720
|
}
|
|
@@ -12219,8 +12219,8 @@ var require_follow_redirects = __commonJS({
|
|
|
12219
12219
|
}
|
|
12220
12220
|
return input;
|
|
12221
12221
|
}
|
|
12222
|
-
function spreadUrlObject(urlObject,
|
|
12223
|
-
var spread =
|
|
12222
|
+
function spreadUrlObject(urlObject, target2) {
|
|
12223
|
+
var spread = target2 || {};
|
|
12224
12224
|
for (var key of preservedUrlFields) {
|
|
12225
12225
|
spread[key] = urlObject[key];
|
|
12226
12226
|
}
|
|
@@ -12768,22 +12768,22 @@ var require_axios = __commonJS({
|
|
|
12768
12768
|
}
|
|
12769
12769
|
if (!("toJSON" in source)) {
|
|
12770
12770
|
visited.add(source);
|
|
12771
|
-
let
|
|
12771
|
+
let target2;
|
|
12772
12772
|
if (isSet(source)) {
|
|
12773
|
-
|
|
12773
|
+
target2 = [];
|
|
12774
12774
|
for (const value2 of source) {
|
|
12775
12775
|
const reducedValue = visit(value2);
|
|
12776
|
-
!isUndefined(reducedValue) &&
|
|
12776
|
+
!isUndefined(reducedValue) && target2.push(reducedValue);
|
|
12777
12777
|
}
|
|
12778
12778
|
} else {
|
|
12779
|
-
|
|
12779
|
+
target2 = isArray(source) ? [] : {};
|
|
12780
12780
|
forEach(source, (value2, key) => {
|
|
12781
12781
|
const reducedValue = visit(value2);
|
|
12782
|
-
!isUndefined(reducedValue) && (
|
|
12782
|
+
!isUndefined(reducedValue) && (target2[key] = reducedValue);
|
|
12783
12783
|
});
|
|
12784
12784
|
}
|
|
12785
12785
|
visited.delete(source);
|
|
12786
|
-
return
|
|
12786
|
+
return target2;
|
|
12787
12787
|
}
|
|
12788
12788
|
}
|
|
12789
12789
|
return source;
|
|
@@ -13234,7 +13234,7 @@ var require_axios = __commonJS({
|
|
|
13234
13234
|
}
|
|
13235
13235
|
static concat(first, ...targets) {
|
|
13236
13236
|
const computed = new this(first);
|
|
13237
|
-
targets.forEach((
|
|
13237
|
+
targets.forEach((target2) => computed.set(target2));
|
|
13238
13238
|
return computed;
|
|
13239
13239
|
}
|
|
13240
13240
|
static accessor(header) {
|
|
@@ -13862,27 +13862,27 @@ var require_axios = __commonJS({
|
|
|
13862
13862
|
return obj;
|
|
13863
13863
|
}
|
|
13864
13864
|
function formDataToJSON(formData) {
|
|
13865
|
-
function buildPath(path2, value2,
|
|
13865
|
+
function buildPath(path2, value2, target2, index) {
|
|
13866
13866
|
throwIfDepthExceeded(index);
|
|
13867
13867
|
let name = path2[index++];
|
|
13868
13868
|
if (name === "__proto__") return true;
|
|
13869
13869
|
const isNumericKey = Number.isFinite(+name);
|
|
13870
13870
|
const isLast = index >= path2.length;
|
|
13871
|
-
name = !name && utils$1.isArray(
|
|
13871
|
+
name = !name && utils$1.isArray(target2) ? target2.length : name;
|
|
13872
13872
|
if (isLast) {
|
|
13873
|
-
if (utils$1.hasOwnProp(
|
|
13874
|
-
|
|
13873
|
+
if (utils$1.hasOwnProp(target2, name)) {
|
|
13874
|
+
target2[name] = utils$1.isArray(target2[name]) ? target2[name].concat(value2) : [target2[name], value2];
|
|
13875
13875
|
} else {
|
|
13876
|
-
|
|
13876
|
+
target2[name] = value2;
|
|
13877
13877
|
}
|
|
13878
13878
|
return !isNumericKey;
|
|
13879
13879
|
}
|
|
13880
|
-
if (!utils$1.hasOwnProp(
|
|
13881
|
-
|
|
13880
|
+
if (!utils$1.hasOwnProp(target2, name) || !utils$1.isObject(target2[name])) {
|
|
13881
|
+
target2[name] = [];
|
|
13882
13882
|
}
|
|
13883
|
-
const result = buildPath(path2, value2,
|
|
13884
|
-
if (result && utils$1.isArray(
|
|
13885
|
-
|
|
13883
|
+
const result = buildPath(path2, value2, target2[name], index);
|
|
13884
|
+
if (result && utils$1.isArray(target2[name])) {
|
|
13885
|
+
target2[name] = arrayToObject(target2[name]);
|
|
13886
13886
|
}
|
|
13887
13887
|
return !isNumericKey;
|
|
13888
13888
|
}
|
|
@@ -16043,11 +16043,11 @@ var require_axios = __commonJS({
|
|
|
16043
16043
|
writable: true,
|
|
16044
16044
|
configurable: true
|
|
16045
16045
|
});
|
|
16046
|
-
function getMergedValue(
|
|
16047
|
-
if (utils$1.isPlainObject(
|
|
16046
|
+
function getMergedValue(target2, source, prop, caseless) {
|
|
16047
|
+
if (utils$1.isPlainObject(target2) && utils$1.isPlainObject(source)) {
|
|
16048
16048
|
return utils$1.merge.call({
|
|
16049
16049
|
caseless
|
|
16050
|
-
},
|
|
16050
|
+
}, target2, source);
|
|
16051
16051
|
} else if (utils$1.isPlainObject(source)) {
|
|
16052
16052
|
return utils$1.merge({}, source);
|
|
16053
16053
|
} else if (utils$1.isArray(source)) {
|
|
@@ -16862,14 +16862,14 @@ var require_axios = __commonJS({
|
|
|
16862
16862
|
Response
|
|
16863
16863
|
} = env;
|
|
16864
16864
|
const seeds = [Request, Response, fetch2];
|
|
16865
|
-
let len = seeds.length, i = len, seed,
|
|
16865
|
+
let len = seeds.length, i = len, seed, target2, map = seedCache;
|
|
16866
16866
|
while (i--) {
|
|
16867
16867
|
seed = seeds[i];
|
|
16868
|
-
|
|
16869
|
-
|
|
16870
|
-
map =
|
|
16868
|
+
target2 = map.get(seed);
|
|
16869
|
+
target2 === void 0 && map.set(seed, target2 = i ? /* @__PURE__ */ new Map() : factory(env));
|
|
16870
|
+
map = target2;
|
|
16871
16871
|
}
|
|
16872
|
-
return
|
|
16872
|
+
return target2;
|
|
16873
16873
|
};
|
|
16874
16874
|
getFetch();
|
|
16875
16875
|
var knownAdapters = {
|
|
@@ -18377,46 +18377,46 @@ var require_utils = __commonJS({
|
|
|
18377
18377
|
obj[key] = value2;
|
|
18378
18378
|
}
|
|
18379
18379
|
};
|
|
18380
|
-
var merge = function merge2(
|
|
18380
|
+
var merge = function merge2(target2, source, options) {
|
|
18381
18381
|
if (!source) {
|
|
18382
|
-
return
|
|
18382
|
+
return target2;
|
|
18383
18383
|
}
|
|
18384
18384
|
if (typeof source !== "object" && typeof source !== "function") {
|
|
18385
|
-
if (isArray(
|
|
18386
|
-
var nextIndex =
|
|
18385
|
+
if (isArray(target2)) {
|
|
18386
|
+
var nextIndex = target2.length;
|
|
18387
18387
|
if (options && typeof options.arrayLimit === "number" && nextIndex >= options.arrayLimit) {
|
|
18388
18388
|
if (options.throwOnLimitExceeded) {
|
|
18389
18389
|
throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array.");
|
|
18390
18390
|
}
|
|
18391
|
-
return markOverflow(arrayToObject(
|
|
18392
|
-
}
|
|
18393
|
-
|
|
18394
|
-
} else if (
|
|
18395
|
-
if (isOverflow(
|
|
18396
|
-
var newIndex = getMaxIndex(
|
|
18397
|
-
|
|
18398
|
-
setMaxIndex(
|
|
18391
|
+
return markOverflow(arrayToObject(target2.concat(source), options), nextIndex);
|
|
18392
|
+
}
|
|
18393
|
+
target2[nextIndex] = source;
|
|
18394
|
+
} else if (target2 && typeof target2 === "object") {
|
|
18395
|
+
if (isOverflow(target2)) {
|
|
18396
|
+
var newIndex = getMaxIndex(target2) + 1;
|
|
18397
|
+
target2[newIndex] = source;
|
|
18398
|
+
setMaxIndex(target2, newIndex);
|
|
18399
18399
|
} else if (options && options.strictMerge) {
|
|
18400
|
-
return [
|
|
18400
|
+
return [target2, source];
|
|
18401
18401
|
} else if (options && (options.plainObjects || options.allowPrototypes) || !has.call(Object.prototype, source)) {
|
|
18402
|
-
|
|
18402
|
+
target2[source] = true;
|
|
18403
18403
|
}
|
|
18404
18404
|
} else {
|
|
18405
|
-
return [
|
|
18405
|
+
return [target2, source];
|
|
18406
18406
|
}
|
|
18407
|
-
return
|
|
18407
|
+
return target2;
|
|
18408
18408
|
}
|
|
18409
|
-
if (!
|
|
18409
|
+
if (!target2 || typeof target2 !== "object") {
|
|
18410
18410
|
if (isOverflow(source)) {
|
|
18411
18411
|
var sourceKeys = Object.keys(source);
|
|
18412
|
-
var result = options && options.plainObjects ? { __proto__: null, 0:
|
|
18412
|
+
var result = options && options.plainObjects ? { __proto__: null, 0: target2 } : { 0: target2 };
|
|
18413
18413
|
for (var m = 0; m < sourceKeys.length; m++) {
|
|
18414
18414
|
var oldKey = parseInt(sourceKeys[m], 10);
|
|
18415
18415
|
result[oldKey + 1] = source[sourceKeys[m]];
|
|
18416
18416
|
}
|
|
18417
18417
|
return markOverflow(result, getMaxIndex(source) + 1);
|
|
18418
18418
|
}
|
|
18419
|
-
var combined = [
|
|
18419
|
+
var combined = [target2].concat(source);
|
|
18420
18420
|
if (options && typeof options.arrayLimit === "number" && combined.length > options.arrayLimit) {
|
|
18421
18421
|
if (options.throwOnLimitExceeded) {
|
|
18422
18422
|
throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array.");
|
|
@@ -18425,30 +18425,30 @@ var require_utils = __commonJS({
|
|
|
18425
18425
|
}
|
|
18426
18426
|
return combined;
|
|
18427
18427
|
}
|
|
18428
|
-
var mergeTarget =
|
|
18429
|
-
if (isArray(
|
|
18430
|
-
mergeTarget = arrayToObject(
|
|
18428
|
+
var mergeTarget = target2;
|
|
18429
|
+
if (isArray(target2) && !isArray(source)) {
|
|
18430
|
+
mergeTarget = arrayToObject(target2, options);
|
|
18431
18431
|
}
|
|
18432
|
-
if (isArray(
|
|
18432
|
+
if (isArray(target2) && isArray(source)) {
|
|
18433
18433
|
source.forEach(function(item, i) {
|
|
18434
|
-
if (has.call(
|
|
18435
|
-
var targetItem =
|
|
18434
|
+
if (has.call(target2, i)) {
|
|
18435
|
+
var targetItem = target2[i];
|
|
18436
18436
|
if (targetItem && typeof targetItem === "object" && item && typeof item === "object") {
|
|
18437
|
-
|
|
18437
|
+
target2[i] = merge2(targetItem, item, options);
|
|
18438
18438
|
} else {
|
|
18439
|
-
|
|
18439
|
+
target2[target2.length] = item;
|
|
18440
18440
|
}
|
|
18441
18441
|
} else {
|
|
18442
|
-
|
|
18442
|
+
target2[i] = item;
|
|
18443
18443
|
}
|
|
18444
18444
|
});
|
|
18445
|
-
if (options && typeof options.arrayLimit === "number" &&
|
|
18445
|
+
if (options && typeof options.arrayLimit === "number" && target2.length > options.arrayLimit) {
|
|
18446
18446
|
if (options.throwOnLimitExceeded) {
|
|
18447
18447
|
throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array.");
|
|
18448
18448
|
}
|
|
18449
|
-
return markOverflow(arrayToObject(
|
|
18449
|
+
return markOverflow(arrayToObject(target2, options), target2.length - 1);
|
|
18450
18450
|
}
|
|
18451
|
-
return
|
|
18451
|
+
return target2;
|
|
18452
18452
|
}
|
|
18453
18453
|
return Object.keys(source).reduce(function(acc, key) {
|
|
18454
18454
|
var value2 = source[key];
|
|
@@ -18469,11 +18469,11 @@ var require_utils = __commonJS({
|
|
|
18469
18469
|
return acc;
|
|
18470
18470
|
}, mergeTarget);
|
|
18471
18471
|
};
|
|
18472
|
-
var assign = function assignSingleSource(
|
|
18472
|
+
var assign = function assignSingleSource(target2, source) {
|
|
18473
18473
|
return Object.keys(source).reduce(function(acc, key) {
|
|
18474
18474
|
setProperty(acc, key, source[key]);
|
|
18475
18475
|
return acc;
|
|
18476
|
-
},
|
|
18476
|
+
}, target2);
|
|
18477
18477
|
};
|
|
18478
18478
|
var decode2 = function(str2, defaultDecoder, charset) {
|
|
18479
18479
|
var strWithoutPlus = str2.replace(/\+/g, " ");
|
|
@@ -20911,7 +20911,7 @@ var require_node_gyp_build = __commonJS({
|
|
|
20911
20911
|
if (prebuild) return prebuild;
|
|
20912
20912
|
var nearby = resolve(path.dirname(process.execPath));
|
|
20913
20913
|
if (nearby) return nearby;
|
|
20914
|
-
var
|
|
20914
|
+
var target2 = [
|
|
20915
20915
|
"platform=" + platform,
|
|
20916
20916
|
"arch=" + arch,
|
|
20917
20917
|
"runtime=" + runtime,
|
|
@@ -20924,7 +20924,7 @@ var require_node_gyp_build = __commonJS({
|
|
|
20924
20924
|
typeof __webpack_require__ === "function" ? "webpack=true" : ""
|
|
20925
20925
|
// eslint-disable-line
|
|
20926
20926
|
].filter(Boolean).join(" ");
|
|
20927
|
-
throw new Error("No native build was found for " +
|
|
20927
|
+
throw new Error("No native build was found for " + target2 + "\n loaded from: " + dir + "\n");
|
|
20928
20928
|
function resolve(dir2) {
|
|
20929
20929
|
var tuples = readdirSync(path.join(dir2, "prebuilds")).map(parseTuple);
|
|
20930
20930
|
var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
|
|
@@ -21095,17 +21095,17 @@ var require_buffer_util = __commonJS({
|
|
|
21095
21095
|
function concat(list2, totalLength) {
|
|
21096
21096
|
if (list2.length === 0) return EMPTY_BUFFER;
|
|
21097
21097
|
if (list2.length === 1) return list2[0];
|
|
21098
|
-
const
|
|
21098
|
+
const target2 = Buffer.allocUnsafe(totalLength);
|
|
21099
21099
|
let offset = 0;
|
|
21100
21100
|
for (let i = 0; i < list2.length; i++) {
|
|
21101
21101
|
const buf = list2[i];
|
|
21102
|
-
|
|
21102
|
+
target2.set(buf, offset);
|
|
21103
21103
|
offset += buf.length;
|
|
21104
21104
|
}
|
|
21105
21105
|
if (offset < totalLength) {
|
|
21106
|
-
return new FastBuffer(
|
|
21106
|
+
return new FastBuffer(target2.buffer, target2.byteOffset, offset);
|
|
21107
21107
|
}
|
|
21108
|
-
return
|
|
21108
|
+
return target2;
|
|
21109
21109
|
}
|
|
21110
21110
|
function _mask(source, mask, output, offset, length) {
|
|
21111
21111
|
for (let i = 0; i < length; i++) {
|
|
@@ -22587,29 +22587,29 @@ var require_sender = __commonJS({
|
|
|
22587
22587
|
offset += 2;
|
|
22588
22588
|
payloadLength = 126;
|
|
22589
22589
|
}
|
|
22590
|
-
const
|
|
22591
|
-
|
|
22592
|
-
if (options.rsv1)
|
|
22593
|
-
|
|
22590
|
+
const target2 = Buffer.allocUnsafe(merge ? dataLength + offset : offset);
|
|
22591
|
+
target2[0] = options.fin ? options.opcode | 128 : options.opcode;
|
|
22592
|
+
if (options.rsv1) target2[0] |= 64;
|
|
22593
|
+
target2[1] = payloadLength;
|
|
22594
22594
|
if (payloadLength === 126) {
|
|
22595
|
-
|
|
22595
|
+
target2.writeUInt16BE(dataLength, 2);
|
|
22596
22596
|
} else if (payloadLength === 127) {
|
|
22597
|
-
|
|
22598
|
-
|
|
22599
|
-
}
|
|
22600
|
-
if (!options.mask) return [
|
|
22601
|
-
|
|
22602
|
-
|
|
22603
|
-
|
|
22604
|
-
|
|
22605
|
-
|
|
22606
|
-
if (skipMasking) return [
|
|
22597
|
+
target2[2] = target2[3] = 0;
|
|
22598
|
+
target2.writeUIntBE(dataLength, 4, 6);
|
|
22599
|
+
}
|
|
22600
|
+
if (!options.mask) return [target2, data];
|
|
22601
|
+
target2[1] |= 128;
|
|
22602
|
+
target2[offset - 4] = mask[0];
|
|
22603
|
+
target2[offset - 3] = mask[1];
|
|
22604
|
+
target2[offset - 2] = mask[2];
|
|
22605
|
+
target2[offset - 1] = mask[3];
|
|
22606
|
+
if (skipMasking) return [target2, data];
|
|
22607
22607
|
if (merge) {
|
|
22608
|
-
applyMask(data, mask,
|
|
22609
|
-
return [
|
|
22608
|
+
applyMask(data, mask, target2, offset, dataLength);
|
|
22609
|
+
return [target2];
|
|
22610
22610
|
}
|
|
22611
22611
|
applyMask(data, mask, data, 0, dataLength);
|
|
22612
|
-
return [
|
|
22612
|
+
return [target2, data];
|
|
22613
22613
|
}
|
|
22614
22614
|
/**
|
|
22615
22615
|
* Sends a close message to the other peer.
|
|
@@ -126168,6 +126168,11 @@ var makeAcknowledgements = (core) => {
|
|
|
126168
126168
|
const acknowledgements = /* @__PURE__ */ new Map();
|
|
126169
126169
|
const markWorking = async (binding, threadId, messageId) => {
|
|
126170
126170
|
const adapter = adapterFor(binding.platform);
|
|
126171
|
+
if (adapter?.sendTyping !== void 0) {
|
|
126172
|
+
void adapter.sendTyping(binding).catch((error) => {
|
|
126173
|
+
host.log.info("chat could not show typing", { error: describeError(error) });
|
|
126174
|
+
});
|
|
126175
|
+
}
|
|
126171
126176
|
if (adapter?.acknowledge === void 0) return;
|
|
126172
126177
|
try {
|
|
126173
126178
|
const ackId = await adapter.acknowledge(binding, messageId);
|
|
@@ -126180,14 +126185,14 @@ var makeAcknowledgements = (core) => {
|
|
|
126180
126185
|
host.log.warn("chat could not acknowledge the message", { error: describeError(error) });
|
|
126181
126186
|
}
|
|
126182
126187
|
};
|
|
126183
|
-
const clearWorking = async (binding, threadId) => {
|
|
126188
|
+
const clearWorking = async (binding, threadId, outcome) => {
|
|
126184
126189
|
const adapter = adapterFor(binding.platform);
|
|
126185
126190
|
const pending = acknowledgements.get(threadId);
|
|
126186
126191
|
if (pending === void 0 || adapter?.clearAcknowledge === void 0) return;
|
|
126187
126192
|
acknowledgements.delete(threadId);
|
|
126188
126193
|
for (const entry of pending) {
|
|
126189
126194
|
try {
|
|
126190
|
-
await adapter.clearAcknowledge(binding, entry.messageId, entry.ackId);
|
|
126195
|
+
await adapter.clearAcknowledge(binding, entry.messageId, entry.ackId, outcome);
|
|
126191
126196
|
} catch (error) {
|
|
126192
126197
|
host.log.warn("chat could not clear the acknowledgement", {
|
|
126193
126198
|
error: describeError(error)
|
|
@@ -126220,6 +126225,26 @@ var readAttached = (data) => {
|
|
|
126220
126225
|
return chatKey === null || threadId === null || projectId === null || attachedAt === null ? null : { chatKey, threadId, projectId, attachedAt };
|
|
126221
126226
|
};
|
|
126222
126227
|
|
|
126228
|
+
// src/chatAliases.ts
|
|
126229
|
+
var aliasKey = (rowId, alias) => `${rowId}:${alias}`;
|
|
126230
|
+
var chatAliasOf = (state, rowId, alias) => state.aliases?.[aliasKey(rowId, alias)];
|
|
126231
|
+
var nonEmpty2 = (value2) => typeof value2 === "string" && value2 !== "" ? value2 : null;
|
|
126232
|
+
var foldAliased = (state, data) => {
|
|
126233
|
+
const rowId = nonEmpty2(data["rowId"]);
|
|
126234
|
+
const alias = nonEmpty2(data["alias"]);
|
|
126235
|
+
const chatId = nonEmpty2(data["chatId"]);
|
|
126236
|
+
if (rowId === null || alias === null || chatId === null) return state;
|
|
126237
|
+
const key = aliasKey(rowId, alias);
|
|
126238
|
+
if (state.aliases?.[key] !== void 0) return state;
|
|
126239
|
+
return { ...state, aliases: { ...state.aliases, [key]: chatId } };
|
|
126240
|
+
};
|
|
126241
|
+
|
|
126242
|
+
// src/keepNewest.ts
|
|
126243
|
+
var keepNewest = (record2, limit) => {
|
|
126244
|
+
const entries = Object.entries(record2);
|
|
126245
|
+
return entries.length <= limit ? record2 : Object.fromEntries(entries.slice(entries.length - limit));
|
|
126246
|
+
};
|
|
126247
|
+
|
|
126223
126248
|
// src/chatState.ts
|
|
126224
126249
|
var IM_STATE_KEY = "chats";
|
|
126225
126250
|
var IM_STATE_VERSION = 1;
|
|
@@ -126231,7 +126256,8 @@ var emptyState = () => ({
|
|
|
126231
126256
|
approvals: {},
|
|
126232
126257
|
turnCards: {},
|
|
126233
126258
|
questions: {},
|
|
126234
|
-
queue: {}
|
|
126259
|
+
queue: {},
|
|
126260
|
+
aliases: {}
|
|
126235
126261
|
});
|
|
126236
126262
|
var questionsOf = (state) => state.questions ?? {};
|
|
126237
126263
|
var queueOf = (state) => state.queue ?? {};
|
|
@@ -126289,11 +126315,11 @@ var openQueueOfThread = (state, threadId) => Object.values(queueOf(state)).filte
|
|
|
126289
126315
|
(record2) => record2.threadId === threadId && record2.settled === void 0
|
|
126290
126316
|
);
|
|
126291
126317
|
var isRecord = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
126292
|
-
var
|
|
126318
|
+
var nonEmpty3 = (value2) => typeof value2 === "string" && value2 !== "" ? value2 : null;
|
|
126293
126319
|
var readTarget = (value2) => {
|
|
126294
126320
|
if (!isRecord(value2)) return null;
|
|
126295
126321
|
if (value2["kind"] === "thread") return { kind: "thread" };
|
|
126296
|
-
const teamId =
|
|
126322
|
+
const teamId = nonEmpty3(value2["teamId"]);
|
|
126297
126323
|
return value2["kind"] === "team" && teamId !== null ? { kind: "team", teamId } : null;
|
|
126298
126324
|
};
|
|
126299
126325
|
var readButtons = (value2) => {
|
|
@@ -126301,8 +126327,8 @@ var readButtons = (value2) => {
|
|
|
126301
126327
|
const buttons = [];
|
|
126302
126328
|
for (const entry of value2) {
|
|
126303
126329
|
if (!isRecord(entry)) return null;
|
|
126304
|
-
const token =
|
|
126305
|
-
const decision =
|
|
126330
|
+
const token = nonEmpty3(entry["token"]);
|
|
126331
|
+
const decision = nonEmpty3(entry["decision"]);
|
|
126306
126332
|
const label = typeof entry["label"] === "string" ? entry["label"] : null;
|
|
126307
126333
|
if (token === null || decision === null || label === null) return null;
|
|
126308
126334
|
buttons.push({ token, label, decision });
|
|
@@ -126314,8 +126340,8 @@ var readQuestionOptions = (value2) => {
|
|
|
126314
126340
|
const options = [];
|
|
126315
126341
|
for (const entry of value2) {
|
|
126316
126342
|
if (!isRecord(entry)) return null;
|
|
126317
|
-
const token =
|
|
126318
|
-
const optionValue =
|
|
126343
|
+
const token = nonEmpty3(entry["token"]);
|
|
126344
|
+
const optionValue = nonEmpty3(entry["value"]);
|
|
126319
126345
|
if (token === null || optionValue === null || typeof entry["label"] !== "string") return null;
|
|
126320
126346
|
const planAction = entry["planAction"];
|
|
126321
126347
|
options.push({
|
|
@@ -126333,10 +126359,10 @@ var readQuestionItems = (value2) => {
|
|
|
126333
126359
|
const items = [];
|
|
126334
126360
|
for (const entry of value2) {
|
|
126335
126361
|
if (!isRecord(entry)) return null;
|
|
126336
|
-
const id =
|
|
126362
|
+
const id = nonEmpty3(entry["id"]);
|
|
126337
126363
|
const options = readQuestionOptions(entry["options"]);
|
|
126338
126364
|
if (id === null || options === null || typeof entry["question"] !== "string") return null;
|
|
126339
|
-
const submitToken =
|
|
126365
|
+
const submitToken = nonEmpty3(entry["submitToken"]);
|
|
126340
126366
|
items.push({
|
|
126341
126367
|
id,
|
|
126342
126368
|
header: typeof entry["header"] === "string" ? entry["header"] : "",
|
|
@@ -126379,10 +126405,6 @@ var withQueueRecord = (state, intentId, patch) => {
|
|
|
126379
126405
|
if (intentId === null || record2 === void 0) return state;
|
|
126380
126406
|
return { ...state, queue: { ...queueOf(state), [intentId]: patch(record2) } };
|
|
126381
126407
|
};
|
|
126382
|
-
var keepNewest = (record2, limit) => {
|
|
126383
|
-
const entries = Object.entries(record2);
|
|
126384
|
-
return entries.length <= limit ? record2 : Object.fromEntries(entries.slice(entries.length - limit));
|
|
126385
|
-
};
|
|
126386
126408
|
var withChat = (state, chatKey, patch) => ({
|
|
126387
126409
|
...state,
|
|
126388
126410
|
chats: { ...state.chats, [chatKey]: { ...chatOf(state, chatKey), ...patch } }
|
|
@@ -126391,19 +126413,19 @@ var foldImEvent = (state, name, data) => {
|
|
|
126391
126413
|
if (!isRecord(data)) return state;
|
|
126392
126414
|
switch (name) {
|
|
126393
126415
|
case "chat-updated": {
|
|
126394
|
-
const chatKey =
|
|
126416
|
+
const chatKey = nonEmpty3(data["chatKey"]);
|
|
126395
126417
|
if (chatKey === null) return state;
|
|
126396
126418
|
const patch = {};
|
|
126397
126419
|
if (data["projectId"] === null) patch.projectId = null;
|
|
126398
|
-
else if (
|
|
126420
|
+
else if (nonEmpty3(data["projectId"]) !== null) patch.projectId = nonEmpty3(data["projectId"]);
|
|
126399
126421
|
if (data["threadId"] === null) patch.threadId = null;
|
|
126400
|
-
else if (
|
|
126401
|
-
const
|
|
126402
|
-
if (
|
|
126422
|
+
else if (nonEmpty3(data["threadId"]) !== null) patch.threadId = nonEmpty3(data["threadId"]);
|
|
126423
|
+
const target2 = readTarget(data["target"]);
|
|
126424
|
+
if (target2 !== null) patch.target = target2;
|
|
126403
126425
|
if (data["model"] === null) patch.model = null;
|
|
126404
126426
|
else if (isRecord(data["model"])) {
|
|
126405
|
-
const instanceId =
|
|
126406
|
-
const model =
|
|
126427
|
+
const instanceId = nonEmpty3(data["model"]["instanceId"]);
|
|
126428
|
+
const model = nonEmpty3(data["model"]["model"]);
|
|
126407
126429
|
if (instanceId !== null && model !== null) patch.model = { instanceId, model };
|
|
126408
126430
|
}
|
|
126409
126431
|
if (typeof data["plan"] === "boolean") patch.plan = data["plan"];
|
|
@@ -126414,10 +126436,10 @@ var foldImEvent = (state, name, data) => {
|
|
|
126414
126436
|
return withChat(state, chatKey, patch);
|
|
126415
126437
|
}
|
|
126416
126438
|
case "thread-opened": {
|
|
126417
|
-
const chatKey =
|
|
126418
|
-
const threadId =
|
|
126419
|
-
const projectId =
|
|
126420
|
-
const openedAt =
|
|
126439
|
+
const chatKey = nonEmpty3(data["chatKey"]);
|
|
126440
|
+
const threadId = nonEmpty3(data["threadId"]);
|
|
126441
|
+
const projectId = nonEmpty3(data["projectId"]);
|
|
126442
|
+
const openedAt = nonEmpty3(data["openedAt"]);
|
|
126421
126443
|
if (chatKey === null || threadId === null || projectId === null || openedAt === null) {
|
|
126422
126444
|
return state;
|
|
126423
126445
|
}
|
|
@@ -126438,9 +126460,9 @@ var foldImEvent = (state, name, data) => {
|
|
|
126438
126460
|
return { ...state, attached: keepNewest(attached, ATTACHED_THREAD_LIMIT) };
|
|
126439
126461
|
}
|
|
126440
126462
|
case "approval-offered": {
|
|
126441
|
-
const chatKey =
|
|
126442
|
-
const threadId =
|
|
126443
|
-
const requestId =
|
|
126463
|
+
const chatKey = nonEmpty3(data["chatKey"]);
|
|
126464
|
+
const threadId = nonEmpty3(data["threadId"]);
|
|
126465
|
+
const requestId = nonEmpty3(data["requestId"]);
|
|
126444
126466
|
const options = readButtons(data["options"]);
|
|
126445
126467
|
if (chatKey === null || threadId === null || requestId === null || options === null) {
|
|
126446
126468
|
return state;
|
|
@@ -126457,7 +126479,7 @@ var foldImEvent = (state, name, data) => {
|
|
|
126457
126479
|
};
|
|
126458
126480
|
}
|
|
126459
126481
|
case "approval-resolved": {
|
|
126460
|
-
const requestId =
|
|
126482
|
+
const requestId = nonEmpty3(data["requestId"]);
|
|
126461
126483
|
const existing = requestId === null ? void 0 : state.approvals[requestId];
|
|
126462
126484
|
if (requestId === null || existing === void 0) return state;
|
|
126463
126485
|
return {
|
|
@@ -126466,8 +126488,8 @@ var foldImEvent = (state, name, data) => {
|
|
|
126466
126488
|
};
|
|
126467
126489
|
}
|
|
126468
126490
|
case "approval-carded": {
|
|
126469
|
-
const requestId =
|
|
126470
|
-
const cardId =
|
|
126491
|
+
const requestId = nonEmpty3(data["requestId"]);
|
|
126492
|
+
const cardId = nonEmpty3(data["cardId"]);
|
|
126471
126493
|
const existing = requestId === null ? void 0 : state.approvals[requestId];
|
|
126472
126494
|
if (requestId === null || cardId === null || existing === void 0) return state;
|
|
126473
126495
|
return {
|
|
@@ -126476,9 +126498,9 @@ var foldImEvent = (state, name, data) => {
|
|
|
126476
126498
|
};
|
|
126477
126499
|
}
|
|
126478
126500
|
case "question-offered": {
|
|
126479
|
-
const chatKey =
|
|
126480
|
-
const threadId =
|
|
126481
|
-
const requestId =
|
|
126501
|
+
const chatKey = nonEmpty3(data["chatKey"]);
|
|
126502
|
+
const threadId = nonEmpty3(data["threadId"]);
|
|
126503
|
+
const requestId = nonEmpty3(data["requestId"]);
|
|
126482
126504
|
const items = readQuestionItems(data["items"]);
|
|
126483
126505
|
if (chatKey === null || threadId === null || requestId === null || items === null) {
|
|
126484
126506
|
return state;
|
|
@@ -126495,12 +126517,12 @@ var foldImEvent = (state, name, data) => {
|
|
|
126495
126517
|
};
|
|
126496
126518
|
}
|
|
126497
126519
|
case "question-carded": {
|
|
126498
|
-
const cardId =
|
|
126520
|
+
const cardId = nonEmpty3(data["cardId"]);
|
|
126499
126521
|
if (cardId === null) return state;
|
|
126500
126522
|
return withQuestionItem(
|
|
126501
126523
|
state,
|
|
126502
|
-
|
|
126503
|
-
|
|
126524
|
+
nonEmpty3(data["requestId"]),
|
|
126525
|
+
nonEmpty3(data["questionId"]),
|
|
126504
126526
|
(item) => ({ ...item, cardId })
|
|
126505
126527
|
);
|
|
126506
126528
|
}
|
|
@@ -126509,8 +126531,8 @@ var foldImEvent = (state, name, data) => {
|
|
|
126509
126531
|
if (!Array.isArray(selected)) return state;
|
|
126510
126532
|
return withQuestionItem(
|
|
126511
126533
|
state,
|
|
126512
|
-
|
|
126513
|
-
|
|
126534
|
+
nonEmpty3(data["requestId"]),
|
|
126535
|
+
nonEmpty3(data["questionId"]),
|
|
126514
126536
|
(item) => ({ ...item, selected })
|
|
126515
126537
|
);
|
|
126516
126538
|
}
|
|
@@ -126520,13 +126542,13 @@ var foldImEvent = (state, name, data) => {
|
|
|
126520
126542
|
const label = typeof data["label"] === "string" ? data["label"] : "";
|
|
126521
126543
|
return withQuestionItem(
|
|
126522
126544
|
state,
|
|
126523
|
-
|
|
126524
|
-
|
|
126545
|
+
nonEmpty3(data["requestId"]),
|
|
126546
|
+
nonEmpty3(data["questionId"]),
|
|
126525
126547
|
(item) => ({ ...item, answer, answerLabel: label })
|
|
126526
126548
|
);
|
|
126527
126549
|
}
|
|
126528
126550
|
case "question-resolved": {
|
|
126529
|
-
const requestId =
|
|
126551
|
+
const requestId = nonEmpty3(data["requestId"]);
|
|
126530
126552
|
const existing = requestId === null ? void 0 : questionsOf(state)[requestId];
|
|
126531
126553
|
if (requestId === null || existing === void 0) return state;
|
|
126532
126554
|
const ending = data["ending"];
|
|
@@ -126543,12 +126565,12 @@ var foldImEvent = (state, name, data) => {
|
|
|
126543
126565
|
};
|
|
126544
126566
|
}
|
|
126545
126567
|
case "queue-offered": {
|
|
126546
|
-
const chatKey =
|
|
126547
|
-
const threadId =
|
|
126548
|
-
const intentId =
|
|
126549
|
-
const steerToken =
|
|
126550
|
-
const withdrawToken =
|
|
126551
|
-
const resumeToken =
|
|
126568
|
+
const chatKey = nonEmpty3(data["chatKey"]);
|
|
126569
|
+
const threadId = nonEmpty3(data["threadId"]);
|
|
126570
|
+
const intentId = nonEmpty3(data["intentId"]);
|
|
126571
|
+
const steerToken = nonEmpty3(data["steerToken"]);
|
|
126572
|
+
const withdrawToken = nonEmpty3(data["withdrawToken"]);
|
|
126573
|
+
const resumeToken = nonEmpty3(data["resumeToken"]);
|
|
126552
126574
|
if (chatKey === null || threadId === null || intentId === null || steerToken === null || withdrawToken === null || resumeToken === null) {
|
|
126553
126575
|
return state;
|
|
126554
126576
|
}
|
|
@@ -126573,30 +126595,30 @@ var foldImEvent = (state, name, data) => {
|
|
|
126573
126595
|
};
|
|
126574
126596
|
}
|
|
126575
126597
|
case "queue-carded": {
|
|
126576
|
-
const cardId =
|
|
126598
|
+
const cardId = nonEmpty3(data["cardId"]);
|
|
126577
126599
|
if (cardId === null) return state;
|
|
126578
|
-
return withQueueRecord(state,
|
|
126600
|
+
return withQueueRecord(state, nonEmpty3(data["intentId"]), (record2) => ({
|
|
126579
126601
|
...record2,
|
|
126580
126602
|
cardId
|
|
126581
126603
|
}));
|
|
126582
126604
|
}
|
|
126583
126605
|
case "queue-steering":
|
|
126584
|
-
return withQueueRecord(state,
|
|
126606
|
+
return withQueueRecord(state, nonEmpty3(data["intentId"]), (record2) => ({
|
|
126585
126607
|
...record2,
|
|
126586
126608
|
steering: data["steering"] === true
|
|
126587
126609
|
}));
|
|
126588
126610
|
case "queue-settled": {
|
|
126589
126611
|
const outcome = data["outcome"];
|
|
126590
126612
|
if (outcome !== "steered" && outcome !== "sent" && outcome !== "removed") return state;
|
|
126591
|
-
return withQueueRecord(state,
|
|
126613
|
+
return withQueueRecord(state, nonEmpty3(data["intentId"]), (record2) => ({
|
|
126592
126614
|
...record2,
|
|
126593
126615
|
settled: outcome
|
|
126594
126616
|
}));
|
|
126595
126617
|
}
|
|
126596
126618
|
case "turn-card-opened": {
|
|
126597
|
-
const cardId =
|
|
126598
|
-
const chatKey =
|
|
126599
|
-
const threadId =
|
|
126619
|
+
const cardId = nonEmpty3(data["cardId"]);
|
|
126620
|
+
const chatKey = nonEmpty3(data["chatKey"]);
|
|
126621
|
+
const threadId = nonEmpty3(data["threadId"]);
|
|
126600
126622
|
if (cardId === null || chatKey === null || threadId === null) return state;
|
|
126601
126623
|
const title = typeof data["title"] === "string" ? data["title"] : "";
|
|
126602
126624
|
return {
|
|
@@ -126608,11 +126630,13 @@ var foldImEvent = (state, name, data) => {
|
|
|
126608
126630
|
};
|
|
126609
126631
|
}
|
|
126610
126632
|
case "turn-card-closed": {
|
|
126611
|
-
const cardId =
|
|
126633
|
+
const cardId = nonEmpty3(data["cardId"]);
|
|
126612
126634
|
if (cardId === null) return state;
|
|
126613
126635
|
const { [cardId]: _closed, ...rest } = openTurnCardsOf(state);
|
|
126614
126636
|
return { ...state, turnCards: rest };
|
|
126615
126637
|
}
|
|
126638
|
+
case "chat-aliased":
|
|
126639
|
+
return foldAliased(state, data);
|
|
126616
126640
|
default:
|
|
126617
126641
|
return state;
|
|
126618
126642
|
}
|
|
@@ -126985,6 +127009,7 @@ var readBots = (config2, adapterFor) => {
|
|
|
126985
127009
|
};
|
|
126986
127010
|
var bindingOf = (bot, chatId, state) => ({
|
|
126987
127011
|
...bot,
|
|
127012
|
+
reply: void 0,
|
|
126988
127013
|
chatId,
|
|
126989
127014
|
projectId: chatOf(state, chatKeyOf({ rowId: bot.rowId, chatId })).projectId ?? ""
|
|
126990
127015
|
});
|
|
@@ -127039,7 +127064,7 @@ var numberedApprovalText = (request) => [
|
|
|
127039
127064
|
].join("\n");
|
|
127040
127065
|
|
|
127041
127066
|
// src/approvals.ts
|
|
127042
|
-
var makeApprovals = (core) => {
|
|
127067
|
+
var makeApprovals = (core, anchors) => {
|
|
127043
127068
|
const { host, t, adapterFor, commit, outbound, bindingForChatKey, bindingOfThread, ready } = core;
|
|
127044
127069
|
const settleApprovalCard = async (approval, settlement) => {
|
|
127045
127070
|
if (approval.cardId === void 0) return;
|
|
@@ -127075,7 +127100,7 @@ var makeApprovals = (core) => {
|
|
|
127075
127100
|
};
|
|
127076
127101
|
const sendApprovalCard = async (binding, adapter, threadId, offer) => {
|
|
127077
127102
|
try {
|
|
127078
|
-
const cardId = await adapter.askApproval(binding, {
|
|
127103
|
+
const cardId = await adapter.askApproval(await anchors.anchored(binding, threadId, null), {
|
|
127079
127104
|
title: offer.title,
|
|
127080
127105
|
body: offer.body,
|
|
127081
127106
|
options: offer.buttons,
|
|
@@ -127136,10 +127161,10 @@ var makeApprovals = (core) => {
|
|
|
127136
127161
|
const found = findApprovalByToken(core.state, token);
|
|
127137
127162
|
if (found === void 0) return null;
|
|
127138
127163
|
if (found.approval.resolved) return t("approval.alreadyHandled");
|
|
127139
|
-
const
|
|
127140
|
-
if (
|
|
127164
|
+
const target2 = bindingForChatKey(found.approval.chatKey);
|
|
127165
|
+
if (target2 === void 0 || !isAllowedSender(target2, operatorId)) {
|
|
127141
127166
|
host.log.warn("chat ignored an approval click from someone not on the allow list", {
|
|
127142
|
-
bot:
|
|
127167
|
+
bot: target2?.displayName ?? found.approval.chatKey,
|
|
127143
127168
|
operator: operatorId
|
|
127144
127169
|
});
|
|
127145
127170
|
return t("reply.notAllowed");
|
|
@@ -127219,7 +127244,7 @@ var makeChatSetup = (core, deps) => {
|
|
|
127219
127244
|
listedProjectsByChat.set(chatKey, listedProjectIds(rows));
|
|
127220
127245
|
if (rows.length > 0 && hasPanel(binding)) {
|
|
127221
127246
|
try {
|
|
127222
|
-
await deps.openPicker(chatKey, rows);
|
|
127247
|
+
await deps.openPicker(chatKey, rows, binding.reply);
|
|
127223
127248
|
return;
|
|
127224
127249
|
} catch (error) {
|
|
127225
127250
|
host.log.warn("chat could not open the project picker card", {
|
|
@@ -127248,13 +127273,13 @@ var makeChatSetup = (core, deps) => {
|
|
|
127248
127273
|
await deliver(binding, t("repo.notFound", { query: arg }));
|
|
127249
127274
|
return;
|
|
127250
127275
|
}
|
|
127251
|
-
const
|
|
127252
|
-
if (
|
|
127276
|
+
const target2 = rows.find((row) => row.projectId === picked);
|
|
127277
|
+
if (target2 === void 0) {
|
|
127253
127278
|
await deliver(binding, t("repo.gone"));
|
|
127254
127279
|
return;
|
|
127255
127280
|
}
|
|
127256
|
-
if (
|
|
127257
|
-
await deliver(binding, t("repo.already", { title:
|
|
127281
|
+
if (target2.current) {
|
|
127282
|
+
await deliver(binding, t("repo.already", { title: target2.title }));
|
|
127258
127283
|
return;
|
|
127259
127284
|
}
|
|
127260
127285
|
const threadId = chatOf(core.state, chatKey).threadId;
|
|
@@ -127273,7 +127298,7 @@ var makeChatSetup = (core, deps) => {
|
|
|
127273
127298
|
});
|
|
127274
127299
|
listedProjectsByChat.delete(chatKey);
|
|
127275
127300
|
host.log.info("chat picked a project", { bot: binding.displayName, projectId: picked });
|
|
127276
|
-
await deliver(binding, t("repo.done", { title:
|
|
127301
|
+
await deliver(binding, t("repo.done", { title: target2.title }));
|
|
127277
127302
|
};
|
|
127278
127303
|
const handleGroup = async (binding, name, senderId) => {
|
|
127279
127304
|
const adapter = adapterFor(binding.platform);
|
|
@@ -127428,9 +127453,9 @@ var helpText = (t, options = {}) => [
|
|
|
127428
127453
|
t("help.aliases"),
|
|
127429
127454
|
...options.panel === true ? ["", t("help.panel")] : []
|
|
127430
127455
|
].join("\n");
|
|
127431
|
-
var describeTargets = (
|
|
127432
|
-
const current =
|
|
127433
|
-
title: teams.find((team) => team.teamId ===
|
|
127456
|
+
var describeTargets = (target2, teams, t) => {
|
|
127457
|
+
const current = target2.kind === "thread" ? t("targets.currentThread") : t("targets.currentTeam", {
|
|
127458
|
+
title: teams.find((team) => team.teamId === target2.teamId)?.title ?? target2.teamId
|
|
127434
127459
|
});
|
|
127435
127460
|
const list2 = teams.length === 0 ? t("targets.noTeams") : [t("targets.teamList"), ...teams.map((team) => `\xB7 ${team.title}`)].join("\n");
|
|
127436
127461
|
return [current, "", list2, "", t("targets.hint")].join("\n");
|
|
@@ -127569,7 +127594,7 @@ var makeCommands = (core, deps) => {
|
|
|
127569
127594
|
case "panel":
|
|
127570
127595
|
if (hasPanel(binding)) {
|
|
127571
127596
|
try {
|
|
127572
|
-
await openPanel(chatKey);
|
|
127597
|
+
await openPanel(chatKey, binding.reply);
|
|
127573
127598
|
return true;
|
|
127574
127599
|
} catch (error) {
|
|
127575
127600
|
host.log.warn("chat could not open the command panel", {
|
|
@@ -127680,7 +127705,7 @@ var makeCommands = (core, deps) => {
|
|
|
127680
127705
|
turnId: activeTurnId,
|
|
127681
127706
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
127682
127707
|
});
|
|
127683
|
-
await clearWorking(binding, threadId);
|
|
127708
|
+
await clearWorking(binding, threadId, "stopped");
|
|
127684
127709
|
await deliver(binding, t("command.stopped"));
|
|
127685
127710
|
return true;
|
|
127686
127711
|
}
|
|
@@ -127689,51 +127714,339 @@ var makeCommands = (core, deps) => {
|
|
|
127689
127714
|
return { handleCommand, targetOf };
|
|
127690
127715
|
};
|
|
127691
127716
|
|
|
127717
|
+
// src/keyedQueue.ts
|
|
127718
|
+
var makeKeyedQueue = (onError) => {
|
|
127719
|
+
const tails = /* @__PURE__ */ new Map();
|
|
127720
|
+
return (key, work) => {
|
|
127721
|
+
const run = (tails.get(key) ?? Promise.resolve()).then(work).catch(onError).then(() => {
|
|
127722
|
+
if (tails.get(key) === run) tails.delete(key);
|
|
127723
|
+
});
|
|
127724
|
+
tails.set(key, run);
|
|
127725
|
+
};
|
|
127726
|
+
};
|
|
127727
|
+
|
|
127692
127728
|
// src/connections.ts
|
|
127729
|
+
var connectionKey = (adapter, bot) => JSON.stringify([
|
|
127730
|
+
adapter.platform,
|
|
127731
|
+
bot.displayName,
|
|
127732
|
+
// 「跟机器默认」与「不加代理」是两种选择,分开记。
|
|
127733
|
+
bot.proxy === void 0 ? [] : [bot.proxy],
|
|
127734
|
+
bot.groupMention,
|
|
127735
|
+
[...adapter.columns.map((column) => column.key), ...adapter.unlistedValues ?? []].map(
|
|
127736
|
+
(key) => bot.values[key] ?? ""
|
|
127737
|
+
)
|
|
127738
|
+
]);
|
|
127693
127739
|
var startConnections = (core, inboundHandlersFor) => {
|
|
127694
127740
|
const { host, adapterFor, ready } = core;
|
|
127695
|
-
const
|
|
127696
|
-
const
|
|
127697
|
-
|
|
127741
|
+
const live = /* @__PURE__ */ new Map();
|
|
127742
|
+
const enqueueForRow = makeKeyedQueue((error) => {
|
|
127743
|
+
host.log.warn("chat could not start an inbound connection", { error: describeError(error) });
|
|
127744
|
+
});
|
|
127698
127745
|
let disposed = false;
|
|
127699
|
-
|
|
127746
|
+
const open = (bot, key) => {
|
|
127700
127747
|
const adapter = adapterFor(bot.platform);
|
|
127701
|
-
|
|
127702
|
-
|
|
127703
|
-
|
|
127704
|
-
|
|
127705
|
-
|
|
127706
|
-
|
|
127707
|
-
|
|
127708
|
-
|
|
127709
|
-
|
|
127710
|
-
|
|
127711
|
-
|
|
127712
|
-
|
|
127713
|
-
|
|
127714
|
-
|
|
127715
|
-
|
|
127716
|
-
|
|
127717
|
-
platform: bot.platform,
|
|
127718
|
-
error: describeError(error)
|
|
127719
|
-
});
|
|
127748
|
+
let closed = false;
|
|
127749
|
+
let closeConnection;
|
|
127750
|
+
enqueueForRow(bot.rowId, async () => {
|
|
127751
|
+
try {
|
|
127752
|
+
await ready;
|
|
127753
|
+
if (closed || adapter === void 0) return;
|
|
127754
|
+
const connection = await adapter.connect(bot, inboundHandlersFor(bot));
|
|
127755
|
+
if (closed) connection.close();
|
|
127756
|
+
else closeConnection = () => connection.close();
|
|
127757
|
+
} catch (error) {
|
|
127758
|
+
host.log.warn("chat could not start an inbound connection", {
|
|
127759
|
+
bot: bot.displayName,
|
|
127760
|
+
platform: bot.platform,
|
|
127761
|
+
error: describeError(error)
|
|
127762
|
+
});
|
|
127763
|
+
}
|
|
127720
127764
|
});
|
|
127721
|
-
|
|
127765
|
+
return {
|
|
127766
|
+
key,
|
|
127767
|
+
close: () => {
|
|
127768
|
+
closed = true;
|
|
127769
|
+
closeConnection?.();
|
|
127770
|
+
}
|
|
127771
|
+
};
|
|
127772
|
+
};
|
|
127773
|
+
const reconcile = () => {
|
|
127774
|
+
const bots = disposed ? [] : core.bots();
|
|
127775
|
+
const wanted = /* @__PURE__ */ new Map();
|
|
127776
|
+
const credentials3 = /* @__PURE__ */ new Set();
|
|
127777
|
+
for (const bot of bots) {
|
|
127778
|
+
const adapter = adapterFor(bot.platform);
|
|
127779
|
+
if (adapter === void 0) continue;
|
|
127780
|
+
const fingerprint = `${bot.platform}:${adapter.columns.map((column) => bot.values[column.key] ?? "").join(" ")}`;
|
|
127781
|
+
if (credentials3.has(fingerprint)) {
|
|
127782
|
+
host.log.warn("chat did not connect a bot that repeats another bot's credentials", {
|
|
127783
|
+
bot: bot.displayName,
|
|
127784
|
+
platform: bot.platform
|
|
127785
|
+
});
|
|
127786
|
+
continue;
|
|
127787
|
+
}
|
|
127788
|
+
credentials3.add(fingerprint);
|
|
127789
|
+
wanted.set(bot.rowId, { bot, key: connectionKey(adapter, bot) });
|
|
127790
|
+
}
|
|
127791
|
+
for (const [rowId, connection] of live) {
|
|
127792
|
+
if (wanted.get(rowId)?.key === connection.key) continue;
|
|
127793
|
+
connection.close();
|
|
127794
|
+
live.delete(rowId);
|
|
127795
|
+
}
|
|
127796
|
+
for (const [rowId, { bot, key }] of wanted) {
|
|
127797
|
+
if (!live.has(rowId)) live.set(rowId, open(bot, key));
|
|
127798
|
+
}
|
|
127799
|
+
return { bots: bots.length, connecting: wanted.size };
|
|
127800
|
+
};
|
|
127722
127801
|
host.onDispose(() => {
|
|
127723
127802
|
disposed = true;
|
|
127724
|
-
|
|
127803
|
+
reconcile();
|
|
127725
127804
|
});
|
|
127726
|
-
return {
|
|
127805
|
+
return { reconcile };
|
|
127727
127806
|
};
|
|
127728
127807
|
|
|
127729
|
-
// src/
|
|
127730
|
-
|
|
127731
|
-
|
|
127732
|
-
|
|
127733
|
-
|
|
127734
|
-
|
|
127808
|
+
// src/deliveryHttp.ts
|
|
127809
|
+
import * as NodeCrypto from "node:crypto";
|
|
127810
|
+
import * as NodeHttp from "node:http";
|
|
127811
|
+
|
|
127812
|
+
// src/boundedBody.ts
|
|
127813
|
+
var readBoundedBody = (req, limit) => new Promise((resolve) => {
|
|
127814
|
+
const chunks = [];
|
|
127815
|
+
let size = 0;
|
|
127816
|
+
let settled = false;
|
|
127817
|
+
const finish = (result) => {
|
|
127818
|
+
if (settled) return;
|
|
127819
|
+
settled = true;
|
|
127820
|
+
resolve(result);
|
|
127821
|
+
};
|
|
127822
|
+
req.on("data", (chunk) => {
|
|
127823
|
+
if (settled) return;
|
|
127824
|
+
size += chunk.length;
|
|
127825
|
+
if (size > limit) {
|
|
127826
|
+
finish({ kind: "too-large" });
|
|
127827
|
+
req.destroy();
|
|
127828
|
+
return;
|
|
127829
|
+
}
|
|
127830
|
+
chunks.push(chunk);
|
|
127831
|
+
});
|
|
127832
|
+
req.on("end", () => finish({ kind: "ok", bytes: Buffer.concat(chunks) }));
|
|
127833
|
+
req.on("error", () => finish({ kind: "read-failed" }));
|
|
127834
|
+
req.on("close", () => finish({ kind: "read-failed" }));
|
|
127835
|
+
});
|
|
127836
|
+
|
|
127837
|
+
// src/deliveryContract.ts
|
|
127838
|
+
var DELIVERY_SEND_ERROR_CODES = [
|
|
127839
|
+
"bad-request",
|
|
127840
|
+
"unknown-bot",
|
|
127841
|
+
"unknown-target",
|
|
127842
|
+
"bot-not-connected",
|
|
127843
|
+
"delivery-failed"
|
|
127844
|
+
];
|
|
127845
|
+
var isDeliverySendErrorCode = (value2) => typeof value2 === "string" && DELIVERY_SEND_ERROR_CODES.includes(value2);
|
|
127846
|
+
var DeliverySendError = class extends Error {
|
|
127847
|
+
code;
|
|
127848
|
+
constructor(code2, message) {
|
|
127849
|
+
super(message);
|
|
127850
|
+
this.name = "DeliverySendError";
|
|
127851
|
+
this.code = code2;
|
|
127852
|
+
}
|
|
127853
|
+
};
|
|
127854
|
+
|
|
127855
|
+
// src/deliveryHttp.ts
|
|
127856
|
+
var LOOPBACK = "127.0.0.1";
|
|
127857
|
+
var MAX_BODY_BYTES = 1 * 1024 * 1024;
|
|
127858
|
+
var PATH = "/v1/delivery/messages";
|
|
127859
|
+
var statusFor = (code2) => {
|
|
127860
|
+
switch (code2) {
|
|
127861
|
+
case "bad-request":
|
|
127862
|
+
return 400;
|
|
127863
|
+
case "unauthorized":
|
|
127864
|
+
return 401;
|
|
127865
|
+
case "unknown-bot":
|
|
127866
|
+
case "unknown-target":
|
|
127867
|
+
return 404;
|
|
127868
|
+
case "bot-not-connected":
|
|
127869
|
+
return 503;
|
|
127870
|
+
case "delivery-failed":
|
|
127871
|
+
return 502;
|
|
127872
|
+
case "method-not-allowed":
|
|
127873
|
+
return 405;
|
|
127874
|
+
case "unsupported-media-type":
|
|
127875
|
+
return 415;
|
|
127876
|
+
case "payload-too-large":
|
|
127877
|
+
return 413;
|
|
127878
|
+
}
|
|
127879
|
+
};
|
|
127880
|
+
var writeJson = (res, status, body) => {
|
|
127881
|
+
const payload = JSON.stringify(body);
|
|
127882
|
+
res.writeHead(status, {
|
|
127883
|
+
"content-type": "application/json; charset=utf-8",
|
|
127884
|
+
"content-length": Buffer.byteLength(payload),
|
|
127885
|
+
"cache-control": "no-store"
|
|
127886
|
+
});
|
|
127887
|
+
res.end(payload);
|
|
127888
|
+
};
|
|
127889
|
+
var writeError = (res, code2, message) => {
|
|
127890
|
+
writeJson(res, statusFor(code2), { error: { code: code2, message } });
|
|
127891
|
+
};
|
|
127892
|
+
var isLoopbackRemote = (remote) => {
|
|
127893
|
+
if (remote === void 0 || remote === "") return false;
|
|
127894
|
+
return remote === "127.0.0.1" || remote === "::1" || remote === "::ffff:127.0.0.1";
|
|
127895
|
+
};
|
|
127896
|
+
var timingSafeEqualString = (a, b) => {
|
|
127897
|
+
const left = Buffer.from(a);
|
|
127898
|
+
const right = Buffer.from(b);
|
|
127899
|
+
if (left.length !== right.length) return false;
|
|
127900
|
+
return NodeCrypto.timingSafeEqual(left, right);
|
|
127901
|
+
};
|
|
127902
|
+
var parseSendBody = (raw) => {
|
|
127903
|
+
let parsed;
|
|
127904
|
+
try {
|
|
127905
|
+
parsed = JSON.parse(raw.toString("utf8"));
|
|
127906
|
+
} catch {
|
|
127907
|
+
return "bad-request";
|
|
127908
|
+
}
|
|
127909
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return "bad-request";
|
|
127910
|
+
const record2 = parsed;
|
|
127911
|
+
const botId = record2["botId"];
|
|
127912
|
+
const targetId = record2["targetId"];
|
|
127913
|
+
const text3 = record2["text"];
|
|
127914
|
+
const format2 = record2["format"];
|
|
127915
|
+
if (typeof botId !== "string" || botId.trim() === "") return "bad-request";
|
|
127916
|
+
if (typeof targetId !== "string" || targetId.trim() === "") return "bad-request";
|
|
127917
|
+
if (typeof text3 !== "string" || text3.trim() === "") return "bad-request";
|
|
127918
|
+
if (format2 !== void 0 && format2 !== "plain" && format2 !== "markdown") return "bad-request";
|
|
127919
|
+
for (const key of Object.keys(record2)) {
|
|
127920
|
+
if (key !== "botId" && key !== "targetId" && key !== "text" && key !== "format") {
|
|
127921
|
+
return "bad-request";
|
|
127922
|
+
}
|
|
127923
|
+
}
|
|
127924
|
+
return {
|
|
127925
|
+
botId: botId.trim(),
|
|
127926
|
+
targetId: targetId.trim(),
|
|
127927
|
+
text: text3,
|
|
127928
|
+
format: format2 === "markdown" ? "markdown" : format2 === "plain" ? "plain" : void 0
|
|
127929
|
+
};
|
|
127930
|
+
};
|
|
127931
|
+
var startDeliveryHttpServer = async (options) => {
|
|
127932
|
+
const server = NodeHttp.createServer((req, res) => {
|
|
127933
|
+
void (async () => {
|
|
127934
|
+
if (!isLoopbackRemote(req.socket.remoteAddress)) {
|
|
127935
|
+
writeError(res, "unauthorized", "Only loopback clients are accepted.");
|
|
127936
|
+
return;
|
|
127937
|
+
}
|
|
127938
|
+
const url = new URL(req.url ?? "/", `http://${LOOPBACK}`);
|
|
127939
|
+
if (url.pathname !== PATH) {
|
|
127940
|
+
writeError(res, "bad-request", `Unknown path '${url.pathname}'.`);
|
|
127941
|
+
return;
|
|
127942
|
+
}
|
|
127943
|
+
if (req.method !== "POST") {
|
|
127944
|
+
res.setHeader("allow", "POST");
|
|
127945
|
+
writeError(res, "method-not-allowed", "Only POST is accepted.");
|
|
127946
|
+
return;
|
|
127947
|
+
}
|
|
127948
|
+
const contentType = (req.headers["content-type"] ?? "").split(";")[0]?.trim().toLowerCase();
|
|
127949
|
+
if (contentType !== "application/json") {
|
|
127950
|
+
writeError(res, "unsupported-media-type", "Content-Type must be application/json.");
|
|
127951
|
+
return;
|
|
127952
|
+
}
|
|
127953
|
+
if (options.token !== "") {
|
|
127954
|
+
const header = req.headers.authorization ?? "";
|
|
127955
|
+
const prefix = "Bearer ";
|
|
127956
|
+
if (!header.startsWith(prefix) || !timingSafeEqualString(header.slice(prefix.length), options.token)) {
|
|
127957
|
+
writeError(res, "unauthorized", "Bearer token required.");
|
|
127958
|
+
return;
|
|
127959
|
+
}
|
|
127960
|
+
}
|
|
127961
|
+
const read = await readBoundedBody(req, MAX_BODY_BYTES);
|
|
127962
|
+
if (read.kind !== "ok") {
|
|
127963
|
+
if (read.kind === "too-large") {
|
|
127964
|
+
writeError(res, "payload-too-large", "JSON body exceeds 1 MiB.");
|
|
127965
|
+
} else {
|
|
127966
|
+
writeError(res, "bad-request", "Failed to read body.");
|
|
127967
|
+
}
|
|
127968
|
+
return;
|
|
127969
|
+
}
|
|
127970
|
+
const parsed = parseSendBody(read.bytes);
|
|
127971
|
+
if (typeof parsed === "string") {
|
|
127972
|
+
writeError(res, parsed, "Invalid JSON body.");
|
|
127973
|
+
return;
|
|
127974
|
+
}
|
|
127975
|
+
try {
|
|
127976
|
+
const result = await options.send(parsed);
|
|
127977
|
+
writeJson(res, 200, { sent: result.sent });
|
|
127978
|
+
} catch (error) {
|
|
127979
|
+
const rawCode = error instanceof Error ? error.code : void 0;
|
|
127980
|
+
const code2 = isDeliverySendErrorCode(rawCode) ? rawCode : "delivery-failed";
|
|
127981
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
127982
|
+
options.log?.warn("delivery http send failed", { code: code2, message });
|
|
127983
|
+
writeError(res, code2, message);
|
|
127984
|
+
}
|
|
127985
|
+
})().catch((error) => {
|
|
127986
|
+
options.log?.warn("delivery http handler crashed", {
|
|
127987
|
+
error: error instanceof Error ? error.message : String(error)
|
|
127988
|
+
});
|
|
127989
|
+
if (!res.headersSent) writeError(res, "delivery-failed", "Internal error.");
|
|
127735
127990
|
});
|
|
127736
|
-
|
|
127991
|
+
});
|
|
127992
|
+
await new Promise((resolve, reject) => {
|
|
127993
|
+
server.once("error", reject);
|
|
127994
|
+
server.listen(options.port, LOOPBACK, () => resolve());
|
|
127995
|
+
});
|
|
127996
|
+
const address = server.address();
|
|
127997
|
+
const port = address.port;
|
|
127998
|
+
options.log?.info("delivery http listening", { host: LOOPBACK, port, path: PATH });
|
|
127999
|
+
return {
|
|
128000
|
+
port,
|
|
128001
|
+
origin: `http://${LOOPBACK}:${String(port)}`,
|
|
128002
|
+
close: () => new Promise((resolve, reject) => {
|
|
128003
|
+
server.close((error) => error ? reject(error) : resolve());
|
|
128004
|
+
})
|
|
128005
|
+
};
|
|
128006
|
+
};
|
|
128007
|
+
|
|
128008
|
+
// src/deliveryHttpLifecycle.ts
|
|
128009
|
+
var makeDeliveryHttp = (input) => {
|
|
128010
|
+
const start = input.start ?? startDeliveryHttpServer;
|
|
128011
|
+
let running;
|
|
128012
|
+
let disposed = false;
|
|
128013
|
+
const stop = async () => {
|
|
128014
|
+
const current = running;
|
|
128015
|
+
running = void 0;
|
|
128016
|
+
if (current === void 0) return;
|
|
128017
|
+
await current.server.close().catch((error) => {
|
|
128018
|
+
input.log.warn("delivery http could not close", { error: describeError(error) });
|
|
128019
|
+
});
|
|
128020
|
+
};
|
|
128021
|
+
input.onDispose(() => {
|
|
128022
|
+
disposed = true;
|
|
128023
|
+
void stop();
|
|
128024
|
+
});
|
|
128025
|
+
return {
|
|
128026
|
+
apply: async (config2) => {
|
|
128027
|
+
const port = readDeliveryHttpPort(config2);
|
|
128028
|
+
const token = readDeliveryHttpToken(config2);
|
|
128029
|
+
const wanted = readDeliveryHttpEnabled(config2) ? `${String(port)}
|
|
128030
|
+
${token}` : void 0;
|
|
128031
|
+
if (wanted === running?.listening) return;
|
|
128032
|
+
await stop();
|
|
128033
|
+
if (wanted === void 0 || disposed) return;
|
|
128034
|
+
try {
|
|
128035
|
+
const server = await start({
|
|
128036
|
+
port,
|
|
128037
|
+
token,
|
|
128038
|
+
send: input.send,
|
|
128039
|
+
log: {
|
|
128040
|
+
info: (message, fields) => input.log.info(message, fields),
|
|
128041
|
+
warn: (message, fields) => input.log.warn(message, fields)
|
|
128042
|
+
}
|
|
128043
|
+
});
|
|
128044
|
+
running = { listening: wanted, server };
|
|
128045
|
+
if (disposed) await stop();
|
|
128046
|
+
} catch (error) {
|
|
128047
|
+
input.log.warn("delivery http failed to listen", { port, error: describeError(error) });
|
|
128048
|
+
}
|
|
128049
|
+
}
|
|
127737
128050
|
};
|
|
127738
128051
|
};
|
|
127739
128052
|
|
|
@@ -127804,7 +128117,7 @@ var makeImCore = (input) => {
|
|
|
127804
128117
|
host.log.warn("chat could not deliver", { error: describeError(error) });
|
|
127805
128118
|
}
|
|
127806
128119
|
};
|
|
127807
|
-
const bots = () => readBots(input.config, adapterFor);
|
|
128120
|
+
const bots = () => readBots(input.config(), adapterFor);
|
|
127808
128121
|
const bindingForChatKey = (chatKey) => findBindingByChatKey(bots(), state, chatKey);
|
|
127809
128122
|
return {
|
|
127810
128123
|
host,
|
|
@@ -128118,6 +128431,64 @@ var makeCooldown = (windowMs, now, maxKeys = Number.POSITIVE_INFINITY) => {
|
|
|
128118
128431
|
};
|
|
128119
128432
|
};
|
|
128120
128433
|
|
|
128434
|
+
// src/boundedMap.ts
|
|
128435
|
+
var makeBoundedMap = (limit) => {
|
|
128436
|
+
const entries = /* @__PURE__ */ new Map();
|
|
128437
|
+
return {
|
|
128438
|
+
get: (key) => entries.get(key),
|
|
128439
|
+
set: (key, value2) => {
|
|
128440
|
+
entries.delete(key);
|
|
128441
|
+
entries.set(key, value2);
|
|
128442
|
+
if (entries.size > limit) {
|
|
128443
|
+
const oldest = entries.keys().next().value;
|
|
128444
|
+
if (oldest !== void 0) entries.delete(oldest);
|
|
128445
|
+
}
|
|
128446
|
+
}
|
|
128447
|
+
};
|
|
128448
|
+
};
|
|
128449
|
+
|
|
128450
|
+
// src/replyAnchors.ts
|
|
128451
|
+
var THREAD_LIMIT = 256;
|
|
128452
|
+
var TURNS_PER_THREAD = 16;
|
|
128453
|
+
var anchorOfMessage = (adapter, message) => adapter?.quotesReplies === true ? { messageId: message.messageId, inThread: message.replyInThread === true } : void 0;
|
|
128454
|
+
var makeReplyAnchors = (host) => {
|
|
128455
|
+
const byThread = makeBoundedMap(THREAD_LIMIT);
|
|
128456
|
+
const userMessageOfTurn = async (threadId, turnId) => {
|
|
128457
|
+
const execution = await host.projections.getThreadExecution(threadId).catch(() => null);
|
|
128458
|
+
if (execution === null) return void 0;
|
|
128459
|
+
const latest = execution.latestTurn;
|
|
128460
|
+
const wanted = turnId ?? execution.session?.activeTurnId ?? latest?.turnId;
|
|
128461
|
+
if (wanted == null) return void 0;
|
|
128462
|
+
const intent = execution.turnIntents.find((candidate) => candidate.turn?.turnId === wanted);
|
|
128463
|
+
return intent?.messageId ?? (latest?.turnId === wanted ? latest.userMessageId : void 0);
|
|
128464
|
+
};
|
|
128465
|
+
return {
|
|
128466
|
+
/**
|
|
128467
|
+
* 开轮时记一笔:`userMessageId` 是派给宿主的那条用户消息,`binding` 是收到聊天消息的那个
|
|
128468
|
+
* 聊天(带着它的锚点)。没有锚点(平台不引用)就不记。
|
|
128469
|
+
*/
|
|
128470
|
+
note: (threadId, userMessageId, binding) => {
|
|
128471
|
+
if (binding.reply === void 0) return;
|
|
128472
|
+
const turns = byThread.get(threadId) ?? makeBoundedMap(TURNS_PER_THREAD);
|
|
128473
|
+
byThread.set(threadId, turns);
|
|
128474
|
+
turns.set(userMessageId, { chatKey: chatKeyOf(binding), anchor: binding.reply });
|
|
128475
|
+
},
|
|
128476
|
+
/**
|
|
128477
|
+
* 给发往这条会话的聊天挂上 `turnId` 那一轮的锚点(null 的含义见上);取不到就原样返回。
|
|
128478
|
+
*
|
|
128479
|
+
* 锚点只配给它那条消息所在的聊天:会话可以被另一个聊天接走(`/resume`),而回复接口只按被
|
|
128480
|
+
* 回复的消息寻址,挂错了答复就发回原来的聊天。
|
|
128481
|
+
*/
|
|
128482
|
+
anchored: async (binding, threadId, turnId) => {
|
|
128483
|
+
const turns = byThread.get(threadId);
|
|
128484
|
+
if (turns === void 0) return binding;
|
|
128485
|
+
const asked = await userMessageOfTurn(threadId, turnId);
|
|
128486
|
+
const noted = asked === void 0 ? void 0 : turns.get(asked);
|
|
128487
|
+
return noted?.chatKey === chatKeyOf(binding) ? { ...binding, reply: noted.anchor } : binding;
|
|
128488
|
+
}
|
|
128489
|
+
};
|
|
128490
|
+
};
|
|
128491
|
+
|
|
128121
128492
|
// src/inbound.ts
|
|
128122
128493
|
var SEEN_MESSAGE_LIMIT = 256;
|
|
128123
128494
|
var ARCHIVED_REPLY_COOLDOWN_MS = 10 * 6e4;
|
|
@@ -128134,7 +128505,7 @@ var makeInbound = (core, deps) => {
|
|
|
128134
128505
|
const { questionFlow, handleButtonClick } = deps.interactions;
|
|
128135
128506
|
const { answerByToken } = deps.approvals;
|
|
128136
128507
|
const { handlePanelClick } = deps.panelWiring;
|
|
128137
|
-
const { startTurn, receiveAttachmentsOnly } = deps.turns;
|
|
128508
|
+
const { startTurn, receiveAttachmentsOnly, hasWaitingAttachments } = deps.turns;
|
|
128138
128509
|
const { fetchTeams, startTeamRun } = deps.teams;
|
|
128139
128510
|
const { markWorking } = deps.acknowledgements;
|
|
128140
128511
|
const archivedReplyCooldown = makeCooldown(ARCHIVED_REPLY_COOLDOWN_MS, () => Date.now());
|
|
@@ -128146,21 +128517,49 @@ var makeInbound = (core, deps) => {
|
|
|
128146
128517
|
);
|
|
128147
128518
|
const projectPromptCooldown = makeCooldown(PROJECT_PROMPT_COOLDOWN_MS, () => Date.now());
|
|
128148
128519
|
const handledMessages = makeBoundedSeen(SEEN_MESSAGE_LIMIT);
|
|
128149
|
-
const alreadyHandled = (
|
|
128150
|
-
return !handledMessages.claim(`${chatKeyOf(
|
|
128520
|
+
const alreadyHandled = (target2, messageId) => {
|
|
128521
|
+
return !handledMessages.claim(`${chatKeyOf(target2)}:${messageId}`);
|
|
128151
128522
|
};
|
|
128152
|
-
const turnAwayStranger = (
|
|
128523
|
+
const turnAwayStranger = (target2, sender) => {
|
|
128153
128524
|
host.log.warn("chat ignored a message from someone not on the allow list", {
|
|
128154
|
-
bot:
|
|
128525
|
+
bot: target2.displayName,
|
|
128155
128526
|
sender
|
|
128156
128527
|
});
|
|
128157
128528
|
if (sender === null) return;
|
|
128158
|
-
if (!notAllowedReplyCooldown.tryAcquire(`${
|
|
128529
|
+
if (!notAllowedReplyCooldown.tryAcquire(`${target2.rowId}:${sender}`)) return;
|
|
128159
128530
|
enqueueForChat(
|
|
128160
|
-
chatKeyOf(
|
|
128161
|
-
() => deliver(
|
|
128531
|
+
chatKeyOf(target2),
|
|
128532
|
+
() => deliver(target2, t("reply.notAllowedYet", { id: sender }))
|
|
128162
128533
|
);
|
|
128163
128534
|
};
|
|
128535
|
+
const currentBot = (rowId) => bots().find((candidate) => candidate.rowId === rowId);
|
|
128536
|
+
const inheritFromParent = (bot, chatId, parentChatId) => {
|
|
128537
|
+
if (parentChatId === void 0) return;
|
|
128538
|
+
const chatKey = chatKeyOf({ rowId: bot.rowId, chatId });
|
|
128539
|
+
if (chatOf(core.state, chatKey).projectId) return;
|
|
128540
|
+
const parent = chatOf(core.state, chatKeyOf({ rowId: bot.rowId, chatId: parentChatId }));
|
|
128541
|
+
if (!parent.projectId) return;
|
|
128542
|
+
commit("chat-updated", {
|
|
128543
|
+
chatKey,
|
|
128544
|
+
projectId: parent.projectId,
|
|
128545
|
+
model: parent.model,
|
|
128546
|
+
plan: parent.plan
|
|
128547
|
+
});
|
|
128548
|
+
};
|
|
128549
|
+
const noteChatAlias = (bot, alias, chatId) => {
|
|
128550
|
+
if (chatAliasOf(core.state, bot.rowId, alias) !== void 0) return;
|
|
128551
|
+
commit("chat-aliased", { rowId: bot.rowId, alias, chatId });
|
|
128552
|
+
};
|
|
128553
|
+
const settleChat = (bot, message) => {
|
|
128554
|
+
if (message.chatAlias === void 0) return message;
|
|
128555
|
+
const known = chatAliasOf(core.state, bot.rowId, message.chatAlias);
|
|
128556
|
+
if (known === void 0) noteChatAlias(bot, message.chatAlias, message.chatId);
|
|
128557
|
+
return known === void 0 || known === message.chatId ? message : { ...message, chatId: known };
|
|
128558
|
+
};
|
|
128559
|
+
const openTurn = async (speaker, message) => {
|
|
128560
|
+
const threadId = await startTurn(speaker, message);
|
|
128561
|
+
if (threadId !== null) await markWorking(speaker, threadId, message.messageId);
|
|
128562
|
+
};
|
|
128164
128563
|
const inboundHandlersFor = (bot) => ({
|
|
128165
128564
|
onError: (message) => host.log.warn("chat inbound connection failed", {
|
|
128166
128565
|
platform: bot.platform,
|
|
@@ -128168,10 +128567,16 @@ var makeInbound = (core, deps) => {
|
|
|
128168
128567
|
message
|
|
128169
128568
|
}),
|
|
128170
128569
|
onButton: handleButtonClick,
|
|
128171
|
-
onPanelClick: (click) =>
|
|
128172
|
-
|
|
128173
|
-
|
|
128570
|
+
onPanelClick: (click) => {
|
|
128571
|
+
const current = currentBot(bot.rowId);
|
|
128572
|
+
return current === void 0 ? null : handlePanelClick(current, click);
|
|
128573
|
+
},
|
|
128574
|
+
noteChatAlias: (alias, chatId) => noteChatAlias(bot, alias, chatId),
|
|
128575
|
+
knowsChatAlias: (alias) => chatAliasOf(core.state, bot.rowId, alias) !== void 0,
|
|
128576
|
+
onMessage: (received) => {
|
|
128577
|
+
const current = currentBot(bot.rowId);
|
|
128174
128578
|
if (current === void 0) return;
|
|
128579
|
+
const message = settleChat(current, received);
|
|
128175
128580
|
const arrived = bindingOf2(current, message.chatId);
|
|
128176
128581
|
if (alreadyHandled(arrived, message.messageId)) return;
|
|
128177
128582
|
if (message.chatKind !== void 0 && chatOf(core.state, chatKeyOf(arrived)).chatKind !== message.chatKind) {
|
|
@@ -128201,16 +128606,20 @@ var makeInbound = (core, deps) => {
|
|
|
128201
128606
|
return;
|
|
128202
128607
|
}
|
|
128203
128608
|
enqueueForChat(chatKeyOf(arrived), async () => {
|
|
128204
|
-
|
|
128205
|
-
const
|
|
128206
|
-
|
|
128207
|
-
|
|
128208
|
-
|
|
128609
|
+
inheritFromParent(current, message.chatId, message.parentChatId);
|
|
128610
|
+
const target2 = {
|
|
128611
|
+
...bindingOf2(current, message.chatId),
|
|
128612
|
+
reply: anchorOfMessage(adapterFor(current.platform), message)
|
|
128613
|
+
};
|
|
128614
|
+
const chatKey = chatKeyOf(target2);
|
|
128615
|
+
const teams = await fetchTeams(target2);
|
|
128616
|
+
if (await handleCommand(target2, message.text, teams ?? [], message.senderId)) return;
|
|
128617
|
+
if (target2.projectId === "") {
|
|
128209
128618
|
const asked = message.text.trim();
|
|
128210
128619
|
if (/^[1-9]\d{0,2}$/u.test(asked) && listedProjectsByChat.has(chatKey)) {
|
|
128211
|
-
await handleRepo(
|
|
128620
|
+
await handleRepo(target2, asked);
|
|
128212
128621
|
} else if (projectPromptCooldown.tryAcquire(chatKey)) {
|
|
128213
|
-
await promptProject(
|
|
128622
|
+
await promptProject(target2);
|
|
128214
128623
|
}
|
|
128215
128624
|
return;
|
|
128216
128625
|
}
|
|
@@ -128218,23 +128627,23 @@ var makeInbound = (core, deps) => {
|
|
|
128218
128627
|
if (boundThread !== null && message.text !== "" && await questionFlow.answerByText(chatKey, boundThread, message.text)) {
|
|
128219
128628
|
return;
|
|
128220
128629
|
}
|
|
128221
|
-
const project = await host.projections.getProject(
|
|
128630
|
+
const project = await host.projections.getProject(target2.projectId);
|
|
128222
128631
|
if (project === null || project.archivedAt != null) {
|
|
128223
128632
|
if (project === null) {
|
|
128224
128633
|
host.log.warn("chat cannot start work: the chat's project is gone", {
|
|
128225
|
-
bot:
|
|
128226
|
-
projectId:
|
|
128634
|
+
bot: target2.displayName,
|
|
128635
|
+
projectId: target2.projectId
|
|
128227
128636
|
});
|
|
128228
128637
|
}
|
|
128229
128638
|
if (archivedReplyCooldown.tryAcquire(chatKey)) {
|
|
128230
128639
|
await deliver(
|
|
128231
|
-
|
|
128640
|
+
target2,
|
|
128232
128641
|
project === null ? t("reply.projectMissing") : t("reply.projectArchived", { title: project.title })
|
|
128233
128642
|
);
|
|
128234
128643
|
}
|
|
128235
128644
|
return;
|
|
128236
128645
|
}
|
|
128237
|
-
const routed = targetOf(
|
|
128646
|
+
const routed = targetOf(target2);
|
|
128238
128647
|
const attachmentsOnly = message.text.trim() === "" && message.resources.length > 0;
|
|
128239
128648
|
if (routed.kind === "team") {
|
|
128240
128649
|
if (teams !== null && !teams.some((team) => team.teamId === routed.teamId)) {
|
|
@@ -128243,21 +128652,28 @@ var makeInbound = (core, deps) => {
|
|
|
128243
128652
|
target: { kind: "thread" },
|
|
128244
128653
|
threadId: null
|
|
128245
128654
|
});
|
|
128246
|
-
await deliver(
|
|
128655
|
+
await deliver(target2, t("reply.teamGone"));
|
|
128247
128656
|
} else {
|
|
128248
|
-
if (message.resources.length > 0) await deliver(
|
|
128657
|
+
if (message.resources.length > 0) await deliver(target2, t("reply.attachmentsNoTeam"));
|
|
128249
128658
|
if (attachmentsOnly) return;
|
|
128250
|
-
await startTeamRun(
|
|
128251
|
-
await markWorking(
|
|
128659
|
+
await startTeamRun(target2, routed.teamId, message.text);
|
|
128660
|
+
await markWorking(target2, chatKey, message.messageId);
|
|
128252
128661
|
return;
|
|
128253
128662
|
}
|
|
128254
128663
|
}
|
|
128255
128664
|
if (attachmentsOnly) {
|
|
128256
|
-
await receiveAttachmentsOnly(
|
|
128665
|
+
await receiveAttachmentsOnly(target2, message);
|
|
128257
128666
|
return;
|
|
128258
128667
|
}
|
|
128259
|
-
const
|
|
128260
|
-
if (
|
|
128668
|
+
const branchChatId = hasWaitingAttachments(chatKey) ? void 0 : message.branchChatId;
|
|
128669
|
+
if (branchChatId === void 0) {
|
|
128670
|
+
await openTurn(target2, message);
|
|
128671
|
+
return;
|
|
128672
|
+
}
|
|
128673
|
+
enqueueForChat(chatKeyOf({ rowId: current.rowId, chatId: branchChatId }), async () => {
|
|
128674
|
+
inheritFromParent(current, branchChatId, message.chatId);
|
|
128675
|
+
await openTurn({ ...bindingOf2(current, branchChatId), reply: target2.reply }, message);
|
|
128676
|
+
});
|
|
128261
128677
|
});
|
|
128262
128678
|
}
|
|
128263
128679
|
});
|
|
@@ -128376,12 +128792,12 @@ var makeQuestionFlow = (host) => {
|
|
|
128376
128792
|
const redraw = async (requestId, questionId) => {
|
|
128377
128793
|
const record2 = recordOf(requestId);
|
|
128378
128794
|
const item = itemOf(requestId, questionId);
|
|
128379
|
-
const
|
|
128380
|
-
if (record2 === void 0 || item?.cardId === void 0 ||
|
|
128795
|
+
const target2 = record2 === void 0 ? void 0 : host.target(record2.chatKey);
|
|
128796
|
+
if (record2 === void 0 || item?.cardId === void 0 || target2 === void 0) return;
|
|
128381
128797
|
if (record2.resolved || item.answer !== void 0) return;
|
|
128382
128798
|
try {
|
|
128383
|
-
await
|
|
128384
|
-
|
|
128799
|
+
await target2.adapter.choiceCards?.update(
|
|
128800
|
+
target2.binding,
|
|
128385
128801
|
item.cardId,
|
|
128386
128802
|
questionCardOf(item, record2.items.indexOf(item), record2.items.length, t)
|
|
128387
128803
|
);
|
|
@@ -128392,11 +128808,11 @@ var makeQuestionFlow = (host) => {
|
|
|
128392
128808
|
const freeze = async (requestId, questionId) => {
|
|
128393
128809
|
const record2 = recordOf(requestId);
|
|
128394
128810
|
const item = itemOf(requestId, questionId);
|
|
128395
|
-
const
|
|
128396
|
-
if (record2 === void 0 || item?.cardId === void 0 ||
|
|
128811
|
+
const target2 = record2 === void 0 ? void 0 : host.target(record2.chatKey);
|
|
128812
|
+
if (record2 === void 0 || item?.cardId === void 0 || target2 === void 0) return;
|
|
128397
128813
|
try {
|
|
128398
|
-
await
|
|
128399
|
-
|
|
128814
|
+
await target2.adapter.choiceCards?.update(
|
|
128815
|
+
target2.binding,
|
|
128400
128816
|
item.cardId,
|
|
128401
128817
|
questionSettledCardOf(
|
|
128402
128818
|
item,
|
|
@@ -128422,9 +128838,9 @@ var makeQuestionFlow = (host) => {
|
|
|
128422
128838
|
};
|
|
128423
128839
|
const post = async (requestId) => {
|
|
128424
128840
|
const first = recordOf(requestId);
|
|
128425
|
-
const
|
|
128426
|
-
if (first === void 0 ||
|
|
128427
|
-
const cards =
|
|
128841
|
+
const target2 = first === void 0 ? void 0 : host.target(first.chatKey);
|
|
128842
|
+
if (first === void 0 || target2 === void 0) return;
|
|
128843
|
+
const cards = target2.adapter.choiceCards;
|
|
128428
128844
|
if (cards === void 0) {
|
|
128429
128845
|
await sayNext(requestId);
|
|
128430
128846
|
return;
|
|
@@ -128435,7 +128851,7 @@ var makeQuestionFlow = (host) => {
|
|
|
128435
128851
|
if (record2 === void 0 || record2.resolved || item === void 0) return;
|
|
128436
128852
|
try {
|
|
128437
128853
|
const cardId = await cards.open(
|
|
128438
|
-
|
|
128854
|
+
await host.anchored(target2.binding, record2.threadId),
|
|
128439
128855
|
questionCardOf(item, record2.items.indexOf(item), record2.items.length, t)
|
|
128440
128856
|
);
|
|
128441
128857
|
if (cardId === null) continue;
|
|
@@ -128450,10 +128866,10 @@ var makeQuestionFlow = (host) => {
|
|
|
128450
128866
|
}
|
|
128451
128867
|
};
|
|
128452
128868
|
const offer = (chatKey, threadId, pending) => {
|
|
128453
|
-
const
|
|
128454
|
-
if (
|
|
128455
|
-
const buttons =
|
|
128456
|
-
if (!buttons &&
|
|
128869
|
+
const target2 = host.target(chatKey);
|
|
128870
|
+
if (target2 === void 0) return;
|
|
128871
|
+
const buttons = target2.adapter.choiceCards !== void 0;
|
|
128872
|
+
if (!buttons && target2.adapter.answerByText === void 0) {
|
|
128457
128873
|
host.warn("chat cannot show questions on this platform");
|
|
128458
128874
|
return;
|
|
128459
128875
|
}
|
|
@@ -128673,9 +129089,9 @@ var makeQueueFlow = (host, deps) => {
|
|
|
128673
129089
|
queuePaused: execution.queuePaused,
|
|
128674
129090
|
intent: execution.intents.find((intent) => intent.intentId === intentId)
|
|
128675
129091
|
});
|
|
128676
|
-
const noteQueued = async (chatKey, threadId, messageId, text3) => {
|
|
128677
|
-
const
|
|
128678
|
-
if (
|
|
129092
|
+
const noteQueued = async (chatKey, threadId, messageId, text3, reply) => {
|
|
129093
|
+
const target2 = host.target(chatKey);
|
|
129094
|
+
if (target2 === void 0) return;
|
|
128679
129095
|
let execution;
|
|
128680
129096
|
try {
|
|
128681
129097
|
execution = await deps.readExecution(threadId);
|
|
@@ -128689,7 +129105,7 @@ var makeQueueFlow = (host, deps) => {
|
|
|
128689
129105
|
(other) => other.intentId !== intent.intentId && LIVE_STATUSES.has(other.status) && other.sequence < intent.sequence
|
|
128690
129106
|
);
|
|
128691
129107
|
if (!waiting) return;
|
|
128692
|
-
const cards =
|
|
129108
|
+
const cards = target2.adapter.choiceCards;
|
|
128693
129109
|
if (cards === void 0) {
|
|
128694
129110
|
await host.say(chatKey, t("queue.plainNotice"));
|
|
128695
129111
|
return;
|
|
@@ -128718,7 +129134,10 @@ var makeQueueFlow = (host, deps) => {
|
|
|
128718
129134
|
host.commit("queue-settled", { intentId, outcome: view.outcome });
|
|
128719
129135
|
return;
|
|
128720
129136
|
}
|
|
128721
|
-
const cardId = await cards.open(
|
|
129137
|
+
const cardId = await cards.open(
|
|
129138
|
+
{ ...target2.binding, reply },
|
|
129139
|
+
queueCardOf(record2, view, null, t)
|
|
129140
|
+
);
|
|
128722
129141
|
if (cardId === null) return;
|
|
128723
129142
|
host.commit("queue-carded", { intentId, cardId });
|
|
128724
129143
|
shown.set(intentId, queueViewKey(view, null));
|
|
@@ -128729,8 +129148,8 @@ var makeQueueFlow = (host, deps) => {
|
|
|
128729
129148
|
};
|
|
128730
129149
|
const redraw = async (intentId, released) => {
|
|
128731
129150
|
const record2 = recordOf(intentId);
|
|
128732
|
-
const
|
|
128733
|
-
if (record2 === void 0 || record2.settled !== void 0 ||
|
|
129151
|
+
const target2 = record2 === void 0 ? void 0 : host.target(record2.chatKey);
|
|
129152
|
+
if (record2 === void 0 || record2.settled !== void 0 || target2 === void 0) return;
|
|
128734
129153
|
if (record2.cardId === void 0) return;
|
|
128735
129154
|
let execution;
|
|
128736
129155
|
try {
|
|
@@ -128754,14 +129173,14 @@ var makeQueueFlow = (host, deps) => {
|
|
|
128754
129173
|
}
|
|
128755
129174
|
};
|
|
128756
129175
|
const paint = async (record2, view) => {
|
|
128757
|
-
const
|
|
128758
|
-
const cards =
|
|
128759
|
-
if (
|
|
129176
|
+
const target2 = host.target(record2.chatKey);
|
|
129177
|
+
const cards = target2?.adapter.choiceCards;
|
|
129178
|
+
if (target2 === void 0 || cards === void 0 || record2.cardId === void 0) return;
|
|
128760
129179
|
const note = notes.get(record2.intentId) ?? null;
|
|
128761
129180
|
const key = queueViewKey(view, note);
|
|
128762
129181
|
if (shown.get(record2.intentId) === key) return;
|
|
128763
129182
|
try {
|
|
128764
|
-
await cards.update(
|
|
129183
|
+
await cards.update(target2.binding, record2.cardId, queueCardOf(record2, view, note, t));
|
|
128765
129184
|
shown.set(record2.intentId, key);
|
|
128766
129185
|
} catch (error) {
|
|
128767
129186
|
host.warn("chat could not update the queued message card", error);
|
|
@@ -128878,6 +129297,8 @@ var makeInteractions = (core, deps) => {
|
|
|
128878
129297
|
const adapter = binding === void 0 ? void 0 : adapterFor(binding.platform);
|
|
128879
129298
|
return binding === void 0 || adapter === void 0 ? void 0 : { binding, adapter };
|
|
128880
129299
|
},
|
|
129300
|
+
// 提问是在跑的那一轮问的。
|
|
129301
|
+
anchored: (binding, threadId) => deps.anchors.anchored(binding, threadId, null),
|
|
128881
129302
|
allowed: (chatKey, operatorId) => {
|
|
128882
129303
|
const binding = bindingForChatKey(chatKey);
|
|
128883
129304
|
if (binding !== void 0 && isAllowedSender(binding, operatorId)) return true;
|
|
@@ -128956,6 +129377,9 @@ var makeInteractions = (core, deps) => {
|
|
|
128956
129377
|
const resolved = readRequestResolved(event);
|
|
128957
129378
|
if (resolved === null) return;
|
|
128958
129379
|
await ready;
|
|
129380
|
+
if (resolved.outcome !== "cancelled" && event.threadId !== null) {
|
|
129381
|
+
deps.rotateTurnCard(event.threadId);
|
|
129382
|
+
}
|
|
128959
129383
|
if (resolved.requestKind === "user-input") {
|
|
128960
129384
|
questionFlow.resolved(
|
|
128961
129385
|
resolved.requestId,
|
|
@@ -130774,24 +131198,50 @@ var fetchTenantToken = async (input) => {
|
|
|
130774
131198
|
}
|
|
130775
131199
|
return { token: body.tenant_access_token, expiresInSeconds: body.expire ?? 0 };
|
|
130776
131200
|
};
|
|
130777
|
-
var
|
|
131201
|
+
var postMessage = async (input) => {
|
|
131202
|
+
const headers = {
|
|
131203
|
+
authorization: `Bearer ${input.token}`,
|
|
131204
|
+
"content-type": "application/json; charset=utf-8"
|
|
131205
|
+
};
|
|
131206
|
+
const message = { msg_type: input.msgType, content: JSON.stringify(input.content) };
|
|
131207
|
+
const sentOf = async (response2) => (await readEnvelope(input.operation, response2)).data;
|
|
131208
|
+
if (input.reply !== void 0) {
|
|
131209
|
+
try {
|
|
131210
|
+
const response2 = await input.http(
|
|
131211
|
+
`${LARK_BASE}/im/v1/messages/${encodeURIComponent(input.reply.messageId)}/reply`,
|
|
131212
|
+
{
|
|
131213
|
+
method: "POST",
|
|
131214
|
+
headers,
|
|
131215
|
+
body: JSON.stringify({
|
|
131216
|
+
...message,
|
|
131217
|
+
...input.reply.inThread ? { reply_in_thread: true } : {}
|
|
131218
|
+
})
|
|
131219
|
+
}
|
|
131220
|
+
);
|
|
131221
|
+
const sent = await sentOf(response2);
|
|
131222
|
+
if (input.reply.inThread) input.onThreadReply?.(sent?.thread_id || void 0);
|
|
131223
|
+
return sent?.message_id ?? null;
|
|
131224
|
+
} catch (error) {
|
|
131225
|
+
if (!(error instanceof LarkApiError)) throw error;
|
|
131226
|
+
}
|
|
131227
|
+
}
|
|
130778
131228
|
const idType = input.receiveIdType ?? "chat_id";
|
|
130779
131229
|
const response = await input.http(`${LARK_BASE}/im/v1/messages?receive_id_type=${idType}`, {
|
|
130780
131230
|
method: "POST",
|
|
130781
|
-
headers
|
|
130782
|
-
|
|
130783
|
-
"content-type": "application/json; charset=utf-8"
|
|
130784
|
-
},
|
|
130785
|
-
body: JSON.stringify({
|
|
130786
|
-
receive_id: input.chatId,
|
|
130787
|
-
msg_type: "text",
|
|
130788
|
-
// content 是一个 JSON **字符串**,不是对象——飞书这条接口就是这么定的。
|
|
130789
|
-
content: JSON.stringify({ text: input.text })
|
|
130790
|
-
})
|
|
131231
|
+
headers,
|
|
131232
|
+
body: JSON.stringify({ receive_id: input.chatId, ...message })
|
|
130791
131233
|
});
|
|
130792
|
-
|
|
130793
|
-
|
|
131234
|
+
return (await sentOf(response))?.message_id ?? null;
|
|
131235
|
+
};
|
|
131236
|
+
var fetchMessageThreadId = async (input) => {
|
|
131237
|
+
const response = await input.http(
|
|
131238
|
+
`${LARK_BASE}/im/v1/messages/${encodeURIComponent(input.messageId)}`,
|
|
131239
|
+
{ headers: { authorization: `Bearer ${input.token}` } }
|
|
131240
|
+
);
|
|
131241
|
+
const body = await readEnvelope("message.get", response);
|
|
131242
|
+
return body.data?.items?.[0]?.thread_id || void 0;
|
|
130794
131243
|
};
|
|
131244
|
+
var sendChatText = async (input) => postMessage({ ...input, operation: "send", msgType: "text", content: { text: input.text } });
|
|
130795
131245
|
var LARK_WORKING_REACTION = "OnIt";
|
|
130796
131246
|
var addReaction = async (input) => {
|
|
130797
131247
|
const response = await input.http(
|
|
@@ -130851,54 +131301,19 @@ var uploadFile = async (input) => {
|
|
|
130851
131301
|
}
|
|
130852
131302
|
return body.data.file_key;
|
|
130853
131303
|
};
|
|
130854
|
-
var sendChatFile = async (input) => {
|
|
130855
|
-
|
|
130856
|
-
|
|
130857
|
-
|
|
130858
|
-
|
|
130859
|
-
|
|
130860
|
-
|
|
130861
|
-
|
|
130862
|
-
|
|
130863
|
-
|
|
130864
|
-
|
|
130865
|
-
|
|
130866
|
-
|
|
130867
|
-
const body = await readEnvelope("send.file", response);
|
|
130868
|
-
return body.data?.message_id ?? null;
|
|
130869
|
-
};
|
|
130870
|
-
var sendChatImage = async (input) => {
|
|
130871
|
-
const response = await input.http(`${LARK_BASE}/im/v1/messages?receive_id_type=chat_id`, {
|
|
130872
|
-
method: "POST",
|
|
130873
|
-
headers: {
|
|
130874
|
-
authorization: `Bearer ${input.token}`,
|
|
130875
|
-
"content-type": "application/json; charset=utf-8"
|
|
130876
|
-
},
|
|
130877
|
-
body: JSON.stringify({
|
|
130878
|
-
receive_id: input.chatId,
|
|
130879
|
-
msg_type: "image",
|
|
130880
|
-
content: JSON.stringify({ image_key: input.imageKey })
|
|
130881
|
-
})
|
|
130882
|
-
});
|
|
130883
|
-
const body = await readEnvelope("send.image", response);
|
|
130884
|
-
return body.data?.message_id ?? null;
|
|
130885
|
-
};
|
|
130886
|
-
var sendCard = async (input) => {
|
|
130887
|
-
const response = await input.http(`${LARK_BASE}/im/v1/messages?receive_id_type=chat_id`, {
|
|
130888
|
-
method: "POST",
|
|
130889
|
-
headers: {
|
|
130890
|
-
authorization: `Bearer ${input.token}`,
|
|
130891
|
-
"content-type": "application/json; charset=utf-8"
|
|
130892
|
-
},
|
|
130893
|
-
body: JSON.stringify({
|
|
130894
|
-
receive_id: input.chatId,
|
|
130895
|
-
msg_type: "interactive",
|
|
130896
|
-
content: JSON.stringify(input.card)
|
|
130897
|
-
})
|
|
130898
|
-
});
|
|
130899
|
-
const body = await readEnvelope("send.card", response);
|
|
130900
|
-
return body.data?.message_id ?? null;
|
|
130901
|
-
};
|
|
131304
|
+
var sendChatFile = async (input) => postMessage({
|
|
131305
|
+
...input,
|
|
131306
|
+
operation: "send.file",
|
|
131307
|
+
msgType: "file",
|
|
131308
|
+
content: { file_key: input.fileKey }
|
|
131309
|
+
});
|
|
131310
|
+
var sendChatImage = async (input) => postMessage({
|
|
131311
|
+
...input,
|
|
131312
|
+
operation: "send.image",
|
|
131313
|
+
msgType: "image",
|
|
131314
|
+
content: { image_key: input.imageKey }
|
|
131315
|
+
});
|
|
131316
|
+
var sendCard = async (input) => postMessage({ ...input, operation: "send.card", msgType: "interactive", content: input.card });
|
|
130902
131317
|
var patchCard = async (input) => {
|
|
130903
131318
|
const response = await input.http(
|
|
130904
131319
|
`${LARK_BASE}/im/v1/messages/${encodeURIComponent(input.messageId)}`,
|
|
@@ -132374,13 +132789,13 @@ var LinkifyIt = class {
|
|
|
132374
132789
|
var import_punycode = __toESM(require_punycode(), 1);
|
|
132375
132790
|
var __defProp2 = Object.defineProperty;
|
|
132376
132791
|
var __exportAll = (all, no_symbols) => {
|
|
132377
|
-
let
|
|
132378
|
-
for (var name in all) __defProp2(
|
|
132792
|
+
let target2 = {};
|
|
132793
|
+
for (var name in all) __defProp2(target2, name, {
|
|
132379
132794
|
get: all[name],
|
|
132380
132795
|
enumerable: true
|
|
132381
132796
|
});
|
|
132382
|
-
if (!no_symbols) __defProp2(
|
|
132383
|
-
return
|
|
132797
|
+
if (!no_symbols) __defProp2(target2, Symbol.toStringTag, { value: "Module" });
|
|
132798
|
+
return target2;
|
|
132384
132799
|
};
|
|
132385
132800
|
var utils_exports = /* @__PURE__ */ __exportAll({
|
|
132386
132801
|
arrayReplaceAt: () => arrayReplaceAt,
|
|
@@ -136199,7 +136614,8 @@ var STATUS_TEMPLATE = {
|
|
|
136199
136614
|
working: "wathet",
|
|
136200
136615
|
done: "green",
|
|
136201
136616
|
error: "red",
|
|
136202
|
-
interrupted: "orange"
|
|
136617
|
+
interrupted: "orange",
|
|
136618
|
+
continued: "grey"
|
|
136203
136619
|
};
|
|
136204
136620
|
var encoder = new TextEncoder();
|
|
136205
136621
|
var stripAngleBrackets = (text3) => text3.replaceAll("<", "").replaceAll(">", "");
|
|
@@ -136383,9 +136799,9 @@ var styledText = (text3, style) => {
|
|
|
136383
136799
|
if (style?.includes("underline")) out = `<u>${out}</u>`;
|
|
136384
136800
|
return out;
|
|
136385
136801
|
};
|
|
136386
|
-
var
|
|
136802
|
+
var nonEmpty4 = (value2) => typeof value2 === "string" && value2 !== "";
|
|
136387
136803
|
var resourceOf = (element, index) => {
|
|
136388
|
-
if (element.tag === "img" &&
|
|
136804
|
+
if (element.tag === "img" && nonEmpty4(element.image_key)) {
|
|
136389
136805
|
return {
|
|
136390
136806
|
fileKey: element.image_key,
|
|
136391
136807
|
kind: "image",
|
|
@@ -136393,14 +136809,14 @@ var resourceOf = (element, index) => {
|
|
|
136393
136809
|
mimeType: "image/png"
|
|
136394
136810
|
};
|
|
136395
136811
|
}
|
|
136396
|
-
if ((element.tag === "media" || element.tag === "file") &&
|
|
136812
|
+
if ((element.tag === "media" || element.tag === "file") && nonEmpty4(element.file_key)) {
|
|
136397
136813
|
const video = element.tag === "media";
|
|
136398
|
-
const name =
|
|
136814
|
+
const name = nonEmpty4(element.file_name) ? element.file_name : video ? `video-${String(index)}.mp4` : `file-${String(index)}`;
|
|
136399
136815
|
return {
|
|
136400
136816
|
fileKey: element.file_key,
|
|
136401
136817
|
kind: "file",
|
|
136402
136818
|
name,
|
|
136403
|
-
mimeType: video && !
|
|
136819
|
+
mimeType: video && !nonEmpty4(element.file_name) ? "video/mp4" : mimeFromName(name)
|
|
136404
136820
|
};
|
|
136405
136821
|
}
|
|
136406
136822
|
return null;
|
|
@@ -136412,11 +136828,11 @@ var serializeElement = (element, index, botIds) => {
|
|
|
136412
136828
|
return styledText(element.text ?? "", element.style);
|
|
136413
136829
|
case "a": {
|
|
136414
136830
|
const label = element.text ?? element.href ?? "";
|
|
136415
|
-
return
|
|
136831
|
+
return nonEmpty4(element.href) ? `[${label}](${element.href})` : label;
|
|
136416
136832
|
}
|
|
136417
136833
|
case "at": {
|
|
136418
136834
|
if (element.user_id !== void 0 && botIds.has(element.user_id)) return "";
|
|
136419
|
-
return
|
|
136835
|
+
return nonEmpty4(element.user_name) ? `@${element.user_name}` : "";
|
|
136420
136836
|
}
|
|
136421
136837
|
case "code_block":
|
|
136422
136838
|
return `\`\`\`${element.language ?? ""}
|
|
@@ -136456,7 +136872,7 @@ var serializePost = (content, botIds = /* @__PURE__ */ new Set()) => {
|
|
|
136456
136872
|
for (const element of elements) {
|
|
136457
136873
|
const index = indexOf.get(element);
|
|
136458
136874
|
const key = element.tag === "img" ? element.image_key : element.file_key;
|
|
136459
|
-
if (index !== void 0 &&
|
|
136875
|
+
if (index !== void 0 && nonEmpty4(key)) {
|
|
136460
136876
|
placeholderByKey.set(key, placeholderOf(element, index));
|
|
136461
136877
|
}
|
|
136462
136878
|
}
|
|
@@ -136547,7 +136963,7 @@ var readText = (content) => {
|
|
|
136547
136963
|
const text3 = readJson(content)?.["text"];
|
|
136548
136964
|
return typeof text3 === "string" ? text3 : null;
|
|
136549
136965
|
};
|
|
136550
|
-
var parseInboundMessage = (event, appId, groupMention = "always") => {
|
|
136966
|
+
var parseInboundMessage = (event, appId, groupMention = "always", topicOnMention = true) => {
|
|
136551
136967
|
if (event.sender?.sender_type === "app") return null;
|
|
136552
136968
|
const message = event.message;
|
|
136553
136969
|
if (message === void 0) return null;
|
|
@@ -136557,6 +136973,11 @@ var parseInboundMessage = (event, appId, groupMention = "always") => {
|
|
|
136557
136973
|
const messageType = message.message_type ?? "";
|
|
136558
136974
|
if (!passesGroupGate(event, appId, groupMention, messageType)) return null;
|
|
136559
136975
|
const senderOpenId = event.sender?.sender_id?.open_id ?? null;
|
|
136976
|
+
const threadId = typeof message.thread_id === "string" && message.thread_id !== "" ? message.thread_id : void 0;
|
|
136977
|
+
const inThread = threadId !== void 0 || topicOnMention && mentionsApp(event, appId);
|
|
136978
|
+
const rootGiven = typeof message.root_id === "string" && message.root_id !== "";
|
|
136979
|
+
const rootId = rootGiven && message.root_id !== void 0 ? message.root_id : messageId;
|
|
136980
|
+
const topic = chatType === "p2p" || !inThread ? {} : threadId === void 0 ? { topic: { rootMessageId: messageId } } : { topic: { rootMessageId: rootId, threadId, rootGiven } };
|
|
136560
136981
|
if (UNSUPPORTED_MESSAGE_TYPES.has(messageType)) {
|
|
136561
136982
|
return {
|
|
136562
136983
|
messageId,
|
|
@@ -136565,6 +136986,8 @@ var parseInboundMessage = (event, appId, groupMention = "always") => {
|
|
|
136565
136986
|
senderOpenId,
|
|
136566
136987
|
text: "",
|
|
136567
136988
|
resources: [],
|
|
136989
|
+
inThread,
|
|
136990
|
+
...topic,
|
|
136568
136991
|
unsupportedType: messageType
|
|
136569
136992
|
};
|
|
136570
136993
|
}
|
|
@@ -136575,7 +136998,7 @@ var parseInboundMessage = (event, appId, groupMention = "always") => {
|
|
|
136575
136998
|
const raw = post !== void 0 ? post.text : messageType === "text" ? readText(message.content) : null;
|
|
136576
136999
|
const text3 = mentions.reduce((value2, mention) => value2.replaceAll(mention.key, ""), raw ?? "").trim();
|
|
136577
137000
|
if (text3.length === 0 && resources.length === 0) return null;
|
|
136578
|
-
return { messageId, chatId, chatType, senderOpenId, text: text3, resources };
|
|
137001
|
+
return { messageId, chatId, chatType, senderOpenId, text: text3, resources, inThread, ...topic };
|
|
136579
137002
|
};
|
|
136580
137003
|
var fetchMessageResource = async (input) => {
|
|
136581
137004
|
const url = `${LARK_BASE}/im/v1/messages/${encodeURIComponent(
|
|
@@ -136651,7 +137074,13 @@ var startLarkInbound = (input) => {
|
|
|
136651
137074
|
const dispatcher = new import_node_sdk.EventDispatcher({}).register({
|
|
136652
137075
|
"im.message.receive_v1": (event) => {
|
|
136653
137076
|
const mode = input.groupMention ?? "always";
|
|
136654
|
-
const
|
|
137077
|
+
const parse = (groupMention) => parseInboundMessage(
|
|
137078
|
+
event,
|
|
137079
|
+
input.appId,
|
|
137080
|
+
groupMention,
|
|
137081
|
+
input.topicOnMention
|
|
137082
|
+
);
|
|
137083
|
+
const parsed = parse(mode);
|
|
136655
137084
|
if (parsed !== null) {
|
|
136656
137085
|
input.onMessage(parsed);
|
|
136657
137086
|
return {};
|
|
@@ -136661,7 +137090,7 @@ var startLarkInbound = (input) => {
|
|
|
136661
137090
|
const chatId = chat?.chat_id;
|
|
136662
137091
|
if (typeof chatId === "string") {
|
|
136663
137092
|
void input.isSoloGroup(chatId).then((solo) => {
|
|
136664
|
-
const relaxed = solo ?
|
|
137093
|
+
const relaxed = solo ? parse("never") : null;
|
|
136665
137094
|
if (relaxed !== null) input.onMessage(relaxed);
|
|
136666
137095
|
});
|
|
136667
137096
|
}
|
|
@@ -136728,8 +137157,27 @@ var COLUMNS = [
|
|
|
136728
137157
|
labelKey: "column.larkAppId.label",
|
|
136729
137158
|
placeholderKey: "column.larkAppId.placeholder"
|
|
136730
137159
|
},
|
|
136731
|
-
{ key: "larkAppSecret", kind: "password", labelKey: "column.larkAppSecret.label" }
|
|
137160
|
+
{ key: "larkAppSecret", kind: "password", labelKey: "column.larkAppSecret.label" },
|
|
137161
|
+
// 被 @ 时答复要不要开话题。只有这个适配器读它,没填过就是开(见 `topicOnMentionOf`)。
|
|
137162
|
+
{
|
|
137163
|
+
key: "larkTopicOnMention",
|
|
137164
|
+
kind: "select",
|
|
137165
|
+
labelKey: "column.larkTopicOnMention.label",
|
|
137166
|
+
descriptionKey: "column.larkTopicOnMention.description",
|
|
137167
|
+
options: [
|
|
137168
|
+
{ value: "on", labelKey: "settings.onOff.on" },
|
|
137169
|
+
{ value: "off", labelKey: "settings.onOff.off" }
|
|
137170
|
+
]
|
|
137171
|
+
}
|
|
136732
137172
|
];
|
|
137173
|
+
var topicOnMentionOf = (binding) => binding.values["larkTopicOnMention"] !== "off";
|
|
137174
|
+
var TOPIC_THREAD_CACHE_LIMIT = 2e3;
|
|
137175
|
+
var topicChatIdOf = (chatId, rootMessageId) => `${chatId}:${rootMessageId}`;
|
|
137176
|
+
var splitTopicChatId = (chatId) => {
|
|
137177
|
+
const at = chatId.indexOf(":");
|
|
137178
|
+
return at < 0 ? { chatId } : { chatId: chatId.slice(0, at), rootMessageId: chatId.slice(at + 1) };
|
|
137179
|
+
};
|
|
137180
|
+
var topicAliasOf = (chatId, threadId) => `${chatId}:${threadId}`;
|
|
136733
137181
|
var credentials = (binding) => ({
|
|
136734
137182
|
appId: binding.values["larkAppId"] ?? "",
|
|
136735
137183
|
appSecret: binding.values["larkAppSecret"] ?? ""
|
|
@@ -136744,6 +137192,60 @@ var makeLarkAdapter = (deps) => {
|
|
|
136744
137192
|
await deps.cacheSet(key, { token: minted.token });
|
|
136745
137193
|
return minted.token;
|
|
136746
137194
|
};
|
|
137195
|
+
const aliasPorts = /* @__PURE__ */ new Map();
|
|
137196
|
+
const topicThreadIds = makeBoundedMap(TOPIC_THREAD_CACHE_LIMIT);
|
|
137197
|
+
const learning = /* @__PURE__ */ new Map();
|
|
137198
|
+
const learnTopic = (binding, target2, threadId) => {
|
|
137199
|
+
const key = chatKeyOf(binding);
|
|
137200
|
+
const report = (id) => {
|
|
137201
|
+
topicThreadIds.set(key, id);
|
|
137202
|
+
target2.port?.noteChatAlias?.(topicAliasOf(target2.chatId, id), binding.chatId);
|
|
137203
|
+
};
|
|
137204
|
+
const known = threadId ?? topicThreadIds.get(key);
|
|
137205
|
+
if (known !== void 0) {
|
|
137206
|
+
report(known);
|
|
137207
|
+
return;
|
|
137208
|
+
}
|
|
137209
|
+
const group = chatKeyOf({ rowId: binding.rowId, chatId: target2.chatId });
|
|
137210
|
+
const inflight = learning.get(group) ?? /* @__PURE__ */ new Map();
|
|
137211
|
+
if (inflight.has(key)) return;
|
|
137212
|
+
learning.set(group, inflight);
|
|
137213
|
+
const reading = fetchMessageThreadId({
|
|
137214
|
+
http: deps.http,
|
|
137215
|
+
token: target2.token,
|
|
137216
|
+
messageId: target2.rootMessageId
|
|
137217
|
+
}).then((id) => {
|
|
137218
|
+
if (id !== void 0) report(id);
|
|
137219
|
+
}).catch((error) => {
|
|
137220
|
+
deps.log.warn("lark could not learn the topic of a chat", { error: describeError(error) });
|
|
137221
|
+
}).finally(() => {
|
|
137222
|
+
inflight.delete(key);
|
|
137223
|
+
if (inflight.size === 0) learning.delete(group);
|
|
137224
|
+
});
|
|
137225
|
+
inflight.set(key, reading);
|
|
137226
|
+
};
|
|
137227
|
+
const topicUnsettled = (rowId, groupId, topic) => {
|
|
137228
|
+
if (topic.rootGiven === true) return null;
|
|
137229
|
+
const inflight = learning.get(chatKeyOf({ rowId, chatId: groupId }));
|
|
137230
|
+
if (inflight === void 0) return null;
|
|
137231
|
+
const known = aliasPorts.get(rowId)?.knowsChatAlias?.(topicAliasOf(groupId, topic.threadId));
|
|
137232
|
+
return known === true ? null : Promise.all(inflight.values());
|
|
137233
|
+
};
|
|
137234
|
+
const sendTarget = async (binding) => {
|
|
137235
|
+
const port = aliasPorts.get(binding.rowId);
|
|
137236
|
+
const token = await tenantToken(binding);
|
|
137237
|
+
const { chatId, rootMessageId } = splitTopicChatId(binding.chatId);
|
|
137238
|
+
if (rootMessageId === void 0) {
|
|
137239
|
+
return { http: deps.http, token, chatId, reply: binding.reply };
|
|
137240
|
+
}
|
|
137241
|
+
return {
|
|
137242
|
+
http: deps.http,
|
|
137243
|
+
token,
|
|
137244
|
+
chatId,
|
|
137245
|
+
reply: binding.reply ?? { messageId: rootMessageId, inThread: true },
|
|
137246
|
+
onThreadReply: (threadId) => learnTopic(binding, { token, chatId, rootMessageId, port }, threadId)
|
|
137247
|
+
};
|
|
137248
|
+
};
|
|
136747
137249
|
const soloGroupFor = (bot) => makeSoloGroupCheck(async (chatId) => {
|
|
136748
137250
|
const stats = await fetchChatStats({
|
|
136749
137251
|
http: deps.http,
|
|
@@ -136757,16 +137259,28 @@ var makeLarkAdapter = (deps) => {
|
|
|
136757
137259
|
icon: "lark",
|
|
136758
137260
|
label: "Lark",
|
|
136759
137261
|
columns: COLUMNS,
|
|
137262
|
+
quotesReplies: true,
|
|
137263
|
+
parentChatIdOf: (chatId) => {
|
|
137264
|
+
const { chatId: groupId, rootMessageId } = splitTopicChatId(chatId);
|
|
137265
|
+
return rootMessageId === void 0 ? void 0 : groupId;
|
|
137266
|
+
},
|
|
136760
137267
|
isConfigured: (binding) => {
|
|
136761
137268
|
const { appId, appSecret } = credentials(binding);
|
|
136762
137269
|
return appId !== "" && appSecret !== "";
|
|
136763
137270
|
},
|
|
136764
137271
|
connect: (binding, handlers) => {
|
|
136765
137272
|
const { appId, appSecret } = credentials(binding);
|
|
136766
|
-
|
|
137273
|
+
const port = {
|
|
137274
|
+
noteChatAlias: handlers.noteChatAlias,
|
|
137275
|
+
knowsChatAlias: handlers.knowsChatAlias
|
|
137276
|
+
};
|
|
137277
|
+
aliasPorts.set(binding.rowId, port);
|
|
137278
|
+
let open = true;
|
|
137279
|
+
const inbound = startLarkInbound({
|
|
136767
137280
|
appId,
|
|
136768
137281
|
appSecret,
|
|
136769
137282
|
groupMention: binding.groupMention,
|
|
137283
|
+
topicOnMention: topicOnMentionOf(binding),
|
|
136770
137284
|
isSoloGroup: soloGroupFor(binding),
|
|
136771
137285
|
onError: handlers.onError,
|
|
136772
137286
|
onCardAction: handlers.onButton,
|
|
@@ -136778,12 +137292,23 @@ var makeLarkAdapter = (deps) => {
|
|
|
136778
137292
|
arg: click.arg
|
|
136779
137293
|
}) ?? null,
|
|
136780
137294
|
onMessage: (message) => {
|
|
136781
|
-
|
|
137295
|
+
const { topic } = message;
|
|
137296
|
+
const deliver = () => handlers.onMessage({
|
|
136782
137297
|
messageId: message.messageId,
|
|
136783
|
-
|
|
137298
|
+
// 已经开出来的话题就是它自己那个聊天;将要开出来的(主窗口里 @ 机器人)先算群的,
|
|
137299
|
+
// 由核心决定要不要分出去。
|
|
137300
|
+
...topic === void 0 ? { chatId: message.chatId } : topic.threadId === void 0 ? {
|
|
137301
|
+
chatId: message.chatId,
|
|
137302
|
+
branchChatId: topicChatIdOf(message.chatId, topic.rootMessageId)
|
|
137303
|
+
} : {
|
|
137304
|
+
chatId: topicChatIdOf(message.chatId, topic.rootMessageId),
|
|
137305
|
+
parentChatId: message.chatId,
|
|
137306
|
+
chatAlias: topicAliasOf(message.chatId, topic.threadId)
|
|
137307
|
+
},
|
|
136784
137308
|
senderId: message.senderOpenId,
|
|
136785
137309
|
text: message.text,
|
|
136786
137310
|
chatKind: message.chatType === "p2p" ? "private" : "group",
|
|
137311
|
+
replyInThread: message.inThread,
|
|
136787
137312
|
resources: message.resources.map((resource) => ({
|
|
136788
137313
|
key: resource.fileKey,
|
|
136789
137314
|
name: resource.name,
|
|
@@ -136792,8 +137317,21 @@ var makeLarkAdapter = (deps) => {
|
|
|
136792
137317
|
})),
|
|
136793
137318
|
...message.unsupportedType === void 0 ? {} : { unsupportedType: message.unsupportedType }
|
|
136794
137319
|
});
|
|
137320
|
+
const pending = topic?.threadId === void 0 ? null : topicUnsettled(binding.rowId, message.chatId, {
|
|
137321
|
+
threadId: topic.threadId,
|
|
137322
|
+
rootGiven: topic.rootGiven
|
|
137323
|
+
});
|
|
137324
|
+
if (pending === null) deliver();
|
|
137325
|
+
else void pending.then(() => open ? deliver() : void 0);
|
|
136795
137326
|
}
|
|
136796
137327
|
});
|
|
137328
|
+
return {
|
|
137329
|
+
close: () => {
|
|
137330
|
+
open = false;
|
|
137331
|
+
if (aliasPorts.get(binding.rowId) === port) aliasPorts.delete(binding.rowId);
|
|
137332
|
+
inbound.close();
|
|
137333
|
+
}
|
|
137334
|
+
};
|
|
136797
137335
|
},
|
|
136798
137336
|
createGroup: async (binding, input) => createChat({
|
|
136799
137337
|
http: deps.http,
|
|
@@ -136802,13 +137340,11 @@ var makeLarkAdapter = (deps) => {
|
|
|
136802
137340
|
memberOpenIds: input.memberIds
|
|
136803
137341
|
}),
|
|
136804
137342
|
sendText: async (binding, text3, options) => {
|
|
136805
|
-
const
|
|
137343
|
+
const target2 = await sendTarget(binding);
|
|
136806
137344
|
const receiveIdType = options?.targetKind === "user" ? "open_id" : "chat_id";
|
|
136807
137345
|
for (const chunk of splitForLark(text3)) {
|
|
136808
137346
|
const messageId = await sendChatText({
|
|
136809
|
-
|
|
136810
|
-
token,
|
|
136811
|
-
chatId: binding.chatId,
|
|
137347
|
+
...target2,
|
|
136812
137348
|
receiveIdType,
|
|
136813
137349
|
text: chunk
|
|
136814
137350
|
});
|
|
@@ -136836,35 +137372,39 @@ var makeLarkAdapter = (deps) => {
|
|
|
136836
137372
|
}
|
|
136837
137373
|
},
|
|
136838
137374
|
sendImage: async (binding, image2) => {
|
|
136839
|
-
const
|
|
137375
|
+
const target2 = await sendTarget(binding);
|
|
136840
137376
|
const imageKey = await uploadImage({
|
|
136841
137377
|
http: deps.http,
|
|
136842
|
-
token,
|
|
137378
|
+
token: target2.token,
|
|
136843
137379
|
bytes: image2.bytes,
|
|
136844
137380
|
name: image2.name,
|
|
136845
137381
|
mimeType: image2.mimeType
|
|
136846
137382
|
});
|
|
136847
|
-
await sendChatImage({
|
|
137383
|
+
await sendChatImage({
|
|
137384
|
+
...target2,
|
|
137385
|
+
imageKey
|
|
137386
|
+
});
|
|
136848
137387
|
deps.log.info("lark delivered an image", { name: image2.name });
|
|
136849
137388
|
},
|
|
136850
137389
|
sendFile: async (binding, file) => {
|
|
136851
|
-
const
|
|
137390
|
+
const target2 = await sendTarget(binding);
|
|
136852
137391
|
const fileKey = await uploadFile({
|
|
136853
137392
|
http: deps.http,
|
|
136854
|
-
token,
|
|
137393
|
+
token: target2.token,
|
|
136855
137394
|
bytes: file.bytes,
|
|
136856
137395
|
name: file.name,
|
|
136857
137396
|
mimeType: file.mimeType
|
|
136858
137397
|
});
|
|
136859
|
-
await sendChatFile({
|
|
137398
|
+
await sendChatFile({
|
|
137399
|
+
...target2,
|
|
137400
|
+
fileKey
|
|
137401
|
+
});
|
|
136860
137402
|
deps.log.info("lark delivered a file", { name: file.name });
|
|
136861
137403
|
},
|
|
136862
137404
|
// 图 10 MB、文件 30 MB(飞书开放平台文档:上传图片接口、上传文件接口;空文件会被拒)。
|
|
136863
137405
|
outboundLimits: { imageBytes: 10 * 1024 * 1024, fileBytes: 30 * 1024 * 1024 },
|
|
136864
137406
|
askApproval: async (binding, request) => sendCard({
|
|
136865
|
-
|
|
136866
|
-
token: await tenantToken(binding),
|
|
136867
|
-
chatId: binding.chatId,
|
|
137407
|
+
...await sendTarget(binding),
|
|
136868
137408
|
card: buildApprovalCard({
|
|
136869
137409
|
title: request.title,
|
|
136870
137410
|
body: request.body,
|
|
@@ -136884,10 +137424,9 @@ var makeLarkAdapter = (deps) => {
|
|
|
136884
137424
|
},
|
|
136885
137425
|
turnCards: {
|
|
136886
137426
|
throttleMs: LARK_CARD_THROTTLE_MS,
|
|
137427
|
+
rotatesOnInteraction: true,
|
|
136887
137428
|
open: async (binding, view) => sendCard({
|
|
136888
|
-
|
|
136889
|
-
token: await tenantToken(binding),
|
|
136890
|
-
chatId: binding.chatId,
|
|
137429
|
+
...await sendTarget(binding),
|
|
136891
137430
|
card: buildTurnCard(view, deps.translate)
|
|
136892
137431
|
}),
|
|
136893
137432
|
update: async (binding, cardId, view) => {
|
|
@@ -136901,9 +137440,7 @@ var makeLarkAdapter = (deps) => {
|
|
|
136901
137440
|
},
|
|
136902
137441
|
panel: {
|
|
136903
137442
|
open: async (binding, card) => sendCard({
|
|
136904
|
-
|
|
136905
|
-
token: await tenantToken(binding),
|
|
136906
|
-
chatId: binding.chatId,
|
|
137443
|
+
...await sendTarget(binding),
|
|
136907
137444
|
card: buildPanelCard(card)
|
|
136908
137445
|
}),
|
|
136909
137446
|
update: async (binding, cardId, card) => {
|
|
@@ -136917,9 +137454,7 @@ var makeLarkAdapter = (deps) => {
|
|
|
136917
137454
|
},
|
|
136918
137455
|
choiceCards: {
|
|
136919
137456
|
open: async (binding, card) => sendCard({
|
|
136920
|
-
|
|
136921
|
-
token: await tenantToken(binding),
|
|
136922
|
-
chatId: binding.chatId,
|
|
137457
|
+
...await sendTarget(binding),
|
|
136923
137458
|
card: buildChoiceCard(card)
|
|
136924
137459
|
}),
|
|
136925
137460
|
update: async (binding, cardId, card) => {
|
|
@@ -136971,7 +137506,7 @@ var en_default = {
|
|
|
136971
137506
|
bots: "Bots",
|
|
136972
137507
|
language: {
|
|
136973
137508
|
label: "Reply language",
|
|
136974
|
-
description: "The language of the bot's own sentences in the chat: help, status, confirmations and notices. Chinese shortcut commands only work when this is Chinese.
|
|
137509
|
+
description: "The language of the bot's own sentences in the chat: help, status, confirmations and notices. Chinese shortcut commands only work when this is Chinese. A change applies from the bot's next sentence.",
|
|
136975
137510
|
zhCN: "\u4E2D\u6587",
|
|
136976
137511
|
en: "English"
|
|
136977
137512
|
},
|
|
@@ -137092,7 +137627,7 @@ var en_default = {
|
|
|
137092
137627
|
},
|
|
137093
137628
|
deliveryPlatformChatId: {
|
|
137094
137629
|
label: "Platform chat ID",
|
|
137095
|
-
description: "Lark open_id/chat_id, Telegram chat id, WeCom user/group id, etc.",
|
|
137630
|
+
description: "Lark open_id/chat_id, Telegram chat id (a forum topic: chat id:topic id), WeCom user/group id, etc.",
|
|
137096
137631
|
placeholder: "oc_\u2026 / ou_\u2026 / -100\u2026"
|
|
137097
137632
|
},
|
|
137098
137633
|
queueMode: {
|
|
@@ -137103,6 +137638,10 @@ var en_default = {
|
|
|
137103
137638
|
label: "Command panel",
|
|
137104
137639
|
description: "Which commands /panel (or typing /) lists. Minimal hides low-frequency system items; typing the same command still works."
|
|
137105
137640
|
},
|
|
137641
|
+
larkTopicOnMention: {
|
|
137642
|
+
label: "Open a topic when mentioned",
|
|
137643
|
+
description: "When someone @-mentions the bot, its answer opens a Lark topic under that message, so the question and the answer stay together. Messages already inside a topic are answered in that topic either way."
|
|
137644
|
+
},
|
|
137106
137645
|
wecomNumberedHints: {
|
|
137107
137646
|
label: "Numbered-reply hints",
|
|
137108
137647
|
description: "WeCom has no buttons; approvals and questions use reply numbers. When on, include fuller usage hints."
|
|
@@ -137332,7 +137871,8 @@ var en_default = {
|
|
|
137332
137871
|
working: "Working on it\u2026",
|
|
137333
137872
|
done: "Done",
|
|
137334
137873
|
error: "Something went wrong",
|
|
137335
|
-
interrupted: "Interrupted"
|
|
137874
|
+
interrupted: "Interrupted",
|
|
137875
|
+
continued: "Continues in the card below"
|
|
137336
137876
|
},
|
|
137337
137877
|
step: {
|
|
137338
137878
|
think: "think",
|
|
@@ -137518,7 +138058,13 @@ var en_default = {
|
|
|
137518
138058
|
running: "Checking {{rowId}}\u2026",
|
|
137519
138059
|
done: "Connection OK",
|
|
137520
138060
|
failed: "Connection failed (ref {{ref}})",
|
|
137521
|
-
notSaved: "Save this row first (credentials are read from saved config only)."
|
|
138061
|
+
notSaved: "Save this row first (credentials are read from saved config only).",
|
|
138062
|
+
hint: {
|
|
138063
|
+
badToken: "This does not look like a bot token. Copy it again from BotFather: digits, a colon, then the key (ref {{ref}})",
|
|
138064
|
+
unauthorized: "Telegram does not accept this token. It may have been revoked; get the current one from BotFather (ref {{ref}})",
|
|
138065
|
+
notBot: "This token does not belong to a bot. Use the token BotFather gave you (ref {{ref}})",
|
|
138066
|
+
webhookActive: "This bot has a webhook set by another service, so it cannot receive messages here. Remove the webhook there, then check again (ref {{ref}})"
|
|
138067
|
+
}
|
|
137522
138068
|
},
|
|
137523
138069
|
copyDiagnostics: {
|
|
137524
138070
|
label: "Copy diagnostics",
|
|
@@ -137545,6 +138091,21 @@ var en_default = {
|
|
|
137545
138091
|
failed: "Could not verify the Lark app (ref {{ref}})",
|
|
137546
138092
|
notLark: "This row is not a saved Lark bot."
|
|
137547
138093
|
}
|
|
138094
|
+
},
|
|
138095
|
+
menu: {
|
|
138096
|
+
new: "Start a new session with the next message",
|
|
138097
|
+
stop: "Stop the turn that is running",
|
|
138098
|
+
continue: "Resume sending after a stop or a failure",
|
|
138099
|
+
status: "What is going on right now",
|
|
138100
|
+
sessions: "List the sessions for this chat's project",
|
|
138101
|
+
resume: "Switch to a session (number from /sessions)",
|
|
138102
|
+
model: "See or switch the model",
|
|
138103
|
+
plan: "Toggle plan mode",
|
|
138104
|
+
repo: "Pick the project this chat works on",
|
|
138105
|
+
team: "Send the next messages to a team",
|
|
138106
|
+
thread: "Go back to a normal session",
|
|
138107
|
+
panel: "Open the command panel",
|
|
138108
|
+
help: "Show all commands"
|
|
137548
138109
|
}
|
|
137549
138110
|
};
|
|
137550
138111
|
|
|
@@ -137556,7 +138117,7 @@ var zh_CN_default = {
|
|
|
137556
138117
|
bots: "\u673A\u5668\u4EBA",
|
|
137557
138118
|
language: {
|
|
137558
138119
|
label: "\u56DE\u8BDD\u8BED\u8A00",
|
|
137559
|
-
description: "\u673A\u5668\u4EBA\u5728\u804A\u5929\u91CC\u81EA\u5DF1\u8BF4\u7684\u8BDD\u7528\u4EC0\u4E48\u8BED\u8A00\uFF1A\u5E2E\u52A9\u3001\u72B6\u6001\u3001\u786E\u8BA4\u548C\u5404\u79CD\u63D0\u793A\u3002\u4E2D\u6587\u5FEB\u6377\u547D\u4EE4\u53EA\u5728\u9009\u4E2D\u6587\u65F6\u8BA4\u3002\
|
|
138120
|
+
description: "\u673A\u5668\u4EBA\u5728\u804A\u5929\u91CC\u81EA\u5DF1\u8BF4\u7684\u8BDD\u7528\u4EC0\u4E48\u8BED\u8A00\uFF1A\u5E2E\u52A9\u3001\u72B6\u6001\u3001\u786E\u8BA4\u548C\u5404\u79CD\u63D0\u793A\u3002\u4E2D\u6587\u5FEB\u6377\u547D\u4EE4\u53EA\u5728\u9009\u4E2D\u6587\u65F6\u8BA4\u3002\u6539\u4E86\u4E4B\u540E\u4ECE\u673A\u5668\u4EBA\u7684\u4E0B\u4E00\u53E5\u8BDD\u8D77\u751F\u6548\u3002",
|
|
137560
138121
|
zhCN: "\u4E2D\u6587",
|
|
137561
138122
|
en: "English"
|
|
137562
138123
|
},
|
|
@@ -137677,7 +138238,7 @@ var zh_CN_default = {
|
|
|
137677
138238
|
},
|
|
137678
138239
|
deliveryPlatformChatId: {
|
|
137679
138240
|
label: "\u5E73\u53F0\u804A\u5929 ID",
|
|
137680
|
-
description: "\u98DE\u4E66 open_id\uFF0Fchat_id\u3001Telegram chat id\u3001\u4F01\u5FAE\u7528\u6237\uFF0F\u7FA4 id \u7B49\u3002",
|
|
138241
|
+
description: "\u98DE\u4E66 open_id\uFF0Fchat_id\u3001Telegram chat id\uFF08\u8BBA\u575B\u8BDD\u9898\u586B \u7FA4\u53F7:\u8BDD\u9898\u53F7\uFF09\u3001\u4F01\u5FAE\u7528\u6237\uFF0F\u7FA4 id \u7B49\u3002",
|
|
137681
138242
|
placeholder: "oc_\u2026 / ou_\u2026 / -100\u2026"
|
|
137682
138243
|
},
|
|
137683
138244
|
queueMode: {
|
|
@@ -137688,6 +138249,10 @@ var zh_CN_default = {
|
|
|
137688
138249
|
label: "\u6307\u4EE4\u9762\u677F",
|
|
137689
138250
|
description: "\u804A\u5929\u91CC /panel \u6216\u6253 / \u65F6\u5217\u51FA\u7684\u547D\u4EE4\u8303\u56F4\u3002\u7CBE\u7B80\u9690\u85CF\u4F4E\u9891\u7CFB\u7EDF\u9879\uFF1B\u624B\u52A8\u8F93\u5165\u540C\u4E00\u547D\u4EE4\u4ECD\u53EF\u7528\u3002"
|
|
137690
138251
|
},
|
|
138252
|
+
larkTopicOnMention: {
|
|
138253
|
+
label: "\u88AB @ \u65F6\u5F00\u8BDD\u9898",
|
|
138254
|
+
description: "\u6709\u4EBA @ \u673A\u5668\u4EBA\u63D0\u95EE\u65F6\uFF0C\u7B54\u590D\u5728\u90A3\u6761\u6D88\u606F\u4E0B\u5F00\u4E00\u4E2A\u98DE\u4E66\u8BDD\u9898\uFF0C\u4E00\u95EE\u4E00\u7B54\u6536\u5728\u8BDD\u9898\u91CC\u3002\u5DF2\u7ECF\u5728\u8BDD\u9898\u91CC\u7684\u6D88\u606F\uFF0C\u4E0D\u7BA1\u5F00\u4E0D\u5F00\uFF0C\u7B54\u590D\u90FD\u7559\u5728\u8BE5\u8BDD\u9898\u91CC\u3002"
|
|
138255
|
+
},
|
|
137691
138256
|
wecomNumberedHints: {
|
|
137692
138257
|
label: "\u7F16\u53F7\u5E94\u7B54\u63D0\u793A",
|
|
137693
138258
|
description: "\u4F01\u5FAE\u6CA1\u6709\u6309\u94AE\uFF0C\u5BA1\u6279\u4E0E\u63D0\u95EE\u9760\u56DE\u7F16\u53F7\u3002\u5F00\u542F\u65F6\u9644\u5E26\u66F4\u5B8C\u6574\u7684\u7528\u6CD5\u8BF4\u660E\u3002"
|
|
@@ -137917,7 +138482,8 @@ var zh_CN_default = {
|
|
|
137917
138482
|
working: "\u5904\u7406\u4E2D\u2026",
|
|
137918
138483
|
done: "\u5DF2\u5B8C\u6210",
|
|
137919
138484
|
error: "\u51FA\u9519\u4E86",
|
|
137920
|
-
interrupted: "\u5DF2\u4E2D\u65AD"
|
|
138485
|
+
interrupted: "\u5DF2\u4E2D\u65AD",
|
|
138486
|
+
continued: "\u540E\u7EED\u89C1\u4E0B\u65B9\u5361\u7247"
|
|
137921
138487
|
},
|
|
137922
138488
|
step: {
|
|
137923
138489
|
think: "\u601D\u8003",
|
|
@@ -138103,7 +138669,13 @@ var zh_CN_default = {
|
|
|
138103
138669
|
running: "\u6B63\u5728\u68C0\u67E5 {{rowId}} \u2026",
|
|
138104
138670
|
done: "\u8FDE\u63A5\u6B63\u5E38",
|
|
138105
138671
|
failed: "\u8FDE\u63A5\u5931\u8D25\uFF08\u53C2\u8003\u53F7 {{ref}}\uFF09",
|
|
138106
|
-
notSaved: "\u8BF7\u5148\u4FDD\u5B58\u8FD9\u4E00\u884C\u518D\u68C0\u67E5\u8FDE\u63A5\uFF08\u51ED\u636E\u53EA\u4ECE\u5DF2\u4FDD\u5B58\u914D\u7F6E\u8BFB\u53D6\uFF09\u3002"
|
|
138672
|
+
notSaved: "\u8BF7\u5148\u4FDD\u5B58\u8FD9\u4E00\u884C\u518D\u68C0\u67E5\u8FDE\u63A5\uFF08\u51ED\u636E\u53EA\u4ECE\u5DF2\u4FDD\u5B58\u914D\u7F6E\u8BFB\u53D6\uFF09\u3002",
|
|
138673
|
+
hint: {
|
|
138674
|
+
badToken: "\u8FD9\u4E0D\u50CF\u673A\u5668\u4EBA\u7684 token\u3002\u5230 BotFather \u91CD\u65B0\u590D\u5236\u4E00\u4EFD\uFF1A\u6570\u5B57\u3001\u5192\u53F7\uFF0C\u540E\u9762\u662F\u5BC6\u94A5\uFF08\u53C2\u8003\u53F7 {{ref}}\uFF09",
|
|
138675
|
+
unauthorized: "Telegram \u4E0D\u8BA4\u8FD9\u4E2A token\uFF0C\u53EF\u80FD\u5DF2\u7ECF\u4F5C\u5E9F\u3002\u5230 BotFather \u53D6\u73B0\u5728\u7684\u90A3\u4E00\u4EFD\uFF08\u53C2\u8003\u53F7 {{ref}}\uFF09",
|
|
138676
|
+
notBot: "\u8FD9\u4E2A token \u4E0D\u662F\u673A\u5668\u4EBA\u7684\u3002\u8BF7\u7528 BotFather \u7ED9\u7684\u90A3\u4E00\u4EFD\uFF08\u53C2\u8003\u53F7 {{ref}}\uFF09",
|
|
138677
|
+
webhookActive: "\u8FD9\u4E2A\u673A\u5668\u4EBA\u88AB\u522B\u7684\u670D\u52A1\u8BBE\u4E86 webhook\uFF0C\u5728\u8FD9\u91CC\u6536\u4E0D\u5230\u6D88\u606F\u3002\u5148\u5230\u90A3\u8FB9\u64A4\u6389 webhook\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\uFF08\u53C2\u8003\u53F7 {{ref}}\uFF09"
|
|
138678
|
+
}
|
|
138107
138679
|
},
|
|
138108
138680
|
copyDiagnostics: {
|
|
138109
138681
|
label: "\u590D\u5236\u8BCA\u65AD",
|
|
@@ -138130,6 +138702,21 @@ var zh_CN_default = {
|
|
|
138130
138702
|
failed: "\u65E0\u6CD5\u9A8C\u8BC1\u98DE\u4E66\u5E94\u7528\uFF08\u53C2\u8003\u53F7 {{ref}}\uFF09",
|
|
138131
138703
|
notLark: "\u8FD9\u4E00\u884C\u4E0D\u662F\u5DF2\u4FDD\u5B58\u7684\u98DE\u4E66\u673A\u5668\u4EBA\u3002"
|
|
138132
138704
|
}
|
|
138705
|
+
},
|
|
138706
|
+
menu: {
|
|
138707
|
+
new: "\u4E0B\u4E00\u53E5\u5F00\u4E00\u4E2A\u65B0\u4F1A\u8BDD",
|
|
138708
|
+
stop: "\u505C\u6389\u6B63\u5728\u8DD1\u7684\u8FD9\u4E00\u8F6E",
|
|
138709
|
+
continue: "\u505C\u4E0B\u6216\u5931\u8D25\u4E4B\u540E\u63A5\u7740\u53D1",
|
|
138710
|
+
status: "\u770B\u73B0\u5728\u5728\u5E72\u4EC0\u4E48",
|
|
138711
|
+
sessions: "\u5217\u51FA\u8FD9\u4E2A\u804A\u5929\u6240\u5728\u9879\u76EE\u7684\u4F1A\u8BDD",
|
|
138712
|
+
resume: "\u5207\u5230\u67D0\u4E2A\u4F1A\u8BDD\uFF08/sessions \u91CC\u7684\u7F16\u53F7\uFF09",
|
|
138713
|
+
model: "\u770B\u6216\u6362\u6A21\u578B",
|
|
138714
|
+
plan: "\u5F00\u5173\u8BA1\u5212\u6A21\u5F0F",
|
|
138715
|
+
repo: "\u9009\u8FD9\u4E2A\u804A\u5929\u5728\u54EA\u4E2A\u9879\u76EE\u4E0A\u5E72\u6D3B",
|
|
138716
|
+
team: "\u628A\u63A5\u4E0B\u6765\u7684\u8BDD\u53D1\u7ED9\u4E00\u652F\u56E2\u961F",
|
|
138717
|
+
thread: "\u5207\u56DE\u666E\u901A\u4F1A\u8BDD",
|
|
138718
|
+
panel: "\u6253\u5F00\u547D\u4EE4\u9762\u677F",
|
|
138719
|
+
help: "\u5217\u51FA\u5168\u90E8\u547D\u4EE4"
|
|
138133
138720
|
}
|
|
138134
138721
|
};
|
|
138135
138722
|
|
|
@@ -138160,6 +138747,24 @@ var makeTranslate = (language) => {
|
|
|
138160
138747
|
{ optional, language }
|
|
138161
138748
|
);
|
|
138162
138749
|
};
|
|
138750
|
+
var makeLiveTranslate = (initial) => {
|
|
138751
|
+
let current = makeTranslate(initial);
|
|
138752
|
+
const t = Object.defineProperties(
|
|
138753
|
+
(key, params) => current(key, params),
|
|
138754
|
+
{
|
|
138755
|
+
optional: {
|
|
138756
|
+
value: (key, params) => current.optional(key, params)
|
|
138757
|
+
},
|
|
138758
|
+
language: { get: () => current.language }
|
|
138759
|
+
}
|
|
138760
|
+
);
|
|
138761
|
+
return {
|
|
138762
|
+
t,
|
|
138763
|
+
setLanguage: (language) => {
|
|
138764
|
+
if (language !== current.language) current = makeTranslate(language);
|
|
138765
|
+
}
|
|
138766
|
+
};
|
|
138767
|
+
};
|
|
138163
138768
|
|
|
138164
138769
|
// src/modelPlan.ts
|
|
138165
138770
|
var makeModelPlan = (core, deps) => {
|
|
@@ -138237,13 +138842,28 @@ var makeModelPlan = (core, deps) => {
|
|
|
138237
138842
|
return { currentModelOf, handleModel, handlePlan };
|
|
138238
138843
|
};
|
|
138239
138844
|
|
|
138845
|
+
// src/notificationTargets.ts
|
|
138846
|
+
var notificationChatKeys = (state, threadId, projectId) => {
|
|
138847
|
+
const owner = chatOfThread(state, threadId);
|
|
138848
|
+
if (owner !== void 0) return [owner];
|
|
138849
|
+
return projectId === null ? [] : chatsOnProject(state, projectId);
|
|
138850
|
+
};
|
|
138851
|
+
|
|
138852
|
+
// src/turnOutcome.ts
|
|
138853
|
+
var outcomeOfSession = (status) => {
|
|
138854
|
+
if (status === "error") return "failed";
|
|
138855
|
+
if (status === "interrupted" || status === "stopped") return "stopped";
|
|
138856
|
+
return "done";
|
|
138857
|
+
};
|
|
138858
|
+
var outcomeOfTeamRun = (state) => state === "settled" ? "done" : state === "failed" ? "failed" : "stopped";
|
|
138859
|
+
|
|
138240
138860
|
// src/notifications.ts
|
|
138241
138861
|
var THREAD_PROJECT_CACHE_LIMIT = 256;
|
|
138242
138862
|
var makeNotifications = (core, deps) => {
|
|
138243
138863
|
const { host, adapterFor, deliver, bindingForChatKey, ready } = core;
|
|
138244
138864
|
const { clearWorking } = deps;
|
|
138245
138865
|
const { turnCards } = deps.replyCards;
|
|
138246
|
-
const { failures } = deps;
|
|
138866
|
+
const { failures, anchors } = deps;
|
|
138247
138867
|
const projectByThread = /* @__PURE__ */ new Map();
|
|
138248
138868
|
const projectOfThread = async (threadId) => {
|
|
138249
138869
|
const known = projectByThread.get(threadId);
|
|
@@ -138257,7 +138877,7 @@ var makeNotifications = (core, deps) => {
|
|
|
138257
138877
|
projectByThread.set(threadId, thread.projectId);
|
|
138258
138878
|
return thread.projectId;
|
|
138259
138879
|
};
|
|
138260
|
-
const targetsForProject = (projectId) =>
|
|
138880
|
+
const targetsForProject = (threadId, projectId) => notificationChatKeys(core.state, threadId, projectId).flatMap((chatKey) => {
|
|
138261
138881
|
const binding = bindingForChatKey(chatKey);
|
|
138262
138882
|
return binding === void 0 ? [] : [binding];
|
|
138263
138883
|
});
|
|
@@ -138283,7 +138903,7 @@ var makeNotifications = (core, deps) => {
|
|
|
138283
138903
|
if (payload.session?.activeTurnId != null) return;
|
|
138284
138904
|
const said = threadsWithSomethingToReport.delete(threadId);
|
|
138285
138905
|
await ready;
|
|
138286
|
-
const targets = targetsForProject(await projectOfThread(threadId));
|
|
138906
|
+
const targets = targetsForProject(threadId, await projectOfThread(threadId));
|
|
138287
138907
|
const reporters = said ? targets : [];
|
|
138288
138908
|
if (reporters.length > 0) {
|
|
138289
138909
|
const thread = await host.projections.getThread(threadId);
|
|
@@ -138293,11 +138913,17 @@ var makeNotifications = (core, deps) => {
|
|
|
138293
138913
|
const text3 = streamsTo(binding, threadId) ? "" : `${thread.title}
|
|
138294
138914
|
|
|
138295
138915
|
${final.text}`;
|
|
138296
|
-
|
|
138916
|
+
const owns = chatOf(core.state, chatKeyOf(binding)).threadId === threadId;
|
|
138917
|
+
await deliver(
|
|
138918
|
+
owns ? await anchors.anchored(binding, threadId, final.turnId) : binding,
|
|
138919
|
+
text3,
|
|
138920
|
+
final.attachments
|
|
138921
|
+
);
|
|
138297
138922
|
}
|
|
138298
138923
|
}
|
|
138299
138924
|
}
|
|
138300
|
-
|
|
138925
|
+
const outcome = outcomeOfSession(payload.session?.status);
|
|
138926
|
+
for (const binding of targets) await clearWorking(binding, threadId, outcome);
|
|
138301
138927
|
}
|
|
138302
138928
|
});
|
|
138303
138929
|
host.events.on("thread.failed", async (event) => {
|
|
@@ -138305,7 +138931,7 @@ ${final.text}`;
|
|
|
138305
138931
|
if (threadId === null) return;
|
|
138306
138932
|
threadsWithSomethingToReport.delete(threadId);
|
|
138307
138933
|
await ready;
|
|
138308
|
-
const targets = targetsForProject(await projectOfThread(threadId));
|
|
138934
|
+
const targets = targetsForProject(threadId, await projectOfThread(threadId));
|
|
138309
138935
|
const textTargets = targets.filter(
|
|
138310
138936
|
(binding) => !(streamsTo(binding, threadId) && turnCards.covers(threadId))
|
|
138311
138937
|
);
|
|
@@ -138317,7 +138943,7 @@ ${final.text}`;
|
|
|
138317
138943
|
if (notice !== null && drawingTurn !== null)
|
|
138318
138944
|
failures.holdForCard(threadId, drawingTurn, notice);
|
|
138319
138945
|
for (const binding of targets) {
|
|
138320
|
-
await clearWorking(binding, threadId);
|
|
138946
|
+
await clearWorking(binding, threadId, "failed");
|
|
138321
138947
|
if (notice !== null && textTargets.includes(binding)) await deliver(binding, notice);
|
|
138322
138948
|
}
|
|
138323
138949
|
});
|
|
@@ -138753,8 +139379,8 @@ ${t("panel.projects.hint")}`;
|
|
|
138753
139379
|
};
|
|
138754
139380
|
return {
|
|
138755
139381
|
/** 开一张新面板卡(`/help`)。发不出就抛,调用方退回文字版。 */
|
|
138756
|
-
open: async (chatKey) => {
|
|
138757
|
-
const surface = deps.surface(chatKey);
|
|
139382
|
+
open: async (chatKey, reply) => {
|
|
139383
|
+
const surface = deps.surface(chatKey, reply);
|
|
138758
139384
|
if (surface === null) throw new Error("this chat has no panel");
|
|
138759
139385
|
const entry = { cardId: "", chatKey, stack: [{ kind: "menu" }], busy: false };
|
|
138760
139386
|
const cardId = await surface.open(menuCard(chatKey));
|
|
@@ -138766,8 +139392,8 @@ ${t("panel.projects.hint")}`;
|
|
|
138766
139392
|
* 单独发一张选项目卡(聊天还没选项目时的第一句话、`/repo`)。发不出就抛,调用方退回文字
|
|
138767
139393
|
* 列表。选完不回面板菜单。
|
|
138768
139394
|
*/
|
|
138769
|
-
openProjects: async (chatKey, rows) => {
|
|
138770
|
-
const surface = deps.surface(chatKey);
|
|
139395
|
+
openProjects: async (chatKey, rows, reply) => {
|
|
139396
|
+
const surface = deps.surface(chatKey, reply);
|
|
138771
139397
|
if (surface === null) throw new Error("this chat has no panel");
|
|
138772
139398
|
const entry = {
|
|
138773
139399
|
cardId: "",
|
|
@@ -138781,6 +139407,11 @@ ${t("panel.projects.hint")}`;
|
|
|
138781
139407
|
entry.cardId = cardId;
|
|
138782
139408
|
remember(entry);
|
|
138783
139409
|
},
|
|
139410
|
+
/**
|
|
139411
|
+
* 这张卡开在哪个聊天上。没记过,或已经被淘汰,就是 undefined。
|
|
139412
|
+
* 只读:不改 `cards`,也不改淘汰顺序。
|
|
139413
|
+
*/
|
|
139414
|
+
chatKeyOfCard: (cardId) => cards.get(cardId)?.chatKey,
|
|
138784
139415
|
/**
|
|
138785
139416
|
* 处理一次点击,同步回给点击者的一句提示(null 就是没话说)。取数据、跑命令、改卡都
|
|
138786
139417
|
* 在回调应答之后做。
|
|
@@ -138852,12 +139483,12 @@ var makePanelWiring = (core, deps) => {
|
|
|
138852
139483
|
const { projectRowsFor, listedProjectsByChat } = deps.rows;
|
|
138853
139484
|
const panel = makePanelController({
|
|
138854
139485
|
t,
|
|
138855
|
-
surface: (chatKey) => {
|
|
139486
|
+
surface: (chatKey, reply) => {
|
|
138856
139487
|
const binding = bindingForChatKey(chatKey);
|
|
138857
139488
|
const surface = binding === void 0 ? void 0 : adapterFor(binding.platform)?.panel;
|
|
138858
139489
|
if (binding === void 0 || surface === void 0) return null;
|
|
138859
139490
|
return {
|
|
138860
|
-
open: (card) => surface.open(binding, card),
|
|
139491
|
+
open: (card) => surface.open({ ...binding, reply }, card),
|
|
138861
139492
|
update: (cardId, card) => surface.update(binding, cardId, card)
|
|
138862
139493
|
};
|
|
138863
139494
|
},
|
|
@@ -138909,16 +139540,19 @@ var makePanelWiring = (core, deps) => {
|
|
|
138909
139540
|
}
|
|
138910
139541
|
});
|
|
138911
139542
|
const handlePanelClick = (bot, click) => {
|
|
138912
|
-
const
|
|
138913
|
-
|
|
139543
|
+
const remembered = panel.chatKeyOfCard(click.cardId);
|
|
139544
|
+
const opener = remembered === void 0 ? void 0 : bindingForChatKey(remembered);
|
|
139545
|
+
const chatId = opener !== void 0 && opener.rowId === bot.rowId && adapterFor(opener.platform)?.parentChatIdOf?.(opener.chatId) === click.chatId ? opener.chatId : click.chatId;
|
|
139546
|
+
const target2 = bindingOf2(bot, chatId);
|
|
139547
|
+
if (!isAllowedSender(target2, click.operatorId)) {
|
|
138914
139548
|
host.log.warn("chat ignored a panel click from someone not on the allow list", {
|
|
138915
|
-
bot:
|
|
139549
|
+
bot: target2.displayName,
|
|
138916
139550
|
operator: click.operatorId
|
|
138917
139551
|
});
|
|
138918
139552
|
return t("reply.notAllowed");
|
|
138919
139553
|
}
|
|
138920
139554
|
return panel.click({
|
|
138921
|
-
chatKey: chatKeyOf(
|
|
139555
|
+
chatKey: chatKeyOf(target2),
|
|
138922
139556
|
cardId: click.cardId,
|
|
138923
139557
|
op: click.op,
|
|
138924
139558
|
arg: click.arg
|
|
@@ -139055,6 +139689,8 @@ var trailingReply = (messages) => {
|
|
|
139055
139689
|
};
|
|
139056
139690
|
|
|
139057
139691
|
// src/turnCards.ts
|
|
139692
|
+
var ROTATE = "rotate";
|
|
139693
|
+
var isDrawing = (live) => live.card !== null || live.reopen;
|
|
139058
139694
|
var RECENT_ENDED_LIMIT = 256;
|
|
139059
139695
|
var makeTurnCards = (deps) => {
|
|
139060
139696
|
const slots = /* @__PURE__ */ new Map();
|
|
@@ -139091,12 +139727,37 @@ var makeTurnCards = (deps) => {
|
|
|
139091
139727
|
status: end.status,
|
|
139092
139728
|
errorText: end.errorText
|
|
139093
139729
|
});
|
|
139730
|
+
const openCard = (target2, view) => makeCardStream({
|
|
139731
|
+
open: target2.open,
|
|
139732
|
+
update: target2.update,
|
|
139733
|
+
schedule: deps.schedule,
|
|
139734
|
+
throttleMs: target2.throttleMs,
|
|
139735
|
+
warn: deps.warn
|
|
139736
|
+
}).open(view);
|
|
139737
|
+
const seal = async (slot) => {
|
|
139738
|
+
await deps.ready;
|
|
139739
|
+
const live = slot.live;
|
|
139740
|
+
if (disposed || live === null || live.card === null || !live.target.rotates) return;
|
|
139741
|
+
const card = live.card;
|
|
139742
|
+
await card.finish(
|
|
139743
|
+
buildTurnView({
|
|
139744
|
+
title: live.title,
|
|
139745
|
+
progress: live.lastProgress,
|
|
139746
|
+
texts: await readTexts(live, live.lastProgress),
|
|
139747
|
+
status: "continued"
|
|
139748
|
+
})
|
|
139749
|
+
);
|
|
139750
|
+
deps.onClosed(card.cardId);
|
|
139751
|
+
live.card = null;
|
|
139752
|
+
live.reopen = true;
|
|
139753
|
+
};
|
|
139094
139754
|
const finalize = async (slot, threadId, progress, end) => {
|
|
139095
139755
|
const live = slot.live;
|
|
139096
139756
|
slot.live = null;
|
|
139097
|
-
const
|
|
139098
|
-
|
|
139099
|
-
|
|
139757
|
+
const turnId = progress.turnId ?? live?.turnId ?? null;
|
|
139758
|
+
const target2 = live?.target ?? deps.resolveTarget(threadId, turnId);
|
|
139759
|
+
if (target2 === null) return;
|
|
139760
|
+
rememberEnded(threadId, turnId);
|
|
139100
139761
|
if (end.status === "error") erroredThreads.add(threadId);
|
|
139101
139762
|
const title = live?.title ?? await deps.titleOf(threadId);
|
|
139102
139763
|
const view = await finalView(title, progress, live, end);
|
|
@@ -139105,15 +139766,9 @@ var makeTurnCards = (deps) => {
|
|
|
139105
139766
|
deps.onClosed(live.card.cardId);
|
|
139106
139767
|
return;
|
|
139107
139768
|
}
|
|
139108
|
-
const card = await
|
|
139109
|
-
open: target.open,
|
|
139110
|
-
update: target.update,
|
|
139111
|
-
schedule: deps.schedule,
|
|
139112
|
-
throttleMs: target.throttleMs,
|
|
139113
|
-
warn: deps.warn
|
|
139114
|
-
}).open(view);
|
|
139769
|
+
const card = await openCard(target2, view);
|
|
139115
139770
|
if (card === null) {
|
|
139116
|
-
await deps.fallback(threadId,
|
|
139771
|
+
await deps.fallback(threadId, turnId, target2.chatKey, view);
|
|
139117
139772
|
return;
|
|
139118
139773
|
}
|
|
139119
139774
|
};
|
|
@@ -139132,56 +139787,63 @@ var makeTurnCards = (deps) => {
|
|
|
139132
139787
|
}
|
|
139133
139788
|
}
|
|
139134
139789
|
if (item.phase === "ended") {
|
|
139135
|
-
if (live === null && deps.resolveTarget(threadId) === null) return;
|
|
139790
|
+
if (live === null && deps.resolveTarget(threadId, item.turnId) === null) return;
|
|
139136
139791
|
await finalize(slot, threadId, item, await deps.endOf(threadId, item.turnId));
|
|
139137
139792
|
return;
|
|
139138
139793
|
}
|
|
139139
139794
|
erroredThreads.delete(threadId);
|
|
139140
139795
|
if (live === null) {
|
|
139141
|
-
const
|
|
139142
|
-
if (
|
|
139796
|
+
const target2 = deps.resolveTarget(threadId, item.turnId);
|
|
139797
|
+
if (target2 === null) return;
|
|
139143
139798
|
const title = await deps.titleOf(threadId);
|
|
139144
139799
|
const fresh = {
|
|
139145
|
-
chatKey:
|
|
139800
|
+
chatKey: target2.chatKey,
|
|
139146
139801
|
title,
|
|
139147
139802
|
card: null,
|
|
139148
|
-
|
|
139803
|
+
reopen: false,
|
|
139804
|
+
target: target2,
|
|
139149
139805
|
turnId: item.turnId,
|
|
139150
139806
|
lastSeq: item.seq,
|
|
139151
139807
|
lastProgress: item,
|
|
139152
139808
|
settledTexts: /* @__PURE__ */ new Map()
|
|
139153
139809
|
};
|
|
139154
|
-
const
|
|
139810
|
+
const view2 = buildTurnView({
|
|
139155
139811
|
title,
|
|
139156
139812
|
progress: item,
|
|
139157
139813
|
texts: await readTexts(fresh, item),
|
|
139158
139814
|
status: "working"
|
|
139159
139815
|
});
|
|
139160
|
-
const card = await
|
|
139161
|
-
open: target.open,
|
|
139162
|
-
update: target.update,
|
|
139163
|
-
schedule: deps.schedule,
|
|
139164
|
-
throttleMs: target.throttleMs,
|
|
139165
|
-
warn: deps.warn
|
|
139166
|
-
}).open(view);
|
|
139816
|
+
const card = await openCard(target2, view2);
|
|
139167
139817
|
slot.live = { ...fresh, card };
|
|
139168
139818
|
if (card !== null) {
|
|
139169
|
-
deps.onOpened({ cardId: card.cardId, chatKey:
|
|
139819
|
+
deps.onOpened({ cardId: card.cardId, chatKey: target2.chatKey, threadId, title });
|
|
139170
139820
|
}
|
|
139171
139821
|
return;
|
|
139172
139822
|
}
|
|
139173
139823
|
live.turnId ??= item.turnId;
|
|
139174
139824
|
live.lastSeq = item.seq;
|
|
139175
139825
|
live.lastProgress = item;
|
|
139176
|
-
if (live.card === null) return;
|
|
139177
|
-
|
|
139178
|
-
|
|
139179
|
-
|
|
139180
|
-
|
|
139181
|
-
|
|
139182
|
-
|
|
139183
|
-
|
|
139184
|
-
|
|
139826
|
+
if (live.card === null && !live.reopen) return;
|
|
139827
|
+
const view = buildTurnView({
|
|
139828
|
+
title: live.title,
|
|
139829
|
+
progress: item,
|
|
139830
|
+
texts: await readTexts(live, item),
|
|
139831
|
+
status: "working"
|
|
139832
|
+
});
|
|
139833
|
+
if (live.card !== null) {
|
|
139834
|
+
live.card.push(view);
|
|
139835
|
+
return;
|
|
139836
|
+
}
|
|
139837
|
+
live.reopen = false;
|
|
139838
|
+
live.card = await openCard(live.target, view);
|
|
139839
|
+
if (live.card !== null) {
|
|
139840
|
+
deps.onOpened({
|
|
139841
|
+
cardId: live.card.cardId,
|
|
139842
|
+
chatKey: live.chatKey,
|
|
139843
|
+
threadId,
|
|
139844
|
+
title: live.title
|
|
139845
|
+
});
|
|
139846
|
+
}
|
|
139185
139847
|
};
|
|
139186
139848
|
const pump = async (threadId, slot) => {
|
|
139187
139849
|
try {
|
|
@@ -139189,7 +139851,8 @@ var makeTurnCards = (deps) => {
|
|
|
139189
139851
|
const item = slot.queue.shift();
|
|
139190
139852
|
if (item === void 0) break;
|
|
139191
139853
|
try {
|
|
139192
|
-
|
|
139854
|
+
if (item === ROTATE) await seal(slot);
|
|
139855
|
+
else await handle(slot, threadId, item);
|
|
139193
139856
|
} catch (error) {
|
|
139194
139857
|
deps.warn("could not draw a turn card", error);
|
|
139195
139858
|
}
|
|
@@ -139209,7 +139872,7 @@ var makeTurnCards = (deps) => {
|
|
|
139209
139872
|
slots.set(threadId, slot);
|
|
139210
139873
|
}
|
|
139211
139874
|
const last = slot.queue.at(-1);
|
|
139212
|
-
if (last !== void 0 && last.phase === "running" && last.turnId === progress.turnId) {
|
|
139875
|
+
if (last !== void 0 && last !== ROTATE && last.phase === "running" && last.turnId === progress.turnId) {
|
|
139213
139876
|
slot.queue[slot.queue.length - 1] = progress;
|
|
139214
139877
|
} else {
|
|
139215
139878
|
slot.queue.push(progress);
|
|
@@ -139219,13 +139882,29 @@ var makeTurnCards = (deps) => {
|
|
|
139219
139882
|
void pump(threadId, slot);
|
|
139220
139883
|
}
|
|
139221
139884
|
},
|
|
139222
|
-
/**
|
|
139885
|
+
/**
|
|
139886
|
+
* 审批或提问答完了:封存这条会话开着的卡,下一拍另开一张。立刻返回;没有在画的卡、或
|
|
139887
|
+
* 平台不换卡,就什么都不做。
|
|
139888
|
+
*/
|
|
139889
|
+
rotate: (threadId) => {
|
|
139890
|
+
const slot = slots.get(threadId);
|
|
139891
|
+
if (disposed || slot === void 0) return;
|
|
139892
|
+
slot.queue.push(ROTATE);
|
|
139893
|
+
if (!slot.running) {
|
|
139894
|
+
slot.running = true;
|
|
139895
|
+
void pump(threadId, slot);
|
|
139896
|
+
}
|
|
139897
|
+
},
|
|
139898
|
+
/** 这条会话正在画卡的那一轮(封存后等着另开的也算);没有在画的卡是 null。 */
|
|
139223
139899
|
drawingTurn: (threadId) => {
|
|
139224
139900
|
const live = slots.get(threadId)?.live;
|
|
139225
|
-
return live
|
|
139901
|
+
return live != null && isDrawing(live) ? live.turnId : null;
|
|
139226
139902
|
},
|
|
139227
139903
|
/** 这条会话现在有一张在画的卡,或者上一轮刚以失败收了卡:失败原因已经在卡上了。 */
|
|
139228
|
-
covers: (threadId) =>
|
|
139904
|
+
covers: (threadId) => {
|
|
139905
|
+
const live = slots.get(threadId)?.live;
|
|
139906
|
+
return live != null && isDrawing(live) || erroredThreads.has(threadId);
|
|
139907
|
+
},
|
|
139229
139908
|
/** 插件停用:放下所有在画的卡,不再发任何更新。卡会停在最后一拍,重启时被标「已中断」。 */
|
|
139230
139909
|
dispose: () => {
|
|
139231
139910
|
disposed = true;
|
|
@@ -139236,19 +139915,21 @@ var makeTurnCards = (deps) => {
|
|
|
139236
139915
|
};
|
|
139237
139916
|
|
|
139238
139917
|
// src/replyCards.ts
|
|
139239
|
-
var makeReplyCards = (core, failures) => {
|
|
139918
|
+
var makeReplyCards = (core, failures, anchors) => {
|
|
139240
139919
|
const { host, adapterFor, commit, deliver, bindingForChatKey, bindingOfThread, ready } = core;
|
|
139241
139920
|
const stopRequested = /* @__PURE__ */ new Set();
|
|
139242
139921
|
const turnCards = makeTurnCards({
|
|
139243
139922
|
ready,
|
|
139244
|
-
resolveTarget: (threadId) => {
|
|
139923
|
+
resolveTarget: (threadId, turnId) => {
|
|
139245
139924
|
const binding = bindingOfThread(threadId);
|
|
139246
139925
|
const cards = binding === void 0 ? void 0 : adapterFor(binding.platform)?.turnCards;
|
|
139247
139926
|
if (binding === void 0 || cards === void 0) return null;
|
|
139927
|
+
let anchored;
|
|
139248
139928
|
return {
|
|
139249
139929
|
chatKey: chatKeyOf(binding),
|
|
139250
139930
|
throttleMs: cards.throttleMs,
|
|
139251
|
-
|
|
139931
|
+
rotates: cards.rotatesOnInteraction === true,
|
|
139932
|
+
open: async (view) => cards.open(await (anchored ??= anchors.anchored(binding, threadId, turnId)), view),
|
|
139252
139933
|
update: (cardId, view) => cards.update(binding, cardId, view)
|
|
139253
139934
|
};
|
|
139254
139935
|
},
|
|
@@ -139264,25 +139945,26 @@ var makeReplyCards = (core, failures) => {
|
|
|
139264
139945
|
const stopped = stopRequested.delete(threadId);
|
|
139265
139946
|
const thread = await host.projections.getThread(threadId).catch(() => null);
|
|
139266
139947
|
const session = thread?.session;
|
|
139948
|
+
const outcome = outcomeOfSession(session?.status);
|
|
139267
139949
|
const errorText2 = failures.forCard(
|
|
139268
139950
|
threadId,
|
|
139269
139951
|
turnId,
|
|
139270
139952
|
session?.lastError,
|
|
139271
|
-
|
|
139953
|
+
outcome === "failed"
|
|
139272
139954
|
);
|
|
139273
139955
|
if (errorText2 !== null) return { status: "error", errorText: errorText2 };
|
|
139274
|
-
if (stopped ||
|
|
139956
|
+
if (stopped || outcome === "stopped") {
|
|
139275
139957
|
return { status: "interrupted", errorText: null };
|
|
139276
139958
|
}
|
|
139277
139959
|
return { status: "done", errorText: null };
|
|
139278
139960
|
},
|
|
139279
139961
|
onOpened: (card) => commit("turn-card-opened", card),
|
|
139280
139962
|
onClosed: (cardId) => commit("turn-card-closed", { cardId }),
|
|
139281
|
-
fallback: async (
|
|
139963
|
+
fallback: async (threadId, turnId, chatKey, view) => {
|
|
139282
139964
|
const binding = bindingForChatKey(chatKey);
|
|
139283
139965
|
if (binding === void 0) return;
|
|
139284
139966
|
const text3 = [view.body, view.errorText ?? ""].filter((part) => part !== "").join("\n\n");
|
|
139285
|
-
await deliver(binding, text3);
|
|
139967
|
+
await deliver(await anchors.anchored(binding, threadId, turnId), text3);
|
|
139286
139968
|
},
|
|
139287
139969
|
schedule: (run, delayMs) => {
|
|
139288
139970
|
const timer = setTimeout(run, delayMs);
|
|
@@ -139333,24 +140015,6 @@ var ImNotConnectedError = class extends Error {
|
|
|
139333
140015
|
}
|
|
139334
140016
|
};
|
|
139335
140017
|
|
|
139336
|
-
// src/deliveryContract.ts
|
|
139337
|
-
var DELIVERY_SEND_ERROR_CODES = [
|
|
139338
|
-
"bad-request",
|
|
139339
|
-
"unknown-bot",
|
|
139340
|
-
"unknown-target",
|
|
139341
|
-
"bot-not-connected",
|
|
139342
|
-
"delivery-failed"
|
|
139343
|
-
];
|
|
139344
|
-
var isDeliverySendErrorCode = (value2) => typeof value2 === "string" && DELIVERY_SEND_ERROR_CODES.includes(value2);
|
|
139345
|
-
var DeliverySendError = class extends Error {
|
|
139346
|
-
code;
|
|
139347
|
-
constructor(code2, message) {
|
|
139348
|
-
super(message);
|
|
139349
|
-
this.name = "DeliverySendError";
|
|
139350
|
-
this.code = code2;
|
|
139351
|
-
}
|
|
139352
|
-
};
|
|
139353
|
-
|
|
139354
140018
|
// src/delivery.ts
|
|
139355
140019
|
var makeDeliverySender = (core, config2) => {
|
|
139356
140020
|
return async (input) => {
|
|
@@ -139359,16 +140023,16 @@ var makeDeliverySender = (core, config2) => {
|
|
|
139359
140023
|
if (bot === void 0) {
|
|
139360
140024
|
throw new DeliverySendError("unknown-bot", `Unknown bot '${input.botId}'.`);
|
|
139361
140025
|
}
|
|
139362
|
-
const
|
|
139363
|
-
if (
|
|
140026
|
+
const target2 = findDeliveryTarget(readDeliveryTargets(config2), input.botId, input.targetId);
|
|
140027
|
+
if (target2 === void 0) {
|
|
139364
140028
|
throw new DeliverySendError(
|
|
139365
140029
|
"unknown-target",
|
|
139366
140030
|
`Unknown target '${input.targetId}' for bot '${input.botId}'.`
|
|
139367
140031
|
);
|
|
139368
140032
|
}
|
|
139369
|
-
const binding = core.bindingOf(bot,
|
|
140033
|
+
const binding = core.bindingOf(bot, target2.platformChatId);
|
|
139370
140034
|
try {
|
|
139371
|
-
await core.adapterFor(bot.platform)?.sendText(binding, input.text, { targetKind:
|
|
140035
|
+
await core.adapterFor(bot.platform)?.sendText(binding, input.text, { targetKind: target2.kind });
|
|
139372
140036
|
} catch (error) {
|
|
139373
140037
|
throw new DeliverySendError(
|
|
139374
140038
|
error instanceof ImNotConnectedError ? "bot-not-connected" : "delivery-failed",
|
|
@@ -139379,188 +140043,6 @@ var makeDeliverySender = (core, config2) => {
|
|
|
139379
140043
|
};
|
|
139380
140044
|
};
|
|
139381
140045
|
|
|
139382
|
-
// src/deliveryHttp.ts
|
|
139383
|
-
import * as NodeCrypto from "node:crypto";
|
|
139384
|
-
import * as NodeHttp from "node:http";
|
|
139385
|
-
|
|
139386
|
-
// src/boundedBody.ts
|
|
139387
|
-
var readBoundedBody = (req, limit) => new Promise((resolve) => {
|
|
139388
|
-
const chunks = [];
|
|
139389
|
-
let size = 0;
|
|
139390
|
-
let settled = false;
|
|
139391
|
-
const finish = (result) => {
|
|
139392
|
-
if (settled) return;
|
|
139393
|
-
settled = true;
|
|
139394
|
-
resolve(result);
|
|
139395
|
-
};
|
|
139396
|
-
req.on("data", (chunk) => {
|
|
139397
|
-
if (settled) return;
|
|
139398
|
-
size += chunk.length;
|
|
139399
|
-
if (size > limit) {
|
|
139400
|
-
finish({ kind: "too-large" });
|
|
139401
|
-
req.destroy();
|
|
139402
|
-
return;
|
|
139403
|
-
}
|
|
139404
|
-
chunks.push(chunk);
|
|
139405
|
-
});
|
|
139406
|
-
req.on("end", () => finish({ kind: "ok", bytes: Buffer.concat(chunks) }));
|
|
139407
|
-
req.on("error", () => finish({ kind: "read-failed" }));
|
|
139408
|
-
req.on("close", () => finish({ kind: "read-failed" }));
|
|
139409
|
-
});
|
|
139410
|
-
|
|
139411
|
-
// src/deliveryHttp.ts
|
|
139412
|
-
var LOOPBACK = "127.0.0.1";
|
|
139413
|
-
var MAX_BODY_BYTES = 1 * 1024 * 1024;
|
|
139414
|
-
var PATH = "/v1/delivery/messages";
|
|
139415
|
-
var statusFor = (code2) => {
|
|
139416
|
-
switch (code2) {
|
|
139417
|
-
case "bad-request":
|
|
139418
|
-
return 400;
|
|
139419
|
-
case "unauthorized":
|
|
139420
|
-
return 401;
|
|
139421
|
-
case "unknown-bot":
|
|
139422
|
-
case "unknown-target":
|
|
139423
|
-
return 404;
|
|
139424
|
-
case "bot-not-connected":
|
|
139425
|
-
return 503;
|
|
139426
|
-
case "delivery-failed":
|
|
139427
|
-
return 502;
|
|
139428
|
-
case "method-not-allowed":
|
|
139429
|
-
return 405;
|
|
139430
|
-
case "unsupported-media-type":
|
|
139431
|
-
return 415;
|
|
139432
|
-
case "payload-too-large":
|
|
139433
|
-
return 413;
|
|
139434
|
-
}
|
|
139435
|
-
};
|
|
139436
|
-
var writeJson = (res, status, body) => {
|
|
139437
|
-
const payload = JSON.stringify(body);
|
|
139438
|
-
res.writeHead(status, {
|
|
139439
|
-
"content-type": "application/json; charset=utf-8",
|
|
139440
|
-
"content-length": Buffer.byteLength(payload),
|
|
139441
|
-
"cache-control": "no-store"
|
|
139442
|
-
});
|
|
139443
|
-
res.end(payload);
|
|
139444
|
-
};
|
|
139445
|
-
var writeError = (res, code2, message) => {
|
|
139446
|
-
writeJson(res, statusFor(code2), { error: { code: code2, message } });
|
|
139447
|
-
};
|
|
139448
|
-
var isLoopbackRemote = (remote) => {
|
|
139449
|
-
if (remote === void 0 || remote === "") return false;
|
|
139450
|
-
return remote === "127.0.0.1" || remote === "::1" || remote === "::ffff:127.0.0.1";
|
|
139451
|
-
};
|
|
139452
|
-
var timingSafeEqualString = (a, b) => {
|
|
139453
|
-
const left = Buffer.from(a);
|
|
139454
|
-
const right = Buffer.from(b);
|
|
139455
|
-
if (left.length !== right.length) return false;
|
|
139456
|
-
return NodeCrypto.timingSafeEqual(left, right);
|
|
139457
|
-
};
|
|
139458
|
-
var parseSendBody = (raw) => {
|
|
139459
|
-
let parsed;
|
|
139460
|
-
try {
|
|
139461
|
-
parsed = JSON.parse(raw.toString("utf8"));
|
|
139462
|
-
} catch {
|
|
139463
|
-
return "bad-request";
|
|
139464
|
-
}
|
|
139465
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return "bad-request";
|
|
139466
|
-
const record2 = parsed;
|
|
139467
|
-
const botId = record2["botId"];
|
|
139468
|
-
const targetId = record2["targetId"];
|
|
139469
|
-
const text3 = record2["text"];
|
|
139470
|
-
const format2 = record2["format"];
|
|
139471
|
-
if (typeof botId !== "string" || botId.trim() === "") return "bad-request";
|
|
139472
|
-
if (typeof targetId !== "string" || targetId.trim() === "") return "bad-request";
|
|
139473
|
-
if (typeof text3 !== "string" || text3.trim() === "") return "bad-request";
|
|
139474
|
-
if (format2 !== void 0 && format2 !== "plain" && format2 !== "markdown") return "bad-request";
|
|
139475
|
-
for (const key of Object.keys(record2)) {
|
|
139476
|
-
if (key !== "botId" && key !== "targetId" && key !== "text" && key !== "format") {
|
|
139477
|
-
return "bad-request";
|
|
139478
|
-
}
|
|
139479
|
-
}
|
|
139480
|
-
return {
|
|
139481
|
-
botId: botId.trim(),
|
|
139482
|
-
targetId: targetId.trim(),
|
|
139483
|
-
text: text3,
|
|
139484
|
-
format: format2 === "markdown" ? "markdown" : format2 === "plain" ? "plain" : void 0
|
|
139485
|
-
};
|
|
139486
|
-
};
|
|
139487
|
-
var startDeliveryHttpServer = async (options) => {
|
|
139488
|
-
const server = NodeHttp.createServer((req, res) => {
|
|
139489
|
-
void (async () => {
|
|
139490
|
-
if (!isLoopbackRemote(req.socket.remoteAddress)) {
|
|
139491
|
-
writeError(res, "unauthorized", "Only loopback clients are accepted.");
|
|
139492
|
-
return;
|
|
139493
|
-
}
|
|
139494
|
-
const url = new URL(req.url ?? "/", `http://${LOOPBACK}`);
|
|
139495
|
-
if (url.pathname !== PATH) {
|
|
139496
|
-
writeError(res, "bad-request", `Unknown path '${url.pathname}'.`);
|
|
139497
|
-
return;
|
|
139498
|
-
}
|
|
139499
|
-
if (req.method !== "POST") {
|
|
139500
|
-
res.setHeader("allow", "POST");
|
|
139501
|
-
writeError(res, "method-not-allowed", "Only POST is accepted.");
|
|
139502
|
-
return;
|
|
139503
|
-
}
|
|
139504
|
-
const contentType = (req.headers["content-type"] ?? "").split(";")[0]?.trim().toLowerCase();
|
|
139505
|
-
if (contentType !== "application/json") {
|
|
139506
|
-
writeError(res, "unsupported-media-type", "Content-Type must be application/json.");
|
|
139507
|
-
return;
|
|
139508
|
-
}
|
|
139509
|
-
if (options.token !== "") {
|
|
139510
|
-
const header = req.headers.authorization ?? "";
|
|
139511
|
-
const prefix = "Bearer ";
|
|
139512
|
-
if (!header.startsWith(prefix) || !timingSafeEqualString(header.slice(prefix.length), options.token)) {
|
|
139513
|
-
writeError(res, "unauthorized", "Bearer token required.");
|
|
139514
|
-
return;
|
|
139515
|
-
}
|
|
139516
|
-
}
|
|
139517
|
-
const read = await readBoundedBody(req, MAX_BODY_BYTES);
|
|
139518
|
-
if (read.kind !== "ok") {
|
|
139519
|
-
if (read.kind === "too-large") {
|
|
139520
|
-
writeError(res, "payload-too-large", "JSON body exceeds 1 MiB.");
|
|
139521
|
-
} else {
|
|
139522
|
-
writeError(res, "bad-request", "Failed to read body.");
|
|
139523
|
-
}
|
|
139524
|
-
return;
|
|
139525
|
-
}
|
|
139526
|
-
const parsed = parseSendBody(read.bytes);
|
|
139527
|
-
if (typeof parsed === "string") {
|
|
139528
|
-
writeError(res, parsed, "Invalid JSON body.");
|
|
139529
|
-
return;
|
|
139530
|
-
}
|
|
139531
|
-
try {
|
|
139532
|
-
const result = await options.send(parsed);
|
|
139533
|
-
writeJson(res, 200, { sent: result.sent });
|
|
139534
|
-
} catch (error) {
|
|
139535
|
-
const rawCode = error instanceof Error ? error.code : void 0;
|
|
139536
|
-
const code2 = isDeliverySendErrorCode(rawCode) ? rawCode : "delivery-failed";
|
|
139537
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
139538
|
-
options.log?.warn("delivery http send failed", { code: code2, message });
|
|
139539
|
-
writeError(res, code2, message);
|
|
139540
|
-
}
|
|
139541
|
-
})().catch((error) => {
|
|
139542
|
-
options.log?.warn("delivery http handler crashed", {
|
|
139543
|
-
error: error instanceof Error ? error.message : String(error)
|
|
139544
|
-
});
|
|
139545
|
-
if (!res.headersSent) writeError(res, "delivery-failed", "Internal error.");
|
|
139546
|
-
});
|
|
139547
|
-
});
|
|
139548
|
-
await new Promise((resolve, reject) => {
|
|
139549
|
-
server.once("error", reject);
|
|
139550
|
-
server.listen(options.port, LOOPBACK, () => resolve());
|
|
139551
|
-
});
|
|
139552
|
-
const address = server.address();
|
|
139553
|
-
const port = address.port;
|
|
139554
|
-
options.log?.info("delivery http listening", { host: LOOPBACK, port, path: PATH });
|
|
139555
|
-
return {
|
|
139556
|
-
port,
|
|
139557
|
-
origin: `http://${LOOPBACK}:${String(port)}`,
|
|
139558
|
-
close: () => new Promise((resolve, reject) => {
|
|
139559
|
-
server.close((error) => error ? reject(error) : resolve());
|
|
139560
|
-
})
|
|
139561
|
-
};
|
|
139562
|
-
};
|
|
139563
|
-
|
|
139564
140046
|
// src/sendFile.ts
|
|
139565
140047
|
var failure = (code2, text3) => ({
|
|
139566
140048
|
text: text3,
|
|
@@ -139616,7 +140098,7 @@ var makeSendFileTool = (deps) => ({
|
|
|
139616
140098
|
handle: async (input, invocation) => {
|
|
139617
140099
|
const path = typeof input["path"] === "string" ? input["path"].trim() : "";
|
|
139618
140100
|
if (path === "") return failure("unreadable", "`path` is required.");
|
|
139619
|
-
const binding = invocation.threadId === null ? void 0 : deps.boundChat(invocation.threadId);
|
|
140101
|
+
const binding = invocation.threadId === null ? void 0 : await deps.boundChat(invocation.threadId);
|
|
139620
140102
|
if (binding === void 0) {
|
|
139621
140103
|
return failure(
|
|
139622
140104
|
"not-in-chat",
|
|
@@ -139795,22 +140277,22 @@ var makeSessions = (core) => {
|
|
|
139795
140277
|
listedByChat.set(chatKeyOf(binding), listedThreadIds(rows));
|
|
139796
140278
|
await deliver(binding, formatSessions(rows, Date.now(), t));
|
|
139797
140279
|
};
|
|
139798
|
-
const bindToSession = async (binding, chatKey,
|
|
140280
|
+
const bindToSession = async (binding, chatKey, target2) => {
|
|
139799
140281
|
for (const [otherKey, record2] of Object.entries(core.state.chats)) {
|
|
139800
|
-
if (otherKey !== chatKey && record2.threadId ===
|
|
140282
|
+
if (otherKey !== chatKey && record2.threadId === target2.threadId) bindChat(otherKey, null);
|
|
139801
140283
|
}
|
|
139802
|
-
if (
|
|
140284
|
+
if (target2.origin === "web" && !hasAttached(core.state, chatKey, target2.threadId)) {
|
|
139803
140285
|
commit("thread-attached", {
|
|
139804
140286
|
chatKey,
|
|
139805
|
-
threadId:
|
|
140287
|
+
threadId: target2.threadId,
|
|
139806
140288
|
projectId: binding.projectId,
|
|
139807
140289
|
attachedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
139808
140290
|
});
|
|
139809
140291
|
}
|
|
139810
|
-
commit("chat-updated", { chatKey, threadId:
|
|
140292
|
+
commit("chat-updated", { chatKey, threadId: target2.threadId, target: { kind: "thread" } });
|
|
139811
140293
|
pendingAttachByChat.delete(chatKey);
|
|
139812
140294
|
listedByChat.delete(chatKey);
|
|
139813
|
-
await deliver(binding, t("resume.done", { title:
|
|
140295
|
+
await deliver(binding, t("resume.done", { title: target2.title }));
|
|
139814
140296
|
};
|
|
139815
140297
|
const resumeSession = async (binding, arg) => {
|
|
139816
140298
|
const chatKey = chatKeyOf(binding);
|
|
@@ -139845,8 +140327,8 @@ var makeSessions = (core) => {
|
|
|
139845
140327
|
return;
|
|
139846
140328
|
}
|
|
139847
140329
|
}
|
|
139848
|
-
const
|
|
139849
|
-
if (
|
|
140330
|
+
const target2 = rows.find((row) => row.threadId === targetId);
|
|
140331
|
+
if (target2 === void 0) {
|
|
139850
140332
|
if (confirming) pendingAttachByChat.delete(chatKey);
|
|
139851
140333
|
await deliver(binding, t("resume.gone"));
|
|
139852
140334
|
return;
|
|
@@ -139855,21 +140337,21 @@ var makeSessions = (core) => {
|
|
|
139855
140337
|
await deliver(binding, t("resume.busy"));
|
|
139856
140338
|
return;
|
|
139857
140339
|
}
|
|
139858
|
-
if (
|
|
140340
|
+
if (target2.current) {
|
|
139859
140341
|
if (confirming) pendingAttachByChat.delete(chatKey);
|
|
139860
140342
|
await deliver(binding, t("resume.already"));
|
|
139861
140343
|
return;
|
|
139862
140344
|
}
|
|
139863
|
-
if (
|
|
140345
|
+
if (target2.running && target2.elsewhere) {
|
|
139864
140346
|
await deliver(binding, t("resume.runningElsewhere"));
|
|
139865
140347
|
return;
|
|
139866
140348
|
}
|
|
139867
|
-
if (
|
|
139868
|
-
pendingAttachByChat.set(chatKey,
|
|
139869
|
-
await deliver(binding, t("resume.confirmWeb", { title:
|
|
140349
|
+
if (target2.origin === "web" && !confirming && pending !== target2.threadId && !hasAttached(core.state, chatKey, target2.threadId)) {
|
|
140350
|
+
pendingAttachByChat.set(chatKey, target2.threadId);
|
|
140351
|
+
await deliver(binding, t("resume.confirmWeb", { title: target2.title }));
|
|
139870
140352
|
return;
|
|
139871
140353
|
}
|
|
139872
|
-
await bindToSession(binding, chatKey,
|
|
140354
|
+
await bindToSession(binding, chatKey, target2);
|
|
139873
140355
|
};
|
|
139874
140356
|
return { listedByChat, sessionRowsFor, showSessions, resumeSession };
|
|
139875
140357
|
};
|
|
@@ -139915,7 +140397,7 @@ var makeTeamRuns = (core, deps) => {
|
|
|
139915
140397
|
const binding = chatByRun.get(runId);
|
|
139916
140398
|
if (binding === void 0) return;
|
|
139917
140399
|
chatByRun.delete(runId);
|
|
139918
|
-
await clearWorking(binding, chatKeyOf(binding));
|
|
140400
|
+
await clearWorking(binding, chatKeyOf(binding), outcomeOfTeamRun(event.data.state));
|
|
139919
140401
|
await deliver(binding, event.summary);
|
|
139920
140402
|
});
|
|
139921
140403
|
return { fetchTeams, startTeamRun };
|
|
@@ -139924,7 +140406,27 @@ var makeTeamRuns = (core, deps) => {
|
|
|
139924
140406
|
// src/telegramApi.ts
|
|
139925
140407
|
var API_BASE = "https://api.telegram.org";
|
|
139926
140408
|
var POLL_TIMEOUT_SECONDS = 45;
|
|
140409
|
+
var CALL_TIMEOUT_MS = 15e3;
|
|
140410
|
+
var POLL_CALL_TIMEOUT_MS = (POLL_TIMEOUT_SECONDS + 10) * 1e3;
|
|
140411
|
+
var UPLOAD_TIMEOUT_MS = 12e4;
|
|
140412
|
+
var DOWNLOAD_TIMEOUT_MS = 6e4;
|
|
140413
|
+
var HINT_TIMEOUT_MS = 3e3;
|
|
140414
|
+
var isTelegramToken = (token) => /^\d{5,20}:[A-Za-z0-9_-]{20,}$/u.test(token);
|
|
139927
140415
|
var TELEGRAM_TEXT_MAX_CHARS = 4e3;
|
|
140416
|
+
var chatIdOf = (message) => {
|
|
140417
|
+
const thread = message.message_thread_id;
|
|
140418
|
+
return message.is_topic_message === true && thread !== void 0 && thread > 0 ? `${String(message.chat.id)}:${String(thread)}` : String(message.chat.id);
|
|
140419
|
+
};
|
|
140420
|
+
var parentChatIdOf = (message) => chatIdOf(message) === String(message.chat.id) ? void 0 : String(message.chat.id);
|
|
140421
|
+
var splitChatId = (chatId) => {
|
|
140422
|
+
const match = /^(.+):([1-9]\d*)$/u.exec(chatId);
|
|
140423
|
+
return match === null ? { chat: chatId, thread: null } : { chat: match[1] ?? chatId, thread: Number(match[2]) };
|
|
140424
|
+
};
|
|
140425
|
+
var target = (chatId) => {
|
|
140426
|
+
const { chat, thread } = splitChatId(chatId);
|
|
140427
|
+
return { chat_id: chat, ...thread === null ? {} : { message_thread_id: thread } };
|
|
140428
|
+
};
|
|
140429
|
+
var chatOnly = (chatId) => ({ chat_id: splitChatId(chatId).chat });
|
|
139928
140430
|
var TelegramApiError = class extends Error {
|
|
139929
140431
|
code;
|
|
139930
140432
|
/** 限流(429)时平台给的等待秒数;别的错误没有。 */
|
|
@@ -140019,12 +140521,27 @@ var passesGroupGate2 = (input) => {
|
|
|
140019
140521
|
return input.groupMention === "ambient" && names.length === 0;
|
|
140020
140522
|
};
|
|
140021
140523
|
var makeTelegramApi = (input) => {
|
|
140022
|
-
const
|
|
140023
|
-
|
|
140024
|
-
|
|
140025
|
-
|
|
140026
|
-
|
|
140027
|
-
|
|
140524
|
+
const send = async (method, url, init, timeoutMs) => {
|
|
140525
|
+
try {
|
|
140526
|
+
return await input.http(url, { ...init, signal: AbortSignal.timeout(timeoutMs) });
|
|
140527
|
+
} catch (error) {
|
|
140528
|
+
if (error instanceof Error && error.name === "TimeoutError") {
|
|
140529
|
+
throw new TelegramApiError(method, void 0, `timed out after ${String(timeoutMs)} ms`);
|
|
140530
|
+
}
|
|
140531
|
+
throw error;
|
|
140532
|
+
}
|
|
140533
|
+
};
|
|
140534
|
+
const call = async (method, body, timeoutMs = CALL_TIMEOUT_MS) => {
|
|
140535
|
+
const response = await send(
|
|
140536
|
+
method,
|
|
140537
|
+
`${API_BASE}/bot${input.token}/${method}`,
|
|
140538
|
+
{
|
|
140539
|
+
method: "POST",
|
|
140540
|
+
headers: { "content-type": "application/json" },
|
|
140541
|
+
body: JSON.stringify(body)
|
|
140542
|
+
},
|
|
140543
|
+
timeoutMs
|
|
140544
|
+
);
|
|
140028
140545
|
const envelope = await response.json();
|
|
140029
140546
|
if (envelope.ok !== true) {
|
|
140030
140547
|
throw new TelegramApiError(
|
|
@@ -140038,12 +140555,18 @@ var makeTelegramApi = (input) => {
|
|
|
140038
140555
|
};
|
|
140039
140556
|
const upload = async (method, field, chatId, file) => {
|
|
140040
140557
|
const form = new FormData();
|
|
140041
|
-
|
|
140558
|
+
const where = target(chatId);
|
|
140559
|
+
form.set("chat_id", where.chat_id);
|
|
140560
|
+
if (where.message_thread_id !== void 0) {
|
|
140561
|
+
form.set("message_thread_id", String(where.message_thread_id));
|
|
140562
|
+
}
|
|
140042
140563
|
form.set(field, new Blob([new Uint8Array(file.bytes)], { type: file.mimeType }), file.name);
|
|
140043
|
-
const response = await
|
|
140044
|
-
method
|
|
140045
|
-
|
|
140046
|
-
|
|
140564
|
+
const response = await send(
|
|
140565
|
+
method,
|
|
140566
|
+
`${API_BASE}/bot${input.token}/${method}`,
|
|
140567
|
+
{ method: "POST", body: form },
|
|
140568
|
+
UPLOAD_TIMEOUT_MS
|
|
140569
|
+
);
|
|
140047
140570
|
const envelope = await response.json();
|
|
140048
140571
|
if (envelope.ok !== true) {
|
|
140049
140572
|
throw new TelegramApiError(
|
|
@@ -140061,7 +140584,7 @@ var makeTelegramApi = (input) => {
|
|
|
140061
140584
|
});
|
|
140062
140585
|
const sendSingle = async (method, chatId, body, rows) => {
|
|
140063
140586
|
const sent = await call(method, {
|
|
140064
|
-
|
|
140587
|
+
...target(chatId),
|
|
140065
140588
|
...body,
|
|
140066
140589
|
...rows === void 0 ? {} : { reply_markup: keyboard(rows) }
|
|
140067
140590
|
});
|
|
@@ -140070,7 +140593,7 @@ var makeTelegramApi = (input) => {
|
|
|
140070
140593
|
const editSingle = async (chatId, messageId, body, rows) => {
|
|
140071
140594
|
try {
|
|
140072
140595
|
await call("editMessageText", {
|
|
140073
|
-
|
|
140596
|
+
...chatOnly(chatId),
|
|
140074
140597
|
message_id: Number(messageId),
|
|
140075
140598
|
...body,
|
|
140076
140599
|
reply_markup: keyboard(rows)
|
|
@@ -140081,23 +140604,49 @@ var makeTelegramApi = (input) => {
|
|
|
140081
140604
|
};
|
|
140082
140605
|
return {
|
|
140083
140606
|
/** 机器人自己是谁;群里的命令靠它的 `username` 认出是不是发给自己的。 */
|
|
140084
|
-
getMe: () => call(
|
|
140607
|
+
getMe: () => call(
|
|
140608
|
+
"getMe",
|
|
140609
|
+
{}
|
|
140610
|
+
),
|
|
140611
|
+
/**
|
|
140612
|
+
* 这个机器人是不是还挂着别处设的 webhook。挂着的话 `getUpdates` 一直回 409,表现就是
|
|
140613
|
+
* 「没反应」。只查不删:那多半是另一个服务正在用这个机器人。
|
|
140614
|
+
*/
|
|
140615
|
+
getWebhookInfo: () => call("getWebhookInfo", {}),
|
|
140616
|
+
/** 整表替换输入 `/` 时弹出的命令菜单(缺省范围、缺省语言)。 */
|
|
140617
|
+
setMyCommands: (commands) => call("setMyCommands", { commands }),
|
|
140618
|
+
/** 「正在输入」:客户端显示几秒,或机器人发出下一条消息时消失。 */
|
|
140619
|
+
sendTyping: (chatId) => call("sendChatAction", { ...target(chatId), action: "typing" }, HINT_TIMEOUT_MS),
|
|
140620
|
+
/** 给一条消息贴一个表情(整体替换);`emoji` 为 null 就撤掉。 */
|
|
140621
|
+
setReaction: (chatId, messageId, emoji) => call(
|
|
140622
|
+
"setMessageReaction",
|
|
140623
|
+
{
|
|
140624
|
+
...chatOnly(chatId),
|
|
140625
|
+
message_id: Number(messageId),
|
|
140626
|
+
reaction: emoji === null ? [] : [{ type: "emoji", emoji }]
|
|
140627
|
+
},
|
|
140628
|
+
HINT_TIMEOUT_MS
|
|
140629
|
+
),
|
|
140085
140630
|
/** 群里一共多少成员(含机器人自己)。单人群放宽靠它:两个成员就是发命令的人加机器人。 */
|
|
140086
|
-
getChatMemberCount: (chatId) => call("getChatMemberCount",
|
|
140631
|
+
getChatMemberCount: (chatId) => call("getChatMemberCount", chatOnly(chatId)),
|
|
140087
140632
|
/**
|
|
140088
140633
|
* 拉一批更新。挂在服务端最多 `POLL_TIMEOUT_SECONDS` 秒。
|
|
140089
140634
|
*
|
|
140090
140635
|
* `allowed_updates` 必须列全:它是服务端白名单,不写 `callback_query` 的话按钮点击
|
|
140091
140636
|
* 根本不会投递过来,而且不会有任何报错。
|
|
140092
140637
|
*/
|
|
140093
|
-
getUpdates: (offset) => call(
|
|
140094
|
-
|
|
140095
|
-
|
|
140096
|
-
|
|
140097
|
-
|
|
140638
|
+
getUpdates: (offset) => call(
|
|
140639
|
+
"getUpdates",
|
|
140640
|
+
{
|
|
140641
|
+
offset,
|
|
140642
|
+
timeout: POLL_TIMEOUT_SECONDS,
|
|
140643
|
+
allowed_updates: ["message", "callback_query"]
|
|
140644
|
+
},
|
|
140645
|
+
POLL_CALL_TIMEOUT_MS
|
|
140646
|
+
),
|
|
140098
140647
|
sendMessage: async (chatId, text3) => {
|
|
140099
140648
|
for (const chunk of splitForTelegram(text3)) {
|
|
140100
|
-
await call("sendMessage", {
|
|
140649
|
+
await call("sendMessage", { ...target(chatId), text: chunk });
|
|
140101
140650
|
}
|
|
140102
140651
|
},
|
|
140103
140652
|
/**
|
|
@@ -140147,7 +140696,12 @@ var makeTelegramApi = (input) => {
|
|
|
140147
140696
|
});
|
|
140148
140697
|
const path = file.file_path;
|
|
140149
140698
|
if (path === void 0) throw new TelegramApiError("getFile", void 0, "no file_path");
|
|
140150
|
-
const response = await
|
|
140699
|
+
const response = await send(
|
|
140700
|
+
"file",
|
|
140701
|
+
`${API_BASE}/file/bot${input.token}/${path}`,
|
|
140702
|
+
{},
|
|
140703
|
+
DOWNLOAD_TIMEOUT_MS
|
|
140704
|
+
);
|
|
140151
140705
|
if (!response.ok) {
|
|
140152
140706
|
throw new TelegramApiError("file", response.status, "download failed");
|
|
140153
140707
|
}
|
|
@@ -140156,6 +140710,29 @@ var makeTelegramApi = (input) => {
|
|
|
140156
140710
|
};
|
|
140157
140711
|
};
|
|
140158
140712
|
|
|
140713
|
+
// src/telegramCommandMenu.ts
|
|
140714
|
+
var DESCRIPTIONS = {
|
|
140715
|
+
new: "menu.new",
|
|
140716
|
+
stop: "menu.stop",
|
|
140717
|
+
continue: "menu.continue",
|
|
140718
|
+
repo: "menu.repo",
|
|
140719
|
+
sessions: "menu.sessions",
|
|
140720
|
+
team: "menu.team",
|
|
140721
|
+
thread: "menu.thread",
|
|
140722
|
+
model: "menu.model",
|
|
140723
|
+
plan: "menu.plan",
|
|
140724
|
+
status: "menu.status",
|
|
140725
|
+
help: "menu.help",
|
|
140726
|
+
resume: "menu.resume",
|
|
140727
|
+
panel: "menu.panel"
|
|
140728
|
+
};
|
|
140729
|
+
var TELEGRAM_MENU = [
|
|
140730
|
+
...PANEL_COMMANDS.map((spec) => ({ command: spec.line.slice(1), key: DESCRIPTIONS[spec.id] })),
|
|
140731
|
+
{ command: "resume", key: DESCRIPTIONS.resume },
|
|
140732
|
+
{ command: "panel", key: DESCRIPTIONS.panel }
|
|
140733
|
+
];
|
|
140734
|
+
var telegramCommandMenu = (t) => TELEGRAM_MENU.map((item) => ({ command: item.command, description: t(item.key) }));
|
|
140735
|
+
|
|
140159
140736
|
// src/telegramChoice.ts
|
|
140160
140737
|
var renderChoiceCard = (card) => ({
|
|
140161
140738
|
text: [card.title, card.heading ?? "", card.body, card.note ?? ""].filter((part) => part !== "").join("\n\n"),
|
|
@@ -140294,8 +140871,18 @@ var BACKOFF_MAX_MS = 6e4;
|
|
|
140294
140871
|
var TELEGRAM_CARD_THROTTLE_MS = 1200;
|
|
140295
140872
|
var FLOOD_WAIT_MAX_SECONDS = 30;
|
|
140296
140873
|
var REMEMBERED_CARD_LIMIT = 200;
|
|
140297
|
-
var tokenOf = (binding) => binding.values["telegramToken"] ?? "";
|
|
140874
|
+
var tokenOf = (binding) => (binding.values["telegramToken"] ?? "").trim();
|
|
140875
|
+
var REACTION_WORKING = "\u{1F440}";
|
|
140876
|
+
var REACTION_DONE = "\u{1F44D}";
|
|
140877
|
+
var REACTION_FAILED = "\u{1F44E}";
|
|
140298
140878
|
var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
140879
|
+
var webhookHost = (url) => {
|
|
140880
|
+
try {
|
|
140881
|
+
return new URL(url).host;
|
|
140882
|
+
} catch {
|
|
140883
|
+
return "(unreadable)";
|
|
140884
|
+
}
|
|
140885
|
+
};
|
|
140299
140886
|
var makeTelegramAdapter = (deps) => {
|
|
140300
140887
|
const apis = /* @__PURE__ */ new Map();
|
|
140301
140888
|
const sleep3 = deps.sleep ?? defaultSleep;
|
|
@@ -140340,26 +140927,31 @@ var makeTelegramAdapter = (deps) => {
|
|
|
140340
140927
|
const panelKeyboards = remembering();
|
|
140341
140928
|
const panelClick = (rowId, callback, operatorId, handlers) => {
|
|
140342
140929
|
const messageId = callback.message?.message_id;
|
|
140343
|
-
const chatId = callback.message
|
|
140930
|
+
const chatId = callback.message === void 0 ? void 0 : chatIdOf(callback.message);
|
|
140344
140931
|
if (messageId === void 0 || chatId === void 0) return t("panel.expired");
|
|
140345
|
-
const keyboard = panelKeyboards.get(`${rowId}:${
|
|
140932
|
+
const keyboard = panelKeyboards.get(`${rowId}:${chatId}:${String(messageId)}`);
|
|
140346
140933
|
const parsed = parsePanelData(callback.data ?? "");
|
|
140347
140934
|
const action = keyboard === void 0 || parsed === null || parsed.version !== keyboard.version ? void 0 : keyboard.actions[parsed.index];
|
|
140348
140935
|
if (action === void 0) return t("panel.expired");
|
|
140349
140936
|
return handlers.onPanelClick?.({
|
|
140350
|
-
chatId
|
|
140937
|
+
chatId,
|
|
140351
140938
|
cardId: String(messageId),
|
|
140352
140939
|
operatorId,
|
|
140353
140940
|
op: action.op,
|
|
140354
140941
|
arg: action.arg ?? null
|
|
140355
140942
|
}) ?? null;
|
|
140356
140943
|
};
|
|
140357
|
-
const apiFor =
|
|
140944
|
+
const apiFor = (binding) => {
|
|
140945
|
+
const token = tokenOf(binding);
|
|
140946
|
+
const builtFor = JSON.stringify([token, binding.proxy === void 0 ? [] : [binding.proxy]]);
|
|
140358
140947
|
const existing = apis.get(binding.rowId);
|
|
140359
|
-
if (existing
|
|
140360
|
-
const
|
|
140361
|
-
const
|
|
140362
|
-
apis.set(binding.rowId,
|
|
140948
|
+
if (existing?.builtFor === builtFor) return existing.api;
|
|
140949
|
+
const api = deps.fetchVia(binding.proxy).then((http) => makeTelegramApi({ http, token }));
|
|
140950
|
+
const entry = { builtFor, api };
|
|
140951
|
+
apis.set(binding.rowId, entry);
|
|
140952
|
+
api.catch(() => {
|
|
140953
|
+
if (apis.get(binding.rowId) === entry) apis.delete(binding.rowId);
|
|
140954
|
+
});
|
|
140363
140955
|
return api;
|
|
140364
140956
|
};
|
|
140365
140957
|
const makeWriter = (api, chatId, resume) => makeTurnWriter({
|
|
@@ -140393,6 +140985,7 @@ var makeTelegramAdapter = (deps) => {
|
|
|
140393
140985
|
let offset = 0;
|
|
140394
140986
|
let backoff = BACKOFF_START_MS;
|
|
140395
140987
|
let botUsername;
|
|
140988
|
+
let menuSent = false;
|
|
140396
140989
|
const isSoloGroup = makeSoloGroupCheck(async (chatId) => {
|
|
140397
140990
|
const count = await (await apiFor(binding)).getChatMemberCount(chatId);
|
|
140398
140991
|
return Number.isFinite(count) ? count <= 2 : void 0;
|
|
@@ -140403,6 +140996,15 @@ var makeTelegramAdapter = (deps) => {
|
|
|
140403
140996
|
try {
|
|
140404
140997
|
const api = await apiFor(binding);
|
|
140405
140998
|
botUsername ??= (await api.getMe()).username ?? null;
|
|
140999
|
+
if (!menuSent) {
|
|
141000
|
+
menuSent = true;
|
|
141001
|
+
void api.setMyCommands(telegramCommandMenu(t)).catch((error) => {
|
|
141002
|
+
deps.log.warn("telegram could not set the command menu", {
|
|
141003
|
+
bot: binding.displayName,
|
|
141004
|
+
error: describeError(error)
|
|
141005
|
+
});
|
|
141006
|
+
});
|
|
141007
|
+
}
|
|
140406
141008
|
const updates = await api.getUpdates(offset);
|
|
140407
141009
|
if (!running) return;
|
|
140408
141010
|
backoff = BACKOFF_START_MS;
|
|
@@ -140438,7 +141040,7 @@ var makeTelegramAdapter = (deps) => {
|
|
|
140438
141040
|
if (unsupported === null) continue;
|
|
140439
141041
|
handlers.onMessage({
|
|
140440
141042
|
messageId: String(message.message_id),
|
|
140441
|
-
chatId:
|
|
141043
|
+
chatId: chatIdOf(message),
|
|
140442
141044
|
senderId: message.from === void 0 ? null : String(message.from.id),
|
|
140443
141045
|
text: "",
|
|
140444
141046
|
chatKind: message.chat.type === "private" ? "private" : "group",
|
|
@@ -140447,9 +141049,11 @@ var makeTelegramAdapter = (deps) => {
|
|
|
140447
141049
|
});
|
|
140448
141050
|
continue;
|
|
140449
141051
|
}
|
|
141052
|
+
const parentChatId = parentChatIdOf(message);
|
|
140450
141053
|
handlers.onMessage({
|
|
140451
141054
|
messageId: String(message.message_id),
|
|
140452
|
-
chatId:
|
|
141055
|
+
chatId: chatIdOf(message),
|
|
141056
|
+
...parentChatId === void 0 ? {} : { parentChatId },
|
|
140453
141057
|
senderId: message.from === void 0 ? null : String(message.from.id),
|
|
140454
141058
|
text: text3,
|
|
140455
141059
|
chatKind: message.chat.type === "private" ? "private" : "group",
|
|
@@ -140487,16 +141091,68 @@ var makeTelegramAdapter = (deps) => {
|
|
|
140487
141091
|
await api.sendMessage(binding.chatId, text3);
|
|
140488
141092
|
},
|
|
140489
141093
|
checkConnection: async (bot) => {
|
|
140490
|
-
|
|
141094
|
+
const token = tokenOf(bot);
|
|
141095
|
+
if (token === "") {
|
|
140491
141096
|
return { stage: "credentials", ok: false, detail: "missing bot token in saved config" };
|
|
140492
141097
|
}
|
|
141098
|
+
if (!isTelegramToken(token)) {
|
|
141099
|
+
return {
|
|
141100
|
+
stage: "token-format",
|
|
141101
|
+
ok: false,
|
|
141102
|
+
detail: "saved token is not in the BotFather format",
|
|
141103
|
+
hint: "badToken"
|
|
141104
|
+
};
|
|
141105
|
+
}
|
|
141106
|
+
const api = await apiFor(bot);
|
|
141107
|
+
let username;
|
|
141108
|
+
try {
|
|
141109
|
+
const me = await api.getMe();
|
|
141110
|
+
if (me.is_bot !== true) {
|
|
141111
|
+
return { stage: "getMe", ok: false, detail: "token is not a bot's", hint: "notBot" };
|
|
141112
|
+
}
|
|
141113
|
+
username = me.username !== void 0 && me.username !== "" ? `@${me.username}` : "(no username)";
|
|
141114
|
+
} catch (error) {
|
|
141115
|
+
const rejected = error instanceof TelegramApiError && (error.code === 401 || error.code === 404);
|
|
141116
|
+
return {
|
|
141117
|
+
stage: "getMe",
|
|
141118
|
+
ok: false,
|
|
141119
|
+
detail: describeError(error),
|
|
141120
|
+
...rejected ? { hint: "unauthorized" } : {}
|
|
141121
|
+
};
|
|
141122
|
+
}
|
|
140493
141123
|
try {
|
|
140494
|
-
const
|
|
140495
|
-
|
|
140496
|
-
|
|
141124
|
+
const webhook = (await api.getWebhookInfo()).url ?? "";
|
|
141125
|
+
if (webhook !== "") {
|
|
141126
|
+
return {
|
|
141127
|
+
stage: "getWebhookInfo",
|
|
141128
|
+
ok: false,
|
|
141129
|
+
detail: `webhook is set (host ${webhookHost(webhook)})`,
|
|
141130
|
+
hint: "webhookActive"
|
|
141131
|
+
};
|
|
141132
|
+
}
|
|
140497
141133
|
} catch (error) {
|
|
140498
|
-
return { stage: "
|
|
141134
|
+
return { stage: "getWebhookInfo", ok: false, detail: describeError(error) };
|
|
140499
141135
|
}
|
|
141136
|
+
return { stage: "getMe", ok: true, detail: `username=${username} webhook=none` };
|
|
141137
|
+
},
|
|
141138
|
+
sendTyping: async (binding) => {
|
|
141139
|
+
await (await apiFor(binding)).sendTyping(binding.chatId);
|
|
141140
|
+
},
|
|
141141
|
+
acknowledge: async (binding, messageId) => {
|
|
141142
|
+
try {
|
|
141143
|
+
await (await apiFor(binding)).setReaction(binding.chatId, messageId, REACTION_WORKING);
|
|
141144
|
+
return REACTION_WORKING;
|
|
141145
|
+
} catch (error) {
|
|
141146
|
+
if (error instanceof TelegramApiError && error.code === 400) {
|
|
141147
|
+
deps.log.info("telegram could not react to the message", { reason: error.message });
|
|
141148
|
+
return null;
|
|
141149
|
+
}
|
|
141150
|
+
throw error;
|
|
141151
|
+
}
|
|
141152
|
+
},
|
|
141153
|
+
clearAcknowledge: async (binding, messageId, _ackId, outcome) => {
|
|
141154
|
+
const emoji = outcome === "done" ? REACTION_DONE : outcome === "failed" ? REACTION_FAILED : null;
|
|
141155
|
+
await (await apiFor(binding)).setReaction(binding.chatId, messageId, emoji);
|
|
140500
141156
|
},
|
|
140501
141157
|
sendImage: async (binding, image2) => {
|
|
140502
141158
|
const api = await apiFor(binding);
|
|
@@ -140623,6 +141279,10 @@ var makeTurns = (core, deps) => {
|
|
|
140623
141279
|
return true;
|
|
140624
141280
|
}
|
|
140625
141281
|
};
|
|
141282
|
+
const waitingFor = (chatKey, threadId) => {
|
|
141283
|
+
const waiting = pendingByChat.get(chatKey);
|
|
141284
|
+
return waiting !== void 0 && waiting.threadId === threadId ? waiting : void 0;
|
|
141285
|
+
};
|
|
140626
141286
|
const interactionModeOf = (chatKey) => chatOf(core.state, chatKey).plan ? "plan" : "default";
|
|
140627
141287
|
const ensureThread = async (binding, titleSeed) => {
|
|
140628
141288
|
const chatKey = chatKeyOf(binding);
|
|
@@ -140682,9 +141342,8 @@ var makeTurns = (core, deps) => {
|
|
|
140682
141342
|
const text3 = message.text;
|
|
140683
141343
|
const threadId = await ensureThread(binding, text3 || message.resources[0]?.name || "Chat");
|
|
140684
141344
|
if (threadId === null) return null;
|
|
140685
|
-
const
|
|
141345
|
+
const carried = waitingFor(chatKey, threadId);
|
|
140686
141346
|
pendingByChat.delete(chatKey);
|
|
140687
|
-
const carried = waiting?.threadId === threadId ? waiting : void 0;
|
|
140688
141347
|
const own = await collectResources(
|
|
140689
141348
|
binding,
|
|
140690
141349
|
threadId,
|
|
@@ -140695,6 +141354,7 @@ var makeTurns = (core, deps) => {
|
|
|
140695
141354
|
const attachments = [...carried?.attachments ?? [], ...own.attachments];
|
|
140696
141355
|
const notes = [...carried?.notes ?? [], ...own.notes];
|
|
140697
141356
|
const userMessageId = crypto.randomUUID();
|
|
141357
|
+
deps.anchors.note(threadId, userMessageId, binding);
|
|
140698
141358
|
let intentAction;
|
|
140699
141359
|
if (binding.queueMode === "steer") {
|
|
140700
141360
|
try {
|
|
@@ -140742,7 +141402,8 @@ var makeTurns = (core, deps) => {
|
|
|
140742
141402
|
chatKey,
|
|
140743
141403
|
threadId,
|
|
140744
141404
|
userMessageId,
|
|
140745
|
-
text3.trim() || attachments[0]?.name || message.resources[0]?.name || ""
|
|
141405
|
+
text3.trim() || attachments[0]?.name || message.resources[0]?.name || "",
|
|
141406
|
+
binding.reply
|
|
140746
141407
|
);
|
|
140747
141408
|
return threadId;
|
|
140748
141409
|
};
|
|
@@ -140768,7 +141429,14 @@ var makeTurns = (core, deps) => {
|
|
|
140768
141429
|
})
|
|
140769
141430
|
);
|
|
140770
141431
|
};
|
|
140771
|
-
|
|
141432
|
+
const hasWaitingAttachments = (chatKey) => (waitingFor(chatKey, chatOf(core.state, chatKey).threadId)?.attachments.length ?? 0) > 0;
|
|
141433
|
+
return {
|
|
141434
|
+
threadStillUsable,
|
|
141435
|
+
ensureThread,
|
|
141436
|
+
startTurn,
|
|
141437
|
+
receiveAttachmentsOnly,
|
|
141438
|
+
hasWaitingAttachments
|
|
141439
|
+
};
|
|
140772
141440
|
};
|
|
140773
141441
|
|
|
140774
141442
|
// src/webSync.ts
|
|
@@ -140842,7 +141510,7 @@ var botOf = (config2, adapters, rowId) => {
|
|
|
140842
141510
|
const adapterFor = (platform) => adapters.find((adapter) => adapter.platform === platform);
|
|
140843
141511
|
return readBots(config2, adapterFor).find((bot) => bot.rowId === rowId);
|
|
140844
141512
|
};
|
|
140845
|
-
var reportOf = (bot, stage, ok, detail) => ({
|
|
141513
|
+
var reportOf = (bot, stage, ok, detail, hint) => ({
|
|
140846
141514
|
ref: diagnosticRef("conn"),
|
|
140847
141515
|
platform: bot.platform,
|
|
140848
141516
|
botName: bot.displayName,
|
|
@@ -140850,7 +141518,8 @@ var reportOf = (bot, stage, ok, detail) => ({
|
|
|
140850
141518
|
stage,
|
|
140851
141519
|
ok,
|
|
140852
141520
|
detail,
|
|
140853
|
-
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
141521
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
141522
|
+
...hint === void 0 ? {} : { hint }
|
|
140854
141523
|
});
|
|
140855
141524
|
var probe = async (adapters, bot) => {
|
|
140856
141525
|
const adapter = adapters.find((candidate) => candidate.platform === bot.platform);
|
|
@@ -140867,7 +141536,8 @@ var probe = async (adapters, bot) => {
|
|
|
140867
141536
|
bot,
|
|
140868
141537
|
result.stage,
|
|
140869
141538
|
result.ok,
|
|
140870
|
-
result.ok ? result.detail : redactor.redact(result.detail)
|
|
141539
|
+
result.ok ? result.detail : redactor.redact(result.detail),
|
|
141540
|
+
result.hint
|
|
140871
141541
|
);
|
|
140872
141542
|
} catch (error) {
|
|
140873
141543
|
return reportOf(bot, "check", false, redactor.redact(describeError(error)));
|
|
@@ -140886,7 +141556,7 @@ var emitReport = (emit, report, action) => {
|
|
|
140886
141556
|
}
|
|
140887
141557
|
emit({
|
|
140888
141558
|
kind: "failed",
|
|
140889
|
-
reasonKey: `${action.keyPrefix}.failed`,
|
|
141559
|
+
reasonKey: report.hint !== void 0 && action.keyPrefix === "rowAction.checkConnection" ? `rowAction.checkConnection.hint.${report.hint}` : `${action.keyPrefix}.failed`,
|
|
140890
141560
|
params: { ref: report.ref },
|
|
140891
141561
|
detail
|
|
140892
141562
|
});
|
|
@@ -141589,6 +142259,7 @@ ${kept}`;
|
|
|
141589
142259
|
icon: "wecom",
|
|
141590
142260
|
label: "WeCom",
|
|
141591
142261
|
columns: COLUMNS4,
|
|
142262
|
+
unlistedValues: ["wecomEndpoint"],
|
|
141592
142263
|
isConfigured: (binding) => {
|
|
141593
142264
|
const { botId, botSecret } = credentials2(binding);
|
|
141594
142265
|
return botId !== "" && botSecret !== "";
|
|
@@ -142695,7 +143366,9 @@ var imPlugin = definePlugin({
|
|
|
142695
143366
|
id: "im",
|
|
142696
143367
|
apiVersion: 3,
|
|
142697
143368
|
activate: async (ctx) => {
|
|
142698
|
-
const t =
|
|
143369
|
+
const { t, setLanguage } = makeLiveTranslate(
|
|
143370
|
+
parseReplyLanguage(ctx.config[REPLY_LANGUAGE_FIELD])
|
|
143371
|
+
);
|
|
142699
143372
|
const adapters = [
|
|
142700
143373
|
makeLarkAdapter({
|
|
142701
143374
|
http: ctx.http,
|
|
@@ -142764,29 +143437,36 @@ var imPlugin = definePlugin({
|
|
|
142764
143437
|
onDispose: ctx.onDispose
|
|
142765
143438
|
},
|
|
142766
143439
|
pluginId: ctx.id,
|
|
142767
|
-
config: ctx.config,
|
|
143440
|
+
config: () => ctx.config,
|
|
142768
143441
|
derivedState: ctx.derivedState,
|
|
142769
143442
|
t,
|
|
142770
143443
|
adapters
|
|
142771
143444
|
});
|
|
142772
143445
|
const acknowledgements = makeAcknowledgements(core);
|
|
142773
143446
|
const failures = makeFailureNotices(core);
|
|
142774
|
-
const
|
|
143447
|
+
const replyAnchors = makeReplyAnchors(core.host);
|
|
143448
|
+
const replyCards = makeReplyCards(core, failures, replyAnchors);
|
|
142775
143449
|
const teams = makeTeamRuns(core, { clearWorking: acknowledgements.clearWorking });
|
|
142776
143450
|
const notifications = makeNotifications(core, {
|
|
142777
143451
|
clearWorking: acknowledgements.clearWorking,
|
|
142778
143452
|
replyCards,
|
|
142779
|
-
failures
|
|
143453
|
+
failures,
|
|
143454
|
+
anchors: replyAnchors
|
|
142780
143455
|
});
|
|
142781
143456
|
const webSync = makeWebSync(core);
|
|
142782
|
-
const approvals = makeApprovals(core);
|
|
142783
|
-
const interactions = makeInteractions(core,
|
|
143457
|
+
const approvals = makeApprovals(core, replyAnchors);
|
|
143458
|
+
const interactions = makeInteractions(core, {
|
|
143459
|
+
...approvals,
|
|
143460
|
+
anchors: replyAnchors,
|
|
143461
|
+
rotateTurnCard: replyCards.turnCards.rotate
|
|
143462
|
+
});
|
|
142784
143463
|
const inboundAttachments = makeInboundAttachments(core);
|
|
142785
143464
|
const turns = makeTurns(core, {
|
|
142786
143465
|
attachments: inboundAttachments,
|
|
142787
143466
|
queueFlow: interactions.queueFlow,
|
|
142788
143467
|
rememberThreadProject: notifications.rememberThreadProject,
|
|
142789
|
-
noteInboundUserMessage: webSync.noteInboundUserMessage
|
|
143468
|
+
noteInboundUserMessage: webSync.noteInboundUserMessage,
|
|
143469
|
+
anchors: replyAnchors
|
|
142790
143470
|
});
|
|
142791
143471
|
const sessions = makeSessions(core);
|
|
142792
143472
|
const modelPlan = makeModelPlan(core, turns);
|
|
@@ -142802,7 +143482,7 @@ var imPlugin = definePlugin({
|
|
|
142802
143482
|
});
|
|
142803
143483
|
const chatSetup = makeChatSetup(core, {
|
|
142804
143484
|
rows: projectRows,
|
|
142805
|
-
openPicker: (chatKey, rows) => panelWiring.panel.openProjects(chatKey, rows)
|
|
143485
|
+
openPicker: (chatKey, rows, reply) => panelWiring.panel.openProjects(chatKey, rows, reply)
|
|
142806
143486
|
});
|
|
142807
143487
|
const commands = makeCommands(core, {
|
|
142808
143488
|
clearWorking: acknowledgements.clearWorking,
|
|
@@ -142810,7 +143490,7 @@ var imPlugin = definePlugin({
|
|
|
142810
143490
|
sessions,
|
|
142811
143491
|
modelPlan,
|
|
142812
143492
|
chatSetup,
|
|
142813
|
-
openPanel: (chatKey) => panelWiring.panel.open(chatKey)
|
|
143493
|
+
openPanel: (chatKey, reply) => panelWiring.panel.open(chatKey, reply)
|
|
142814
143494
|
});
|
|
142815
143495
|
const inbound = makeInbound(core, {
|
|
142816
143496
|
enqueueForChat: chatQueue.enqueueForChat,
|
|
@@ -142828,7 +143508,10 @@ var imPlugin = definePlugin({
|
|
|
142828
143508
|
name: "im",
|
|
142829
143509
|
tools: [
|
|
142830
143510
|
makeSendFileTool({
|
|
142831
|
-
boundChat: (threadId) =>
|
|
143511
|
+
boundChat: async (threadId) => {
|
|
143512
|
+
const binding = core.bindingOfThread(threadId);
|
|
143513
|
+
return binding === void 0 ? void 0 : replyAnchors.anchored(binding, threadId, null);
|
|
143514
|
+
},
|
|
142832
143515
|
adapterFor: (binding) => core.adapterFor(binding.platform),
|
|
142833
143516
|
translate: t,
|
|
142834
143517
|
log: {
|
|
@@ -142838,34 +143521,21 @@ var imPlugin = definePlugin({
|
|
|
142838
143521
|
})
|
|
142839
143522
|
]
|
|
142840
143523
|
});
|
|
142841
|
-
const
|
|
142842
|
-
|
|
142843
|
-
|
|
142844
|
-
|
|
142845
|
-
|
|
142846
|
-
|
|
142847
|
-
|
|
142848
|
-
|
|
142849
|
-
|
|
142850
|
-
|
|
142851
|
-
|
|
142852
|
-
|
|
142853
|
-
|
|
142854
|
-
|
|
142855
|
-
|
|
142856
|
-
ctx.onDispose(() => {
|
|
142857
|
-
void server.close().catch((error) => {
|
|
142858
|
-
ctx.log.warn("delivery http could not close", {
|
|
142859
|
-
error: error instanceof Error ? error.message : String(error)
|
|
142860
|
-
});
|
|
142861
|
-
});
|
|
142862
|
-
});
|
|
142863
|
-
} catch (error) {
|
|
142864
|
-
ctx.log.warn("delivery http failed to listen", {
|
|
142865
|
-
port,
|
|
142866
|
-
error: error instanceof Error ? error.message : String(error)
|
|
142867
|
-
});
|
|
142868
|
-
}
|
|
143524
|
+
const connections = startConnections(core, inbound.inboundHandlersFor);
|
|
143525
|
+
const { bots, connecting } = connections.reconcile();
|
|
143526
|
+
const deliveryHttp = makeDeliveryHttp({
|
|
143527
|
+
// 每次请求按此刻的设置找目标:投递目标表改了不用重开监听。
|
|
143528
|
+
send: (input) => makeDeliverySender(core, ctx.config)(input),
|
|
143529
|
+
log: ctx.log,
|
|
143530
|
+
onDispose: ctx.onDispose
|
|
143531
|
+
});
|
|
143532
|
+
await deliveryHttp.apply(ctx.config);
|
|
143533
|
+
if (typeof ctx.settings.onChange === "function") {
|
|
143534
|
+
ctx.settings.onChange(async (config2) => {
|
|
143535
|
+
setLanguage(parseReplyLanguage(config2[REPLY_LANGUAGE_FIELD]));
|
|
143536
|
+
connections.reconcile();
|
|
143537
|
+
await deliveryHttp.apply(config2);
|
|
143538
|
+
});
|
|
142869
143539
|
}
|
|
142870
143540
|
ctx.log.info("chat plugin active", { bots, connecting });
|
|
142871
143541
|
}
|