kimaki 0.4.82 → 0.4.84
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/LICENSE +21 -0
- package/dist/anthropic-auth-plugin.js +7 -0
- package/dist/cli.js +51 -7
- package/dist/commands/abort.js +5 -16
- package/dist/commands/action-buttons.js +3 -3
- package/dist/commands/add-project.js +1 -1
- package/dist/commands/ask-question.js +3 -3
- package/dist/commands/context-usage.js +1 -1
- package/dist/commands/create-new-project.js +1 -1
- package/dist/commands/fork.js +11 -8
- package/dist/commands/merge-worktree.js +1 -1
- package/dist/commands/new-worktree.js +63 -44
- package/dist/commands/remove-project.js +1 -1
- package/dist/commands/resume.js +11 -8
- package/dist/commands/screenshare.js +14 -6
- package/dist/commands/screenshare.test.js +20 -0
- package/dist/commands/session.js +1 -1
- package/dist/commands/undo-redo.js +91 -7
- package/dist/commands/user-command.js +1 -1
- package/dist/config.js +16 -1
- package/dist/database.js +53 -2
- package/dist/db.js +6 -0
- package/dist/discord-bot.js +48 -85
- package/dist/discord-command-registration.js +1 -1
- package/dist/external-opencode-sync.js +515 -0
- package/dist/external-opencode-sync.test.js +151 -0
- package/dist/gateway-proxy.e2e.test.js +8 -5
- package/dist/genai.js +1 -1
- package/dist/generated/enums.js +4 -0
- package/dist/generated/internal/class.js +4 -4
- package/dist/generated/internal/prismaNamespace.js +1 -0
- package/dist/generated/internal/prismaNamespaceBrowser.js +1 -0
- package/dist/generated/models/external_session_pending_prompts.js +1 -0
- package/dist/hrana-server.js +14 -285
- package/dist/hrana-server.test.js +4 -2
- package/dist/kimaki-opencode-plugin-loading.e2e.test.js +7 -0
- package/dist/kimaki-opencode-plugin.js +2 -0
- package/dist/kitty-graphics-parser.js +3 -0
- package/dist/kitty-graphics-parser.test.js +276 -0
- package/dist/kitty-graphics-plugin.js +3 -0
- package/dist/markdown.js +4 -4
- package/dist/markdown.test.js +1 -1
- package/dist/message-formatting.js +54 -15
- package/dist/onboarding-tutorial.js +1 -1
- package/dist/openai-realtime.js +9 -13
- package/dist/opencode.js +28 -5
- package/dist/queue-advanced-e2e-setup.js +89 -0
- package/dist/queue-advanced-permissions-typing.e2e.test.js +5 -5
- package/dist/queue-advanced-typing.e2e.test.js +9 -22
- package/dist/queue-question-select-drain.e2e.test.js +117 -0
- package/dist/session-handler/event-stream-state.js +101 -7
- package/dist/session-handler/event-stream-state.test.js +7 -3
- package/dist/session-handler/thread-session-runtime.js +120 -9
- package/dist/store.js +1 -0
- package/dist/system-message.js +22 -4
- package/dist/system-message.test.js +19 -0
- package/dist/task-runner.js +1 -1
- package/dist/thread-message-queue.e2e.test.js +8 -14
- package/dist/tools.js +1 -1
- package/dist/undo-redo.e2e.test.js +20 -25
- package/package.json +10 -6
- package/schema.prisma +6 -0
- package/skills/errore/SKILL.md +40 -13
- package/skills/goke/SKILL.md +12 -0
- package/skills/lintcn/SKILL.md +868 -0
- package/skills/npm-package/SKILL.md +1 -0
- package/skills/proxyman/SKILL.md +215 -0
- package/skills/spiceflow/SKILL.md +1 -1
- package/skills/usecomputer/SKILL.md +339 -0
- package/src/ai-tool-to-genai.ts +1 -0
- package/src/anthropic-auth-plugin.ts +7 -0
- package/src/cli.ts +59 -6
- package/src/commands/abort.ts +6 -16
- package/src/commands/action-buttons.ts +5 -1
- package/src/commands/add-project.ts +1 -1
- package/src/commands/ask-question.ts +5 -2
- package/src/commands/context-usage.ts +1 -1
- package/src/commands/create-new-project.ts +1 -1
- package/src/commands/fork.ts +12 -11
- package/src/commands/merge-worktree.ts +1 -1
- package/src/commands/new-worktree.ts +74 -55
- package/src/commands/remove-project.ts +1 -1
- package/src/commands/resume.ts +12 -10
- package/src/commands/screenshare.test.ts +30 -0
- package/src/commands/screenshare.ts +18 -6
- package/src/commands/session.ts +1 -1
- package/src/commands/undo-redo.ts +108 -10
- package/src/commands/user-command.ts +1 -1
- package/src/config.ts +19 -1
- package/src/database.ts +72 -3
- package/src/db.ts +8 -0
- package/src/discord-bot.ts +58 -93
- package/src/discord-command-registration.ts +1 -1
- package/src/external-opencode-sync.ts +729 -0
- package/src/gateway-proxy.e2e.test.ts +9 -5
- package/src/genai.ts +3 -3
- package/src/generated/commonInputTypes.ts +34 -0
- package/src/generated/enums.ts +8 -0
- package/src/generated/internal/class.ts +4 -4
- package/src/generated/internal/prismaNamespace.ts +8 -0
- package/src/generated/internal/prismaNamespaceBrowser.ts +1 -0
- package/src/generated/models/thread_sessions.ts +53 -1
- package/src/hrana-server.test.ts +8 -2
- package/src/hrana-server.ts +18 -390
- package/src/kimaki-opencode-plugin-loading.e2e.test.ts +7 -0
- package/src/kimaki-opencode-plugin.ts +2 -0
- package/src/markdown.test.ts +1 -1
- package/src/markdown.ts +4 -4
- package/src/message-formatting.ts +66 -17
- package/src/onboarding-tutorial.ts +1 -1
- package/src/openai-realtime.ts +6 -10
- package/src/opencode.ts +31 -7
- package/src/queue-advanced-e2e-setup.ts +92 -0
- package/src/queue-advanced-permissions-typing.e2e.test.ts +5 -5
- package/src/queue-advanced-typing.e2e.test.ts +9 -22
- package/src/queue-question-select-drain.e2e.test.ts +149 -0
- package/src/schema.sql +1 -0
- package/src/session-handler/event-stream-state.test.ts +7 -2
- package/src/session-handler/event-stream-state.ts +128 -7
- package/src/session-handler/thread-runtime-state.ts +5 -0
- package/src/session-handler/thread-session-runtime.ts +153 -11
- package/src/store.ts +8 -0
- package/src/system-message.ts +27 -4
- package/src/task-runner.ts +1 -1
- package/src/thread-message-queue.e2e.test.ts +8 -14
- package/src/tools.ts +1 -1
- package/src/undo-redo.e2e.test.ts +28 -26
- package/skills/jitter/node_modules/.bin/esbuild +0 -21
- package/skills/jitter/node_modules/.bin/tsc +0 -21
- package/skills/jitter/node_modules/.bin/tsserver +0 -21
- package/skills/jitter/node_modules/typescript/LICENSE.txt +0 -55
- package/skills/jitter/node_modules/typescript/README.md +0 -50
- package/skills/jitter/node_modules/typescript/SECURITY.md +0 -41
- package/skills/jitter/node_modules/typescript/ThirdPartyNoticeText.txt +0 -193
- package/skills/jitter/node_modules/typescript/bin/tsc +0 -2
- package/skills/jitter/node_modules/typescript/bin/tsserver +0 -2
- package/skills/jitter/node_modules/typescript/lib/_tsc.js +0 -133792
- package/skills/jitter/node_modules/typescript/lib/_tsserver.js +0 -659
- package/skills/jitter/node_modules/typescript/lib/_typingsInstaller.js +0 -222
- package/skills/jitter/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/de/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/es/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/it/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/lib.d.ts +0 -22
- package/skills/jitter/node_modules/typescript/lib/lib.decorators.d.ts +0 -384
- package/skills/jitter/node_modules/typescript/lib/lib.decorators.legacy.d.ts +0 -22
- package/skills/jitter/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +0 -41
- package/skills/jitter/node_modules/typescript/lib/lib.dom.d.ts +0 -39429
- package/skills/jitter/node_modules/typescript/lib/lib.dom.iterable.d.ts +0 -571
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.collection.d.ts +0 -147
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.core.d.ts +0 -597
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.d.ts +0 -28
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.generator.d.ts +0 -77
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.iterable.d.ts +0 -605
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.promise.d.ts +0 -81
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.proxy.d.ts +0 -128
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.reflect.d.ts +0 -144
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.symbol.d.ts +0 -46
- package/skills/jitter/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +0 -326
- package/skills/jitter/node_modules/typescript/lib/lib.es2016.array.include.d.ts +0 -116
- package/skills/jitter/node_modules/typescript/lib/lib.es2016.d.ts +0 -21
- package/skills/jitter/node_modules/typescript/lib/lib.es2016.full.d.ts +0 -23
- package/skills/jitter/node_modules/typescript/lib/lib.es2016.intl.d.ts +0 -31
- package/skills/jitter/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +0 -21
- package/skills/jitter/node_modules/typescript/lib/lib.es2017.d.ts +0 -26
- package/skills/jitter/node_modules/typescript/lib/lib.es2017.date.d.ts +0 -31
- package/skills/jitter/node_modules/typescript/lib/lib.es2017.full.d.ts +0 -23
- package/skills/jitter/node_modules/typescript/lib/lib.es2017.intl.d.ts +0 -44
- package/skills/jitter/node_modules/typescript/lib/lib.es2017.object.d.ts +0 -49
- package/skills/jitter/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +0 -135
- package/skills/jitter/node_modules/typescript/lib/lib.es2017.string.d.ts +0 -45
- package/skills/jitter/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +0 -53
- package/skills/jitter/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +0 -77
- package/skills/jitter/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +0 -53
- package/skills/jitter/node_modules/typescript/lib/lib.es2018.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2018.full.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2018.intl.d.ts +0 -83
- package/skills/jitter/node_modules/typescript/lib/lib.es2018.promise.d.ts +0 -30
- package/skills/jitter/node_modules/typescript/lib/lib.es2018.regexp.d.ts +0 -37
- package/skills/jitter/node_modules/typescript/lib/lib.es2019.array.d.ts +0 -79
- package/skills/jitter/node_modules/typescript/lib/lib.es2019.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2019.full.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2019.intl.d.ts +0 -23
- package/skills/jitter/node_modules/typescript/lib/lib.es2019.object.d.ts +0 -33
- package/skills/jitter/node_modules/typescript/lib/lib.es2019.string.d.ts +0 -37
- package/skills/jitter/node_modules/typescript/lib/lib.es2019.symbol.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.bigint.d.ts +0 -765
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.d.ts +0 -27
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.date.d.ts +0 -42
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.full.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.intl.d.ts +0 -474
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.number.d.ts +0 -28
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.promise.d.ts +0 -47
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +0 -99
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.string.d.ts +0 -44
- package/skills/jitter/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +0 -41
- package/skills/jitter/node_modules/typescript/lib/lib.es2021.d.ts +0 -23
- package/skills/jitter/node_modules/typescript/lib/lib.es2021.full.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2021.intl.d.ts +0 -166
- package/skills/jitter/node_modules/typescript/lib/lib.es2021.promise.d.ts +0 -48
- package/skills/jitter/node_modules/typescript/lib/lib.es2021.string.d.ts +0 -33
- package/skills/jitter/node_modules/typescript/lib/lib.es2021.weakref.d.ts +0 -78
- package/skills/jitter/node_modules/typescript/lib/lib.es2022.array.d.ts +0 -121
- package/skills/jitter/node_modules/typescript/lib/lib.es2022.d.ts +0 -25
- package/skills/jitter/node_modules/typescript/lib/lib.es2022.error.d.ts +0 -75
- package/skills/jitter/node_modules/typescript/lib/lib.es2022.full.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2022.intl.d.ts +0 -145
- package/skills/jitter/node_modules/typescript/lib/lib.es2022.object.d.ts +0 -26
- package/skills/jitter/node_modules/typescript/lib/lib.es2022.regexp.d.ts +0 -39
- package/skills/jitter/node_modules/typescript/lib/lib.es2022.string.d.ts +0 -25
- package/skills/jitter/node_modules/typescript/lib/lib.es2023.array.d.ts +0 -924
- package/skills/jitter/node_modules/typescript/lib/lib.es2023.collection.d.ts +0 -21
- package/skills/jitter/node_modules/typescript/lib/lib.es2023.d.ts +0 -22
- package/skills/jitter/node_modules/typescript/lib/lib.es2023.full.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2023.intl.d.ts +0 -56
- package/skills/jitter/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +0 -65
- package/skills/jitter/node_modules/typescript/lib/lib.es2024.collection.d.ts +0 -29
- package/skills/jitter/node_modules/typescript/lib/lib.es2024.d.ts +0 -26
- package/skills/jitter/node_modules/typescript/lib/lib.es2024.full.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.es2024.object.d.ts +0 -29
- package/skills/jitter/node_modules/typescript/lib/lib.es2024.promise.d.ts +0 -35
- package/skills/jitter/node_modules/typescript/lib/lib.es2024.regexp.d.ts +0 -25
- package/skills/jitter/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +0 -68
- package/skills/jitter/node_modules/typescript/lib/lib.es2024.string.d.ts +0 -29
- package/skills/jitter/node_modules/typescript/lib/lib.es5.d.ts +0 -4601
- package/skills/jitter/node_modules/typescript/lib/lib.es6.d.ts +0 -23
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.array.d.ts +0 -35
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.collection.d.ts +0 -96
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.d.ts +0 -29
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.decorators.d.ts +0 -28
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.disposable.d.ts +0 -193
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.error.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.float16.d.ts +0 -443
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.full.d.ts +0 -24
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.intl.d.ts +0 -21
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.iterator.d.ts +0 -148
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.promise.d.ts +0 -34
- package/skills/jitter/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +0 -25
- package/skills/jitter/node_modules/typescript/lib/lib.scripthost.d.ts +0 -322
- package/skills/jitter/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +0 -41
- package/skills/jitter/node_modules/typescript/lib/lib.webworker.d.ts +0 -13150
- package/skills/jitter/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +0 -23
- package/skills/jitter/node_modules/typescript/lib/lib.webworker.iterable.d.ts +0 -340
- package/skills/jitter/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/tsc.js +0 -8
- package/skills/jitter/node_modules/typescript/lib/tsserver.js +0 -8
- package/skills/jitter/node_modules/typescript/lib/tsserverlibrary.d.ts +0 -17
- package/skills/jitter/node_modules/typescript/lib/tsserverlibrary.js +0 -21
- package/skills/jitter/node_modules/typescript/lib/typesMap.json +0 -497
- package/skills/jitter/node_modules/typescript/lib/typescript.d.ts +0 -11438
- package/skills/jitter/node_modules/typescript/lib/typescript.js +0 -200253
- package/skills/jitter/node_modules/typescript/lib/typingsInstaller.js +0 -8
- package/skills/jitter/node_modules/typescript/lib/watchGuard.js +0 -53
- package/skills/jitter/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +0 -2122
- package/skills/jitter/node_modules/typescript/node_modules/.bin/tsc +0 -21
- package/skills/jitter/node_modules/typescript/node_modules/.bin/tsserver +0 -21
- package/skills/jitter/node_modules/typescript/package.json +0 -120
|
@@ -350,7 +350,7 @@ function getTokenTotal(tokens: TokenUsage): number {
|
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
/** Check if a tool part is "essential" (shown in text-and-essential-tools mode). */
|
|
353
|
-
function isEssentialToolName(toolName: string): boolean {
|
|
353
|
+
export function isEssentialToolName(toolName: string): boolean {
|
|
354
354
|
const essentialTools = [
|
|
355
355
|
'edit',
|
|
356
356
|
'write',
|
|
@@ -370,7 +370,7 @@ function isEssentialToolName(toolName: string): boolean {
|
|
|
370
370
|
})
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
-
function isEssentialToolPart(part: Part): boolean {
|
|
373
|
+
export function isEssentialToolPart(part: Part): boolean {
|
|
374
374
|
if (part.type !== 'tool') {
|
|
375
375
|
return false
|
|
376
376
|
}
|
|
@@ -411,6 +411,11 @@ export type IngressInput = {
|
|
|
411
411
|
prompt: string
|
|
412
412
|
userId: string
|
|
413
413
|
username: string
|
|
414
|
+
// Discord message ID and thread ID for the source message, embedded in
|
|
415
|
+
// <discord-user> synthetic context so the external sync loop can detect
|
|
416
|
+
// messages that originated from Discord and skip re-mirroring them.
|
|
417
|
+
sourceMessageId?: string
|
|
418
|
+
sourceThreadId?: string
|
|
414
419
|
images?: DiscordFileAttachment[]
|
|
415
420
|
appId?: string
|
|
416
421
|
command?: { name: string; arguments: string }
|
|
@@ -982,10 +987,28 @@ export class ThreadSessionRuntime {
|
|
|
982
987
|
// with every tool call and was the primary OOM vector — 1000 buffer entries
|
|
983
988
|
// each carrying the full cumulative parts array reached 4GB+.
|
|
984
989
|
const info = compacted.properties.info as Record<string, unknown>
|
|
990
|
+
const partsSummary = Array.isArray(info.parts)
|
|
991
|
+
? info.parts.flatMap((part) => {
|
|
992
|
+
if (!part || typeof part !== 'object') {
|
|
993
|
+
return [] as Array<{ id: string; type: string }>
|
|
994
|
+
}
|
|
995
|
+
const candidate = part as { id?: unknown; type?: unknown }
|
|
996
|
+
if (
|
|
997
|
+
typeof candidate.id !== 'string'
|
|
998
|
+
|| typeof candidate.type !== 'string'
|
|
999
|
+
) {
|
|
1000
|
+
return [] as Array<{ id: string; type: string }>
|
|
1001
|
+
}
|
|
1002
|
+
return [{ id: candidate.id, type: candidate.type }]
|
|
1003
|
+
})
|
|
1004
|
+
: []
|
|
985
1005
|
delete info.system
|
|
986
1006
|
delete info.summary
|
|
987
1007
|
delete info.tools
|
|
988
1008
|
delete info.parts
|
|
1009
|
+
if (partsSummary.length > 0) {
|
|
1010
|
+
info.partsSummary = partsSummary
|
|
1011
|
+
}
|
|
989
1012
|
return this.finalizeCompactedEventForEventBuffer(compacted)
|
|
990
1013
|
}
|
|
991
1014
|
|
|
@@ -1986,6 +2009,7 @@ export class ThreadSessionRuntime {
|
|
|
1986
2009
|
sessionId: request.sessionId,
|
|
1987
2010
|
directory: request.directory,
|
|
1988
2011
|
buttons: request.buttons,
|
|
2012
|
+
silent: this.getQueueLength() > 0,
|
|
1989
2013
|
})
|
|
1990
2014
|
})
|
|
1991
2015
|
if (showResult instanceof Error) {
|
|
@@ -2425,6 +2449,7 @@ export class ThreadSessionRuntime {
|
|
|
2425
2449
|
directory: this.projectDirectory,
|
|
2426
2450
|
requestId: questionRequest.id,
|
|
2427
2451
|
input: { questions: questionRequest.questions },
|
|
2452
|
+
silent: this.getQueueLength() > 0,
|
|
2428
2453
|
})
|
|
2429
2454
|
},
|
|
2430
2455
|
})
|
|
@@ -2439,6 +2464,66 @@ export class ThreadSessionRuntime {
|
|
|
2439
2464
|
return
|
|
2440
2465
|
}
|
|
2441
2466
|
this.onInteractiveUiStateChanged()
|
|
2467
|
+
|
|
2468
|
+
// When a question is answered and the local queue has items, the model may
|
|
2469
|
+
// continue the same run without ever reaching the local-queue idle gate.
|
|
2470
|
+
// Hand the queued items to OpenCode's own prompt queue immediately instead
|
|
2471
|
+
// of waiting for tryDrainQueue() to see an idle session.
|
|
2472
|
+
if (this.getQueueLength() > 0 && !this.questionReplyQueueHandoffPromise) {
|
|
2473
|
+
logger.log(
|
|
2474
|
+
`[QUESTION REPLIED] Queue has ${this.getQueueLength()} items, handing off to opencode queue`,
|
|
2475
|
+
)
|
|
2476
|
+
this.questionReplyQueueHandoffPromise = this.handoffQueuedItemsAfterQuestionReply({
|
|
2477
|
+
sessionId,
|
|
2478
|
+
}).catch((error) => {
|
|
2479
|
+
logger.error('[QUESTION REPLIED] Failed to hand off queued messages:', error)
|
|
2480
|
+
if (error instanceof Error) {
|
|
2481
|
+
void notifyError(error, 'Failed to hand off queued messages after question reply')
|
|
2482
|
+
}
|
|
2483
|
+
}).finally(() => {
|
|
2484
|
+
this.questionReplyQueueHandoffPromise = null
|
|
2485
|
+
})
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
// Detached helper promise for the "question answered while local queue has
|
|
2490
|
+
// items" flow. Prevents starting two overlapping local->opencode queue
|
|
2491
|
+
// handoff sequences when multiple question replies land close together.
|
|
2492
|
+
private questionReplyQueueHandoffPromise: Promise<void> | null = null
|
|
2493
|
+
|
|
2494
|
+
private async handoffQueuedItemsAfterQuestionReply({
|
|
2495
|
+
sessionId,
|
|
2496
|
+
}: {
|
|
2497
|
+
sessionId: string
|
|
2498
|
+
}): Promise<void> {
|
|
2499
|
+
if (this.listenerAborted) {
|
|
2500
|
+
return
|
|
2501
|
+
}
|
|
2502
|
+
if (this.state?.sessionId !== sessionId) {
|
|
2503
|
+
logger.log(
|
|
2504
|
+
`[QUESTION REPLIED] Session changed before queue handoff for thread ${this.threadId}`,
|
|
2505
|
+
)
|
|
2506
|
+
return
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2509
|
+
while (this.state?.sessionId === sessionId) {
|
|
2510
|
+
const next = threadState.dequeueItem(this.threadId)
|
|
2511
|
+
if (!next) {
|
|
2512
|
+
return
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
const displayText = next.command
|
|
2516
|
+
? `/${next.command.name}`
|
|
2517
|
+
: `${next.prompt.slice(0, 150)}${next.prompt.length > 150 ? '...' : ''}`
|
|
2518
|
+
if (displayText.trim()) {
|
|
2519
|
+
await sendThreadMessage(
|
|
2520
|
+
this.thread,
|
|
2521
|
+
`» **${next.username}:** ${displayText}`,
|
|
2522
|
+
)
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
await this.submitViaOpencodeQueue(next)
|
|
2526
|
+
}
|
|
2442
2527
|
}
|
|
2443
2528
|
|
|
2444
2529
|
private async handleSessionStatus(properties: {
|
|
@@ -2698,7 +2783,9 @@ export class ThreadSessionRuntime {
|
|
|
2698
2783
|
|
|
2699
2784
|
let syntheticContext = ''
|
|
2700
2785
|
if (input.username) {
|
|
2701
|
-
|
|
2786
|
+
const msgAttr = input.sourceMessageId ? ` message-id="${input.sourceMessageId}"` : ''
|
|
2787
|
+
const thrAttr = input.sourceThreadId ? ` thread-id="${input.sourceThreadId}"` : ''
|
|
2788
|
+
syntheticContext += `<discord-user name="${input.username}"${msgAttr}${thrAttr} />`
|
|
2702
2789
|
}
|
|
2703
2790
|
const parts = [
|
|
2704
2791
|
{ type: 'text' as const, text: promptWithImagePaths },
|
|
@@ -2819,6 +2906,8 @@ export class ThreadSessionRuntime {
|
|
|
2819
2906
|
agent: input.agent,
|
|
2820
2907
|
model: input.model,
|
|
2821
2908
|
permissions: input.permissions,
|
|
2909
|
+
sourceMessageId: input.sourceMessageId,
|
|
2910
|
+
sourceThreadId: input.sourceThreadId,
|
|
2822
2911
|
sessionStartScheduleKind: input.sessionStartSource?.scheduleKind,
|
|
2823
2912
|
sessionStartScheduledTaskId: input.sessionStartSource?.scheduledTaskId,
|
|
2824
2913
|
}
|
|
@@ -3040,11 +3129,60 @@ export class ThreadSessionRuntime {
|
|
|
3040
3129
|
})
|
|
3041
3130
|
}
|
|
3042
3131
|
|
|
3132
|
+
async abortActiveRunAndWait({
|
|
3133
|
+
reason,
|
|
3134
|
+
timeoutMs = 2_000,
|
|
3135
|
+
}: {
|
|
3136
|
+
reason: string
|
|
3137
|
+
timeoutMs?: number
|
|
3138
|
+
}): Promise<void> {
|
|
3139
|
+
const state = this.state
|
|
3140
|
+
const sessionId = state?.sessionId
|
|
3141
|
+
if (!sessionId) {
|
|
3142
|
+
return
|
|
3143
|
+
}
|
|
3144
|
+
|
|
3145
|
+
let needsIdleWait = false
|
|
3146
|
+
const waitSinceTimestamp = Date.now()
|
|
3147
|
+
const abortResult = await errore.tryAsync(() => {
|
|
3148
|
+
return this.dispatchAction(async () => {
|
|
3149
|
+
needsIdleWait = this.isMainSessionBusy()
|
|
3150
|
+
const outcome = this.abortActiveRunInternal({ reason })
|
|
3151
|
+
if (outcome.apiAbortPromise) {
|
|
3152
|
+
void outcome.apiAbortPromise
|
|
3153
|
+
}
|
|
3154
|
+
})
|
|
3155
|
+
})
|
|
3156
|
+
if (abortResult instanceof Error) {
|
|
3157
|
+
logger.error(`[ABORT WAIT] Failed to abort active run: ${abortResult.message}`)
|
|
3158
|
+
return
|
|
3159
|
+
}
|
|
3160
|
+
if (!needsIdleWait) {
|
|
3161
|
+
return
|
|
3162
|
+
}
|
|
3163
|
+
await this.waitForEvent({
|
|
3164
|
+
predicate: (event) => {
|
|
3165
|
+
return event.type === 'session.idle'
|
|
3166
|
+
&& (event.properties as { sessionID?: string }).sessionID === sessionId
|
|
3167
|
+
},
|
|
3168
|
+
sinceTimestamp: waitSinceTimestamp,
|
|
3169
|
+
timeoutMs,
|
|
3170
|
+
})
|
|
3171
|
+
}
|
|
3172
|
+
|
|
3043
3173
|
/** Number of messages waiting in the queue. */
|
|
3044
3174
|
getQueueLength(): number {
|
|
3045
3175
|
return this.state?.queueItems.length ?? 0
|
|
3046
3176
|
}
|
|
3047
3177
|
|
|
3178
|
+
/** NOTIFY_MESSAGE_FLAGS unless queue has a next item, then SILENT.
|
|
3179
|
+
* Permissions should NOT use this — they always notify. */
|
|
3180
|
+
private getNotifyFlags(): number {
|
|
3181
|
+
return this.getQueueLength() > 0
|
|
3182
|
+
? SILENT_MESSAGE_FLAGS
|
|
3183
|
+
: NOTIFY_MESSAGE_FLAGS
|
|
3184
|
+
}
|
|
3185
|
+
|
|
3048
3186
|
/** Clear all queued messages. */
|
|
3049
3187
|
clearQueue(): void {
|
|
3050
3188
|
threadState.clearQueueItems(this.threadId)
|
|
@@ -3301,7 +3439,9 @@ export class ThreadSessionRuntime {
|
|
|
3301
3439
|
|
|
3302
3440
|
let syntheticContext = ''
|
|
3303
3441
|
if (input.username) {
|
|
3304
|
-
|
|
3442
|
+
const msgAttr = input.sourceMessageId ? ` message-id="${input.sourceMessageId}"` : ''
|
|
3443
|
+
const thrAttr = input.sourceThreadId ? ` thread-id="${input.sourceThreadId}"` : ''
|
|
3444
|
+
syntheticContext += `<discord-user name="${input.username}"${msgAttr}${thrAttr} />`
|
|
3305
3445
|
}
|
|
3306
3446
|
const parts = [
|
|
3307
3447
|
{ type: 'text' as const, text: promptWithImagePaths },
|
|
@@ -3575,8 +3715,6 @@ export class ThreadSessionRuntime {
|
|
|
3575
3715
|
}
|
|
3576
3716
|
|
|
3577
3717
|
if (!session) {
|
|
3578
|
-
const sessionTitle =
|
|
3579
|
-
prompt.length > 80 ? prompt.slice(0, 77) + '...' : prompt.slice(0, 80)
|
|
3580
3718
|
// Pass per-session external_directory permissions so this session can
|
|
3581
3719
|
// access its own project directory (and worktree origin if applicable)
|
|
3582
3720
|
// without prompts. These override the server-level 'ask' default via
|
|
@@ -3590,12 +3728,18 @@ export class ThreadSessionRuntime {
|
|
|
3590
3728
|
}),
|
|
3591
3729
|
...parsePermissionRules(permissions ?? []),
|
|
3592
3730
|
]
|
|
3731
|
+
// Omit title so OpenCode auto-generates a summary from the conversation
|
|
3593
3732
|
const sessionResponse = await getClient().session.create({
|
|
3594
|
-
title: sessionTitle,
|
|
3595
3733
|
directory: this.sdkDirectory,
|
|
3596
3734
|
permission: sessionPermissions,
|
|
3597
3735
|
})
|
|
3598
3736
|
session = sessionResponse.data
|
|
3737
|
+
// Insert DB row immediately so the external-sync poller sees
|
|
3738
|
+
// source='kimaki' before the next poll tick and skips this session.
|
|
3739
|
+
// The upsert at the end of ensureSession is kept for the reuse path.
|
|
3740
|
+
if (session) {
|
|
3741
|
+
await setThreadSession(this.thread.id, session.id)
|
|
3742
|
+
}
|
|
3599
3743
|
createdNewSession = true
|
|
3600
3744
|
}
|
|
3601
3745
|
|
|
@@ -3700,7 +3844,7 @@ export class ThreadSessionRuntime {
|
|
|
3700
3844
|
if (m.info.role !== 'assistant') {
|
|
3701
3845
|
return false
|
|
3702
3846
|
}
|
|
3703
|
-
if (!
|
|
3847
|
+
if (!m.info.tokens) {
|
|
3704
3848
|
return false
|
|
3705
3849
|
}
|
|
3706
3850
|
return getTokenTotal(m.info.tokens) > 0
|
|
@@ -3750,10 +3894,8 @@ export class ThreadSessionRuntime {
|
|
|
3750
3894
|
|
|
3751
3895
|
// Skip notification if there's a queued message next — the user only
|
|
3752
3896
|
// needs to be notified when the entire queue finishes.
|
|
3753
|
-
const queuedNext =
|
|
3754
|
-
(threadState.getThreadState(this.threadId)?.queueItems.length ?? 0) > 0
|
|
3755
3897
|
await sendThreadMessage(this.thread, footerText, {
|
|
3756
|
-
flags:
|
|
3898
|
+
flags: this.getNotifyFlags(),
|
|
3757
3899
|
})
|
|
3758
3900
|
logger.log(
|
|
3759
3901
|
`DURATION: Session completed in ${sessionDuration}, model ${runInfo.model}, tokens ${runInfo.tokensUsed}`,
|
package/src/store.ts
CHANGED
|
@@ -38,6 +38,13 @@ export type KimakiState = {
|
|
|
38
38
|
// Read by: database paths, heap snapshot dir, log file path, hrana server.
|
|
39
39
|
dataDir: string | null
|
|
40
40
|
|
|
41
|
+
// Custom projects directory override (default: <dataDir>/projects).
|
|
42
|
+
// When set via --projects-dir CLI flag, project create commands will
|
|
43
|
+
// create new project folders here instead of ~/.kimaki/projects/.
|
|
44
|
+
// Changes: set once at startup from --projects-dir CLI flag.
|
|
45
|
+
// Read by: config.ts getProjectsDir().
|
|
46
|
+
projectsDir: string | null
|
|
47
|
+
|
|
41
48
|
// Default output verbosity for sessions when no channel-level override
|
|
42
49
|
// exists in the DB. Controls which tool outputs are shown in Discord.
|
|
43
50
|
// Changes: set once at startup from --verbosity CLI flag.
|
|
@@ -107,6 +114,7 @@ export type KimakiState = {
|
|
|
107
114
|
|
|
108
115
|
export const store = createStore<KimakiState>(() => ({
|
|
109
116
|
dataDir: null,
|
|
117
|
+
projectsDir: null,
|
|
110
118
|
defaultVerbosity: 'text_and_essential_tools',
|
|
111
119
|
defaultMentionMode: false,
|
|
112
120
|
critiqueEnabled: true,
|
package/src/system-message.ts
CHANGED
|
@@ -56,6 +56,18 @@ bunx critique --web "Short title describing the changes" --filter "src/config.ts
|
|
|
56
56
|
|
|
57
57
|
The string after \`--web\` becomes the diff page title — make it reflect what the changes do (e.g. "Add retry logic to API client", "Fix auth timeout bug").
|
|
58
58
|
|
|
59
|
+
### fetching user comments from critique diffs
|
|
60
|
+
|
|
61
|
+
Users can add line-level comments (annotations) on any critique diff page via the Agentation widget (bottom-right corner of the diff page). To read those comments:
|
|
62
|
+
|
|
63
|
+
\`\`\`bash
|
|
64
|
+
curl https://critique.work/v/<id>/annotations
|
|
65
|
+
\`\`\`
|
|
66
|
+
|
|
67
|
+
Returns \`text/markdown\` with each annotation showing the file, line, and comment text.
|
|
68
|
+
Use this when the user says they left comments on a critique diff and you need to read them.
|
|
69
|
+
You can also use WebFetch on \`https://critique.work/v/<id>/annotations\` to get the markdown directly.
|
|
70
|
+
|
|
59
71
|
### about critique
|
|
60
72
|
|
|
61
73
|
critique is an open source tool (MIT license) at https://github.com/remorses/critique.
|
|
@@ -134,7 +146,7 @@ Use random tunnel IDs by default. Only pass \`-t\` when exposing a service that
|
|
|
134
146
|
tmux new-session -d -s myapp-dev
|
|
135
147
|
|
|
136
148
|
# Run the dev server with kimaki tunnel inside the session
|
|
137
|
-
tmux send-keys -t myapp-dev "kimaki tunnel -p 3000 -- pnpm dev" Enter
|
|
149
|
+
tmux send-keys -t myapp-dev "kimaki tunnel --kill -p 3000 -- pnpm dev" Enter
|
|
138
150
|
\`\`\`
|
|
139
151
|
|
|
140
152
|
### getting the tunnel URL
|
|
@@ -149,15 +161,15 @@ tmux capture-pane -t myapp-dev -p | grep -i "tunnel"
|
|
|
149
161
|
\`\`\`bash
|
|
150
162
|
# Next.js project
|
|
151
163
|
tmux new-session -d -s projectname-nextjs-dev-3000
|
|
152
|
-
tmux send-keys -t nextjs-dev "kimaki tunnel -p 3000 -- pnpm dev" Enter
|
|
164
|
+
tmux send-keys -t nextjs-dev "kimaki tunnel --kill -p 3000 -- pnpm dev" Enter
|
|
153
165
|
|
|
154
166
|
# Vite project on port 5173
|
|
155
167
|
tmux new-session -d -s vite-dev-5173
|
|
156
|
-
tmux send-keys -t vite-dev "kimaki tunnel -p 5173 -- pnpm dev" Enter
|
|
168
|
+
tmux send-keys -t vite-dev "kimaki tunnel --kill -p 5173 -- pnpm dev" Enter
|
|
157
169
|
|
|
158
170
|
# Custom tunnel ID (only for intentionally public-safe services)
|
|
159
171
|
tmux new-session -d -s holocron-dev
|
|
160
|
-
tmux send-keys -t holocron-dev "kimaki tunnel -p 3000 -t holocron -- pnpm dev" Enter
|
|
172
|
+
tmux send-keys -t holocron-dev "kimaki tunnel --kill -p 3000 -t holocron -- pnpm dev" Enter
|
|
161
173
|
\`\`\`
|
|
162
174
|
|
|
163
175
|
### stopping the dev server
|
|
@@ -215,6 +227,17 @@ export type ThreadStartMarker = {
|
|
|
215
227
|
permissions?: string[]
|
|
216
228
|
}
|
|
217
229
|
|
|
230
|
+
export function isInjectedPromptMarker({
|
|
231
|
+
marker,
|
|
232
|
+
}: {
|
|
233
|
+
marker: ThreadStartMarker | undefined
|
|
234
|
+
}): boolean {
|
|
235
|
+
if (!marker) {
|
|
236
|
+
return false
|
|
237
|
+
}
|
|
238
|
+
return Boolean(marker.cliThreadPrompt || marker.start)
|
|
239
|
+
}
|
|
240
|
+
|
|
218
241
|
export type AgentInfo = {
|
|
219
242
|
name: string
|
|
220
243
|
description?: string
|
package/src/task-runner.ts
CHANGED
|
@@ -56,7 +56,7 @@ async function executeThreadScheduledTask({
|
|
|
56
56
|
payload: Extract<ScheduledTaskPayload, { kind: 'thread' }>
|
|
57
57
|
}): Promise<void | Error> {
|
|
58
58
|
const marker: ThreadStartMarker = {
|
|
59
|
-
|
|
59
|
+
start: true,
|
|
60
60
|
scheduledKind: task.schedule_kind,
|
|
61
61
|
scheduledTaskId: task.id,
|
|
62
62
|
...(payload.agent ? { agent: payload.agent } : {}),
|
|
@@ -485,21 +485,16 @@ e2eTest('thread message queue ordering', () => {
|
|
|
485
485
|
await waitForFooterMessage({
|
|
486
486
|
discord,
|
|
487
487
|
threadId: thread.id,
|
|
488
|
-
timeout:
|
|
488
|
+
timeout: 8_000,
|
|
489
489
|
afterMessageIncludes: 'beta',
|
|
490
490
|
afterAuthorId: TEST_USER_ID,
|
|
491
491
|
})
|
|
492
492
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
--- from: user (queue-tester)
|
|
499
|
-
Reply with exactly: beta
|
|
500
|
-
--- from: assistant (TestBot)
|
|
501
|
-
*project ⋅ main ⋅ Ns ⋅ N% ⋅ deterministic-v2*"
|
|
502
|
-
`)
|
|
493
|
+
const timeline = await th.text()
|
|
494
|
+
expect(timeline).toContain('Reply with exactly: alpha')
|
|
495
|
+
expect(timeline).toContain('Reply with exactly: beta')
|
|
496
|
+
expect(timeline).toContain('⬥ ok')
|
|
497
|
+
expect(timeline).toContain('*project ⋅ main ⋅')
|
|
503
498
|
// User B's message must appear before the new bot response
|
|
504
499
|
const userBIndex = after.findIndex((m) => {
|
|
505
500
|
return (
|
|
@@ -519,7 +514,7 @@ e2eTest('thread message queue ordering', () => {
|
|
|
519
514
|
const newBotReply = afterBotMessages[afterBotMessages.length - 1]!
|
|
520
515
|
expect(newBotReply.content.trim().length).toBeGreaterThan(0)
|
|
521
516
|
},
|
|
522
|
-
|
|
517
|
+
12_000,
|
|
523
518
|
)
|
|
524
519
|
|
|
525
520
|
test(
|
|
@@ -1000,11 +995,10 @@ e2eTest('thread message queue ordering', () => {
|
|
|
1000
995
|
Reply with exactly: echo
|
|
1001
996
|
--- from: assistant (TestBot)
|
|
1002
997
|
*project ⋅ main ⋅ Ns ⋅ N% ⋅ deterministic-v2*
|
|
998
|
+
⬥ ok
|
|
1003
999
|
--- from: user (queue-tester)
|
|
1004
1000
|
Reply with exactly: foxtrot
|
|
1005
1001
|
--- from: assistant (TestBot)
|
|
1006
|
-
⬥ ok
|
|
1007
|
-
⬥ ok
|
|
1008
1002
|
*project ⋅ main ⋅ Ns ⋅ N% ⋅ deterministic-v2*"
|
|
1009
1003
|
`)
|
|
1010
1004
|
expect(userEchoIndex).toBeGreaterThan(-1)
|
package/src/tools.ts
CHANGED
|
@@ -14,11 +14,16 @@
|
|
|
14
14
|
// Poll timeouts: 4s max, 100ms interval.
|
|
15
15
|
|
|
16
16
|
import { describe, test, expect } from 'vitest'
|
|
17
|
+
import fs from 'node:fs'
|
|
18
|
+
import path from 'node:path'
|
|
17
19
|
import {
|
|
18
20
|
setupQueueAdvancedSuite,
|
|
19
21
|
TEST_USER_ID,
|
|
20
22
|
} from './queue-advanced-e2e-setup.js'
|
|
21
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
waitForBotMessageContaining,
|
|
25
|
+
waitForFooterMessage,
|
|
26
|
+
} from './test-utils.js'
|
|
22
27
|
import { getThreadSession } from './database.js'
|
|
23
28
|
import { initializeOpencodeForDirectory } from './opencode.js'
|
|
24
29
|
|
|
@@ -37,30 +42,36 @@ e2eTest('/undo sets revert state and cleans up on next prompt', () => {
|
|
|
37
42
|
test(
|
|
38
43
|
'undo sets revert state, next message cleans up reverted messages',
|
|
39
44
|
async () => {
|
|
45
|
+
const markerPath = path.join(
|
|
46
|
+
ctx.directories.projectDirectory,
|
|
47
|
+
'tmp',
|
|
48
|
+
'undo-marker.txt',
|
|
49
|
+
)
|
|
50
|
+
|
|
40
51
|
// 1. Send a message and wait for complete session (footer)
|
|
41
52
|
await ctx.discord
|
|
42
53
|
.channel(TEXT_CHANNEL_ID)
|
|
43
54
|
.user(TEST_USER_ID)
|
|
44
55
|
.sendMessage({
|
|
45
|
-
content: '
|
|
56
|
+
content: 'UNDO_FILE_MARKER',
|
|
46
57
|
})
|
|
47
58
|
|
|
48
59
|
const thread = await ctx.discord
|
|
49
60
|
.channel(TEXT_CHANNEL_ID)
|
|
50
61
|
.waitForThread({
|
|
51
|
-
timeout:
|
|
62
|
+
timeout: 8_000,
|
|
52
63
|
predicate: (t) => {
|
|
53
|
-
return t.name === '
|
|
64
|
+
return t.name === 'UNDO_FILE_MARKER'
|
|
54
65
|
},
|
|
55
66
|
})
|
|
56
67
|
|
|
57
68
|
const th = ctx.discord.thread(thread.id)
|
|
58
|
-
await th.waitForBotReply({ timeout:
|
|
69
|
+
await th.waitForBotReply({ timeout: 8_000 })
|
|
59
70
|
|
|
60
71
|
await waitForFooterMessage({
|
|
61
72
|
discord: ctx.discord,
|
|
62
73
|
threadId: thread.id,
|
|
63
|
-
timeout:
|
|
74
|
+
timeout: 8_000,
|
|
64
75
|
})
|
|
65
76
|
|
|
66
77
|
// 2. Get session ID and verify it has messages
|
|
@@ -91,6 +102,7 @@ e2eTest('/undo sets revert state and cleans up on next prompt', () => {
|
|
|
91
102
|
)
|
|
92
103
|
expect(beforeUserMessages.length).toBeGreaterThan(0)
|
|
93
104
|
expect(beforeAssistantMessages.length).toBeGreaterThan(0)
|
|
105
|
+
expect(fs.existsSync(markerPath)).toBe(true)
|
|
94
106
|
|
|
95
107
|
// Verify no revert state yet
|
|
96
108
|
const beforeSession = await getClient().session.get({
|
|
@@ -109,23 +121,12 @@ e2eTest('/undo sets revert state and cleans up on next prompt', () => {
|
|
|
109
121
|
})
|
|
110
122
|
expect(undoAck).toBeDefined()
|
|
111
123
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return m.id === undoAck.messageId
|
|
119
|
-
})
|
|
120
|
-
if (undoMessage && undoMessage.content.length > 0) {
|
|
121
|
-
break
|
|
122
|
-
}
|
|
123
|
-
await new Promise((r) => {
|
|
124
|
-
setTimeout(r, 100)
|
|
125
|
-
})
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
124
|
+
await waitForBotMessageContaining({
|
|
125
|
+
discord: ctx.discord,
|
|
126
|
+
threadId: thread.id,
|
|
127
|
+
text: 'Undone - reverted last assistant message',
|
|
128
|
+
timeout: 8_000,
|
|
129
|
+
})
|
|
129
130
|
// 4. Verify session now has revert state set
|
|
130
131
|
const afterSession = await getClient().session.get({
|
|
131
132
|
sessionID: sessionId!,
|
|
@@ -149,7 +150,7 @@ e2eTest('/undo sets revert state and cleans up on next prompt', () => {
|
|
|
149
150
|
await waitForFooterMessage({
|
|
150
151
|
discord: ctx.discord,
|
|
151
152
|
threadId: thread.id,
|
|
152
|
-
timeout:
|
|
153
|
+
timeout: 8_000,
|
|
153
154
|
afterMessageIncludes: 'after-undo-message',
|
|
154
155
|
})
|
|
155
156
|
|
|
@@ -190,9 +191,10 @@ e2eTest('/undo sets revert state and cleans up on next prompt', () => {
|
|
|
190
191
|
// 7. Snapshot the Discord thread
|
|
191
192
|
expect(await th.text()).toMatchInlineSnapshot(`
|
|
192
193
|
"--- from: user (undo-tester)
|
|
193
|
-
|
|
194
|
+
UNDO_FILE_MARKER
|
|
194
195
|
--- from: assistant (TestBot)
|
|
195
|
-
⬥
|
|
196
|
+
⬥ creating undo file
|
|
197
|
+
⬥ undo file created
|
|
196
198
|
*project ⋅ main ⋅ Ns ⋅ N% ⋅ deterministic-v2*
|
|
197
199
|
Undone - reverted last assistant message
|
|
198
200
|
--- from: user (undo-tester)
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
-
|
|
4
|
-
case `uname` in
|
|
5
|
-
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
-
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
-
basedir=`cygpath -w "$basedir"`
|
|
8
|
-
fi
|
|
9
|
-
;;
|
|
10
|
-
esac
|
|
11
|
-
|
|
12
|
-
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/esbuild@0.24.2/node_modules/esbuild/bin/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/esbuild@0.24.2/node_modules/esbuild/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/esbuild@0.24.2/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/node_modules"
|
|
14
|
-
else
|
|
15
|
-
export NODE_PATH="/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/esbuild@0.24.2/node_modules/esbuild/bin/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/esbuild@0.24.2/node_modules/esbuild/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/esbuild@0.24.2/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
-
fi
|
|
17
|
-
if [ -x "$basedir/node" ]; then
|
|
18
|
-
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/esbuild@0.24.2/node_modules/esbuild/bin/esbuild" "$@"
|
|
19
|
-
else
|
|
20
|
-
exec node "$basedir/../../../../node_modules/.pnpm/esbuild@0.24.2/node_modules/esbuild/bin/esbuild" "$@"
|
|
21
|
-
fi
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
-
|
|
4
|
-
case `uname` in
|
|
5
|
-
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
-
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
-
basedir=`cygpath -w "$basedir"`
|
|
8
|
-
fi
|
|
9
|
-
;;
|
|
10
|
-
esac
|
|
11
|
-
|
|
12
|
-
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/node_modules"
|
|
14
|
-
else
|
|
15
|
-
export NODE_PATH="/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
-
fi
|
|
17
|
-
if [ -x "$basedir/node" ]; then
|
|
18
|
-
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/tsc" "$@"
|
|
19
|
-
else
|
|
20
|
-
exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/tsc" "$@"
|
|
21
|
-
fi
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
-
|
|
4
|
-
case `uname` in
|
|
5
|
-
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
-
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
-
basedir=`cygpath -w "$basedir"`
|
|
8
|
-
fi
|
|
9
|
-
;;
|
|
10
|
-
esac
|
|
11
|
-
|
|
12
|
-
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/node_modules"
|
|
14
|
-
else
|
|
15
|
-
export NODE_PATH="/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/typescript@5.9.2/node_modules:/Users/morse/Documents/GitHub/kimakivoice/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
-
fi
|
|
17
|
-
if [ -x "$basedir/node" ]; then
|
|
18
|
-
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/tsserver" "$@"
|
|
19
|
-
else
|
|
20
|
-
exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/tsserver" "$@"
|
|
21
|
-
fi
|