@ycodium-ai/plugin-im 0.2.3240 → 0.2.3250
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 +8 -6
- package/assets/ui.js +1 -1
- package/dist/index.js +695 -270
- package/locales/en.json +19 -1
- package/locales/zh-CN.json +19 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -126162,16 +126162,152 @@ import { definePlugin } from "@ycodium-ai/plugin-api";
|
|
|
126162
126162
|
// src/errors.ts
|
|
126163
126163
|
var describeError = (error) => error instanceof Error ? error.message : String(error);
|
|
126164
126164
|
|
|
126165
|
+
// src/inboundOutcome.ts
|
|
126166
|
+
var runInbound = async (core, binding, messageId, execute, lifecycle) => {
|
|
126167
|
+
let outcome;
|
|
126168
|
+
let failure2;
|
|
126169
|
+
let accepted = false;
|
|
126170
|
+
let completed = false;
|
|
126171
|
+
const completeFailure = async () => {
|
|
126172
|
+
try {
|
|
126173
|
+
await lifecycle?.complete();
|
|
126174
|
+
completed = true;
|
|
126175
|
+
} catch (error) {
|
|
126176
|
+
core.host.log.warn("chat could not complete a failed inbound message", {
|
|
126177
|
+
messageId,
|
|
126178
|
+
error: describeError(error)
|
|
126179
|
+
});
|
|
126180
|
+
}
|
|
126181
|
+
};
|
|
126182
|
+
const reportFailure = async () => {
|
|
126183
|
+
try {
|
|
126184
|
+
if (!await core.deliver(
|
|
126185
|
+
binding,
|
|
126186
|
+
core.t(completed ? "reply.inboundFailed" : "reply.inboundDeferred")
|
|
126187
|
+
))
|
|
126188
|
+
core.host.log.warn("chat could not deliver an inbound failure notice", { messageId });
|
|
126189
|
+
} catch (error) {
|
|
126190
|
+
core.host.log.warn("chat could not deliver an inbound failure notice", {
|
|
126191
|
+
messageId,
|
|
126192
|
+
error: describeError(error)
|
|
126193
|
+
});
|
|
126194
|
+
}
|
|
126195
|
+
};
|
|
126196
|
+
try {
|
|
126197
|
+
outcome = await execute(() => {
|
|
126198
|
+
accepted = true;
|
|
126199
|
+
lifecycle?.clearDeferred();
|
|
126200
|
+
});
|
|
126201
|
+
} catch (error) {
|
|
126202
|
+
failure2 = { error };
|
|
126203
|
+
if (!accepted) await completeFailure();
|
|
126204
|
+
} finally {
|
|
126205
|
+
if (!accepted) {
|
|
126206
|
+
if (outcome?.status === "deferred") lifecycle?.rememberDeferred();
|
|
126207
|
+
else lifecycle?.clearDeferred();
|
|
126208
|
+
}
|
|
126209
|
+
if (!accepted && (outcome === void 0 || outcome.status === "settled") || outcome?.status === "started" && outcome.claimsPlaceholder === false) {
|
|
126210
|
+
try {
|
|
126211
|
+
await core.adapterFor(binding.platform)?.inboundSettled?.(binding, messageId);
|
|
126212
|
+
} catch (error) {
|
|
126213
|
+
core.host.log.warn("chat could not settle inbound message", {
|
|
126214
|
+
messageId,
|
|
126215
|
+
error: describeError(error)
|
|
126216
|
+
});
|
|
126217
|
+
}
|
|
126218
|
+
}
|
|
126219
|
+
}
|
|
126220
|
+
if (failure2 !== void 0) {
|
|
126221
|
+
if (!accepted) await reportFailure();
|
|
126222
|
+
throw failure2.error;
|
|
126223
|
+
}
|
|
126224
|
+
if (outcome?.status === "deferred") outcome.resume?.();
|
|
126225
|
+
if (outcome?.status === "settled") {
|
|
126226
|
+
try {
|
|
126227
|
+
await outcome.respond?.();
|
|
126228
|
+
} catch (error) {
|
|
126229
|
+
core.host.log.warn("chat could not deliver an inbound response", {
|
|
126230
|
+
messageId,
|
|
126231
|
+
error: describeError(error)
|
|
126232
|
+
});
|
|
126233
|
+
throw error;
|
|
126234
|
+
}
|
|
126235
|
+
}
|
|
126236
|
+
};
|
|
126237
|
+
|
|
126165
126238
|
// src/acknowledgements.ts
|
|
126166
|
-
var
|
|
126239
|
+
var TYPING_KEEPALIVE_MS = 4e3;
|
|
126240
|
+
var makeAcknowledgements = (core, intervals) => {
|
|
126167
126241
|
const { host, adapterFor } = core;
|
|
126168
126242
|
const acknowledgements = /* @__PURE__ */ new Map();
|
|
126243
|
+
const deferred = /* @__PURE__ */ new Map();
|
|
126244
|
+
const typingKeepalive = /* @__PURE__ */ new Map();
|
|
126245
|
+
const messageKey = (identity2) => JSON.stringify([identity2.platform, identity2.rowId, identity2.chatId, identity2.messageId]);
|
|
126246
|
+
const noteTypingFailure = (error) => {
|
|
126247
|
+
host.log.info("chat could not show typing", { error: describeError(error) });
|
|
126248
|
+
};
|
|
126249
|
+
const clearDeferred = (identity2) => {
|
|
126250
|
+
deferred.delete(messageKey(identity2));
|
|
126251
|
+
};
|
|
126252
|
+
const stopTyping = (threadId) => {
|
|
126253
|
+
const lane = typingKeepalive.get(threadId);
|
|
126254
|
+
if (lane === void 0) return;
|
|
126255
|
+
typingKeepalive.delete(threadId);
|
|
126256
|
+
lane.cancel();
|
|
126257
|
+
};
|
|
126258
|
+
const stopTypingFor = (threadId) => {
|
|
126259
|
+
stopTyping(threadId);
|
|
126260
|
+
};
|
|
126261
|
+
const showTyping = (binding, threadId, sendTyping) => {
|
|
126262
|
+
const existing = typingKeepalive.get(threadId);
|
|
126263
|
+
if (existing !== void 0) {
|
|
126264
|
+
existing.retarget(binding, sendTyping);
|
|
126265
|
+
existing.send();
|
|
126266
|
+
return;
|
|
126267
|
+
}
|
|
126268
|
+
let pending = false;
|
|
126269
|
+
let stopped = false;
|
|
126270
|
+
let currentBinding = binding;
|
|
126271
|
+
let currentSend = sendTyping;
|
|
126272
|
+
const send = () => {
|
|
126273
|
+
if (stopped || pending) return;
|
|
126274
|
+
pending = true;
|
|
126275
|
+
let sending;
|
|
126276
|
+
try {
|
|
126277
|
+
sending = currentSend(currentBinding);
|
|
126278
|
+
} catch (error) {
|
|
126279
|
+
pending = false;
|
|
126280
|
+
noteTypingFailure(error);
|
|
126281
|
+
return;
|
|
126282
|
+
}
|
|
126283
|
+
void sending.catch(noteTypingFailure).finally(() => {
|
|
126284
|
+
pending = false;
|
|
126285
|
+
});
|
|
126286
|
+
};
|
|
126287
|
+
const dispose = intervals({
|
|
126288
|
+
name: `typing-keepalive:${threadId}`,
|
|
126289
|
+
everyMs: TYPING_KEEPALIVE_MS,
|
|
126290
|
+
handle: () => {
|
|
126291
|
+
send();
|
|
126292
|
+
}
|
|
126293
|
+
});
|
|
126294
|
+
typingKeepalive.set(threadId, {
|
|
126295
|
+
send,
|
|
126296
|
+
cancel: () => {
|
|
126297
|
+
stopped = true;
|
|
126298
|
+
dispose();
|
|
126299
|
+
},
|
|
126300
|
+
retarget: (nextBinding, nextSend) => {
|
|
126301
|
+
currentBinding = nextBinding;
|
|
126302
|
+
currentSend = nextSend;
|
|
126303
|
+
}
|
|
126304
|
+
});
|
|
126305
|
+
send();
|
|
126306
|
+
};
|
|
126169
126307
|
const markWorking = async (binding, threadId, messageId) => {
|
|
126170
126308
|
const adapter = adapterFor(binding.platform);
|
|
126171
126309
|
if (adapter?.sendTyping !== void 0) {
|
|
126172
|
-
|
|
126173
|
-
host.log.info("chat could not show typing", { error: describeError(error) });
|
|
126174
|
-
});
|
|
126310
|
+
showTyping(binding, threadId, adapter.sendTyping.bind(adapter));
|
|
126175
126311
|
}
|
|
126176
126312
|
if (adapter?.acknowledge === void 0) return;
|
|
126177
126313
|
try {
|
|
@@ -126186,6 +126322,7 @@ var makeAcknowledgements = (core) => {
|
|
|
126186
126322
|
}
|
|
126187
126323
|
};
|
|
126188
126324
|
const takeWorking = (binding, threadId, outcome) => {
|
|
126325
|
+
stopTyping(threadId);
|
|
126189
126326
|
const adapter = adapterFor(binding.platform);
|
|
126190
126327
|
const clear = adapter?.clearAcknowledge?.bind(adapter);
|
|
126191
126328
|
const pending = acknowledgements.get(threadId);
|
|
@@ -126204,7 +126341,26 @@ var makeAcknowledgements = (core) => {
|
|
|
126204
126341
|
};
|
|
126205
126342
|
};
|
|
126206
126343
|
const clearWorking = (binding, threadId, outcome) => takeWorking(binding, threadId, outcome)();
|
|
126207
|
-
|
|
126344
|
+
const rememberDeferred = (identity2, binding) => {
|
|
126345
|
+
const key2 = messageKey(identity2);
|
|
126346
|
+
if (!deferred.has(key2)) deferred.set(key2, { binding, identity: identity2 });
|
|
126347
|
+
};
|
|
126348
|
+
const stopDeferred = async (rowId) => {
|
|
126349
|
+
for (const [key2, { binding, identity: identity2 }] of [...deferred]) {
|
|
126350
|
+
if (rowId !== void 0 && identity2.rowId !== rowId) continue;
|
|
126351
|
+
if (!deferred.delete(key2)) continue;
|
|
126352
|
+
await runInbound(core, binding, identity2.messageId, async () => ({ status: "settled" }));
|
|
126353
|
+
}
|
|
126354
|
+
};
|
|
126355
|
+
return {
|
|
126356
|
+
markWorking,
|
|
126357
|
+
takeWorking,
|
|
126358
|
+
clearWorking,
|
|
126359
|
+
clearDeferred,
|
|
126360
|
+
rememberDeferred,
|
|
126361
|
+
stopDeferred,
|
|
126362
|
+
stopTypingFor
|
|
126363
|
+
};
|
|
126208
126364
|
};
|
|
126209
126365
|
|
|
126210
126366
|
// src/botConfig.ts
|
|
@@ -128085,7 +128241,8 @@ var makeChatSetup = (core, deps) => {
|
|
|
128085
128241
|
await deliver(binding, t("repo.done", { title: target2.title }));
|
|
128086
128242
|
const pending = pendingMessages.get(chatKey);
|
|
128087
128243
|
pendingMessages.forget((key2) => key2 === chatKey);
|
|
128088
|
-
if (pending !== void 0)
|
|
128244
|
+
if (pending !== void 0)
|
|
128245
|
+
deps.enqueueForChat(chatKey, () => deps.resumeMessage(binding, pending), true);
|
|
128089
128246
|
};
|
|
128090
128247
|
const handleRepo = async (binding, arg) => {
|
|
128091
128248
|
if (arg === "") {
|
|
@@ -128139,7 +128296,7 @@ var makeChatSetup = (core, deps) => {
|
|
|
128139
128296
|
const only = rows.length === 1 ? rows[0] : void 0;
|
|
128140
128297
|
return only === void 0 ? { kind: "list" } : { kind: "auto", projectId: only.projectId };
|
|
128141
128298
|
};
|
|
128142
|
-
const executeProjectDecision = async (binding, message, decision) => {
|
|
128299
|
+
const executeProjectDecision = async (binding, message, decision, deferReply) => {
|
|
128143
128300
|
if (decision.kind === "loadFailed" || decision.kind === "notFound") {
|
|
128144
128301
|
await deliver(
|
|
128145
128302
|
binding,
|
|
@@ -128148,8 +128305,18 @@ var makeChatSetup = (core, deps) => {
|
|
|
128148
128305
|
return false;
|
|
128149
128306
|
}
|
|
128150
128307
|
const chatKey = chatKeyOf(binding);
|
|
128151
|
-
const
|
|
128152
|
-
|
|
128308
|
+
const send = async (text3) => {
|
|
128309
|
+
const reply = async () => {
|
|
128310
|
+
await deliver(binding, text3);
|
|
128311
|
+
};
|
|
128312
|
+
if (deferReply === void 0) await reply();
|
|
128313
|
+
else deferReply(reply);
|
|
128314
|
+
};
|
|
128315
|
+
const rows = await readProjectRows(chatKey);
|
|
128316
|
+
if (rows === null) {
|
|
128317
|
+
await send(t("panel.loadFailed"));
|
|
128318
|
+
return false;
|
|
128319
|
+
}
|
|
128153
128320
|
if (decision.kind === "pick") {
|
|
128154
128321
|
await selectProject(binding, decision.projectId, rows);
|
|
128155
128322
|
return false;
|
|
@@ -128157,12 +128324,12 @@ var makeChatSetup = (core, deps) => {
|
|
|
128157
128324
|
if (decision.kind === "auto") {
|
|
128158
128325
|
const target2 = rows.find((row) => row.projectId === decision.projectId);
|
|
128159
128326
|
if (target2 === void 0) {
|
|
128160
|
-
await
|
|
128327
|
+
await send(t("repo.gone"));
|
|
128161
128328
|
return false;
|
|
128162
128329
|
}
|
|
128163
128330
|
commit("chat-updated", { chatKey, projectId: target2.projectId });
|
|
128164
128331
|
pendingMessages.forget((key2) => key2 === chatKey);
|
|
128165
|
-
await
|
|
128332
|
+
await send(t("repo.autoSelected", { title: target2.title }));
|
|
128166
128333
|
return true;
|
|
128167
128334
|
}
|
|
128168
128335
|
pendingMessages.set(chatKey, message);
|
|
@@ -133373,6 +133540,7 @@ var Uint8Array2 = /* @__PURE__ */ instanceOf(globalThis.Uint8Array, {
|
|
|
133373
133540
|
});
|
|
133374
133541
|
|
|
133375
133542
|
// src/chatCommand.ts
|
|
133543
|
+
var HISTORY_COUNTS = { defaultCount: 3, maxCount: 5 };
|
|
133376
133544
|
var SimpleChatCommand = Struct({
|
|
133377
133545
|
kind: Literals([
|
|
133378
133546
|
"stop",
|
|
@@ -133390,6 +133558,7 @@ var ParsedChatCommand = Union2([
|
|
|
133390
133558
|
SimpleChatCommand,
|
|
133391
133559
|
Struct({ kind: Literal2("sessions"), arg: optionalKey2(String4) }),
|
|
133392
133560
|
Struct({ kind: Literals(["resume", "model", "repo"]), arg: String4 }),
|
|
133561
|
+
Struct({ kind: Literal2("history"), count: NullOr(Number5) }),
|
|
133393
133562
|
Struct({
|
|
133394
133563
|
kind: Literal2("preset"),
|
|
133395
133564
|
arg: String4,
|
|
@@ -133441,6 +133610,16 @@ var parseChatCommand = (input) => {
|
|
|
133441
133610
|
if (sessions !== void 0) {
|
|
133442
133611
|
return sessions === "" ? { kind: "sessions" } : { kind: "sessions", arg: sessions };
|
|
133443
133612
|
}
|
|
133613
|
+
const history = commandArgument(
|
|
133614
|
+
trimmed,
|
|
133615
|
+
input.chinese,
|
|
133616
|
+
/^\/history(?:\s+([\s\S]*))?$/i,
|
|
133617
|
+
/^会话历史(?:\s+([\s\S]*))?$/
|
|
133618
|
+
);
|
|
133619
|
+
if (history !== void 0) {
|
|
133620
|
+
const count = history === "" ? HISTORY_COUNTS.defaultCount : /^\d+$/.test(history) ? Math.min(Number(history), HISTORY_COUNTS.maxCount) : 0;
|
|
133621
|
+
return { kind: "history", count: count > 0 ? count : null };
|
|
133622
|
+
}
|
|
133444
133623
|
const resume = resumeArgument(input.text, input.chinese);
|
|
133445
133624
|
if (resume !== void 0) {
|
|
133446
133625
|
return resume === "" ? { kind: "sessions" } : { kind: "resume", arg: resume };
|
|
@@ -133480,6 +133659,7 @@ var helpText = (t, options = {}) => [
|
|
|
133480
133659
|
t("help.new"),
|
|
133481
133660
|
t("help.sessions"),
|
|
133482
133661
|
t("help.resume"),
|
|
133662
|
+
t("help.history", HISTORY_COUNTS),
|
|
133483
133663
|
t("help.syncNote"),
|
|
133484
133664
|
t("help.model"),
|
|
133485
133665
|
t("help.preset"),
|
|
@@ -133492,6 +133672,175 @@ var helpText = (t, options = {}) => [
|
|
|
133492
133672
|
...options.panel === true ? ["", t("help.panel")] : []
|
|
133493
133673
|
].join("\n");
|
|
133494
133674
|
|
|
133675
|
+
// src/deadline.ts
|
|
133676
|
+
var withDeadline = async (timeoutMs, load) => {
|
|
133677
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
133678
|
+
let onAbort = () => {
|
|
133679
|
+
};
|
|
133680
|
+
const aborted = new Promise((_, reject) => {
|
|
133681
|
+
onAbort = () => reject(signal.reason);
|
|
133682
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
133683
|
+
});
|
|
133684
|
+
try {
|
|
133685
|
+
return await Promise.race([load(signal), aborted]);
|
|
133686
|
+
} finally {
|
|
133687
|
+
signal.removeEventListener("abort", onAbort);
|
|
133688
|
+
}
|
|
133689
|
+
};
|
|
133690
|
+
|
|
133691
|
+
// src/threadMessages.ts
|
|
133692
|
+
import {
|
|
133693
|
+
isThreadNotFound,
|
|
133694
|
+
threadMessagesNewestFirst
|
|
133695
|
+
} from "@ycodium-ai/plugin-api";
|
|
133696
|
+
var PAGE_SIZE = 20;
|
|
133697
|
+
async function* newestFirst(threads, threadId) {
|
|
133698
|
+
try {
|
|
133699
|
+
yield* threadMessagesNewestFirst(threads, threadId, { pageSize: PAGE_SIZE });
|
|
133700
|
+
} catch (error) {
|
|
133701
|
+
if (!isThreadNotFound(error)) throw error;
|
|
133702
|
+
}
|
|
133703
|
+
}
|
|
133704
|
+
async function attachmentsOf(threads, threadId, message) {
|
|
133705
|
+
const collected = [...message.attachments ?? []];
|
|
133706
|
+
const total = message.attachmentsTotal ?? collected.length;
|
|
133707
|
+
while (collected.length < total) {
|
|
133708
|
+
let page;
|
|
133709
|
+
try {
|
|
133710
|
+
page = await threads.messages.list({
|
|
133711
|
+
threadId,
|
|
133712
|
+
messageId: message.id,
|
|
133713
|
+
attachmentOffset: collected.length,
|
|
133714
|
+
textLimit: 2
|
|
133715
|
+
});
|
|
133716
|
+
} catch (error) {
|
|
133717
|
+
if (isThreadNotFound(error)) break;
|
|
133718
|
+
throw error;
|
|
133719
|
+
}
|
|
133720
|
+
const more = page.items[0]?.attachments ?? [];
|
|
133721
|
+
if (more.length === 0) break;
|
|
133722
|
+
collected.push(...more);
|
|
133723
|
+
}
|
|
133724
|
+
return collected;
|
|
133725
|
+
}
|
|
133726
|
+
async function latestMessage(threads, threadId, accept) {
|
|
133727
|
+
for await (const message of newestFirst(threads, threadId)) {
|
|
133728
|
+
if (accept(message)) return message;
|
|
133729
|
+
}
|
|
133730
|
+
return void 0;
|
|
133731
|
+
}
|
|
133732
|
+
async function recentMessages(threads, threadId, count, accept) {
|
|
133733
|
+
const collected = [];
|
|
133734
|
+
for await (const message of newestFirst(threads, threadId)) {
|
|
133735
|
+
if (!accept(message)) continue;
|
|
133736
|
+
collected.push(message);
|
|
133737
|
+
if (collected.length >= count) break;
|
|
133738
|
+
}
|
|
133739
|
+
return collected.toReversed();
|
|
133740
|
+
}
|
|
133741
|
+
async function messagesAfterLastUser(threads, threadId) {
|
|
133742
|
+
const after = [];
|
|
133743
|
+
for await (const message of newestFirst(threads, threadId)) {
|
|
133744
|
+
if (message.role === "user") break;
|
|
133745
|
+
after.push(message);
|
|
133746
|
+
}
|
|
133747
|
+
return after.toReversed();
|
|
133748
|
+
}
|
|
133749
|
+
|
|
133750
|
+
// src/historyCommand.ts
|
|
133751
|
+
var READ_TIMEOUT_MS = 1e4;
|
|
133752
|
+
var MAX_PAGES = 3;
|
|
133753
|
+
var TEXT_LIMIT = 1e3;
|
|
133754
|
+
var makeHistoryCommand = (core) => {
|
|
133755
|
+
const { host, t, deliver } = core;
|
|
133756
|
+
return async (binding, command, chatKind) => {
|
|
133757
|
+
if (chatKind !== "private") {
|
|
133758
|
+
await deliver(binding, t("history.directOnly"));
|
|
133759
|
+
return;
|
|
133760
|
+
}
|
|
133761
|
+
const count = command.count;
|
|
133762
|
+
if (count === null) {
|
|
133763
|
+
await deliver(binding, t("history.usage", HISTORY_COUNTS));
|
|
133764
|
+
return;
|
|
133765
|
+
}
|
|
133766
|
+
const chatKey = chatKeyOf(binding);
|
|
133767
|
+
const threadId = chatOf(core.state, chatKey).threadId;
|
|
133768
|
+
if (threadId === null) {
|
|
133769
|
+
await deliver(binding, t("history.noSession"));
|
|
133770
|
+
return;
|
|
133771
|
+
}
|
|
133772
|
+
const switched = () => {
|
|
133773
|
+
if (chatOf(core.state, chatKey).threadId === threadId) return false;
|
|
133774
|
+
host.log.info("chat cancelled a history read after the session changed", { threadId });
|
|
133775
|
+
return true;
|
|
133776
|
+
};
|
|
133777
|
+
const adapter = core.adapterFor(binding.platform);
|
|
133778
|
+
if (adapter?.sendTyping !== void 0) {
|
|
133779
|
+
void adapter.sendTyping(binding).catch(() => {
|
|
133780
|
+
host.log.info("chat could not show history typing", { threadId });
|
|
133781
|
+
});
|
|
133782
|
+
}
|
|
133783
|
+
let text3;
|
|
133784
|
+
try {
|
|
133785
|
+
text3 = await withDeadline(READ_TIMEOUT_MS, async (signal) => {
|
|
133786
|
+
const threads = {
|
|
133787
|
+
messages: {
|
|
133788
|
+
list: async (input) => {
|
|
133789
|
+
signal.throwIfAborted();
|
|
133790
|
+
const page = await host.threads.messages.list({
|
|
133791
|
+
...input,
|
|
133792
|
+
textLimit: input.textLimit ?? TEXT_LIMIT
|
|
133793
|
+
});
|
|
133794
|
+
signal.throwIfAborted();
|
|
133795
|
+
return page;
|
|
133796
|
+
}
|
|
133797
|
+
}
|
|
133798
|
+
};
|
|
133799
|
+
let pages = 0;
|
|
133800
|
+
let reachedEnd = false;
|
|
133801
|
+
const bounded = {
|
|
133802
|
+
messages: {
|
|
133803
|
+
list: async (input) => {
|
|
133804
|
+
const page = await threads.messages.list(input);
|
|
133805
|
+
pages += 1;
|
|
133806
|
+
reachedEnd = page.nextCursor === null;
|
|
133807
|
+
return { ...page, nextCursor: pages >= MAX_PAGES ? null : page.nextCursor };
|
|
133808
|
+
}
|
|
133809
|
+
}
|
|
133810
|
+
};
|
|
133811
|
+
const messages = await recentMessages(
|
|
133812
|
+
bounded,
|
|
133813
|
+
threadId,
|
|
133814
|
+
count,
|
|
133815
|
+
(message) => message.role === "user" || message.role === "assistant" && !message.streaming
|
|
133816
|
+
);
|
|
133817
|
+
if (messages.length === 0) return t(reachedEnd ? "history.empty" : "history.noneRecent");
|
|
133818
|
+
const entries = [];
|
|
133819
|
+
for (const message of messages) {
|
|
133820
|
+
const attachments = await attachmentsOf(threads, threadId, message);
|
|
133821
|
+
const body = [
|
|
133822
|
+
message.text.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/gu, "").trim(),
|
|
133823
|
+
...message.textWindow?.nextOffset != null ? [t("history.truncated")] : [],
|
|
133824
|
+
...attachments.map(
|
|
133825
|
+
(attachment) => t(attachment.type === "image" ? "history.image" : "history.file")
|
|
133826
|
+
)
|
|
133827
|
+
].filter(Boolean).join("\n") || t("history.noText");
|
|
133828
|
+
const role = t(message.role === "user" ? "history.user" : "history.assistant");
|
|
133829
|
+
entries.push(`${entries.length + 1}. ${role}
|
|
133830
|
+
${body}`);
|
|
133831
|
+
}
|
|
133832
|
+
return [t("history.title", { count: messages.length }), ...entries].join("\n\n");
|
|
133833
|
+
});
|
|
133834
|
+
} catch {
|
|
133835
|
+
if (switched()) return;
|
|
133836
|
+
host.log.warn("chat could not read history", { threadId });
|
|
133837
|
+
text3 = t("history.failed");
|
|
133838
|
+
}
|
|
133839
|
+
if (switched()) return;
|
|
133840
|
+
await deliver(binding, text3);
|
|
133841
|
+
};
|
|
133842
|
+
};
|
|
133843
|
+
|
|
133495
133844
|
// src/commands.ts
|
|
133496
133845
|
var NEEDS_PROJECT_COMMANDS = /* @__PURE__ */ new Set(["sessions", "resume", "selectTeam", "selectThread"]);
|
|
133497
133846
|
var makeCommands = (core, deps) => {
|
|
@@ -133501,8 +133850,9 @@ var makeCommands = (core, deps) => {
|
|
|
133501
133850
|
const { showSessions, resumeSession } = deps.sessions;
|
|
133502
133851
|
const { handleModel, handlePlan } = deps.modelPlan;
|
|
133503
133852
|
const { openPanel } = deps;
|
|
133853
|
+
const handleHistory = makeHistoryCommand(core);
|
|
133504
133854
|
const targetOf = (binding) => chatOf(core.state, chatKeyOf(binding)).target;
|
|
133505
|
-
const executeCommand = async (binding, command, senderId = null) => {
|
|
133855
|
+
const executeCommand = async (binding, command, senderId = null, chatKind = void 0) => {
|
|
133506
133856
|
const chatKey = chatKeyOf(binding);
|
|
133507
133857
|
host.log.info("chat handled a command", {
|
|
133508
133858
|
bot: binding.displayName,
|
|
@@ -133553,6 +133903,9 @@ var makeCommands = (core, deps) => {
|
|
|
133553
133903
|
case "sessions":
|
|
133554
133904
|
await showSessions(binding, command.arg);
|
|
133555
133905
|
return;
|
|
133906
|
+
case "history":
|
|
133907
|
+
await handleHistory(binding, command, chatKind);
|
|
133908
|
+
return;
|
|
133556
133909
|
case "resume":
|
|
133557
133910
|
await resumeSession(binding, command.arg);
|
|
133558
133911
|
return;
|
|
@@ -135185,56 +135538,6 @@ var deliveryFailure = (core, binding, threadId, turnId) => async (error) => {
|
|
|
135185
135538
|
}
|
|
135186
135539
|
};
|
|
135187
135540
|
|
|
135188
|
-
// src/threadMessages.ts
|
|
135189
|
-
import {
|
|
135190
|
-
isThreadNotFound,
|
|
135191
|
-
threadMessagesNewestFirst
|
|
135192
|
-
} from "@ycodium-ai/plugin-api";
|
|
135193
|
-
var PAGE_SIZE = 20;
|
|
135194
|
-
async function* newestFirst(threads, threadId) {
|
|
135195
|
-
try {
|
|
135196
|
-
yield* threadMessagesNewestFirst(threads, threadId, { pageSize: PAGE_SIZE });
|
|
135197
|
-
} catch (error) {
|
|
135198
|
-
if (!isThreadNotFound(error)) throw error;
|
|
135199
|
-
}
|
|
135200
|
-
}
|
|
135201
|
-
async function attachmentsOf(threads, threadId, message) {
|
|
135202
|
-
const collected = [...message.attachments ?? []];
|
|
135203
|
-
const total = message.attachmentsTotal ?? collected.length;
|
|
135204
|
-
while (collected.length < total) {
|
|
135205
|
-
let page;
|
|
135206
|
-
try {
|
|
135207
|
-
page = await threads.messages.list({
|
|
135208
|
-
threadId,
|
|
135209
|
-
messageId: message.id,
|
|
135210
|
-
attachmentOffset: collected.length,
|
|
135211
|
-
textLimit: 2
|
|
135212
|
-
});
|
|
135213
|
-
} catch (error) {
|
|
135214
|
-
if (isThreadNotFound(error)) break;
|
|
135215
|
-
throw error;
|
|
135216
|
-
}
|
|
135217
|
-
const more = page.items[0]?.attachments ?? [];
|
|
135218
|
-
if (more.length === 0) break;
|
|
135219
|
-
collected.push(...more);
|
|
135220
|
-
}
|
|
135221
|
-
return collected;
|
|
135222
|
-
}
|
|
135223
|
-
async function latestMessage(threads, threadId, accept) {
|
|
135224
|
-
for await (const message of newestFirst(threads, threadId)) {
|
|
135225
|
-
if (accept(message)) return message;
|
|
135226
|
-
}
|
|
135227
|
-
return void 0;
|
|
135228
|
-
}
|
|
135229
|
-
async function messagesAfterLastUser(threads, threadId) {
|
|
135230
|
-
const after = [];
|
|
135231
|
-
for await (const message of newestFirst(threads, threadId)) {
|
|
135232
|
-
if (message.role === "user") break;
|
|
135233
|
-
after.push(message);
|
|
135234
|
-
}
|
|
135235
|
-
return after.toReversed();
|
|
135236
|
-
}
|
|
135237
|
-
|
|
135238
135541
|
// src/conclusionDelivery.ts
|
|
135239
135542
|
var ALWAYS_OWED = () => true;
|
|
135240
135543
|
var makeConclusionDelivery = (core, anchors) => {
|
|
@@ -135604,16 +135907,6 @@ var workForMessage = (message) => ({
|
|
|
135604
135907
|
});
|
|
135605
135908
|
|
|
135606
135909
|
// src/inboundRoutes.ts
|
|
135607
|
-
var settleInbound = async (core, binding, messageId) => {
|
|
135608
|
-
try {
|
|
135609
|
-
await core.adapterFor(binding.platform)?.inboundSettled?.(binding, messageId);
|
|
135610
|
-
} catch (error) {
|
|
135611
|
-
core.host.log.warn("chat could not settle inbound message", {
|
|
135612
|
-
messageId,
|
|
135613
|
-
error: describeError(error)
|
|
135614
|
-
});
|
|
135615
|
-
}
|
|
135616
|
-
};
|
|
135617
135910
|
var executeInboundRoute = async (core, actions, input) => {
|
|
135618
135911
|
const { current, message, route, work } = input;
|
|
135619
135912
|
const target2 = input.target;
|
|
@@ -135623,82 +135916,113 @@ var executeInboundRoute = async (core, actions, input) => {
|
|
|
135623
135916
|
switch (route.kind) {
|
|
135624
135917
|
case "command":
|
|
135625
135918
|
await complete();
|
|
135626
|
-
await actions.commands.executeCommand(
|
|
135627
|
-
|
|
135628
|
-
|
|
135629
|
-
|
|
135630
|
-
|
|
135631
|
-
|
|
135632
|
-
|
|
135919
|
+
await actions.commands.executeCommand(
|
|
135920
|
+
target2,
|
|
135921
|
+
route.command,
|
|
135922
|
+
message.senderId,
|
|
135923
|
+
message.chatKind
|
|
135924
|
+
);
|
|
135925
|
+
return { status: "settled" };
|
|
135926
|
+
case "project": {
|
|
135927
|
+
if (route.decision.kind !== "auto") {
|
|
135928
|
+
await complete();
|
|
135929
|
+
await actions.chatSetup.executeProjectDecision(target2, message, route.decision);
|
|
135930
|
+
return { status: "settled" };
|
|
135931
|
+
}
|
|
135932
|
+
const replies = [];
|
|
135933
|
+
const respond = async () => {
|
|
135934
|
+
for (const reply of replies) await reply();
|
|
135935
|
+
};
|
|
135936
|
+
if (await actions.chatSetup.executeProjectDecision(
|
|
135937
|
+
target2,
|
|
135938
|
+
message,
|
|
135939
|
+
route.decision,
|
|
135940
|
+
(reply) => replies.push(reply)
|
|
135941
|
+
)) {
|
|
135942
|
+
const outcome = await actions.continueMessage({
|
|
135633
135943
|
...core.bindingOf(current, message.chatId),
|
|
135634
135944
|
reply: target2.reply
|
|
135635
135945
|
});
|
|
135636
|
-
|
|
135637
|
-
|
|
135638
|
-
|
|
135946
|
+
if (outcome.status === "settled")
|
|
135947
|
+
return {
|
|
135948
|
+
status: "settled",
|
|
135949
|
+
respond: async () => {
|
|
135950
|
+
await respond();
|
|
135951
|
+
await outcome.respond?.();
|
|
135952
|
+
}
|
|
135953
|
+
};
|
|
135954
|
+
await respond();
|
|
135955
|
+
return outcome;
|
|
135639
135956
|
}
|
|
135640
|
-
|
|
135957
|
+
await complete();
|
|
135958
|
+
return { status: "settled", respond };
|
|
135959
|
+
}
|
|
135641
135960
|
case "question":
|
|
135642
135961
|
await complete();
|
|
135643
135962
|
await actions.interactions.questionFlow.answerText(route.answer);
|
|
135644
|
-
|
|
135645
|
-
return;
|
|
135963
|
+
return { status: "settled" };
|
|
135646
135964
|
case "approval":
|
|
135647
135965
|
await complete();
|
|
135648
135966
|
await actions.approvals.answerByToken(route.token);
|
|
135649
|
-
|
|
135650
|
-
return;
|
|
135967
|
+
return { status: "settled" };
|
|
135651
135968
|
case "unavailable":
|
|
135652
135969
|
await complete();
|
|
135653
|
-
|
|
135654
|
-
|
|
135655
|
-
|
|
135656
|
-
await actions.turns.receiveAttachmentsOnly(target2, message, complete);
|
|
135970
|
+
return { status: "settled" };
|
|
135971
|
+
case "attachments": {
|
|
135972
|
+
const outcome = await actions.turns.receiveAttachmentsOnly(target2, message, complete);
|
|
135657
135973
|
await complete();
|
|
135658
|
-
|
|
135659
|
-
|
|
135974
|
+
return outcome;
|
|
135975
|
+
}
|
|
135660
135976
|
case "team": {
|
|
135661
135977
|
const routed = { ...target2, chatId: route.chatId, projectId: route.projectId };
|
|
135662
|
-
|
|
135663
|
-
await core.deliver(routed, core.t("reply.attachmentsNoTeam"));
|
|
135664
|
-
const leadThreadId = await actions.teams.startTeamGoal(
|
|
135978
|
+
const outcome = await actions.teams.startTeamGoal(
|
|
135665
135979
|
routed,
|
|
135666
135980
|
message,
|
|
135667
|
-
actions.acceptedWork(routed, message, work)
|
|
135981
|
+
actions.acceptedWork(routed, message, work, input.onAccepted)
|
|
135668
135982
|
);
|
|
135669
|
-
if (
|
|
135983
|
+
if (outcome.status === "settled") {
|
|
135670
135984
|
await complete();
|
|
135671
|
-
|
|
135985
|
+
return {
|
|
135986
|
+
status: "settled",
|
|
135987
|
+
respond: async () => {
|
|
135988
|
+
if (message.resources.length > 0)
|
|
135989
|
+
await core.deliver(routed, core.t("reply.attachmentsNoTeam"));
|
|
135990
|
+
await outcome.respond?.();
|
|
135991
|
+
}
|
|
135992
|
+
};
|
|
135672
135993
|
}
|
|
135673
|
-
|
|
135994
|
+
if (message.resources.length > 0)
|
|
135995
|
+
await core.deliver(routed, core.t("reply.attachmentsNoTeam"));
|
|
135996
|
+
return outcome;
|
|
135674
135997
|
}
|
|
135675
135998
|
case "turn":
|
|
135676
|
-
|
|
135999
|
+
return actions.openTurn(
|
|
135677
136000
|
{ ...target2, chatId: route.chatId, projectId: route.projectId },
|
|
135678
136001
|
message,
|
|
135679
|
-
work
|
|
136002
|
+
work,
|
|
136003
|
+
input.onAccepted
|
|
135680
136004
|
);
|
|
135681
|
-
return;
|
|
135682
136005
|
case "handoff": {
|
|
135683
|
-
const executeHandoff = async () => {
|
|
136006
|
+
const executeHandoff = async (onAccepted) => {
|
|
135684
136007
|
actions.inheritFromParent(current, route.chatId, message.chatId);
|
|
135685
136008
|
const child = {
|
|
135686
136009
|
...core.bindingOf(current, route.chatId),
|
|
135687
136010
|
projectId: route.projectId,
|
|
135688
136011
|
reply: target2.reply
|
|
135689
136012
|
};
|
|
135690
|
-
|
|
136013
|
+
return actions.openTurn(child, message, work, onAccepted);
|
|
135691
136014
|
};
|
|
135692
136015
|
if (input.queueChatId === route.chatId) {
|
|
135693
|
-
|
|
135694
|
-
return;
|
|
136016
|
+
return executeHandoff(input.onAccepted);
|
|
135695
136017
|
}
|
|
135696
|
-
|
|
135697
|
-
|
|
135698
|
-
|
|
135699
|
-
|
|
135700
|
-
|
|
135701
|
-
|
|
136018
|
+
return {
|
|
136019
|
+
status: "deferred",
|
|
136020
|
+
resume: () => actions.enqueueForChat(
|
|
136021
|
+
chatKeyOf({ rowId: current.rowId, chatId: route.chatId }),
|
|
136022
|
+
() => actions.run(executeHandoff),
|
|
136023
|
+
true
|
|
136024
|
+
)
|
|
136025
|
+
};
|
|
135702
136026
|
}
|
|
135703
136027
|
}
|
|
135704
136028
|
};
|
|
@@ -135875,16 +136199,14 @@ var makeInbound = (core, deps) => {
|
|
|
135875
136199
|
}));
|
|
135876
136200
|
return true;
|
|
135877
136201
|
};
|
|
135878
|
-
const turnAwayStranger = (target2, sender) => {
|
|
136202
|
+
const turnAwayStranger = async (target2, sender) => {
|
|
135879
136203
|
host.log.warn("chat ignored a message from someone not on the allow list", {
|
|
135880
136204
|
bot: target2.displayName,
|
|
135881
136205
|
sender
|
|
135882
136206
|
});
|
|
135883
136207
|
if (sender === null) return;
|
|
135884
136208
|
if (!notAllowedReplyCooldown.tryAcquire(`${target2.rowId}:${sender}`)) return;
|
|
135885
|
-
|
|
135886
|
-
await deliver(target2, t("reply.notAllowedYet", { id: sender }));
|
|
135887
|
-
});
|
|
136209
|
+
await deliver(target2, t("reply.notAllowedYet", { id: sender }));
|
|
135888
136210
|
};
|
|
135889
136211
|
const currentBot = (rowId) => bots().find((candidate) => candidate.rowId === rowId);
|
|
135890
136212
|
const inheritFromParent = (bot, chatId, parentChatId) => {
|
|
@@ -135911,24 +136233,24 @@ var makeInbound = (core, deps) => {
|
|
|
135911
136233
|
if (known === void 0) noteChatAlias(bot, message.chatAlias, message.chatId);
|
|
135912
136234
|
return known === void 0 || known === message.chatId ? message : { ...message, chatId: known };
|
|
135913
136235
|
};
|
|
135914
|
-
const acceptedWork = (speaker, message, work
|
|
135915
|
-
|
|
135916
|
-
|
|
135917
|
-
|
|
135918
|
-
|
|
135919
|
-
|
|
135920
|
-
|
|
135921
|
-
|
|
135922
|
-
|
|
135923
|
-
|
|
135924
|
-
|
|
135925
|
-
|
|
135926
|
-
|
|
135927
|
-
|
|
135928
|
-
|
|
136236
|
+
const acceptedWork = (speaker, message, work, onAccepted) => Object.assign(
|
|
136237
|
+
async (threadId, register) => {
|
|
136238
|
+
await markWorking(speaker, threadId, message.messageId);
|
|
136239
|
+
await register?.();
|
|
136240
|
+
if (work !== void 0) await inboundState.complete(speaker.rowId, work.key);
|
|
136241
|
+
},
|
|
136242
|
+
{ onAccepted }
|
|
136243
|
+
);
|
|
136244
|
+
const openTurn = (speaker, message, work, onAccepted) => startTurn(
|
|
136245
|
+
speaker,
|
|
136246
|
+
message,
|
|
136247
|
+
acceptedWork(speaker, message, work, onAccepted),
|
|
136248
|
+
work === void 0 ? void 0 : processingFor(inboundState, speaker.rowId, work, () => {
|
|
136249
|
+
replay.enqueue(speaker.rowId, work.key, Promise.resolve(true));
|
|
136250
|
+
})
|
|
136251
|
+
);
|
|
135929
136252
|
const resumeMessage = async (current, message, work, queueChatId = message.chatId) => {
|
|
135930
|
-
|
|
135931
|
-
const target2 = {
|
|
136253
|
+
let target2 = {
|
|
135932
136254
|
...bindingOf2(current, message.chatId),
|
|
135933
136255
|
reply: anchorOfMessage(adapterFor(current.platform), message)
|
|
135934
136256
|
};
|
|
@@ -135939,14 +136261,24 @@ var makeInbound = (core, deps) => {
|
|
|
135939
136261
|
const complete = async () => {
|
|
135940
136262
|
if (work !== void 0) await inboundState.complete(current.rowId, work.key);
|
|
135941
136263
|
};
|
|
136264
|
+
const identity2 = {
|
|
136265
|
+
platform: current.platform,
|
|
136266
|
+
rowId: current.rowId,
|
|
136267
|
+
chatId: message.chatId,
|
|
136268
|
+
messageId: message.messageId
|
|
136269
|
+
};
|
|
136270
|
+
const run2 = (execute2) => runInbound(core, target2, message.messageId, execute2, {
|
|
136271
|
+
rememberDeferred: () => deps.acknowledgements.rememberDeferred(identity2, target2),
|
|
136272
|
+
clearDeferred: () => deps.acknowledgements.clearDeferred(identity2),
|
|
136273
|
+
complete
|
|
136274
|
+
});
|
|
135942
136275
|
const continueMessage = async (target3) => {
|
|
135943
136276
|
const boundThread = chatOf(core.state, chatKey).threadId;
|
|
135944
136277
|
const answer = boundThread === null ? void 0 : questionFlow.textAnswer(chatKey, boundThread, message.text);
|
|
135945
136278
|
if (answer !== void 0) {
|
|
135946
136279
|
const route2 = { kind: "question", answer };
|
|
135947
136280
|
await saveRoute(route2);
|
|
135948
|
-
|
|
135949
|
-
return;
|
|
136281
|
+
return execute(route2, target3);
|
|
135950
136282
|
}
|
|
135951
136283
|
const project = await projectOrNull(host.projects, target3.projectId);
|
|
135952
136284
|
if (project === null || project.archivedAt != null) {
|
|
@@ -135958,14 +136290,16 @@ var makeInbound = (core, deps) => {
|
|
|
135958
136290
|
projectId: target3.projectId
|
|
135959
136291
|
});
|
|
135960
136292
|
}
|
|
135961
|
-
|
|
135962
|
-
|
|
135963
|
-
|
|
135964
|
-
|
|
135965
|
-
|
|
135966
|
-
|
|
135967
|
-
|
|
135968
|
-
|
|
136293
|
+
return {
|
|
136294
|
+
status: "settled",
|
|
136295
|
+
respond: async () => {
|
|
136296
|
+
if (archivedReplyCooldown.tryAcquire(chatKey))
|
|
136297
|
+
await deliver(
|
|
136298
|
+
target3,
|
|
136299
|
+
project === null ? t("reply.projectMissing") : t("reply.projectArchived", { title: project.title })
|
|
136300
|
+
);
|
|
136301
|
+
}
|
|
136302
|
+
};
|
|
135969
136303
|
}
|
|
135970
136304
|
const routed = targetOf(target3);
|
|
135971
136305
|
const attachmentsOnly = message.text.trim() === "" && message.resources.length > 0;
|
|
@@ -135973,20 +136307,21 @@ var makeInbound = (core, deps) => {
|
|
|
135973
136307
|
if (attachmentsOnly) {
|
|
135974
136308
|
await saveRoute({ kind: "unavailable" });
|
|
135975
136309
|
await complete();
|
|
135976
|
-
|
|
135977
|
-
|
|
135978
|
-
|
|
136310
|
+
return {
|
|
136311
|
+
status: "settled",
|
|
136312
|
+
respond: async () => {
|
|
136313
|
+
await deliver(target3, t("reply.attachmentsNoTeam"));
|
|
136314
|
+
}
|
|
136315
|
+
};
|
|
135979
136316
|
}
|
|
135980
136317
|
const route2 = { kind: "team", chatId: target3.chatId, projectId: target3.projectId };
|
|
135981
136318
|
await saveRoute(route2);
|
|
135982
|
-
|
|
135983
|
-
return;
|
|
136319
|
+
return execute(route2, target3);
|
|
135984
136320
|
}
|
|
135985
136321
|
if (attachmentsOnly) {
|
|
135986
136322
|
const route2 = { kind: "attachments" };
|
|
135987
136323
|
await saveRoute(route2);
|
|
135988
|
-
|
|
135989
|
-
return;
|
|
136324
|
+
return execute(route2, target3);
|
|
135990
136325
|
}
|
|
135991
136326
|
const branchChatId = hasWaitingAttachments(chatKey) ? void 0 : message.branchChatId;
|
|
135992
136327
|
const route = {
|
|
@@ -135995,62 +136330,65 @@ var makeInbound = (core, deps) => {
|
|
|
135995
136330
|
projectId: target3.projectId
|
|
135996
136331
|
};
|
|
135997
136332
|
await saveRoute(route);
|
|
135998
|
-
|
|
136333
|
+
return execute(route, target3);
|
|
135999
136334
|
};
|
|
136000
136335
|
const execute = (route, routedTarget = target2) => executeInboundRoute(
|
|
136001
136336
|
core,
|
|
136002
|
-
{ ...deps, openTurn, acceptedWork, inheritFromParent, continueMessage },
|
|
136003
|
-
{ current, message, target: routedTarget, route, work, queueChatId }
|
|
136337
|
+
{ ...deps, openTurn, acceptedWork, inheritFromParent, continueMessage, run: run2 },
|
|
136338
|
+
{ current, message, target: routedTarget, route, work, queueChatId, onAccepted }
|
|
136004
136339
|
);
|
|
136005
|
-
|
|
136006
|
-
|
|
136007
|
-
|
|
136008
|
-
|
|
136009
|
-
|
|
136010
|
-
|
|
136011
|
-
|
|
136012
|
-
|
|
136013
|
-
|
|
136014
|
-
|
|
136015
|
-
|
|
136016
|
-
|
|
136017
|
-
|
|
136018
|
-
|
|
136019
|
-
|
|
136020
|
-
|
|
136021
|
-
|
|
136022
|
-
|
|
136023
|
-
|
|
136024
|
-
|
|
136025
|
-
|
|
136026
|
-
|
|
136027
|
-
|
|
136028
|
-
|
|
136029
|
-
|
|
136030
|
-
|
|
136031
|
-
|
|
136032
|
-
|
|
136033
|
-
|
|
136034
|
-
|
|
136035
|
-
|
|
136036
|
-
|
|
136037
|
-
|
|
136038
|
-
|
|
136039
|
-
|
|
136040
|
-
|
|
136041
|
-
|
|
136042
|
-
|
|
136043
|
-
|
|
136044
|
-
|
|
136045
|
-
|
|
136046
|
-
|
|
136047
|
-
|
|
136048
|
-
|
|
136049
|
-
|
|
136050
|
-
|
|
136051
|
-
|
|
136052
|
-
|
|
136053
|
-
|
|
136340
|
+
let onAccepted;
|
|
136341
|
+
const executeMessage = async (accepted) => {
|
|
136342
|
+
onAccepted = accepted;
|
|
136343
|
+
inheritFromParent(current, message.chatId, message.parentChatId);
|
|
136344
|
+
target2 = { ...bindingOf2(current, message.chatId), reply: target2.reply };
|
|
136345
|
+
if (work?.route !== void 0) return execute(work.route);
|
|
136346
|
+
if (!isAllowedSender(target2, message.senderId, message.chatKind)) {
|
|
136347
|
+
await saveRoute({ kind: "unavailable" });
|
|
136348
|
+
await complete();
|
|
136349
|
+
return { status: "settled", respond: () => turnAwayStranger(target2, message.senderId) };
|
|
136350
|
+
}
|
|
136351
|
+
const unsupportedType = message.unsupportedType;
|
|
136352
|
+
if (unsupportedType !== void 0) {
|
|
136353
|
+
await saveRoute({ kind: "unavailable" });
|
|
136354
|
+
await complete();
|
|
136355
|
+
return {
|
|
136356
|
+
status: "settled",
|
|
136357
|
+
respond: async () => {
|
|
136358
|
+
if (unsupportedReplyCooldown.tryAcquire(chatKey))
|
|
136359
|
+
await deliver(
|
|
136360
|
+
target2,
|
|
136361
|
+
unsupportedType === "folder" ? t("reply.unsupportedFolder") : unsupportedType === "voice" ? t("reply.unsupportedVoice") : t("reply.unsupportedType", { type: unsupportedType })
|
|
136362
|
+
);
|
|
136363
|
+
}
|
|
136364
|
+
};
|
|
136365
|
+
}
|
|
136366
|
+
const approval = openApprovalOf(core.state, chatKey);
|
|
136367
|
+
const token = approval === void 0 ? null : adapterFor(target2.platform)?.answerByText?.(target2, message.text, approval.options) ?? null;
|
|
136368
|
+
if (token !== null) {
|
|
136369
|
+
const route = { kind: "approval", token };
|
|
136370
|
+
await saveRoute(route);
|
|
136371
|
+
return execute(route);
|
|
136372
|
+
}
|
|
136373
|
+
const command = parseChatCommand({
|
|
136374
|
+
text: message.text,
|
|
136375
|
+
chinese: t.language === "zh-CN",
|
|
136376
|
+
hasImages: message.resources.length > 0
|
|
136377
|
+
});
|
|
136378
|
+
if (command.kind !== "message") {
|
|
136379
|
+
const route = { kind: "command", command };
|
|
136380
|
+
await saveRoute(route);
|
|
136381
|
+
return execute(route);
|
|
136382
|
+
}
|
|
136383
|
+
if (target2.projectId === "") {
|
|
136384
|
+
const decision = await decideProjectMessage(target2, message);
|
|
136385
|
+
const route = { kind: "project", decision };
|
|
136386
|
+
await saveRoute(route);
|
|
136387
|
+
return execute(route);
|
|
136388
|
+
}
|
|
136389
|
+
return continueMessage(target2);
|
|
136390
|
+
};
|
|
136391
|
+
await run2(executeMessage);
|
|
136054
136392
|
};
|
|
136055
136393
|
const inboundHandlersFor = (bot) => ({
|
|
136056
136394
|
onError: (message) => host.log.warn("chat inbound connection failed", {
|
|
@@ -136137,7 +136475,10 @@ var makeInbound = (core, deps) => {
|
|
|
136137
136475
|
inboundHandlersFor,
|
|
136138
136476
|
resumeMessage,
|
|
136139
136477
|
enqueueReplay,
|
|
136140
|
-
cancelReplay:
|
|
136478
|
+
cancelReplay: (rowId) => {
|
|
136479
|
+
replay.cancelReplay(rowId);
|
|
136480
|
+
track(deps.acknowledgements.stopDeferred(rowId));
|
|
136481
|
+
},
|
|
136141
136482
|
stop: async () => {
|
|
136142
136483
|
accepting = false;
|
|
136143
136484
|
replay.stop();
|
|
@@ -137410,7 +137751,7 @@ var ConsoleError = class extends Error {
|
|
|
137410
137751
|
this.retryAfterMs = extra.retryAfterMs;
|
|
137411
137752
|
}
|
|
137412
137753
|
};
|
|
137413
|
-
var
|
|
137754
|
+
var withDeadline2 = async (deps, ms, run2) => {
|
|
137414
137755
|
const controller = new AbortController();
|
|
137415
137756
|
const timer = new AbortController();
|
|
137416
137757
|
let timedOut = false;
|
|
@@ -137437,7 +137778,7 @@ var withDeadline = async (deps, ms, run2) => {
|
|
|
137437
137778
|
deps.signal.removeEventListener("abort", onParentAbort);
|
|
137438
137779
|
}
|
|
137439
137780
|
};
|
|
137440
|
-
var guarded =
|
|
137781
|
+
var guarded = withDeadline2;
|
|
137441
137782
|
var sleepOrAbort = async (deps, ms) => {
|
|
137442
137783
|
try {
|
|
137443
137784
|
await deps.clock.sleep(ms, deps.signal);
|
|
@@ -137469,7 +137810,7 @@ var retryAfterMs = (response) => {
|
|
|
137469
137810
|
};
|
|
137470
137811
|
var openConsole = async (deps, jar) => {
|
|
137471
137812
|
const pageUrl = `${CONSOLE_ORIGIN}${CONSOLE_APP_PATH}`;
|
|
137472
|
-
const loadPage = () =>
|
|
137813
|
+
const loadPage = () => withDeadline2(deps, TIMEOUT_MS.page, async (signal) => {
|
|
137473
137814
|
const { response, finalUrl } = await jar.fetch(deps.fetch, pageUrl, {
|
|
137474
137815
|
method: "GET",
|
|
137475
137816
|
headers: { accept: "text/html,application/xhtml+xml" },
|
|
@@ -137498,7 +137839,7 @@ var openConsole = async (deps, jar) => {
|
|
|
137498
137839
|
calls += 1;
|
|
137499
137840
|
const started = deps.clock.now();
|
|
137500
137841
|
try {
|
|
137501
|
-
const result2 = await
|
|
137842
|
+
const result2 = await withDeadline2(deps, timeoutOf(kind), async (signal) => {
|
|
137502
137843
|
const { response } = await jar.fetch(deps.fetch, `${origin}${path}`, {
|
|
137503
137844
|
method: "POST",
|
|
137504
137845
|
headers: {
|
|
@@ -145068,22 +145409,6 @@ var larkInboundPersistence = (contextFor) => ({
|
|
|
145068
145409
|
}
|
|
145069
145410
|
});
|
|
145070
145411
|
|
|
145071
|
-
// src/deadline.ts
|
|
145072
|
-
var withDeadline2 = async (timeoutMs, load) => {
|
|
145073
|
-
const signal = AbortSignal.timeout(timeoutMs);
|
|
145074
|
-
let onAbort = () => {
|
|
145075
|
-
};
|
|
145076
|
-
const aborted = new Promise((_, reject) => {
|
|
145077
|
-
onAbort = () => reject(signal.reason);
|
|
145078
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
145079
|
-
});
|
|
145080
|
-
try {
|
|
145081
|
-
return await Promise.race([load(signal), aborted]);
|
|
145082
|
-
} finally {
|
|
145083
|
-
signal.removeEventListener("abort", onAbort);
|
|
145084
|
-
}
|
|
145085
|
-
};
|
|
145086
|
-
|
|
145087
145412
|
// src/boundedSeen.ts
|
|
145088
145413
|
var makeBoundedSeen = (limit) => {
|
|
145089
145414
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -145229,7 +145554,7 @@ var errorReason = (error) => {
|
|
|
145229
145554
|
};
|
|
145230
145555
|
var loadReplyReference = async (load) => {
|
|
145231
145556
|
try {
|
|
145232
|
-
return await
|
|
145557
|
+
return await withDeadline(LOAD_TIMEOUT_MS, load) ?? { unavailableReason: "not-found" };
|
|
145233
145558
|
} catch (error) {
|
|
145234
145559
|
return { unavailableReason: errorReason(error) };
|
|
145235
145560
|
}
|
|
@@ -145248,7 +145573,7 @@ var makeLookup = (rowId, load) => {
|
|
|
145248
145573
|
if (known !== void 0 && Date.now() - known.at < CACHE_MS) return known.value;
|
|
145249
145574
|
const pending = inflight.get(key2);
|
|
145250
145575
|
if (pending !== void 0) return pending;
|
|
145251
|
-
const reading =
|
|
145576
|
+
const reading = withDeadline(LOOKUP_TIMEOUT_MS, (signal) => load(id, signal)).catch(() => null).then((value2) => {
|
|
145252
145577
|
cache.set(key2, { value: value2, at: Date.now() });
|
|
145253
145578
|
return value2;
|
|
145254
145579
|
}).finally(() => inflight.delete(key2));
|
|
@@ -145428,7 +145753,7 @@ ${indent} `)}`;
|
|
|
145428
145753
|
};
|
|
145429
145754
|
var loadMergeForward = async (message, deps) => {
|
|
145430
145755
|
try {
|
|
145431
|
-
const items = await
|
|
145756
|
+
const items = await withDeadline(1e4, async (signal) => {
|
|
145432
145757
|
const token = await deps.tenantToken();
|
|
145433
145758
|
signal.throwIfAborted();
|
|
145434
145759
|
return fetchMergeForwardMessages({
|
|
@@ -145848,6 +146173,8 @@ var en_default = {
|
|
|
145848
146173
|
sendingFile: "Sending {{name}}:",
|
|
145849
146174
|
notAllowedYet: `You are not on the allow list yet. Your user id is {{id}}. Add it under Settings \u2192 Plugins \u2192 Chat, in this bot's "Allowed people" box.`,
|
|
145850
146175
|
received: "Got it, working on it.",
|
|
146176
|
+
inboundFailed: "This message couldn't be handled. Please send it again later.",
|
|
146177
|
+
inboundDeferred: "No need to send this again \u2014 it will be handled automatically the next time the machine starts.",
|
|
145851
146178
|
welcome: "Connected. Send text or images to get started, or send /help to see the available commands."
|
|
145852
146179
|
},
|
|
145853
146180
|
approval: {
|
|
@@ -145932,9 +146259,10 @@ var en_default = {
|
|
|
145932
146259
|
new: "\xB7 /new \u2014 forget the current session; the next message starts a new one",
|
|
145933
146260
|
team: "\xB7 /team \u2014 give this project's team a goal with each message; use /repo to pick the project first",
|
|
145934
146261
|
thread: "\xB7 /thread \u2014 go back to a normal session",
|
|
145935
|
-
aliases: "Chinese shortcuts (\u505C / \u7EE7\u7EED\u53D1\u9001 / \u72B6\u6001 / \u65B0\u5BF9\u8BDD / \u4F1A\u8BDD\u5217\u8868 / \u5207\u6362\u4F1A\u8BDD / \u6362\u6A21\u578B / \u8BA1\u5212\u6A21\u5F0F / \u6362\u9879\u76EE / \u5EFA\u7FA4 / \u6362\u56E2\u961F / \u6362\u5BF9\u8BDD) work when the reply language is Chinese.",
|
|
146262
|
+
aliases: "Chinese shortcuts (\u505C / \u7EE7\u7EED\u53D1\u9001 / \u72B6\u6001 / \u65B0\u5BF9\u8BDD / \u4F1A\u8BDD\u5217\u8868 / \u5207\u6362\u4F1A\u8BDD / \u4F1A\u8BDD\u5386\u53F2 / \u6362\u6A21\u578B / \u8BA1\u5212\u6A21\u5F0F / \u6362\u9879\u76EE / \u5EFA\u7FA4 / \u6362\u56E2\u961F / \u6362\u5BF9\u8BDD) work when the reply language is Chinese.",
|
|
145936
146263
|
sessions: "\xB7 /sessions \u2014 list this project's sessions; add a project number from /repo to list the ones this bot opened in another project",
|
|
145937
146264
|
resume: "\xB7 /resume number-or-id-prefix \u2014 switch sessions; one from another project switches the project too",
|
|
146265
|
+
history: "\xB7 /history [count] \u2014 preview recent messages in the current session, in private chats only (default {{defaultCount}}, maximum {{maxCount}})",
|
|
145938
146266
|
model: "\xB7 /model \u2014 see the model this chat uses; /model number or /model instance/model switches it",
|
|
145939
146267
|
preset: "\xB7 /preset \u2014 see the preset this chat uses for new sessions; /preset number or /preset name-or-id switches it; /preset none clears the chat choice",
|
|
145940
146268
|
plan: "\xB7 /plan \u2014 toggle plan mode (the agent proposes a plan instead of acting); /plan on, /plan off set it",
|
|
@@ -145943,6 +146271,21 @@ var en_default = {
|
|
|
145943
146271
|
group: "\xB7 /group name \u2014 Lark only: the bot creates a group and adds you (bots on other platforms cannot)",
|
|
145944
146272
|
syncNote: "\xB7 After a private chat attaches a session, web user text and final assistant text sync here (groups never sync)."
|
|
145945
146273
|
},
|
|
146274
|
+
history: {
|
|
146275
|
+
usage: "Usage: /history [count] \u2014 1 to {{maxCount}} (larger numbers count as {{maxCount}}), default {{defaultCount}}.",
|
|
146276
|
+
directOnly: "In a group this would show the session to everyone. Send /history in a private chat with the bot.",
|
|
146277
|
+
noSession: "This chat has no current session. Send a message to start one, or use /sessions to find a session and /resume to switch to it.",
|
|
146278
|
+
empty: "No messages to show in this session yet.",
|
|
146279
|
+
noneRecent: "Nothing to show among this session's most recent messages (older ones were not checked).",
|
|
146280
|
+
failed: "Could not read the recent messages. Try again in a moment.",
|
|
146281
|
+
title: "Recent messages in this session ({{count}}):",
|
|
146282
|
+
user: "User",
|
|
146283
|
+
assistant: "Assistant",
|
|
146284
|
+
image: "[Image]",
|
|
146285
|
+
file: "[File]",
|
|
146286
|
+
noText: "[No previewable text]",
|
|
146287
|
+
truncated: "[Remaining text omitted]"
|
|
146288
|
+
},
|
|
145946
146289
|
sessions: {
|
|
145947
146290
|
title: "This project's sessions ({{count}}):",
|
|
145948
146291
|
empty: "This bot has not opened any session in this project yet. Send a message to start one.",
|
|
@@ -146755,6 +147098,8 @@ var zh_CN_default = {
|
|
|
146755
147098
|
sendingFile: "\u6B63\u5728\u53D1\u9001 {{name}}\uFF1A",
|
|
146756
147099
|
notAllowedYet: "\u4F60\u8FD8\u4E0D\u5728\u5141\u8BB8\u540D\u5355\u91CC\uFF0C\u4F60\u7684\u7528\u6237 id \u662F {{id}}\uFF0C\u8BF7\u628A\u5B83\u586B\u8FDB \u8BBE\u7F6E \u2192 \u63D2\u4EF6 \u2192 \u804A\u5929 \u2192 \u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u300C\u5141\u8BB8\u7684\u4EBA\u300D\u3002",
|
|
146757
147100
|
received: "\u6536\u5230\uFF0C\u5728\u5904\u7406\u3002",
|
|
147101
|
+
inboundFailed: "\u8FD9\u6761\u6D88\u606F\u5904\u7406\u65F6\u51FA\u4E86\u9519\uFF0C\u8BF7\u7A0D\u540E\u91CD\u53D1\u3002",
|
|
147102
|
+
inboundDeferred: "\u4E0D\u7528\u91CD\u53D1\uFF1A\u673A\u5668\u4E0B\u6B21\u542F\u52A8\u65F6\u4F1A\u81EA\u52A8\u5904\u7406\u8FD9\u6761\u6D88\u606F\u3002",
|
|
146758
147103
|
welcome: "\u5DF2\u8FDE\u4E0A\u3002\u76F4\u63A5\u53D1\u6587\u5B57\u6216\u56FE\u7247\u5C31\u80FD\u5F00\u59CB\uFF0C\u53D1 /help \u770B\u80FD\u7528\u7684\u547D\u4EE4\u3002"
|
|
146759
147104
|
},
|
|
146760
147105
|
approval: {
|
|
@@ -146839,9 +147184,10 @@ var zh_CN_default = {
|
|
|
146839
147184
|
new: "\xB7 /new \u2014\u2014 \u5FD8\u6389\u5F53\u524D\u4F1A\u8BDD\uFF0C\u4E0B\u4E00\u53E5\u5F00\u65B0\u7684",
|
|
146840
147185
|
team: "\xB7 /team \u2014\u2014 \u6BCF\u6761\u6D88\u606F\u90FD\u7ED9\u8FD9\u4E2A\u9879\u76EE\u7684\u56E2\u961F\u5F00\u4E00\u4E2A\u76EE\u6807\uFF1B\u5148\u7528 /repo \u9009\u9879\u76EE",
|
|
146841
147186
|
thread: "\xB7 /thread \u2014\u2014 \u5207\u56DE\u666E\u901A\u4F1A\u8BDD",
|
|
146842
|
-
aliases: "\u4E2D\u6587\u4E5F\u884C\uFF1A\u505C / \u7EE7\u7EED\u53D1\u9001 / \u72B6\u6001 / \u65B0\u5BF9\u8BDD / \u4F1A\u8BDD\u5217\u8868 / \u5207\u6362\u4F1A\u8BDD / \u6362\u6A21\u578B / \u8BA1\u5212\u6A21\u5F0F / \u6362\u9879\u76EE / \u5EFA\u7FA4 / \u6362\u56E2\u961F / \u6362\u5BF9\u8BDD\u3002",
|
|
147187
|
+
aliases: "\u4E2D\u6587\u4E5F\u884C\uFF1A\u505C / \u7EE7\u7EED\u53D1\u9001 / \u72B6\u6001 / \u65B0\u5BF9\u8BDD / \u4F1A\u8BDD\u5217\u8868 / \u5207\u6362\u4F1A\u8BDD / \u4F1A\u8BDD\u5386\u53F2 / \u6362\u6A21\u578B / \u8BA1\u5212\u6A21\u5F0F / \u6362\u9879\u76EE / \u5EFA\u7FA4 / \u6362\u56E2\u961F / \u6362\u5BF9\u8BDD\u3002",
|
|
146843
147188
|
sessions: "\xB7 /sessions \u2014\u2014 \u5217\u51FA\u672C\u9879\u76EE\u7684\u4F1A\u8BDD\uFF1B\u52A0 /repo \u91CC\u7684\u9879\u76EE\u7F16\u53F7\uFF0C\u5217\u51FA\u672C\u673A\u5668\u4EBA\u5728\u522B\u7684\u9879\u76EE\u5F00\u8FC7\u7684",
|
|
146844
147189
|
resume: "\xB7 /resume \u7F16\u53F7\u6216 id \u5F00\u5934 \u2014\u2014 \u5207\u4F1A\u8BDD\uFF1B\u522B\u7684\u9879\u76EE\u7684\u4F1A\u8BDD\u4F1A\u8FDE\u540C\u9879\u76EE\u4E00\u8D77\u5207",
|
|
147190
|
+
history: "\xB7 /history [\u6570\u91CF] \u2014\u2014 \u4EC5\u79C1\u804A\uFF1A\u67E5\u770B\u5F53\u524D\u4F1A\u8BDD\u6700\u8FD1\u7684\u6D88\u606F\uFF08\u9ED8\u8BA4 {{defaultCount}} \u6761\uFF0C\u6700\u591A {{maxCount}} \u6761\uFF09",
|
|
146845
147191
|
model: "\xB7 /model \u2014\u2014 \u770B\u8FD9\u4E2A\u804A\u5929\u7528\u7684\u6A21\u578B\uFF1B/model \u7F16\u53F7 \u6216 /model \u5B9E\u4F8B/\u6A21\u578B \u5207\u6362",
|
|
146846
147192
|
preset: "\xB7 /preset \u2014\u2014 \u770B\u8FD9\u4E2A\u804A\u5929\u65B0\u4F1A\u8BDD\u7528\u7684\u9884\u8BBE\uFF1B/preset \u7F16\u53F7 \u6216 /preset \u540D\u5B57\u6216 id \u5207\u6362\uFF1B/preset none \u6E05\u6389\u804A\u5929\u9009\u62E9",
|
|
146847
147193
|
plan: "\xB7 /plan \u2014\u2014 \u5F00\u5173\u8BA1\u5212\u6A21\u5F0F\uFF08agent \u5148\u51FA\u8BA1\u5212\u3001\u4E0D\u52A8\u624B\uFF09\uFF1B/plan on\u3001/plan off \u660E\u786E\u8BBE\u5B9A",
|
|
@@ -146850,6 +147196,21 @@ var zh_CN_default = {
|
|
|
146850
147196
|
group: "\xB7 /group \u7FA4\u540D \u2014\u2014 \u4EC5\u98DE\u4E66\uFF1A\u673A\u5668\u4EBA\u5EFA\u4E00\u4E2A\u7FA4\u5E76\u628A\u4F60\u62C9\u8FDB\u53BB\uFF08\u522B\u7684\u5E73\u53F0\u7684\u673A\u5668\u4EBA\u5EFA\u4E0D\u4E86\u7FA4\uFF09",
|
|
146851
147197
|
syncNote: "\xB7 \u79C1\u804A\u9644\u7740\u4F1A\u8BDD\u540E\uFF0C\u7F51\u9875\u4E0A\u7684\u7528\u6237\u6587\u5B57\u4E0E\u7EC8\u6001\u52A9\u624B\u6587\u5B57\u4F1A\u540C\u6B65\u5230\u6B64\uFF08\u7FA4\u804A\u4E0D\u540C\u6B65\uFF09\u3002"
|
|
146852
147198
|
},
|
|
147199
|
+
history: {
|
|
147200
|
+
usage: "\u7528\u6CD5\uFF1A/history [\u6570\u91CF] \u2014\u2014 1\u2013{{maxCount}} \u6761\uFF08\u8D85\u51FA\u6309 {{maxCount}} \u6761\u7B97\uFF09\uFF0C\u9ED8\u8BA4 {{defaultCount}} \u6761\u3002",
|
|
147201
|
+
directOnly: "\u5728\u7FA4\u91CC\u4F1A\u628A\u4F1A\u8BDD\u5185\u5BB9\u53D1\u7ED9\u6240\u6709\u4EBA\u3002\u5728\u4E0E\u673A\u5668\u4EBA\u7684\u79C1\u804A\u91CC\u53D1 /history\u3002",
|
|
147202
|
+
noSession: "\u8FD9\u4E2A\u804A\u5929\u8FD8\u6CA1\u6709\u5F53\u524D\u4F1A\u8BDD\u3002\u53D1\u4E00\u53E5\u8BDD\u5F00\u4E00\u4E2A\uFF0C\u6216\u5148\u7528 /sessions \u627E\u5230\u4F1A\u8BDD\uFF0C\u518D\u7528 /resume \u5207\u8FC7\u53BB\u3002",
|
|
147203
|
+
empty: "\u5F53\u524D\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u80FD\u67E5\u770B\u7684\u6D88\u606F\u3002",
|
|
147204
|
+
noneRecent: "\u5F53\u524D\u4F1A\u8BDD\u6700\u8FD1\u7684\u6D88\u606F\u91CC\u6CA1\u6709\u80FD\u67E5\u770B\u7684\uFF08\u66F4\u65E9\u7684\u6CA1\u6709\u5F80\u524D\u7FFB\uFF09\u3002",
|
|
147205
|
+
failed: "\u6CA1\u80FD\u8BFB\u53D6\u6700\u8FD1\u7684\u6D88\u606F\uFF0C\u7A0D\u540E\u518D\u8BD5\u3002",
|
|
147206
|
+
title: "\u5F53\u524D\u4F1A\u8BDD\u6700\u8FD1\u7684\u6D88\u606F\uFF08{{count}} \u6761\uFF09\uFF1A",
|
|
147207
|
+
user: "\u7528\u6237",
|
|
147208
|
+
assistant: "\u52A9\u624B",
|
|
147209
|
+
image: "[\u56FE\u7247]",
|
|
147210
|
+
file: "[\u6587\u4EF6]",
|
|
147211
|
+
noText: "[\u6CA1\u6709\u53EF\u9884\u89C8\u7684\u6587\u5B57]",
|
|
147212
|
+
truncated: "[\u5176\u4F59\u6587\u5B57\u5DF2\u7701\u7565]"
|
|
147213
|
+
},
|
|
146853
147214
|
sessions: {
|
|
146854
147215
|
title: "\u672C\u9879\u76EE\u7684\u4F1A\u8BDD\uFF08{{count}} \u6761\uFF09\uFF1A",
|
|
146855
147216
|
empty: "\u672C\u673A\u5668\u4EBA\u8FD8\u6CA1\u5728\u672C\u9879\u76EE\u5F00\u8FC7\u4F1A\u8BDD\uFF0C\u53D1\u4E00\u53E5\u8BDD\u5C31\u4F1A\u5F00\u4E00\u6761\u3002",
|
|
@@ -147604,7 +147965,7 @@ var CREATE_INTERVAL_MS = 1100;
|
|
|
147604
147965
|
var syncLarkSlashCommands = async (input) => {
|
|
147605
147966
|
const request = async (method, id, body) => {
|
|
147606
147967
|
input.signal.throwIfAborted();
|
|
147607
|
-
return
|
|
147968
|
+
return withDeadline(REQUEST_TIMEOUT_MS, async (timeout2) => {
|
|
147608
147969
|
const signal = AbortSignal.any([input.signal, timeout2]);
|
|
147609
147970
|
const response = await input.http(
|
|
147610
147971
|
id === void 0 ? ENDPOINT : `${ENDPOINT}/${encodeURIComponent(id)}`,
|
|
@@ -147681,7 +148042,7 @@ var makeLarkSlashCommands = (deps) => {
|
|
|
147681
148042
|
const run2 = app.settled.then(async () => {
|
|
147682
148043
|
if (signal.aborted) return;
|
|
147683
148044
|
try {
|
|
147684
|
-
const token = await
|
|
148045
|
+
const token = await withDeadline(
|
|
147685
148046
|
REQUEST_TIMEOUT_MS,
|
|
147686
148047
|
(timeout2) => deps.tenantToken(bot, AbortSignal.any([signal, timeout2]))
|
|
147687
148048
|
);
|
|
@@ -148159,14 +148520,14 @@ var makeLarkAdapter = (deps) => {
|
|
|
148159
148520
|
}),
|
|
148160
148521
|
clearAcknowledge: async (binding, messageId, ackId, outcome) => {
|
|
148161
148522
|
const token = await tenantToken(binding);
|
|
148162
|
-
await
|
|
148523
|
+
await withDeadline(
|
|
148163
148524
|
LARK_REACTION_TIMEOUT_MS,
|
|
148164
148525
|
(signal) => removeReaction({ http: deps.http, token, messageId, reactionId: ackId, signal })
|
|
148165
148526
|
);
|
|
148166
148527
|
const emojiType = outcome === "done" ? LARK_DONE_REACTION : outcome === "failed" ? LARK_FAILED_REACTION : null;
|
|
148167
148528
|
if (emojiType === null) return;
|
|
148168
148529
|
try {
|
|
148169
|
-
await
|
|
148530
|
+
await withDeadline(
|
|
148170
148531
|
LARK_REACTION_TIMEOUT_MS,
|
|
148171
148532
|
(signal) => addReaction({ http: deps.http, token, messageId, emojiType, signal })
|
|
148172
148533
|
);
|
|
@@ -148436,7 +148797,7 @@ var outcomeOfSession = (status) => {
|
|
|
148436
148797
|
var THREAD_PROJECT_CACHE_LIMIT = 256;
|
|
148437
148798
|
var makeNotifications = (core, deps) => {
|
|
148438
148799
|
const { host, adapterFor, bindingForChatKey, ready } = core;
|
|
148439
|
-
const { takeWorking } = deps;
|
|
148800
|
+
const { takeWorking, stopTypingFor } = deps;
|
|
148440
148801
|
const { turnCards } = deps.replyCards;
|
|
148441
148802
|
const { failures, conclusions, delivery } = deps;
|
|
148442
148803
|
const { recoverConclusion, recoverConclusions } = makeConclusionRecovery(
|
|
@@ -148489,6 +148850,7 @@ var makeNotifications = (core, deps) => {
|
|
|
148489
148850
|
const threadId = payload.threadId;
|
|
148490
148851
|
if (typeof threadId !== "string") return;
|
|
148491
148852
|
if (payload.session?.activeTurnId != null) return;
|
|
148853
|
+
stopTypingFor(threadId);
|
|
148492
148854
|
const outcome = outcomeOfSession(payload.session?.status);
|
|
148493
148855
|
const said = threadsWithSomethingToReport.delete(threadId);
|
|
148494
148856
|
await ready;
|
|
@@ -148533,6 +148895,7 @@ var makeNotifications = (core, deps) => {
|
|
|
148533
148895
|
host.events.on("thread.failed", async (event) => {
|
|
148534
148896
|
const threadId = event.threadId;
|
|
148535
148897
|
if (threadId === null) return;
|
|
148898
|
+
stopTypingFor(threadId);
|
|
148536
148899
|
threadsWithSomethingToReport.delete(threadId);
|
|
148537
148900
|
await ready;
|
|
148538
148901
|
const targets = targetsForProject(threadId, await projectOfThread(threadId));
|
|
@@ -150072,6 +150435,7 @@ var makeTeamGoals = (core) => {
|
|
|
150072
150435
|
};
|
|
150073
150436
|
const startTeamGoal = async (binding, message, accepted) => {
|
|
150074
150437
|
let goal;
|
|
150438
|
+
let confirmConsumed;
|
|
150075
150439
|
try {
|
|
150076
150440
|
const requestId = teamGoalRequestId(binding, message.messageId);
|
|
150077
150441
|
const topicRoot = await message.topicRootForSession?.(requestId);
|
|
@@ -150086,24 +150450,30 @@ var makeTeamGoals = (core) => {
|
|
|
150086
150450
|
}
|
|
150087
150451
|
});
|
|
150088
150452
|
if (isRecord3(result2) && result2._tag === "TeamGoalRejection") {
|
|
150089
|
-
|
|
150090
|
-
|
|
150091
|
-
|
|
150092
|
-
|
|
150093
|
-
|
|
150094
|
-
|
|
150095
|
-
|
|
150453
|
+
const key2 = result2.code === "no-roster" ? "team.noRoster" : result2.code === "invalid-goal" ? "team.invalidGoal" : "team.startFailed";
|
|
150454
|
+
return {
|
|
150455
|
+
status: "settled",
|
|
150456
|
+
respond: async () => {
|
|
150457
|
+
await deliver(binding, t(key2));
|
|
150458
|
+
}
|
|
150459
|
+
};
|
|
150096
150460
|
}
|
|
150097
150461
|
if (!isRecord3(result2) || typeof result2.leadThreadId !== "string" || result2.leadThreadId === "" || result2.leadName !== null && typeof result2.leadName !== "string") {
|
|
150098
150462
|
throw new Error("team startGoal returned an invalid result");
|
|
150099
150463
|
}
|
|
150100
|
-
topicRoot?.confirmConsumed();
|
|
150101
150464
|
goal = { leadThreadId: result2.leadThreadId, leadName: result2.leadName };
|
|
150465
|
+
confirmConsumed = () => topicRoot?.confirmConsumed();
|
|
150102
150466
|
} catch (error) {
|
|
150103
150467
|
host.log.warn("chat could not start the team goal", { error: describeError(error) });
|
|
150104
|
-
|
|
150105
|
-
|
|
150468
|
+
return {
|
|
150469
|
+
status: "settled",
|
|
150470
|
+
respond: async () => {
|
|
150471
|
+
await deliver(binding, t("team.startFailed"));
|
|
150472
|
+
}
|
|
150473
|
+
};
|
|
150106
150474
|
}
|
|
150475
|
+
accepted?.onAccepted?.();
|
|
150476
|
+
confirmConsumed();
|
|
150107
150477
|
await commitDurably("team-goal-started", {
|
|
150108
150478
|
chatKey: chatKeyOf(binding),
|
|
150109
150479
|
threadId: goal.leadThreadId
|
|
@@ -150117,7 +150487,7 @@ var makeTeamGoals = (core) => {
|
|
|
150117
150487
|
bot: binding.displayName,
|
|
150118
150488
|
threadId: goal.leadThreadId
|
|
150119
150489
|
});
|
|
150120
|
-
return
|
|
150490
|
+
return { status: "started", claimsPlaceholder: false };
|
|
150121
150491
|
};
|
|
150122
150492
|
return { hasRosterFor, startTeamGoal };
|
|
150123
150493
|
};
|
|
@@ -151350,12 +151720,11 @@ var dispatchTurnWithReceipt = async (host, input, options) => {
|
|
|
151350
151720
|
var DELAYS = [3e4, 12e4, 6e5];
|
|
151351
151721
|
var MAX_DISPATCH_ATTEMPTS = DELAYS.length + 1;
|
|
151352
151722
|
var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried, messageText2, firstAttachmentName) => {
|
|
151353
|
-
if (deps.signal.aborted) return
|
|
151723
|
+
if (deps.signal.aborted) return { status: "deferred" };
|
|
151354
151724
|
const previous = inbox?.entry?.attempts ?? 0;
|
|
151355
151725
|
const attempt = Math.min(previous + 1, MAX_DISPATCH_ATTEMPTS);
|
|
151356
151726
|
const nextAttemptAt = inbox?.entry?.nextAttemptAt;
|
|
151357
151727
|
const incremented = previous < MAX_DISPATCH_ATTEMPTS;
|
|
151358
|
-
if (incremented) await inbox?.saveRetry(attempt, nextAttemptAt);
|
|
151359
151728
|
const reference2 = dispatchFailureReference(input.requestId);
|
|
151360
151729
|
const notify = async (text3) => {
|
|
151361
151730
|
try {
|
|
@@ -151368,6 +151737,18 @@ var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried
|
|
|
151368
151737
|
});
|
|
151369
151738
|
}
|
|
151370
151739
|
};
|
|
151740
|
+
if (incremented) {
|
|
151741
|
+
try {
|
|
151742
|
+
await inbox?.saveRetry(attempt, nextAttemptAt);
|
|
151743
|
+
} catch (error) {
|
|
151744
|
+
core.host.log.warn("chat could not save a dispatch attempt; leaving it for replay", {
|
|
151745
|
+
threadId: input.threadId,
|
|
151746
|
+
requestId: input.requestId,
|
|
151747
|
+
error: describeError(error)
|
|
151748
|
+
});
|
|
151749
|
+
return { status: "settled", respond: () => notify(core.t("reply.inboundDeferred")) };
|
|
151750
|
+
}
|
|
151751
|
+
}
|
|
151371
151752
|
try {
|
|
151372
151753
|
if (incremented) {
|
|
151373
151754
|
await dispatchTurnWithReceipt(core.host, input, {
|
|
@@ -151376,14 +151757,14 @@ var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried
|
|
|
151376
151757
|
});
|
|
151377
151758
|
} else {
|
|
151378
151759
|
const status = await confirmTurnReceipt(core.host, input);
|
|
151379
|
-
if (deps.signal.aborted) return
|
|
151760
|
+
if (deps.signal.aborted) return { status: "deferred" };
|
|
151380
151761
|
if (status === "absent") throw new Error("attempt budget exhausted; receipt absent");
|
|
151381
151762
|
}
|
|
151382
|
-
return
|
|
151763
|
+
return { status: "accepted" };
|
|
151383
151764
|
} catch (error) {
|
|
151384
151765
|
if (deps.signal.aborted) {
|
|
151385
151766
|
if (incremented) await inbox?.saveRetry(previous, nextAttemptAt);
|
|
151386
|
-
return
|
|
151767
|
+
return { status: "deferred" };
|
|
151387
151768
|
}
|
|
151388
151769
|
const delay2 = DELAYS[attempt - 1];
|
|
151389
151770
|
if (!(error instanceof TurnDispatchRejected) && delay2 !== void 0 && inbox?.entry !== void 0) {
|
|
@@ -151397,7 +151778,7 @@ var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried
|
|
|
151397
151778
|
error: describeError(error)
|
|
151398
151779
|
});
|
|
151399
151780
|
if (attempt === 1) await notify(deps.failures.forDispatchRetry(input.requestId));
|
|
151400
|
-
return
|
|
151781
|
+
return { status: "deferred" };
|
|
151401
151782
|
}
|
|
151402
151783
|
const redactor = botRedactor(
|
|
151403
151784
|
core.adapterFor(binding.platform)?.columns ?? [],
|
|
@@ -151416,10 +151797,12 @@ var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried
|
|
|
151416
151797
|
const textExcerpt = messageText2.trim();
|
|
151417
151798
|
const attachmentName = firstAttachmentName?.trim() ?? "";
|
|
151418
151799
|
const identifyingNotice = textExcerpt !== "" ? deps.failures.forDispatchFailureQuoted(input.requestId, textExcerpt) : attachmentName !== "" ? deps.failures.forDispatchFailureAttachment(input.requestId, attachmentName) : void 0;
|
|
151419
|
-
|
|
151420
|
-
|
|
151421
|
-
|
|
151422
|
-
|
|
151800
|
+
return {
|
|
151801
|
+
status: "settled",
|
|
151802
|
+
respond: () => notify(
|
|
151803
|
+
binding.reply === void 0 && attempt > 1 && identifyingNotice !== void 0 ? identifyingNotice : failureNotice
|
|
151804
|
+
)
|
|
151805
|
+
};
|
|
151423
151806
|
}
|
|
151424
151807
|
};
|
|
151425
151808
|
|
|
@@ -151473,6 +151856,7 @@ var makeTurns = (core, deps) => {
|
|
|
151473
151856
|
const ensureThread = async (binding, message) => {
|
|
151474
151857
|
const chatKey = chatKeyOf(binding);
|
|
151475
151858
|
let threadId = chatOf(core.state, chatKey).threadId ?? void 0;
|
|
151859
|
+
let dropped = false;
|
|
151476
151860
|
if (threadId !== void 0 && !await threadStillUsable(binding, threadId)) {
|
|
151477
151861
|
host.log.info("chat dropped a saved thread that is no longer usable", {
|
|
151478
151862
|
bot: binding.displayName,
|
|
@@ -151480,7 +151864,7 @@ var makeTurns = (core, deps) => {
|
|
|
151480
151864
|
});
|
|
151481
151865
|
bindChat(chatKey, null);
|
|
151482
151866
|
threadId = void 0;
|
|
151483
|
-
|
|
151867
|
+
dropped = true;
|
|
151484
151868
|
}
|
|
151485
151869
|
if (threadId !== void 0) return threadId;
|
|
151486
151870
|
const project = await projectOrNull2(host.projects, binding.projectId);
|
|
@@ -151489,7 +151873,13 @@ var makeTurns = (core, deps) => {
|
|
|
151489
151873
|
bot: binding.displayName,
|
|
151490
151874
|
projectId: binding.projectId
|
|
151491
151875
|
});
|
|
151492
|
-
return
|
|
151876
|
+
return {
|
|
151877
|
+
status: "settled",
|
|
151878
|
+
respond: async () => {
|
|
151879
|
+
if (dropped) await deliver(binding, t("reply.threadGone"));
|
|
151880
|
+
await deliver(binding, t("reply.projectMissing"));
|
|
151881
|
+
}
|
|
151882
|
+
};
|
|
151493
151883
|
}
|
|
151494
151884
|
const modelSelection = await resolveDefaultModel(
|
|
151495
151885
|
binding,
|
|
@@ -151502,8 +151892,13 @@ var makeTurns = (core, deps) => {
|
|
|
151502
151892
|
bot: binding.displayName,
|
|
151503
151893
|
projectId: binding.projectId
|
|
151504
151894
|
});
|
|
151505
|
-
|
|
151506
|
-
|
|
151895
|
+
return {
|
|
151896
|
+
status: "settled",
|
|
151897
|
+
respond: async () => {
|
|
151898
|
+
if (dropped) await deliver(binding, t("reply.threadGone"));
|
|
151899
|
+
await deliver(binding, t("reply.noDefaultModel", { title: project.title }));
|
|
151900
|
+
}
|
|
151901
|
+
};
|
|
151507
151902
|
}
|
|
151508
151903
|
const createdThreadId = identity2("thread", binding, message);
|
|
151509
151904
|
const presetId = await resolveDefaultPreset(chatOf(core.state, chatKey).preset, binding, host);
|
|
@@ -151526,17 +151921,19 @@ var makeTurns = (core, deps) => {
|
|
|
151526
151921
|
openedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
151527
151922
|
});
|
|
151528
151923
|
rememberThreadProject(createdThreadId, binding.projectId);
|
|
151924
|
+
if (dropped) await deliver(binding, t("reply.threadGone"));
|
|
151529
151925
|
return createdThreadId;
|
|
151530
151926
|
};
|
|
151531
151927
|
const startTurn = async (binding, message, accepted, inbox) => {
|
|
151532
151928
|
const chatKey = chatKeyOf(binding);
|
|
151533
151929
|
const text3 = message.text;
|
|
151534
151930
|
const replayed = inbox?.replayed === true || (inbox?.entry?.attempts ?? 0) > 0;
|
|
151535
|
-
const
|
|
151536
|
-
if (
|
|
151931
|
+
const prepared = inbox?.entry?.threadId ?? await ensureThread(binding, message);
|
|
151932
|
+
if (typeof prepared !== "string") {
|
|
151537
151933
|
await inbox?.complete();
|
|
151538
|
-
return
|
|
151934
|
+
return prepared;
|
|
151539
151935
|
}
|
|
151936
|
+
const threadId = prepared;
|
|
151540
151937
|
await inbox?.saveThread(threadId);
|
|
151541
151938
|
const topicRoot = await message.topicRootForSession?.(threadId);
|
|
151542
151939
|
const requestId = identity2("turn", binding, message);
|
|
@@ -151570,11 +151967,33 @@ var makeTurns = (core, deps) => {
|
|
|
151570
151967
|
stored: [...saved.stored, ...own.attachments],
|
|
151571
151968
|
notes: [...saved.notes, ...own.notes]
|
|
151572
151969
|
};
|
|
151573
|
-
await inbox?.saveAttachments(saved);
|
|
151574
151970
|
} catch (error) {
|
|
151575
151971
|
restoreCarried();
|
|
151576
151972
|
throw error;
|
|
151577
151973
|
}
|
|
151974
|
+
try {
|
|
151975
|
+
await inbox?.saveAttachments(saved);
|
|
151976
|
+
} catch (error) {
|
|
151977
|
+
restoreCarried();
|
|
151978
|
+
host.log.warn("chat could not save inbound attachments; leaving them for replay", {
|
|
151979
|
+
threadId,
|
|
151980
|
+
error: describeError(error)
|
|
151981
|
+
});
|
|
151982
|
+
return {
|
|
151983
|
+
status: "settled",
|
|
151984
|
+
respond: async () => {
|
|
151985
|
+
try {
|
|
151986
|
+
if (!await deliver(binding, t("reply.inboundDeferred")))
|
|
151987
|
+
host.log.warn("chat could not deliver an inbound deferral notice", { threadId });
|
|
151988
|
+
} catch (deliveryError) {
|
|
151989
|
+
host.log.warn("chat could not deliver an inbound deferral notice", {
|
|
151990
|
+
threadId,
|
|
151991
|
+
error: describeError(deliveryError)
|
|
151992
|
+
});
|
|
151993
|
+
}
|
|
151994
|
+
}
|
|
151995
|
+
};
|
|
151996
|
+
}
|
|
151578
151997
|
}
|
|
151579
151998
|
const attachments = saved.stored;
|
|
151580
151999
|
const notes = saved.notes;
|
|
@@ -151634,7 +152053,8 @@ var makeTurns = (core, deps) => {
|
|
|
151634
152053
|
message.text,
|
|
151635
152054
|
message.resources[0]?.name
|
|
151636
152055
|
);
|
|
151637
|
-
if (
|
|
152056
|
+
if (dispatched.status !== "accepted") return dispatched;
|
|
152057
|
+
accepted.onAccepted?.();
|
|
151638
152058
|
topicRoot?.confirmConsumed();
|
|
151639
152059
|
await deps.conclusions.owe(
|
|
151640
152060
|
{ chatKey, threadId, userMessageId, recordedAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
@@ -151658,11 +152078,12 @@ var makeTurns = (core, deps) => {
|
|
|
151658
152078
|
binding.reply
|
|
151659
152079
|
);
|
|
151660
152080
|
});
|
|
151661
|
-
return
|
|
152081
|
+
return { status: "started" };
|
|
151662
152082
|
};
|
|
151663
152083
|
const receiveAttachmentsOnly = async (binding, message, enteredWaiting) => {
|
|
151664
|
-
const
|
|
151665
|
-
if (
|
|
152084
|
+
const prepared = await ensureThread(binding, message);
|
|
152085
|
+
if (typeof prepared !== "string") return prepared;
|
|
152086
|
+
const threadId = prepared;
|
|
151666
152087
|
const waiting = pendingFor(chatKeyOf(binding), threadId);
|
|
151667
152088
|
const collected = await collectResources(
|
|
151668
152089
|
binding,
|
|
@@ -151674,7 +152095,7 @@ var makeTurns = (core, deps) => {
|
|
|
151674
152095
|
waiting.attachments.push(...collected.attachments);
|
|
151675
152096
|
waiting.notes.push(...collected.notes.slice(0, MAX_ATTACHMENTS_PER_TURN));
|
|
151676
152097
|
await enteredWaiting?.();
|
|
151677
|
-
if (collected.attachments.length === 0) return;
|
|
152098
|
+
if (collected.attachments.length === 0) return { status: "settled" };
|
|
151678
152099
|
await deliver(
|
|
151679
152100
|
binding,
|
|
151680
152101
|
t("reply.attachmentReceived", {
|
|
@@ -151682,6 +152103,7 @@ var makeTurns = (core, deps) => {
|
|
|
151682
152103
|
count: waiting.attachments.length
|
|
151683
152104
|
})
|
|
151684
152105
|
);
|
|
152106
|
+
return { status: "settled" };
|
|
151685
152107
|
};
|
|
151686
152108
|
const hasWaitingAttachments = (chatKey) => (waitingFor(chatKey, chatOf(core.state, chatKey).threadId)?.attachments.length ?? 0) > 0;
|
|
151687
152109
|
return {
|
|
@@ -155175,7 +155597,7 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
155175
155597
|
// src/index.ts
|
|
155176
155598
|
var definition = {
|
|
155177
155599
|
id: "im",
|
|
155178
|
-
apiVersion:
|
|
155600
|
+
apiVersion: 28,
|
|
155179
155601
|
// 第二个参数只给插件自己的测试夹具:换掉文件 IO 与派发重试的等待。宿主只传 ctx。
|
|
155180
155602
|
activate: async (ctx, testing = {}) => {
|
|
155181
155603
|
const { dispatchSleep } = testing;
|
|
@@ -155276,7 +155698,7 @@ var definition = {
|
|
|
155276
155698
|
t,
|
|
155277
155699
|
adapters
|
|
155278
155700
|
});
|
|
155279
|
-
const acknowledgements = makeAcknowledgements(core);
|
|
155701
|
+
const acknowledgements = makeAcknowledgements(core, ctx.interval);
|
|
155280
155702
|
const failures = makeFailureNotices(core);
|
|
155281
155703
|
const replyAnchors = makeReplyAnchors(core.host);
|
|
155282
155704
|
const conclusions = makeConclusionLedger(core);
|
|
@@ -155291,6 +155713,7 @@ var definition = {
|
|
|
155291
155713
|
const teams = makeTeamGoals(core);
|
|
155292
155714
|
const notifications = makeNotifications(core, {
|
|
155293
155715
|
takeWorking: acknowledgements.takeWorking,
|
|
155716
|
+
stopTypingFor: acknowledgements.stopTypingFor,
|
|
155294
155717
|
replyCards,
|
|
155295
155718
|
failures,
|
|
155296
155719
|
conclusions,
|
|
@@ -155330,6 +155753,7 @@ var definition = {
|
|
|
155330
155753
|
});
|
|
155331
155754
|
const chatSetup = makeChatSetup(core, {
|
|
155332
155755
|
rows: projectRows,
|
|
155756
|
+
enqueueForChat: chatQueue.enqueueForChat,
|
|
155333
155757
|
resumeMessage: (bot, message) => inbound.resumeMessage(bot, message),
|
|
155334
155758
|
openPicker: (chatKey, rows, reply) => panelWiring.panel.openProjects(chatKey, rows, reply)
|
|
155335
155759
|
});
|
|
@@ -155380,6 +155804,7 @@ var definition = {
|
|
|
155380
155804
|
await inbound.stop();
|
|
155381
155805
|
turns.stop();
|
|
155382
155806
|
await chatQueue.closeAndDrain();
|
|
155807
|
+
await acknowledgements.stopDeferred();
|
|
155383
155808
|
}
|
|
155384
155809
|
});
|
|
155385
155810
|
registerSettingsRowActions(
|