@ycodium-ai/plugin-im 0.2.3096 → 0.2.3106
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 +14 -1
- package/dist/index.js +1190 -497
- package/locales/en.json +6 -0
- package/locales/zh-CN.json +6 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -23360,7 +23360,7 @@ var require_websocket = __commonJS({
|
|
|
23360
23360
|
var http = __require("http");
|
|
23361
23361
|
var net = __require("net");
|
|
23362
23362
|
var tls = __require("tls");
|
|
23363
|
-
var { randomBytes, createHash:
|
|
23363
|
+
var { randomBytes, createHash: createHash5 } = __require("crypto");
|
|
23364
23364
|
var { Duplex, Readable } = __require("stream");
|
|
23365
23365
|
var { URL: URL2 } = __require("url");
|
|
23366
23366
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -24028,7 +24028,7 @@ var require_websocket = __commonJS({
|
|
|
24028
24028
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
24029
24029
|
return;
|
|
24030
24030
|
}
|
|
24031
|
-
const digest =
|
|
24031
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
24032
24032
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
24033
24033
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
24034
24034
|
return;
|
|
@@ -24397,7 +24397,7 @@ var require_websocket_server = __commonJS({
|
|
|
24397
24397
|
var EventEmitter = __require("events");
|
|
24398
24398
|
var http = __require("http");
|
|
24399
24399
|
var { Duplex } = __require("stream");
|
|
24400
|
-
var { createHash:
|
|
24400
|
+
var { createHash: createHash5 } = __require("crypto");
|
|
24401
24401
|
var extension = require_extension();
|
|
24402
24402
|
var PerMessageDeflate = require_permessage_deflate();
|
|
24403
24403
|
var subprotocol = require_subprotocol();
|
|
@@ -24704,7 +24704,7 @@ var require_websocket_server = __commonJS({
|
|
|
24704
24704
|
);
|
|
24705
24705
|
}
|
|
24706
24706
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
24707
|
-
const digest =
|
|
24707
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
24708
24708
|
const headers = [
|
|
24709
24709
|
"HTTP/1.1 101 Switching Protocols",
|
|
24710
24710
|
"Upgrade: websocket",
|
|
@@ -126249,9 +126249,172 @@ var recordOwner = (owners, goal) => ({
|
|
|
126249
126249
|
});
|
|
126250
126250
|
|
|
126251
126251
|
// src/keepNewest.ts
|
|
126252
|
-
var keepNewest = (
|
|
126253
|
-
const entries = Object.entries(
|
|
126254
|
-
return entries.length <= limit ?
|
|
126252
|
+
var keepNewest = (record3, limit) => {
|
|
126253
|
+
const entries = Object.entries(record3);
|
|
126254
|
+
return entries.length <= limit ? record3 : Object.fromEntries(entries.slice(entries.length - limit));
|
|
126255
|
+
};
|
|
126256
|
+
|
|
126257
|
+
// src/boundedMap.ts
|
|
126258
|
+
var makeBoundedMap = (limit) => {
|
|
126259
|
+
const entries = /* @__PURE__ */ new Map();
|
|
126260
|
+
return {
|
|
126261
|
+
get: (key) => entries.get(key),
|
|
126262
|
+
set: (key, value2) => {
|
|
126263
|
+
entries.delete(key);
|
|
126264
|
+
entries.set(key, value2);
|
|
126265
|
+
if (entries.size > limit) {
|
|
126266
|
+
const oldest = entries.keys().next().value;
|
|
126267
|
+
if (oldest !== void 0) entries.delete(oldest);
|
|
126268
|
+
}
|
|
126269
|
+
},
|
|
126270
|
+
/** 忘掉键满足条件的那些。 */
|
|
126271
|
+
forget: (matches) => {
|
|
126272
|
+
for (const key of [...entries.keys()]) if (matches(key)) entries.delete(key);
|
|
126273
|
+
}
|
|
126274
|
+
};
|
|
126275
|
+
};
|
|
126276
|
+
|
|
126277
|
+
// src/replyAnchors.ts
|
|
126278
|
+
var THREAD_LIMIT = 256;
|
|
126279
|
+
var TURNS_PER_THREAD = 16;
|
|
126280
|
+
var anchorOfMessage = (adapter, message) => adapter?.quotesReplies === true ? { messageId: message.messageId, inThread: message.replyInThread === true } : void 0;
|
|
126281
|
+
var userMessageIdOfTurn = (execution, turnId) => {
|
|
126282
|
+
const intent = execution.turnIntents.find((candidate) => candidate.turn?.turnId === turnId);
|
|
126283
|
+
const latest = execution.latestTurn;
|
|
126284
|
+
return intent?.messageId ?? (latest?.turnId === turnId ? latest.userMessageId : void 0);
|
|
126285
|
+
};
|
|
126286
|
+
var makeReplyAnchors = (host) => {
|
|
126287
|
+
const byThread = makeBoundedMap(THREAD_LIMIT);
|
|
126288
|
+
const userMessageOfTurn = async (threadId, turnId) => {
|
|
126289
|
+
const execution = await host.projections.getThreadExecution(threadId).catch(() => null);
|
|
126290
|
+
if (execution === null) return void 0;
|
|
126291
|
+
const wanted = turnId ?? execution.session?.activeTurnId ?? execution.latestTurn?.turnId;
|
|
126292
|
+
return wanted == null ? void 0 : userMessageIdOfTurn(execution, wanted);
|
|
126293
|
+
};
|
|
126294
|
+
return {
|
|
126295
|
+
/**
|
|
126296
|
+
* 开轮时记一笔:`userMessageId` 是派给宿主的那条用户消息,`binding` 是收到聊天消息的那个
|
|
126297
|
+
* 聊天(带着它的锚点)。没有锚点(平台不引用)就不记。
|
|
126298
|
+
*/
|
|
126299
|
+
note: (threadId, userMessageId, binding) => {
|
|
126300
|
+
if (binding.reply === void 0) return;
|
|
126301
|
+
const turns = byThread.get(threadId) ?? makeBoundedMap(TURNS_PER_THREAD);
|
|
126302
|
+
byThread.set(threadId, turns);
|
|
126303
|
+
turns.set(userMessageId, { chatKey: chatKeyOf(binding), anchor: binding.reply });
|
|
126304
|
+
},
|
|
126305
|
+
/**
|
|
126306
|
+
* 给发往这条会话的聊天挂上 `turnId` 那一轮的锚点(null 的含义见上);取不到就原样返回。
|
|
126307
|
+
*
|
|
126308
|
+
* 锚点只配给它那条消息所在的聊天:会话可以被另一个聊天接走(`/resume`),而回复接口只按被
|
|
126309
|
+
* 回复的消息寻址,挂错了答复就发回原来的聊天。
|
|
126310
|
+
*/
|
|
126311
|
+
anchored: async (binding, threadId, turnId) => {
|
|
126312
|
+
const turns = byThread.get(threadId);
|
|
126313
|
+
if (turns === void 0) return binding;
|
|
126314
|
+
const asked = await userMessageOfTurn(threadId, turnId);
|
|
126315
|
+
const noted = asked === void 0 ? void 0 : turns.get(asked);
|
|
126316
|
+
return noted?.chatKey === chatKeyOf(binding) ? { ...binding, reply: noted.anchor } : binding;
|
|
126317
|
+
}
|
|
126318
|
+
};
|
|
126319
|
+
};
|
|
126320
|
+
|
|
126321
|
+
// src/conclusionLedger.ts
|
|
126322
|
+
var CONCLUSION_DEBT_LIMIT = 500;
|
|
126323
|
+
var keyOf = (threadId, userMessageId) => JSON.stringify([threadId, userMessageId]);
|
|
126324
|
+
var conclusionDebtsOf = (state) => state.conclusions ?? {};
|
|
126325
|
+
var foldConclusionEvent = (state, name, data) => {
|
|
126326
|
+
const threadId = data["threadId"];
|
|
126327
|
+
const userMessageId = data["userMessageId"];
|
|
126328
|
+
if (typeof threadId !== "string" || threadId === "" || typeof userMessageId !== "string" || userMessageId === "") {
|
|
126329
|
+
return state;
|
|
126330
|
+
}
|
|
126331
|
+
const key = keyOf(threadId, userMessageId);
|
|
126332
|
+
const pending = conclusionDebtsOf(state);
|
|
126333
|
+
if (name === "conclusion-delivered") {
|
|
126334
|
+
const { [key]: _delivered, ...rest } = pending;
|
|
126335
|
+
return { ...state, conclusions: rest };
|
|
126336
|
+
}
|
|
126337
|
+
const chatKey = data["chatKey"];
|
|
126338
|
+
const recordedAt = data["recordedAt"];
|
|
126339
|
+
if (typeof chatKey !== "string" || chatKey === "" || typeof recordedAt !== "string" || !Number.isFinite(Date.parse(recordedAt))) {
|
|
126340
|
+
return state;
|
|
126341
|
+
}
|
|
126342
|
+
return {
|
|
126343
|
+
...state,
|
|
126344
|
+
conclusions: keepNewest(
|
|
126345
|
+
{ ...pending, [key]: { chatKey, threadId, userMessageId, recordedAt } },
|
|
126346
|
+
CONCLUSION_DEBT_LIMIT
|
|
126347
|
+
)
|
|
126348
|
+
};
|
|
126349
|
+
};
|
|
126350
|
+
var makeConclusionLedger = (core) => {
|
|
126351
|
+
const inFlight = /* @__PURE__ */ new Set();
|
|
126352
|
+
const registering = /* @__PURE__ */ new Map();
|
|
126353
|
+
const delivered = makeBoundedMap(CONCLUSION_DEBT_LIMIT);
|
|
126354
|
+
let disposed = false;
|
|
126355
|
+
core.host.onDispose(() => {
|
|
126356
|
+
disposed = true;
|
|
126357
|
+
});
|
|
126358
|
+
const settle = (debt) => {
|
|
126359
|
+
delivered.set(keyOf(debt.threadId, debt.userMessageId), true);
|
|
126360
|
+
core.commit("conclusion-delivered", {
|
|
126361
|
+
threadId: debt.threadId,
|
|
126362
|
+
userMessageId: debt.userMessageId
|
|
126363
|
+
});
|
|
126364
|
+
};
|
|
126365
|
+
return {
|
|
126366
|
+
starting: (threadId) => {
|
|
126367
|
+
const gate = Promise.withResolvers();
|
|
126368
|
+
const pending = registering.get(threadId) ?? /* @__PURE__ */ new Set();
|
|
126369
|
+
registering.set(threadId, pending);
|
|
126370
|
+
pending.add(gate.promise);
|
|
126371
|
+
return () => {
|
|
126372
|
+
pending.delete(gate.promise);
|
|
126373
|
+
if (pending.size === 0) registering.delete(threadId);
|
|
126374
|
+
gate.resolve();
|
|
126375
|
+
};
|
|
126376
|
+
},
|
|
126377
|
+
owe: (debt) => {
|
|
126378
|
+
const pending = conclusionDebtsOf(core.state);
|
|
126379
|
+
if (Object.keys(pending).length >= CONCLUSION_DEBT_LIMIT && pending[keyOf(debt.threadId, debt.userMessageId)] === void 0) {
|
|
126380
|
+
core.host.log.warn("chat dropped its oldest conclusion debt at capacity", {
|
|
126381
|
+
oldest: Object.values(pending)[0],
|
|
126382
|
+
limit: CONCLUSION_DEBT_LIMIT
|
|
126383
|
+
});
|
|
126384
|
+
}
|
|
126385
|
+
core.commit("conclusion-owed", { ...debt });
|
|
126386
|
+
},
|
|
126387
|
+
forTurn: async (threadId, turnId = null) => {
|
|
126388
|
+
await Promise.all(registering.get(threadId) ?? []);
|
|
126389
|
+
const execution = await core.host.projections.getThreadExecution(threadId);
|
|
126390
|
+
const userMessageId = execution === null ? void 0 : turnId === null ? execution.latestTurn?.userMessageId : userMessageIdOfTurn(execution, turnId);
|
|
126391
|
+
const key = userMessageId === void 0 ? void 0 : keyOf(threadId, userMessageId);
|
|
126392
|
+
return {
|
|
126393
|
+
debt: key === void 0 ? void 0 : conclusionDebtsOf(core.state)[key],
|
|
126394
|
+
handled: key !== void 0 && (delivered.get(key) === true || inFlight.has(key)),
|
|
126395
|
+
execution
|
|
126396
|
+
};
|
|
126397
|
+
},
|
|
126398
|
+
deliver: async (debt, send) => {
|
|
126399
|
+
const key = keyOf(debt.threadId, debt.userMessageId);
|
|
126400
|
+
if (disposed || inFlight.has(key) || conclusionDebtsOf(core.state)[key] === void 0)
|
|
126401
|
+
return false;
|
|
126402
|
+
inFlight.add(key);
|
|
126403
|
+
try {
|
|
126404
|
+
const sent = await send();
|
|
126405
|
+
if (sent) settle(debt);
|
|
126406
|
+
return sent;
|
|
126407
|
+
} finally {
|
|
126408
|
+
inFlight.delete(key);
|
|
126409
|
+
}
|
|
126410
|
+
},
|
|
126411
|
+
discard: (debt) => {
|
|
126412
|
+
const key = keyOf(debt.threadId, debt.userMessageId);
|
|
126413
|
+
if (!disposed && !inFlight.has(key) && conclusionDebtsOf(core.state)[key] !== void 0) {
|
|
126414
|
+
settle(debt);
|
|
126415
|
+
}
|
|
126416
|
+
}
|
|
126417
|
+
};
|
|
126255
126418
|
};
|
|
126256
126419
|
|
|
126257
126420
|
// src/chatState.ts
|
|
@@ -126286,8 +126449,8 @@ var chatOf = (state, chatKey) => ({
|
|
|
126286
126449
|
...DEFAULT_CHAT_RECORD,
|
|
126287
126450
|
...state.chats[chatKey]
|
|
126288
126451
|
});
|
|
126289
|
-
var chatsOnProject = (state, projectId) => Object.entries(state.chats).filter(([,
|
|
126290
|
-
var chatOfThread = (state, threadId) => Object.entries(state.chats).find(([,
|
|
126452
|
+
var chatsOnProject = (state, projectId) => Object.entries(state.chats).filter(([, record3]) => record3.projectId === projectId).map(([chatKey]) => chatKey);
|
|
126453
|
+
var chatOfThread = (state, threadId) => Object.entries(state.chats).find(([, record3]) => record3.threadId === threadId)?.[0] ?? state.teamGoals?.[threadId]?.chatKey;
|
|
126291
126454
|
var findApprovalByToken = (state, token) => {
|
|
126292
126455
|
for (const approval of Object.values(state.approvals)) {
|
|
126293
126456
|
const button = approval.options.find((option) => option.token === token);
|
|
@@ -126299,29 +126462,29 @@ var openApprovalOf = (state, chatKey) => Object.values(state.approvals).findLast
|
|
|
126299
126462
|
(approval) => approval.chatKey === chatKey && !approval.resolved
|
|
126300
126463
|
);
|
|
126301
126464
|
var findQuestionByToken = (state, token) => {
|
|
126302
|
-
for (const
|
|
126303
|
-
for (const item of
|
|
126465
|
+
for (const record3 of Object.values(questionsOf(state))) {
|
|
126466
|
+
for (const item of record3.items) {
|
|
126304
126467
|
const option = item.options.find((candidate) => candidate.token === token);
|
|
126305
|
-
if (option !== void 0) return { record:
|
|
126306
|
-
if (item.submitToken === token) return { record:
|
|
126468
|
+
if (option !== void 0) return { record: record3, item, click: { kind: "option", option } };
|
|
126469
|
+
if (item.submitToken === token) return { record: record3, item, click: { kind: "submit" } };
|
|
126307
126470
|
}
|
|
126308
126471
|
}
|
|
126309
126472
|
return void 0;
|
|
126310
126473
|
};
|
|
126311
126474
|
var openQuestionOf = (state, chatKey, threadId) => Object.values(questionsOf(state)).findLast(
|
|
126312
|
-
(
|
|
126475
|
+
(record3) => record3.chatKey === chatKey && record3.threadId === threadId && !record3.resolved
|
|
126313
126476
|
);
|
|
126314
126477
|
var isUnanswered = (item) => item.answer === void 0;
|
|
126315
126478
|
var findQueueByToken = (state, token) => {
|
|
126316
|
-
for (const
|
|
126317
|
-
if (
|
|
126318
|
-
if (
|
|
126319
|
-
if (
|
|
126479
|
+
for (const record3 of Object.values(queueOf(state))) {
|
|
126480
|
+
if (record3.steerToken === token) return { record: record3, op: "steer" };
|
|
126481
|
+
if (record3.withdrawToken === token) return { record: record3, op: "withdraw" };
|
|
126482
|
+
if (record3.resumeToken === token) return { record: record3, op: "resume" };
|
|
126320
126483
|
}
|
|
126321
126484
|
return void 0;
|
|
126322
126485
|
};
|
|
126323
126486
|
var openQueueOfThread = (state, threadId) => Object.values(queueOf(state)).filter(
|
|
126324
|
-
(
|
|
126487
|
+
(record3) => record3.threadId === threadId && record3.settled === void 0
|
|
126325
126488
|
);
|
|
126326
126489
|
var isRecord = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
126327
126490
|
var nonEmpty3 = (value2) => typeof value2 === "string" && value2 !== "" ? value2 : null;
|
|
@@ -126394,24 +126557,24 @@ var readAnswer = (value2) => {
|
|
|
126394
126557
|
return null;
|
|
126395
126558
|
};
|
|
126396
126559
|
var withQuestionItem = (state, requestId, questionId, patch) => {
|
|
126397
|
-
const
|
|
126398
|
-
if (requestId === null || questionId === null ||
|
|
126399
|
-
if (!
|
|
126560
|
+
const record3 = requestId === null ? void 0 : questionsOf(state)[requestId];
|
|
126561
|
+
if (requestId === null || questionId === null || record3 === void 0) return state;
|
|
126562
|
+
if (!record3.items.some((item) => item.id === questionId)) return state;
|
|
126400
126563
|
return {
|
|
126401
126564
|
...state,
|
|
126402
126565
|
questions: {
|
|
126403
126566
|
...questionsOf(state),
|
|
126404
126567
|
[requestId]: {
|
|
126405
|
-
...
|
|
126406
|
-
items:
|
|
126568
|
+
...record3,
|
|
126569
|
+
items: record3.items.map((item) => item.id === questionId ? patch(item) : item)
|
|
126407
126570
|
}
|
|
126408
126571
|
}
|
|
126409
126572
|
};
|
|
126410
126573
|
};
|
|
126411
126574
|
var withQueueRecord = (state, intentId, patch) => {
|
|
126412
|
-
const
|
|
126413
|
-
if (intentId === null ||
|
|
126414
|
-
return { ...state, queue: { ...queueOf(state), [intentId]: patch(
|
|
126575
|
+
const record3 = intentId === null ? void 0 : queueOf(state)[intentId];
|
|
126576
|
+
if (intentId === null || record3 === void 0) return state;
|
|
126577
|
+
return { ...state, queue: { ...queueOf(state), [intentId]: patch(record3) } };
|
|
126415
126578
|
};
|
|
126416
126579
|
var withChat = (state, chatKey, patch) => ({
|
|
126417
126580
|
...state,
|
|
@@ -126420,6 +126583,9 @@ var withChat = (state, chatKey, patch) => ({
|
|
|
126420
126583
|
var foldImEvent = (state, name, data) => {
|
|
126421
126584
|
if (!isRecord(data)) return state;
|
|
126422
126585
|
switch (name) {
|
|
126586
|
+
case "conclusion-owed":
|
|
126587
|
+
case "conclusion-delivered":
|
|
126588
|
+
return foldConclusionEvent(state, name, data);
|
|
126423
126589
|
case "chat-updated": {
|
|
126424
126590
|
const chatKey = nonEmpty3(data["chatKey"]);
|
|
126425
126591
|
if (chatKey === null) return state;
|
|
@@ -126467,10 +126633,10 @@ var foldImEvent = (state, name, data) => {
|
|
|
126467
126633
|
return { ...bound, teamGoals: recordOwner(bound.teamGoals, goal) };
|
|
126468
126634
|
}
|
|
126469
126635
|
case "thread-attached": {
|
|
126470
|
-
const
|
|
126471
|
-
if (
|
|
126472
|
-
const key = attachedKey(
|
|
126473
|
-
const attached = { ...state.attached, [key]:
|
|
126636
|
+
const record3 = readAttached(data);
|
|
126637
|
+
if (record3 === null) return state;
|
|
126638
|
+
const key = attachedKey(record3.chatKey, record3.threadId);
|
|
126639
|
+
const attached = { ...state.attached, [key]: record3 };
|
|
126474
126640
|
return { ...state, attached: keepNewest(attached, ATTACHED_THREAD_LIMIT) };
|
|
126475
126641
|
}
|
|
126476
126642
|
case "approval-offered": {
|
|
@@ -126611,21 +126777,21 @@ var foldImEvent = (state, name, data) => {
|
|
|
126611
126777
|
case "queue-carded": {
|
|
126612
126778
|
const cardId = nonEmpty3(data["cardId"]);
|
|
126613
126779
|
if (cardId === null) return state;
|
|
126614
|
-
return withQueueRecord(state, nonEmpty3(data["intentId"]), (
|
|
126615
|
-
...
|
|
126780
|
+
return withQueueRecord(state, nonEmpty3(data["intentId"]), (record3) => ({
|
|
126781
|
+
...record3,
|
|
126616
126782
|
cardId
|
|
126617
126783
|
}));
|
|
126618
126784
|
}
|
|
126619
126785
|
case "queue-steering":
|
|
126620
|
-
return withQueueRecord(state, nonEmpty3(data["intentId"]), (
|
|
126621
|
-
...
|
|
126786
|
+
return withQueueRecord(state, nonEmpty3(data["intentId"]), (record3) => ({
|
|
126787
|
+
...record3,
|
|
126622
126788
|
steering: data["steering"] === true
|
|
126623
126789
|
}));
|
|
126624
126790
|
case "queue-settled": {
|
|
126625
126791
|
const outcome = data["outcome"];
|
|
126626
126792
|
if (outcome !== "steered" && outcome !== "sent" && outcome !== "removed") return state;
|
|
126627
|
-
return withQueueRecord(state, nonEmpty3(data["intentId"]), (
|
|
126628
|
-
...
|
|
126793
|
+
return withQueueRecord(state, nonEmpty3(data["intentId"]), (record3) => ({
|
|
126794
|
+
...record3,
|
|
126629
126795
|
settled: outcome
|
|
126630
126796
|
}));
|
|
126631
126797
|
}
|
|
@@ -126750,18 +126916,18 @@ var readDeliveryTargets = (config2) => {
|
|
|
126750
126916
|
if (typeof table2 !== "object" || table2 === null) return [];
|
|
126751
126917
|
return Object.entries(table2).flatMap(([rowId, row]) => {
|
|
126752
126918
|
if (typeof row !== "object" || row === null) return [];
|
|
126753
|
-
const
|
|
126754
|
-
const kind = readString(
|
|
126755
|
-
if (targetIssues(
|
|
126756
|
-
const targetId = readString(
|
|
126919
|
+
const record3 = row;
|
|
126920
|
+
const kind = readString(record3, "kind") || "chat";
|
|
126921
|
+
if (targetIssues(record3).length > 0 || !isTargetKind(kind)) return [];
|
|
126922
|
+
const targetId = readString(record3, "targetId");
|
|
126757
126923
|
return [
|
|
126758
126924
|
{
|
|
126759
126925
|
rowId,
|
|
126760
|
-
botId: readString(
|
|
126926
|
+
botId: readString(record3, DELIVERY_BOT_COLUMN),
|
|
126761
126927
|
targetId,
|
|
126762
|
-
name: readString(
|
|
126928
|
+
name: readString(record3, "name") || targetId,
|
|
126763
126929
|
kind,
|
|
126764
|
-
platformChatId: readString(
|
|
126930
|
+
platformChatId: readString(record3, "platformChatId")
|
|
126765
126931
|
}
|
|
126766
126932
|
];
|
|
126767
126933
|
});
|
|
@@ -127154,8 +127320,8 @@ var makeApprovals = (core, anchors) => {
|
|
|
127154
127320
|
host.log.info("chat asked for an approval", { threadId, requestId: offer.requestId });
|
|
127155
127321
|
if (cardId === null) return;
|
|
127156
127322
|
commit("approval-carded", { requestId: offer.requestId, cardId });
|
|
127157
|
-
const
|
|
127158
|
-
if (
|
|
127323
|
+
const record3 = core.state.approvals[offer.requestId];
|
|
127324
|
+
if (record3?.resolved === true) await settleApprovalCard(record3, { kind: "elsewhere" });
|
|
127159
127325
|
} catch (error) {
|
|
127160
127326
|
host.log.warn("chat could not ask for the approval", { error: describeError(error) });
|
|
127161
127327
|
}
|
|
@@ -127974,16 +128140,16 @@ var parseSendBody = (raw) => {
|
|
|
127974
128140
|
return "bad-request";
|
|
127975
128141
|
}
|
|
127976
128142
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return "bad-request";
|
|
127977
|
-
const
|
|
127978
|
-
const botId =
|
|
127979
|
-
const targetId =
|
|
127980
|
-
const text4 =
|
|
127981
|
-
const format2 =
|
|
128143
|
+
const record3 = parsed;
|
|
128144
|
+
const botId = record3["botId"];
|
|
128145
|
+
const targetId = record3["targetId"];
|
|
128146
|
+
const text4 = record3["text"];
|
|
128147
|
+
const format2 = record3["format"];
|
|
127982
128148
|
if (typeof botId !== "string" || botId.trim() === "") return "bad-request";
|
|
127983
128149
|
if (typeof targetId !== "string" || targetId.trim() === "") return "bad-request";
|
|
127984
128150
|
if (typeof text4 !== "string" || text4.trim() === "") return "bad-request";
|
|
127985
128151
|
if (format2 !== void 0 && format2 !== "plain" && format2 !== "markdown") return "bad-request";
|
|
127986
|
-
for (const key of Object.keys(
|
|
128152
|
+
for (const key of Object.keys(record3)) {
|
|
127987
128153
|
if (key !== "botId" && key !== "targetId" && key !== "text" && key !== "format") {
|
|
127988
128154
|
return "bad-request";
|
|
127989
128155
|
}
|
|
@@ -128177,11 +128343,15 @@ var makeImCore = (input) => {
|
|
|
128177
128343
|
};
|
|
128178
128344
|
const deliver = async (binding, text4, attachments = []) => {
|
|
128179
128345
|
await postImages(binding, attachments);
|
|
128180
|
-
if (text4.trim() === "") return;
|
|
128346
|
+
if (text4.trim() === "") return true;
|
|
128347
|
+
const adapter = adapterFor(binding.platform);
|
|
128348
|
+
if (adapter === void 0) return false;
|
|
128181
128349
|
try {
|
|
128182
|
-
await
|
|
128350
|
+
await adapter.sendText(binding, text4);
|
|
128351
|
+
return true;
|
|
128183
128352
|
} catch (error) {
|
|
128184
128353
|
host.log.warn("chat could not deliver", { error: describeError(error) });
|
|
128354
|
+
return false;
|
|
128185
128355
|
}
|
|
128186
128356
|
};
|
|
128187
128357
|
const bots = () => readBots(input.config(), adapterFor);
|
|
@@ -128209,6 +128379,93 @@ var makeImCore = (input) => {
|
|
|
128209
128379
|
};
|
|
128210
128380
|
};
|
|
128211
128381
|
|
|
128382
|
+
// src/conclusionDelivery.ts
|
|
128383
|
+
import { threadOrNull as threadOrNull3 } from "@ycodium-ai/plugin-api";
|
|
128384
|
+
|
|
128385
|
+
// src/threadMessages.ts
|
|
128386
|
+
import {
|
|
128387
|
+
isThreadNotFound,
|
|
128388
|
+
threadMessagesNewestFirst
|
|
128389
|
+
} from "@ycodium-ai/plugin-api";
|
|
128390
|
+
var PAGE_SIZE = 20;
|
|
128391
|
+
async function* newestFirst(threads, threadId) {
|
|
128392
|
+
try {
|
|
128393
|
+
yield* threadMessagesNewestFirst(threads, threadId, { pageSize: PAGE_SIZE });
|
|
128394
|
+
} catch (error) {
|
|
128395
|
+
if (!isThreadNotFound(error)) throw error;
|
|
128396
|
+
}
|
|
128397
|
+
}
|
|
128398
|
+
async function attachmentsOf(threads, threadId, message) {
|
|
128399
|
+
const collected = [...message.attachments ?? []];
|
|
128400
|
+
const total = message.attachmentsTotal ?? collected.length;
|
|
128401
|
+
while (collected.length < total) {
|
|
128402
|
+
let page;
|
|
128403
|
+
try {
|
|
128404
|
+
page = await threads.messages.list({
|
|
128405
|
+
threadId,
|
|
128406
|
+
messageId: message.id,
|
|
128407
|
+
attachmentOffset: collected.length,
|
|
128408
|
+
textLimit: 2
|
|
128409
|
+
});
|
|
128410
|
+
} catch (error) {
|
|
128411
|
+
if (isThreadNotFound(error)) break;
|
|
128412
|
+
throw error;
|
|
128413
|
+
}
|
|
128414
|
+
const more = page.items[0]?.attachments ?? [];
|
|
128415
|
+
if (more.length === 0) break;
|
|
128416
|
+
collected.push(...more);
|
|
128417
|
+
}
|
|
128418
|
+
return collected;
|
|
128419
|
+
}
|
|
128420
|
+
async function latestMessage(threads, threadId, accept) {
|
|
128421
|
+
for await (const message of newestFirst(threads, threadId)) {
|
|
128422
|
+
if (accept(message)) return message;
|
|
128423
|
+
}
|
|
128424
|
+
return void 0;
|
|
128425
|
+
}
|
|
128426
|
+
async function messagesAfterLastUser(threads, threadId) {
|
|
128427
|
+
const after = [];
|
|
128428
|
+
for await (const message of newestFirst(threads, threadId)) {
|
|
128429
|
+
if (message.role === "user") break;
|
|
128430
|
+
after.push(message);
|
|
128431
|
+
}
|
|
128432
|
+
return after.toReversed();
|
|
128433
|
+
}
|
|
128434
|
+
|
|
128435
|
+
// src/conclusionDelivery.ts
|
|
128436
|
+
var makeConclusionDelivery = (core, anchors) => {
|
|
128437
|
+
let disposed = false;
|
|
128438
|
+
core.host.onDispose(() => {
|
|
128439
|
+
disposed = true;
|
|
128440
|
+
});
|
|
128441
|
+
const marked = (text4, recovered) => recovered ? `${core.t("reply.conclusionRecovered")}
|
|
128442
|
+
${text4}` : text4;
|
|
128443
|
+
return {
|
|
128444
|
+
prepareConclusion: async (threadId, turnId = null) => {
|
|
128445
|
+
const thread = await threadOrNull3(core.host.threads, threadId);
|
|
128446
|
+
const final = thread === null ? void 0 : await latestMessage(
|
|
128447
|
+
core.host.threads,
|
|
128448
|
+
threadId,
|
|
128449
|
+
(message) => message.role === "assistant" && message.text.trim() !== ""
|
|
128450
|
+
);
|
|
128451
|
+
const attachments = final === void 0 ? [] : await attachmentsOf(core.host.threads, threadId, final);
|
|
128452
|
+
return async (binding, options) => {
|
|
128453
|
+
if (disposed || thread === null) return false;
|
|
128454
|
+
if (final === void 0) return options.streaming;
|
|
128455
|
+
const text4 = options.streaming ? "" : marked(`${thread.title}
|
|
128456
|
+
|
|
128457
|
+
${final.text}`, options.recovered);
|
|
128458
|
+
const anchored = await anchors.anchored(binding, threadId, turnId ?? final.turnId);
|
|
128459
|
+
return !disposed && core.deliver(anchored, text4, attachments);
|
|
128460
|
+
};
|
|
128461
|
+
},
|
|
128462
|
+
failure: async (binding, threadId, notice, recovered, turnId = null) => {
|
|
128463
|
+
const anchored = await anchors.anchored(binding, threadId, turnId);
|
|
128464
|
+
return !disposed && core.deliver(anchored, marked(notice, recovered));
|
|
128465
|
+
}
|
|
128466
|
+
};
|
|
128467
|
+
};
|
|
128468
|
+
|
|
128212
128469
|
// src/attachments.ts
|
|
128213
128470
|
var IMAGE_LIMIT_BYTES = 10 * 1024 * 1024;
|
|
128214
128471
|
var FILE_LIMIT_BYTES = 25 * 1024 * 1024;
|
|
@@ -128501,68 +128758,6 @@ var makeCooldown = (windowMs, now, maxKeys = Number.POSITIVE_INFINITY) => {
|
|
|
128501
128758
|
};
|
|
128502
128759
|
};
|
|
128503
128760
|
|
|
128504
|
-
// src/boundedMap.ts
|
|
128505
|
-
var makeBoundedMap = (limit) => {
|
|
128506
|
-
const entries = /* @__PURE__ */ new Map();
|
|
128507
|
-
return {
|
|
128508
|
-
get: (key) => entries.get(key),
|
|
128509
|
-
set: (key, value2) => {
|
|
128510
|
-
entries.delete(key);
|
|
128511
|
-
entries.set(key, value2);
|
|
128512
|
-
if (entries.size > limit) {
|
|
128513
|
-
const oldest = entries.keys().next().value;
|
|
128514
|
-
if (oldest !== void 0) entries.delete(oldest);
|
|
128515
|
-
}
|
|
128516
|
-
},
|
|
128517
|
-
/** 忘掉键满足条件的那些。 */
|
|
128518
|
-
forget: (matches) => {
|
|
128519
|
-
for (const key of [...entries.keys()]) if (matches(key)) entries.delete(key);
|
|
128520
|
-
}
|
|
128521
|
-
};
|
|
128522
|
-
};
|
|
128523
|
-
|
|
128524
|
-
// src/replyAnchors.ts
|
|
128525
|
-
var THREAD_LIMIT = 256;
|
|
128526
|
-
var TURNS_PER_THREAD = 16;
|
|
128527
|
-
var anchorOfMessage = (adapter, message) => adapter?.quotesReplies === true ? { messageId: message.messageId, inThread: message.replyInThread === true } : void 0;
|
|
128528
|
-
var makeReplyAnchors = (host) => {
|
|
128529
|
-
const byThread = makeBoundedMap(THREAD_LIMIT);
|
|
128530
|
-
const userMessageOfTurn = async (threadId, turnId) => {
|
|
128531
|
-
const execution = await host.projections.getThreadExecution(threadId).catch(() => null);
|
|
128532
|
-
if (execution === null) return void 0;
|
|
128533
|
-
const latest = execution.latestTurn;
|
|
128534
|
-
const wanted = turnId ?? execution.session?.activeTurnId ?? latest?.turnId;
|
|
128535
|
-
if (wanted == null) return void 0;
|
|
128536
|
-
const intent = execution.turnIntents.find((candidate) => candidate.turn?.turnId === wanted);
|
|
128537
|
-
return intent?.messageId ?? (latest?.turnId === wanted ? latest.userMessageId : void 0);
|
|
128538
|
-
};
|
|
128539
|
-
return {
|
|
128540
|
-
/**
|
|
128541
|
-
* 开轮时记一笔:`userMessageId` 是派给宿主的那条用户消息,`binding` 是收到聊天消息的那个
|
|
128542
|
-
* 聊天(带着它的锚点)。没有锚点(平台不引用)就不记。
|
|
128543
|
-
*/
|
|
128544
|
-
note: (threadId, userMessageId, binding) => {
|
|
128545
|
-
if (binding.reply === void 0) return;
|
|
128546
|
-
const turns = byThread.get(threadId) ?? makeBoundedMap(TURNS_PER_THREAD);
|
|
128547
|
-
byThread.set(threadId, turns);
|
|
128548
|
-
turns.set(userMessageId, { chatKey: chatKeyOf(binding), anchor: binding.reply });
|
|
128549
|
-
},
|
|
128550
|
-
/**
|
|
128551
|
-
* 给发往这条会话的聊天挂上 `turnId` 那一轮的锚点(null 的含义见上);取不到就原样返回。
|
|
128552
|
-
*
|
|
128553
|
-
* 锚点只配给它那条消息所在的聊天:会话可以被另一个聊天接走(`/resume`),而回复接口只按被
|
|
128554
|
-
* 回复的消息寻址,挂错了答复就发回原来的聊天。
|
|
128555
|
-
*/
|
|
128556
|
-
anchored: async (binding, threadId, turnId) => {
|
|
128557
|
-
const turns = byThread.get(threadId);
|
|
128558
|
-
if (turns === void 0) return binding;
|
|
128559
|
-
const asked = await userMessageOfTurn(threadId, turnId);
|
|
128560
|
-
const noted = asked === void 0 ? void 0 : turns.get(asked);
|
|
128561
|
-
return noted?.chatKey === chatKeyOf(binding) ? { ...binding, reply: noted.anchor } : binding;
|
|
128562
|
-
}
|
|
128563
|
-
};
|
|
128564
|
-
};
|
|
128565
|
-
|
|
128566
128761
|
// src/inbound.ts
|
|
128567
128762
|
var SEEN_MESSAGE_LIMIT = 256;
|
|
128568
128763
|
var ARCHIVED_REPLY_COOLDOWN_MS = 10 * 6e4;
|
|
@@ -128600,10 +128795,9 @@ var makeInbound = (core, deps) => {
|
|
|
128600
128795
|
});
|
|
128601
128796
|
if (sender === null) return;
|
|
128602
128797
|
if (!notAllowedReplyCooldown.tryAcquire(`${target2.rowId}:${sender}`)) return;
|
|
128603
|
-
enqueueForChat(
|
|
128604
|
-
|
|
128605
|
-
|
|
128606
|
-
);
|
|
128798
|
+
enqueueForChat(chatKeyOf(target2), async () => {
|
|
128799
|
+
await deliver(target2, t("reply.notAllowedYet", { id: sender }));
|
|
128800
|
+
});
|
|
128607
128801
|
};
|
|
128608
128802
|
const currentBot = (rowId) => bots().find((candidate) => candidate.rowId === rowId);
|
|
128609
128803
|
const inheritFromParent = (bot, chatId, parentChatId) => {
|
|
@@ -128857,35 +129051,35 @@ var makeQuestionFlow = (host) => {
|
|
|
128857
129051
|
const itemOf = (requestId, questionId) => recordOf(requestId)?.items.find((item) => item.id === questionId);
|
|
128858
129052
|
const hasButtons = (chatKey) => host.target(chatKey)?.adapter.choiceCards !== void 0;
|
|
128859
129053
|
const redraw = async (requestId, questionId) => {
|
|
128860
|
-
const
|
|
129054
|
+
const record3 = recordOf(requestId);
|
|
128861
129055
|
const item = itemOf(requestId, questionId);
|
|
128862
|
-
const target2 =
|
|
128863
|
-
if (
|
|
128864
|
-
if (
|
|
129056
|
+
const target2 = record3 === void 0 ? void 0 : host.target(record3.chatKey);
|
|
129057
|
+
if (record3 === void 0 || item?.cardId === void 0 || target2 === void 0) return;
|
|
129058
|
+
if (record3.resolved || item.answer !== void 0) return;
|
|
128865
129059
|
try {
|
|
128866
129060
|
await target2.adapter.choiceCards?.update(
|
|
128867
129061
|
target2.binding,
|
|
128868
129062
|
item.cardId,
|
|
128869
|
-
questionCardOf(item,
|
|
129063
|
+
questionCardOf(item, record3.items.indexOf(item), record3.items.length, t)
|
|
128870
129064
|
);
|
|
128871
129065
|
} catch (error) {
|
|
128872
129066
|
host.warn("chat could not update the question card", error);
|
|
128873
129067
|
}
|
|
128874
129068
|
};
|
|
128875
129069
|
const freeze = async (requestId, questionId) => {
|
|
128876
|
-
const
|
|
129070
|
+
const record3 = recordOf(requestId);
|
|
128877
129071
|
const item = itemOf(requestId, questionId);
|
|
128878
|
-
const target2 =
|
|
128879
|
-
if (
|
|
129072
|
+
const target2 = record3 === void 0 ? void 0 : host.target(record3.chatKey);
|
|
129073
|
+
if (record3 === void 0 || item?.cardId === void 0 || target2 === void 0) return;
|
|
128880
129074
|
try {
|
|
128881
129075
|
await target2.adapter.choiceCards?.update(
|
|
128882
129076
|
target2.binding,
|
|
128883
129077
|
item.cardId,
|
|
128884
129078
|
questionSettledCardOf(
|
|
128885
129079
|
item,
|
|
128886
|
-
|
|
128887
|
-
|
|
128888
|
-
|
|
129080
|
+
record3.items.indexOf(item),
|
|
129081
|
+
record3.items.length,
|
|
129082
|
+
record3.ending ?? "here",
|
|
128889
129083
|
t
|
|
128890
129084
|
)
|
|
128891
129085
|
);
|
|
@@ -128894,13 +129088,13 @@ var makeQuestionFlow = (host) => {
|
|
|
128894
129088
|
}
|
|
128895
129089
|
};
|
|
128896
129090
|
const sayNext = async (requestId) => {
|
|
128897
|
-
const
|
|
128898
|
-
if (
|
|
128899
|
-
const item =
|
|
129091
|
+
const record3 = recordOf(requestId);
|
|
129092
|
+
if (record3 === void 0 || record3.resolved) return;
|
|
129093
|
+
const item = record3.items.find(isUnanswered);
|
|
128900
129094
|
if (item === void 0) return;
|
|
128901
129095
|
await host.say(
|
|
128902
|
-
|
|
128903
|
-
questionPlainText(item,
|
|
129096
|
+
record3.chatKey,
|
|
129097
|
+
questionPlainText(item, record3.items.indexOf(item), record3.items.length, t)
|
|
128904
129098
|
);
|
|
128905
129099
|
};
|
|
128906
129100
|
const post = async (requestId) => {
|
|
@@ -128913,13 +129107,13 @@ var makeQuestionFlow = (host) => {
|
|
|
128913
129107
|
return;
|
|
128914
129108
|
}
|
|
128915
129109
|
for (const questionId of first.items.map((item) => item.id)) {
|
|
128916
|
-
const
|
|
129110
|
+
const record3 = recordOf(requestId);
|
|
128917
129111
|
const item = itemOf(requestId, questionId);
|
|
128918
|
-
if (
|
|
129112
|
+
if (record3 === void 0 || record3.resolved || item === void 0) return;
|
|
128919
129113
|
try {
|
|
128920
129114
|
const cardId = await cards.open(
|
|
128921
|
-
await host.anchored(target2.binding,
|
|
128922
|
-
questionCardOf(item,
|
|
129115
|
+
await host.anchored(target2.binding, record3.threadId),
|
|
129116
|
+
questionCardOf(item, record3.items.indexOf(item), record3.items.length, t)
|
|
128923
129117
|
);
|
|
128924
129118
|
if (cardId === null) continue;
|
|
128925
129119
|
host.commit("question-carded", { requestId, questionId, cardId });
|
|
@@ -128999,10 +129193,10 @@ var makeQuestionFlow = (host) => {
|
|
|
128999
129193
|
const click = (token, operatorId) => {
|
|
129000
129194
|
const found = findQuestionByToken(host.state(), token);
|
|
129001
129195
|
if (found === void 0) return NOT_MINE;
|
|
129002
|
-
const { record:
|
|
129003
|
-
if (
|
|
129004
|
-
if (!host.allowed(
|
|
129005
|
-
const requestId =
|
|
129196
|
+
const { record: record3, item } = found;
|
|
129197
|
+
if (record3.resolved || !isUnanswered(item)) return handledWith(t("question.alreadyHandled"));
|
|
129198
|
+
if (!host.allowed(record3.chatKey, operatorId)) return handledWith(t("reply.notAllowed"));
|
|
129199
|
+
const requestId = record3.requestId;
|
|
129006
129200
|
if (found.click.kind === "option") {
|
|
129007
129201
|
const option = found.click.option;
|
|
129008
129202
|
if (!item.multiSelect) {
|
|
@@ -129011,7 +129205,7 @@ var makeQuestionFlow = (host) => {
|
|
|
129011
129205
|
}
|
|
129012
129206
|
const selected = item.selected.includes(option.value) ? item.selected.filter((value2) => value2 !== option.value) : [...item.selected, option.value];
|
|
129013
129207
|
host.commit("question-selected", { requestId, questionId: item.id, selected });
|
|
129014
|
-
host.outbound(
|
|
129208
|
+
host.outbound(record3.chatKey, () => redraw(requestId, item.id));
|
|
129015
129209
|
return handledWith(null);
|
|
129016
129210
|
}
|
|
129017
129211
|
const chosen = item.options.filter((option) => item.selected.includes(option.value));
|
|
@@ -129025,29 +129219,29 @@ var makeQuestionFlow = (host) => {
|
|
|
129025
129219
|
return handledWith(null);
|
|
129026
129220
|
};
|
|
129027
129221
|
const answerByText = async (chatKey, threadId, text4) => {
|
|
129028
|
-
const
|
|
129222
|
+
const record3 = openQuestionOf(host.state(), chatKey, threadId);
|
|
129029
129223
|
const trimmed = text4.trim();
|
|
129030
|
-
if (
|
|
129031
|
-
const unanswered =
|
|
129224
|
+
if (record3 === void 0 || trimmed === "") return false;
|
|
129225
|
+
const unanswered = record3.items.filter(isUnanswered);
|
|
129032
129226
|
const first = unanswered[0];
|
|
129033
129227
|
if (first === void 0) return false;
|
|
129034
129228
|
if (!hasButtons(chatKey)) {
|
|
129035
129229
|
const numbered = parseNumberedReply(first, trimmed, t);
|
|
129036
129230
|
if (numbered !== null) {
|
|
129037
|
-
return answer(
|
|
129231
|
+
return answer(record3.requestId, first.id, numbered.answer, numbered.label);
|
|
129038
129232
|
}
|
|
129039
129233
|
}
|
|
129040
129234
|
const freeform = unanswered.find((item) => item.allowFreeform);
|
|
129041
129235
|
if (freeform === void 0) return false;
|
|
129042
|
-
return answer(
|
|
129236
|
+
return answer(record3.requestId, freeform.id, trimmed, clip(trimmed, ANSWER_ECHO_MAX_CHARS));
|
|
129043
129237
|
};
|
|
129044
129238
|
const resolved = (requestId, outcome) => {
|
|
129045
|
-
const
|
|
129046
|
-
if (
|
|
129239
|
+
const record3 = recordOf(requestId);
|
|
129240
|
+
if (record3 === void 0 || record3.resolved) return;
|
|
129047
129241
|
const ending = outcome === "answered" ? "elsewhere" : "cancelled";
|
|
129048
129242
|
host.commit("question-resolved", { requestId, ending });
|
|
129049
|
-
for (const item of
|
|
129050
|
-
if (isUnanswered(item)) host.outbound(
|
|
129243
|
+
for (const item of record3.items) {
|
|
129244
|
+
if (isUnanswered(item)) host.outbound(record3.chatKey, () => freeze(requestId, item.id));
|
|
129051
129245
|
}
|
|
129052
129246
|
};
|
|
129053
129247
|
return { offer, click, answerByText, resolved };
|
|
@@ -129062,16 +129256,16 @@ var IN_FLIGHT_STATUSES = /* @__PURE__ */ new Set([
|
|
|
129062
129256
|
"reconciling"
|
|
129063
129257
|
]);
|
|
129064
129258
|
var WITHDRAWN_STATUSES = /* @__PURE__ */ new Set(["cancelled", "abandoned"]);
|
|
129065
|
-
var queueViewOf = (
|
|
129259
|
+
var queueViewOf = (record3, facts, released) => {
|
|
129066
129260
|
const status = facts.intent?.status;
|
|
129067
129261
|
if (status === void 0) return null;
|
|
129068
129262
|
if (WITHDRAWN_STATUSES.has(status)) return { kind: "settled", outcome: "removed" };
|
|
129069
129263
|
if (IN_FLIGHT_STATUSES.has(status))
|
|
129070
|
-
return
|
|
129264
|
+
return record3.steering ? { kind: "steering" } : { kind: "sending" };
|
|
129071
129265
|
if (!WAITING_STATUSES.has(status)) {
|
|
129072
|
-
return { kind: "settled", outcome:
|
|
129266
|
+
return { kind: "settled", outcome: record3.steering ? "steered" : "sent" };
|
|
129073
129267
|
}
|
|
129074
|
-
if (
|
|
129268
|
+
if (record3.steering && !released) return { kind: "steering" };
|
|
129075
129269
|
return { kind: "queued", running: facts.activeTurnId !== null, paused: facts.queuePaused };
|
|
129076
129270
|
};
|
|
129077
129271
|
var SETTLED_TITLE = {
|
|
@@ -129084,8 +129278,8 @@ var SETTLED_NOTE = {
|
|
|
129084
129278
|
sent: "queue.sent",
|
|
129085
129279
|
removed: "queue.removed"
|
|
129086
129280
|
};
|
|
129087
|
-
var queueCardOf = (
|
|
129088
|
-
const body = clip(
|
|
129281
|
+
var queueCardOf = (record3, view, note, t) => {
|
|
129282
|
+
const body = clip(record3.text, QUEUE_PREVIEW_MAX_CHARS);
|
|
129089
129283
|
if (view.kind === "steering") {
|
|
129090
129284
|
return {
|
|
129091
129285
|
tone: "queue",
|
|
@@ -129126,10 +129320,10 @@ var queueCardOf = (record2, view, note, t) => {
|
|
|
129126
129320
|
note: note ?? state,
|
|
129127
129321
|
rows: [
|
|
129128
129322
|
[
|
|
129129
|
-
...steerable ? [{ label: t("queue.steer"), token:
|
|
129130
|
-
{ label: t("queue.withdraw"), token:
|
|
129323
|
+
...steerable ? [{ label: t("queue.steer"), token: record3.steerToken, style: "primary" }] : [],
|
|
129324
|
+
{ label: t("queue.withdraw"), token: record3.withdrawToken, style: "default" }
|
|
129131
129325
|
],
|
|
129132
|
-
...view.paused ? [[{ label: t("queue.resume"), token:
|
|
129326
|
+
...view.paused ? [[{ label: t("queue.resume"), token: record3.resumeToken, style: "primary" }]] : []
|
|
129133
129327
|
]
|
|
129134
129328
|
};
|
|
129135
129329
|
};
|
|
@@ -129186,11 +129380,11 @@ var makeQueueFlow = (host, deps) => {
|
|
|
129186
129380
|
resumeToken: host.newToken()
|
|
129187
129381
|
});
|
|
129188
129382
|
host.outbound(chatKey, async () => {
|
|
129189
|
-
const
|
|
129190
|
-
if (
|
|
129383
|
+
const record3 = recordOf(intentId);
|
|
129384
|
+
if (record3 === void 0) return;
|
|
129191
129385
|
try {
|
|
129192
129386
|
const latest = await deps.readExecution(threadId) ?? execution;
|
|
129193
|
-
const view = queueViewOf(
|
|
129387
|
+
const view = queueViewOf(record3, factsOf(latest, intentId), false) ?? {
|
|
129194
129388
|
kind: "queued",
|
|
129195
129389
|
running: latest.activeTurnId !== null,
|
|
129196
129390
|
paused: latest.queuePaused
|
|
@@ -129201,7 +129395,7 @@ var makeQueueFlow = (host, deps) => {
|
|
|
129201
129395
|
}
|
|
129202
129396
|
const cardId = await cards.open(
|
|
129203
129397
|
{ ...target2.binding, reply },
|
|
129204
|
-
queueCardOf(
|
|
129398
|
+
queueCardOf(record3, view, null, t)
|
|
129205
129399
|
);
|
|
129206
129400
|
if (cardId === null) return;
|
|
129207
129401
|
host.commit("queue-carded", { intentId, cardId });
|
|
@@ -129212,99 +129406,99 @@ var makeQueueFlow = (host, deps) => {
|
|
|
129212
129406
|
});
|
|
129213
129407
|
};
|
|
129214
129408
|
const redraw = async (intentId, released) => {
|
|
129215
|
-
const
|
|
129216
|
-
const target2 =
|
|
129217
|
-
if (
|
|
129218
|
-
if (
|
|
129409
|
+
const record3 = recordOf(intentId);
|
|
129410
|
+
const target2 = record3 === void 0 ? void 0 : host.target(record3.chatKey);
|
|
129411
|
+
if (record3 === void 0 || record3.settled !== void 0 || target2 === void 0) return;
|
|
129412
|
+
if (record3.cardId === void 0) return;
|
|
129219
129413
|
let execution;
|
|
129220
129414
|
try {
|
|
129221
|
-
execution = await deps.readExecution(
|
|
129415
|
+
execution = await deps.readExecution(record3.threadId);
|
|
129222
129416
|
} catch (error) {
|
|
129223
129417
|
host.warn("chat could not read the turn queue", error);
|
|
129224
129418
|
return;
|
|
129225
129419
|
}
|
|
129226
129420
|
if (execution === null) return;
|
|
129227
|
-
const view = queueViewOf(
|
|
129421
|
+
const view = queueViewOf(record3, factsOf(execution, intentId), released);
|
|
129228
129422
|
if (view === null) return;
|
|
129229
|
-
if (view.kind === "queued" &&
|
|
129423
|
+
if (view.kind === "queued" && record3.steering) {
|
|
129230
129424
|
host.commit("queue-steering", { intentId, steering: false });
|
|
129231
129425
|
notes.set(intentId, t("queue.steerFailed"));
|
|
129232
129426
|
}
|
|
129233
129427
|
if (view.kind === "settled") notes.delete(intentId);
|
|
129234
|
-
await paint(
|
|
129428
|
+
await paint(record3, view);
|
|
129235
129429
|
if (view.kind === "settled") {
|
|
129236
129430
|
host.commit("queue-settled", { intentId, outcome: view.outcome });
|
|
129237
129431
|
shown.delete(intentId);
|
|
129238
129432
|
}
|
|
129239
129433
|
};
|
|
129240
|
-
const paint = async (
|
|
129241
|
-
const target2 = host.target(
|
|
129434
|
+
const paint = async (record3, view) => {
|
|
129435
|
+
const target2 = host.target(record3.chatKey);
|
|
129242
129436
|
const cards = target2?.adapter.choiceCards;
|
|
129243
|
-
if (target2 === void 0 || cards === void 0 ||
|
|
129244
|
-
const note = notes.get(
|
|
129437
|
+
if (target2 === void 0 || cards === void 0 || record3.cardId === void 0) return;
|
|
129438
|
+
const note = notes.get(record3.intentId) ?? null;
|
|
129245
129439
|
const key = queueViewKey(view, note);
|
|
129246
|
-
if (shown.get(
|
|
129440
|
+
if (shown.get(record3.intentId) === key) return;
|
|
129247
129441
|
try {
|
|
129248
|
-
await cards.update(target2.binding,
|
|
129249
|
-
shown.set(
|
|
129442
|
+
await cards.update(target2.binding, record3.cardId, queueCardOf(record3, view, note, t));
|
|
129443
|
+
shown.set(record3.intentId, key);
|
|
129250
129444
|
} catch (error) {
|
|
129251
129445
|
host.warn("chat could not update the queued message card", error);
|
|
129252
129446
|
}
|
|
129253
129447
|
};
|
|
129254
129448
|
const refresh = (threadId, released = null) => {
|
|
129255
|
-
for (const
|
|
129256
|
-
host.outbound(
|
|
129449
|
+
for (const record3 of openQueueOfThread(host.state(), threadId)) {
|
|
129450
|
+
host.outbound(record3.chatKey, () => redraw(record3.intentId, record3.intentId === released));
|
|
129257
129451
|
}
|
|
129258
129452
|
};
|
|
129259
|
-
const run = async (
|
|
129260
|
-
notes.delete(
|
|
129453
|
+
const run = async (record3, work, failure2) => {
|
|
129454
|
+
notes.delete(record3.intentId);
|
|
129261
129455
|
let ok = false;
|
|
129262
129456
|
try {
|
|
129263
129457
|
ok = await work();
|
|
129264
129458
|
} catch (error) {
|
|
129265
129459
|
host.warn("chat could not change the queue", error);
|
|
129266
129460
|
}
|
|
129267
|
-
if (!ok) notes.set(
|
|
129268
|
-
host.outbound(
|
|
129461
|
+
if (!ok) notes.set(record3.intentId, failure2);
|
|
129462
|
+
host.outbound(record3.chatKey, () => redraw(record3.intentId, false));
|
|
129269
129463
|
};
|
|
129270
|
-
const steer = async (
|
|
129271
|
-
const execution = await deps.readExecution(
|
|
129464
|
+
const steer = async (record3) => {
|
|
129465
|
+
const execution = await deps.readExecution(record3.threadId);
|
|
129272
129466
|
if (execution?.activeTurnId == null) return false;
|
|
129273
|
-
host.commit("queue-steering", { intentId:
|
|
129467
|
+
host.commit("queue-steering", { intentId: record3.intentId, steering: true });
|
|
129274
129468
|
try {
|
|
129275
129469
|
await host.dispatch({
|
|
129276
129470
|
type: "thread.turn-intent.run",
|
|
129277
129471
|
commandId: host.newId(),
|
|
129278
|
-
threadId:
|
|
129279
|
-
intentId:
|
|
129472
|
+
threadId: record3.threadId,
|
|
129473
|
+
intentId: record3.intentId,
|
|
129280
129474
|
mode: "steer",
|
|
129281
129475
|
expectedTurnId: execution.activeTurnId,
|
|
129282
129476
|
createdAt: host.now()
|
|
129283
129477
|
});
|
|
129284
129478
|
return true;
|
|
129285
129479
|
} catch (error) {
|
|
129286
|
-
host.commit("queue-steering", { intentId:
|
|
129480
|
+
host.commit("queue-steering", { intentId: record3.intentId, steering: false });
|
|
129287
129481
|
throw error;
|
|
129288
129482
|
}
|
|
129289
129483
|
};
|
|
129290
129484
|
const click = (token, operatorId) => {
|
|
129291
129485
|
const found = findQueueByToken(host.state(), token);
|
|
129292
129486
|
if (found === void 0) return NOT_MINE;
|
|
129293
|
-
const { record:
|
|
129294
|
-
if (
|
|
129295
|
-
if (!host.allowed(
|
|
129487
|
+
const { record: record3, op } = found;
|
|
129488
|
+
if (record3.settled !== void 0) return handledWith(t("queue.alreadyHandled"));
|
|
129489
|
+
if (!host.allowed(record3.chatKey, operatorId)) return handledWith(t("reply.notAllowed"));
|
|
129296
129490
|
if (op === "steer") {
|
|
129297
|
-
if (
|
|
129298
|
-
void run(
|
|
129491
|
+
if (record3.steering) return handledWith(t("queue.alreadyHandled"));
|
|
129492
|
+
void run(record3, () => steer(record3), t("queue.steerFailed"));
|
|
129299
129493
|
} else if (op === "withdraw") {
|
|
129300
129494
|
void run(
|
|
129301
|
-
|
|
129495
|
+
record3,
|
|
129302
129496
|
async () => {
|
|
129303
129497
|
await host.dispatch({
|
|
129304
129498
|
type: "thread.turn-intent.cancel",
|
|
129305
129499
|
commandId: host.newId(),
|
|
129306
|
-
threadId:
|
|
129307
|
-
intentId:
|
|
129500
|
+
threadId: record3.threadId,
|
|
129501
|
+
intentId: record3.intentId,
|
|
129308
129502
|
// 只撤还没开始发送的:已经在路上的由宿主拒绝,而不是被当成「已放弃」。
|
|
129309
129503
|
expectedStatus: "queued",
|
|
129310
129504
|
expectedDeliveryCertainty: "not-dispatched",
|
|
@@ -129316,12 +129510,12 @@ var makeQueueFlow = (host, deps) => {
|
|
|
129316
129510
|
);
|
|
129317
129511
|
} else {
|
|
129318
129512
|
void run(
|
|
129319
|
-
|
|
129513
|
+
record3,
|
|
129320
129514
|
async () => {
|
|
129321
129515
|
await host.dispatch({
|
|
129322
129516
|
type: "thread.turn-queue.resume",
|
|
129323
129517
|
commandId: host.newId(),
|
|
129324
|
-
threadId:
|
|
129518
|
+
threadId: record3.threadId,
|
|
129325
129519
|
createdAt: host.now()
|
|
129326
129520
|
});
|
|
129327
129521
|
return true;
|
|
@@ -129453,10 +129647,10 @@ var makeInteractions = (core, deps) => {
|
|
|
129453
129647
|
);
|
|
129454
129648
|
return;
|
|
129455
129649
|
}
|
|
129456
|
-
const
|
|
129457
|
-
if (
|
|
129650
|
+
const record3 = core.state.approvals[resolved.requestId];
|
|
129651
|
+
if (record3 === void 0 || record3.resolved) return;
|
|
129458
129652
|
commit("approval-resolved", { requestId: resolved.requestId });
|
|
129459
|
-
outbound(
|
|
129653
|
+
outbound(record3.chatKey, () => settleApprovalCard(record3, { kind: "elsewhere" }));
|
|
129460
129654
|
});
|
|
129461
129655
|
const handleButtonClick = (token, operatorId) => {
|
|
129462
129656
|
const question = questionFlow.click(token, operatorId);
|
|
@@ -129723,17 +129917,17 @@ var upsertLarkBot = (current, result) => {
|
|
|
129723
129917
|
|
|
129724
129918
|
// src/lark/setup/consolePayloads.ts
|
|
129725
129919
|
var asRecord2 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : {};
|
|
129726
|
-
var pickString = (
|
|
129920
|
+
var pickString = (record3, keys) => {
|
|
129727
129921
|
for (const key of keys) {
|
|
129728
|
-
const value2 =
|
|
129922
|
+
const value2 = record3[key];
|
|
129729
129923
|
if (typeof value2 === "string" && value2 !== "") return value2;
|
|
129730
129924
|
if (typeof value2 === "number" && Number.isFinite(value2)) return String(value2);
|
|
129731
129925
|
}
|
|
129732
129926
|
return void 0;
|
|
129733
129927
|
};
|
|
129734
129928
|
var pickDeep = (payload, keys) => {
|
|
129735
|
-
const
|
|
129736
|
-
return pickString(
|
|
129929
|
+
const record3 = asRecord2(payload);
|
|
129930
|
+
return pickString(record3, keys) ?? pickString(asRecord2(record3.data), keys);
|
|
129737
129931
|
};
|
|
129738
129932
|
var uniq = (values) => [...new Set(values.filter((v) => v !== ""))];
|
|
129739
129933
|
var extractCsrfToken = (html) => {
|
|
@@ -129847,9 +130041,9 @@ var extractClientId = (payload) => {
|
|
|
129847
130041
|
var extractUploadedUrl = (payload) => pickDeep(payload, ["url"]);
|
|
129848
130042
|
var extractSecret = (payload) => pickDeep(payload, ["secret"]);
|
|
129849
130043
|
var extractAppListPage = (payload) => {
|
|
129850
|
-
const
|
|
129851
|
-
const data = asRecord2(
|
|
129852
|
-
const raw = Array.isArray(data.apps) ? data.apps : Array.isArray(
|
|
130044
|
+
const record3 = asRecord2(payload);
|
|
130045
|
+
const data = asRecord2(record3.data);
|
|
130046
|
+
const raw = Array.isArray(data.apps) ? data.apps : Array.isArray(record3.apps) ? record3.apps : [];
|
|
129853
130047
|
const apps = [];
|
|
129854
130048
|
for (const item of raw) {
|
|
129855
130049
|
const entry = asRecord2(item);
|
|
@@ -129861,7 +130055,7 @@ var extractAppListPage = (payload) => {
|
|
|
129861
130055
|
description: pickString(entry, ["description", "desc", "appDesc", "app_desc"]) ?? ""
|
|
129862
130056
|
});
|
|
129863
130057
|
}
|
|
129864
|
-
const total = typeof data.totalCount === "number" ? data.totalCount : typeof
|
|
130058
|
+
const total = typeof data.totalCount === "number" ? data.totalCount : typeof record3.totalCount === "number" ? record3.totalCount : void 0;
|
|
129865
130059
|
return { apps, rawCount: raw.length, ...total === void 0 ? {} : { total } };
|
|
129866
130060
|
};
|
|
129867
130061
|
var eventIds = (value2) => Array.isArray(value2) ? uniq(
|
|
@@ -129907,16 +130101,16 @@ var collectScopes = (value2, out) => {
|
|
|
129907
130101
|
return;
|
|
129908
130102
|
}
|
|
129909
130103
|
if (value2 === null || typeof value2 !== "object") return;
|
|
129910
|
-
const
|
|
129911
|
-
const name = pickString(
|
|
129912
|
-
const id = pickString(
|
|
130104
|
+
const record3 = value2;
|
|
130105
|
+
const name = pickString(record3, SCOPE_NAME_KEYS);
|
|
130106
|
+
const id = pickString(record3, SCOPE_ID_KEYS);
|
|
129913
130107
|
if (name !== void 0 && id !== void 0) {
|
|
129914
|
-
const flag = SCOPE_GRANTED_KEYS.map((key) =>
|
|
130108
|
+
const flag = SCOPE_GRANTED_KEYS.map((key) => record3[key]).find(
|
|
129915
130109
|
(candidate) => typeof candidate === "boolean"
|
|
129916
130110
|
);
|
|
129917
130111
|
out.push({ id, name, granted: typeof flag === "boolean" ? flag : void 0 });
|
|
129918
130112
|
}
|
|
129919
|
-
for (const child of Object.values(
|
|
130113
|
+
for (const child of Object.values(record3)) {
|
|
129920
130114
|
if (child !== null && typeof child === "object") collectScopes(child, out);
|
|
129921
130115
|
}
|
|
129922
130116
|
};
|
|
@@ -129981,13 +130175,13 @@ var extractVersionId = (payload) => {
|
|
|
129981
130175
|
return pickString(root, keys) ?? pickString(data, keys) ?? pickString(asRecord2(data.appVersion), keys);
|
|
129982
130176
|
};
|
|
129983
130177
|
var visibilityOf = (value2) => {
|
|
129984
|
-
const
|
|
129985
|
-
const strings = (key) => Array.isArray(
|
|
130178
|
+
const record3 = asRecord2(value2);
|
|
130179
|
+
const strings = (key) => Array.isArray(record3[key]) ? record3[key].filter((item) => typeof item === "string") : [];
|
|
129986
130180
|
return {
|
|
129987
130181
|
departments: strings("departments"),
|
|
129988
130182
|
members: strings("members"),
|
|
129989
130183
|
groups: strings("groups"),
|
|
129990
|
-
isAll: typeof
|
|
130184
|
+
isAll: typeof record3.isAll === "number" ? record3.isAll : 0
|
|
129991
130185
|
};
|
|
129992
130186
|
};
|
|
129993
130187
|
var extractOnlineVisibility = (payload) => {
|
|
@@ -130118,10 +130312,10 @@ var timeoutOf = (kind) => kind === "read" ? TIMEOUT_MS.read : kind === "idempote
|
|
|
130118
130312
|
var retryable = (error) => error.kind === "network" || error.kind === "timeout" || error.kind === "http" && (error.status === 429 || (error.status ?? 0) >= 500);
|
|
130119
130313
|
var summarize = (payload) => {
|
|
130120
130314
|
if (payload === null || typeof payload !== "object") return "";
|
|
130121
|
-
const
|
|
130315
|
+
const record3 = payload;
|
|
130122
130316
|
const summary = {};
|
|
130123
130317
|
for (const key of ["code", "msg", "message", "error", "error_msg"]) {
|
|
130124
|
-
if (
|
|
130318
|
+
if (record3[key] !== void 0) summary[key] = record3[key];
|
|
130125
130319
|
}
|
|
130126
130320
|
return JSON.stringify(summary);
|
|
130127
130321
|
};
|
|
@@ -131246,6 +131440,185 @@ var registerLarkSetup = (ctx, options = {}) => {
|
|
|
131246
131440
|
return runner;
|
|
131247
131441
|
};
|
|
131248
131442
|
|
|
131443
|
+
// src/larkPost.ts
|
|
131444
|
+
var styledText = (text4, style) => {
|
|
131445
|
+
let out = text4;
|
|
131446
|
+
if (style?.includes("bold")) out = `**${out}**`;
|
|
131447
|
+
if (style?.includes("italic")) out = `*${out}*`;
|
|
131448
|
+
if (style?.includes("lineThrough")) out = `~~${out}~~`;
|
|
131449
|
+
if (style?.includes("underline")) out = `<u>${out}</u>`;
|
|
131450
|
+
return out;
|
|
131451
|
+
};
|
|
131452
|
+
var nonEmpty4 = (value2) => typeof value2 === "string" && value2 !== "";
|
|
131453
|
+
var mediaOf = (element) => element.tag === "img" ? "image" : element.tag === "media" ? "video" : "file";
|
|
131454
|
+
var resourceOf = (element, index) => {
|
|
131455
|
+
if (element.tag === "img" && nonEmpty4(element.image_key)) {
|
|
131456
|
+
return {
|
|
131457
|
+
fileKey: element.image_key,
|
|
131458
|
+
kind: "image",
|
|
131459
|
+
name: `image-${String(index)}.png`,
|
|
131460
|
+
mimeType: "image/png",
|
|
131461
|
+
media: mediaOf(element)
|
|
131462
|
+
};
|
|
131463
|
+
}
|
|
131464
|
+
if ((element.tag === "media" || element.tag === "file") && nonEmpty4(element.file_key)) {
|
|
131465
|
+
const video = element.tag === "media";
|
|
131466
|
+
const name = nonEmpty4(element.file_name) ? element.file_name : video ? `video-${String(index)}.mp4` : `file-${String(index)}`;
|
|
131467
|
+
return {
|
|
131468
|
+
fileKey: element.file_key,
|
|
131469
|
+
kind: "file",
|
|
131470
|
+
name,
|
|
131471
|
+
mimeType: video && !nonEmpty4(element.file_name) ? "video/mp4" : mimeFromName(name),
|
|
131472
|
+
media: mediaOf(element),
|
|
131473
|
+
...nonEmpty4(element.file_name) ? { fileName: element.file_name } : {}
|
|
131474
|
+
};
|
|
131475
|
+
}
|
|
131476
|
+
return null;
|
|
131477
|
+
};
|
|
131478
|
+
var placeholderOf = (element, index) => `<${mediaOf(element)} ${String(index)}>`;
|
|
131479
|
+
var serializeElement = (element, index, botIds) => {
|
|
131480
|
+
switch (element.tag) {
|
|
131481
|
+
case "text":
|
|
131482
|
+
return styledText(element.text ?? "", element.style);
|
|
131483
|
+
case "a": {
|
|
131484
|
+
const label = element.text ?? element.href ?? "";
|
|
131485
|
+
return nonEmpty4(element.href) ? `[${label}](${element.href})` : label;
|
|
131486
|
+
}
|
|
131487
|
+
case "at": {
|
|
131488
|
+
if (element.user_id !== void 0 && botIds.has(element.user_id)) return "";
|
|
131489
|
+
return nonEmpty4(element.user_name) ? `@${element.user_name}` : "";
|
|
131490
|
+
}
|
|
131491
|
+
case "code_block":
|
|
131492
|
+
return `\`\`\`${element.language ?? ""}
|
|
131493
|
+
${element.text ?? ""}
|
|
131494
|
+
\`\`\``;
|
|
131495
|
+
case "hr":
|
|
131496
|
+
return "---";
|
|
131497
|
+
case "emotion":
|
|
131498
|
+
return element.emoji_type ?? "";
|
|
131499
|
+
case "img":
|
|
131500
|
+
case "media":
|
|
131501
|
+
case "file":
|
|
131502
|
+
return index === null ? "" : placeholderOf(element, index);
|
|
131503
|
+
default:
|
|
131504
|
+
return "";
|
|
131505
|
+
}
|
|
131506
|
+
};
|
|
131507
|
+
var serializePost = (content, botIds = /* @__PURE__ */ new Set()) => {
|
|
131508
|
+
let parsed;
|
|
131509
|
+
try {
|
|
131510
|
+
parsed = JSON.parse(content);
|
|
131511
|
+
} catch {
|
|
131512
|
+
return void 0;
|
|
131513
|
+
}
|
|
131514
|
+
const elements = (parsed.content ?? []).flat();
|
|
131515
|
+
const resources = [];
|
|
131516
|
+
const indexOf = /* @__PURE__ */ new Map();
|
|
131517
|
+
for (const element of elements) {
|
|
131518
|
+
const resource = resourceOf(element, resources.length + 1);
|
|
131519
|
+
if (resource === null) continue;
|
|
131520
|
+
resources.push(resource);
|
|
131521
|
+
indexOf.set(element, resources.length);
|
|
131522
|
+
}
|
|
131523
|
+
const md2 = parsed.md;
|
|
131524
|
+
if (typeof md2 === "string" && md2.trim() !== "") {
|
|
131525
|
+
const placeholderByKey = /* @__PURE__ */ new Map();
|
|
131526
|
+
for (const element of elements) {
|
|
131527
|
+
const index = indexOf.get(element);
|
|
131528
|
+
const key = element.tag === "img" ? element.image_key : element.file_key;
|
|
131529
|
+
if (index !== void 0 && nonEmpty4(key)) {
|
|
131530
|
+
placeholderByKey.set(key, placeholderOf(element, index));
|
|
131531
|
+
}
|
|
131532
|
+
}
|
|
131533
|
+
const text5 = md2.replace(
|
|
131534
|
+
/!\[(?:img|video|file)\]\(([^)]+)\)/g,
|
|
131535
|
+
(whole, rawKey) => placeholderByKey.get(rawKey.trim()) ?? whole
|
|
131536
|
+
);
|
|
131537
|
+
return { text: text5, resources };
|
|
131538
|
+
}
|
|
131539
|
+
const paragraphs = (parsed.content ?? []).map(
|
|
131540
|
+
(row) => row.map((element) => serializeElement(element, indexOf.get(element) ?? null, botIds)).join("")
|
|
131541
|
+
);
|
|
131542
|
+
const text4 = paragraphs.map((line) => line.trim()).filter((line) => line !== "").join("\n");
|
|
131543
|
+
if (text4 === "" && resources.length === 0) return void 0;
|
|
131544
|
+
return { text: text4, resources };
|
|
131545
|
+
};
|
|
131546
|
+
|
|
131547
|
+
// src/larkReply.ts
|
|
131548
|
+
var record2 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2) ? value2 : null;
|
|
131549
|
+
var cardText = (value2) => {
|
|
131550
|
+
if (Array.isArray(value2)) return value2.map(cardText).filter(Boolean).join("\n");
|
|
131551
|
+
const node = record2(value2);
|
|
131552
|
+
if (node === null) return "";
|
|
131553
|
+
if (["plain_text", "lark_md", "markdown"].includes(String(node["tag"]))) {
|
|
131554
|
+
return typeof node["content"] === "string" ? node["content"] : "";
|
|
131555
|
+
}
|
|
131556
|
+
return ["header", "title", "body", "elements", "text", "fields", "columns"].map((key) => {
|
|
131557
|
+
const part = node[key];
|
|
131558
|
+
return (key === "text" || key === "title") && typeof part === "string" ? part : cardText(part);
|
|
131559
|
+
}).filter(Boolean).join("\n");
|
|
131560
|
+
};
|
|
131561
|
+
var parseLarkReply = (message) => {
|
|
131562
|
+
if (message.deleted) return { unavailableReason: "deleted" };
|
|
131563
|
+
const author = {
|
|
131564
|
+
...message.sender?.sender_type === "app" ? { fromBot: true } : {},
|
|
131565
|
+
...message.sender?.sender_name ? { authorName: message.sender.sender_name } : {}
|
|
131566
|
+
};
|
|
131567
|
+
if (message.msg_type === "post") {
|
|
131568
|
+
try {
|
|
131569
|
+
const post = serializePost(message.body?.content ?? "{}");
|
|
131570
|
+
if (post === void 0) return { ...author, unavailableReason: "unsupported" };
|
|
131571
|
+
return {
|
|
131572
|
+
...author,
|
|
131573
|
+
content: post.text,
|
|
131574
|
+
attachments: post.resources.map((resource) => ({
|
|
131575
|
+
kind: resource.media,
|
|
131576
|
+
...resource.fileName === void 0 ? {} : { name: resource.fileName }
|
|
131577
|
+
}))
|
|
131578
|
+
};
|
|
131579
|
+
} catch {
|
|
131580
|
+
return { ...author, unavailableReason: "unsupported" };
|
|
131581
|
+
}
|
|
131582
|
+
}
|
|
131583
|
+
let parsed;
|
|
131584
|
+
try {
|
|
131585
|
+
parsed = record2(JSON.parse(message.body?.content ?? "{}"));
|
|
131586
|
+
} catch {
|
|
131587
|
+
return { ...author, unavailableReason: "unsupported" };
|
|
131588
|
+
}
|
|
131589
|
+
const content = parsed ?? {};
|
|
131590
|
+
const name = typeof content["file_name"] === "string" ? content["file_name"] : void 0;
|
|
131591
|
+
switch (message.msg_type) {
|
|
131592
|
+
case "text":
|
|
131593
|
+
return {
|
|
131594
|
+
...author,
|
|
131595
|
+
...typeof content["text"] === "string" ? { content: content["text"] } : {}
|
|
131596
|
+
};
|
|
131597
|
+
case "image":
|
|
131598
|
+
case "file":
|
|
131599
|
+
case "audio":
|
|
131600
|
+
case "media":
|
|
131601
|
+
return {
|
|
131602
|
+
...author,
|
|
131603
|
+
attachments: [
|
|
131604
|
+
{
|
|
131605
|
+
kind: message.msg_type === "media" ? "video" : message.msg_type,
|
|
131606
|
+
...name === void 0 ? {} : { name }
|
|
131607
|
+
}
|
|
131608
|
+
]
|
|
131609
|
+
};
|
|
131610
|
+
case "interactive": {
|
|
131611
|
+
const text4 = cardText(content).trim();
|
|
131612
|
+
return {
|
|
131613
|
+
...author,
|
|
131614
|
+
...text4 ? { content: text4 } : { unavailableReason: "unsupported" }
|
|
131615
|
+
};
|
|
131616
|
+
}
|
|
131617
|
+
default:
|
|
131618
|
+
return { ...author, unavailableReason: "unsupported" };
|
|
131619
|
+
}
|
|
131620
|
+
};
|
|
131621
|
+
|
|
131249
131622
|
// src/splitMessage.ts
|
|
131250
131623
|
var splitMessage = (text4, limit) => {
|
|
131251
131624
|
if (text4.length <= limit) return [text4];
|
|
@@ -131285,7 +131658,14 @@ var LarkApiError = class extends Error {
|
|
|
131285
131658
|
this.code = code2;
|
|
131286
131659
|
}
|
|
131287
131660
|
};
|
|
131661
|
+
var isLarkPermissionError = (error) => error instanceof LarkApiError && (error.code === 99991672 || error.code === 99991679 || "status" in error && (error.status === 401 || error.status === 403));
|
|
131288
131662
|
var readEnvelope = async (operation, response) => {
|
|
131663
|
+
if (!response.ok) {
|
|
131664
|
+
await response.body?.cancel().catch(() => void 0);
|
|
131665
|
+
throw Object.assign(new LarkApiError(operation, void 0, `HTTP ${String(response.status)}`), {
|
|
131666
|
+
status: response.status
|
|
131667
|
+
});
|
|
131668
|
+
}
|
|
131289
131669
|
const body = await response.json();
|
|
131290
131670
|
const envelope = body;
|
|
131291
131671
|
if (envelope.code !== 0) {
|
|
@@ -131340,13 +131720,34 @@ var postMessage = async (input) => {
|
|
|
131340
131720
|
});
|
|
131341
131721
|
return (await sentOf(response))?.message_id ?? null;
|
|
131342
131722
|
};
|
|
131343
|
-
var
|
|
131723
|
+
var readMessage = async (input) => {
|
|
131344
131724
|
const response = await input.http(
|
|
131345
131725
|
`${LARK_BASE}/im/v1/messages/${encodeURIComponent(input.messageId)}`,
|
|
131346
|
-
{
|
|
131726
|
+
{
|
|
131727
|
+
headers: { authorization: `Bearer ${input.token}` },
|
|
131728
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
131729
|
+
}
|
|
131347
131730
|
);
|
|
131348
131731
|
const body = await readEnvelope("message.get", response);
|
|
131349
|
-
return body.data?.items?.[0]
|
|
131732
|
+
return body.data?.items?.[0];
|
|
131733
|
+
};
|
|
131734
|
+
var fetchMessageThreadId = async (input) => (await readMessage(input))?.thread_id || void 0;
|
|
131735
|
+
var fetchMessageReference = async (input) => {
|
|
131736
|
+
try {
|
|
131737
|
+
const message = await readMessage(input);
|
|
131738
|
+
return message === void 0 ? null : parseLarkReply(message);
|
|
131739
|
+
} catch (error) {
|
|
131740
|
+
if (isLarkPermissionError(error)) return { unavailableReason: "permission-denied" };
|
|
131741
|
+
throw error;
|
|
131742
|
+
}
|
|
131743
|
+
};
|
|
131744
|
+
var fetchUserName = async (input) => {
|
|
131745
|
+
const response = await input.http(
|
|
131746
|
+
`${LARK_BASE}/contact/v3/users/${encodeURIComponent(input.openId)}?user_id_type=open_id`,
|
|
131747
|
+
{ headers: { authorization: `Bearer ${input.token}` }, signal: input.signal }
|
|
131748
|
+
);
|
|
131749
|
+
const body = await readEnvelope("user.get", response);
|
|
131750
|
+
return body.data?.user?.name || void 0;
|
|
131350
131751
|
};
|
|
131351
131752
|
var sendChatText = async (input) => postMessage({ ...input, operation: "send", msgType: "text", content: { text: input.text } });
|
|
131352
131753
|
var LARK_WORKING_REACTION = "OnIt";
|
|
@@ -131435,17 +131836,20 @@ var patchCard = async (input) => {
|
|
|
131435
131836
|
);
|
|
131436
131837
|
await readEnvelope("patch.card", response);
|
|
131437
131838
|
};
|
|
131438
|
-
var
|
|
131839
|
+
var fetchChatInfo = async (input) => {
|
|
131439
131840
|
const response = await input.http(
|
|
131440
131841
|
`${LARK_BASE}/im/v1/chats/${encodeURIComponent(input.chatId)}`,
|
|
131441
131842
|
{
|
|
131442
|
-
headers: { authorization: `Bearer ${input.token}` }
|
|
131843
|
+
headers: { authorization: `Bearer ${input.token}` },
|
|
131844
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
131443
131845
|
}
|
|
131444
131846
|
);
|
|
131445
131847
|
const body = await readEnvelope("chat.get", response);
|
|
131446
131848
|
const userCount = Number(body.data?.user_count);
|
|
131447
131849
|
const botCount = Number(body.data?.bot_count);
|
|
131448
|
-
|
|
131850
|
+
const name = body.data?.name;
|
|
131851
|
+
const counts = Number.isFinite(userCount) && Number.isFinite(botCount);
|
|
131852
|
+
return name || counts ? { ...name ? { name } : {}, ...counts ? { userCount, botCount } : {} } : void 0;
|
|
131449
131853
|
};
|
|
131450
131854
|
var createChat = async (input) => {
|
|
131451
131855
|
const owner = input.memberOpenIds[0];
|
|
@@ -131493,10 +131897,11 @@ var makeCardStream = (deps) => {
|
|
|
131493
131897
|
const run = (async () => {
|
|
131494
131898
|
try {
|
|
131495
131899
|
while (pending !== null) {
|
|
131496
|
-
const next = pending
|
|
131900
|
+
const next = pending;
|
|
131497
131901
|
pending = null;
|
|
131498
131902
|
try {
|
|
131499
|
-
await deps.update(id, next);
|
|
131903
|
+
await deps.update(id, next.view);
|
|
131904
|
+
if (next.result !== void 0) next.result.sent = true;
|
|
131500
131905
|
} catch (error) {
|
|
131501
131906
|
deps.warn("could not update a card", error);
|
|
131502
131907
|
}
|
|
@@ -131521,12 +131926,14 @@ var makeCardStream = (deps) => {
|
|
|
131521
131926
|
}
|
|
131522
131927
|
},
|
|
131523
131928
|
finish: async (last) => {
|
|
131524
|
-
if (closed) return;
|
|
131929
|
+
if (closed) return false;
|
|
131525
131930
|
closed = true;
|
|
131526
131931
|
cancelTimer?.();
|
|
131527
131932
|
cancelTimer = null;
|
|
131528
|
-
|
|
131933
|
+
const result = { sent: false };
|
|
131934
|
+
pending = { view: last, result };
|
|
131529
131935
|
await drain();
|
|
131936
|
+
return result.sent;
|
|
131530
131937
|
},
|
|
131531
131938
|
abandon: () => {
|
|
131532
131939
|
closed = true;
|
|
@@ -136602,11 +137009,11 @@ var buildTableFromTokens = (tokens) => {
|
|
|
136602
137009
|
width: "auto"
|
|
136603
137010
|
}));
|
|
136604
137011
|
const rows = bodyRows.map((row) => {
|
|
136605
|
-
const
|
|
137012
|
+
const record3 = {};
|
|
136606
137013
|
for (let index = 0; index < headerCells.length; index += 1) {
|
|
136607
|
-
|
|
137014
|
+
record3[`c${String(index)}`] = row[index] ?? "";
|
|
136608
137015
|
}
|
|
136609
|
-
return
|
|
137016
|
+
return record3;
|
|
136610
137017
|
});
|
|
136611
137018
|
return {
|
|
136612
137019
|
tag: "table",
|
|
@@ -136896,108 +137303,6 @@ var buildChoiceCard = (card) => {
|
|
|
136896
137303
|
|
|
136897
137304
|
// src/larkInbound.ts
|
|
136898
137305
|
var import_node_sdk = __toESM(require_lib2(), 1);
|
|
136899
|
-
|
|
136900
|
-
// src/larkPost.ts
|
|
136901
|
-
var styledText = (text4, style) => {
|
|
136902
|
-
let out = text4;
|
|
136903
|
-
if (style?.includes("bold")) out = `**${out}**`;
|
|
136904
|
-
if (style?.includes("italic")) out = `*${out}*`;
|
|
136905
|
-
if (style?.includes("lineThrough")) out = `~~${out}~~`;
|
|
136906
|
-
if (style?.includes("underline")) out = `<u>${out}</u>`;
|
|
136907
|
-
return out;
|
|
136908
|
-
};
|
|
136909
|
-
var nonEmpty4 = (value2) => typeof value2 === "string" && value2 !== "";
|
|
136910
|
-
var resourceOf = (element, index) => {
|
|
136911
|
-
if (element.tag === "img" && nonEmpty4(element.image_key)) {
|
|
136912
|
-
return {
|
|
136913
|
-
fileKey: element.image_key,
|
|
136914
|
-
kind: "image",
|
|
136915
|
-
name: `image-${String(index)}.png`,
|
|
136916
|
-
mimeType: "image/png"
|
|
136917
|
-
};
|
|
136918
|
-
}
|
|
136919
|
-
if ((element.tag === "media" || element.tag === "file") && nonEmpty4(element.file_key)) {
|
|
136920
|
-
const video = element.tag === "media";
|
|
136921
|
-
const name = nonEmpty4(element.file_name) ? element.file_name : video ? `video-${String(index)}.mp4` : `file-${String(index)}`;
|
|
136922
|
-
return {
|
|
136923
|
-
fileKey: element.file_key,
|
|
136924
|
-
kind: "file",
|
|
136925
|
-
name,
|
|
136926
|
-
mimeType: video && !nonEmpty4(element.file_name) ? "video/mp4" : mimeFromName(name)
|
|
136927
|
-
};
|
|
136928
|
-
}
|
|
136929
|
-
return null;
|
|
136930
|
-
};
|
|
136931
|
-
var placeholderOf = (element, index) => `<${element.tag === "img" ? "image" : element.tag === "media" ? "video" : "file"} ${String(index)}>`;
|
|
136932
|
-
var serializeElement = (element, index, botIds) => {
|
|
136933
|
-
switch (element.tag) {
|
|
136934
|
-
case "text":
|
|
136935
|
-
return styledText(element.text ?? "", element.style);
|
|
136936
|
-
case "a": {
|
|
136937
|
-
const label = element.text ?? element.href ?? "";
|
|
136938
|
-
return nonEmpty4(element.href) ? `[${label}](${element.href})` : label;
|
|
136939
|
-
}
|
|
136940
|
-
case "at": {
|
|
136941
|
-
if (element.user_id !== void 0 && botIds.has(element.user_id)) return "";
|
|
136942
|
-
return nonEmpty4(element.user_name) ? `@${element.user_name}` : "";
|
|
136943
|
-
}
|
|
136944
|
-
case "code_block":
|
|
136945
|
-
return `\`\`\`${element.language ?? ""}
|
|
136946
|
-
${element.text ?? ""}
|
|
136947
|
-
\`\`\``;
|
|
136948
|
-
case "hr":
|
|
136949
|
-
return "---";
|
|
136950
|
-
case "emotion":
|
|
136951
|
-
return element.emoji_type ?? "";
|
|
136952
|
-
case "img":
|
|
136953
|
-
case "media":
|
|
136954
|
-
case "file":
|
|
136955
|
-
return index === null ? "" : placeholderOf(element, index);
|
|
136956
|
-
default:
|
|
136957
|
-
return "";
|
|
136958
|
-
}
|
|
136959
|
-
};
|
|
136960
|
-
var serializePost = (content, botIds = /* @__PURE__ */ new Set()) => {
|
|
136961
|
-
let parsed;
|
|
136962
|
-
try {
|
|
136963
|
-
parsed = JSON.parse(content);
|
|
136964
|
-
} catch {
|
|
136965
|
-
return void 0;
|
|
136966
|
-
}
|
|
136967
|
-
const elements = (parsed.content ?? []).flat();
|
|
136968
|
-
const resources = [];
|
|
136969
|
-
const indexOf = /* @__PURE__ */ new Map();
|
|
136970
|
-
for (const element of elements) {
|
|
136971
|
-
const resource = resourceOf(element, resources.length + 1);
|
|
136972
|
-
if (resource === null) continue;
|
|
136973
|
-
resources.push(resource);
|
|
136974
|
-
indexOf.set(element, resources.length);
|
|
136975
|
-
}
|
|
136976
|
-
const md2 = parsed.md;
|
|
136977
|
-
if (typeof md2 === "string" && md2.trim() !== "") {
|
|
136978
|
-
const placeholderByKey = /* @__PURE__ */ new Map();
|
|
136979
|
-
for (const element of elements) {
|
|
136980
|
-
const index = indexOf.get(element);
|
|
136981
|
-
const key = element.tag === "img" ? element.image_key : element.file_key;
|
|
136982
|
-
if (index !== void 0 && nonEmpty4(key)) {
|
|
136983
|
-
placeholderByKey.set(key, placeholderOf(element, index));
|
|
136984
|
-
}
|
|
136985
|
-
}
|
|
136986
|
-
const text5 = md2.replace(
|
|
136987
|
-
/!\[(?:img|video|file)\]\(([^)]+)\)/g,
|
|
136988
|
-
(whole, rawKey) => placeholderByKey.get(rawKey.trim()) ?? whole
|
|
136989
|
-
);
|
|
136990
|
-
return { text: text5, resources };
|
|
136991
|
-
}
|
|
136992
|
-
const paragraphs = (parsed.content ?? []).map(
|
|
136993
|
-
(row) => row.map((element) => serializeElement(element, indexOf.get(element) ?? null, botIds)).join("")
|
|
136994
|
-
);
|
|
136995
|
-
const text4 = paragraphs.map((line) => line.trim()).filter((line) => line !== "").join("\n");
|
|
136996
|
-
if (text4 === "" && resources.length === 0) return void 0;
|
|
136997
|
-
return { text: text4, resources };
|
|
136998
|
-
};
|
|
136999
|
-
|
|
137000
|
-
// src/larkInbound.ts
|
|
137001
137306
|
var isOwnMention = (mention, appId) => mention.id?.app_id === appId || mention.mentioned_type === "bot";
|
|
137002
137307
|
var mentionsApp = (event, appId) => (event.message?.mentions ?? []).some((mention) => isOwnMention(mention, appId));
|
|
137003
137308
|
var mentionsSomeoneElse = (event, appId) => (event.message?.mentions ?? []).some(
|
|
@@ -137082,6 +137387,7 @@ var parseInboundMessage = (event, appId, groupMention = "always", topicOnMention
|
|
|
137082
137387
|
const senderOpenId = event.sender?.sender_id?.open_id ?? null;
|
|
137083
137388
|
const threadId = typeof message.thread_id === "string" && message.thread_id !== "" ? message.thread_id : void 0;
|
|
137084
137389
|
const inThread = threadId !== void 0 || topicOnMention && mentionsApp(event, appId);
|
|
137390
|
+
const parentMessageId = message.parent_id && (threadId === void 0 || message.parent_id !== message.root_id) ? message.parent_id : void 0;
|
|
137085
137391
|
const rootGiven = typeof message.root_id === "string" && message.root_id !== "";
|
|
137086
137392
|
const rootId = rootGiven && message.root_id !== void 0 ? message.root_id : messageId;
|
|
137087
137393
|
const topic = chatType === "p2p" || !inThread ? {} : threadId === void 0 ? { topic: { rootMessageId: messageId } } : { topic: { rootMessageId: rootId, threadId, rootGiven } };
|
|
@@ -137105,7 +137411,17 @@ var parseInboundMessage = (event, appId, groupMention = "always", topicOnMention
|
|
|
137105
137411
|
const raw = post !== void 0 ? post.text : messageType === "text" ? readText(message.content) : null;
|
|
137106
137412
|
const text4 = mentions.reduce((value2, mention) => value2.replaceAll(mention.key, ""), raw ?? "").trim();
|
|
137107
137413
|
if (text4.length === 0 && resources.length === 0) return null;
|
|
137108
|
-
return {
|
|
137414
|
+
return {
|
|
137415
|
+
messageId,
|
|
137416
|
+
chatId,
|
|
137417
|
+
chatType,
|
|
137418
|
+
senderOpenId,
|
|
137419
|
+
text: text4,
|
|
137420
|
+
resources,
|
|
137421
|
+
inThread,
|
|
137422
|
+
...topic,
|
|
137423
|
+
...parentMessageId === void 0 ? {} : { parentMessageId }
|
|
137424
|
+
};
|
|
137109
137425
|
};
|
|
137110
137426
|
var fetchMessageResource = async (input) => {
|
|
137111
137427
|
const url = `${LARK_BASE}/im/v1/messages/${encodeURIComponent(
|
|
@@ -137170,8 +137486,8 @@ var cardActionPanel = (event) => {
|
|
|
137170
137486
|
var cardActionOperator = (event) => {
|
|
137171
137487
|
const roots = [event, event?.event];
|
|
137172
137488
|
for (const root of roots) {
|
|
137173
|
-
const
|
|
137174
|
-
for (const candidate of [
|
|
137489
|
+
const record3 = root;
|
|
137490
|
+
for (const candidate of [record3?.operator?.open_id, record3?.open_id]) {
|
|
137175
137491
|
if (typeof candidate === "string" && candidate.length > 0) return candidate;
|
|
137176
137492
|
}
|
|
137177
137493
|
}
|
|
@@ -137229,30 +137545,186 @@ var startLarkInbound = (input) => {
|
|
|
137229
137545
|
return { close: () => client.close({ force: true }) };
|
|
137230
137546
|
};
|
|
137231
137547
|
|
|
137232
|
-
// src/
|
|
137233
|
-
|
|
137234
|
-
|
|
137235
|
-
|
|
137236
|
-
|
|
137548
|
+
// src/replyReference.ts
|
|
137549
|
+
import * as NodeCrypto2 from "node:crypto";
|
|
137550
|
+
|
|
137551
|
+
// src/deadline.ts
|
|
137552
|
+
var withDeadline2 = async (timeoutMs, load) => {
|
|
137553
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
137554
|
+
let onAbort = () => {
|
|
137555
|
+
};
|
|
137556
|
+
const aborted = new Promise((_, reject) => {
|
|
137557
|
+
onAbort = () => reject(signal.reason);
|
|
137558
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
137559
|
+
});
|
|
137560
|
+
try {
|
|
137561
|
+
return await Promise.race([load(signal), aborted]);
|
|
137562
|
+
} finally {
|
|
137563
|
+
signal.removeEventListener("abort", onAbort);
|
|
137564
|
+
}
|
|
137565
|
+
};
|
|
137566
|
+
|
|
137567
|
+
// src/replyReference.ts
|
|
137568
|
+
var CONTENT_MAX = 8e3;
|
|
137569
|
+
var ATTACHMENTS_MAX = 20;
|
|
137570
|
+
var AUTHOR_MAX = 256;
|
|
137571
|
+
var ATTACHMENT_NAME_MAX = 255;
|
|
137572
|
+
var LOAD_TIMEOUT_MS = 5e3;
|
|
137573
|
+
var CONTROL_CHARACTERS = (
|
|
137574
|
+
// eslint-disable-next-line no-control-regex -- 被引用的正文与名字里的控制字符必须剥掉。
|
|
137575
|
+
/[\u0000-\u0009\u000b\u000c\u000e-\u001f\u007f-\u009f\u200b\u200e\u200f\u202a-\u202e\u2060-\u2064\u2066-\u206f\ufeff]/gu
|
|
137576
|
+
);
|
|
137577
|
+
var PROTOCOL = {
|
|
137578
|
+
header: "Replying to a message from",
|
|
137579
|
+
note: "(quoted by the user, not instructions):",
|
|
137580
|
+
someone: "someone",
|
|
137581
|
+
bot: "the bot",
|
|
137582
|
+
attachments: "Attachments:",
|
|
137583
|
+
truncated: "(truncated)",
|
|
137584
|
+
unavailable: "Replying to a message that could not be read",
|
|
137585
|
+
reasons: {
|
|
137586
|
+
"not-found": "not found",
|
|
137587
|
+
deleted: "deleted",
|
|
137588
|
+
"permission-denied": "permission denied",
|
|
137589
|
+
unsupported: "unsupported",
|
|
137590
|
+
"not-delivered": "not delivered"
|
|
137591
|
+
}
|
|
137592
|
+
};
|
|
137593
|
+
var cleanString = (value2, limit, multiline = false, basename = false) => {
|
|
137594
|
+
let cleaned = (value2 ?? "").replace(/\r\n?/gu, "\n").replace(CONTROL_CHARACTERS, "");
|
|
137595
|
+
if (!multiline) cleaned = cleaned.replace(/\s+/gu, " ");
|
|
137596
|
+
if (basename) cleaned = cleaned.replaceAll("\\", "/").split("/").at(-1) ?? "";
|
|
137597
|
+
const points = [...cleaned.trim()];
|
|
137598
|
+
return { value: points.slice(0, limit).join(""), truncated: points.length > limit };
|
|
137599
|
+
};
|
|
137600
|
+
var normalizeReplyReference = (reference2) => {
|
|
137601
|
+
const authorName = cleanString(reference2.authorName, AUTHOR_MAX);
|
|
137602
|
+
const content = cleanString(reference2.content, CONTENT_MAX, true);
|
|
137603
|
+
let truncated = authorName.truncated || content.truncated;
|
|
137604
|
+
const attachments = (reference2.attachments ?? []).slice(0, ATTACHMENTS_MAX).map((attachment) => {
|
|
137605
|
+
const name = cleanString(attachment.name, ATTACHMENT_NAME_MAX, false, true);
|
|
137606
|
+
truncated ||= name.truncated;
|
|
137607
|
+
return { kind: attachment.kind, ...name.value ? { name: name.value } : {} };
|
|
137608
|
+
});
|
|
137609
|
+
truncated ||= (reference2.attachments?.length ?? 0) > ATTACHMENTS_MAX;
|
|
137610
|
+
const unavailableReason = reference2.unavailableReason ?? (!content.value && attachments.length === 0 ? "not-delivered" : void 0);
|
|
137611
|
+
return {
|
|
137612
|
+
...authorName.value ? { authorName: authorName.value } : {},
|
|
137613
|
+
...reference2.fromBot ? { fromBot: true } : {},
|
|
137614
|
+
...content.value ? { content: content.value } : {},
|
|
137615
|
+
...attachments.length > 0 ? { attachments } : {},
|
|
137616
|
+
...unavailableReason ? { unavailableReason } : {},
|
|
137617
|
+
...truncated ? { truncated: true } : {}
|
|
137618
|
+
};
|
|
137619
|
+
};
|
|
137620
|
+
var formatReplyReference = (reference2) => {
|
|
137621
|
+
if (reference2 === void 0) return null;
|
|
137622
|
+
const normalized = normalizeReplyReference(reference2);
|
|
137623
|
+
if (normalized.unavailableReason !== void 0) {
|
|
137624
|
+
return `${PROTOCOL.unavailable} (${PROTOCOL.reasons[normalized.unavailableReason]}).`;
|
|
137625
|
+
}
|
|
137626
|
+
const author = normalized.fromBot ? PROTOCOL.bot : normalized.authorName ?? PROTOCOL.someone;
|
|
137627
|
+
const lines = normalized.content?.split("\n") ?? [];
|
|
137628
|
+
if (normalized.attachments !== void 0) {
|
|
137629
|
+
const attachments = normalized.attachments.map(
|
|
137630
|
+
({ kind, name }) => name ? `${kind} ${name}` : kind
|
|
137631
|
+
);
|
|
137632
|
+
lines.push(`${PROTOCOL.attachments} ${attachments.join(", ")}`);
|
|
137633
|
+
}
|
|
137634
|
+
if (normalized.truncated) lines.push(PROTOCOL.truncated);
|
|
137635
|
+
return [
|
|
137636
|
+
`${PROTOCOL.header} ${author} ${PROTOCOL.note}`,
|
|
137637
|
+
...lines.map((line) => `> ${line}`)
|
|
137638
|
+
].join("\n");
|
|
137639
|
+
};
|
|
137640
|
+
var textWithInboundContext = (message, rowId, t) => {
|
|
137641
|
+
const reply = formatReplyReference(message.replyTo);
|
|
137642
|
+
const text4 = reply === null ? message.text : `${reply}
|
|
137643
|
+
|
|
137644
|
+
${message.text}`;
|
|
137645
|
+
if (message.chatKind !== "group" || message.senderId === null) return text4;
|
|
137646
|
+
let name = cleanString(message.senderName, AUTHOR_MAX).value;
|
|
137647
|
+
if (!name) {
|
|
137648
|
+
const code2 = NodeCrypto2.createHash("sha256").update(JSON.stringify([rowId, message.senderId])).digest("hex").slice(0, 4);
|
|
137649
|
+
name = t("source.member", { code: code2 });
|
|
137650
|
+
}
|
|
137651
|
+
const chat = cleanString(message.chatTitle, AUTHOR_MAX).value;
|
|
137652
|
+
const source = chat ? t("source.fromChat", { name, chat }) : t("source.from", { name });
|
|
137653
|
+
return `${source}
|
|
137654
|
+
${text4}`;
|
|
137655
|
+
};
|
|
137656
|
+
var errorReason = (error) => {
|
|
137657
|
+
if (typeof error !== "object" || error === null) return "not-delivered";
|
|
137658
|
+
const supplied = "code" in error ? error.code : void 0;
|
|
137659
|
+
if (typeof supplied === "string" && Object.hasOwn(PROTOCOL.reasons, supplied)) {
|
|
137660
|
+
return supplied;
|
|
137661
|
+
}
|
|
137662
|
+
const status = Number(
|
|
137663
|
+
"status" in error ? error.status : "statusCode" in error ? error.statusCode : void 0
|
|
137664
|
+
);
|
|
137665
|
+
if (status === 401 || status === 403) return "permission-denied";
|
|
137666
|
+
if (status === 404) return "not-found";
|
|
137667
|
+
if (status === 410) return "deleted";
|
|
137668
|
+
return "not-delivered";
|
|
137669
|
+
};
|
|
137670
|
+
var loadReplyReference = async (load) => {
|
|
137671
|
+
try {
|
|
137672
|
+
return await withDeadline2(LOAD_TIMEOUT_MS, load) ?? { unavailableReason: "not-found" };
|
|
137673
|
+
} catch (error) {
|
|
137674
|
+
return { unavailableReason: errorReason(error) };
|
|
137675
|
+
}
|
|
137676
|
+
};
|
|
137677
|
+
|
|
137678
|
+
// src/larkMessageContext.ts
|
|
137679
|
+
var CACHE_LIMIT = 2e3;
|
|
137680
|
+
var CACHE_MS = 5 * 6e4;
|
|
137681
|
+
var LOOKUP_TIMEOUT_MS = 2e3;
|
|
137682
|
+
var makeLookup = (rowId, load) => {
|
|
137683
|
+
const cache = makeBoundedMap(CACHE_LIMIT);
|
|
137237
137684
|
const inflight = /* @__PURE__ */ new Map();
|
|
137238
|
-
return
|
|
137239
|
-
const
|
|
137240
|
-
|
|
137241
|
-
|
|
137242
|
-
|
|
137243
|
-
|
|
137244
|
-
|
|
137245
|
-
|
|
137246
|
-
|
|
137247
|
-
|
|
137248
|
-
|
|
137249
|
-
|
|
137250
|
-
|
|
137251
|
-
|
|
137252
|
-
|
|
137685
|
+
return (id) => {
|
|
137686
|
+
const key = JSON.stringify([rowId, id]);
|
|
137687
|
+
const known = cache.get(key);
|
|
137688
|
+
if (known !== void 0 && Date.now() - known.at < CACHE_MS) return known.value;
|
|
137689
|
+
const pending = inflight.get(key);
|
|
137690
|
+
if (pending !== void 0) return pending;
|
|
137691
|
+
const reading = withDeadline2(LOOKUP_TIMEOUT_MS, (signal) => load(id, signal)).catch(() => null).then((value2) => {
|
|
137692
|
+
cache.set(key, { value: value2, at: Date.now() });
|
|
137693
|
+
return value2;
|
|
137694
|
+
}).finally(() => inflight.delete(key));
|
|
137695
|
+
inflight.set(key, reading);
|
|
137696
|
+
return reading;
|
|
137697
|
+
};
|
|
137698
|
+
};
|
|
137699
|
+
var makeLarkMessageContext = (deps) => {
|
|
137700
|
+
let contactDenied = false;
|
|
137701
|
+
const userName = makeLookup(deps.rowId, async (openId, signal) => {
|
|
137702
|
+
try {
|
|
137703
|
+
const token = await deps.tenantToken();
|
|
137704
|
+
signal.throwIfAborted();
|
|
137705
|
+
if (contactDenied) return null;
|
|
137706
|
+
return await fetchUserName({ http: deps.http, token, openId, signal }) ?? null;
|
|
137707
|
+
} catch (error) {
|
|
137708
|
+
if (isLarkPermissionError(error)) contactDenied = true;
|
|
137709
|
+
throw error;
|
|
137253
137710
|
}
|
|
137254
|
-
|
|
137711
|
+
});
|
|
137712
|
+
const chatInfo = makeLookup(deps.rowId, async (chatId, signal) => {
|
|
137713
|
+
const token = await deps.tenantToken();
|
|
137714
|
+
signal.throwIfAborted();
|
|
137715
|
+
return await fetchChatInfo({ http: deps.http, token, chatId, signal }) ?? null;
|
|
137716
|
+
});
|
|
137717
|
+
const forMessage = (message) => {
|
|
137718
|
+
if (message.chatType !== "group" || message.senderOpenId === null) return {};
|
|
137719
|
+
const name = contactDenied ? null : userName(message.senderOpenId);
|
|
137720
|
+
const chat = chatInfo(message.chatId);
|
|
137721
|
+
const fields = (senderName, info) => ({
|
|
137722
|
+
...senderName ? { senderName } : {},
|
|
137723
|
+
...info?.name ? { chatTitle: info.name } : {}
|
|
137724
|
+
});
|
|
137725
|
+
return name instanceof Promise || chat instanceof Promise ? Promise.all([name, chat]).then(([senderName, info]) => fields(senderName, info)) : fields(name, chat);
|
|
137255
137726
|
};
|
|
137727
|
+
return { chatInfo, forMessage };
|
|
137256
137728
|
};
|
|
137257
137729
|
|
|
137258
137730
|
// src/larkAdapter.ts
|
|
@@ -137279,6 +137751,7 @@ var COLUMNS = [
|
|
|
137279
137751
|
];
|
|
137280
137752
|
var topicOnMentionOf = (binding) => binding.values["larkTopicOnMention"] !== "off";
|
|
137281
137753
|
var TOPIC_THREAD_CACHE_LIMIT = 2e3;
|
|
137754
|
+
var MESSAGE_CONTEXT_CACHE_LIMIT = 2e3;
|
|
137282
137755
|
var topicChatIdOf = (chatId, rootMessageId) => `${chatId}:${rootMessageId}`;
|
|
137283
137756
|
var splitTopicChatId = (chatId) => {
|
|
137284
137757
|
const at = chatId.indexOf(":");
|
|
@@ -137308,6 +137781,7 @@ var makeLarkAdapter = (deps) => {
|
|
|
137308
137781
|
};
|
|
137309
137782
|
const aliasPorts = /* @__PURE__ */ new Map();
|
|
137310
137783
|
const topicThreadIds = makeBoundedMap(TOPIC_THREAD_CACHE_LIMIT);
|
|
137784
|
+
const messageContexts = makeBoundedMap(MESSAGE_CONTEXT_CACHE_LIMIT);
|
|
137311
137785
|
const unreported = /* @__PURE__ */ new Map();
|
|
137312
137786
|
const learning = /* @__PURE__ */ new Map();
|
|
137313
137787
|
const learnTopic = (binding, target2, threadId) => {
|
|
@@ -137364,14 +137838,10 @@ var makeLarkAdapter = (deps) => {
|
|
|
137364
137838
|
onThreadReply: (threadId) => learnTopic(binding, { token, chatId, rootMessageId, port }, threadId)
|
|
137365
137839
|
};
|
|
137366
137840
|
};
|
|
137367
|
-
const soloGroupFor = (
|
|
137368
|
-
const
|
|
137369
|
-
|
|
137370
|
-
|
|
137371
|
-
chatId
|
|
137372
|
-
});
|
|
137373
|
-
return stats === void 0 ? void 0 : stats.userCount <= 1 && stats.botCount <= 1;
|
|
137374
|
-
});
|
|
137841
|
+
const soloGroupFor = (context) => async (chatId) => {
|
|
137842
|
+
const info = await context.chatInfo(chatId);
|
|
137843
|
+
return info?.userCount !== void 0 && info.botCount !== void 0 && info.userCount <= 1 && info.botCount <= 1;
|
|
137844
|
+
};
|
|
137375
137845
|
return {
|
|
137376
137846
|
platform: "lark",
|
|
137377
137847
|
icon: "lark",
|
|
@@ -137397,12 +137867,20 @@ var makeLarkAdapter = (deps) => {
|
|
|
137397
137867
|
unreported.delete(key);
|
|
137398
137868
|
}
|
|
137399
137869
|
let open = true;
|
|
137870
|
+
const pendingDeliveries = /* @__PURE__ */ new Map();
|
|
137871
|
+
const previousContext = messageContexts.get(binding.rowId);
|
|
137872
|
+
const context = previousContext?.appId === appId && previousContext.appSecret === appSecret ? previousContext.context : makeLarkMessageContext({
|
|
137873
|
+
rowId: binding.rowId,
|
|
137874
|
+
http: deps.http,
|
|
137875
|
+
tenantToken: () => tenantToken(binding)
|
|
137876
|
+
});
|
|
137877
|
+
messageContexts.set(binding.rowId, { appId, appSecret, context });
|
|
137400
137878
|
const inbound = startLarkInbound({
|
|
137401
137879
|
appId,
|
|
137402
137880
|
appSecret,
|
|
137403
137881
|
groupMention: binding.groupMention,
|
|
137404
137882
|
topicOnMention: topicOnMentionOf(binding),
|
|
137405
|
-
isSoloGroup: soloGroupFor(
|
|
137883
|
+
isSoloGroup: soloGroupFor(context),
|
|
137406
137884
|
onError: handlers.onError,
|
|
137407
137885
|
onCardAction: handlers.onButton,
|
|
137408
137886
|
onPanelClick: (click, operatorOpenId) => handlers.onPanelClick?.({
|
|
@@ -137414,7 +137892,17 @@ var makeLarkAdapter = (deps) => {
|
|
|
137414
137892
|
}) ?? null,
|
|
137415
137893
|
onMessage: (message) => {
|
|
137416
137894
|
const { topic } = message;
|
|
137417
|
-
const
|
|
137895
|
+
const source = context.forMessage(message);
|
|
137896
|
+
const parentMessageId = message.parentMessageId;
|
|
137897
|
+
const reference2 = parentMessageId === void 0 ? null : loadReplyReference(
|
|
137898
|
+
async (signal) => fetchMessageReference({
|
|
137899
|
+
http: deps.http,
|
|
137900
|
+
token: await tenantToken(binding),
|
|
137901
|
+
messageId: parentMessageId,
|
|
137902
|
+
signal
|
|
137903
|
+
})
|
|
137904
|
+
);
|
|
137905
|
+
const deliver = (names, replyTo) => handlers.onMessage({
|
|
137418
137906
|
messageId: message.messageId,
|
|
137419
137907
|
// 已经开出来的话题就是它自己那个聊天;将要开出来的(主窗口里 @ 机器人)先算群的,
|
|
137420
137908
|
// 由核心决定要不要分出去。
|
|
@@ -137427,7 +137915,9 @@ var makeLarkAdapter = (deps) => {
|
|
|
137427
137915
|
chatAlias: topicAliasOf(message.chatId, topic.threadId)
|
|
137428
137916
|
},
|
|
137429
137917
|
senderId: message.senderOpenId,
|
|
137918
|
+
...names,
|
|
137430
137919
|
text: message.text,
|
|
137920
|
+
...replyTo === void 0 ? {} : { replyTo },
|
|
137431
137921
|
chatKind: message.chatType === "p2p" ? "private" : "group",
|
|
137432
137922
|
replyInThread: message.inThread,
|
|
137433
137923
|
resources: message.resources.map((resource) => ({
|
|
@@ -137442,8 +137932,19 @@ var makeLarkAdapter = (deps) => {
|
|
|
137442
137932
|
threadId: topic.threadId,
|
|
137443
137933
|
rootGiven: topic.rootGiven
|
|
137444
137934
|
});
|
|
137445
|
-
|
|
137446
|
-
|
|
137935
|
+
const key = JSON.stringify([message.chatId, topic?.threadId]);
|
|
137936
|
+
const earlier = pendingDeliveries.get(key);
|
|
137937
|
+
if (earlier === void 0 && pending === null && reference2 === null && !(source instanceof Promise)) {
|
|
137938
|
+
deliver(source);
|
|
137939
|
+
} else {
|
|
137940
|
+
const completed = Promise.all([earlier, pending, reference2, source]).then(([, , replyTo, names]) => {
|
|
137941
|
+
if (pendingDeliveries.get(key) === completed) pendingDeliveries.delete(key);
|
|
137942
|
+
if (open) deliver(names, replyTo ?? void 0);
|
|
137943
|
+
}).catch((error) => handlers.onError(describeError(error))).finally(() => {
|
|
137944
|
+
if (pendingDeliveries.get(key) === completed) pendingDeliveries.delete(key);
|
|
137945
|
+
});
|
|
137946
|
+
pendingDeliveries.set(key, completed);
|
|
137947
|
+
}
|
|
137447
137948
|
}
|
|
137448
137949
|
});
|
|
137449
137950
|
return {
|
|
@@ -137624,6 +138125,11 @@ var makeLarkAdapter = (deps) => {
|
|
|
137624
138125
|
|
|
137625
138126
|
// locales/en.json
|
|
137626
138127
|
var en_default = {
|
|
138128
|
+
source: {
|
|
138129
|
+
fromChat: "From {{name}} in {{chat}}:",
|
|
138130
|
+
from: "From {{name}}:",
|
|
138131
|
+
member: "member {{code}}"
|
|
138132
|
+
},
|
|
137627
138133
|
settings: {
|
|
137628
138134
|
title: "Chat",
|
|
137629
138135
|
description: "Connect chat bots to Ycodium. One row per bot: create the bot on its platform, paste its credentials, and pick an access mode (allowlist / open). In allowlist mode, list the people allowed to use it. For Lark, Connect a Lark bot does all of that with one scan. Admitted people message the bot (or add it to a group), pick a project in the chat, and can start work.",
|
|
@@ -137813,6 +138319,7 @@ var en_default = {
|
|
|
137813
138319
|
}
|
|
137814
138320
|
},
|
|
137815
138321
|
reply: {
|
|
138322
|
+
conclusionRecovered: "(Finished while restarting; delivered now)",
|
|
137816
138323
|
notAllowed: "You are not on this bot's allow list, so this tap had no effect.",
|
|
137817
138324
|
noDefaultModel: 'Project "{{title}}" has no agent selected yet, so a thread cannot be started. Send /model to pick one, or set a default in the project settings, then message again.',
|
|
137818
138325
|
projectArchived: 'Project "{{title}}" is archived. Restore it, or send /repo to pick another project, then message again.',
|
|
@@ -138288,6 +138795,11 @@ var en_default = {
|
|
|
138288
138795
|
|
|
138289
138796
|
// locales/zh-CN.json
|
|
138290
138797
|
var zh_CN_default = {
|
|
138798
|
+
source: {
|
|
138799
|
+
fromChat: "\u6765\u81EA {{name}}\uFF08{{chat}}\uFF09\uFF1A",
|
|
138800
|
+
from: "\u6765\u81EA {{name}}\uFF1A",
|
|
138801
|
+
member: "\u6210\u5458 {{code}}"
|
|
138802
|
+
},
|
|
138291
138803
|
settings: {
|
|
138292
138804
|
title: "\u804A\u5929",
|
|
138293
138805
|
description: "\u628A\u804A\u5929\u673A\u5668\u4EBA\u63A5\u5230 Ycodium\u3002\u4E00\u884C\u4E00\u4E2A\u673A\u5668\u4EBA\uFF1A\u5148\u5728\u5BF9\u5E94\u5E73\u53F0\u5EFA\u597D\u673A\u5668\u4EBA\u3001\u628A\u51ED\u636E\u586B\u8FDB\u6765\uFF0C\u518D\u9009\u8BBF\u95EE\u6A21\u5F0F\uFF08\u4EC5\u767D\u540D\u5355\uFF0F\u5141\u8BB8\u6240\u6709\u4EBA\uFF09\u3002\u4EC5\u767D\u540D\u5355\u65F6\u628A\u5141\u8BB8\u4F7F\u7528\u5B83\u7684\u4EBA\u586B\u8FDB\u300C\u5141\u8BB8\u7684\u4EBA\u300D\u3002\u98DE\u4E66\u53EF\u4EE5\u7528\u300C\u8FDE\u63A5\u98DE\u4E66\u673A\u5668\u4EBA\u300D\uFF0C\u626B\u4E00\u6B21\u7801\u5168\u90E8\u914D\u597D\u3002\u83B7\u51C6\u7684\u4EBA\u79C1\u804A\u673A\u5668\u4EBA\uFF08\u6216\u628A\u5B83\u62C9\u8FDB\u7FA4\uFF09\u3001\u5728\u804A\u5929\u91CC\u9009\u597D\u9879\u76EE\uFF0C\u5C31\u80FD\u6D3E\u6D3B\u3002",
|
|
@@ -138477,6 +138989,7 @@ var zh_CN_default = {
|
|
|
138477
138989
|
}
|
|
138478
138990
|
},
|
|
138479
138991
|
reply: {
|
|
138992
|
+
conclusionRecovered: "\uFF08\u91CD\u542F\u671F\u95F4\u5B8C\u6210\uFF0C\u73B0\u5728\u8865\u53D1\uFF09",
|
|
138480
138993
|
notAllowed: "\u4F60\u4E0D\u5728\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u5141\u8BB8\u540D\u5355\u91CC\uFF0C\u8FD9\u6B21\u70B9\u51FB\u6CA1\u6709\u751F\u6548\u3002",
|
|
138481
138994
|
noDefaultModel: "\u9879\u76EE\u300C{{title}}\u300D\u8FD8\u6CA1\u9009 agent\uFF0C\u5F00\u4E0D\u4E86\u4F1A\u8BDD\u3002\u53D1 /model \u9009\u4E00\u4E2A\uFF0C\u6216\u8005\u5230\u9879\u76EE\u8BBE\u7F6E\u91CC\u8BBE\u4E2A\u9ED8\u8BA4\uFF0C\u518D\u53D1\u4E00\u6B21\u6D88\u606F\u3002",
|
|
138482
138995
|
projectArchived: "\u9879\u76EE\u300C{{title}}\u300D\u5DF2\u5F52\u6863\u3002\u6062\u590D\u5B83\uFF0C\u6216\u53D1 /repo \u6362\u4E2A\u9879\u76EE\uFF0C\u518D\u53D1\u6D88\u606F\u3002",
|
|
@@ -138997,14 +139510,14 @@ var makeLiveTranslate = (initial) => {
|
|
|
138997
139510
|
};
|
|
138998
139511
|
|
|
138999
139512
|
// src/modelPlan.ts
|
|
139000
|
-
import { threadOrNull as
|
|
139513
|
+
import { threadOrNull as threadOrNull4 } from "@ycodium-ai/plugin-api";
|
|
139001
139514
|
var makeModelPlan = (core, deps) => {
|
|
139002
139515
|
const { host, t, commit, deliver } = core;
|
|
139003
139516
|
const { threadStillUsable } = deps;
|
|
139004
139517
|
const currentModelOf = async (binding) => {
|
|
139005
139518
|
const chat = chatOf(core.state, chatKeyOf(binding));
|
|
139006
139519
|
if (chat.threadId !== null) {
|
|
139007
|
-
const thread = await
|
|
139520
|
+
const thread = await threadOrNull4(host.threads, chat.threadId).catch(() => null);
|
|
139008
139521
|
if (thread !== null) {
|
|
139009
139522
|
return {
|
|
139010
139523
|
instanceId: thread.modelSelection.instanceId,
|
|
@@ -139073,7 +139586,62 @@ var makeModelPlan = (core, deps) => {
|
|
|
139073
139586
|
};
|
|
139074
139587
|
|
|
139075
139588
|
// src/notifications.ts
|
|
139076
|
-
import { readThreadFailed, threadOrNull as
|
|
139589
|
+
import { readThreadFailed, threadOrNull as threadOrNull5 } from "@ycodium-ai/plugin-api";
|
|
139590
|
+
|
|
139591
|
+
// src/conclusionRecovery.ts
|
|
139592
|
+
var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
139593
|
+
var recoverConclusions = async (core, ledger, delivery, failures) => {
|
|
139594
|
+
let disposed = false;
|
|
139595
|
+
core.host.onDispose(() => {
|
|
139596
|
+
disposed = true;
|
|
139597
|
+
});
|
|
139598
|
+
await core.ready;
|
|
139599
|
+
for (const debt of Object.values(conclusionDebtsOf(core.state))) {
|
|
139600
|
+
if (disposed) return;
|
|
139601
|
+
try {
|
|
139602
|
+
const execution = await core.host.projections.getThreadExecution(debt.threadId);
|
|
139603
|
+
if (disposed) return;
|
|
139604
|
+
if (execution === null) {
|
|
139605
|
+
ledger.discard(debt);
|
|
139606
|
+
continue;
|
|
139607
|
+
}
|
|
139608
|
+
const latest = execution.latestTurn;
|
|
139609
|
+
if (latest?.userMessageId !== debt.userMessageId) {
|
|
139610
|
+
core.host.log.info("chat discarded a conclusion whose turn is no longer latest", {
|
|
139611
|
+
...debt
|
|
139612
|
+
});
|
|
139613
|
+
ledger.discard(debt);
|
|
139614
|
+
continue;
|
|
139615
|
+
}
|
|
139616
|
+
if (latest.state === "running" || execution.session?.activeTurnId != null) continue;
|
|
139617
|
+
if (latest.completedAt !== null && Date.parse(latest.completedAt) < Date.now() - MAX_AGE_MS) {
|
|
139618
|
+
core.host.log.info("chat discarded a conclusion older than seven days", { ...debt });
|
|
139619
|
+
ledger.discard(debt);
|
|
139620
|
+
continue;
|
|
139621
|
+
}
|
|
139622
|
+
const binding = core.bindingForChatKey(debt.chatKey);
|
|
139623
|
+
if (binding === void 0) continue;
|
|
139624
|
+
await ledger.deliver(debt, async () => {
|
|
139625
|
+
if (latest.state === "error") {
|
|
139626
|
+
return delivery.failure(
|
|
139627
|
+
binding,
|
|
139628
|
+
debt.threadId,
|
|
139629
|
+
failures.forFailure(debt.threadId, execution.session?.lastError),
|
|
139630
|
+
true,
|
|
139631
|
+
latest.turnId
|
|
139632
|
+
);
|
|
139633
|
+
}
|
|
139634
|
+
const send = await delivery.prepareConclusion(debt.threadId, latest.turnId);
|
|
139635
|
+
return send(binding, { recovered: true, streaming: false });
|
|
139636
|
+
});
|
|
139637
|
+
} catch (error) {
|
|
139638
|
+
core.host.log.warn("chat could not recover a conclusion", {
|
|
139639
|
+
...debt,
|
|
139640
|
+
error: describeError(error)
|
|
139641
|
+
});
|
|
139642
|
+
}
|
|
139643
|
+
}
|
|
139644
|
+
};
|
|
139077
139645
|
|
|
139078
139646
|
// src/notificationTargets.ts
|
|
139079
139647
|
var notificationChatKeys = (state, threadId, projectId) => {
|
|
@@ -139082,56 +139650,6 @@ var notificationChatKeys = (state, threadId, projectId) => {
|
|
|
139082
139650
|
return projectId === null ? [] : chatsOnProject(state, projectId);
|
|
139083
139651
|
};
|
|
139084
139652
|
|
|
139085
|
-
// src/threadMessages.ts
|
|
139086
|
-
import {
|
|
139087
|
-
isThreadNotFound,
|
|
139088
|
-
threadMessagesNewestFirst
|
|
139089
|
-
} from "@ycodium-ai/plugin-api";
|
|
139090
|
-
var PAGE_SIZE = 20;
|
|
139091
|
-
async function* newestFirst(threads, threadId) {
|
|
139092
|
-
try {
|
|
139093
|
-
yield* threadMessagesNewestFirst(threads, threadId, { pageSize: PAGE_SIZE });
|
|
139094
|
-
} catch (error) {
|
|
139095
|
-
if (!isThreadNotFound(error)) throw error;
|
|
139096
|
-
}
|
|
139097
|
-
}
|
|
139098
|
-
async function attachmentsOf(threads, threadId, message) {
|
|
139099
|
-
const collected = [...message.attachments ?? []];
|
|
139100
|
-
const total = message.attachmentsTotal ?? collected.length;
|
|
139101
|
-
while (collected.length < total) {
|
|
139102
|
-
let page;
|
|
139103
|
-
try {
|
|
139104
|
-
page = await threads.messages.list({
|
|
139105
|
-
threadId,
|
|
139106
|
-
messageId: message.id,
|
|
139107
|
-
attachmentOffset: collected.length,
|
|
139108
|
-
textLimit: 2
|
|
139109
|
-
});
|
|
139110
|
-
} catch (error) {
|
|
139111
|
-
if (isThreadNotFound(error)) break;
|
|
139112
|
-
throw error;
|
|
139113
|
-
}
|
|
139114
|
-
const more = page.items[0]?.attachments ?? [];
|
|
139115
|
-
if (more.length === 0) break;
|
|
139116
|
-
collected.push(...more);
|
|
139117
|
-
}
|
|
139118
|
-
return collected;
|
|
139119
|
-
}
|
|
139120
|
-
async function latestMessage(threads, threadId, accept) {
|
|
139121
|
-
for await (const message of newestFirst(threads, threadId)) {
|
|
139122
|
-
if (accept(message)) return message;
|
|
139123
|
-
}
|
|
139124
|
-
return void 0;
|
|
139125
|
-
}
|
|
139126
|
-
async function messagesAfterLastUser(threads, threadId) {
|
|
139127
|
-
const after = [];
|
|
139128
|
-
for await (const message of newestFirst(threads, threadId)) {
|
|
139129
|
-
if (message.role === "user") break;
|
|
139130
|
-
after.push(message);
|
|
139131
|
-
}
|
|
139132
|
-
return after.toReversed();
|
|
139133
|
-
}
|
|
139134
|
-
|
|
139135
139653
|
// src/turnOutcome.ts
|
|
139136
139654
|
var outcomeOfSession = (status) => {
|
|
139137
139655
|
if (status === "error") return "failed";
|
|
@@ -139142,15 +139660,16 @@ var outcomeOfSession = (status) => {
|
|
|
139142
139660
|
// src/notifications.ts
|
|
139143
139661
|
var THREAD_PROJECT_CACHE_LIMIT = 256;
|
|
139144
139662
|
var makeNotifications = (core, deps) => {
|
|
139145
|
-
const { host, adapterFor,
|
|
139663
|
+
const { host, adapterFor, bindingForChatKey, ready } = core;
|
|
139146
139664
|
const { clearWorking } = deps;
|
|
139147
139665
|
const { turnCards } = deps.replyCards;
|
|
139148
|
-
const { failures,
|
|
139666
|
+
const { failures, conclusions, delivery } = deps;
|
|
139667
|
+
void recoverConclusions(core, conclusions, delivery, failures);
|
|
139149
139668
|
const projectByThread = /* @__PURE__ */ new Map();
|
|
139150
139669
|
const projectOfThread = async (threadId) => {
|
|
139151
139670
|
const known = projectByThread.get(threadId);
|
|
139152
139671
|
if (known !== void 0) return known;
|
|
139153
|
-
const thread = await
|
|
139672
|
+
const thread = await threadOrNull5(host.threads, threadId);
|
|
139154
139673
|
if (thread === null) return null;
|
|
139155
139674
|
if (projectByThread.size >= THREAD_PROJECT_CACHE_LIMIT) {
|
|
139156
139675
|
const oldest = projectByThread.keys().next().value;
|
|
@@ -139187,26 +139706,28 @@ var makeNotifications = (core, deps) => {
|
|
|
139187
139706
|
const said = threadsWithSomethingToReport.delete(threadId);
|
|
139188
139707
|
await ready;
|
|
139189
139708
|
const targets = targetsForProject(threadId, await projectOfThread(threadId));
|
|
139190
|
-
const
|
|
139191
|
-
|
|
139192
|
-
|
|
139193
|
-
|
|
139194
|
-
|
|
139195
|
-
|
|
139196
|
-
|
|
139197
|
-
|
|
139198
|
-
|
|
139199
|
-
|
|
139200
|
-
|
|
139201
|
-
const text4 = streamsTo(binding, threadId) ? "" : `${thread.title}
|
|
139202
|
-
|
|
139203
|
-
${final.text}`;
|
|
139204
|
-
await deliver(
|
|
139205
|
-
owns(binding, threadId) ? await anchors.anchored(binding, threadId, final.turnId) : binding,
|
|
139206
|
-
text4,
|
|
139207
|
-
attachments
|
|
139709
|
+
const owes = Object.values(conclusionDebtsOf(core.state)).some(
|
|
139710
|
+
(debt2) => debt2.threadId === threadId
|
|
139711
|
+
);
|
|
139712
|
+
const { debt, handled, execution } = said || owes ? await conclusions.forTurn(threadId) : { debt: void 0, handled: false, execution: null };
|
|
139713
|
+
if (debt !== void 0) {
|
|
139714
|
+
const binding = bindingForChatKey(debt.chatKey);
|
|
139715
|
+
if (binding !== void 0 && !streamsTo(binding, threadId) && execution?.session?.activeTurnId == null && execution?.latestTurn?.state !== "running" && execution?.latestTurn?.state !== "error" && payload.session?.status !== "error") {
|
|
139716
|
+
await conclusions.deliver(debt, async () => {
|
|
139717
|
+
const send = await delivery.prepareConclusion(
|
|
139718
|
+
threadId,
|
|
139719
|
+
execution?.latestTurn?.turnId ?? null
|
|
139208
139720
|
);
|
|
139209
|
-
|
|
139721
|
+
return send(binding, { recovered: false, streaming: false });
|
|
139722
|
+
});
|
|
139723
|
+
}
|
|
139724
|
+
} else if (said && !handled) {
|
|
139725
|
+
const send = await delivery.prepareConclusion(threadId);
|
|
139726
|
+
for (const binding of targets) {
|
|
139727
|
+
await send(binding, {
|
|
139728
|
+
recovered: false,
|
|
139729
|
+
streaming: streamsTo(binding, threadId)
|
|
139730
|
+
});
|
|
139210
139731
|
}
|
|
139211
139732
|
}
|
|
139212
139733
|
const outcome = outcomeOfSession(payload.session?.status);
|
|
@@ -139219,7 +139740,10 @@ ${final.text}`;
|
|
|
139219
139740
|
threadsWithSomethingToReport.delete(threadId);
|
|
139220
139741
|
await ready;
|
|
139221
139742
|
const targets = targetsForProject(threadId, await projectOfThread(threadId));
|
|
139222
|
-
const
|
|
139743
|
+
const { debt, handled } = await conclusions.forTurn(threadId);
|
|
139744
|
+
const debtBinding = debt === void 0 ? void 0 : bindingForChatKey(debt.chatKey);
|
|
139745
|
+
const recipients = debt !== void 0 ? debtBinding === void 0 ? [] : [debtBinding] : targets;
|
|
139746
|
+
const textTargets = handled ? [] : recipients.filter(
|
|
139223
139747
|
(binding) => !(streamsTo(binding, threadId) && turnCards.covers(threadId))
|
|
139224
139748
|
);
|
|
139225
139749
|
const drawingTurn = turnCards.drawingTurn(threadId);
|
|
@@ -139228,7 +139752,13 @@ ${final.text}`;
|
|
|
139228
139752
|
failures.holdForCard(threadId, drawingTurn, notice);
|
|
139229
139753
|
for (const binding of targets) {
|
|
139230
139754
|
await clearWorking(binding, threadId, "failed");
|
|
139231
|
-
|
|
139755
|
+
}
|
|
139756
|
+
if (notice !== null) {
|
|
139757
|
+
for (const binding of textTargets) {
|
|
139758
|
+
const send = () => delivery.failure(binding, threadId, notice, false);
|
|
139759
|
+
if (debt !== void 0) await conclusions.deliver(debt, send);
|
|
139760
|
+
else await send();
|
|
139761
|
+
}
|
|
139232
139762
|
}
|
|
139233
139763
|
});
|
|
139234
139764
|
const rememberThreadProject = (threadId, projectId) => {
|
|
@@ -139821,7 +140351,7 @@ var makeFailureNotices = (core) => {
|
|
|
139821
140351
|
const heldForCard = /* @__PURE__ */ new Map();
|
|
139822
140352
|
const reasonOf2 = (detail) => detail?.trim() ?? "";
|
|
139823
140353
|
return {
|
|
139824
|
-
/**
|
|
140354
|
+
/** 一次失败通知的那句话(带新参考号,同号进日志):实时失败事件与重启补发各取一次。 */
|
|
139825
140355
|
forFailure: (threadId, detail) => {
|
|
139826
140356
|
const reference2 = diagnosticRef("msg");
|
|
139827
140357
|
core.host.log.warn("chat turn failed", { threadId, reference: reference2 });
|
|
@@ -139851,7 +140381,7 @@ var makeFailureNotices = (core) => {
|
|
|
139851
140381
|
// src/replyCards.ts
|
|
139852
140382
|
import {
|
|
139853
140383
|
readTurnProgress,
|
|
139854
|
-
threadOrNull as
|
|
140384
|
+
threadOrNull as threadOrNull6,
|
|
139855
140385
|
TURN_PROGRESS_TRIGGER_KIND
|
|
139856
140386
|
} from "@ycodium-ai/plugin-api";
|
|
139857
140387
|
|
|
@@ -139977,15 +140507,19 @@ var makeTurnCards = (deps) => {
|
|
|
139977
140507
|
const title = live?.title ?? await deps.titleOf(threadId);
|
|
139978
140508
|
const view = await finalView(title, progress, live, end);
|
|
139979
140509
|
if (live?.card != null) {
|
|
139980
|
-
|
|
139981
|
-
|
|
139982
|
-
|
|
139983
|
-
|
|
139984
|
-
|
|
139985
|
-
if (card === null) {
|
|
139986
|
-
await deps.fallback(threadId, turnId, target2.chatKey, view);
|
|
140510
|
+
const card = live.card;
|
|
140511
|
+
const sent = await card.finish(view);
|
|
140512
|
+
deps.onClosed(card.cardId);
|
|
140513
|
+
if (deps.finalize !== void 0)
|
|
140514
|
+
await deps.finalize(threadId, turnId, target2.chatKey, async () => sent);
|
|
139987
140515
|
return;
|
|
139988
140516
|
}
|
|
140517
|
+
const send = async () => {
|
|
140518
|
+
const card = await openCard(target2, view);
|
|
140519
|
+
return card !== null || await deps.fallback(threadId, turnId, target2.chatKey, view);
|
|
140520
|
+
};
|
|
140521
|
+
if (deps.finalize === void 0) await send();
|
|
140522
|
+
else await deps.finalize(threadId, turnId, target2.chatKey, send);
|
|
139989
140523
|
};
|
|
139990
140524
|
const handle = async (slot, threadId, item) => {
|
|
139991
140525
|
await deps.ready;
|
|
@@ -140130,7 +140664,7 @@ var makeTurnCards = (deps) => {
|
|
|
140130
140664
|
};
|
|
140131
140665
|
|
|
140132
140666
|
// src/replyCards.ts
|
|
140133
|
-
var makeReplyCards = (core, failures, anchors) => {
|
|
140667
|
+
var makeReplyCards = (core, failures, anchors, conclusions, delivery) => {
|
|
140134
140668
|
const { host, adapterFor, commit, deliver, bindingForChatKey, bindingOfThread, ready } = core;
|
|
140135
140669
|
const stopRequested = /* @__PURE__ */ new Set();
|
|
140136
140670
|
const turnCards = makeTurnCards({
|
|
@@ -140166,12 +140700,12 @@ var makeReplyCards = (core, failures, anchors) => {
|
|
|
140166
140700
|
(message) => message.role === "user" && message.text.trim() !== ""
|
|
140167
140701
|
).catch(() => void 0);
|
|
140168
140702
|
if (asked !== void 0) return turnTitleOf(asked.text);
|
|
140169
|
-
const thread = await
|
|
140703
|
+
const thread = await threadOrNull6(host.threads, threadId).catch(() => null);
|
|
140170
140704
|
return turnTitleOf(thread?.title ?? "");
|
|
140171
140705
|
},
|
|
140172
140706
|
endOf: async (threadId, turnId) => {
|
|
140173
140707
|
const stopped = stopRequested.delete(threadId);
|
|
140174
|
-
const thread = await
|
|
140708
|
+
const thread = await threadOrNull6(host.threads, threadId).catch(() => null);
|
|
140175
140709
|
const session = thread?.session;
|
|
140176
140710
|
const outcome = outcomeOfSession(session?.status);
|
|
140177
140711
|
const errorText2 = failures.forCard(
|
|
@@ -140188,11 +140722,24 @@ var makeReplyCards = (core, failures, anchors) => {
|
|
|
140188
140722
|
},
|
|
140189
140723
|
onOpened: (card) => commit("turn-card-opened", card),
|
|
140190
140724
|
onClosed: (cardId) => commit("turn-card-closed", { cardId }),
|
|
140191
|
-
|
|
140725
|
+
finalize: async (threadId, turnId, chatKey, send) => {
|
|
140726
|
+
const { debt, handled } = await conclusions.forTurn(threadId, turnId);
|
|
140727
|
+
if (handled) return;
|
|
140728
|
+
if (debt === void 0) {
|
|
140729
|
+
await send();
|
|
140730
|
+
return;
|
|
140731
|
+
}
|
|
140732
|
+
if (!await conclusions.deliver(debt, send)) return;
|
|
140192
140733
|
const binding = bindingForChatKey(chatKey);
|
|
140193
140734
|
if (binding === void 0) return;
|
|
140735
|
+
const sendConclusion = await delivery.prepareConclusion(threadId, turnId);
|
|
140736
|
+
await sendConclusion(binding, { recovered: false, streaming: true });
|
|
140737
|
+
},
|
|
140738
|
+
fallback: async (threadId, turnId, chatKey, view) => {
|
|
140739
|
+
const binding = bindingForChatKey(chatKey);
|
|
140740
|
+
if (binding === void 0) return false;
|
|
140194
140741
|
const text4 = [view.body, view.errorText ?? ""].filter((part) => part !== "").join("\n\n");
|
|
140195
|
-
|
|
140742
|
+
return deliver(await anchors.anchored(binding, threadId, turnId), text4);
|
|
140196
140743
|
},
|
|
140197
140744
|
schedule: (run, delayMs) => {
|
|
140198
140745
|
const timer = setTimeout(run, delayMs);
|
|
@@ -140209,18 +140756,18 @@ var makeReplyCards = (core, failures, anchors) => {
|
|
|
140209
140756
|
});
|
|
140210
140757
|
host.onDispose(() => turnCards.dispose());
|
|
140211
140758
|
void ready.then(async () => {
|
|
140212
|
-
for (const [cardId,
|
|
140213
|
-
const binding = bindingForChatKey(
|
|
140759
|
+
for (const [cardId, record3] of Object.entries(openTurnCardsOf(core.state))) {
|
|
140760
|
+
const binding = bindingForChatKey(record3.chatKey);
|
|
140214
140761
|
const cards = binding === void 0 ? void 0 : adapterFor(binding.platform)?.turnCards;
|
|
140215
140762
|
if (binding !== void 0 && cards !== void 0) {
|
|
140216
140763
|
try {
|
|
140217
|
-
const messages = await messagesAfterLastUser(host.threads,
|
|
140764
|
+
const messages = await messagesAfterLastUser(host.threads, record3.threadId).catch(
|
|
140218
140765
|
() => []
|
|
140219
140766
|
);
|
|
140220
140767
|
await cards.update(
|
|
140221
140768
|
binding,
|
|
140222
140769
|
cardId,
|
|
140223
|
-
interruptedView({ title:
|
|
140770
|
+
interruptedView({ title: record3.title, body: trailingReply(messages) })
|
|
140224
140771
|
);
|
|
140225
140772
|
} catch (error) {
|
|
140226
140773
|
host.log.warn("chat could not mark a stale card as interrupted", {
|
|
@@ -140410,7 +140957,7 @@ var makeSendFileTool = (deps) => ({
|
|
|
140410
140957
|
});
|
|
140411
140958
|
|
|
140412
140959
|
// src/sessions.ts
|
|
140413
|
-
import { threadOrNull as
|
|
140960
|
+
import { threadOrNull as threadOrNull7 } from "@ycodium-ai/plugin-api";
|
|
140414
140961
|
var WEB_LIST_PAGE = 100;
|
|
140415
140962
|
var shellOf = (thread) => ({
|
|
140416
140963
|
threadId: thread.id,
|
|
@@ -140470,7 +141017,7 @@ var makeSessions = (core) => {
|
|
|
140470
141017
|
});
|
|
140471
141018
|
};
|
|
140472
141019
|
const rowForThread = async (binding, chatKey, threadId) => {
|
|
140473
|
-
const thread = await
|
|
141020
|
+
const thread = await threadOrNull7(host.threads, threadId, { archived: "include" });
|
|
140474
141021
|
if (thread === null || thread.projectId !== binding.projectId) return null;
|
|
140475
141022
|
return rowFromThread(shellOf(thread), chatKey, originOf(threadId, binding.projectId));
|
|
140476
141023
|
};
|
|
@@ -140480,8 +141027,8 @@ var makeSessions = (core) => {
|
|
|
140480
141027
|
await deliver(binding, formatSessions(rows, Date.now(), t));
|
|
140481
141028
|
};
|
|
140482
141029
|
const bindToSession = async (binding, chatKey, target2) => {
|
|
140483
|
-
for (const [otherKey,
|
|
140484
|
-
if (otherKey !== chatKey &&
|
|
141030
|
+
for (const [otherKey, record3] of Object.entries(core.state.chats)) {
|
|
141031
|
+
if (otherKey !== chatKey && record3.threadId === target2.threadId) bindChat(otherKey, null);
|
|
140485
141032
|
}
|
|
140486
141033
|
if (target2.origin === "web" && !hasAttached(core.state, chatKey, target2.threadId)) {
|
|
140487
141034
|
commit("thread-attached", {
|
|
@@ -140562,7 +141109,7 @@ var makeSessions = (core) => {
|
|
|
140562
141109
|
};
|
|
140563
141110
|
|
|
140564
141111
|
// src/teamGoals.ts
|
|
140565
|
-
import * as
|
|
141112
|
+
import * as NodeCrypto3 from "node:crypto";
|
|
140566
141113
|
var isRecord2 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
140567
141114
|
var teamGoalRequestId = (binding, messageId) => {
|
|
140568
141115
|
const identity = JSON.stringify([
|
|
@@ -140572,7 +141119,7 @@ var teamGoalRequestId = (binding, messageId) => {
|
|
|
140572
141119
|
binding.chatId,
|
|
140573
141120
|
messageId
|
|
140574
141121
|
]);
|
|
140575
|
-
return
|
|
141122
|
+
return NodeCrypto3.createHash("sha256").update(identity).digest("hex");
|
|
140576
141123
|
};
|
|
140577
141124
|
var makeTeamGoals = (core) => {
|
|
140578
141125
|
const { host, t, deliver, commit } = core;
|
|
@@ -140598,7 +141145,8 @@ var makeTeamGoals = (core) => {
|
|
|
140598
141145
|
command: "startGoal",
|
|
140599
141146
|
payload: {
|
|
140600
141147
|
projectId: binding.projectId,
|
|
140601
|
-
goal: message.
|
|
141148
|
+
goal: textWithInboundContext(message, binding.rowId, t),
|
|
141149
|
+
titleSeed: message.text,
|
|
140602
141150
|
requestId: teamGoalRequestId(binding, message.messageId)
|
|
140603
141151
|
}
|
|
140604
141152
|
});
|
|
@@ -140643,6 +141191,7 @@ var DOWNLOAD_TIMEOUT_MS = 6e4;
|
|
|
140643
141191
|
var HINT_TIMEOUT_MS = 3e3;
|
|
140644
141192
|
var isTelegramToken = (token) => /^\d{5,20}:[A-Za-z0-9_-]{20,}$/u.test(token);
|
|
140645
141193
|
var TELEGRAM_TEXT_MAX_CHARS = 4e3;
|
|
141194
|
+
var telegramDisplayName = (user) => [user?.first_name, user?.last_name].filter(Boolean).join(" ").trim() || user?.username;
|
|
140646
141195
|
var chatIdOf = (message) => {
|
|
140647
141196
|
const thread = message.message_thread_id;
|
|
140648
141197
|
return message.is_topic_message === true && thread !== void 0 && thread > 0 ? `${String(message.chat.id)}:${String(thread)}` : String(message.chat.id);
|
|
@@ -140940,6 +141489,32 @@ var makeTelegramApi = (input) => {
|
|
|
140940
141489
|
};
|
|
140941
141490
|
};
|
|
140942
141491
|
|
|
141492
|
+
// src/soloGroup.ts
|
|
141493
|
+
var SOLO_GROUP_CACHE_MS = 5 * 6e4;
|
|
141494
|
+
var SOLO_GROUP_CACHE_LIMIT = 500;
|
|
141495
|
+
var makeSoloGroupCheck = (lookup2, now = () => Date.now()) => {
|
|
141496
|
+
const cache = /* @__PURE__ */ new Map();
|
|
141497
|
+
const inflight = /* @__PURE__ */ new Map();
|
|
141498
|
+
return async (chatId) => {
|
|
141499
|
+
const cached = cache.get(chatId);
|
|
141500
|
+
if (cached !== void 0 && now() - cached.at < SOLO_GROUP_CACHE_MS) return cached.solo;
|
|
141501
|
+
let asking = inflight.get(chatId);
|
|
141502
|
+
if (asking === void 0) {
|
|
141503
|
+
asking = lookup2(chatId).catch(() => void 0).finally(() => inflight.delete(chatId));
|
|
141504
|
+
inflight.set(chatId, asking);
|
|
141505
|
+
}
|
|
141506
|
+
const solo = await asking;
|
|
141507
|
+
if (solo === void 0) return false;
|
|
141508
|
+
cache.delete(chatId);
|
|
141509
|
+
cache.set(chatId, { solo, at: now() });
|
|
141510
|
+
if (cache.size > SOLO_GROUP_CACHE_LIMIT) {
|
|
141511
|
+
const oldest = cache.keys().next().value;
|
|
141512
|
+
if (oldest !== void 0) cache.delete(oldest);
|
|
141513
|
+
}
|
|
141514
|
+
return solo;
|
|
141515
|
+
};
|
|
141516
|
+
};
|
|
141517
|
+
|
|
140943
141518
|
// src/telegramCommandMenu.ts
|
|
140944
141519
|
var DESCRIPTIONS = {
|
|
140945
141520
|
new: "menu.new",
|
|
@@ -140999,6 +141574,54 @@ var parsePanelData = (data) => {
|
|
|
140999
141574
|
return { version: Number(match[1]), index: Number(match[2]) };
|
|
141000
141575
|
};
|
|
141001
141576
|
|
|
141577
|
+
// src/telegramReply.ts
|
|
141578
|
+
var topicServiceMessage = (message, reply) => message.is_topic_message === true && message.message_thread_id !== void 0 && (message.message_thread_id === reply.message_id || message.message_thread_id === reply.message_thread_id) && [
|
|
141579
|
+
reply.forum_topic_created,
|
|
141580
|
+
reply.forum_topic_edited,
|
|
141581
|
+
reply.forum_topic_closed,
|
|
141582
|
+
reply.forum_topic_reopened,
|
|
141583
|
+
reply.general_forum_topic_hidden,
|
|
141584
|
+
reply.general_forum_topic_unhidden
|
|
141585
|
+
].some((value2) => value2 !== void 0);
|
|
141586
|
+
var telegramReplyReference = (message, botUsername, botId) => {
|
|
141587
|
+
const reply = message.reply_to_message;
|
|
141588
|
+
const external = message.external_reply;
|
|
141589
|
+
if (reply !== void 0 && topicServiceMessage(message, reply) && external === void 0 && message.quote === void 0) {
|
|
141590
|
+
return null;
|
|
141591
|
+
}
|
|
141592
|
+
const source = external ?? reply;
|
|
141593
|
+
if (source === void 0 && message.quote === void 0) return null;
|
|
141594
|
+
const origin = external?.origin;
|
|
141595
|
+
const author = external === void 0 ? reply?.from : origin?.type === "user" ? origin.sender_user : void 0;
|
|
141596
|
+
const authorName = author === void 0 ? origin?.sender_user_name ?? origin?.author_signature ?? origin?.sender_chat?.title ?? origin?.chat?.title : telegramDisplayName(author);
|
|
141597
|
+
const fromBot = author !== void 0 && (botId !== void 0 && author.id === botId || botUsername !== null && author.username?.toLowerCase() === botUsername.toLowerCase());
|
|
141598
|
+
const attachments = [];
|
|
141599
|
+
if ((source?.photo?.length ?? 0) > 0) attachments.push({ kind: "image" });
|
|
141600
|
+
for (const [media, kind] of [
|
|
141601
|
+
[source?.document, "file"],
|
|
141602
|
+
[source?.audio, "audio"],
|
|
141603
|
+
[source?.voice, "audio"],
|
|
141604
|
+
[source?.video, "video"],
|
|
141605
|
+
[source?.video_note, "video"],
|
|
141606
|
+
[source?.animation, "video"]
|
|
141607
|
+
]) {
|
|
141608
|
+
if (media !== void 0) {
|
|
141609
|
+
attachments.push({
|
|
141610
|
+
kind,
|
|
141611
|
+
...media.file_name === void 0 ? {} : { name: media.file_name }
|
|
141612
|
+
});
|
|
141613
|
+
}
|
|
141614
|
+
}
|
|
141615
|
+
if (source?.sticker !== void 0) attachments.push({ kind: "other" });
|
|
141616
|
+
const content = message.quote?.text ?? source?.text ?? source?.caption;
|
|
141617
|
+
return {
|
|
141618
|
+
...authorName ? { authorName } : {},
|
|
141619
|
+
...fromBot ? { fromBot: true } : {},
|
|
141620
|
+
...content === void 0 ? {} : { content },
|
|
141621
|
+
...attachments.length === 0 ? {} : { attachments }
|
|
141622
|
+
};
|
|
141623
|
+
};
|
|
141624
|
+
|
|
141002
141625
|
// src/telegramRichText.ts
|
|
141003
141626
|
var TELEGRAM_RICH_TEXT_LIMIT = 3e4;
|
|
141004
141627
|
var escapeCharacter = (character) => {
|
|
@@ -141223,6 +141846,7 @@ var makeTelegramAdapter = (deps) => {
|
|
|
141223
141846
|
let acknowledged = 0;
|
|
141224
141847
|
let backoff = BACKOFF_START_MS;
|
|
141225
141848
|
let botUsername;
|
|
141849
|
+
let botId;
|
|
141226
141850
|
let menuSent = false;
|
|
141227
141851
|
let liveApi;
|
|
141228
141852
|
const isSoloGroup = makeSoloGroupCheck(async (chatId) => {
|
|
@@ -141243,7 +141867,11 @@ var makeTelegramAdapter = (deps) => {
|
|
|
141243
141867
|
const api = await apiFor(binding);
|
|
141244
141868
|
liveApi = api;
|
|
141245
141869
|
if (!running) return;
|
|
141246
|
-
botUsername
|
|
141870
|
+
if (botUsername == null) {
|
|
141871
|
+
const own = await api.getMe();
|
|
141872
|
+
botUsername = own.username ?? null;
|
|
141873
|
+
botId = own.id;
|
|
141874
|
+
}
|
|
141247
141875
|
if (!running) return;
|
|
141248
141876
|
if (!menuSent) {
|
|
141249
141877
|
menuSent = true;
|
|
@@ -141300,6 +141928,7 @@ var makeTelegramAdapter = (deps) => {
|
|
|
141300
141928
|
if (!running) break;
|
|
141301
141929
|
offset = nextOffset([update], offset);
|
|
141302
141930
|
const senderId = message.from === void 0 ? null : String(message.from.id);
|
|
141931
|
+
const senderName = telegramDisplayName(message.from);
|
|
141303
141932
|
const chatKind = message.chat.type === "private" ? "private" : "group";
|
|
141304
141933
|
if (text4 === "" && resource === null) {
|
|
141305
141934
|
const unsupported = unsupportedTypeOf(message);
|
|
@@ -141316,12 +141945,16 @@ var makeTelegramAdapter = (deps) => {
|
|
|
141316
141945
|
continue;
|
|
141317
141946
|
}
|
|
141318
141947
|
const parentChatId = parentChatIdOf(message);
|
|
141948
|
+
const replyTo = telegramReplyReference(message, botUsername, botId);
|
|
141319
141949
|
handlers.onMessage({
|
|
141320
141950
|
messageId: String(message.message_id),
|
|
141321
141951
|
chatId: chatIdOf(message),
|
|
141322
141952
|
...parentChatId === void 0 ? {} : { parentChatId },
|
|
141323
141953
|
senderId,
|
|
141324
141954
|
text: text4,
|
|
141955
|
+
...senderName ? { senderName } : {},
|
|
141956
|
+
...message.chat.title ? { chatTitle: message.chat.title } : {},
|
|
141957
|
+
...replyTo === null ? {} : { replyTo },
|
|
141325
141958
|
chatKind,
|
|
141326
141959
|
resources: resource === null ? [] : [
|
|
141327
141960
|
{
|
|
@@ -141538,7 +142171,7 @@ ${line}`
|
|
|
141538
142171
|
};
|
|
141539
142172
|
|
|
141540
142173
|
// src/turns.ts
|
|
141541
|
-
import { projectOrNull as projectOrNull2, threadOrNull as
|
|
142174
|
+
import { projectOrNull as projectOrNull2, threadOrNull as threadOrNull8 } from "@ycodium-ai/plugin-api";
|
|
141542
142175
|
var TITLE_MAX_CHARS = 72;
|
|
141543
142176
|
var titleFrom = (text4) => text4.replace(/\s+/g, " ").slice(0, TITLE_MAX_CHARS) || "Chat thread";
|
|
141544
142177
|
var makeTurns = (core, deps) => {
|
|
@@ -141547,7 +142180,7 @@ var makeTurns = (core, deps) => {
|
|
|
141547
142180
|
const { pendingByChat, pendingFor, collectResources } = deps.attachments;
|
|
141548
142181
|
const threadStillUsable = async (binding, threadId) => {
|
|
141549
142182
|
try {
|
|
141550
|
-
const thread = await
|
|
142183
|
+
const thread = await threadOrNull8(host.threads, threadId, { archived: "include" });
|
|
141551
142184
|
return thread !== null && thread.archivedAt == null && thread.projectId === binding.projectId;
|
|
141552
142185
|
} catch {
|
|
141553
142186
|
return true;
|
|
@@ -141645,6 +142278,7 @@ var makeTurns = (core, deps) => {
|
|
|
141645
142278
|
} catch {
|
|
141646
142279
|
}
|
|
141647
142280
|
}
|
|
142281
|
+
const registered = deps.conclusions.starting(threadId);
|
|
141648
142282
|
try {
|
|
141649
142283
|
await host.threads.turns.start({
|
|
141650
142284
|
requestId: crypto.randomUUID(),
|
|
@@ -141652,7 +142286,7 @@ var makeTurns = (core, deps) => {
|
|
|
141652
142286
|
message: {
|
|
141653
142287
|
messageId: userMessageId,
|
|
141654
142288
|
role: "user",
|
|
141655
|
-
text:
|
|
142289
|
+
text: [textWithInboundContext(message, binding.rowId, t), ...notes].join("\n"),
|
|
141656
142290
|
attachments: attachments.map(
|
|
141657
142291
|
(attachment) => attachment.type === "image" ? { ...attachment, type: "image" } : { ...attachment, type: "file" }
|
|
141658
142292
|
)
|
|
@@ -141662,9 +142296,19 @@ var makeTurns = (core, deps) => {
|
|
|
141662
142296
|
interactionMode: interactionModeOf(chatKey),
|
|
141663
142297
|
...intentAction !== void 0 ? { intentAction } : {}
|
|
141664
142298
|
});
|
|
142299
|
+
if (intentAction?.kind !== "steer") {
|
|
142300
|
+
deps.conclusions.owe({
|
|
142301
|
+
chatKey,
|
|
142302
|
+
threadId,
|
|
142303
|
+
userMessageId,
|
|
142304
|
+
recordedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
142305
|
+
});
|
|
142306
|
+
}
|
|
141665
142307
|
} catch (error) {
|
|
141666
142308
|
if (carried !== void 0) pendingByChat.set(chatKey, carried);
|
|
141667
142309
|
throw error;
|
|
142310
|
+
} finally {
|
|
142311
|
+
registered();
|
|
141668
142312
|
}
|
|
141669
142313
|
deps.noteInboundUserMessage?.(userMessageId);
|
|
141670
142314
|
host.log.info("chat started a turn from a message", {
|
|
@@ -141715,8 +142359,8 @@ var makeTurns = (core, deps) => {
|
|
|
141715
142359
|
|
|
141716
142360
|
// src/webSync.ts
|
|
141717
142361
|
var isWebSyncChat = (state, chatKey, threadId) => {
|
|
141718
|
-
const
|
|
141719
|
-
return
|
|
142362
|
+
const record3 = chatOf(state, chatKey);
|
|
142363
|
+
return record3.chatKind === "private" && record3.threadId === threadId;
|
|
141720
142364
|
};
|
|
141721
142365
|
var IM_ORIGIN_LIMIT = 256;
|
|
141722
142366
|
var MIRRORED_LIMIT = 256;
|
|
@@ -142269,7 +142913,7 @@ var makeWechatAdapter = (deps) => {
|
|
|
142269
142913
|
};
|
|
142270
142914
|
|
|
142271
142915
|
// src/wecomUpload.ts
|
|
142272
|
-
import * as
|
|
142916
|
+
import * as NodeCrypto4 from "node:crypto";
|
|
142273
142917
|
var WECOM_CHUNK_BYTES = 512 * 1024;
|
|
142274
142918
|
var WECOM_MAX_CHUNKS = 100;
|
|
142275
142919
|
var WECOM_MIN_UPLOAD_BYTES = 5;
|
|
@@ -142302,7 +142946,7 @@ var uploadWecomMedia = async (input) => {
|
|
|
142302
142946
|
filename: clampName(input.filename),
|
|
142303
142947
|
total_size: bytes.byteLength,
|
|
142304
142948
|
total_chunks: totalChunks,
|
|
142305
|
-
md5:
|
|
142949
|
+
md5: NodeCrypto4.createHash("md5").update(bytes).digest("hex")
|
|
142306
142950
|
});
|
|
142307
142951
|
const uploadId = init.upload_id;
|
|
142308
142952
|
if (typeof uploadId !== "string" || uploadId === "") {
|
|
@@ -142351,6 +142995,43 @@ var uploadWecomMedia = async (input) => {
|
|
|
142351
142995
|
return mediaId;
|
|
142352
142996
|
};
|
|
142353
142997
|
|
|
142998
|
+
// src/wecomReply.ts
|
|
142999
|
+
var wecomReplyReference = (quote) => {
|
|
143000
|
+
const attachments = [];
|
|
143001
|
+
const parts = [];
|
|
143002
|
+
const read = (item) => {
|
|
143003
|
+
switch (item.msgtype) {
|
|
143004
|
+
case "text":
|
|
143005
|
+
if (item.text?.content) parts.push(item.text.content);
|
|
143006
|
+
return true;
|
|
143007
|
+
case "voice":
|
|
143008
|
+
if (item.voice?.content) parts.push(item.voice.content);
|
|
143009
|
+
attachments.push({ kind: "audio" });
|
|
143010
|
+
return true;
|
|
143011
|
+
case "image":
|
|
143012
|
+
attachments.push({ kind: "image" });
|
|
143013
|
+
return true;
|
|
143014
|
+
case "file":
|
|
143015
|
+
attachments.push({ kind: "file" });
|
|
143016
|
+
return true;
|
|
143017
|
+
case "video":
|
|
143018
|
+
attachments.push({ kind: "video" });
|
|
143019
|
+
return true;
|
|
143020
|
+
case "mixed":
|
|
143021
|
+
for (const child of item.mixed?.msg_item ?? []) read(child);
|
|
143022
|
+
return true;
|
|
143023
|
+
default:
|
|
143024
|
+
return false;
|
|
143025
|
+
}
|
|
143026
|
+
};
|
|
143027
|
+
const supported = read(quote);
|
|
143028
|
+
return {
|
|
143029
|
+
...parts.length === 0 ? {} : { content: parts.join("\n") },
|
|
143030
|
+
...attachments.length === 0 ? {} : { attachments },
|
|
143031
|
+
...!supported ? { unavailableReason: "unsupported" } : {}
|
|
143032
|
+
};
|
|
143033
|
+
};
|
|
143034
|
+
|
|
142354
143035
|
// src/wecomApi.ts
|
|
142355
143036
|
var DEFAULT_WECOM_ENDPOINT = "wss://openws.work.weixin.qq.com/wssvr/";
|
|
142356
143037
|
var PING_INTERVAL_MS = 3e4;
|
|
@@ -142435,6 +143116,7 @@ var parseWecomMessage = (frame, botId) => {
|
|
|
142435
143116
|
chatId,
|
|
142436
143117
|
senderUserId: body.from?.userid ?? null,
|
|
142437
143118
|
text: text4,
|
|
143119
|
+
...body.quote === void 0 ? {} : { replyTo: wecomReplyReference(body.quote) },
|
|
142438
143120
|
resources,
|
|
142439
143121
|
requestId: frame.headers?.req_id ?? null,
|
|
142440
143122
|
chatType: mentioned ? "single" : chatType,
|
|
@@ -142674,7 +143356,7 @@ var runWecomClient = (input) => {
|
|
|
142674
143356
|
};
|
|
142675
143357
|
|
|
142676
143358
|
// src/wecomMedia.ts
|
|
142677
|
-
import * as
|
|
143359
|
+
import * as NodeCrypto5 from "node:crypto";
|
|
142678
143360
|
|
|
142679
143361
|
// src/wecomPadding.ts
|
|
142680
143362
|
var PADDING_BLOCK = 32;
|
|
@@ -142705,7 +143387,7 @@ var decryptWecomMedia = (cipher, aesKey) => {
|
|
|
142705
143387
|
if (cipher.byteLength === 0 || cipher.byteLength % AES_BLOCK !== 0) {
|
|
142706
143388
|
throw new WecomDecryptError("the ciphertext is not a whole number of blocks");
|
|
142707
143389
|
}
|
|
142708
|
-
const decipher =
|
|
143390
|
+
const decipher = NodeCrypto5.createDecipheriv("aes-256-cbc", key, key.subarray(0, IV_BYTES));
|
|
142709
143391
|
decipher.setAutoPadding(false);
|
|
142710
143392
|
const plain = Buffer.concat([decipher.update(cipher), decipher.final()]);
|
|
142711
143393
|
const unpadded = stripPadding(plain);
|
|
@@ -142857,6 +143539,7 @@ ${kept}`;
|
|
|
142857
143539
|
chatId: message.chatId,
|
|
142858
143540
|
senderId: message.senderUserId,
|
|
142859
143541
|
text: message.text,
|
|
143542
|
+
...message.replyTo === void 0 ? {} : { replyTo: message.replyTo },
|
|
142860
143543
|
// 群里 @ 到机器人的消息被折算成 single 才放行;真实的聊天类型只留在 conversation。
|
|
142861
143544
|
chatKind: message.conversation === "single" ? "private" : "group",
|
|
142862
143545
|
// 下载地址与密钥打成一个键:核心只管把它原样交回来。
|
|
@@ -142995,14 +143678,14 @@ var WecomAppApiError = class extends Error {
|
|
|
142995
143678
|
this.hint = extras?.hint;
|
|
142996
143679
|
}
|
|
142997
143680
|
};
|
|
142998
|
-
var
|
|
143681
|
+
var cleanString2 = (value2) => {
|
|
142999
143682
|
if (typeof value2 !== "string") return null;
|
|
143000
143683
|
const trimmed = value2.trim();
|
|
143001
143684
|
return trimmed === "" ? null : trimmed;
|
|
143002
143685
|
};
|
|
143003
143686
|
var isHttpUrl = (raw) => /^https?:\/\//iu.test(raw) && URL.canParse(raw);
|
|
143004
143687
|
var normalizeApiBaseUrl = (value2) => {
|
|
143005
|
-
const raw =
|
|
143688
|
+
const raw = cleanString2(value2);
|
|
143006
143689
|
if (raw === null) return WECOM_APP_DEFAULT_API_BASE;
|
|
143007
143690
|
if (!isHttpUrl(raw)) {
|
|
143008
143691
|
throw new WecomAppApiError("invalid-api-base", "API base must be an http(s) URL.");
|
|
@@ -143227,7 +143910,7 @@ var WecomAppApi = class {
|
|
|
143227
143910
|
import * as NodeHttp2 from "node:http";
|
|
143228
143911
|
|
|
143229
143912
|
// src/wecomAppCrypto.ts
|
|
143230
|
-
import * as
|
|
143913
|
+
import * as NodeCrypto6 from "node:crypto";
|
|
143231
143914
|
var AES_KEY_BYTES = 32;
|
|
143232
143915
|
var RANDOM_BYTES = 16;
|
|
143233
143916
|
var WecomAppCryptoError = class extends Error {
|
|
@@ -143250,13 +143933,13 @@ var timingSafeEqualString2 = (a, b) => {
|
|
|
143250
143933
|
const left = Buffer.from(a);
|
|
143251
143934
|
const right = Buffer.from(b);
|
|
143252
143935
|
if (left.length === 0 || left.length !== right.length) return false;
|
|
143253
|
-
return
|
|
143936
|
+
return NodeCrypto6.timingSafeEqual(left, right);
|
|
143254
143937
|
};
|
|
143255
|
-
var computeSignature = (token, timestamp, nonce, encrypt) =>
|
|
143938
|
+
var computeSignature = (token, timestamp, nonce, encrypt) => NodeCrypto6.createHash("sha1").update([token, timestamp, nonce, encrypt].sort().join("")).digest("hex");
|
|
143256
143939
|
var verifySignature = (token, timestamp, nonce, encrypt, signature) => timingSafeEqualString2(computeSignature(token, timestamp, nonce, encrypt), signature);
|
|
143257
143940
|
var decrypt = (encodingAESKey, encryptText, expectReceiveId) => {
|
|
143258
143941
|
const { key, iv } = parseEncodingAESKey(encodingAESKey);
|
|
143259
|
-
const decipher =
|
|
143942
|
+
const decipher = NodeCrypto6.createDecipheriv("aes-256-cbc", key, iv);
|
|
143260
143943
|
decipher.setAutoPadding(false);
|
|
143261
143944
|
let deciphered;
|
|
143262
143945
|
try {
|
|
@@ -143315,7 +143998,7 @@ var createWecomAppCrypto = (input) => {
|
|
|
143315
143998
|
decrypt: (encryptText) => decrypt(encodingAESKey, encryptText, corpId).message
|
|
143316
143999
|
};
|
|
143317
144000
|
};
|
|
143318
|
-
var deriveCallbackPathSecret = (token, encodingAESKey) =>
|
|
144001
|
+
var deriveCallbackPathSecret = (token, encodingAESKey) => NodeCrypto6.createHash("sha256").update(`${token.trim()}:${encodingAESKey.trim()}`).digest("hex").slice(0, 24);
|
|
143319
144002
|
|
|
143320
144003
|
// src/wecomAppParse.ts
|
|
143321
144004
|
var isRecord4 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
@@ -144034,13 +144717,22 @@ var imPlugin = definePlugin({
|
|
|
144034
144717
|
const acknowledgements = makeAcknowledgements(core);
|
|
144035
144718
|
const failures = makeFailureNotices(core);
|
|
144036
144719
|
const replyAnchors = makeReplyAnchors(core.host);
|
|
144037
|
-
const
|
|
144720
|
+
const conclusions = makeConclusionLedger(core);
|
|
144721
|
+
const conclusionDelivery = makeConclusionDelivery(core, replyAnchors);
|
|
144722
|
+
const replyCards = makeReplyCards(
|
|
144723
|
+
core,
|
|
144724
|
+
failures,
|
|
144725
|
+
replyAnchors,
|
|
144726
|
+
conclusions,
|
|
144727
|
+
conclusionDelivery
|
|
144728
|
+
);
|
|
144038
144729
|
const teams = makeTeamGoals(core);
|
|
144039
144730
|
const notifications = makeNotifications(core, {
|
|
144040
144731
|
clearWorking: acknowledgements.clearWorking,
|
|
144041
144732
|
replyCards,
|
|
144042
144733
|
failures,
|
|
144043
|
-
|
|
144734
|
+
conclusions,
|
|
144735
|
+
delivery: conclusionDelivery
|
|
144044
144736
|
});
|
|
144045
144737
|
const webSync = makeWebSync(core);
|
|
144046
144738
|
const approvals = makeApprovals(core, replyAnchors);
|
|
@@ -144051,6 +144743,7 @@ var imPlugin = definePlugin({
|
|
|
144051
144743
|
});
|
|
144052
144744
|
const inboundAttachments = makeInboundAttachments(core);
|
|
144053
144745
|
const turns = makeTurns(core, {
|
|
144746
|
+
conclusions,
|
|
144054
144747
|
attachments: inboundAttachments,
|
|
144055
144748
|
queueFlow: interactions.queueFlow,
|
|
144056
144749
|
rememberThreadProject: notifications.rememberThreadProject,
|