@ycodium-ai/plugin-im 0.2.3244 → 0.2.3252
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 +11 -7
- package/assets/ui.js +1 -1
- package/dist/index.js +807 -271
- package/locales/en.json +24 -1
- package/locales/zh-CN.json +24 -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",
|
|
@@ -133389,7 +133557,11 @@ var PlanCommandMode = Literals(["toggle", "on", "off", "invalid"]);
|
|
|
133389
133557
|
var ParsedChatCommand = Union2([
|
|
133390
133558
|
SimpleChatCommand,
|
|
133391
133559
|
Struct({ kind: Literal2("sessions"), arg: optionalKey2(String4) }),
|
|
133392
|
-
Struct({
|
|
133560
|
+
Struct({
|
|
133561
|
+
kind: Literals(["resume", "model", "repo", "version"]),
|
|
133562
|
+
arg: String4
|
|
133563
|
+
}),
|
|
133564
|
+
Struct({ kind: Literal2("history"), count: NullOr(Number5) }),
|
|
133393
133565
|
Struct({
|
|
133394
133566
|
kind: Literal2("preset"),
|
|
133395
133567
|
arg: String4,
|
|
@@ -133434,6 +133606,8 @@ var parseChatCommand = (input) => {
|
|
|
133434
133606
|
if (/^\/stop$/i.test(trimmed)) return { kind: "stop" };
|
|
133435
133607
|
if (/^\/continue$/i.test(trimmed)) return { kind: "continue" };
|
|
133436
133608
|
if (/^\/status$/i.test(trimmed)) return { kind: "status" };
|
|
133609
|
+
const versionArg = trimmed.match(/^\/version(?:\s+([\s\S]*))?$/iu);
|
|
133610
|
+
if (versionArg !== null) return { kind: "version", arg: (versionArg[1] ?? "").trim() };
|
|
133437
133611
|
if (/^\/new$/i.test(trimmed)) return { kind: "new" };
|
|
133438
133612
|
if (/^\/help$/i.test(trimmed)) return { kind: "help" };
|
|
133439
133613
|
if (/^\/panel$/i.test(trimmed)) return { kind: "panel" };
|
|
@@ -133441,6 +133615,16 @@ var parseChatCommand = (input) => {
|
|
|
133441
133615
|
if (sessions !== void 0) {
|
|
133442
133616
|
return sessions === "" ? { kind: "sessions" } : { kind: "sessions", arg: sessions };
|
|
133443
133617
|
}
|
|
133618
|
+
const history = commandArgument(
|
|
133619
|
+
trimmed,
|
|
133620
|
+
input.chinese,
|
|
133621
|
+
/^\/history(?:\s+([\s\S]*))?$/i,
|
|
133622
|
+
/^会话历史(?:\s+([\s\S]*))?$/
|
|
133623
|
+
);
|
|
133624
|
+
if (history !== void 0) {
|
|
133625
|
+
const count = history === "" ? HISTORY_COUNTS.defaultCount : /^\d+$/.test(history) ? Math.min(Number(history), HISTORY_COUNTS.maxCount) : 0;
|
|
133626
|
+
return { kind: "history", count: count > 0 ? count : null };
|
|
133627
|
+
}
|
|
133444
133628
|
const resume = resumeArgument(input.text, input.chinese);
|
|
133445
133629
|
if (resume !== void 0) {
|
|
133446
133630
|
return resume === "" ? { kind: "sessions" } : { kind: "resume", arg: resume };
|
|
@@ -133477,9 +133661,11 @@ var helpText = (t, options = {}) => [
|
|
|
133477
133661
|
t("help.stop"),
|
|
133478
133662
|
t("help.continue"),
|
|
133479
133663
|
t("help.status"),
|
|
133664
|
+
t("help.version"),
|
|
133480
133665
|
t("help.new"),
|
|
133481
133666
|
t("help.sessions"),
|
|
133482
133667
|
t("help.resume"),
|
|
133668
|
+
t("help.history", HISTORY_COUNTS),
|
|
133483
133669
|
t("help.syncNote"),
|
|
133484
133670
|
t("help.model"),
|
|
133485
133671
|
t("help.preset"),
|
|
@@ -133492,6 +133678,267 @@ var helpText = (t, options = {}) => [
|
|
|
133492
133678
|
...options.panel === true ? ["", t("help.panel")] : []
|
|
133493
133679
|
].join("\n");
|
|
133494
133680
|
|
|
133681
|
+
// src/deadline.ts
|
|
133682
|
+
var withDeadline = async (timeoutMs, load) => {
|
|
133683
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
133684
|
+
let onAbort = () => {
|
|
133685
|
+
};
|
|
133686
|
+
const aborted = new Promise((_, reject) => {
|
|
133687
|
+
onAbort = () => reject(signal.reason);
|
|
133688
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
133689
|
+
});
|
|
133690
|
+
try {
|
|
133691
|
+
return await Promise.race([load(signal), aborted]);
|
|
133692
|
+
} finally {
|
|
133693
|
+
signal.removeEventListener("abort", onAbort);
|
|
133694
|
+
}
|
|
133695
|
+
};
|
|
133696
|
+
|
|
133697
|
+
// src/threadMessages.ts
|
|
133698
|
+
import {
|
|
133699
|
+
isThreadNotFound,
|
|
133700
|
+
threadMessagesNewestFirst
|
|
133701
|
+
} from "@ycodium-ai/plugin-api";
|
|
133702
|
+
var PAGE_SIZE = 20;
|
|
133703
|
+
async function* newestFirst(threads, threadId) {
|
|
133704
|
+
try {
|
|
133705
|
+
yield* threadMessagesNewestFirst(threads, threadId, { pageSize: PAGE_SIZE });
|
|
133706
|
+
} catch (error) {
|
|
133707
|
+
if (!isThreadNotFound(error)) throw error;
|
|
133708
|
+
}
|
|
133709
|
+
}
|
|
133710
|
+
async function attachmentsOf(threads, threadId, message) {
|
|
133711
|
+
const collected = [...message.attachments ?? []];
|
|
133712
|
+
const total = message.attachmentsTotal ?? collected.length;
|
|
133713
|
+
while (collected.length < total) {
|
|
133714
|
+
let page;
|
|
133715
|
+
try {
|
|
133716
|
+
page = await threads.messages.list({
|
|
133717
|
+
threadId,
|
|
133718
|
+
messageId: message.id,
|
|
133719
|
+
attachmentOffset: collected.length,
|
|
133720
|
+
textLimit: 2
|
|
133721
|
+
});
|
|
133722
|
+
} catch (error) {
|
|
133723
|
+
if (isThreadNotFound(error)) break;
|
|
133724
|
+
throw error;
|
|
133725
|
+
}
|
|
133726
|
+
const more = page.items[0]?.attachments ?? [];
|
|
133727
|
+
if (more.length === 0) break;
|
|
133728
|
+
collected.push(...more);
|
|
133729
|
+
}
|
|
133730
|
+
return collected;
|
|
133731
|
+
}
|
|
133732
|
+
async function latestMessage(threads, threadId, accept) {
|
|
133733
|
+
for await (const message of newestFirst(threads, threadId)) {
|
|
133734
|
+
if (accept(message)) return message;
|
|
133735
|
+
}
|
|
133736
|
+
return void 0;
|
|
133737
|
+
}
|
|
133738
|
+
async function recentMessages(threads, threadId, count, accept) {
|
|
133739
|
+
const collected = [];
|
|
133740
|
+
for await (const message of newestFirst(threads, threadId)) {
|
|
133741
|
+
if (!accept(message)) continue;
|
|
133742
|
+
collected.push(message);
|
|
133743
|
+
if (collected.length >= count) break;
|
|
133744
|
+
}
|
|
133745
|
+
return collected.toReversed();
|
|
133746
|
+
}
|
|
133747
|
+
async function messagesAfterLastUser(threads, threadId) {
|
|
133748
|
+
const after = [];
|
|
133749
|
+
for await (const message of newestFirst(threads, threadId)) {
|
|
133750
|
+
if (message.role === "user") break;
|
|
133751
|
+
after.push(message);
|
|
133752
|
+
}
|
|
133753
|
+
return after.toReversed();
|
|
133754
|
+
}
|
|
133755
|
+
|
|
133756
|
+
// src/historyCommand.ts
|
|
133757
|
+
var READ_TIMEOUT_MS = 1e4;
|
|
133758
|
+
var MAX_PAGES = 3;
|
|
133759
|
+
var TEXT_LIMIT = 1e3;
|
|
133760
|
+
var makeHistoryCommand = (core) => {
|
|
133761
|
+
const { host, t, deliver } = core;
|
|
133762
|
+
return async (binding, command, chatKind) => {
|
|
133763
|
+
if (chatKind !== "private") {
|
|
133764
|
+
await deliver(binding, t("history.directOnly"));
|
|
133765
|
+
return;
|
|
133766
|
+
}
|
|
133767
|
+
const count = command.count;
|
|
133768
|
+
if (count === null) {
|
|
133769
|
+
await deliver(binding, t("history.usage", HISTORY_COUNTS));
|
|
133770
|
+
return;
|
|
133771
|
+
}
|
|
133772
|
+
const chatKey = chatKeyOf(binding);
|
|
133773
|
+
const threadId = chatOf(core.state, chatKey).threadId;
|
|
133774
|
+
if (threadId === null) {
|
|
133775
|
+
await deliver(binding, t("history.noSession"));
|
|
133776
|
+
return;
|
|
133777
|
+
}
|
|
133778
|
+
const switched = () => {
|
|
133779
|
+
if (chatOf(core.state, chatKey).threadId === threadId) return false;
|
|
133780
|
+
host.log.info("chat cancelled a history read after the session changed", { threadId });
|
|
133781
|
+
return true;
|
|
133782
|
+
};
|
|
133783
|
+
const adapter = core.adapterFor(binding.platform);
|
|
133784
|
+
if (adapter?.sendTyping !== void 0) {
|
|
133785
|
+
void adapter.sendTyping(binding).catch(() => {
|
|
133786
|
+
host.log.info("chat could not show history typing", { threadId });
|
|
133787
|
+
});
|
|
133788
|
+
}
|
|
133789
|
+
let text3;
|
|
133790
|
+
try {
|
|
133791
|
+
text3 = await withDeadline(READ_TIMEOUT_MS, async (signal) => {
|
|
133792
|
+
const threads = {
|
|
133793
|
+
messages: {
|
|
133794
|
+
list: async (input) => {
|
|
133795
|
+
signal.throwIfAborted();
|
|
133796
|
+
const page = await host.threads.messages.list({
|
|
133797
|
+
...input,
|
|
133798
|
+
textLimit: input.textLimit ?? TEXT_LIMIT
|
|
133799
|
+
});
|
|
133800
|
+
signal.throwIfAborted();
|
|
133801
|
+
return page;
|
|
133802
|
+
}
|
|
133803
|
+
}
|
|
133804
|
+
};
|
|
133805
|
+
let pages = 0;
|
|
133806
|
+
let reachedEnd = false;
|
|
133807
|
+
const bounded = {
|
|
133808
|
+
messages: {
|
|
133809
|
+
list: async (input) => {
|
|
133810
|
+
const page = await threads.messages.list(input);
|
|
133811
|
+
pages += 1;
|
|
133812
|
+
reachedEnd = page.nextCursor === null;
|
|
133813
|
+
return { ...page, nextCursor: pages >= MAX_PAGES ? null : page.nextCursor };
|
|
133814
|
+
}
|
|
133815
|
+
}
|
|
133816
|
+
};
|
|
133817
|
+
const messages = await recentMessages(
|
|
133818
|
+
bounded,
|
|
133819
|
+
threadId,
|
|
133820
|
+
count,
|
|
133821
|
+
(message) => message.role === "user" || message.role === "assistant" && !message.streaming
|
|
133822
|
+
);
|
|
133823
|
+
if (messages.length === 0) return t(reachedEnd ? "history.empty" : "history.noneRecent");
|
|
133824
|
+
const entries = [];
|
|
133825
|
+
for (const message of messages) {
|
|
133826
|
+
const attachments = await attachmentsOf(threads, threadId, message);
|
|
133827
|
+
const body = [
|
|
133828
|
+
message.text.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/gu, "").trim(),
|
|
133829
|
+
...message.textWindow?.nextOffset != null ? [t("history.truncated")] : [],
|
|
133830
|
+
...attachments.map(
|
|
133831
|
+
(attachment) => t(attachment.type === "image" ? "history.image" : "history.file")
|
|
133832
|
+
)
|
|
133833
|
+
].filter(Boolean).join("\n") || t("history.noText");
|
|
133834
|
+
const role = t(message.role === "user" ? "history.user" : "history.assistant");
|
|
133835
|
+
entries.push(`${entries.length + 1}. ${role}
|
|
133836
|
+
${body}`);
|
|
133837
|
+
}
|
|
133838
|
+
return [t("history.title", { count: messages.length }), ...entries].join("\n\n");
|
|
133839
|
+
});
|
|
133840
|
+
} catch {
|
|
133841
|
+
if (switched()) return;
|
|
133842
|
+
host.log.warn("chat could not read history", { threadId });
|
|
133843
|
+
text3 = t("history.failed");
|
|
133844
|
+
}
|
|
133845
|
+
if (switched()) return;
|
|
133846
|
+
await deliver(binding, text3);
|
|
133847
|
+
};
|
|
133848
|
+
};
|
|
133849
|
+
|
|
133850
|
+
// package.json
|
|
133851
|
+
var package_default = {
|
|
133852
|
+
name: "@ycodium-ai/plugin-im",
|
|
133853
|
+
version: "0.2.3252",
|
|
133854
|
+
description: "Talk to your agents from Telegram, WeCom, Lark, or WeChat (experimental).",
|
|
133855
|
+
keywords: [
|
|
133856
|
+
"im",
|
|
133857
|
+
"lark",
|
|
133858
|
+
"telegram",
|
|
133859
|
+
"wechat",
|
|
133860
|
+
"wecom",
|
|
133861
|
+
"wecom-app",
|
|
133862
|
+
"ycodium",
|
|
133863
|
+
"ycodium-plugin"
|
|
133864
|
+
],
|
|
133865
|
+
license: "UNLICENSED",
|
|
133866
|
+
files: [
|
|
133867
|
+
"dist",
|
|
133868
|
+
"assets",
|
|
133869
|
+
"locales"
|
|
133870
|
+
],
|
|
133871
|
+
type: "module",
|
|
133872
|
+
publishConfig: {
|
|
133873
|
+
access: "public"
|
|
133874
|
+
},
|
|
133875
|
+
scripts: {
|
|
133876
|
+
build: "node build.mjs",
|
|
133877
|
+
prepack: "pnpm run build",
|
|
133878
|
+
typecheck: "tsgo --noEmit && tsgo --noEmit -p tsconfig.ui.json",
|
|
133879
|
+
test: "vp test run"
|
|
133880
|
+
},
|
|
133881
|
+
devDependencies: {
|
|
133882
|
+
"@effect/vitest": "catalog:",
|
|
133883
|
+
"@larksuiteoapi/node-sdk": "^1.73.0",
|
|
133884
|
+
"@types/markdown-it": "^14.2.0",
|
|
133885
|
+
"@types/react": "~19.2.14",
|
|
133886
|
+
"@ycodium-ai/plugin-api": "workspace:*",
|
|
133887
|
+
effect: "catalog:",
|
|
133888
|
+
esbuild: "catalog:",
|
|
133889
|
+
"markdown-it": "^15.0.2",
|
|
133890
|
+
react: "19.2.6",
|
|
133891
|
+
"vite-plus": "catalog:",
|
|
133892
|
+
"ycodium-react-test-harness": "workspace:*"
|
|
133893
|
+
},
|
|
133894
|
+
ycodium: {
|
|
133895
|
+
plugin: "./dist/index.js",
|
|
133896
|
+
displayName: "Chat bridge",
|
|
133897
|
+
description: "Talk to your agents from Telegram, WeCom, Lark, or WeChat (experimental).",
|
|
133898
|
+
icon: "messageCircle",
|
|
133899
|
+
permissions: [
|
|
133900
|
+
{
|
|
133901
|
+
kind: "sessionProjection"
|
|
133902
|
+
},
|
|
133903
|
+
{
|
|
133904
|
+
kind: "threads.user"
|
|
133905
|
+
},
|
|
133906
|
+
{
|
|
133907
|
+
kind: "workspace.read"
|
|
133908
|
+
},
|
|
133909
|
+
{
|
|
133910
|
+
kind: "commands.dispatch",
|
|
133911
|
+
commands: [
|
|
133912
|
+
"thread.create",
|
|
133913
|
+
"thread.meta.update",
|
|
133914
|
+
"thread.external-messages.append",
|
|
133915
|
+
"thread.turn.start",
|
|
133916
|
+
"thread.turn.interrupt",
|
|
133917
|
+
"thread.approval.respond",
|
|
133918
|
+
"thread.user-input.respond",
|
|
133919
|
+
"thread.turn-intent.run",
|
|
133920
|
+
"thread.turn-intent.cancel",
|
|
133921
|
+
"thread.turn-queue.resume"
|
|
133922
|
+
]
|
|
133923
|
+
},
|
|
133924
|
+
{
|
|
133925
|
+
kind: "ui.seats",
|
|
133926
|
+
seats: [
|
|
133927
|
+
"settings.section"
|
|
133928
|
+
]
|
|
133929
|
+
}
|
|
133930
|
+
],
|
|
133931
|
+
ui: {
|
|
133932
|
+
assets: "./assets",
|
|
133933
|
+
entry: "ui.js"
|
|
133934
|
+
}
|
|
133935
|
+
}
|
|
133936
|
+
};
|
|
133937
|
+
|
|
133938
|
+
// src/versionCommand.ts
|
|
133939
|
+
var pluginVersion = package_default.version;
|
|
133940
|
+
var versionReply = (t, arg) => arg === "" ? t("version.current", { version: pluginVersion }) : t("version.usage");
|
|
133941
|
+
|
|
133495
133942
|
// src/commands.ts
|
|
133496
133943
|
var NEEDS_PROJECT_COMMANDS = /* @__PURE__ */ new Set(["sessions", "resume", "selectTeam", "selectThread"]);
|
|
133497
133944
|
var makeCommands = (core, deps) => {
|
|
@@ -133501,8 +133948,9 @@ var makeCommands = (core, deps) => {
|
|
|
133501
133948
|
const { showSessions, resumeSession } = deps.sessions;
|
|
133502
133949
|
const { handleModel, handlePlan } = deps.modelPlan;
|
|
133503
133950
|
const { openPanel } = deps;
|
|
133951
|
+
const handleHistory = makeHistoryCommand(core);
|
|
133504
133952
|
const targetOf = (binding) => chatOf(core.state, chatKeyOf(binding)).target;
|
|
133505
|
-
const executeCommand = async (binding, command, senderId = null) => {
|
|
133953
|
+
const executeCommand = async (binding, command, senderId = null, chatKind = void 0) => {
|
|
133506
133954
|
const chatKey = chatKeyOf(binding);
|
|
133507
133955
|
host.log.info("chat handled a command", {
|
|
133508
133956
|
bot: binding.displayName,
|
|
@@ -133553,6 +134001,9 @@ var makeCommands = (core, deps) => {
|
|
|
133553
134001
|
case "sessions":
|
|
133554
134002
|
await showSessions(binding, command.arg);
|
|
133555
134003
|
return;
|
|
134004
|
+
case "history":
|
|
134005
|
+
await handleHistory(binding, command, chatKind);
|
|
134006
|
+
return;
|
|
133556
134007
|
case "resume":
|
|
133557
134008
|
await resumeSession(binding, command.arg);
|
|
133558
134009
|
return;
|
|
@@ -133569,6 +134020,9 @@ var makeCommands = (core, deps) => {
|
|
|
133569
134020
|
bindChat(chatKey, null);
|
|
133570
134021
|
await deliver(binding, t("command.newSession"));
|
|
133571
134022
|
return;
|
|
134023
|
+
case "version":
|
|
134024
|
+
await deliver(binding, versionReply(t, command.arg));
|
|
134025
|
+
return;
|
|
133572
134026
|
case "status": {
|
|
133573
134027
|
const threadId = chatOf(core.state, chatKey).threadId ?? void 0;
|
|
133574
134028
|
const routed = targetOf(binding);
|
|
@@ -135185,56 +135639,6 @@ var deliveryFailure = (core, binding, threadId, turnId) => async (error) => {
|
|
|
135185
135639
|
}
|
|
135186
135640
|
};
|
|
135187
135641
|
|
|
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
135642
|
// src/conclusionDelivery.ts
|
|
135239
135643
|
var ALWAYS_OWED = () => true;
|
|
135240
135644
|
var makeConclusionDelivery = (core, anchors) => {
|
|
@@ -135604,16 +136008,6 @@ var workForMessage = (message) => ({
|
|
|
135604
136008
|
});
|
|
135605
136009
|
|
|
135606
136010
|
// 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
136011
|
var executeInboundRoute = async (core, actions, input) => {
|
|
135618
136012
|
const { current, message, route, work } = input;
|
|
135619
136013
|
const target2 = input.target;
|
|
@@ -135623,82 +136017,113 @@ var executeInboundRoute = async (core, actions, input) => {
|
|
|
135623
136017
|
switch (route.kind) {
|
|
135624
136018
|
case "command":
|
|
135625
136019
|
await complete();
|
|
135626
|
-
await actions.commands.executeCommand(
|
|
135627
|
-
|
|
135628
|
-
|
|
135629
|
-
|
|
135630
|
-
|
|
135631
|
-
|
|
135632
|
-
|
|
136020
|
+
await actions.commands.executeCommand(
|
|
136021
|
+
target2,
|
|
136022
|
+
route.command,
|
|
136023
|
+
message.senderId,
|
|
136024
|
+
message.chatKind
|
|
136025
|
+
);
|
|
136026
|
+
return { status: "settled" };
|
|
136027
|
+
case "project": {
|
|
136028
|
+
if (route.decision.kind !== "auto") {
|
|
136029
|
+
await complete();
|
|
136030
|
+
await actions.chatSetup.executeProjectDecision(target2, message, route.decision);
|
|
136031
|
+
return { status: "settled" };
|
|
136032
|
+
}
|
|
136033
|
+
const replies = [];
|
|
136034
|
+
const respond = async () => {
|
|
136035
|
+
for (const reply of replies) await reply();
|
|
136036
|
+
};
|
|
136037
|
+
if (await actions.chatSetup.executeProjectDecision(
|
|
136038
|
+
target2,
|
|
136039
|
+
message,
|
|
136040
|
+
route.decision,
|
|
136041
|
+
(reply) => replies.push(reply)
|
|
136042
|
+
)) {
|
|
136043
|
+
const outcome = await actions.continueMessage({
|
|
135633
136044
|
...core.bindingOf(current, message.chatId),
|
|
135634
136045
|
reply: target2.reply
|
|
135635
136046
|
});
|
|
135636
|
-
|
|
135637
|
-
|
|
135638
|
-
|
|
136047
|
+
if (outcome.status === "settled")
|
|
136048
|
+
return {
|
|
136049
|
+
status: "settled",
|
|
136050
|
+
respond: async () => {
|
|
136051
|
+
await respond();
|
|
136052
|
+
await outcome.respond?.();
|
|
136053
|
+
}
|
|
136054
|
+
};
|
|
136055
|
+
await respond();
|
|
136056
|
+
return outcome;
|
|
135639
136057
|
}
|
|
135640
|
-
|
|
136058
|
+
await complete();
|
|
136059
|
+
return { status: "settled", respond };
|
|
136060
|
+
}
|
|
135641
136061
|
case "question":
|
|
135642
136062
|
await complete();
|
|
135643
136063
|
await actions.interactions.questionFlow.answerText(route.answer);
|
|
135644
|
-
|
|
135645
|
-
return;
|
|
136064
|
+
return { status: "settled" };
|
|
135646
136065
|
case "approval":
|
|
135647
136066
|
await complete();
|
|
135648
136067
|
await actions.approvals.answerByToken(route.token);
|
|
135649
|
-
|
|
135650
|
-
return;
|
|
136068
|
+
return { status: "settled" };
|
|
135651
136069
|
case "unavailable":
|
|
135652
136070
|
await complete();
|
|
135653
|
-
|
|
135654
|
-
|
|
135655
|
-
|
|
135656
|
-
await actions.turns.receiveAttachmentsOnly(target2, message, complete);
|
|
136071
|
+
return { status: "settled" };
|
|
136072
|
+
case "attachments": {
|
|
136073
|
+
const outcome = await actions.turns.receiveAttachmentsOnly(target2, message, complete);
|
|
135657
136074
|
await complete();
|
|
135658
|
-
|
|
135659
|
-
|
|
136075
|
+
return outcome;
|
|
136076
|
+
}
|
|
135660
136077
|
case "team": {
|
|
135661
136078
|
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(
|
|
136079
|
+
const outcome = await actions.teams.startTeamGoal(
|
|
135665
136080
|
routed,
|
|
135666
136081
|
message,
|
|
135667
|
-
actions.acceptedWork(routed, message, work)
|
|
136082
|
+
actions.acceptedWork(routed, message, work, input.onAccepted)
|
|
135668
136083
|
);
|
|
135669
|
-
if (
|
|
136084
|
+
if (outcome.status === "settled") {
|
|
135670
136085
|
await complete();
|
|
135671
|
-
|
|
136086
|
+
return {
|
|
136087
|
+
status: "settled",
|
|
136088
|
+
respond: async () => {
|
|
136089
|
+
if (message.resources.length > 0)
|
|
136090
|
+
await core.deliver(routed, core.t("reply.attachmentsNoTeam"));
|
|
136091
|
+
await outcome.respond?.();
|
|
136092
|
+
}
|
|
136093
|
+
};
|
|
135672
136094
|
}
|
|
135673
|
-
|
|
136095
|
+
if (message.resources.length > 0)
|
|
136096
|
+
await core.deliver(routed, core.t("reply.attachmentsNoTeam"));
|
|
136097
|
+
return outcome;
|
|
135674
136098
|
}
|
|
135675
136099
|
case "turn":
|
|
135676
|
-
|
|
136100
|
+
return actions.openTurn(
|
|
135677
136101
|
{ ...target2, chatId: route.chatId, projectId: route.projectId },
|
|
135678
136102
|
message,
|
|
135679
|
-
work
|
|
136103
|
+
work,
|
|
136104
|
+
input.onAccepted
|
|
135680
136105
|
);
|
|
135681
|
-
return;
|
|
135682
136106
|
case "handoff": {
|
|
135683
|
-
const executeHandoff = async () => {
|
|
136107
|
+
const executeHandoff = async (onAccepted) => {
|
|
135684
136108
|
actions.inheritFromParent(current, route.chatId, message.chatId);
|
|
135685
136109
|
const child = {
|
|
135686
136110
|
...core.bindingOf(current, route.chatId),
|
|
135687
136111
|
projectId: route.projectId,
|
|
135688
136112
|
reply: target2.reply
|
|
135689
136113
|
};
|
|
135690
|
-
|
|
136114
|
+
return actions.openTurn(child, message, work, onAccepted);
|
|
135691
136115
|
};
|
|
135692
136116
|
if (input.queueChatId === route.chatId) {
|
|
135693
|
-
|
|
135694
|
-
return;
|
|
136117
|
+
return executeHandoff(input.onAccepted);
|
|
135695
136118
|
}
|
|
135696
|
-
|
|
135697
|
-
|
|
135698
|
-
|
|
135699
|
-
|
|
135700
|
-
|
|
135701
|
-
|
|
136119
|
+
return {
|
|
136120
|
+
status: "deferred",
|
|
136121
|
+
resume: () => actions.enqueueForChat(
|
|
136122
|
+
chatKeyOf({ rowId: current.rowId, chatId: route.chatId }),
|
|
136123
|
+
() => actions.run(executeHandoff),
|
|
136124
|
+
true
|
|
136125
|
+
)
|
|
136126
|
+
};
|
|
135702
136127
|
}
|
|
135703
136128
|
}
|
|
135704
136129
|
};
|
|
@@ -135875,16 +136300,14 @@ var makeInbound = (core, deps) => {
|
|
|
135875
136300
|
}));
|
|
135876
136301
|
return true;
|
|
135877
136302
|
};
|
|
135878
|
-
const turnAwayStranger = (target2, sender) => {
|
|
136303
|
+
const turnAwayStranger = async (target2, sender) => {
|
|
135879
136304
|
host.log.warn("chat ignored a message from someone not on the allow list", {
|
|
135880
136305
|
bot: target2.displayName,
|
|
135881
136306
|
sender
|
|
135882
136307
|
});
|
|
135883
136308
|
if (sender === null) return;
|
|
135884
136309
|
if (!notAllowedReplyCooldown.tryAcquire(`${target2.rowId}:${sender}`)) return;
|
|
135885
|
-
|
|
135886
|
-
await deliver(target2, t("reply.notAllowedYet", { id: sender }));
|
|
135887
|
-
});
|
|
136310
|
+
await deliver(target2, t("reply.notAllowedYet", { id: sender }));
|
|
135888
136311
|
};
|
|
135889
136312
|
const currentBot = (rowId) => bots().find((candidate) => candidate.rowId === rowId);
|
|
135890
136313
|
const inheritFromParent = (bot, chatId, parentChatId) => {
|
|
@@ -135911,24 +136334,24 @@ var makeInbound = (core, deps) => {
|
|
|
135911
136334
|
if (known === void 0) noteChatAlias(bot, message.chatAlias, message.chatId);
|
|
135912
136335
|
return known === void 0 || known === message.chatId ? message : { ...message, chatId: known };
|
|
135913
136336
|
};
|
|
135914
|
-
const acceptedWork = (speaker, message, work
|
|
135915
|
-
|
|
135916
|
-
|
|
135917
|
-
|
|
135918
|
-
|
|
135919
|
-
|
|
135920
|
-
|
|
135921
|
-
|
|
135922
|
-
|
|
135923
|
-
|
|
135924
|
-
|
|
135925
|
-
|
|
135926
|
-
|
|
135927
|
-
|
|
135928
|
-
|
|
136337
|
+
const acceptedWork = (speaker, message, work, onAccepted) => Object.assign(
|
|
136338
|
+
async (threadId, register) => {
|
|
136339
|
+
await markWorking(speaker, threadId, message.messageId);
|
|
136340
|
+
await register?.();
|
|
136341
|
+
if (work !== void 0) await inboundState.complete(speaker.rowId, work.key);
|
|
136342
|
+
},
|
|
136343
|
+
{ onAccepted }
|
|
136344
|
+
);
|
|
136345
|
+
const openTurn = (speaker, message, work, onAccepted) => startTurn(
|
|
136346
|
+
speaker,
|
|
136347
|
+
message,
|
|
136348
|
+
acceptedWork(speaker, message, work, onAccepted),
|
|
136349
|
+
work === void 0 ? void 0 : processingFor(inboundState, speaker.rowId, work, () => {
|
|
136350
|
+
replay.enqueue(speaker.rowId, work.key, Promise.resolve(true));
|
|
136351
|
+
})
|
|
136352
|
+
);
|
|
135929
136353
|
const resumeMessage = async (current, message, work, queueChatId = message.chatId) => {
|
|
135930
|
-
|
|
135931
|
-
const target2 = {
|
|
136354
|
+
let target2 = {
|
|
135932
136355
|
...bindingOf2(current, message.chatId),
|
|
135933
136356
|
reply: anchorOfMessage(adapterFor(current.platform), message)
|
|
135934
136357
|
};
|
|
@@ -135939,14 +136362,24 @@ var makeInbound = (core, deps) => {
|
|
|
135939
136362
|
const complete = async () => {
|
|
135940
136363
|
if (work !== void 0) await inboundState.complete(current.rowId, work.key);
|
|
135941
136364
|
};
|
|
136365
|
+
const identity2 = {
|
|
136366
|
+
platform: current.platform,
|
|
136367
|
+
rowId: current.rowId,
|
|
136368
|
+
chatId: message.chatId,
|
|
136369
|
+
messageId: message.messageId
|
|
136370
|
+
};
|
|
136371
|
+
const run2 = (execute2) => runInbound(core, target2, message.messageId, execute2, {
|
|
136372
|
+
rememberDeferred: () => deps.acknowledgements.rememberDeferred(identity2, target2),
|
|
136373
|
+
clearDeferred: () => deps.acknowledgements.clearDeferred(identity2),
|
|
136374
|
+
complete
|
|
136375
|
+
});
|
|
135942
136376
|
const continueMessage = async (target3) => {
|
|
135943
136377
|
const boundThread = chatOf(core.state, chatKey).threadId;
|
|
135944
136378
|
const answer = boundThread === null ? void 0 : questionFlow.textAnswer(chatKey, boundThread, message.text);
|
|
135945
136379
|
if (answer !== void 0) {
|
|
135946
136380
|
const route2 = { kind: "question", answer };
|
|
135947
136381
|
await saveRoute(route2);
|
|
135948
|
-
|
|
135949
|
-
return;
|
|
136382
|
+
return execute(route2, target3);
|
|
135950
136383
|
}
|
|
135951
136384
|
const project = await projectOrNull(host.projects, target3.projectId);
|
|
135952
136385
|
if (project === null || project.archivedAt != null) {
|
|
@@ -135958,14 +136391,16 @@ var makeInbound = (core, deps) => {
|
|
|
135958
136391
|
projectId: target3.projectId
|
|
135959
136392
|
});
|
|
135960
136393
|
}
|
|
135961
|
-
|
|
135962
|
-
|
|
135963
|
-
|
|
135964
|
-
|
|
135965
|
-
|
|
135966
|
-
|
|
135967
|
-
|
|
135968
|
-
|
|
136394
|
+
return {
|
|
136395
|
+
status: "settled",
|
|
136396
|
+
respond: async () => {
|
|
136397
|
+
if (archivedReplyCooldown.tryAcquire(chatKey))
|
|
136398
|
+
await deliver(
|
|
136399
|
+
target3,
|
|
136400
|
+
project === null ? t("reply.projectMissing") : t("reply.projectArchived", { title: project.title })
|
|
136401
|
+
);
|
|
136402
|
+
}
|
|
136403
|
+
};
|
|
135969
136404
|
}
|
|
135970
136405
|
const routed = targetOf(target3);
|
|
135971
136406
|
const attachmentsOnly = message.text.trim() === "" && message.resources.length > 0;
|
|
@@ -135973,20 +136408,21 @@ var makeInbound = (core, deps) => {
|
|
|
135973
136408
|
if (attachmentsOnly) {
|
|
135974
136409
|
await saveRoute({ kind: "unavailable" });
|
|
135975
136410
|
await complete();
|
|
135976
|
-
|
|
135977
|
-
|
|
135978
|
-
|
|
136411
|
+
return {
|
|
136412
|
+
status: "settled",
|
|
136413
|
+
respond: async () => {
|
|
136414
|
+
await deliver(target3, t("reply.attachmentsNoTeam"));
|
|
136415
|
+
}
|
|
136416
|
+
};
|
|
135979
136417
|
}
|
|
135980
136418
|
const route2 = { kind: "team", chatId: target3.chatId, projectId: target3.projectId };
|
|
135981
136419
|
await saveRoute(route2);
|
|
135982
|
-
|
|
135983
|
-
return;
|
|
136420
|
+
return execute(route2, target3);
|
|
135984
136421
|
}
|
|
135985
136422
|
if (attachmentsOnly) {
|
|
135986
136423
|
const route2 = { kind: "attachments" };
|
|
135987
136424
|
await saveRoute(route2);
|
|
135988
|
-
|
|
135989
|
-
return;
|
|
136425
|
+
return execute(route2, target3);
|
|
135990
136426
|
}
|
|
135991
136427
|
const branchChatId = hasWaitingAttachments(chatKey) ? void 0 : message.branchChatId;
|
|
135992
136428
|
const route = {
|
|
@@ -135995,62 +136431,65 @@ var makeInbound = (core, deps) => {
|
|
|
135995
136431
|
projectId: target3.projectId
|
|
135996
136432
|
};
|
|
135997
136433
|
await saveRoute(route);
|
|
135998
|
-
|
|
136434
|
+
return execute(route, target3);
|
|
135999
136435
|
};
|
|
136000
136436
|
const execute = (route, routedTarget = target2) => executeInboundRoute(
|
|
136001
136437
|
core,
|
|
136002
|
-
{ ...deps, openTurn, acceptedWork, inheritFromParent, continueMessage },
|
|
136003
|
-
{ current, message, target: routedTarget, route, work, queueChatId }
|
|
136438
|
+
{ ...deps, openTurn, acceptedWork, inheritFromParent, continueMessage, run: run2 },
|
|
136439
|
+
{ current, message, target: routedTarget, route, work, queueChatId, onAccepted }
|
|
136004
136440
|
);
|
|
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
|
-
|
|
136441
|
+
let onAccepted;
|
|
136442
|
+
const executeMessage = async (accepted) => {
|
|
136443
|
+
onAccepted = accepted;
|
|
136444
|
+
inheritFromParent(current, message.chatId, message.parentChatId);
|
|
136445
|
+
target2 = { ...bindingOf2(current, message.chatId), reply: target2.reply };
|
|
136446
|
+
if (work?.route !== void 0) return execute(work.route);
|
|
136447
|
+
if (!isAllowedSender(target2, message.senderId, message.chatKind)) {
|
|
136448
|
+
await saveRoute({ kind: "unavailable" });
|
|
136449
|
+
await complete();
|
|
136450
|
+
return { status: "settled", respond: () => turnAwayStranger(target2, message.senderId) };
|
|
136451
|
+
}
|
|
136452
|
+
const unsupportedType = message.unsupportedType;
|
|
136453
|
+
if (unsupportedType !== void 0) {
|
|
136454
|
+
await saveRoute({ kind: "unavailable" });
|
|
136455
|
+
await complete();
|
|
136456
|
+
return {
|
|
136457
|
+
status: "settled",
|
|
136458
|
+
respond: async () => {
|
|
136459
|
+
if (unsupportedReplyCooldown.tryAcquire(chatKey))
|
|
136460
|
+
await deliver(
|
|
136461
|
+
target2,
|
|
136462
|
+
unsupportedType === "folder" ? t("reply.unsupportedFolder") : unsupportedType === "voice" ? t("reply.unsupportedVoice") : t("reply.unsupportedType", { type: unsupportedType })
|
|
136463
|
+
);
|
|
136464
|
+
}
|
|
136465
|
+
};
|
|
136466
|
+
}
|
|
136467
|
+
const approval = openApprovalOf(core.state, chatKey);
|
|
136468
|
+
const token = approval === void 0 ? null : adapterFor(target2.platform)?.answerByText?.(target2, message.text, approval.options) ?? null;
|
|
136469
|
+
if (token !== null) {
|
|
136470
|
+
const route = { kind: "approval", token };
|
|
136471
|
+
await saveRoute(route);
|
|
136472
|
+
return execute(route);
|
|
136473
|
+
}
|
|
136474
|
+
const command = parseChatCommand({
|
|
136475
|
+
text: message.text,
|
|
136476
|
+
chinese: t.language === "zh-CN",
|
|
136477
|
+
hasImages: message.resources.length > 0
|
|
136478
|
+
});
|
|
136479
|
+
if (command.kind !== "message") {
|
|
136480
|
+
const route = { kind: "command", command };
|
|
136481
|
+
await saveRoute(route);
|
|
136482
|
+
return execute(route);
|
|
136483
|
+
}
|
|
136484
|
+
if (target2.projectId === "") {
|
|
136485
|
+
const decision = await decideProjectMessage(target2, message);
|
|
136486
|
+
const route = { kind: "project", decision };
|
|
136487
|
+
await saveRoute(route);
|
|
136488
|
+
return execute(route);
|
|
136489
|
+
}
|
|
136490
|
+
return continueMessage(target2);
|
|
136491
|
+
};
|
|
136492
|
+
await run2(executeMessage);
|
|
136054
136493
|
};
|
|
136055
136494
|
const inboundHandlersFor = (bot) => ({
|
|
136056
136495
|
onError: (message) => host.log.warn("chat inbound connection failed", {
|
|
@@ -136137,7 +136576,10 @@ var makeInbound = (core, deps) => {
|
|
|
136137
136576
|
inboundHandlersFor,
|
|
136138
136577
|
resumeMessage,
|
|
136139
136578
|
enqueueReplay,
|
|
136140
|
-
cancelReplay:
|
|
136579
|
+
cancelReplay: (rowId) => {
|
|
136580
|
+
replay.cancelReplay(rowId);
|
|
136581
|
+
track(deps.acknowledgements.stopDeferred(rowId));
|
|
136582
|
+
},
|
|
136141
136583
|
stop: async () => {
|
|
136142
136584
|
accepting = false;
|
|
136143
136585
|
replay.stop();
|
|
@@ -137410,7 +137852,7 @@ var ConsoleError = class extends Error {
|
|
|
137410
137852
|
this.retryAfterMs = extra.retryAfterMs;
|
|
137411
137853
|
}
|
|
137412
137854
|
};
|
|
137413
|
-
var
|
|
137855
|
+
var withDeadline2 = async (deps, ms, run2) => {
|
|
137414
137856
|
const controller = new AbortController();
|
|
137415
137857
|
const timer = new AbortController();
|
|
137416
137858
|
let timedOut = false;
|
|
@@ -137437,7 +137879,7 @@ var withDeadline = async (deps, ms, run2) => {
|
|
|
137437
137879
|
deps.signal.removeEventListener("abort", onParentAbort);
|
|
137438
137880
|
}
|
|
137439
137881
|
};
|
|
137440
|
-
var guarded =
|
|
137882
|
+
var guarded = withDeadline2;
|
|
137441
137883
|
var sleepOrAbort = async (deps, ms) => {
|
|
137442
137884
|
try {
|
|
137443
137885
|
await deps.clock.sleep(ms, deps.signal);
|
|
@@ -137469,7 +137911,7 @@ var retryAfterMs = (response) => {
|
|
|
137469
137911
|
};
|
|
137470
137912
|
var openConsole = async (deps, jar) => {
|
|
137471
137913
|
const pageUrl = `${CONSOLE_ORIGIN}${CONSOLE_APP_PATH}`;
|
|
137472
|
-
const loadPage = () =>
|
|
137914
|
+
const loadPage = () => withDeadline2(deps, TIMEOUT_MS.page, async (signal) => {
|
|
137473
137915
|
const { response, finalUrl } = await jar.fetch(deps.fetch, pageUrl, {
|
|
137474
137916
|
method: "GET",
|
|
137475
137917
|
headers: { accept: "text/html,application/xhtml+xml" },
|
|
@@ -137498,7 +137940,7 @@ var openConsole = async (deps, jar) => {
|
|
|
137498
137940
|
calls += 1;
|
|
137499
137941
|
const started = deps.clock.now();
|
|
137500
137942
|
try {
|
|
137501
|
-
const result2 = await
|
|
137943
|
+
const result2 = await withDeadline2(deps, timeoutOf(kind), async (signal) => {
|
|
137502
137944
|
const { response } = await jar.fetch(deps.fetch, `${origin}${path}`, {
|
|
137503
137945
|
method: "POST",
|
|
137504
137946
|
headers: {
|
|
@@ -145068,22 +145510,6 @@ var larkInboundPersistence = (contextFor) => ({
|
|
|
145068
145510
|
}
|
|
145069
145511
|
});
|
|
145070
145512
|
|
|
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
145513
|
// src/boundedSeen.ts
|
|
145088
145514
|
var makeBoundedSeen = (limit) => {
|
|
145089
145515
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -145229,7 +145655,7 @@ var errorReason = (error) => {
|
|
|
145229
145655
|
};
|
|
145230
145656
|
var loadReplyReference = async (load) => {
|
|
145231
145657
|
try {
|
|
145232
|
-
return await
|
|
145658
|
+
return await withDeadline(LOAD_TIMEOUT_MS, load) ?? { unavailableReason: "not-found" };
|
|
145233
145659
|
} catch (error) {
|
|
145234
145660
|
return { unavailableReason: errorReason(error) };
|
|
145235
145661
|
}
|
|
@@ -145248,7 +145674,7 @@ var makeLookup = (rowId, load) => {
|
|
|
145248
145674
|
if (known !== void 0 && Date.now() - known.at < CACHE_MS) return known.value;
|
|
145249
145675
|
const pending = inflight.get(key2);
|
|
145250
145676
|
if (pending !== void 0) return pending;
|
|
145251
|
-
const reading =
|
|
145677
|
+
const reading = withDeadline(LOOKUP_TIMEOUT_MS, (signal) => load(id, signal)).catch(() => null).then((value2) => {
|
|
145252
145678
|
cache.set(key2, { value: value2, at: Date.now() });
|
|
145253
145679
|
return value2;
|
|
145254
145680
|
}).finally(() => inflight.delete(key2));
|
|
@@ -145428,7 +145854,7 @@ ${indent} `)}`;
|
|
|
145428
145854
|
};
|
|
145429
145855
|
var loadMergeForward = async (message, deps) => {
|
|
145430
145856
|
try {
|
|
145431
|
-
const items = await
|
|
145857
|
+
const items = await withDeadline(1e4, async (signal) => {
|
|
145432
145858
|
const token = await deps.tenantToken();
|
|
145433
145859
|
signal.throwIfAborted();
|
|
145434
145860
|
return fetchMergeForwardMessages({
|
|
@@ -145848,6 +146274,8 @@ var en_default = {
|
|
|
145848
146274
|
sendingFile: "Sending {{name}}:",
|
|
145849
146275
|
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
146276
|
received: "Got it, working on it.",
|
|
146277
|
+
inboundFailed: "This message couldn't be handled. Please send it again later.",
|
|
146278
|
+
inboundDeferred: "No need to send this again \u2014 it will be handled automatically the next time the machine starts.",
|
|
145851
146279
|
welcome: "Connected. Send text or images to get started, or send /help to see the available commands."
|
|
145852
146280
|
},
|
|
145853
146281
|
approval: {
|
|
@@ -145924,17 +146352,23 @@ var en_default = {
|
|
|
145924
146352
|
project: "Project: {{title}}",
|
|
145925
146353
|
noProject: "No project picked yet. Send /repo to pick one."
|
|
145926
146354
|
},
|
|
146355
|
+
version: {
|
|
146356
|
+
current: "Ycodium Chat bridge v{{version}}",
|
|
146357
|
+
usage: "Usage: /version (no arguments)."
|
|
146358
|
+
},
|
|
145927
146359
|
help: {
|
|
145928
146360
|
title: "Commands:",
|
|
145929
146361
|
continue: "\xB7 /continue \u2014 resume sending after /stop or a failure paused it; the waiting messages go out",
|
|
145930
146362
|
stop: "\xB7 /stop \u2014 stop the turn that is running; the session stays",
|
|
145931
146363
|
status: "\xB7 /status \u2014 what is going on right now",
|
|
146364
|
+
version: "\xB7 /version \u2014 the chat bridge's version (no arguments)",
|
|
145932
146365
|
new: "\xB7 /new \u2014 forget the current session; the next message starts a new one",
|
|
145933
146366
|
team: "\xB7 /team \u2014 give this project's team a goal with each message; use /repo to pick the project first",
|
|
145934
146367
|
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.",
|
|
146368
|
+
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
146369
|
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
146370
|
resume: "\xB7 /resume number-or-id-prefix \u2014 switch sessions; one from another project switches the project too",
|
|
146371
|
+
history: "\xB7 /history [count] \u2014 preview recent messages in the current session, in private chats only (default {{defaultCount}}, maximum {{maxCount}})",
|
|
145938
146372
|
model: "\xB7 /model \u2014 see the model this chat uses; /model number or /model instance/model switches it",
|
|
145939
146373
|
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
146374
|
plan: "\xB7 /plan \u2014 toggle plan mode (the agent proposes a plan instead of acting); /plan on, /plan off set it",
|
|
@@ -145943,6 +146377,21 @@ var en_default = {
|
|
|
145943
146377
|
group: "\xB7 /group name \u2014 Lark only: the bot creates a group and adds you (bots on other platforms cannot)",
|
|
145944
146378
|
syncNote: "\xB7 After a private chat attaches a session, web user text and final assistant text sync here (groups never sync)."
|
|
145945
146379
|
},
|
|
146380
|
+
history: {
|
|
146381
|
+
usage: "Usage: /history [count] \u2014 1 to {{maxCount}} (larger numbers count as {{maxCount}}), default {{defaultCount}}.",
|
|
146382
|
+
directOnly: "In a group this would show the session to everyone. Send /history in a private chat with the bot.",
|
|
146383
|
+
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.",
|
|
146384
|
+
empty: "No messages to show in this session yet.",
|
|
146385
|
+
noneRecent: "Nothing to show among this session's most recent messages (older ones were not checked).",
|
|
146386
|
+
failed: "Could not read the recent messages. Try again in a moment.",
|
|
146387
|
+
title: "Recent messages in this session ({{count}}):",
|
|
146388
|
+
user: "User",
|
|
146389
|
+
assistant: "Assistant",
|
|
146390
|
+
image: "[Image]",
|
|
146391
|
+
file: "[File]",
|
|
146392
|
+
noText: "[No previewable text]",
|
|
146393
|
+
truncated: "[Remaining text omitted]"
|
|
146394
|
+
},
|
|
145946
146395
|
sessions: {
|
|
145947
146396
|
title: "This project's sessions ({{count}}):",
|
|
145948
146397
|
empty: "This bot has not opened any session in this project yet. Send a message to start one.",
|
|
@@ -146755,6 +147204,8 @@ var zh_CN_default = {
|
|
|
146755
147204
|
sendingFile: "\u6B63\u5728\u53D1\u9001 {{name}}\uFF1A",
|
|
146756
147205
|
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
147206
|
received: "\u6536\u5230\uFF0C\u5728\u5904\u7406\u3002",
|
|
147207
|
+
inboundFailed: "\u8FD9\u6761\u6D88\u606F\u5904\u7406\u65F6\u51FA\u4E86\u9519\uFF0C\u8BF7\u7A0D\u540E\u91CD\u53D1\u3002",
|
|
147208
|
+
inboundDeferred: "\u4E0D\u7528\u91CD\u53D1\uFF1A\u673A\u5668\u4E0B\u6B21\u542F\u52A8\u65F6\u4F1A\u81EA\u52A8\u5904\u7406\u8FD9\u6761\u6D88\u606F\u3002",
|
|
146758
147209
|
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
147210
|
},
|
|
146760
147211
|
approval: {
|
|
@@ -146831,17 +147282,23 @@ var zh_CN_default = {
|
|
|
146831
147282
|
project: "\u9879\u76EE\uFF1A{{title}}",
|
|
146832
147283
|
noProject: "\u8FD8\u6CA1\u9009\u9879\u76EE\u3002\u53D1 /repo \u9009\u4E00\u4E2A\u3002"
|
|
146833
147284
|
},
|
|
147285
|
+
version: {
|
|
147286
|
+
current: "Ycodium \u804A\u5929\u6865 v{{version}}",
|
|
147287
|
+
usage: "\u7528\u6CD5\uFF1A/version\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09\u3002"
|
|
147288
|
+
},
|
|
146834
147289
|
help: {
|
|
146835
147290
|
title: "\u80FD\u7528\u7684\u547D\u4EE4\uFF1A",
|
|
146836
147291
|
continue: "\xB7 /continue \u2014\u2014 /stop \u6216\u51FA\u9519\u6682\u505C\u4E86\u53D1\u9001\u4E4B\u540E\uFF0C\u7528\u5B83\u6062\u590D\uFF0C\u6392\u7740\u7684\u6D88\u606F\u7EE7\u7EED\u53D1\u51FA",
|
|
146837
147292
|
stop: "\xB7 /stop \u2014\u2014 \u505C\u6389\u6B63\u5728\u8DD1\u7684\u8FD9\u4E00\u8F6E\uFF0C\u4F1A\u8BDD\u7559\u7740",
|
|
146838
147293
|
status: "\xB7 /status \u2014\u2014 \u73B0\u5728\u5728\u5E72\u4EC0\u4E48",
|
|
147294
|
+
version: "\xB7 /version \u2014\u2014 \u804A\u5929\u6865\u7684\u7248\u672C\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",
|
|
146839
147295
|
new: "\xB7 /new \u2014\u2014 \u5FD8\u6389\u5F53\u524D\u4F1A\u8BDD\uFF0C\u4E0B\u4E00\u53E5\u5F00\u65B0\u7684",
|
|
146840
147296
|
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
147297
|
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",
|
|
147298
|
+
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
147299
|
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
147300
|
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",
|
|
147301
|
+
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
147302
|
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
147303
|
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
147304
|
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 +147307,21 @@ var zh_CN_default = {
|
|
|
146850
147307
|
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
147308
|
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
147309
|
},
|
|
147310
|
+
history: {
|
|
147311
|
+
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",
|
|
147312
|
+
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",
|
|
147313
|
+
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",
|
|
147314
|
+
empty: "\u5F53\u524D\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u80FD\u67E5\u770B\u7684\u6D88\u606F\u3002",
|
|
147315
|
+
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",
|
|
147316
|
+
failed: "\u6CA1\u80FD\u8BFB\u53D6\u6700\u8FD1\u7684\u6D88\u606F\uFF0C\u7A0D\u540E\u518D\u8BD5\u3002",
|
|
147317
|
+
title: "\u5F53\u524D\u4F1A\u8BDD\u6700\u8FD1\u7684\u6D88\u606F\uFF08{{count}} \u6761\uFF09\uFF1A",
|
|
147318
|
+
user: "\u7528\u6237",
|
|
147319
|
+
assistant: "\u52A9\u624B",
|
|
147320
|
+
image: "[\u56FE\u7247]",
|
|
147321
|
+
file: "[\u6587\u4EF6]",
|
|
147322
|
+
noText: "[\u6CA1\u6709\u53EF\u9884\u89C8\u7684\u6587\u5B57]",
|
|
147323
|
+
truncated: "[\u5176\u4F59\u6587\u5B57\u5DF2\u7701\u7565]"
|
|
147324
|
+
},
|
|
146853
147325
|
sessions: {
|
|
146854
147326
|
title: "\u672C\u9879\u76EE\u7684\u4F1A\u8BDD\uFF08{{count}} \u6761\uFF09\uFF1A",
|
|
146855
147327
|
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 +148076,7 @@ var CREATE_INTERVAL_MS = 1100;
|
|
|
147604
148076
|
var syncLarkSlashCommands = async (input) => {
|
|
147605
148077
|
const request = async (method, id, body) => {
|
|
147606
148078
|
input.signal.throwIfAborted();
|
|
147607
|
-
return
|
|
148079
|
+
return withDeadline(REQUEST_TIMEOUT_MS, async (timeout2) => {
|
|
147608
148080
|
const signal = AbortSignal.any([input.signal, timeout2]);
|
|
147609
148081
|
const response = await input.http(
|
|
147610
148082
|
id === void 0 ? ENDPOINT : `${ENDPOINT}/${encodeURIComponent(id)}`,
|
|
@@ -147681,7 +148153,7 @@ var makeLarkSlashCommands = (deps) => {
|
|
|
147681
148153
|
const run2 = app.settled.then(async () => {
|
|
147682
148154
|
if (signal.aborted) return;
|
|
147683
148155
|
try {
|
|
147684
|
-
const token = await
|
|
148156
|
+
const token = await withDeadline(
|
|
147685
148157
|
REQUEST_TIMEOUT_MS,
|
|
147686
148158
|
(timeout2) => deps.tenantToken(bot, AbortSignal.any([signal, timeout2]))
|
|
147687
148159
|
);
|
|
@@ -148159,14 +148631,14 @@ var makeLarkAdapter = (deps) => {
|
|
|
148159
148631
|
}),
|
|
148160
148632
|
clearAcknowledge: async (binding, messageId, ackId, outcome) => {
|
|
148161
148633
|
const token = await tenantToken(binding);
|
|
148162
|
-
await
|
|
148634
|
+
await withDeadline(
|
|
148163
148635
|
LARK_REACTION_TIMEOUT_MS,
|
|
148164
148636
|
(signal) => removeReaction({ http: deps.http, token, messageId, reactionId: ackId, signal })
|
|
148165
148637
|
);
|
|
148166
148638
|
const emojiType = outcome === "done" ? LARK_DONE_REACTION : outcome === "failed" ? LARK_FAILED_REACTION : null;
|
|
148167
148639
|
if (emojiType === null) return;
|
|
148168
148640
|
try {
|
|
148169
|
-
await
|
|
148641
|
+
await withDeadline(
|
|
148170
148642
|
LARK_REACTION_TIMEOUT_MS,
|
|
148171
148643
|
(signal) => addReaction({ http: deps.http, token, messageId, emojiType, signal })
|
|
148172
148644
|
);
|
|
@@ -148436,7 +148908,7 @@ var outcomeOfSession = (status) => {
|
|
|
148436
148908
|
var THREAD_PROJECT_CACHE_LIMIT = 256;
|
|
148437
148909
|
var makeNotifications = (core, deps) => {
|
|
148438
148910
|
const { host, adapterFor, bindingForChatKey, ready } = core;
|
|
148439
|
-
const { takeWorking } = deps;
|
|
148911
|
+
const { takeWorking, stopTypingFor } = deps;
|
|
148440
148912
|
const { turnCards } = deps.replyCards;
|
|
148441
148913
|
const { failures, conclusions, delivery } = deps;
|
|
148442
148914
|
const { recoverConclusion, recoverConclusions } = makeConclusionRecovery(
|
|
@@ -148489,6 +148961,7 @@ var makeNotifications = (core, deps) => {
|
|
|
148489
148961
|
const threadId = payload.threadId;
|
|
148490
148962
|
if (typeof threadId !== "string") return;
|
|
148491
148963
|
if (payload.session?.activeTurnId != null) return;
|
|
148964
|
+
stopTypingFor(threadId);
|
|
148492
148965
|
const outcome = outcomeOfSession(payload.session?.status);
|
|
148493
148966
|
const said = threadsWithSomethingToReport.delete(threadId);
|
|
148494
148967
|
await ready;
|
|
@@ -148533,6 +149006,7 @@ var makeNotifications = (core, deps) => {
|
|
|
148533
149006
|
host.events.on("thread.failed", async (event) => {
|
|
148534
149007
|
const threadId = event.threadId;
|
|
148535
149008
|
if (threadId === null) return;
|
|
149009
|
+
stopTypingFor(threadId);
|
|
148536
149010
|
threadsWithSomethingToReport.delete(threadId);
|
|
148537
149011
|
await ready;
|
|
148538
149012
|
const targets = targetsForProject(threadId, await projectOfThread(threadId));
|
|
@@ -150072,6 +150546,7 @@ var makeTeamGoals = (core) => {
|
|
|
150072
150546
|
};
|
|
150073
150547
|
const startTeamGoal = async (binding, message, accepted) => {
|
|
150074
150548
|
let goal;
|
|
150549
|
+
let confirmConsumed;
|
|
150075
150550
|
try {
|
|
150076
150551
|
const requestId = teamGoalRequestId(binding, message.messageId);
|
|
150077
150552
|
const topicRoot = await message.topicRootForSession?.(requestId);
|
|
@@ -150086,24 +150561,30 @@ var makeTeamGoals = (core) => {
|
|
|
150086
150561
|
}
|
|
150087
150562
|
});
|
|
150088
150563
|
if (isRecord3(result2) && result2._tag === "TeamGoalRejection") {
|
|
150089
|
-
|
|
150090
|
-
|
|
150091
|
-
|
|
150092
|
-
|
|
150093
|
-
|
|
150094
|
-
|
|
150095
|
-
|
|
150564
|
+
const key2 = result2.code === "no-roster" ? "team.noRoster" : result2.code === "invalid-goal" ? "team.invalidGoal" : "team.startFailed";
|
|
150565
|
+
return {
|
|
150566
|
+
status: "settled",
|
|
150567
|
+
respond: async () => {
|
|
150568
|
+
await deliver(binding, t(key2));
|
|
150569
|
+
}
|
|
150570
|
+
};
|
|
150096
150571
|
}
|
|
150097
150572
|
if (!isRecord3(result2) || typeof result2.leadThreadId !== "string" || result2.leadThreadId === "" || result2.leadName !== null && typeof result2.leadName !== "string") {
|
|
150098
150573
|
throw new Error("team startGoal returned an invalid result");
|
|
150099
150574
|
}
|
|
150100
|
-
topicRoot?.confirmConsumed();
|
|
150101
150575
|
goal = { leadThreadId: result2.leadThreadId, leadName: result2.leadName };
|
|
150576
|
+
confirmConsumed = () => topicRoot?.confirmConsumed();
|
|
150102
150577
|
} catch (error) {
|
|
150103
150578
|
host.log.warn("chat could not start the team goal", { error: describeError(error) });
|
|
150104
|
-
|
|
150105
|
-
|
|
150579
|
+
return {
|
|
150580
|
+
status: "settled",
|
|
150581
|
+
respond: async () => {
|
|
150582
|
+
await deliver(binding, t("team.startFailed"));
|
|
150583
|
+
}
|
|
150584
|
+
};
|
|
150106
150585
|
}
|
|
150586
|
+
accepted?.onAccepted?.();
|
|
150587
|
+
confirmConsumed();
|
|
150107
150588
|
await commitDurably("team-goal-started", {
|
|
150108
150589
|
chatKey: chatKeyOf(binding),
|
|
150109
150590
|
threadId: goal.leadThreadId
|
|
@@ -150117,7 +150598,7 @@ var makeTeamGoals = (core) => {
|
|
|
150117
150598
|
bot: binding.displayName,
|
|
150118
150599
|
threadId: goal.leadThreadId
|
|
150119
150600
|
});
|
|
150120
|
-
return
|
|
150601
|
+
return { status: "started", claimsPlaceholder: false };
|
|
150121
150602
|
};
|
|
150122
150603
|
return { hasRosterFor, startTeamGoal };
|
|
150123
150604
|
};
|
|
@@ -151350,12 +151831,11 @@ var dispatchTurnWithReceipt = async (host, input, options) => {
|
|
|
151350
151831
|
var DELAYS = [3e4, 12e4, 6e5];
|
|
151351
151832
|
var MAX_DISPATCH_ATTEMPTS = DELAYS.length + 1;
|
|
151352
151833
|
var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried, messageText2, firstAttachmentName) => {
|
|
151353
|
-
if (deps.signal.aborted) return
|
|
151834
|
+
if (deps.signal.aborted) return { status: "deferred" };
|
|
151354
151835
|
const previous = inbox?.entry?.attempts ?? 0;
|
|
151355
151836
|
const attempt = Math.min(previous + 1, MAX_DISPATCH_ATTEMPTS);
|
|
151356
151837
|
const nextAttemptAt = inbox?.entry?.nextAttemptAt;
|
|
151357
151838
|
const incremented = previous < MAX_DISPATCH_ATTEMPTS;
|
|
151358
|
-
if (incremented) await inbox?.saveRetry(attempt, nextAttemptAt);
|
|
151359
151839
|
const reference2 = dispatchFailureReference(input.requestId);
|
|
151360
151840
|
const notify = async (text3) => {
|
|
151361
151841
|
try {
|
|
@@ -151368,6 +151848,18 @@ var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried
|
|
|
151368
151848
|
});
|
|
151369
151849
|
}
|
|
151370
151850
|
};
|
|
151851
|
+
if (incremented) {
|
|
151852
|
+
try {
|
|
151853
|
+
await inbox?.saveRetry(attempt, nextAttemptAt);
|
|
151854
|
+
} catch (error) {
|
|
151855
|
+
core.host.log.warn("chat could not save a dispatch attempt; leaving it for replay", {
|
|
151856
|
+
threadId: input.threadId,
|
|
151857
|
+
requestId: input.requestId,
|
|
151858
|
+
error: describeError(error)
|
|
151859
|
+
});
|
|
151860
|
+
return { status: "settled", respond: () => notify(core.t("reply.inboundDeferred")) };
|
|
151861
|
+
}
|
|
151862
|
+
}
|
|
151371
151863
|
try {
|
|
151372
151864
|
if (incremented) {
|
|
151373
151865
|
await dispatchTurnWithReceipt(core.host, input, {
|
|
@@ -151376,14 +151868,14 @@ var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried
|
|
|
151376
151868
|
});
|
|
151377
151869
|
} else {
|
|
151378
151870
|
const status = await confirmTurnReceipt(core.host, input);
|
|
151379
|
-
if (deps.signal.aborted) return
|
|
151871
|
+
if (deps.signal.aborted) return { status: "deferred" };
|
|
151380
151872
|
if (status === "absent") throw new Error("attempt budget exhausted; receipt absent");
|
|
151381
151873
|
}
|
|
151382
|
-
return
|
|
151874
|
+
return { status: "accepted" };
|
|
151383
151875
|
} catch (error) {
|
|
151384
151876
|
if (deps.signal.aborted) {
|
|
151385
151877
|
if (incremented) await inbox?.saveRetry(previous, nextAttemptAt);
|
|
151386
|
-
return
|
|
151878
|
+
return { status: "deferred" };
|
|
151387
151879
|
}
|
|
151388
151880
|
const delay2 = DELAYS[attempt - 1];
|
|
151389
151881
|
if (!(error instanceof TurnDispatchRejected) && delay2 !== void 0 && inbox?.entry !== void 0) {
|
|
@@ -151397,7 +151889,7 @@ var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried
|
|
|
151397
151889
|
error: describeError(error)
|
|
151398
151890
|
});
|
|
151399
151891
|
if (attempt === 1) await notify(deps.failures.forDispatchRetry(input.requestId));
|
|
151400
|
-
return
|
|
151892
|
+
return { status: "deferred" };
|
|
151401
151893
|
}
|
|
151402
151894
|
const redactor = botRedactor(
|
|
151403
151895
|
core.adapterFor(binding.platform)?.columns ?? [],
|
|
@@ -151416,10 +151908,12 @@ var makeTurnRetry = (core, deps) => async (binding, input, inbox, restoreCarried
|
|
|
151416
151908
|
const textExcerpt = messageText2.trim();
|
|
151417
151909
|
const attachmentName = firstAttachmentName?.trim() ?? "";
|
|
151418
151910
|
const identifyingNotice = textExcerpt !== "" ? deps.failures.forDispatchFailureQuoted(input.requestId, textExcerpt) : attachmentName !== "" ? deps.failures.forDispatchFailureAttachment(input.requestId, attachmentName) : void 0;
|
|
151419
|
-
|
|
151420
|
-
|
|
151421
|
-
|
|
151422
|
-
|
|
151911
|
+
return {
|
|
151912
|
+
status: "settled",
|
|
151913
|
+
respond: () => notify(
|
|
151914
|
+
binding.reply === void 0 && attempt > 1 && identifyingNotice !== void 0 ? identifyingNotice : failureNotice
|
|
151915
|
+
)
|
|
151916
|
+
};
|
|
151423
151917
|
}
|
|
151424
151918
|
};
|
|
151425
151919
|
|
|
@@ -151473,6 +151967,7 @@ var makeTurns = (core, deps) => {
|
|
|
151473
151967
|
const ensureThread = async (binding, message) => {
|
|
151474
151968
|
const chatKey = chatKeyOf(binding);
|
|
151475
151969
|
let threadId = chatOf(core.state, chatKey).threadId ?? void 0;
|
|
151970
|
+
let dropped = false;
|
|
151476
151971
|
if (threadId !== void 0 && !await threadStillUsable(binding, threadId)) {
|
|
151477
151972
|
host.log.info("chat dropped a saved thread that is no longer usable", {
|
|
151478
151973
|
bot: binding.displayName,
|
|
@@ -151480,7 +151975,7 @@ var makeTurns = (core, deps) => {
|
|
|
151480
151975
|
});
|
|
151481
151976
|
bindChat(chatKey, null);
|
|
151482
151977
|
threadId = void 0;
|
|
151483
|
-
|
|
151978
|
+
dropped = true;
|
|
151484
151979
|
}
|
|
151485
151980
|
if (threadId !== void 0) return threadId;
|
|
151486
151981
|
const project = await projectOrNull2(host.projects, binding.projectId);
|
|
@@ -151489,7 +151984,13 @@ var makeTurns = (core, deps) => {
|
|
|
151489
151984
|
bot: binding.displayName,
|
|
151490
151985
|
projectId: binding.projectId
|
|
151491
151986
|
});
|
|
151492
|
-
return
|
|
151987
|
+
return {
|
|
151988
|
+
status: "settled",
|
|
151989
|
+
respond: async () => {
|
|
151990
|
+
if (dropped) await deliver(binding, t("reply.threadGone"));
|
|
151991
|
+
await deliver(binding, t("reply.projectMissing"));
|
|
151992
|
+
}
|
|
151993
|
+
};
|
|
151493
151994
|
}
|
|
151494
151995
|
const modelSelection = await resolveDefaultModel(
|
|
151495
151996
|
binding,
|
|
@@ -151502,8 +152003,13 @@ var makeTurns = (core, deps) => {
|
|
|
151502
152003
|
bot: binding.displayName,
|
|
151503
152004
|
projectId: binding.projectId
|
|
151504
152005
|
});
|
|
151505
|
-
|
|
151506
|
-
|
|
152006
|
+
return {
|
|
152007
|
+
status: "settled",
|
|
152008
|
+
respond: async () => {
|
|
152009
|
+
if (dropped) await deliver(binding, t("reply.threadGone"));
|
|
152010
|
+
await deliver(binding, t("reply.noDefaultModel", { title: project.title }));
|
|
152011
|
+
}
|
|
152012
|
+
};
|
|
151507
152013
|
}
|
|
151508
152014
|
const createdThreadId = identity2("thread", binding, message);
|
|
151509
152015
|
const presetId = await resolveDefaultPreset(chatOf(core.state, chatKey).preset, binding, host);
|
|
@@ -151526,17 +152032,19 @@ var makeTurns = (core, deps) => {
|
|
|
151526
152032
|
openedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
151527
152033
|
});
|
|
151528
152034
|
rememberThreadProject(createdThreadId, binding.projectId);
|
|
152035
|
+
if (dropped) await deliver(binding, t("reply.threadGone"));
|
|
151529
152036
|
return createdThreadId;
|
|
151530
152037
|
};
|
|
151531
152038
|
const startTurn = async (binding, message, accepted, inbox) => {
|
|
151532
152039
|
const chatKey = chatKeyOf(binding);
|
|
151533
152040
|
const text3 = message.text;
|
|
151534
152041
|
const replayed = inbox?.replayed === true || (inbox?.entry?.attempts ?? 0) > 0;
|
|
151535
|
-
const
|
|
151536
|
-
if (
|
|
152042
|
+
const prepared = inbox?.entry?.threadId ?? await ensureThread(binding, message);
|
|
152043
|
+
if (typeof prepared !== "string") {
|
|
151537
152044
|
await inbox?.complete();
|
|
151538
|
-
return
|
|
152045
|
+
return prepared;
|
|
151539
152046
|
}
|
|
152047
|
+
const threadId = prepared;
|
|
151540
152048
|
await inbox?.saveThread(threadId);
|
|
151541
152049
|
const topicRoot = await message.topicRootForSession?.(threadId);
|
|
151542
152050
|
const requestId = identity2("turn", binding, message);
|
|
@@ -151570,11 +152078,33 @@ var makeTurns = (core, deps) => {
|
|
|
151570
152078
|
stored: [...saved.stored, ...own.attachments],
|
|
151571
152079
|
notes: [...saved.notes, ...own.notes]
|
|
151572
152080
|
};
|
|
151573
|
-
await inbox?.saveAttachments(saved);
|
|
151574
152081
|
} catch (error) {
|
|
151575
152082
|
restoreCarried();
|
|
151576
152083
|
throw error;
|
|
151577
152084
|
}
|
|
152085
|
+
try {
|
|
152086
|
+
await inbox?.saveAttachments(saved);
|
|
152087
|
+
} catch (error) {
|
|
152088
|
+
restoreCarried();
|
|
152089
|
+
host.log.warn("chat could not save inbound attachments; leaving them for replay", {
|
|
152090
|
+
threadId,
|
|
152091
|
+
error: describeError(error)
|
|
152092
|
+
});
|
|
152093
|
+
return {
|
|
152094
|
+
status: "settled",
|
|
152095
|
+
respond: async () => {
|
|
152096
|
+
try {
|
|
152097
|
+
if (!await deliver(binding, t("reply.inboundDeferred")))
|
|
152098
|
+
host.log.warn("chat could not deliver an inbound deferral notice", { threadId });
|
|
152099
|
+
} catch (deliveryError) {
|
|
152100
|
+
host.log.warn("chat could not deliver an inbound deferral notice", {
|
|
152101
|
+
threadId,
|
|
152102
|
+
error: describeError(deliveryError)
|
|
152103
|
+
});
|
|
152104
|
+
}
|
|
152105
|
+
}
|
|
152106
|
+
};
|
|
152107
|
+
}
|
|
151578
152108
|
}
|
|
151579
152109
|
const attachments = saved.stored;
|
|
151580
152110
|
const notes = saved.notes;
|
|
@@ -151634,7 +152164,8 @@ var makeTurns = (core, deps) => {
|
|
|
151634
152164
|
message.text,
|
|
151635
152165
|
message.resources[0]?.name
|
|
151636
152166
|
);
|
|
151637
|
-
if (
|
|
152167
|
+
if (dispatched.status !== "accepted") return dispatched;
|
|
152168
|
+
accepted.onAccepted?.();
|
|
151638
152169
|
topicRoot?.confirmConsumed();
|
|
151639
152170
|
await deps.conclusions.owe(
|
|
151640
152171
|
{ chatKey, threadId, userMessageId, recordedAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
@@ -151658,11 +152189,12 @@ var makeTurns = (core, deps) => {
|
|
|
151658
152189
|
binding.reply
|
|
151659
152190
|
);
|
|
151660
152191
|
});
|
|
151661
|
-
return
|
|
152192
|
+
return { status: "started" };
|
|
151662
152193
|
};
|
|
151663
152194
|
const receiveAttachmentsOnly = async (binding, message, enteredWaiting) => {
|
|
151664
|
-
const
|
|
151665
|
-
if (
|
|
152195
|
+
const prepared = await ensureThread(binding, message);
|
|
152196
|
+
if (typeof prepared !== "string") return prepared;
|
|
152197
|
+
const threadId = prepared;
|
|
151666
152198
|
const waiting = pendingFor(chatKeyOf(binding), threadId);
|
|
151667
152199
|
const collected = await collectResources(
|
|
151668
152200
|
binding,
|
|
@@ -151674,7 +152206,7 @@ var makeTurns = (core, deps) => {
|
|
|
151674
152206
|
waiting.attachments.push(...collected.attachments);
|
|
151675
152207
|
waiting.notes.push(...collected.notes.slice(0, MAX_ATTACHMENTS_PER_TURN));
|
|
151676
152208
|
await enteredWaiting?.();
|
|
151677
|
-
if (collected.attachments.length === 0) return;
|
|
152209
|
+
if (collected.attachments.length === 0) return { status: "settled" };
|
|
151678
152210
|
await deliver(
|
|
151679
152211
|
binding,
|
|
151680
152212
|
t("reply.attachmentReceived", {
|
|
@@ -151682,6 +152214,7 @@ var makeTurns = (core, deps) => {
|
|
|
151682
152214
|
count: waiting.attachments.length
|
|
151683
152215
|
})
|
|
151684
152216
|
);
|
|
152217
|
+
return { status: "settled" };
|
|
151685
152218
|
};
|
|
151686
152219
|
const hasWaitingAttachments = (chatKey) => (waitingFor(chatKey, chatOf(core.state, chatKey).threadId)?.attachments.length ?? 0) > 0;
|
|
151687
152220
|
return {
|
|
@@ -155175,7 +155708,7 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
155175
155708
|
// src/index.ts
|
|
155176
155709
|
var definition = {
|
|
155177
155710
|
id: "im",
|
|
155178
|
-
apiVersion:
|
|
155711
|
+
apiVersion: 29,
|
|
155179
155712
|
// 第二个参数只给插件自己的测试夹具:换掉文件 IO 与派发重试的等待。宿主只传 ctx。
|
|
155180
155713
|
activate: async (ctx, testing = {}) => {
|
|
155181
155714
|
const { dispatchSleep } = testing;
|
|
@@ -155276,7 +155809,7 @@ var definition = {
|
|
|
155276
155809
|
t,
|
|
155277
155810
|
adapters
|
|
155278
155811
|
});
|
|
155279
|
-
const acknowledgements = makeAcknowledgements(core);
|
|
155812
|
+
const acknowledgements = makeAcknowledgements(core, ctx.interval);
|
|
155280
155813
|
const failures = makeFailureNotices(core);
|
|
155281
155814
|
const replyAnchors = makeReplyAnchors(core.host);
|
|
155282
155815
|
const conclusions = makeConclusionLedger(core);
|
|
@@ -155291,6 +155824,7 @@ var definition = {
|
|
|
155291
155824
|
const teams = makeTeamGoals(core);
|
|
155292
155825
|
const notifications = makeNotifications(core, {
|
|
155293
155826
|
takeWorking: acknowledgements.takeWorking,
|
|
155827
|
+
stopTypingFor: acknowledgements.stopTypingFor,
|
|
155294
155828
|
replyCards,
|
|
155295
155829
|
failures,
|
|
155296
155830
|
conclusions,
|
|
@@ -155330,6 +155864,7 @@ var definition = {
|
|
|
155330
155864
|
});
|
|
155331
155865
|
const chatSetup = makeChatSetup(core, {
|
|
155332
155866
|
rows: projectRows,
|
|
155867
|
+
enqueueForChat: chatQueue.enqueueForChat,
|
|
155333
155868
|
resumeMessage: (bot, message) => inbound.resumeMessage(bot, message),
|
|
155334
155869
|
openPicker: (chatKey, rows, reply) => panelWiring.panel.openProjects(chatKey, rows, reply)
|
|
155335
155870
|
});
|
|
@@ -155380,6 +155915,7 @@ var definition = {
|
|
|
155380
155915
|
await inbound.stop();
|
|
155381
155916
|
turns.stop();
|
|
155382
155917
|
await chatQueue.closeAndDrain();
|
|
155918
|
+
await acknowledgements.stopDeferred();
|
|
155383
155919
|
}
|
|
155384
155920
|
});
|
|
155385
155921
|
registerSettingsRowActions(
|