kimaki 0.26.0 → 0.28.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/agent-model.e2e.test.js +250 -164
- package/dist/anthropic-account-identity.js +9 -1
- package/dist/anthropic-auth-plugin.js +10 -13
- package/dist/anthropic-auth-plugin.test.js +17 -0
- package/dist/anthropic-auth-state.js +1 -0
- package/dist/bash-tool-schema-plugin.js +32 -0
- package/dist/bash-tool-schema-plugin.test.js +49 -0
- package/dist/bin.js +73 -19
- package/dist/cli-commands/maintenance.js +46 -7
- package/dist/cli-commands/project.js +11 -27
- package/dist/cli-commands/send.js +30 -1
- package/dist/cli-commands/session.js +322 -90
- package/dist/cli-commands/task.js +34 -15
- package/dist/cli-parsing.test.js +83 -4
- package/dist/cli-runner.js +44 -8
- package/dist/cli-runner.test.js +27 -0
- package/dist/cli-send-thread.e2e.test.js +9 -9
- package/dist/cli.js +32 -0
- package/dist/commands/abort.js +5 -1
- package/dist/commands/action-buttons.js +2 -1
- package/dist/commands/add-project.js +4 -7
- package/dist/commands/agent.js +164 -32
- package/dist/commands/ask-question.js +23 -33
- package/dist/commands/ask-question.test.js +43 -1
- package/dist/commands/btw.js +28 -6
- package/dist/commands/file-upload.js +2 -1
- package/dist/commands/fork-subagent.js +2 -4
- package/dist/commands/fork.js +4 -4
- package/dist/commands/last-sessions.js +17 -10
- package/dist/commands/login.js +6 -0
- package/dist/commands/merge-worktree.js +47 -14
- package/dist/commands/model-variant.js +8 -1
- package/dist/commands/model.js +16 -9
- package/dist/commands/multioauth.js +1 -0
- package/dist/commands/new-worktree.js +170 -102
- package/dist/commands/queue.js +3 -2
- package/dist/commands/resume.js +4 -4
- package/dist/commands/session.js +78 -63
- package/dist/commands/user-command.js +6 -8
- package/dist/commands/worktrees.js +5 -13
- package/dist/config.js +16 -1
- package/dist/cpu-profiler.js +211 -0
- package/dist/cpu-profiler.test.js +160 -0
- package/dist/database.js +152 -3
- package/dist/db.js +33 -0
- package/dist/db.test.js +267 -1
- package/dist/default-channel-provisioning.test.js +148 -0
- package/dist/discord-bot.js +517 -488
- package/dist/discord-command-registration.js +25 -10
- package/dist/discord-command-registration.test.js +17 -0
- package/dist/discord-utils.js +97 -5
- package/dist/discord-utils.test.js +151 -1
- package/dist/errors.js +10 -0
- package/dist/exec-async.js +17 -5
- package/dist/external-directory-permissions.e2e.test.js +11 -7
- package/dist/external-directory-project-deny.e2e.test.js +5 -3
- package/dist/external-opencode-sync.js +94 -17
- package/dist/external-opencode-sync.test.js +206 -0
- package/dist/extract-sdk-error-message.test.js +13 -0
- package/dist/file-edit-log.js +197 -0
- package/dist/file-edit-log.test.js +258 -0
- package/dist/format-tables.js +52 -0
- package/dist/format-tables.test.js +93 -0
- package/dist/gateway-proxy-reconnect.e2e.test.js +28 -8
- package/dist/gateway-proxy.e2e.test.js +18 -18
- package/dist/git-worktree-core.js +182 -17
- package/dist/interaction-handler.js +416 -398
- package/dist/ipc-tools-plugin.js +68 -3
- package/dist/kimaki-opencode-plugin-loading.e2e.test.js +122 -58
- package/dist/kimaki-opencode-plugin.js +9 -3
- package/dist/kimaki-workspace-adaptor.js +33 -10
- package/dist/logger.js +11 -1
- package/dist/markdown.js +3 -1
- package/dist/markdown.test.js +11 -3
- package/dist/message-formatting.js +181 -51
- package/dist/message-formatting.test.js +529 -22
- package/dist/message-preprocessing.js +105 -1
- package/dist/oauth-rotation-shared.js +10 -0
- package/dist/openai-auth-plugin.js +1 -0
- package/dist/openai-auth-state.js +1 -0
- package/dist/opencode-command.js +28 -0
- package/dist/opencode-command.test.js +109 -1
- package/dist/opencode-interrupt-plugin.js +4 -0
- package/dist/opencode-interrupt-plugin.test.js +24 -0
- package/dist/opencode.js +82 -15
- package/dist/project-add.test.js +62 -0
- package/dist/question-abort-clears-dropdown.e2e.test.js +89 -0
- package/dist/question-abort-retry-text-before-dropdown.e2e.test.js +150 -0
- package/dist/question-text-before-dropdown.e2e.test.js +52 -0
- package/dist/queue-advanced-abort.e2e.test.js +8 -10
- package/dist/queue-advanced-action-buttons.e2e.test.js +8 -8
- package/dist/queue-advanced-e2e-setup.js +78 -5
- package/dist/queue-advanced-footer.e2e.test.js +60 -269
- package/dist/queue-advanced-model-switch.e2e.test.js +9 -11
- package/dist/queue-advanced-permissions-typing.e2e.test.js +15 -15
- package/dist/queue-advanced-question.e2e.test.js +32 -27
- package/dist/queue-advanced-typing-interrupt.e2e.test.js +10 -12
- package/dist/queue-advanced-typing.e2e.test.js +7 -9
- package/dist/queue-delete-message.e2e.test.js +3 -3
- package/dist/queue-drain-after-interactive-ui.e2e.test.js +5 -5
- package/dist/queue-interrupt-drain.e2e.test.js +122 -12
- package/dist/queue-question-select-drain.e2e.test.js +34 -132
- package/dist/runtime-lifecycle.e2e.test.js +21 -51
- package/dist/schema.js +35 -1
- package/dist/session-handler/event-stream-state.js +391 -50
- package/dist/session-handler/event-stream-state.test.js +736 -8
- package/dist/session-handler/model-utils.js +172 -5
- package/dist/session-handler/model-utils.test.js +445 -0
- package/dist/session-handler/opencode-session-event-log.js +30 -1
- package/dist/session-handler/thread-ingress.test.js +41 -0
- package/dist/session-handler/thread-runtime-state.js +2 -0
- package/dist/session-handler/thread-session-runtime-summary.test.js +121 -0
- package/dist/session-handler/thread-session-runtime.js +574 -299
- package/dist/session-search.js +123 -4
- package/dist/session-search.test.js +248 -1
- package/dist/session-sleep.test.js +224 -0
- package/dist/session-title-rename.test.js +37 -39
- package/dist/sleep.e2e.test.js +494 -0
- package/dist/startup-time.e2e.test.js +2 -1
- package/dist/store.js +3 -0
- package/dist/system-message.js +102 -16
- package/dist/system-message.test.js +192 -15
- package/dist/task-runner.js +96 -5
- package/dist/task-schedule.js +87 -1
- package/dist/task-schedule.test.js +149 -1
- package/dist/test-utils.js +17 -9
- package/dist/thinking-utils.js +10 -0
- package/dist/thinking-utils.test.js +35 -0
- package/dist/thread-message-queue.e2e.test.js +65 -213
- package/dist/undo-redo.e2e.test.js +17 -9
- package/dist/voice-attachment.js +23 -1
- package/dist/voice-handler.js +21 -4
- package/dist/voice-message.e2e.test.js +144 -30
- package/dist/voice-routing-input.e2e.test.js +195 -0
- package/dist/voice-routing-question.e2e.test.js +125 -0
- package/dist/voice.js +28 -8
- package/dist/voice.test.js +96 -30
- package/dist/worktree-clone-isolation.e2e.test.js +188 -0
- package/dist/worktree-lifecycle.e2e.test.js +55 -36
- package/dist/worktrees.js +226 -443
- package/dist/worktrees.test.js +435 -58
- package/dist/xai-auth-plugin.js +1 -0
- package/dist/xai-auth-state.js +1 -0
- package/package.json +8 -6
- package/skills/bump-holocron-consumers/SKILL.md +137 -0
- package/skills/critique/SKILL.md +4 -4
- package/skills/errore/SKILL.md +60 -218
- package/skills/goke/SKILL.md +150 -10
- package/skills/holocron/SKILL.md +154 -17
- package/skills/npm-package/SKILL.md +55 -35
- package/skills/profano/SKILL.md +17 -2
- package/skills/spiceflow/SKILL.md +39 -3
- package/skills/strada/SKILL.md +39 -0
- package/skills/zele/SKILL.md +19 -0
- package/src/agent-model.e2e.test.ts +287 -186
- package/src/anthropic-account-identity.ts +20 -1
- package/src/anthropic-auth-plugin.test.ts +19 -0
- package/src/anthropic-auth-plugin.ts +12 -16
- package/src/anthropic-auth-state.ts +1 -0
- package/src/bash-tool-schema-plugin.test.ts +55 -0
- package/src/bash-tool-schema-plugin.ts +46 -0
- package/src/bin.ts +78 -26
- package/src/cli-commands/maintenance.ts +59 -13
- package/src/cli-commands/project.ts +14 -35
- package/src/cli-commands/send.ts +31 -1
- package/src/cli-commands/session.ts +374 -114
- package/src/cli-commands/task.ts +34 -15
- package/src/cli-parsing.test.ts +103 -4
- package/src/cli-runner.test.ts +49 -0
- package/src/cli-runner.ts +44 -7
- package/src/cli-send-thread.e2e.test.ts +9 -11
- package/src/cli.ts +53 -0
- package/src/commands/abort.ts +6 -1
- package/src/commands/action-buttons.ts +2 -1
- package/src/commands/add-project.ts +4 -8
- package/src/commands/agent.ts +205 -29
- package/src/commands/ask-question.test.ts +48 -1
- package/src/commands/ask-question.ts +23 -33
- package/src/commands/btw.ts +40 -5
- package/src/commands/file-upload.ts +2 -1
- package/src/commands/fork-subagent.ts +2 -3
- package/src/commands/fork.ts +4 -3
- package/src/commands/last-sessions.ts +10 -4
- package/src/commands/login.ts +6 -0
- package/src/commands/merge-worktree.ts +54 -16
- package/src/commands/model-variant.ts +9 -1
- package/src/commands/model.ts +20 -9
- package/src/commands/multioauth.ts +1 -0
- package/src/commands/new-worktree.ts +138 -55
- package/src/commands/queue.ts +3 -2
- package/src/commands/resume.ts +4 -3
- package/src/commands/session.ts +94 -70
- package/src/commands/user-command.ts +6 -6
- package/src/commands/worktrees.ts +5 -12
- package/src/config.ts +18 -1
- package/src/cpu-profiler.test.ts +183 -0
- package/src/cpu-profiler.ts +293 -0
- package/src/database.ts +235 -3
- package/src/db.test.ts +293 -0
- package/src/db.ts +38 -0
- package/src/default-channel-provisioning.test.ts +155 -0
- package/src/discord-bot.ts +78 -36
- package/src/discord-command-registration.test.ts +20 -0
- package/src/discord-command-registration.ts +42 -12
- package/src/discord-utils.test.ts +176 -0
- package/src/discord-utils.ts +152 -7
- package/src/errors.ts +12 -0
- package/src/exec-async.ts +20 -11
- package/src/external-directory-permissions.e2e.test.ts +11 -7
- package/src/external-directory-project-deny.e2e.test.ts +5 -3
- package/src/external-opencode-sync.test.ts +248 -0
- package/src/external-opencode-sync.ts +122 -19
- package/src/extract-sdk-error-message.test.ts +18 -0
- package/src/file-edit-log.test.ts +287 -0
- package/src/file-edit-log.ts +283 -0
- package/src/format-tables.test.ts +101 -0
- package/src/format-tables.ts +75 -0
- package/src/gateway-proxy-reconnect.e2e.test.ts +38 -8
- package/src/gateway-proxy.e2e.test.ts +18 -17
- package/src/git-worktree-core.ts +247 -20
- package/src/interaction-handler.ts +36 -13
- package/src/ipc-tools-plugin.ts +82 -5
- package/src/kimaki-opencode-plugin-loading.e2e.test.ts +188 -97
- package/src/kimaki-opencode-plugin.ts +9 -3
- package/src/kimaki-workspace-adaptor.ts +40 -11
- package/src/logger.ts +14 -4
- package/src/markdown.test.ts +13 -3
- package/src/markdown.ts +4 -1
- package/src/message-formatting.test.ts +672 -25
- package/src/message-formatting.ts +242 -53
- package/src/message-preprocessing.ts +116 -1
- package/src/oauth-rotation-shared.ts +10 -0
- package/src/openai-auth-plugin.ts +1 -0
- package/src/openai-auth-state.ts +1 -0
- package/src/opencode-command.test.ts +140 -0
- package/src/opencode-command.ts +38 -0
- package/src/opencode-interrupt-plugin.test.ts +32 -0
- package/src/opencode-interrupt-plugin.ts +3 -0
- package/src/opencode.ts +115 -15
- package/src/project-add.test.ts +80 -0
- package/src/question-abort-clears-dropdown.e2e.test.ts +109 -0
- package/src/question-abort-retry-text-before-dropdown.e2e.test.ts +172 -0
- package/src/question-text-before-dropdown.e2e.test.ts +67 -0
- package/src/queue-advanced-abort.e2e.test.ts +8 -9
- package/src/queue-advanced-action-buttons.e2e.test.ts +8 -8
- package/src/queue-advanced-e2e-setup.ts +83 -4
- package/src/queue-advanced-footer.e2e.test.ts +67 -315
- package/src/queue-advanced-model-switch.e2e.test.ts +9 -10
- package/src/queue-advanced-permissions-typing.e2e.test.ts +15 -15
- package/src/queue-advanced-question.e2e.test.ts +36 -30
- package/src/queue-advanced-typing-interrupt.e2e.test.ts +11 -11
- package/src/queue-advanced-typing.e2e.test.ts +8 -8
- package/src/queue-delete-message.e2e.test.ts +3 -3
- package/src/queue-drain-after-interactive-ui.e2e.test.ts +5 -5
- package/src/queue-interrupt-drain.e2e.test.ts +133 -12
- package/src/queue-question-select-drain.e2e.test.ts +36 -161
- package/src/runtime-lifecycle.e2e.test.ts +21 -54
- package/src/schema.sql +15 -2
- package/src/schema.ts +37 -1
- package/src/session-handler/event-stream-state.test.ts +790 -7
- package/src/session-handler/event-stream-state.ts +568 -53
- package/src/session-handler/model-utils.test.ts +537 -0
- package/src/session-handler/model-utils.ts +281 -5
- package/src/session-handler/opencode-session-event-log.ts +31 -1
- package/src/session-handler/thread-ingress.test.ts +54 -0
- package/src/session-handler/thread-runtime-state.ts +3 -0
- package/src/session-handler/thread-session-runtime-summary.test.ts +169 -0
- package/src/session-handler/thread-session-runtime.ts +712 -358
- package/src/session-search.test.ts +281 -0
- package/src/session-search.ts +241 -7
- package/src/session-sleep.test.ts +294 -0
- package/src/session-title-rename.test.ts +54 -48
- package/src/sleep.e2e.test.ts +565 -0
- package/src/startup-time.e2e.test.ts +5 -1
- package/src/store.ts +22 -0
- package/src/system-message.test.ts +226 -15
- package/src/system-message.ts +130 -16
- package/src/task-runner.ts +138 -3
- package/src/task-schedule.test.ts +170 -0
- package/src/task-schedule.ts +141 -1
- package/src/test-utils.ts +21 -10
- package/src/thinking-utils.test.ts +46 -0
- package/src/thinking-utils.ts +21 -0
- package/src/thread-message-queue.e2e.test.ts +65 -245
- package/src/undo-redo.e2e.test.ts +17 -9
- package/src/voice-attachment.ts +29 -1
- package/src/voice-handler.ts +23 -4
- package/src/voice-message.e2e.test.ts +149 -29
- package/src/voice-routing-input.e2e.test.ts +203 -0
- package/src/voice-routing-question.e2e.test.ts +131 -0
- package/src/voice.test.ts +107 -29
- package/src/voice.ts +34 -6
- package/src/worktree-clone-isolation.e2e.test.ts +213 -0
- package/src/worktree-lifecycle.e2e.test.ts +55 -35
- package/src/worktrees.test.ts +505 -64
- package/src/worktrees.ts +257 -603
- package/src/xai-auth-plugin.ts +1 -0
- package/src/xai-auth-state.ts +1 -0
- package/dist/message-finish-field.e2e.test.js +0 -169
- package/dist/subagent-rate-limit-plugin.js +0 -184
- package/src/message-finish-field.e2e.test.ts +0 -196
- package/src/subagent-rate-limit-plugin.ts +0 -228
|
@@ -25,6 +25,7 @@ import path from 'node:path'
|
|
|
25
25
|
import { createLogger, LogPrefix } from '../logger.js'
|
|
26
26
|
import { notifyError } from '../sentry.js'
|
|
27
27
|
import { NOTIFY_MESSAGE_FLAGS, sendThreadMessage } from '../discord-utils.js'
|
|
28
|
+
import { QUEUE_PREFIX } from '../message-formatting.js'
|
|
28
29
|
|
|
29
30
|
const logger = createLogger(LogPrefix.FILE_UPLOAD)
|
|
30
31
|
|
|
@@ -325,7 +326,7 @@ export async function handleFileUploadModalSubmit(
|
|
|
325
326
|
const username = interaction.user.globalName || interaction.user.username
|
|
326
327
|
await sendThreadMessage(
|
|
327
328
|
context.thread,
|
|
328
|
-
|
|
329
|
+
`${QUEUE_PREFIX}**${username}:** Uploaded ${fileNames.join(', ')}`,
|
|
329
330
|
)
|
|
330
331
|
}
|
|
331
332
|
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
resolveTextChannel,
|
|
19
19
|
resolveWorkingDirectory,
|
|
20
20
|
sendThreadMessage,
|
|
21
|
+
sendSessionPartBatches,
|
|
21
22
|
} from '../discord-utils.js'
|
|
22
23
|
import {
|
|
23
24
|
collectSessionChunks,
|
|
@@ -240,9 +241,7 @@ export async function handleForkSubagentSelectMenu(
|
|
|
240
241
|
limit: 30,
|
|
241
242
|
})
|
|
242
243
|
const batched = batchChunksForDiscord(chunks)
|
|
243
|
-
|
|
244
|
-
await sendThreadMessage(forkedThread, batch.content)
|
|
245
|
-
}
|
|
244
|
+
await sendSessionPartBatches({ thread: forkedThread, batches: batched })
|
|
246
245
|
}
|
|
247
246
|
} catch (error) {
|
|
248
247
|
forkLogger.error('Error replaying forked subagent history:', error)
|
package/src/commands/fork.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
resolveWorkingDirectory,
|
|
21
21
|
resolveTextChannel,
|
|
22
22
|
sendThreadMessage,
|
|
23
|
+
sendSessionPartBatches,
|
|
23
24
|
} from '../discord-utils.js'
|
|
24
25
|
import {
|
|
25
26
|
collectSessionChunks,
|
|
@@ -356,12 +357,12 @@ export async function handleForkSelectMenu(
|
|
|
356
357
|
limit: 30,
|
|
357
358
|
})
|
|
358
359
|
const batched = batchChunksForDiscord(chunks)
|
|
359
|
-
|
|
360
|
-
|
|
360
|
+
const sent = await sendSessionPartBatches({ thread, batches: batched })
|
|
361
|
+
for (const batch of sent) {
|
|
361
362
|
await setPartMessagesBatch(
|
|
362
363
|
batch.partIds.map((partId) => ({
|
|
363
364
|
partId,
|
|
364
|
-
messageId:
|
|
365
|
+
messageId: batch.message.id,
|
|
365
366
|
threadId: thread.id,
|
|
366
367
|
})),
|
|
367
368
|
)
|
|
@@ -148,8 +148,14 @@ export async function handleLastSessionsCommand({
|
|
|
148
148
|
const tableMarkdown = buildSessionTable({ rows })
|
|
149
149
|
const segments = splitTablesFromMarkdown(tableMarkdown)
|
|
150
150
|
|
|
151
|
-
const
|
|
152
|
-
|
|
151
|
+
const btwNote: APITextDisplayComponent = {
|
|
152
|
+
type: ComponentType.TextDisplay,
|
|
153
|
+
content:
|
|
154
|
+
'Titles prefixed `btw:` are side sessions that answer a related question. They are not duplicate sessions.',
|
|
155
|
+
}
|
|
156
|
+
const allComponents: APIMessageTopLevelComponent[] = [
|
|
157
|
+
btwNote,
|
|
158
|
+
...segments.flatMap((segment) => {
|
|
153
159
|
if (segment.type === 'components') {
|
|
154
160
|
return segment.components
|
|
155
161
|
}
|
|
@@ -158,8 +164,8 @@ export async function handleLastSessionsCommand({
|
|
|
158
164
|
content: segment.text,
|
|
159
165
|
}
|
|
160
166
|
return [textDisplay]
|
|
161
|
-
},
|
|
162
|
-
|
|
167
|
+
}),
|
|
168
|
+
]
|
|
163
169
|
|
|
164
170
|
const { components } = truncateComponents(allComponents)
|
|
165
171
|
|
package/src/commands/login.ts
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
getOpencodeServerAuthHeaders,
|
|
35
35
|
} from '../opencode.js'
|
|
36
36
|
import { resolveTextChannel, getKimakiMetadata } from '../discord-utils.js'
|
|
37
|
+
import { clearModelListCache } from '../session-handler/model-utils.js'
|
|
37
38
|
import { createLogger, LogPrefix } from '../logger.js'
|
|
38
39
|
import { buildPaginatedOptions, parsePaginationValue } from './paginated-select.js'
|
|
39
40
|
|
|
@@ -122,7 +123,9 @@ function createContextHash(context: LoginContext): string {
|
|
|
122
123
|
// ── Provider popularity order ───────────────────────────────────
|
|
123
124
|
// Discord select menus cap at 25 options, so we show popular ones first.
|
|
124
125
|
// IDs sourced from opencode's provider.list() API (scripts/list-providers.ts).
|
|
126
|
+
// `subrouter` leads: it pools every subscription and cycles across them.
|
|
125
127
|
const PROVIDER_POPULARITY_ORDER: string[] = [
|
|
128
|
+
'subrouter',
|
|
126
129
|
'anthropic',
|
|
127
130
|
'openai',
|
|
128
131
|
'google',
|
|
@@ -937,6 +940,7 @@ export async function handleOAuthCodeModalSubmit(
|
|
|
937
940
|
}
|
|
938
941
|
|
|
939
942
|
await getClient().instance.dispose({ directory: ctx.dir })
|
|
943
|
+
clearModelListCache()
|
|
940
944
|
pendingLoginContexts.delete(hash)
|
|
941
945
|
|
|
942
946
|
await interaction.editReply({
|
|
@@ -993,6 +997,7 @@ export async function handleApiKeyModalSubmit(
|
|
|
993
997
|
|
|
994
998
|
// Dispose to refresh provider state so new credentials are recognized
|
|
995
999
|
await getClient().instance.dispose({ directory: ctx.dir })
|
|
1000
|
+
clearModelListCache()
|
|
996
1001
|
|
|
997
1002
|
await interaction.editReply({
|
|
998
1003
|
content: `✅ **Successfully authenticated with ${ctx.providerName}!**\n\nYou can now use models from this provider.`,
|
|
@@ -1159,6 +1164,7 @@ async function startOAuthFlow(
|
|
|
1159
1164
|
}
|
|
1160
1165
|
|
|
1161
1166
|
await getClient().instance.dispose({ directory: ctx.dir })
|
|
1167
|
+
clearModelListCache()
|
|
1162
1168
|
pendingLoginContexts.delete(hash)
|
|
1163
1169
|
|
|
1164
1170
|
await interaction.editReply({
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
// /merge-worktree command -
|
|
2
|
-
//
|
|
3
|
-
// Preserves all commits (no squash). On rebase conflicts, asks the AI model
|
|
4
|
-
// in the thread to resolve them.
|
|
1
|
+
// /merge-worktree command - Rebase or squash worktree commits into a target branch.
|
|
2
|
+
// On rebase conflicts, asks the AI model in the thread to resolve them.
|
|
5
3
|
|
|
6
4
|
import { type TextChannel, type ThreadChannel } from 'discord.js'
|
|
7
5
|
import type { AutocompleteContext, CommandContext } from './types.js'
|
|
@@ -12,7 +10,12 @@ import {
|
|
|
12
10
|
} from '../database.js'
|
|
13
11
|
import { createLogger, LogPrefix } from '../logger.js'
|
|
14
12
|
import { notifyError } from '../sentry.js'
|
|
15
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
mergeWorktree,
|
|
15
|
+
listBranchesByLastCommit,
|
|
16
|
+
validateBranchRef,
|
|
17
|
+
formatMergeWorktreeError,
|
|
18
|
+
} from '../worktrees.js'
|
|
16
19
|
import {
|
|
17
20
|
sendThreadMessage,
|
|
18
21
|
resolveWorkingDirectory,
|
|
@@ -27,19 +30,29 @@ import {
|
|
|
27
30
|
TargetDirtyWorktreeError,
|
|
28
31
|
NothingToMergeError,
|
|
29
32
|
} from '../errors.js'
|
|
33
|
+
import { WORKTREE_PREFIX } from '../message-formatting.js'
|
|
30
34
|
|
|
31
35
|
const logger = createLogger(LogPrefix.WORKTREE)
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
function quoteShellArg(value: string): string {
|
|
38
|
+
return `'${value.replaceAll("'", "'\\''")}'`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { WORKTREE_PREFIX }
|
|
42
|
+
|
|
43
|
+
function worktreePrefixLength(name: string) {
|
|
44
|
+
if (name.startsWith(WORKTREE_PREFIX)) return WORKTREE_PREFIX.length
|
|
45
|
+
return 0
|
|
46
|
+
}
|
|
35
47
|
|
|
36
48
|
async function removeWorktreePrefixFromTitle(
|
|
37
49
|
thread: ThreadChannel,
|
|
38
50
|
): Promise<void> {
|
|
39
|
-
|
|
51
|
+
const prefixLength = worktreePrefixLength(thread.name)
|
|
52
|
+
if (!prefixLength) {
|
|
40
53
|
return
|
|
41
54
|
}
|
|
42
|
-
const newName = thread.name.slice(
|
|
55
|
+
const newName = thread.name.slice(prefixLength)
|
|
43
56
|
const timeoutMs = 5000
|
|
44
57
|
await Promise.race([
|
|
45
58
|
thread.setName(newName).catch((e) => {
|
|
@@ -122,6 +135,15 @@ export async function handleMergeWorktreeCommand({
|
|
|
122
135
|
return
|
|
123
136
|
}
|
|
124
137
|
|
|
138
|
+
const strategyOption = command.options.getString('strategy') || 'rebase'
|
|
139
|
+
if (strategyOption !== 'rebase' && strategyOption !== 'squash') {
|
|
140
|
+
await command.editReply(`Invalid merge strategy: \`${strategyOption}\``)
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
const strategyName = strategyOption === 'squash'
|
|
144
|
+
? 'Squash into one commit'
|
|
145
|
+
: 'Keep commits (rebase)'
|
|
146
|
+
|
|
125
147
|
const rawTargetBranch = command.options.getString('target-branch') || undefined
|
|
126
148
|
let targetBranch = rawTargetBranch
|
|
127
149
|
if (targetBranch) {
|
|
@@ -141,6 +163,7 @@ export async function handleMergeWorktreeCommand({
|
|
|
141
163
|
mainRepoDir: info.project_directory,
|
|
142
164
|
worktreeName: info.workspace_name,
|
|
143
165
|
targetBranch,
|
|
166
|
+
strategy: strategyOption,
|
|
144
167
|
onProgress: (msg) => {
|
|
145
168
|
logger.log(`[merge] ${msg}`)
|
|
146
169
|
},
|
|
@@ -163,13 +186,24 @@ export async function handleMergeWorktreeCommand({
|
|
|
163
186
|
|
|
164
187
|
if (result instanceof NothingToMergeError) {
|
|
165
188
|
void removeWorktreePrefixFromTitle(thread)
|
|
166
|
-
await command.editReply(
|
|
189
|
+
await command.editReply(formatMergeWorktreeError(result))
|
|
167
190
|
return
|
|
168
191
|
}
|
|
169
192
|
|
|
170
193
|
if (result instanceof RebaseConflictError) {
|
|
194
|
+
const prefixLength = worktreePrefixLength(thread.name)
|
|
195
|
+
const mergedThreadName = prefixLength
|
|
196
|
+
? thread.name.slice(prefixLength)
|
|
197
|
+
: thread.name
|
|
198
|
+
const mergeCommand = [
|
|
199
|
+
'kimaki merge-worktree',
|
|
200
|
+
`--strategy ${strategyOption}`,
|
|
201
|
+
`--target-branch ${quoteShellArg(String(result.target))}`,
|
|
202
|
+
`--thread ${quoteShellArg(thread.id)}`,
|
|
203
|
+
`--thread-name ${quoteShellArg(mergedThreadName)}`,
|
|
204
|
+
].join(' ')
|
|
171
205
|
await command.editReply(
|
|
172
|
-
|
|
206
|
+
`Rebase conflict detected. Asking the model to resolve it and retry the merge with **${strategyName}**.`,
|
|
173
207
|
)
|
|
174
208
|
await sendPromptToModel({
|
|
175
209
|
prompt: [
|
|
@@ -184,7 +218,8 @@ export async function handleMergeWorktreeCommand({
|
|
|
184
218
|
'6. Stage resolved files with `git add`',
|
|
185
219
|
'7. Continue the rebase with `git rebase --continue`',
|
|
186
220
|
'8. If git reports more conflicts, repeat steps 1-7 until the rebase finishes (no more rebase in progress, `git status` is clean)',
|
|
187
|
-
|
|
221
|
+
`9. Once the rebase is fully complete, run \`${mergeCommand}\` yourself`,
|
|
222
|
+
'10. If that command fails because the target changed or is not ready, stop and report the failure. The user can run it again later.',
|
|
188
223
|
].join('\n'),
|
|
189
224
|
thread,
|
|
190
225
|
projectDirectory: info.project_directory,
|
|
@@ -194,14 +229,17 @@ export async function handleMergeWorktreeCommand({
|
|
|
194
229
|
return
|
|
195
230
|
}
|
|
196
231
|
|
|
197
|
-
|
|
232
|
+
const formatted = formatMergeWorktreeError(result)
|
|
233
|
+
logger.error(formatted)
|
|
234
|
+
await command.editReply(formatted)
|
|
198
235
|
return
|
|
199
236
|
}
|
|
200
237
|
|
|
201
238
|
void removeWorktreePrefixFromTitle(thread)
|
|
202
|
-
|
|
203
|
-
`
|
|
204
|
-
|
|
239
|
+
const mergeSummary = strategyOption === 'squash'
|
|
240
|
+
? `Squashed \`${result.branchName}\` into \`${result.defaultBranch}\` @ ${result.shortSha} (${result.commitCount} source commit${result.commitCount === 1 ? '' : 's'} → 1)`
|
|
241
|
+
: `Merged \`${result.branchName}\` into \`${result.defaultBranch}\` @ ${result.shortSha} (${result.commitCount} commit${result.commitCount === 1 ? '' : 's'})`
|
|
242
|
+
await command.editReply(`${mergeSummary}\nWorktree now at detached HEAD.`)
|
|
205
243
|
}
|
|
206
244
|
|
|
207
245
|
/**
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
} from './model.js'
|
|
35
35
|
|
|
36
36
|
import { getThinkingValuesForModel } from '../thinking-utils.js'
|
|
37
|
+
import { resolveDisplayedModelId } from '../session-handler/model-utils.js'
|
|
37
38
|
import { createLogger, LogPrefix } from '../logger.js'
|
|
38
39
|
|
|
39
40
|
const logger = createLogger(LogPrefix.MODEL)
|
|
@@ -214,6 +215,13 @@ export async function showModelVariantPicker({
|
|
|
214
215
|
const { providerID, modelID, model: fullModelId } = currentModelInfo
|
|
215
216
|
const sourceLabel = formatSourceLabel(currentModelInfo)
|
|
216
217
|
const variantLabel = cascadeVariant ? ` (${cascadeVariant})` : ''
|
|
218
|
+
const displayedModelId =
|
|
219
|
+
(await resolveDisplayedModelId({
|
|
220
|
+
providers: providersResponse.data.all,
|
|
221
|
+
providerID,
|
|
222
|
+
modelID,
|
|
223
|
+
sessionID: sessionId,
|
|
224
|
+
})) ?? fullModelId
|
|
217
225
|
|
|
218
226
|
const provider = providersResponse.data.all.find((p) => {
|
|
219
227
|
return p.id === providerID
|
|
@@ -226,7 +234,7 @@ export async function showModelVariantPicker({
|
|
|
226
234
|
modelId: modelID,
|
|
227
235
|
})
|
|
228
236
|
|
|
229
|
-
const statusText = `**Current model:** \`${
|
|
237
|
+
const statusText = `**Current model:** \`${displayedModelId}\`${variantLabel} — ${sourceLabel}`
|
|
230
238
|
|
|
231
239
|
if (variants.length === 0) {
|
|
232
240
|
await editReply({
|
package/src/commands/model.ts
CHANGED
|
@@ -28,7 +28,10 @@ import {
|
|
|
28
28
|
} from '../database.js'
|
|
29
29
|
import { initializeOpencodeForDirectory } from '../opencode.js'
|
|
30
30
|
import { resolveTextChannel, getKimakiMetadata } from '../discord-utils.js'
|
|
31
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
getDefaultModel,
|
|
33
|
+
resolveDisplayedModelId,
|
|
34
|
+
} from '../session-handler/model-utils.js'
|
|
32
35
|
import { getRuntime } from '../session-handler/thread-session-runtime.js'
|
|
33
36
|
import { getThinkingValuesForModel } from '../thinking-utils.js'
|
|
34
37
|
import {
|
|
@@ -544,22 +547,30 @@ export async function handleModelCommand({
|
|
|
544
547
|
return
|
|
545
548
|
}
|
|
546
549
|
|
|
547
|
-
const currentModelText = (() => {
|
|
550
|
+
const currentModelText = await (async () => {
|
|
551
|
+
if (currentModelInfo.type === 'none') {
|
|
552
|
+
return '**Current:** none'
|
|
553
|
+
}
|
|
554
|
+
const displayed =
|
|
555
|
+
(await resolveDisplayedModelId({
|
|
556
|
+
providers: allProviders,
|
|
557
|
+
providerID: currentModelInfo.providerID,
|
|
558
|
+
modelID: currentModelInfo.modelID,
|
|
559
|
+
sessionID: sessionId,
|
|
560
|
+
})) ?? currentModelInfo.model
|
|
548
561
|
switch (currentModelInfo.type) {
|
|
549
562
|
case 'session':
|
|
550
|
-
return `**Current (this thread):** \`${
|
|
563
|
+
return `**Current (this thread):** \`${displayed}\``
|
|
551
564
|
case 'agent':
|
|
552
|
-
return `**Current (agent "${currentModelInfo.agentName}"):** \`${
|
|
565
|
+
return `**Current (agent "${currentModelInfo.agentName}"):** \`${displayed}\``
|
|
553
566
|
case 'channel':
|
|
554
|
-
return `**Current (channel override):** \`${
|
|
567
|
+
return `**Current (channel override):** \`${displayed}\``
|
|
555
568
|
case 'global':
|
|
556
|
-
return `**Current (global default):** \`${
|
|
569
|
+
return `**Current (global default):** \`${displayed}\``
|
|
557
570
|
case 'opencode-config':
|
|
558
571
|
case 'opencode-recent':
|
|
559
572
|
case 'opencode-provider-default':
|
|
560
|
-
return `**Current (opencode default):** \`${
|
|
561
|
-
case 'none':
|
|
562
|
-
return '**Current:** none'
|
|
573
|
+
return `**Current (opencode default):** \`${displayed}\``
|
|
563
574
|
}
|
|
564
575
|
})()
|
|
565
576
|
|