omoclaw 3.1.0 → 3.2.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/dist/handlers/user-events.d.ts +2 -1
- package/dist/index.js +104 -51
- package/package.json +1 -1
|
@@ -7,5 +7,6 @@ interface UserEventNotifier {
|
|
|
7
7
|
promptText?: string;
|
|
8
8
|
}): void;
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
type DebugLogger = ((msg: string) => void) | undefined;
|
|
11
|
+
export declare function handleUserEvent(event: Event, dedup: DedupEngine, state: SessionStateTracker, notify: UserEventNotifier, debugLog?: DebugLogger): void;
|
|
11
12
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -995,6 +995,7 @@ function handleSessionStatusEvent(event, dedup, state, timers, webhookFn, notify
|
|
|
995
995
|
|
|
996
996
|
// src/handlers/user-events.ts
|
|
997
997
|
var PROMPT_PREVIEW_MAX = 200;
|
|
998
|
+
var PROMPT_FLUSH_DELAY_MS = 2000;
|
|
998
999
|
function shortSessionID3(sessionID) {
|
|
999
1000
|
return sessionID.slice(0, 12);
|
|
1000
1001
|
}
|
|
@@ -1010,77 +1011,129 @@ function asString(value) {
|
|
|
1010
1011
|
function normalizePreviewText(input) {
|
|
1011
1012
|
return input.replace(/\s+/g, " ").trim();
|
|
1012
1013
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1014
|
+
var seenMessageIDs = new Set;
|
|
1015
|
+
var SEEN_MAX = 5000;
|
|
1016
|
+
var pendingPrompts = new Map;
|
|
1017
|
+
function evictOldestSeen() {
|
|
1018
|
+
if (seenMessageIDs.size <= SEEN_MAX)
|
|
1019
|
+
return;
|
|
1020
|
+
const first = seenMessageIDs.values().next().value;
|
|
1021
|
+
if (first !== undefined)
|
|
1022
|
+
seenMessageIDs.delete(first);
|
|
1023
|
+
}
|
|
1024
|
+
function flushPendingPrompt(messageID, notify, debugLog) {
|
|
1025
|
+
const pending = pendingPrompts.get(messageID);
|
|
1026
|
+
if (!pending)
|
|
1027
|
+
return;
|
|
1028
|
+
clearTimeout(pending.timer);
|
|
1029
|
+
pendingPrompts.delete(messageID);
|
|
1030
|
+
seenMessageIDs.add(messageID);
|
|
1031
|
+
evictOldestSeen();
|
|
1032
|
+
const preview = normalizePreviewText(pending.text).slice(0, PROMPT_PREVIEW_MAX);
|
|
1033
|
+
if (!preview) {
|
|
1034
|
+
debugLog?.(`User prompt SKIPPED (no text after flush): session=${shortSessionID3(pending.sessionID)} msg=${messageID}`);
|
|
1035
|
+
return;
|
|
1026
1036
|
}
|
|
1037
|
+
debugLog?.(`User prompt FLUSHED: session=${shortSessionID3(pending.sessionID)} msg=${messageID} text="${preview.slice(0, 60)}..."`);
|
|
1038
|
+
notify("user-prompt", `[OpenCode] User prompt submitted (${shortSessionID3(pending.sessionID)}): ${preview}`, pending.agent, { promptText: preview });
|
|
1027
1039
|
}
|
|
1028
|
-
|
|
1029
|
-
function handleUserEvent(event, dedup, state, notify) {
|
|
1040
|
+
function handleUserEvent(event, dedup, state, notify, debugLog) {
|
|
1030
1041
|
if (event.type === "session.created" || event.type === "session.updated") {
|
|
1031
|
-
const
|
|
1032
|
-
if (!
|
|
1042
|
+
const info2 = asObject3(event.properties.info);
|
|
1043
|
+
if (!info2)
|
|
1033
1044
|
return;
|
|
1034
|
-
const
|
|
1035
|
-
if (!
|
|
1045
|
+
const sessionID2 = asString(info2.id);
|
|
1046
|
+
if (!sessionID2)
|
|
1036
1047
|
return;
|
|
1037
|
-
const parentID = asString(
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
if (event.type === "tui.prompt.append") {
|
|
1042
|
-
const text = event.properties.text;
|
|
1043
|
-
if (typeof text === "string") {
|
|
1044
|
-
promptBuffer.append(text);
|
|
1048
|
+
const parentID = asString(info2.parentID);
|
|
1049
|
+
if (parentID) {
|
|
1050
|
+
state.setParentID(sessionID2, parentID);
|
|
1051
|
+
debugLog?.(`ParentID tracked: ${shortSessionID3(sessionID2)} \u2192 parent=${shortSessionID3(parentID)}`);
|
|
1045
1052
|
}
|
|
1046
1053
|
return;
|
|
1047
1054
|
}
|
|
1048
1055
|
if (event.type === "tui.command.execute") {
|
|
1049
1056
|
const command = event.properties.command;
|
|
1050
|
-
if (command
|
|
1051
|
-
const dedupKey = "user-interrupt:tui-command";
|
|
1052
|
-
if (!dedup.shouldSend(dedupKey))
|
|
1053
|
-
return;
|
|
1054
|
-
notify("user-interrupt", "[OpenCode] User interrupt requested");
|
|
1057
|
+
if (command !== "session.interrupt")
|
|
1055
1058
|
return;
|
|
1056
|
-
|
|
1057
|
-
if (
|
|
1058
|
-
promptBuffer.clear();
|
|
1059
|
-
return;
|
|
1060
|
-
}
|
|
1061
|
-
if (command === "prompt.submit") {
|
|
1062
|
-
const preview = promptBuffer.flush();
|
|
1063
|
-
if (!preview)
|
|
1064
|
-
return;
|
|
1065
|
-
const dedupKey = `user-prompt:submit:${Date.now()}`;
|
|
1066
|
-
if (!dedup.shouldSend(dedupKey))
|
|
1067
|
-
return;
|
|
1068
|
-
notify("user-prompt", `[OpenCode] User prompt submitted: ${preview}`, undefined, { promptText: preview });
|
|
1059
|
+
const dedupKey = "user-interrupt:tui-command";
|
|
1060
|
+
if (!dedup.shouldSend(dedupKey))
|
|
1069
1061
|
return;
|
|
1070
|
-
|
|
1062
|
+
notify("user-interrupt", "[OpenCode] User interrupt requested");
|
|
1071
1063
|
return;
|
|
1072
1064
|
}
|
|
1073
1065
|
if (event.type === "session.error") {
|
|
1074
|
-
const
|
|
1066
|
+
const sessionID2 = event.properties.sessionID;
|
|
1075
1067
|
const errorObj = event.properties.error;
|
|
1076
|
-
if (!
|
|
1068
|
+
if (!sessionID2 || errorObj?.name !== "MessageAbortedError")
|
|
1077
1069
|
return;
|
|
1078
|
-
const dedupKey = `user-interrupt:session-error:${
|
|
1070
|
+
const dedupKey = `user-interrupt:session-error:${sessionID2}`;
|
|
1079
1071
|
if (!dedup.shouldSend(dedupKey))
|
|
1080
1072
|
return;
|
|
1081
|
-
notify("user-interrupt", `[OpenCode] User interrupt (${shortSessionID3(
|
|
1073
|
+
notify("user-interrupt", `[OpenCode] User interrupt (${shortSessionID3(sessionID2)})`, state.getAgent(sessionID2));
|
|
1082
1074
|
return;
|
|
1083
1075
|
}
|
|
1076
|
+
if (event.type === "message.part.updated") {
|
|
1077
|
+
const part = asObject3(event.properties.part);
|
|
1078
|
+
if (!part)
|
|
1079
|
+
return;
|
|
1080
|
+
const messageID2 = asString(part.messageID);
|
|
1081
|
+
if (!messageID2)
|
|
1082
|
+
return;
|
|
1083
|
+
const pending = pendingPrompts.get(messageID2);
|
|
1084
|
+
if (!pending)
|
|
1085
|
+
return;
|
|
1086
|
+
if (asString(part.type) !== "text")
|
|
1087
|
+
return;
|
|
1088
|
+
if (part.synthetic === true) {
|
|
1089
|
+
debugLog?.(`User prompt part SKIPPED (synthetic): msg=${messageID2}`);
|
|
1090
|
+
seenMessageIDs.add(messageID2);
|
|
1091
|
+
evictOldestSeen();
|
|
1092
|
+
clearTimeout(pending.timer);
|
|
1093
|
+
pendingPrompts.delete(messageID2);
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
const partText = asString(part.text);
|
|
1097
|
+
if (!partText)
|
|
1098
|
+
return;
|
|
1099
|
+
pending.text += (pending.text ? " " : "") + partText;
|
|
1100
|
+
flushPendingPrompt(messageID2, notify, debugLog);
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
if (event.type !== "message.updated")
|
|
1104
|
+
return;
|
|
1105
|
+
const info = asObject3(event.properties.info);
|
|
1106
|
+
if (!info)
|
|
1107
|
+
return;
|
|
1108
|
+
if (asString(info.role) !== "user")
|
|
1109
|
+
return;
|
|
1110
|
+
const sessionID = asString(info.sessionID);
|
|
1111
|
+
if (!sessionID)
|
|
1112
|
+
return;
|
|
1113
|
+
const messageID = asString(info.id);
|
|
1114
|
+
if (!messageID)
|
|
1115
|
+
return;
|
|
1116
|
+
if (seenMessageIDs.has(messageID))
|
|
1117
|
+
return;
|
|
1118
|
+
if (pendingPrompts.has(messageID))
|
|
1119
|
+
return;
|
|
1120
|
+
if (state.hasParentID(sessionID)) {
|
|
1121
|
+
debugLog?.(`User prompt SKIPPED (sub-agent): session=${shortSessionID3(sessionID)} msg=${messageID}`);
|
|
1122
|
+
seenMessageIDs.add(messageID);
|
|
1123
|
+
evictOldestSeen();
|
|
1124
|
+
return;
|
|
1125
|
+
}
|
|
1126
|
+
debugLog?.(`User prompt PENDING: session=${shortSessionID3(sessionID)} msg=${messageID} (waiting for text parts)`);
|
|
1127
|
+
const timer = setTimeout(() => {
|
|
1128
|
+
flushPendingPrompt(messageID, notify, debugLog);
|
|
1129
|
+
}, PROMPT_FLUSH_DELAY_MS);
|
|
1130
|
+
pendingPrompts.set(messageID, {
|
|
1131
|
+
sessionID,
|
|
1132
|
+
messageID,
|
|
1133
|
+
agent: state.getAgent(sessionID),
|
|
1134
|
+
text: "",
|
|
1135
|
+
timer
|
|
1136
|
+
});
|
|
1084
1137
|
}
|
|
1085
1138
|
|
|
1086
1139
|
// src/project-config.ts
|
|
@@ -1819,7 +1872,7 @@ var SessionMonitorPlugin = async (ctx) => {
|
|
|
1819
1872
|
event: async ({ event }) => {
|
|
1820
1873
|
debugLog?.(`EVENT: ${event.type} props=${JSON.stringify(event.properties).slice(0, 200)}`);
|
|
1821
1874
|
handleAgentEvent(event, state);
|
|
1822
|
-
handleUserEvent(event, dedup, state, notifyByPolicy);
|
|
1875
|
+
handleUserEvent(event, dedup, state, notifyByPolicy, debugLog);
|
|
1823
1876
|
handlePermissionEvent(event, dedup, timers, state, notifyByPolicy);
|
|
1824
1877
|
handleQuestionEvent(event, dedup, timers, state, notifyByPolicy);
|
|
1825
1878
|
handleSessionStatusEvent(event, dedup, state, timers, sendRealtimeWebhook, notifyByPolicy, debugLog);
|
package/package.json
CHANGED