kimaki 0.2.1 → 0.3.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/discordBot.js +41 -3
- package/dist/utils.js +10 -1
- package/package.json +2 -1
- package/src/discordBot.ts +42 -3
- package/src/utils.ts +16 -2
package/dist/discordBot.js
CHANGED
|
@@ -18,6 +18,10 @@ import { transcribeAudio } from './voice.js';
|
|
|
18
18
|
import { extractTagsArrays, extractNonXmlContent } from './xml.js';
|
|
19
19
|
import prettyMilliseconds from 'pretty-ms';
|
|
20
20
|
import { createLogger } from './logger.js';
|
|
21
|
+
import { isAbortError } from './utils.js';
|
|
22
|
+
import { setGlobalDispatcher, Agent } from 'undici';
|
|
23
|
+
// disables the automatic 5 minutes abort after no body
|
|
24
|
+
setGlobalDispatcher(new Agent({ headersTimeout: 0, bodyTimeout: 0 }));
|
|
21
25
|
const discordLogger = createLogger('DISCORD');
|
|
22
26
|
const voiceLogger = createLogger('VOICE');
|
|
23
27
|
const opencodeLogger = createLogger('OPENCODE');
|
|
@@ -615,6 +619,41 @@ export async function initializeOpencodeForDirectory(directory) {
|
|
|
615
619
|
cwd: directory,
|
|
616
620
|
env: {
|
|
617
621
|
...process.env,
|
|
622
|
+
OPENCODE_CONFIG_CONTENT: JSON.stringify({
|
|
623
|
+
$schema: 'https://opencode.ai/config.json',
|
|
624
|
+
lsp: {
|
|
625
|
+
typescript: { disabled: true },
|
|
626
|
+
eslint: { disabled: true },
|
|
627
|
+
gopls: { disabled: true },
|
|
628
|
+
'ruby-lsp': { disabled: true },
|
|
629
|
+
pyright: { disabled: true },
|
|
630
|
+
'elixir-ls': { disabled: true },
|
|
631
|
+
zls: { disabled: true },
|
|
632
|
+
csharp: { disabled: true },
|
|
633
|
+
vue: { disabled: true },
|
|
634
|
+
rust: { disabled: true },
|
|
635
|
+
clangd: { disabled: true },
|
|
636
|
+
svelte: { disabled: true },
|
|
637
|
+
},
|
|
638
|
+
formatter: {
|
|
639
|
+
prettier: { disabled: true },
|
|
640
|
+
biome: { disabled: true },
|
|
641
|
+
gofmt: { disabled: true },
|
|
642
|
+
mix: { disabled: true },
|
|
643
|
+
zig: { disabled: true },
|
|
644
|
+
'clang-format': { disabled: true },
|
|
645
|
+
ktlint: { disabled: true },
|
|
646
|
+
ruff: { disabled: true },
|
|
647
|
+
rubocop: { disabled: true },
|
|
648
|
+
standardrb: { disabled: true },
|
|
649
|
+
htmlbeautifier: { disabled: true },
|
|
650
|
+
},
|
|
651
|
+
permission: {
|
|
652
|
+
edit: 'allow',
|
|
653
|
+
bash: 'allow',
|
|
654
|
+
webfetch: 'allow',
|
|
655
|
+
},
|
|
656
|
+
}),
|
|
618
657
|
OPENCODE_PORT: port.toString(),
|
|
619
658
|
},
|
|
620
659
|
});
|
|
@@ -1041,8 +1080,7 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1041
1080
|
}
|
|
1042
1081
|
}
|
|
1043
1082
|
catch (e) {
|
|
1044
|
-
if (e
|
|
1045
|
-
// Ignore abort controller errors as requested
|
|
1083
|
+
if (isAbortError(e, abortController.signal)) {
|
|
1046
1084
|
sessionLogger.log('AbortController aborted event handling (normal exit)');
|
|
1047
1085
|
return;
|
|
1048
1086
|
}
|
|
@@ -1118,7 +1156,7 @@ async function handleOpencodeSession(prompt, thread, projectDirectory, originalM
|
|
|
1118
1156
|
}
|
|
1119
1157
|
catch (error) {
|
|
1120
1158
|
sessionLogger.error(`ERROR: Failed to send prompt:`, error);
|
|
1121
|
-
if (!(error
|
|
1159
|
+
if (!isAbortError(error, abortController.signal)) {
|
|
1122
1160
|
abortController.abort('error');
|
|
1123
1161
|
if (originalMessage) {
|
|
1124
1162
|
try {
|
package/dist/utils.js
CHANGED
|
@@ -30,7 +30,7 @@ export function generateBotInstallUrl({ clientId, permissions = [
|
|
|
30
30
|
}
|
|
31
31
|
export function deduplicateByKey(arr, keyFn) {
|
|
32
32
|
const seen = new Set();
|
|
33
|
-
return arr.filter(item => {
|
|
33
|
+
return arr.filter((item) => {
|
|
34
34
|
const key = keyFn(item);
|
|
35
35
|
if (seen.has(key)) {
|
|
36
36
|
return false;
|
|
@@ -39,3 +39,12 @@ export function deduplicateByKey(arr, keyFn) {
|
|
|
39
39
|
return true;
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
|
+
export function isAbortError(error, signal) {
|
|
43
|
+
return (error instanceof Error &&
|
|
44
|
+
(error.name === 'AbortError' ||
|
|
45
|
+
error.name === 'Aborterror' ||
|
|
46
|
+
error.name === 'aborterror' ||
|
|
47
|
+
error.name.toLowerCase() === 'aborterror' ||
|
|
48
|
+
error.message?.includes('aborted') ||
|
|
49
|
+
(signal?.aborted ?? false)));
|
|
50
|
+
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "kimaki",
|
|
3
3
|
"module": "index.ts",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.3.0",
|
|
6
6
|
"repository": "https://github.com/remorses/kimaki",
|
|
7
7
|
"bin": "bin.js",
|
|
8
8
|
"files": [
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"pretty-ms": "^9.3.0",
|
|
42
42
|
"prism-media": "^1.3.5",
|
|
43
43
|
"string-dedent": "^3.0.2",
|
|
44
|
+
"undici": "^7.16.0",
|
|
44
45
|
"zod": "^4.0.17"
|
|
45
46
|
},
|
|
46
47
|
"scripts": {
|
package/src/discordBot.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
createOpencodeClient,
|
|
3
3
|
type OpencodeClient,
|
|
4
4
|
type Part,
|
|
5
|
+
type Config,
|
|
5
6
|
} from '@opencode-ai/sdk'
|
|
6
7
|
|
|
7
8
|
import { createGenAIWorker, type GenAIWorker } from './genai-worker-wrapper.js'
|
|
@@ -45,6 +46,10 @@ import { extractTagsArrays, extractNonXmlContent } from './xml.js'
|
|
|
45
46
|
import prettyMilliseconds from 'pretty-ms'
|
|
46
47
|
import type { Session } from '@google/genai'
|
|
47
48
|
import { createLogger } from './logger.js'
|
|
49
|
+
import { isAbortError } from './utils.js'
|
|
50
|
+
import { setGlobalDispatcher, Agent } from 'undici'
|
|
51
|
+
// disables the automatic 5 minutes abort after no body
|
|
52
|
+
setGlobalDispatcher(new Agent({ headersTimeout: 0, bodyTimeout: 0 }))
|
|
48
53
|
|
|
49
54
|
const discordLogger = createLogger('DISCORD')
|
|
50
55
|
const voiceLogger = createLogger('VOICE')
|
|
@@ -833,6 +838,41 @@ export async function initializeOpencodeForDirectory(directory: string) {
|
|
|
833
838
|
cwd: directory,
|
|
834
839
|
env: {
|
|
835
840
|
...process.env,
|
|
841
|
+
OPENCODE_CONFIG_CONTENT: JSON.stringify({
|
|
842
|
+
$schema: 'https://opencode.ai/config.json',
|
|
843
|
+
lsp: {
|
|
844
|
+
typescript: { disabled: true },
|
|
845
|
+
eslint: { disabled: true },
|
|
846
|
+
gopls: { disabled: true },
|
|
847
|
+
'ruby-lsp': { disabled: true },
|
|
848
|
+
pyright: { disabled: true },
|
|
849
|
+
'elixir-ls': { disabled: true },
|
|
850
|
+
zls: { disabled: true },
|
|
851
|
+
csharp: { disabled: true },
|
|
852
|
+
vue: { disabled: true },
|
|
853
|
+
rust: { disabled: true },
|
|
854
|
+
clangd: { disabled: true },
|
|
855
|
+
svelte: { disabled: true },
|
|
856
|
+
},
|
|
857
|
+
formatter: {
|
|
858
|
+
prettier: { disabled: true },
|
|
859
|
+
biome: { disabled: true },
|
|
860
|
+
gofmt: { disabled: true },
|
|
861
|
+
mix: { disabled: true },
|
|
862
|
+
zig: { disabled: true },
|
|
863
|
+
'clang-format': { disabled: true },
|
|
864
|
+
ktlint: { disabled: true },
|
|
865
|
+
ruff: { disabled: true },
|
|
866
|
+
rubocop: { disabled: true },
|
|
867
|
+
standardrb: { disabled: true },
|
|
868
|
+
htmlbeautifier: { disabled: true },
|
|
869
|
+
},
|
|
870
|
+
permission: {
|
|
871
|
+
edit: 'allow',
|
|
872
|
+
bash: 'allow',
|
|
873
|
+
webfetch: 'allow',
|
|
874
|
+
},
|
|
875
|
+
} satisfies Config),
|
|
836
876
|
OPENCODE_PORT: port.toString(),
|
|
837
877
|
},
|
|
838
878
|
},
|
|
@@ -1364,8 +1404,7 @@ async function handleOpencodeSession(
|
|
|
1364
1404
|
}
|
|
1365
1405
|
}
|
|
1366
1406
|
} catch (e) {
|
|
1367
|
-
if (e
|
|
1368
|
-
// Ignore abort controller errors as requested
|
|
1407
|
+
if (isAbortError(e, abortController.signal)) {
|
|
1369
1408
|
sessionLogger.log(
|
|
1370
1409
|
'AbortController aborted event handling (normal exit)',
|
|
1371
1410
|
)
|
|
@@ -1462,7 +1501,7 @@ async function handleOpencodeSession(
|
|
|
1462
1501
|
} catch (error) {
|
|
1463
1502
|
sessionLogger.error(`ERROR: Failed to send prompt:`, error)
|
|
1464
1503
|
|
|
1465
|
-
if (!(error
|
|
1504
|
+
if (!isAbortError(error, abortController.signal)) {
|
|
1466
1505
|
abortController.abort('error')
|
|
1467
1506
|
|
|
1468
1507
|
if (originalMessage) {
|
package/src/utils.ts
CHANGED
|
@@ -48,10 +48,9 @@ export function generateBotInstallUrl({
|
|
|
48
48
|
return url.toString()
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
52
51
|
export function deduplicateByKey<T, K>(arr: T[], keyFn: (item: T) => K): T[] {
|
|
53
52
|
const seen = new Set<K>()
|
|
54
|
-
return arr.filter(item => {
|
|
53
|
+
return arr.filter((item) => {
|
|
55
54
|
const key = keyFn(item)
|
|
56
55
|
if (seen.has(key)) {
|
|
57
56
|
return false
|
|
@@ -60,3 +59,18 @@ export function deduplicateByKey<T, K>(arr: T[], keyFn: (item: T) => K): T[] {
|
|
|
60
59
|
return true
|
|
61
60
|
})
|
|
62
61
|
}
|
|
62
|
+
|
|
63
|
+
export function isAbortError(
|
|
64
|
+
error: unknown,
|
|
65
|
+
signal?: AbortSignal,
|
|
66
|
+
): error is Error {
|
|
67
|
+
return (
|
|
68
|
+
error instanceof Error &&
|
|
69
|
+
(error.name === 'AbortError' ||
|
|
70
|
+
error.name === 'Aborterror' ||
|
|
71
|
+
error.name === 'aborterror' ||
|
|
72
|
+
error.name.toLowerCase() === 'aborterror' ||
|
|
73
|
+
error.message?.includes('aborted') ||
|
|
74
|
+
(signal?.aborted ?? false))
|
|
75
|
+
)
|
|
76
|
+
}
|