kimaki 0.4.1 → 0.4.2
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/discordBot.js +21 -14
- package/package.json +1 -1
- package/src/discordBot.ts +23 -14
package/dist/discordBot.js
CHANGED
|
@@ -912,9 +912,12 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
912
912
|
if (abortControllers.has(session.id)) {
|
|
913
913
|
abortControllers.get(session.id)?.abort(new Error('new reply'));
|
|
914
914
|
}
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
|
|
915
|
+
const abortController = new AbortController();
|
|
916
|
+
// Store this controller for this session
|
|
917
|
+
abortControllers.set(session.id, abortController);
|
|
918
|
+
const eventsResult = await getClient().event.subscribe({
|
|
919
|
+
signal: abortController.signal,
|
|
920
|
+
});
|
|
918
921
|
const events = eventsResult.stream;
|
|
919
922
|
sessionLogger.log(`Subscribed to OpenCode events`);
|
|
920
923
|
// Load existing part-message mappings from database
|
|
@@ -966,7 +969,7 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
966
969
|
// Outer-scoped interval for typing notifications. Only one at a time.
|
|
967
970
|
let typingInterval = null;
|
|
968
971
|
function startTyping(thread) {
|
|
969
|
-
if (
|
|
972
|
+
if (abortController.signal.aborted) {
|
|
970
973
|
discordLogger.log(`Not starting typing, already aborted`);
|
|
971
974
|
return () => { };
|
|
972
975
|
}
|
|
@@ -988,8 +991,8 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
988
991
|
});
|
|
989
992
|
}, 8000);
|
|
990
993
|
// Only add listener if not already aborted
|
|
991
|
-
if (!
|
|
992
|
-
|
|
994
|
+
if (!abortController.signal.aborted) {
|
|
995
|
+
abortController.signal.addEventListener('abort', () => {
|
|
993
996
|
if (typingInterval) {
|
|
994
997
|
clearInterval(typingInterval);
|
|
995
998
|
typingInterval = null;
|
|
@@ -1061,7 +1064,7 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1061
1064
|
}
|
|
1062
1065
|
// start typing in a moment, so that if the session finished, because step-finish is at the end of the message, we do not show typing status
|
|
1063
1066
|
setTimeout(() => {
|
|
1064
|
-
if (
|
|
1067
|
+
if (abortController.signal.aborted)
|
|
1065
1068
|
return;
|
|
1066
1069
|
stopTyping = startTyping(thread);
|
|
1067
1070
|
}, 300);
|
|
@@ -1100,6 +1103,10 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1100
1103
|
}
|
|
1101
1104
|
}
|
|
1102
1105
|
catch (e) {
|
|
1106
|
+
if (isAbortError(e, abortController.signal)) {
|
|
1107
|
+
sessionLogger.log('AbortController aborted event handling (normal exit)');
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1103
1110
|
sessionLogger.error(`Unexpected error in event handling code`, e);
|
|
1104
1111
|
throw e;
|
|
1105
1112
|
}
|
|
@@ -1132,14 +1139,14 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1132
1139
|
sessionLogger.log(`Stopped typing for session`);
|
|
1133
1140
|
}
|
|
1134
1141
|
// Only send duration message if request was not aborted or was aborted with 'finished' reason
|
|
1135
|
-
if (!
|
|
1136
|
-
|
|
1142
|
+
if (!abortController.signal.aborted ||
|
|
1143
|
+
abortController.signal.reason === 'finished') {
|
|
1137
1144
|
const sessionDuration = prettyMilliseconds(Date.now() - sessionStartTime);
|
|
1138
1145
|
await sendThreadMessage(thread, `_Completed in ${sessionDuration}_`);
|
|
1139
1146
|
sessionLogger.log(`DURATION: Session completed in ${sessionDuration}`);
|
|
1140
1147
|
}
|
|
1141
1148
|
else {
|
|
1142
|
-
sessionLogger.log(`Session was aborted (reason: ${
|
|
1149
|
+
sessionLogger.log(`Session was aborted (reason: ${abortController.signal.reason}), skipping duration message`);
|
|
1143
1150
|
}
|
|
1144
1151
|
}
|
|
1145
1152
|
};
|
|
@@ -1152,9 +1159,9 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1152
1159
|
body: {
|
|
1153
1160
|
parts: [{ type: 'text', text: prompt }],
|
|
1154
1161
|
},
|
|
1155
|
-
signal:
|
|
1162
|
+
signal: abortController.signal,
|
|
1156
1163
|
});
|
|
1157
|
-
|
|
1164
|
+
abortController.abort(new Error('finished'));
|
|
1158
1165
|
sessionLogger.log(`Successfully sent prompt, got response`);
|
|
1159
1166
|
abortControllers.delete(session.id);
|
|
1160
1167
|
// Update reaction to success
|
|
@@ -1172,8 +1179,8 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1172
1179
|
}
|
|
1173
1180
|
catch (error) {
|
|
1174
1181
|
sessionLogger.error(`ERROR: Failed to send prompt:`, error);
|
|
1175
|
-
if (!isAbortError(error,
|
|
1176
|
-
|
|
1182
|
+
if (!isAbortError(error, abortController.signal)) {
|
|
1183
|
+
abortController.abort(new Error('error'));
|
|
1177
1184
|
if (originalMessage) {
|
|
1178
1185
|
try {
|
|
1179
1186
|
await originalMessage.reactions.removeAll();
|
package/package.json
CHANGED
package/src/discordBot.ts
CHANGED
|
@@ -1175,10 +1175,13 @@ async function handleOpencodeSession(
|
|
|
1175
1175
|
if (abortControllers.has(session.id)) {
|
|
1176
1176
|
abortControllers.get(session.id)?.abort(new Error('new reply'))
|
|
1177
1177
|
}
|
|
1178
|
-
const
|
|
1179
|
-
|
|
1178
|
+
const abortController = new AbortController()
|
|
1179
|
+
// Store this controller for this session
|
|
1180
|
+
abortControllers.set(session.id, abortController)
|
|
1180
1181
|
|
|
1181
|
-
const eventsResult = await getClient().event.subscribe({
|
|
1182
|
+
const eventsResult = await getClient().event.subscribe({
|
|
1183
|
+
signal: abortController.signal,
|
|
1184
|
+
})
|
|
1182
1185
|
const events = eventsResult.stream
|
|
1183
1186
|
sessionLogger.log(`Subscribed to OpenCode events`)
|
|
1184
1187
|
|
|
@@ -1250,7 +1253,7 @@ async function handleOpencodeSession(
|
|
|
1250
1253
|
let typingInterval: NodeJS.Timeout | null = null
|
|
1251
1254
|
|
|
1252
1255
|
function startTyping(thread: ThreadChannel): () => void {
|
|
1253
|
-
if (
|
|
1256
|
+
if (abortController.signal.aborted) {
|
|
1254
1257
|
discordLogger.log(`Not starting typing, already aborted`)
|
|
1255
1258
|
return () => {}
|
|
1256
1259
|
}
|
|
@@ -1276,8 +1279,8 @@ async function handleOpencodeSession(
|
|
|
1276
1279
|
}, 8000)
|
|
1277
1280
|
|
|
1278
1281
|
// Only add listener if not already aborted
|
|
1279
|
-
if (!
|
|
1280
|
-
|
|
1282
|
+
if (!abortController.signal.aborted) {
|
|
1283
|
+
abortController.signal.addEventListener(
|
|
1281
1284
|
'abort',
|
|
1282
1285
|
() => {
|
|
1283
1286
|
if (typingInterval) {
|
|
@@ -1375,7 +1378,7 @@ async function handleOpencodeSession(
|
|
|
1375
1378
|
}
|
|
1376
1379
|
// start typing in a moment, so that if the session finished, because step-finish is at the end of the message, we do not show typing status
|
|
1377
1380
|
setTimeout(() => {
|
|
1378
|
-
if (
|
|
1381
|
+
if (abortController.signal.aborted) return
|
|
1379
1382
|
stopTyping = startTyping(thread)
|
|
1380
1383
|
}, 300)
|
|
1381
1384
|
}
|
|
@@ -1415,6 +1418,12 @@ async function handleOpencodeSession(
|
|
|
1415
1418
|
}
|
|
1416
1419
|
}
|
|
1417
1420
|
} catch (e) {
|
|
1421
|
+
if (isAbortError(e, abortController.signal)) {
|
|
1422
|
+
sessionLogger.log(
|
|
1423
|
+
'AbortController aborted event handling (normal exit)',
|
|
1424
|
+
)
|
|
1425
|
+
return
|
|
1426
|
+
}
|
|
1418
1427
|
sessionLogger.error(`Unexpected error in event handling code`, e)
|
|
1419
1428
|
throw e
|
|
1420
1429
|
} finally {
|
|
@@ -1454,8 +1463,8 @@ async function handleOpencodeSession(
|
|
|
1454
1463
|
|
|
1455
1464
|
// Only send duration message if request was not aborted or was aborted with 'finished' reason
|
|
1456
1465
|
if (
|
|
1457
|
-
!
|
|
1458
|
-
|
|
1466
|
+
!abortController.signal.aborted ||
|
|
1467
|
+
abortController.signal.reason === 'finished'
|
|
1459
1468
|
) {
|
|
1460
1469
|
const sessionDuration = prettyMilliseconds(
|
|
1461
1470
|
Date.now() - sessionStartTime,
|
|
@@ -1464,7 +1473,7 @@ async function handleOpencodeSession(
|
|
|
1464
1473
|
sessionLogger.log(`DURATION: Session completed in ${sessionDuration}`)
|
|
1465
1474
|
} else {
|
|
1466
1475
|
sessionLogger.log(
|
|
1467
|
-
`Session was aborted (reason: ${
|
|
1476
|
+
`Session was aborted (reason: ${abortController.signal.reason}), skipping duration message`,
|
|
1468
1477
|
)
|
|
1469
1478
|
}
|
|
1470
1479
|
}
|
|
@@ -1483,9 +1492,9 @@ async function handleOpencodeSession(
|
|
|
1483
1492
|
body: {
|
|
1484
1493
|
parts: [{ type: 'text', text: prompt }],
|
|
1485
1494
|
},
|
|
1486
|
-
signal:
|
|
1495
|
+
signal: abortController.signal,
|
|
1487
1496
|
})
|
|
1488
|
-
|
|
1497
|
+
abortController.abort(new Error('finished'))
|
|
1489
1498
|
|
|
1490
1499
|
sessionLogger.log(`Successfully sent prompt, got response`)
|
|
1491
1500
|
|
|
@@ -1506,8 +1515,8 @@ async function handleOpencodeSession(
|
|
|
1506
1515
|
} catch (error) {
|
|
1507
1516
|
sessionLogger.error(`ERROR: Failed to send prompt:`, error)
|
|
1508
1517
|
|
|
1509
|
-
if (!isAbortError(error,
|
|
1510
|
-
|
|
1518
|
+
if (!isAbortError(error, abortController.signal)) {
|
|
1519
|
+
abortController.abort(new Error('error'))
|
|
1511
1520
|
|
|
1512
1521
|
if (originalMessage) {
|
|
1513
1522
|
try {
|