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
|
@@ -19,7 +19,7 @@ import { getRuntime } from './session-handler/thread-session-runtime.js';
|
|
|
19
19
|
import { setBotToken, initDatabase, closeDatabase, setChannelDirectory, setChannelVerbosity, } from './database.js';
|
|
20
20
|
import { startHranaServer, stopHranaServer } from './hrana-server.js';
|
|
21
21
|
import { initializeOpencodeForDirectory, restartOpencodeServer, stopOpencodeServer, } from './opencode.js';
|
|
22
|
-
import { chooseLockPort, cleanupTestSessions, initTestGitRepo, waitForBotMessageContaining, waitForBotReplyAfterUserMessage, } from './test-utils.js';
|
|
22
|
+
import { chooseLockPort, cleanupTestSessions, initTestGitRepo, isFooterMessage, waitForBotMessageContaining, waitForBotReplyAfterUserMessage, } from './test-utils.js';
|
|
23
23
|
const TEST_USER_ID = '200000000000000888';
|
|
24
24
|
const TEXT_CHANNEL_ID = '200000000000000889';
|
|
25
25
|
function createRunDirectories() {
|
|
@@ -202,10 +202,10 @@ describe('runtime lifecycle', () => {
|
|
|
202
202
|
fs.rmSync(directories.dataDir, { recursive: true, force: true });
|
|
203
203
|
}
|
|
204
204
|
}, 5_000);
|
|
205
|
-
test('
|
|
206
|
-
// Sends A, waits for full completion (footer), sends B
|
|
207
|
-
//
|
|
208
|
-
//
|
|
205
|
+
test('two sequential completions reuse same runtime and listener', async () => {
|
|
206
|
+
// Sends A, waits for full completion (footer), then sends B and waits
|
|
207
|
+
// for its footer. Proves the listener stays alive across full run cycles
|
|
208
|
+
// without any interrupt/queue involvement.
|
|
209
209
|
// This is the "calm" path — no abort, no queue, just sequential use.
|
|
210
210
|
// 1. Send first message → thread created, session established
|
|
211
211
|
await discord.channel(TEXT_CHANNEL_ID).user(TEST_USER_ID).sendMessage({
|
|
@@ -251,47 +251,20 @@ describe('runtime lifecycle', () => {
|
|
|
251
251
|
});
|
|
252
252
|
// Same runtime instance — listener was not recreated
|
|
253
253
|
const runtimeAfterB = getRuntime(thread.id);
|
|
254
|
-
expect(runtimeAfterB).toBe(runtimeAfterA);
|
|
255
|
-
// 3. Send C after B fully completed
|
|
256
|
-
await th.user(TEST_USER_ID).sendMessage({
|
|
257
|
-
content: 'Reply with exactly: seq-gamma',
|
|
258
|
-
});
|
|
259
|
-
await waitForBotReplyAfterUserMessage({
|
|
260
|
-
discord,
|
|
261
|
-
threadId: thread.id,
|
|
262
|
-
userId: TEST_USER_ID,
|
|
263
|
-
userMessageIncludes: 'seq-gamma',
|
|
264
|
-
timeout: 4_000,
|
|
265
|
-
});
|
|
266
|
-
await waitForBotMessageContaining({
|
|
267
|
-
discord,
|
|
268
|
-
threadId: thread.id,
|
|
269
|
-
userId: TEST_USER_ID,
|
|
270
|
-
text: '*project',
|
|
271
|
-
afterUserMessageIncludes: 'seq-gamma',
|
|
272
|
-
timeout: 4_000,
|
|
273
|
-
});
|
|
274
|
-
// Still the same runtime — three full cycles, one runtime, one listener
|
|
275
|
-
const runtimeAfterC = getRuntime(thread.id);
|
|
276
254
|
expect(await th.text()).toMatchInlineSnapshot(`
|
|
277
255
|
"--- from: user (lifecycle-tester)
|
|
278
256
|
Reply with exactly: seq-alpha
|
|
279
257
|
--- from: assistant (TestBot)
|
|
280
|
-
*using deterministic-provider/deterministic-v2*
|
|
281
|
-
|
|
282
|
-
*project ⋅ main ⋅
|
|
258
|
+
> *using deterministic-provider/deterministic-v2*
|
|
259
|
+
> ok
|
|
260
|
+
> *project ⋅ main ⋅ <1s ⋅ 0% ⋅ deterministic-v2* <@200000000000000888>
|
|
283
261
|
--- from: user (lifecycle-tester)
|
|
284
262
|
Reply with exactly: seq-beta
|
|
285
263
|
--- from: assistant (TestBot)
|
|
286
|
-
|
|
287
|
-
*project ⋅ main ⋅
|
|
288
|
-
--- from: user (lifecycle-tester)
|
|
289
|
-
Reply with exactly: seq-gamma
|
|
290
|
-
--- from: assistant (TestBot)
|
|
291
|
-
⬥ ok
|
|
292
|
-
*project ⋅ main ⋅ Ns ⋅ N% ⋅ deterministic-v2*"
|
|
264
|
+
> ok
|
|
265
|
+
> *project ⋅ main ⋅ <1s ⋅ 0% ⋅ deterministic-v2* <@200000000000000888>"
|
|
293
266
|
`);
|
|
294
|
-
expect(
|
|
267
|
+
expect(runtimeAfterB).toBe(runtimeAfterA);
|
|
295
268
|
}, 15_000);
|
|
296
269
|
test('footer includes context percentage and model id', async () => {
|
|
297
270
|
const prompt = 'Reply with exactly: footer-check';
|
|
@@ -313,10 +286,7 @@ describe('runtime lifecycle', () => {
|
|
|
313
286
|
});
|
|
314
287
|
const messages = await discord.thread(thread.id).getMessages();
|
|
315
288
|
const footerMessage = messages.find((message) => {
|
|
316
|
-
if (message
|
|
317
|
-
return false;
|
|
318
|
-
}
|
|
319
|
-
if (!message.content.startsWith('*')) {
|
|
289
|
+
if (!isFooterMessage({ message, botUserId: discord.botUserId })) {
|
|
320
290
|
return false;
|
|
321
291
|
}
|
|
322
292
|
return message.content.includes('deterministic-v2') && message.content.includes('%');
|
|
@@ -325,9 +295,9 @@ describe('runtime lifecycle', () => {
|
|
|
325
295
|
"--- from: user (lifecycle-tester)
|
|
326
296
|
Reply with exactly: footer-check
|
|
327
297
|
--- from: assistant (TestBot)
|
|
328
|
-
*using deterministic-provider/deterministic-v2*
|
|
329
|
-
|
|
330
|
-
*project ⋅ main ⋅
|
|
298
|
+
> *using deterministic-provider/deterministic-v2*
|
|
299
|
+
> ok
|
|
300
|
+
> *project ⋅ main ⋅ <1s ⋅ 0% ⋅ deterministic-v2* <@200000000000000888>"
|
|
331
301
|
`);
|
|
332
302
|
expect(footerMessage).toBeDefined();
|
|
333
303
|
if (!footerMessage) {
|
|
@@ -383,14 +353,14 @@ describe('runtime lifecycle', () => {
|
|
|
383
353
|
"--- from: user (lifecycle-tester)
|
|
384
354
|
Reply with exactly: reconnect-alpha
|
|
385
355
|
--- from: assistant (TestBot)
|
|
386
|
-
*using deterministic-provider/deterministic-v2*
|
|
387
|
-
|
|
388
|
-
*project ⋅ main ⋅
|
|
356
|
+
> *using deterministic-provider/deterministic-v2*
|
|
357
|
+
> ok
|
|
358
|
+
> *project ⋅ main ⋅ <1s ⋅ 0% ⋅ deterministic-v2* <@200000000000000888>
|
|
389
359
|
--- from: user (lifecycle-tester)
|
|
390
360
|
Reply with exactly: reconnect-beta
|
|
391
361
|
--- from: assistant (TestBot)
|
|
392
|
-
|
|
393
|
-
*project ⋅ main ⋅
|
|
362
|
+
> ok
|
|
363
|
+
> *project ⋅ main ⋅ <1s ⋅ 0% ⋅ deterministic-v2* <@200000000000000888>"
|
|
394
364
|
`);
|
|
395
365
|
const runtimeAfterRestart = getRuntime(thread.id);
|
|
396
366
|
expect(runtimeAfterRestart).toBe(runtimeBeforeRestart);
|
|
@@ -420,7 +390,7 @@ describe('runtime lifecycle', () => {
|
|
|
420
390
|
"--- from: user (lifecycle-tester)
|
|
421
391
|
Reply with exactly: footer-high-usage
|
|
422
392
|
--- from: assistant (TestBot)
|
|
423
|
-
*using deterministic-provider/deterministic-v2*"
|
|
393
|
+
> *using deterministic-provider/deterministic-v2*"
|
|
424
394
|
`);
|
|
425
395
|
const threadText = await discord.thread(thread.id).text();
|
|
426
396
|
expect(threadText).not.toContain('⬦ context usage');
|
package/dist/schema.js
CHANGED
|
@@ -27,6 +27,10 @@ export const thread_sessions = sqliteCore.sqliteTable('thread_sessions', {
|
|
|
27
27
|
// Survives bot restarts so child multi-turn system prompts keep the parent ID.
|
|
28
28
|
parent_session_id: sqliteCore.text('parent_session_id'),
|
|
29
29
|
created_at: datetime('created_at').default(orm.sql `CURRENT_TIMESTAMP`),
|
|
30
|
+
// Bumped on every (re)binding of a session to this thread. /resume can map one
|
|
31
|
+
// session to several threads, so session_id -> thread_id needs a tiebreaker.
|
|
32
|
+
// Without it the reverse lookup is arbitrary and tools can target a dead thread.
|
|
33
|
+
updated_at: datetime('updated_at').default(orm.sql `CURRENT_TIMESTAMP`).$onUpdate(() => new Date()),
|
|
30
34
|
});
|
|
31
35
|
export const session_events = sqliteCore.sqliteTable('session_events', {
|
|
32
36
|
id: sqliteCore.integer('id', { mode: 'number' }).primaryKey({ autoIncrement: true }).notNull(),
|
|
@@ -42,7 +46,7 @@ export const session_events = sqliteCore.sqliteTable('session_events', {
|
|
|
42
46
|
export const part_messages = sqliteCore.sqliteTable('part_messages', {
|
|
43
47
|
part_id: sqliteCore.text('part_id').primaryKey().notNull(),
|
|
44
48
|
message_id: sqliteCore.text('message_id').notNull(),
|
|
45
|
-
thread_id: sqliteCore.text('thread_id').notNull().references(() => thread_sessions.thread_id, { onUpdate: 'cascade' }),
|
|
49
|
+
thread_id: sqliteCore.text('thread_id').notNull().references(() => thread_sessions.thread_id, { onDelete: 'cascade', onUpdate: 'cascade' }),
|
|
46
50
|
created_at: datetime('created_at').default(orm.sql `CURRENT_TIMESTAMP`),
|
|
47
51
|
});
|
|
48
52
|
export const bot_tokens = sqliteCore.sqliteTable('bot_tokens', {
|
|
@@ -198,6 +202,35 @@ export const forum_sync_configs = sqliteCore.sqliteTable('forum_sync_configs', {
|
|
|
198
202
|
}, (table) => [
|
|
199
203
|
sqliteCore.uniqueIndex('forum_sync_configs_app_id_forum_channel_id_key').on(table.app_id, table.forum_channel_id),
|
|
200
204
|
]);
|
|
205
|
+
// Durable "wake this session later" rows for the kimaki_sleep tool.
|
|
206
|
+
//
|
|
207
|
+
// Delivery is at-least-once, and ingress makes it at-most-once-per-turn:
|
|
208
|
+
//
|
|
209
|
+
// planned ──► consumed cancelled / failed are terminal
|
|
210
|
+
// ▲ │
|
|
211
|
+
// └───┘ retried until ingress consumes it
|
|
212
|
+
//
|
|
213
|
+
// A row stays `planned` until ingress turns the wake into a turn, so ANY loss
|
|
214
|
+
// (crash before posting, crash after posting, missed gateway event) is covered
|
|
215
|
+
// by the same retry. `delivery_id` is the Discord message nonce, so a retry
|
|
216
|
+
// returns the existing message instead of waking the session twice.
|
|
217
|
+
//
|
|
218
|
+
// There is no thread_id: the owning thread is resolved from session_id at wake
|
|
219
|
+
// time, so a session rebound by /resume wakes in its current thread.
|
|
220
|
+
export const session_sleeps = sqliteCore.sqliteTable('session_sleeps', {
|
|
221
|
+
session_id: sqliteCore.text('session_id').primaryKey().notNull(),
|
|
222
|
+
wake_at: datetime('wake_at').notNull(),
|
|
223
|
+
reason: sqliteCore.text('reason'),
|
|
224
|
+
status: sqliteCore.text('status', { enum: ['planned', 'consumed', 'cancelled', 'failed'] }).notNull().default('planned'),
|
|
225
|
+
// Regenerated per sleep occurrence. Doubles as the Discord nonce and as a
|
|
226
|
+
// generation guard so a stale in-flight wake cannot mutate a newer sleep.
|
|
227
|
+
delivery_id: sqliteCore.text('delivery_id').notNull().$defaultFn(() => crypto.randomUUID()),
|
|
228
|
+
attempts: sqliteCore.integer('attempts', { mode: 'number' }).notNull().default(0),
|
|
229
|
+
last_attempt_at: datetime('last_attempt_at'),
|
|
230
|
+
created_at: datetime('created_at').default(orm.sql `CURRENT_TIMESTAMP`),
|
|
231
|
+
}, (table) => [
|
|
232
|
+
sqliteCore.index('session_sleeps_status_wake_at_idx').on(table.status, table.wake_at),
|
|
233
|
+
]);
|
|
201
234
|
export const ipc_requests = sqliteCore.sqliteTable('ipc_requests', {
|
|
202
235
|
id: sqliteCore.text('id').primaryKey().notNull().$defaultFn(() => crypto.randomUUID()),
|
|
203
236
|
type: sqliteCore.text('type', { enum: ['file_upload', 'action_buttons'] }).notNull(),
|
|
@@ -232,6 +265,7 @@ export const relations = defineRelations({
|
|
|
232
265
|
scheduled_task_runs,
|
|
233
266
|
session_start_sources,
|
|
234
267
|
forum_sync_configs,
|
|
268
|
+
session_sleeps,
|
|
235
269
|
ipc_requests,
|
|
236
270
|
}, (r) => ({
|
|
237
271
|
thread_sessions: {
|