opencode-discord-notify 0.3.2 → 0.3.3
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/dist/index.js +163 -87
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -264,6 +264,7 @@ var plugin = async ({ client }) => {
|
|
|
264
264
|
const toastCooldownMs = 3e4;
|
|
265
265
|
const sendParams = parseSendParams(getEnv("DISCORD_SEND_PARAMS"));
|
|
266
266
|
const lastAlertAtByKey = /* @__PURE__ */ new Map();
|
|
267
|
+
const sentTextPartIds = /* @__PURE__ */ new Set();
|
|
267
268
|
const showToast = async ({ title, message, variant }) => {
|
|
268
269
|
try {
|
|
269
270
|
await client.tui.showToast({
|
|
@@ -424,6 +425,50 @@ var plugin = async ({ client }) => {
|
|
|
424
425
|
function buildPermissionMention() {
|
|
425
426
|
return buildMention(permissionMention, "DISCORD_WEBHOOK_PERMISSION_MENTION");
|
|
426
427
|
}
|
|
428
|
+
function escapeDiscordMention(text) {
|
|
429
|
+
return text.replace(/^@/g, "@\u200B");
|
|
430
|
+
}
|
|
431
|
+
async function handleTextPart(input) {
|
|
432
|
+
const { part, role, sessionID, messageID, replay } = input;
|
|
433
|
+
const partID = part?.id;
|
|
434
|
+
if (!partID) return;
|
|
435
|
+
if (!replay && role === "assistant" && !part?.time?.end) return;
|
|
436
|
+
if (sentTextPartIds.has(partID)) return;
|
|
437
|
+
sentTextPartIds.add(partID);
|
|
438
|
+
const text = escapeDiscordMention(safeString(part?.text));
|
|
439
|
+
if (role === "user" && excludeInputContext && isInputContextText(text)) {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
if (role === "user" && text.trim() === "" || text.trim() === "(empty)") {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
if (role === "user" && !firstUserTextBySession.has(sessionID)) {
|
|
446
|
+
const normalized = normalizeThreadTitle(text);
|
|
447
|
+
if (normalized) firstUserTextBySession.set(sessionID, normalized);
|
|
448
|
+
}
|
|
449
|
+
const embed = {
|
|
450
|
+
title: getTextPartEmbedTitle(role),
|
|
451
|
+
color: COLORS.info,
|
|
452
|
+
fields: buildFields(
|
|
453
|
+
filterSendFields(
|
|
454
|
+
[
|
|
455
|
+
["sessionID", sessionID],
|
|
456
|
+
["messageID", messageID],
|
|
457
|
+
["partID", partID],
|
|
458
|
+
["role", role]
|
|
459
|
+
],
|
|
460
|
+
sendParams
|
|
461
|
+
)
|
|
462
|
+
),
|
|
463
|
+
description: truncateText(text || "(empty)", 4096)
|
|
464
|
+
};
|
|
465
|
+
enqueueToThread(sessionID, { embeds: [embed] });
|
|
466
|
+
if (role === "user") {
|
|
467
|
+
await flushPending(sessionID);
|
|
468
|
+
} else if (shouldFlush(sessionID)) {
|
|
469
|
+
await flushPending(sessionID);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
427
472
|
function setIfChanged(map, key, next) {
|
|
428
473
|
const prev = map.get(key);
|
|
429
474
|
if (prev === next) return false;
|
|
@@ -465,7 +510,102 @@ var plugin = async ({ client }) => {
|
|
|
465
510
|
};
|
|
466
511
|
lastSessionInfo.set(sessionID, { title, shareUrl });
|
|
467
512
|
enqueueToThread(sessionID, { embeds: [embed] });
|
|
468
|
-
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
case "permission.updated": {
|
|
516
|
+
const p = event.properties;
|
|
517
|
+
const sessionID = p?.sessionID;
|
|
518
|
+
if (!sessionID) return;
|
|
519
|
+
const embed = {
|
|
520
|
+
title: "Permission required",
|
|
521
|
+
description: p?.title,
|
|
522
|
+
color: COLORS.warning,
|
|
523
|
+
timestamp: toIsoTimestamp(p?.time?.created),
|
|
524
|
+
fields: buildFields(
|
|
525
|
+
filterSendFields(
|
|
526
|
+
[
|
|
527
|
+
["sessionID", sessionID],
|
|
528
|
+
["permissionID", p?.id],
|
|
529
|
+
["type", p?.type],
|
|
530
|
+
["pattern", p?.pattern],
|
|
531
|
+
["messageID", p?.messageID],
|
|
532
|
+
["callID", p?.callID]
|
|
533
|
+
],
|
|
534
|
+
sendParams
|
|
535
|
+
)
|
|
536
|
+
)
|
|
537
|
+
};
|
|
538
|
+
const mention = buildPermissionMention();
|
|
539
|
+
enqueueToThread(sessionID, {
|
|
540
|
+
content: mention ? `${mention.content}` : void 0,
|
|
541
|
+
allowed_mentions: mention?.allowed_mentions,
|
|
542
|
+
embeds: [embed]
|
|
543
|
+
});
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
case "session.idle": {
|
|
547
|
+
const sessionID = event.properties?.sessionID;
|
|
548
|
+
if (!sessionID) return;
|
|
549
|
+
const embed = {
|
|
550
|
+
title: "Session completed",
|
|
551
|
+
color: COLORS.success,
|
|
552
|
+
fields: buildFields(
|
|
553
|
+
filterSendFields(
|
|
554
|
+
[["sessionID", sessionID]],
|
|
555
|
+
withForcedSendParams(sendParams, ["sessionID"])
|
|
556
|
+
)
|
|
557
|
+
)
|
|
558
|
+
};
|
|
559
|
+
const mention = buildCompleteMention();
|
|
560
|
+
enqueueToThread(sessionID, {
|
|
561
|
+
content: mention ? `${mention.content}` : void 0,
|
|
562
|
+
allowed_mentions: mention?.allowed_mentions,
|
|
563
|
+
embeds: [embed]
|
|
564
|
+
});
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
case "session.error": {
|
|
568
|
+
const p = event.properties;
|
|
569
|
+
const sessionID = p?.sessionID;
|
|
570
|
+
const errorStr = safeString(p?.error);
|
|
571
|
+
const embed = {
|
|
572
|
+
title: "Session error",
|
|
573
|
+
color: COLORS.error,
|
|
574
|
+
description: errorStr ? errorStr.length > 4096 ? errorStr.slice(0, 4093) + "..." : errorStr : void 0,
|
|
575
|
+
fields: buildFields(
|
|
576
|
+
filterSendFields(
|
|
577
|
+
[["sessionID", sessionID]],
|
|
578
|
+
withForcedSendParams(sendParams, [
|
|
579
|
+
"sessionID",
|
|
580
|
+
"projectID",
|
|
581
|
+
"directory"
|
|
582
|
+
])
|
|
583
|
+
)
|
|
584
|
+
)
|
|
585
|
+
};
|
|
586
|
+
if (!sessionID) return;
|
|
587
|
+
const mention = buildCompleteMention();
|
|
588
|
+
enqueueToThread(sessionID, {
|
|
589
|
+
content: mention ? `$Session error` : void 0,
|
|
590
|
+
allowed_mentions: mention?.allowed_mentions,
|
|
591
|
+
embeds: [embed]
|
|
592
|
+
});
|
|
593
|
+
await flushPending(sessionID);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
case "todo.updated": {
|
|
597
|
+
const p = event.properties;
|
|
598
|
+
const sessionID = p?.sessionID;
|
|
599
|
+
if (!sessionID) return;
|
|
600
|
+
const embed = {
|
|
601
|
+
title: "Todo updated",
|
|
602
|
+
color: COLORS.info,
|
|
603
|
+
fields: buildFields(
|
|
604
|
+
filterSendFields([["sessionID", sessionID]], sendParams)
|
|
605
|
+
),
|
|
606
|
+
description: buildTodoChecklist(p?.todos)
|
|
607
|
+
};
|
|
608
|
+
enqueueToThread(sessionID, { embeds: [embed] });
|
|
469
609
|
return;
|
|
470
610
|
}
|
|
471
611
|
case "message.updated": {
|
|
@@ -473,52 +613,22 @@ var plugin = async ({ client }) => {
|
|
|
473
613
|
const messageID = info?.id;
|
|
474
614
|
const role = info?.role;
|
|
475
615
|
if (!messageID) return;
|
|
476
|
-
if (role
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
});
|
|
493
|
-
setIfChanged(/* @__PURE__ */ new Map(), partID, snapshot);
|
|
494
|
-
continue;
|
|
495
|
-
}
|
|
496
|
-
if (role === "user" && !firstUserTextBySession.has(sessionID)) {
|
|
497
|
-
const normalized = normalizeThreadTitle(text);
|
|
498
|
-
if (normalized)
|
|
499
|
-
firstUserTextBySession.set(sessionID, normalized);
|
|
500
|
-
}
|
|
501
|
-
const embed = {
|
|
502
|
-
title: getTextPartEmbedTitle(role),
|
|
503
|
-
color: COLORS.info,
|
|
504
|
-
fields: buildFields(
|
|
505
|
-
filterSendFields(
|
|
506
|
-
[
|
|
507
|
-
["sessionID", sessionID],
|
|
508
|
-
["messageID", messageID],
|
|
509
|
-
["partID", partID],
|
|
510
|
-
["role", role]
|
|
511
|
-
],
|
|
512
|
-
sendParams
|
|
513
|
-
)
|
|
514
|
-
),
|
|
515
|
-
description: truncateText(text || "(empty)", 4096)
|
|
516
|
-
};
|
|
517
|
-
enqueueToThread(sessionID, { embeds: [embed] });
|
|
518
|
-
if (role === "user") await flushPending(sessionID);
|
|
519
|
-
else if (shouldFlush(sessionID)) await flushPending(sessionID);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
616
|
+
if (role !== "user" && role !== "assistant") return;
|
|
617
|
+
messageRoleById.set(messageID, role);
|
|
618
|
+
const pendingParts = pendingTextPartsByMessageId.get(messageID);
|
|
619
|
+
if (!pendingParts?.length) return;
|
|
620
|
+
pendingTextPartsByMessageId.delete(messageID);
|
|
621
|
+
for (const part of pendingParts) {
|
|
622
|
+
const sessionID = part?.sessionID;
|
|
623
|
+
const partID = part?.id;
|
|
624
|
+
if (!sessionID || !partID || part?.type !== "text") continue;
|
|
625
|
+
await handleTextPart({
|
|
626
|
+
part,
|
|
627
|
+
role,
|
|
628
|
+
sessionID,
|
|
629
|
+
messageID,
|
|
630
|
+
replay: true
|
|
631
|
+
});
|
|
522
632
|
}
|
|
523
633
|
return;
|
|
524
634
|
}
|
|
@@ -538,46 +648,12 @@ var plugin = async ({ client }) => {
|
|
|
538
648
|
pendingTextPartsByMessageId.set(messageID, list);
|
|
539
649
|
return;
|
|
540
650
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
role,
|
|
548
|
-
skipped: "input_context"
|
|
549
|
-
});
|
|
550
|
-
setIfChanged(/* @__PURE__ */ new Map(), partID, snapshot);
|
|
551
|
-
return;
|
|
552
|
-
}
|
|
553
|
-
if (role === "user" && !firstUserTextBySession.has(sessionID)) {
|
|
554
|
-
const normalized = normalizeThreadTitle(text);
|
|
555
|
-
if (normalized)
|
|
556
|
-
firstUserTextBySession.set(sessionID, normalized);
|
|
557
|
-
}
|
|
558
|
-
const embed = {
|
|
559
|
-
title: getTextPartEmbedTitle(role),
|
|
560
|
-
color: COLORS.info,
|
|
561
|
-
fields: buildFields(
|
|
562
|
-
filterSendFields(
|
|
563
|
-
[
|
|
564
|
-
["sessionID", sessionID],
|
|
565
|
-
["messageID", messageID],
|
|
566
|
-
["partID", partID],
|
|
567
|
-
["role", role]
|
|
568
|
-
],
|
|
569
|
-
sendParams
|
|
570
|
-
)
|
|
571
|
-
),
|
|
572
|
-
description: truncateText(text || "(empty)", 4096)
|
|
573
|
-
};
|
|
574
|
-
enqueueToThread(sessionID, { embeds: [embed] });
|
|
575
|
-
if (role === "user") {
|
|
576
|
-
await flushPending(sessionID);
|
|
577
|
-
} else if (shouldFlush(sessionID)) {
|
|
578
|
-
await flushPending(sessionID);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
651
|
+
await handleTextPart({
|
|
652
|
+
part,
|
|
653
|
+
role,
|
|
654
|
+
sessionID,
|
|
655
|
+
messageID
|
|
656
|
+
});
|
|
581
657
|
return;
|
|
582
658
|
}
|
|
583
659
|
default:
|