kimaki 0.15.0 → 0.16.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/cli-commands/send.js +1 -0
- package/dist/cli-runner.js +29 -3
- package/dist/system-message.js +1 -1
- package/dist/system-message.test.js +1 -1
- package/package.json +5 -5
- package/src/cli-commands/send.ts +1 -0
- package/src/cli-runner.ts +32 -2
- package/src/system-message.test.ts +1 -1
- package/src/system-message.ts +1 -1
|
@@ -457,6 +457,7 @@ cli
|
|
|
457
457
|
botToken,
|
|
458
458
|
embeds: autoStartEmbed,
|
|
459
459
|
rest,
|
|
460
|
+
splitInsteadOfAttach: notifyOnly,
|
|
460
461
|
});
|
|
461
462
|
// For notify-only on non-project channels, just post the message without
|
|
462
463
|
// creating a thread. There's no session to start, so a thread is unnecessary.
|
package/dist/cli-runner.js
CHANGED
|
@@ -107,7 +107,7 @@ export function isThreadChannelType(type) {
|
|
|
107
107
|
ChannelType.AnnouncementThread,
|
|
108
108
|
].includes(type);
|
|
109
109
|
}
|
|
110
|
-
export async function sendDiscordMessageWithOptionalAttachment({ channelId, prompt, botToken, embeds, rest, }) {
|
|
110
|
+
export async function sendDiscordMessageWithOptionalAttachment({ channelId, prompt, botToken, embeds, rest, splitInsteadOfAttach, }) {
|
|
111
111
|
const discordMaxLength = 2000;
|
|
112
112
|
if (prompt.length <= discordMaxLength) {
|
|
113
113
|
return (await rest.post(Routes.channelMessages(channelId), {
|
|
@@ -118,6 +118,33 @@ export async function sendDiscordMessageWithOptionalAttachment({ channelId, prom
|
|
|
118
118
|
},
|
|
119
119
|
}));
|
|
120
120
|
}
|
|
121
|
+
if (splitInsteadOfAttach) {
|
|
122
|
+
const { splitMarkdownForDiscord } = await import('./discord-utils.js');
|
|
123
|
+
const chunks = splitMarkdownForDiscord({
|
|
124
|
+
content: prompt,
|
|
125
|
+
maxLength: discordMaxLength,
|
|
126
|
+
});
|
|
127
|
+
let firstMessage;
|
|
128
|
+
for (let chunk of chunks) {
|
|
129
|
+
if (!chunk?.trim())
|
|
130
|
+
continue;
|
|
131
|
+
// Safety net: hard-truncate if splitting still produced an oversized chunk
|
|
132
|
+
if (chunk.length > discordMaxLength) {
|
|
133
|
+
chunk = chunk.slice(0, discordMaxLength - 4) + '...';
|
|
134
|
+
}
|
|
135
|
+
const message = (await rest.post(Routes.channelMessages(channelId), {
|
|
136
|
+
body: {
|
|
137
|
+
content: chunk,
|
|
138
|
+
// Only attach embeds to the first message
|
|
139
|
+
...(firstMessage ? {} : { embeds }),
|
|
140
|
+
allowed_mentions: { parse: store.getState().allowedMentions },
|
|
141
|
+
},
|
|
142
|
+
}));
|
|
143
|
+
if (!firstMessage)
|
|
144
|
+
firstMessage = message;
|
|
145
|
+
}
|
|
146
|
+
return firstMessage;
|
|
147
|
+
}
|
|
121
148
|
const preview = prompt.slice(0, 100).replace(/\n/g, ' ');
|
|
122
149
|
const summaryContent = `Prompt attached as file (${prompt.length} chars)\n\n> ${preview}...`;
|
|
123
150
|
const tmpDir = path.join(process.cwd(), 'tmp');
|
|
@@ -759,8 +786,7 @@ export async function resolveCredentials({ forceRestartOnboarding, forceGateway,
|
|
|
759
786
|
options: [
|
|
760
787
|
{
|
|
761
788
|
value: 'gateway',
|
|
762
|
-
|
|
763
|
-
label: 'Gateway (pre-built Kimaki bot, currently disabled because of Discord verification process. will be re-enabled soon)',
|
|
789
|
+
label: 'Gateway (pre-built Kimaki bot, no setup needed)',
|
|
764
790
|
},
|
|
765
791
|
{
|
|
766
792
|
value: 'self_hosted',
|
package/dist/system-message.js
CHANGED
|
@@ -535,7 +535,7 @@ When you are approaching the **context window limit** or the user explicitly ask
|
|
|
535
535
|
kimaki send --channel ${channelId} --prompt 'Continuing from previous session: <summary of current task and state>' --agent <current_agent>${userArg}
|
|
536
536
|
\`\`\`
|
|
537
537
|
|
|
538
|
-
The command automatically handles long prompts (over 2000 chars) by sending them as file attachments.
|
|
538
|
+
The command automatically handles long prompts (over 2000 chars) by sending them as file attachments. With \`--notify-only\`, long prompts are split into multiple messages instead so the content is directly visible.
|
|
539
539
|
|
|
540
540
|
Use this for handoff when:
|
|
541
541
|
- User asks to "handoff", "continue in new thread", or "start fresh session"
|
|
@@ -296,7 +296,7 @@ describe('system-message', () => {
|
|
|
296
296
|
kimaki send --channel chan_123 --prompt 'Continuing from previous session: <summary of current task and state>' --agent <current_agent> --user '<discord-user-id>'
|
|
297
297
|
\`\`\`
|
|
298
298
|
|
|
299
|
-
The command automatically handles long prompts (over 2000 chars) by sending them as file attachments.
|
|
299
|
+
The command automatically handles long prompts (over 2000 chars) by sending them as file attachments. With \`--notify-only\`, long prompts are split into multiple messages instead so the content is directly visible.
|
|
300
300
|
|
|
301
301
|
Use this for handoff when:
|
|
302
302
|
- User asks to "handoff", "continue in new thread", or "start fresh session"
|
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.16.0",
|
|
6
6
|
"repository": "https://github.com/remorses/kimaki",
|
|
7
7
|
"bin": "bin.js",
|
|
8
8
|
"files": [
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"tsx": "^4.20.5",
|
|
26
26
|
"undici": "^8.0.2",
|
|
27
27
|
"discord-digital-twin": "^0.1.0",
|
|
28
|
-
"opencode-deterministic-provider": "^0.0.1",
|
|
29
28
|
"opencode-cached-provider": "^0.0.1",
|
|
29
|
+
"opencode-deterministic-provider": "^0.0.1",
|
|
30
30
|
"db": "^0.0.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
@@ -62,10 +62,10 @@
|
|
|
62
62
|
"yaml": "^2.8.3",
|
|
63
63
|
"zod": "^4.3.6",
|
|
64
64
|
"zustand": "^5.0.11",
|
|
65
|
-
"traforo": "^0.7.0",
|
|
66
65
|
"errore": "^0.14.1",
|
|
67
|
-
"
|
|
68
|
-
"
|
|
66
|
+
"opencode-injection-guard": "^0.2.1",
|
|
67
|
+
"traforo": "^0.7.0",
|
|
68
|
+
"libsqlproxy": "^0.1.0"
|
|
69
69
|
},
|
|
70
70
|
"optionalDependencies": {
|
|
71
71
|
"@snazzah/davey": "^0.1.10",
|
package/src/cli-commands/send.ts
CHANGED
package/src/cli-runner.ts
CHANGED
|
@@ -172,12 +172,17 @@ export async function sendDiscordMessageWithOptionalAttachment({
|
|
|
172
172
|
botToken,
|
|
173
173
|
embeds,
|
|
174
174
|
rest,
|
|
175
|
+
splitInsteadOfAttach,
|
|
175
176
|
}: {
|
|
176
177
|
channelId: string
|
|
177
178
|
prompt: string
|
|
178
179
|
botToken: string
|
|
179
180
|
embeds?: Array<{ color: number; footer: { text: string } }>
|
|
180
181
|
rest: REST
|
|
182
|
+
/** When true, long messages are split into multiple Discord messages instead of
|
|
183
|
+
* being attached as a file. Useful for notify-only messages where the content
|
|
184
|
+
* should be directly visible in the channel. */
|
|
185
|
+
splitInsteadOfAttach?: boolean
|
|
181
186
|
}): Promise<{ id: string }> {
|
|
182
187
|
const discordMaxLength = 2000
|
|
183
188
|
if (prompt.length <= discordMaxLength) {
|
|
@@ -190,6 +195,32 @@ export async function sendDiscordMessageWithOptionalAttachment({
|
|
|
190
195
|
})) as { id: string }
|
|
191
196
|
}
|
|
192
197
|
|
|
198
|
+
if (splitInsteadOfAttach) {
|
|
199
|
+
const { splitMarkdownForDiscord } = await import('./discord-utils.js')
|
|
200
|
+
const chunks = splitMarkdownForDiscord({
|
|
201
|
+
content: prompt,
|
|
202
|
+
maxLength: discordMaxLength,
|
|
203
|
+
})
|
|
204
|
+
let firstMessage: { id: string } | undefined
|
|
205
|
+
for (let chunk of chunks) {
|
|
206
|
+
if (!chunk?.trim()) continue
|
|
207
|
+
// Safety net: hard-truncate if splitting still produced an oversized chunk
|
|
208
|
+
if (chunk.length > discordMaxLength) {
|
|
209
|
+
chunk = chunk.slice(0, discordMaxLength - 4) + '...'
|
|
210
|
+
}
|
|
211
|
+
const message = (await rest.post(Routes.channelMessages(channelId), {
|
|
212
|
+
body: {
|
|
213
|
+
content: chunk,
|
|
214
|
+
// Only attach embeds to the first message
|
|
215
|
+
...(firstMessage ? {} : { embeds }),
|
|
216
|
+
allowed_mentions: { parse: store.getState().allowedMentions },
|
|
217
|
+
},
|
|
218
|
+
})) as { id: string }
|
|
219
|
+
if (!firstMessage) firstMessage = message
|
|
220
|
+
}
|
|
221
|
+
return firstMessage!
|
|
222
|
+
}
|
|
223
|
+
|
|
193
224
|
const preview = prompt.slice(0, 100).replace(/\n/g, ' ')
|
|
194
225
|
const summaryContent = `Prompt attached as file (${prompt.length} chars)\n\n> ${preview}...`
|
|
195
226
|
|
|
@@ -1109,8 +1140,7 @@ export async function resolveCredentials({
|
|
|
1109
1140
|
options: [
|
|
1110
1141
|
{
|
|
1111
1142
|
value: 'gateway' as const,
|
|
1112
|
-
|
|
1113
|
-
label: 'Gateway (pre-built Kimaki bot, currently disabled because of Discord verification process. will be re-enabled soon)',
|
|
1143
|
+
label: 'Gateway (pre-built Kimaki bot, no setup needed)',
|
|
1114
1144
|
},
|
|
1115
1145
|
{
|
|
1116
1146
|
value: 'self_hosted' as const,
|
|
@@ -306,7 +306,7 @@ describe('system-message', () => {
|
|
|
306
306
|
kimaki send --channel chan_123 --prompt 'Continuing from previous session: <summary of current task and state>' --agent <current_agent> --user '<discord-user-id>'
|
|
307
307
|
\`\`\`
|
|
308
308
|
|
|
309
|
-
The command automatically handles long prompts (over 2000 chars) by sending them as file attachments.
|
|
309
|
+
The command automatically handles long prompts (over 2000 chars) by sending them as file attachments. With \`--notify-only\`, long prompts are split into multiple messages instead so the content is directly visible.
|
|
310
310
|
|
|
311
311
|
Use this for handoff when:
|
|
312
312
|
- User asks to "handoff", "continue in new thread", or "start fresh session"
|
package/src/system-message.ts
CHANGED
|
@@ -649,7 +649,7 @@ When you are approaching the **context window limit** or the user explicitly ask
|
|
|
649
649
|
kimaki send --channel ${channelId} --prompt 'Continuing from previous session: <summary of current task and state>' --agent <current_agent>${userArg}
|
|
650
650
|
\`\`\`
|
|
651
651
|
|
|
652
|
-
The command automatically handles long prompts (over 2000 chars) by sending them as file attachments.
|
|
652
|
+
The command automatically handles long prompts (over 2000 chars) by sending them as file attachments. With \`--notify-only\`, long prompts are split into multiple messages instead so the content is directly visible.
|
|
653
653
|
|
|
654
654
|
Use this for handoff when:
|
|
655
655
|
- User asks to "handoff", "continue in new thread", or "start fresh session"
|