@grinev/opencode-telegram-bot 0.17.0 → 0.18.0
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 +15 -1
- package/dist/attach/manager.js +66 -0
- package/dist/attach/service.js +166 -0
- package/dist/bot/commands/abort.js +0 -4
- package/dist/bot/commands/commands.js +13 -3
- package/dist/bot/commands/new.js +10 -18
- package/dist/bot/commands/sessions.js +19 -20
- package/dist/bot/commands/start.js +2 -0
- package/dist/bot/handlers/prompt.js +26 -31
- package/dist/bot/index.js +76 -8
- package/dist/bot/middleware/interaction-guard.js +1 -1
- package/dist/bot/utils/busy-guard.js +3 -2
- package/dist/bot/utils/external-user-input.js +46 -0
- package/dist/bot/utils/switch-project.js +2 -0
- package/dist/external-input/suppression.js +54 -0
- package/dist/i18n/de.js +15 -0
- package/dist/i18n/en.js +15 -0
- package/dist/i18n/es.js +15 -0
- package/dist/i18n/fr.js +15 -0
- package/dist/i18n/ru.js +15 -0
- package/dist/i18n/zh.js +15 -0
- package/dist/interaction/guard.js +2 -1
- package/dist/opencode/events.js +13 -1
- package/dist/pinned/manager.js +18 -0
- package/dist/summary/aggregator.js +54 -9
- package/package.json +1 -1
package/dist/pinned/manager.js
CHANGED
|
@@ -15,6 +15,8 @@ class PinnedMessageManager {
|
|
|
15
15
|
chatId: null,
|
|
16
16
|
sessionId: null,
|
|
17
17
|
sessionTitle: t("pinned.default_session_title"),
|
|
18
|
+
attachActive: false,
|
|
19
|
+
attachBusy: false,
|
|
18
20
|
projectPath: "",
|
|
19
21
|
projectBranch: null,
|
|
20
22
|
projectWorktreePath: null,
|
|
@@ -55,6 +57,8 @@ class PinnedMessageManager {
|
|
|
55
57
|
// Update state
|
|
56
58
|
this.state.sessionId = sessionId;
|
|
57
59
|
this.state.sessionTitle = sessionTitle || t("pinned.default_session_title");
|
|
60
|
+
this.state.attachActive = false;
|
|
61
|
+
this.state.attachBusy = false;
|
|
58
62
|
await this.refreshProjectMetadata();
|
|
59
63
|
// Fetch context limit for current model
|
|
60
64
|
await this.fetchContextLimit();
|
|
@@ -83,6 +87,15 @@ class PinnedMessageManager {
|
|
|
83
87
|
await this.updatePinnedMessage();
|
|
84
88
|
}
|
|
85
89
|
}
|
|
90
|
+
async setAttachState(active, busy) {
|
|
91
|
+
const nextBusy = active ? busy : false;
|
|
92
|
+
if (this.state.attachActive === active && this.state.attachBusy === nextBusy) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.state.attachActive = active;
|
|
96
|
+
this.state.attachBusy = nextBusy;
|
|
97
|
+
await this.updatePinnedMessage();
|
|
98
|
+
}
|
|
86
99
|
/**
|
|
87
100
|
* Load context token usage from session history
|
|
88
101
|
*/
|
|
@@ -672,6 +685,9 @@ class PinnedMessageManager {
|
|
|
672
685
|
// Just reset state if not initialized
|
|
673
686
|
this.state.messageId = null;
|
|
674
687
|
this.state.sessionId = null;
|
|
688
|
+
this.state.sessionTitle = t("pinned.default_session_title");
|
|
689
|
+
this.state.attachActive = false;
|
|
690
|
+
this.state.attachBusy = false;
|
|
675
691
|
this.state.tokensUsed = 0;
|
|
676
692
|
this.state.tokensLimit = 0;
|
|
677
693
|
this.state.projectPath = "";
|
|
@@ -691,6 +707,8 @@ class PinnedMessageManager {
|
|
|
691
707
|
this.state.messageId = null;
|
|
692
708
|
this.state.sessionId = null;
|
|
693
709
|
this.state.sessionTitle = t("pinned.default_session_title");
|
|
710
|
+
this.state.attachActive = false;
|
|
711
|
+
this.state.attachBusy = false;
|
|
694
712
|
this.state.projectPath = "";
|
|
695
713
|
this.state.projectBranch = null;
|
|
696
714
|
this.state.projectWorktreePath = null;
|
|
@@ -32,6 +32,7 @@ class SummaryAggregator {
|
|
|
32
32
|
lastUpdated = 0;
|
|
33
33
|
onCompleteCallback = null;
|
|
34
34
|
onPartialCallback = null;
|
|
35
|
+
onExternalUserInputCallback = null;
|
|
35
36
|
onToolCallback = null;
|
|
36
37
|
onToolFileCallback = null;
|
|
37
38
|
onQuestionCallback = null;
|
|
@@ -50,6 +51,7 @@ class SummaryAggregator {
|
|
|
50
51
|
onClearedCallback = null;
|
|
51
52
|
processedToolStates = new Set();
|
|
52
53
|
thinkingFiredForMessages = new Set();
|
|
54
|
+
deliveredExternalUserMessageIds = new Set();
|
|
53
55
|
knownTextPartIds = new Map();
|
|
54
56
|
bot = null;
|
|
55
57
|
chatId = null;
|
|
@@ -73,6 +75,9 @@ class SummaryAggregator {
|
|
|
73
75
|
setOnPartial(callback) {
|
|
74
76
|
this.onPartialCallback = callback;
|
|
75
77
|
}
|
|
78
|
+
setOnExternalUserInput(callback) {
|
|
79
|
+
this.onExternalUserInputCallback = callback;
|
|
80
|
+
}
|
|
76
81
|
setOnTool(callback) {
|
|
77
82
|
this.onToolCallback = callback;
|
|
78
83
|
}
|
|
@@ -226,6 +231,7 @@ class SummaryAggregator {
|
|
|
226
231
|
this.knownTextPartIds.clear();
|
|
227
232
|
this.processedToolStates.clear();
|
|
228
233
|
this.thinkingFiredForMessages.clear();
|
|
234
|
+
this.deliveredExternalUserMessageIds.clear();
|
|
229
235
|
this.trackedSessionParents.clear();
|
|
230
236
|
this.subagentStates.clear();
|
|
231
237
|
this.subagentOrder = [];
|
|
@@ -605,6 +611,10 @@ class SummaryAggregator {
|
|
|
605
611
|
}
|
|
606
612
|
const messageID = info.id;
|
|
607
613
|
this.messages.set(messageID, { role: info.role });
|
|
614
|
+
if (info.role === "user") {
|
|
615
|
+
this.emitExternalUserInputIfReady(info.sessionID, messageID);
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
608
618
|
if (info.role === "assistant") {
|
|
609
619
|
if (!this.textMessageStates.has(messageID)) {
|
|
610
620
|
this.textMessageStates.set(messageID, {
|
|
@@ -655,15 +665,8 @@ class SummaryAggregator {
|
|
|
655
665
|
completedAt: time?.completed,
|
|
656
666
|
});
|
|
657
667
|
}
|
|
658
|
-
this.
|
|
659
|
-
this.messages.delete(messageID);
|
|
660
|
-
this.partHashes.delete(messageID);
|
|
661
|
-
this.knownTextPartIds.delete(messageID);
|
|
668
|
+
this.cleanupCompletedMessage(messageID);
|
|
662
669
|
logger.debug(`[Aggregator] Message completed cleanup: remaining messages=${this.textMessageStates.size}`);
|
|
663
|
-
if (this.textMessageStates.size === 0) {
|
|
664
|
-
logger.debug("[Aggregator] No more active messages, stopping typing indicator");
|
|
665
|
-
this.stopTypingIndicator();
|
|
666
|
-
}
|
|
667
670
|
}
|
|
668
671
|
this.lastUpdated = Date.now();
|
|
669
672
|
}
|
|
@@ -741,6 +744,9 @@ class SummaryAggregator {
|
|
|
741
744
|
this.startTypingIndicator();
|
|
742
745
|
this.emitPartialText(part.sessionID, messageID, fullText);
|
|
743
746
|
}
|
|
747
|
+
else if (messageInfo && messageInfo.role === "user") {
|
|
748
|
+
this.emitExternalUserInputIfReady(part.sessionID, messageID);
|
|
749
|
+
}
|
|
744
750
|
else {
|
|
745
751
|
const state = this.getOrCreateTextMessageState(messageID);
|
|
746
752
|
state.optimisticUpdateCount++;
|
|
@@ -857,9 +863,48 @@ class SummaryAggregator {
|
|
|
857
863
|
if (!combined.trim()) {
|
|
858
864
|
return;
|
|
859
865
|
}
|
|
866
|
+
const messageInfo = this.messages.get(messageID);
|
|
867
|
+
if (messageInfo?.role === "user") {
|
|
868
|
+
this.emitExternalUserInputIfReady(sessionID, messageID);
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
860
871
|
this.startTypingIndicator();
|
|
861
872
|
this.emitPartialText(sessionID, messageID, combined);
|
|
862
873
|
}
|
|
874
|
+
emitExternalUserInputIfReady(sessionId, messageId) {
|
|
875
|
+
if (sessionId !== this.currentSessionId || this.deliveredExternalUserMessageIds.has(messageId)) {
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
const messageInfo = this.messages.get(messageId);
|
|
879
|
+
if (!messageInfo || messageInfo.role !== "user") {
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
const messageText = this.getCombinedMessageText(messageId).trim();
|
|
883
|
+
if (!messageText) {
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
this.deliveredExternalUserMessageIds.add(messageId);
|
|
887
|
+
this.cleanupCompletedMessage(messageId);
|
|
888
|
+
if (!this.onExternalUserInputCallback) {
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
const callback = this.onExternalUserInputCallback;
|
|
892
|
+
setImmediate(() => {
|
|
893
|
+
Promise.resolve(callback(sessionId, messageId, messageText)).catch((err) => {
|
|
894
|
+
logger.error("[Aggregator] Error in external user input callback:", err);
|
|
895
|
+
});
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
cleanupCompletedMessage(messageId) {
|
|
899
|
+
this.textMessageStates.delete(messageId);
|
|
900
|
+
this.messages.delete(messageId);
|
|
901
|
+
this.partHashes.delete(messageId);
|
|
902
|
+
this.knownTextPartIds.delete(messageId);
|
|
903
|
+
if (this.textMessageStates.size === 0) {
|
|
904
|
+
logger.debug("[Aggregator] No more active messages, stopping typing indicator");
|
|
905
|
+
this.stopTypingIndicator();
|
|
906
|
+
}
|
|
907
|
+
}
|
|
863
908
|
emitPartialText(sessionId, messageId, messageText) {
|
|
864
909
|
if (!this.onPartialCallback || !messageText.trim()) {
|
|
865
910
|
return;
|
|
@@ -1103,7 +1148,7 @@ class SummaryAggregator {
|
|
|
1103
1148
|
const callback = this.onQuestionCallback;
|
|
1104
1149
|
setImmediate(async () => {
|
|
1105
1150
|
try {
|
|
1106
|
-
await callback(questions, id);
|
|
1151
|
+
await callback(questions, id, sessionID);
|
|
1107
1152
|
}
|
|
1108
1153
|
catch (err) {
|
|
1109
1154
|
logger.error("[Aggregator] Error in question callback:", err);
|