kimaki 0.4.0 → 0.4.1
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 +16 -23
- package/package.json +13 -12
- package/src/cli.ts +0 -0
- package/src/discordBot.ts +16 -25
package/dist/discordBot.js
CHANGED
|
@@ -907,17 +907,14 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
907
907
|
const existingController = abortControllers.get(session.id);
|
|
908
908
|
if (existingController) {
|
|
909
909
|
voiceLogger.log(`[ABORT] Cancelling existing request for session: ${session.id}`);
|
|
910
|
-
existingController.abort('New request started');
|
|
910
|
+
existingController.abort(new Error('New request started'));
|
|
911
911
|
}
|
|
912
912
|
if (abortControllers.has(session.id)) {
|
|
913
|
-
abortControllers.get(session.id)?.abort('new reply');
|
|
913
|
+
abortControllers.get(session.id)?.abort(new Error('new reply'));
|
|
914
914
|
}
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
const eventsResult = await getClient().event.subscribe({
|
|
919
|
-
signal: abortController.signal,
|
|
920
|
-
});
|
|
915
|
+
const promptAbortController = new AbortController();
|
|
916
|
+
abortControllers.set(session.id, promptAbortController);
|
|
917
|
+
const eventsResult = await getClient().event.subscribe({});
|
|
921
918
|
const events = eventsResult.stream;
|
|
922
919
|
sessionLogger.log(`Subscribed to OpenCode events`);
|
|
923
920
|
// Load existing part-message mappings from database
|
|
@@ -969,7 +966,7 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
969
966
|
// Outer-scoped interval for typing notifications. Only one at a time.
|
|
970
967
|
let typingInterval = null;
|
|
971
968
|
function startTyping(thread) {
|
|
972
|
-
if (
|
|
969
|
+
if (promptAbortController.signal.aborted) {
|
|
973
970
|
discordLogger.log(`Not starting typing, already aborted`);
|
|
974
971
|
return () => { };
|
|
975
972
|
}
|
|
@@ -991,8 +988,8 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
991
988
|
});
|
|
992
989
|
}, 8000);
|
|
993
990
|
// Only add listener if not already aborted
|
|
994
|
-
if (!
|
|
995
|
-
|
|
991
|
+
if (!promptAbortController.signal.aborted) {
|
|
992
|
+
promptAbortController.signal.addEventListener('abort', () => {
|
|
996
993
|
if (typingInterval) {
|
|
997
994
|
clearInterval(typingInterval);
|
|
998
995
|
typingInterval = null;
|
|
@@ -1064,7 +1061,7 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1064
1061
|
}
|
|
1065
1062
|
// 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
|
|
1066
1063
|
setTimeout(() => {
|
|
1067
|
-
if (
|
|
1064
|
+
if (promptAbortController.signal.aborted)
|
|
1068
1065
|
return;
|
|
1069
1066
|
stopTyping = startTyping(thread);
|
|
1070
1067
|
}, 300);
|
|
@@ -1103,10 +1100,6 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1103
1100
|
}
|
|
1104
1101
|
}
|
|
1105
1102
|
catch (e) {
|
|
1106
|
-
if (isAbortError(e, abortController.signal)) {
|
|
1107
|
-
sessionLogger.log('AbortController aborted event handling (normal exit)');
|
|
1108
|
-
return;
|
|
1109
|
-
}
|
|
1110
1103
|
sessionLogger.error(`Unexpected error in event handling code`, e);
|
|
1111
1104
|
throw e;
|
|
1112
1105
|
}
|
|
@@ -1139,14 +1132,14 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1139
1132
|
sessionLogger.log(`Stopped typing for session`);
|
|
1140
1133
|
}
|
|
1141
1134
|
// Only send duration message if request was not aborted or was aborted with 'finished' reason
|
|
1142
|
-
if (!
|
|
1143
|
-
|
|
1135
|
+
if (!promptAbortController.signal.aborted ||
|
|
1136
|
+
promptAbortController.signal.reason === 'finished') {
|
|
1144
1137
|
const sessionDuration = prettyMilliseconds(Date.now() - sessionStartTime);
|
|
1145
1138
|
await sendThreadMessage(thread, `_Completed in ${sessionDuration}_`);
|
|
1146
1139
|
sessionLogger.log(`DURATION: Session completed in ${sessionDuration}`);
|
|
1147
1140
|
}
|
|
1148
1141
|
else {
|
|
1149
|
-
sessionLogger.log(`Session was aborted (reason: ${
|
|
1142
|
+
sessionLogger.log(`Session was aborted (reason: ${promptAbortController.signal.reason}), skipping duration message`);
|
|
1150
1143
|
}
|
|
1151
1144
|
}
|
|
1152
1145
|
};
|
|
@@ -1159,9 +1152,9 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1159
1152
|
body: {
|
|
1160
1153
|
parts: [{ type: 'text', text: prompt }],
|
|
1161
1154
|
},
|
|
1162
|
-
signal:
|
|
1155
|
+
signal: promptAbortController.signal,
|
|
1163
1156
|
});
|
|
1164
|
-
|
|
1157
|
+
promptAbortController.abort(new Error('finished'));
|
|
1165
1158
|
sessionLogger.log(`Successfully sent prompt, got response`);
|
|
1166
1159
|
abortControllers.delete(session.id);
|
|
1167
1160
|
// Update reaction to success
|
|
@@ -1179,8 +1172,8 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1179
1172
|
}
|
|
1180
1173
|
catch (error) {
|
|
1181
1174
|
sessionLogger.error(`ERROR: Failed to send prompt:`, error);
|
|
1182
|
-
if (!isAbortError(error,
|
|
1183
|
-
|
|
1175
|
+
if (!isAbortError(error, promptAbortController.signal)) {
|
|
1176
|
+
promptAbortController.abort(new Error('error'));
|
|
1184
1177
|
if (originalMessage) {
|
|
1185
1178
|
try {
|
|
1186
1179
|
await originalMessage.reactions.removeAll();
|
package/package.json
CHANGED
|
@@ -2,7 +2,18 @@
|
|
|
2
2
|
"name": "kimaki",
|
|
3
3
|
"module": "index.ts",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.4.
|
|
5
|
+
"version": "0.4.1",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "pnpm tsc && tsx --env-file .env src/cli.ts",
|
|
8
|
+
"prepublishOnly": "pnpm tsc",
|
|
9
|
+
"dev:bun": "DEBUG=1 bun --env-file .env src/cli.ts",
|
|
10
|
+
"test": "tsx scripts/test-opencode.ts",
|
|
11
|
+
"watch": "tsx scripts/watch-session.ts",
|
|
12
|
+
"test:events": "tsx test-events.ts",
|
|
13
|
+
"pcm-to-mp3": "bun scripts/pcm-to-mp3",
|
|
14
|
+
"test:send": "tsx send-test-message.ts",
|
|
15
|
+
"register-commands": "tsx scripts/register-commands.ts"
|
|
16
|
+
},
|
|
6
17
|
"repository": "https://github.com/remorses/kimaki",
|
|
7
18
|
"bin": "bin.js",
|
|
8
19
|
"files": [
|
|
@@ -43,15 +54,5 @@
|
|
|
43
54
|
"string-dedent": "^3.0.2",
|
|
44
55
|
"undici": "^7.16.0",
|
|
45
56
|
"zod": "^4.0.17"
|
|
46
|
-
},
|
|
47
|
-
"scripts": {
|
|
48
|
-
"dev": "pnpm tsc && tsx --env-file .env src/cli.ts",
|
|
49
|
-
"dev:bun": "DEBUG=1 bun --env-file .env src/cli.ts",
|
|
50
|
-
"test": "tsx scripts/test-opencode.ts",
|
|
51
|
-
"watch": "tsx scripts/watch-session.ts",
|
|
52
|
-
"test:events": "tsx test-events.ts",
|
|
53
|
-
"pcm-to-mp3": "bun scripts/pcm-to-mp3",
|
|
54
|
-
"test:send": "tsx send-test-message.ts",
|
|
55
|
-
"register-commands": "tsx scripts/register-commands.ts"
|
|
56
57
|
}
|
|
57
|
-
}
|
|
58
|
+
}
|
package/src/cli.ts
CHANGED
|
File without changes
|
package/src/discordBot.ts
CHANGED
|
@@ -1169,19 +1169,16 @@ async function handleOpencodeSession(
|
|
|
1169
1169
|
voiceLogger.log(
|
|
1170
1170
|
`[ABORT] Cancelling existing request for session: ${session.id}`,
|
|
1171
1171
|
)
|
|
1172
|
-
existingController.abort('New request started')
|
|
1172
|
+
existingController.abort(new Error('New request started'))
|
|
1173
1173
|
}
|
|
1174
1174
|
|
|
1175
1175
|
if (abortControllers.has(session.id)) {
|
|
1176
|
-
abortControllers.get(session.id)?.abort('new reply')
|
|
1176
|
+
abortControllers.get(session.id)?.abort(new Error('new reply'))
|
|
1177
1177
|
}
|
|
1178
|
-
const
|
|
1179
|
-
|
|
1180
|
-
abortControllers.set(session.id, abortController)
|
|
1178
|
+
const promptAbortController = new AbortController()
|
|
1179
|
+
abortControllers.set(session.id, promptAbortController)
|
|
1181
1180
|
|
|
1182
|
-
const eventsResult = await getClient().event.subscribe({
|
|
1183
|
-
signal: abortController.signal,
|
|
1184
|
-
})
|
|
1181
|
+
const eventsResult = await getClient().event.subscribe({})
|
|
1185
1182
|
const events = eventsResult.stream
|
|
1186
1183
|
sessionLogger.log(`Subscribed to OpenCode events`)
|
|
1187
1184
|
|
|
@@ -1253,7 +1250,7 @@ async function handleOpencodeSession(
|
|
|
1253
1250
|
let typingInterval: NodeJS.Timeout | null = null
|
|
1254
1251
|
|
|
1255
1252
|
function startTyping(thread: ThreadChannel): () => void {
|
|
1256
|
-
if (
|
|
1253
|
+
if (promptAbortController.signal.aborted) {
|
|
1257
1254
|
discordLogger.log(`Not starting typing, already aborted`)
|
|
1258
1255
|
return () => {}
|
|
1259
1256
|
}
|
|
@@ -1279,8 +1276,8 @@ async function handleOpencodeSession(
|
|
|
1279
1276
|
}, 8000)
|
|
1280
1277
|
|
|
1281
1278
|
// Only add listener if not already aborted
|
|
1282
|
-
if (!
|
|
1283
|
-
|
|
1279
|
+
if (!promptAbortController.signal.aborted) {
|
|
1280
|
+
promptAbortController.signal.addEventListener(
|
|
1284
1281
|
'abort',
|
|
1285
1282
|
() => {
|
|
1286
1283
|
if (typingInterval) {
|
|
@@ -1378,7 +1375,7 @@ async function handleOpencodeSession(
|
|
|
1378
1375
|
}
|
|
1379
1376
|
// 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
|
|
1380
1377
|
setTimeout(() => {
|
|
1381
|
-
if (
|
|
1378
|
+
if (promptAbortController.signal.aborted) return
|
|
1382
1379
|
stopTyping = startTyping(thread)
|
|
1383
1380
|
}, 300)
|
|
1384
1381
|
}
|
|
@@ -1418,12 +1415,6 @@ async function handleOpencodeSession(
|
|
|
1418
1415
|
}
|
|
1419
1416
|
}
|
|
1420
1417
|
} catch (e) {
|
|
1421
|
-
if (isAbortError(e, abortController.signal)) {
|
|
1422
|
-
sessionLogger.log(
|
|
1423
|
-
'AbortController aborted event handling (normal exit)',
|
|
1424
|
-
)
|
|
1425
|
-
return
|
|
1426
|
-
}
|
|
1427
1418
|
sessionLogger.error(`Unexpected error in event handling code`, e)
|
|
1428
1419
|
throw e
|
|
1429
1420
|
} finally {
|
|
@@ -1463,8 +1454,8 @@ async function handleOpencodeSession(
|
|
|
1463
1454
|
|
|
1464
1455
|
// Only send duration message if request was not aborted or was aborted with 'finished' reason
|
|
1465
1456
|
if (
|
|
1466
|
-
!
|
|
1467
|
-
|
|
1457
|
+
!promptAbortController.signal.aborted ||
|
|
1458
|
+
promptAbortController.signal.reason === 'finished'
|
|
1468
1459
|
) {
|
|
1469
1460
|
const sessionDuration = prettyMilliseconds(
|
|
1470
1461
|
Date.now() - sessionStartTime,
|
|
@@ -1473,7 +1464,7 @@ async function handleOpencodeSession(
|
|
|
1473
1464
|
sessionLogger.log(`DURATION: Session completed in ${sessionDuration}`)
|
|
1474
1465
|
} else {
|
|
1475
1466
|
sessionLogger.log(
|
|
1476
|
-
`Session was aborted (reason: ${
|
|
1467
|
+
`Session was aborted (reason: ${promptAbortController.signal.reason}), skipping duration message`,
|
|
1477
1468
|
)
|
|
1478
1469
|
}
|
|
1479
1470
|
}
|
|
@@ -1492,9 +1483,9 @@ async function handleOpencodeSession(
|
|
|
1492
1483
|
body: {
|
|
1493
1484
|
parts: [{ type: 'text', text: prompt }],
|
|
1494
1485
|
},
|
|
1495
|
-
signal:
|
|
1486
|
+
signal: promptAbortController.signal,
|
|
1496
1487
|
})
|
|
1497
|
-
|
|
1488
|
+
promptAbortController.abort(new Error('finished'))
|
|
1498
1489
|
|
|
1499
1490
|
sessionLogger.log(`Successfully sent prompt, got response`)
|
|
1500
1491
|
|
|
@@ -1515,8 +1506,8 @@ async function handleOpencodeSession(
|
|
|
1515
1506
|
} catch (error) {
|
|
1516
1507
|
sessionLogger.error(`ERROR: Failed to send prompt:`, error)
|
|
1517
1508
|
|
|
1518
|
-
if (!isAbortError(error,
|
|
1519
|
-
|
|
1509
|
+
if (!isAbortError(error, promptAbortController.signal)) {
|
|
1510
|
+
promptAbortController.abort(new Error('error'))
|
|
1520
1511
|
|
|
1521
1512
|
if (originalMessage) {
|
|
1522
1513
|
try {
|