kimaki 0.4.24 → 0.4.26
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/bin.js +6 -1
- package/dist/acp-client.test.js +149 -0
- package/dist/ai-tool-to-genai.js +3 -0
- package/dist/channel-management.js +14 -9
- package/dist/cli.js +148 -17
- package/dist/commands/abort.js +78 -0
- package/dist/commands/add-project.js +98 -0
- package/dist/commands/agent.js +152 -0
- package/dist/commands/ask-question.js +183 -0
- package/dist/commands/create-new-project.js +78 -0
- package/dist/commands/fork.js +186 -0
- package/dist/commands/model.js +313 -0
- package/dist/commands/permissions.js +126 -0
- package/dist/commands/queue.js +129 -0
- package/dist/commands/resume.js +145 -0
- package/dist/commands/session.js +142 -0
- package/dist/commands/share.js +80 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/undo-redo.js +161 -0
- package/dist/commands/user-command.js +145 -0
- package/dist/database.js +54 -0
- package/dist/discord-bot.js +35 -32
- package/dist/discord-utils.js +81 -15
- package/dist/format-tables.js +3 -0
- package/dist/genai-worker-wrapper.js +3 -0
- package/dist/genai-worker.js +3 -0
- package/dist/genai.js +3 -0
- package/dist/interaction-handler.js +89 -695
- package/dist/logger.js +46 -5
- package/dist/markdown.js +107 -0
- package/dist/markdown.test.js +31 -1
- package/dist/message-formatting.js +113 -28
- package/dist/message-formatting.test.js +73 -0
- package/dist/opencode.js +73 -16
- package/dist/session-handler.js +176 -63
- package/dist/system-message.js +7 -38
- package/dist/tools.js +3 -0
- package/dist/utils.js +3 -0
- package/dist/voice-handler.js +21 -8
- package/dist/voice.js +31 -12
- package/dist/worker-types.js +3 -0
- package/dist/xml.js +3 -0
- package/package.json +3 -3
- package/src/__snapshots__/compact-session-context-no-system.md +35 -0
- package/src/__snapshots__/compact-session-context.md +47 -0
- package/src/ai-tool-to-genai.ts +4 -0
- package/src/channel-management.ts +24 -8
- package/src/cli.ts +163 -18
- package/src/commands/abort.ts +94 -0
- package/src/commands/add-project.ts +139 -0
- package/src/commands/agent.ts +201 -0
- package/src/commands/ask-question.ts +276 -0
- package/src/commands/create-new-project.ts +111 -0
- package/src/{fork.ts → commands/fork.ts} +40 -7
- package/src/{model-command.ts → commands/model.ts} +31 -9
- package/src/commands/permissions.ts +146 -0
- package/src/commands/queue.ts +181 -0
- package/src/commands/resume.ts +230 -0
- package/src/commands/session.ts +184 -0
- package/src/commands/share.ts +96 -0
- package/src/commands/types.ts +25 -0
- package/src/commands/undo-redo.ts +213 -0
- package/src/commands/user-command.ts +178 -0
- package/src/database.ts +65 -0
- package/src/discord-bot.ts +40 -33
- package/src/discord-utils.ts +88 -14
- package/src/format-tables.ts +4 -0
- package/src/genai-worker-wrapper.ts +4 -0
- package/src/genai-worker.ts +4 -0
- package/src/genai.ts +4 -0
- package/src/interaction-handler.ts +111 -924
- package/src/logger.ts +51 -10
- package/src/markdown.test.ts +45 -1
- package/src/markdown.ts +136 -0
- package/src/message-formatting.test.ts +81 -0
- package/src/message-formatting.ts +143 -30
- package/src/opencode.ts +84 -21
- package/src/session-handler.ts +248 -91
- package/src/system-message.ts +8 -38
- package/src/tools.ts +4 -0
- package/src/utils.ts +4 -0
- package/src/voice-handler.ts +24 -9
- package/src/voice.ts +36 -13
- package/src/worker-types.ts +4 -0
- package/src/xml.ts +4 -0
- package/README.md +0 -48
package/src/discord-utils.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Discord-specific utility functions.
|
|
2
|
+
// Handles markdown splitting for Discord's 2000-char limit, code block escaping,
|
|
3
|
+
// thread message sending, and channel metadata extraction from topic tags.
|
|
4
|
+
|
|
1
5
|
import {
|
|
2
6
|
ChannelType,
|
|
3
7
|
type Message,
|
|
@@ -12,6 +16,8 @@ import { createLogger } from './logger.js'
|
|
|
12
16
|
const discordLogger = createLogger('DISCORD')
|
|
13
17
|
|
|
14
18
|
export const SILENT_MESSAGE_FLAGS = 4 | 4096
|
|
19
|
+
// Same as SILENT but without SuppressNotifications - triggers badge/notification
|
|
20
|
+
export const NOTIFY_MESSAGE_FLAGS = 4
|
|
15
21
|
|
|
16
22
|
export function escapeBackticksInCodeBlocks(markdown: string): string {
|
|
17
23
|
const lexer = new Lexer()
|
|
@@ -79,31 +85,93 @@ export function splitMarkdownForDiscord({
|
|
|
79
85
|
let currentChunk = ''
|
|
80
86
|
let currentLang: string | null = null
|
|
81
87
|
|
|
88
|
+
// helper to split a long line into smaller pieces at word boundaries or hard breaks
|
|
89
|
+
const splitLongLine = (text: string, available: number, inCode: boolean): string[] => {
|
|
90
|
+
const pieces: string[] = []
|
|
91
|
+
let remaining = text
|
|
92
|
+
|
|
93
|
+
while (remaining.length > available) {
|
|
94
|
+
let splitAt = available
|
|
95
|
+
// for non-code, try to split at word boundary
|
|
96
|
+
if (!inCode) {
|
|
97
|
+
const lastSpace = remaining.lastIndexOf(' ', available)
|
|
98
|
+
if (lastSpace > available * 0.5) {
|
|
99
|
+
splitAt = lastSpace + 1
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
pieces.push(remaining.slice(0, splitAt))
|
|
103
|
+
remaining = remaining.slice(splitAt)
|
|
104
|
+
}
|
|
105
|
+
if (remaining) {
|
|
106
|
+
pieces.push(remaining)
|
|
107
|
+
}
|
|
108
|
+
return pieces
|
|
109
|
+
}
|
|
110
|
+
|
|
82
111
|
for (const line of lines) {
|
|
83
112
|
const wouldExceed = currentChunk.length + line.text.length > maxLength
|
|
84
113
|
|
|
85
|
-
if (wouldExceed
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
114
|
+
if (wouldExceed) {
|
|
115
|
+
// handle case where single line is longer than maxLength
|
|
116
|
+
if (line.text.length > maxLength) {
|
|
117
|
+
// first, flush current chunk if any
|
|
118
|
+
if (currentChunk) {
|
|
119
|
+
if (currentLang !== null) {
|
|
120
|
+
currentChunk += '```\n'
|
|
121
|
+
}
|
|
122
|
+
chunks.push(currentChunk)
|
|
123
|
+
currentChunk = ''
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// calculate overhead for code block markers
|
|
127
|
+
const codeBlockOverhead = line.inCodeBlock ? ('```' + line.lang + '\n').length + '```\n'.length : 0
|
|
128
|
+
const availablePerChunk = maxLength - codeBlockOverhead - 50 // safety margin
|
|
129
|
+
|
|
130
|
+
const pieces = splitLongLine(line.text, availablePerChunk, line.inCodeBlock)
|
|
131
|
+
|
|
132
|
+
for (let i = 0; i < pieces.length; i++) {
|
|
133
|
+
const piece = pieces[i]!
|
|
134
|
+
if (line.inCodeBlock) {
|
|
135
|
+
chunks.push('```' + line.lang + '\n' + piece + '```\n')
|
|
136
|
+
} else {
|
|
137
|
+
chunks.push(piece)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
90
140
|
|
|
91
|
-
if (line.isClosingFence && currentLang !== null) {
|
|
92
|
-
currentChunk = ''
|
|
93
141
|
currentLang = null
|
|
94
142
|
continue
|
|
95
143
|
}
|
|
96
144
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
145
|
+
// normal case: line fits in a chunk but current chunk would overflow
|
|
146
|
+
if (currentChunk) {
|
|
147
|
+
if (currentLang !== null) {
|
|
148
|
+
currentChunk += '```\n'
|
|
149
|
+
}
|
|
150
|
+
chunks.push(currentChunk)
|
|
151
|
+
|
|
152
|
+
if (line.isClosingFence && currentLang !== null) {
|
|
153
|
+
currentChunk = ''
|
|
154
|
+
currentLang = null
|
|
155
|
+
continue
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (line.inCodeBlock || line.isOpeningFence) {
|
|
159
|
+
const lang = line.lang
|
|
160
|
+
currentChunk = '```' + lang + '\n'
|
|
161
|
+
if (!line.isOpeningFence) {
|
|
162
|
+
currentChunk += line.text
|
|
163
|
+
}
|
|
164
|
+
currentLang = lang
|
|
165
|
+
} else {
|
|
166
|
+
currentChunk = line.text
|
|
167
|
+
currentLang = null
|
|
102
168
|
}
|
|
103
|
-
currentLang = lang
|
|
104
169
|
} else {
|
|
170
|
+
// currentChunk is empty but line still exceeds - shouldn't happen after above check
|
|
105
171
|
currentChunk = line.text
|
|
106
|
-
|
|
172
|
+
if (line.inCodeBlock || line.isOpeningFence) {
|
|
173
|
+
currentLang = line.lang
|
|
174
|
+
}
|
|
107
175
|
}
|
|
108
176
|
} else {
|
|
109
177
|
currentChunk += line.text
|
|
@@ -125,12 +193,18 @@ export function splitMarkdownForDiscord({
|
|
|
125
193
|
export async function sendThreadMessage(
|
|
126
194
|
thread: ThreadChannel,
|
|
127
195
|
content: string,
|
|
196
|
+
options?: { flags?: number }
|
|
128
197
|
): Promise<Message> {
|
|
129
198
|
const MAX_LENGTH = 2000
|
|
130
199
|
|
|
131
200
|
content = formatMarkdownTables(content)
|
|
132
201
|
content = escapeBackticksInCodeBlocks(content)
|
|
133
202
|
|
|
203
|
+
// If custom flags provided, send as single message (no chunking)
|
|
204
|
+
if (options?.flags !== undefined) {
|
|
205
|
+
return thread.send({ content, flags: options.flags })
|
|
206
|
+
}
|
|
207
|
+
|
|
134
208
|
const chunks = splitMarkdownForDiscord({ content, maxLength: MAX_LENGTH })
|
|
135
209
|
|
|
136
210
|
if (chunks.length > 1) {
|
package/src/format-tables.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Markdown table to code block converter.
|
|
2
|
+
// Discord doesn't render GFM tables, so this converts them to
|
|
3
|
+
// space-aligned code blocks for proper monospace display.
|
|
4
|
+
|
|
1
5
|
import { Lexer, type Token, type Tokens } from 'marked'
|
|
2
6
|
|
|
3
7
|
export function formatMarkdownTables(markdown: string): string {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Main thread interface for the GenAI worker.
|
|
2
|
+
// Spawns and manages the worker thread, handling message passing for
|
|
3
|
+
// audio input/output, tool call completions, and graceful shutdown.
|
|
4
|
+
|
|
1
5
|
import { Worker } from 'node:worker_threads'
|
|
2
6
|
import type { WorkerInMessage, WorkerOutMessage } from './worker-types.js'
|
|
3
7
|
import type { Tool as AITool } from 'ai'
|
package/src/genai-worker.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Worker thread for GenAI voice processing.
|
|
2
|
+
// Runs in a separate thread to handle audio encoding/decoding without blocking.
|
|
3
|
+
// Resamples 24kHz GenAI output to 48kHz stereo Opus packets for Discord.
|
|
4
|
+
|
|
1
5
|
import { parentPort, threadId } from 'node:worker_threads'
|
|
2
6
|
import { createWriteStream, type WriteStream } from 'node:fs'
|
|
3
7
|
import { mkdir } from 'node:fs/promises'
|
package/src/genai.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Google GenAI Live session manager for real-time voice interactions.
|
|
2
|
+
// Establishes bidirectional audio streaming with Gemini, handles tool calls,
|
|
3
|
+
// and manages the assistant's audio output for Discord voice channels.
|
|
4
|
+
|
|
1
5
|
import {
|
|
2
6
|
GoogleGenAI,
|
|
3
7
|
LiveServerMessage,
|