@brianli/kimaki 0.4.72-brianli.1

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.
Files changed (328) hide show
  1. package/bin.js +2 -0
  2. package/dist/ai-tool-to-genai.js +233 -0
  3. package/dist/ai-tool-to-genai.test.js +267 -0
  4. package/dist/ai-tool.js +6 -0
  5. package/dist/bin.js +87 -0
  6. package/dist/bot-token.js +121 -0
  7. package/dist/bot-token.test.js +134 -0
  8. package/dist/channel-management.js +101 -0
  9. package/dist/cli-parsing.test.js +89 -0
  10. package/dist/cli.js +2529 -0
  11. package/dist/commands/abort.js +82 -0
  12. package/dist/commands/action-buttons.js +257 -0
  13. package/dist/commands/add-project.js +114 -0
  14. package/dist/commands/agent.js +291 -0
  15. package/dist/commands/ask-question.js +223 -0
  16. package/dist/commands/compact.js +120 -0
  17. package/dist/commands/context-usage.js +140 -0
  18. package/dist/commands/create-new-project.js +118 -0
  19. package/dist/commands/diff.js +128 -0
  20. package/dist/commands/file-upload.js +275 -0
  21. package/dist/commands/fork.js +217 -0
  22. package/dist/commands/gemini-apikey.js +70 -0
  23. package/dist/commands/login.js +490 -0
  24. package/dist/commands/mention-mode.js +51 -0
  25. package/dist/commands/merge-worktree.js +124 -0
  26. package/dist/commands/model.js +694 -0
  27. package/dist/commands/permissions.js +163 -0
  28. package/dist/commands/queue.js +217 -0
  29. package/dist/commands/remove-project.js +115 -0
  30. package/dist/commands/restart-opencode-server.js +116 -0
  31. package/dist/commands/resume.js +159 -0
  32. package/dist/commands/run-command.js +79 -0
  33. package/dist/commands/session-id.js +78 -0
  34. package/dist/commands/session.js +192 -0
  35. package/dist/commands/share.js +80 -0
  36. package/dist/commands/types.js +2 -0
  37. package/dist/commands/undo-redo.js +159 -0
  38. package/dist/commands/unset-model.js +152 -0
  39. package/dist/commands/upgrade.js +42 -0
  40. package/dist/commands/user-command.js +148 -0
  41. package/dist/commands/verbosity.js +60 -0
  42. package/dist/commands/worktree-settings.js +50 -0
  43. package/dist/commands/worktree.js +299 -0
  44. package/dist/condense-memory.js +33 -0
  45. package/dist/config.js +110 -0
  46. package/dist/database.js +1050 -0
  47. package/dist/db.js +159 -0
  48. package/dist/db.test.js +49 -0
  49. package/dist/discord-api.js +28 -0
  50. package/dist/discord-auth.js +231 -0
  51. package/dist/discord-auth.test.js +80 -0
  52. package/dist/discord-bot.js +997 -0
  53. package/dist/discord-utils.js +560 -0
  54. package/dist/discord-utils.test.js +115 -0
  55. package/dist/errors.js +167 -0
  56. package/dist/escape-backticks.test.js +429 -0
  57. package/dist/format-tables.js +122 -0
  58. package/dist/format-tables.test.js +199 -0
  59. package/dist/forum-sync/config.js +79 -0
  60. package/dist/forum-sync/discord-operations.js +154 -0
  61. package/dist/forum-sync/index.js +5 -0
  62. package/dist/forum-sync/markdown.js +117 -0
  63. package/dist/forum-sync/sync-to-discord.js +417 -0
  64. package/dist/forum-sync/sync-to-files.js +190 -0
  65. package/dist/forum-sync/types.js +53 -0
  66. package/dist/forum-sync/watchers.js +307 -0
  67. package/dist/gateway-consumer.js +232 -0
  68. package/dist/gateway-consumer.test.js +18 -0
  69. package/dist/genai-worker-wrapper.js +111 -0
  70. package/dist/genai-worker.js +311 -0
  71. package/dist/genai.js +232 -0
  72. package/dist/generated/browser.js +17 -0
  73. package/dist/generated/client.js +35 -0
  74. package/dist/generated/commonInputTypes.js +10 -0
  75. package/dist/generated/enums.js +30 -0
  76. package/dist/generated/internal/class.js +41 -0
  77. package/dist/generated/internal/prismaNamespace.js +239 -0
  78. package/dist/generated/internal/prismaNamespaceBrowser.js +209 -0
  79. package/dist/generated/models/bot_api_keys.js +1 -0
  80. package/dist/generated/models/bot_tokens.js +1 -0
  81. package/dist/generated/models/channel_agents.js +1 -0
  82. package/dist/generated/models/channel_directories.js +1 -0
  83. package/dist/generated/models/channel_mention_mode.js +1 -0
  84. package/dist/generated/models/channel_models.js +1 -0
  85. package/dist/generated/models/channel_verbosity.js +1 -0
  86. package/dist/generated/models/channel_worktrees.js +1 -0
  87. package/dist/generated/models/forum_sync_configs.js +1 -0
  88. package/dist/generated/models/global_models.js +1 -0
  89. package/dist/generated/models/ipc_requests.js +1 -0
  90. package/dist/generated/models/part_messages.js +1 -0
  91. package/dist/generated/models/scheduled_tasks.js +1 -0
  92. package/dist/generated/models/session_agents.js +1 -0
  93. package/dist/generated/models/session_models.js +1 -0
  94. package/dist/generated/models/session_start_sources.js +1 -0
  95. package/dist/generated/models/thread_sessions.js +1 -0
  96. package/dist/generated/models/thread_worktrees.js +1 -0
  97. package/dist/generated/models.js +1 -0
  98. package/dist/heap-monitor.js +95 -0
  99. package/dist/hrana-server.js +416 -0
  100. package/dist/hrana-server.test.js +368 -0
  101. package/dist/image-utils.js +112 -0
  102. package/dist/interaction-handler.js +327 -0
  103. package/dist/ipc-polling.js +251 -0
  104. package/dist/kimaki-digital-twin.e2e.test.js +165 -0
  105. package/dist/limit-heading-depth.js +25 -0
  106. package/dist/limit-heading-depth.test.js +105 -0
  107. package/dist/logger.js +160 -0
  108. package/dist/markdown.js +342 -0
  109. package/dist/markdown.test.js +253 -0
  110. package/dist/message-formatting.js +433 -0
  111. package/dist/message-formatting.test.js +73 -0
  112. package/dist/openai-realtime.js +228 -0
  113. package/dist/opencode-plugin-loading.e2e.test.js +91 -0
  114. package/dist/opencode-plugin.js +536 -0
  115. package/dist/opencode-plugin.test.js +98 -0
  116. package/dist/opencode.js +409 -0
  117. package/dist/privacy-sanitizer.js +105 -0
  118. package/dist/runtime-mode.js +51 -0
  119. package/dist/runtime-mode.test.js +115 -0
  120. package/dist/sentry.js +127 -0
  121. package/dist/session-handler/state.js +151 -0
  122. package/dist/session-handler.js +1874 -0
  123. package/dist/session-search.js +100 -0
  124. package/dist/session-search.test.js +40 -0
  125. package/dist/startup-service.js +153 -0
  126. package/dist/system-message.js +499 -0
  127. package/dist/task-runner.js +282 -0
  128. package/dist/task-schedule.js +191 -0
  129. package/dist/task-schedule.test.js +71 -0
  130. package/dist/thinking-utils.js +35 -0
  131. package/dist/thread-message-queue.e2e.test.js +781 -0
  132. package/dist/tools.js +359 -0
  133. package/dist/unnest-code-blocks.js +136 -0
  134. package/dist/unnest-code-blocks.test.js +641 -0
  135. package/dist/upgrade.js +114 -0
  136. package/dist/utils.js +109 -0
  137. package/dist/voice-handler.js +606 -0
  138. package/dist/voice.js +304 -0
  139. package/dist/voice.test.js +187 -0
  140. package/dist/wait-session.js +94 -0
  141. package/dist/worker-types.js +4 -0
  142. package/dist/worktree-utils.js +727 -0
  143. package/dist/xml.js +92 -0
  144. package/dist/xml.test.js +32 -0
  145. package/package.json +82 -0
  146. package/schema.prisma +246 -0
  147. package/skills/batch/SKILL.md +87 -0
  148. package/skills/critique/SKILL.md +129 -0
  149. package/skills/errore/SKILL.md +589 -0
  150. package/skills/goke/.prettierrc +5 -0
  151. package/skills/goke/CHANGELOG.md +40 -0
  152. package/skills/goke/LICENSE +21 -0
  153. package/skills/goke/README.md +666 -0
  154. package/skills/goke/SKILL.md +458 -0
  155. package/skills/goke/package.json +43 -0
  156. package/skills/goke/src/__test__/coerce.test.ts +411 -0
  157. package/skills/goke/src/__test__/index.test.ts +1798 -0
  158. package/skills/goke/src/__test__/types.test-d.ts +111 -0
  159. package/skills/goke/src/coerce.ts +547 -0
  160. package/skills/goke/src/goke.ts +1362 -0
  161. package/skills/goke/src/index.ts +16 -0
  162. package/skills/goke/src/mri.ts +164 -0
  163. package/skills/goke/tsconfig.json +15 -0
  164. package/skills/jitter/EDITOR.md +219 -0
  165. package/skills/jitter/EXPORT-INTERNALS.md +309 -0
  166. package/skills/jitter/SKILL.md +158 -0
  167. package/skills/jitter/jitter-clipboard.json +1042 -0
  168. package/skills/jitter/package.json +14 -0
  169. package/skills/jitter/tsconfig.json +15 -0
  170. package/skills/jitter/utils/actions.ts +212 -0
  171. package/skills/jitter/utils/export.ts +114 -0
  172. package/skills/jitter/utils/index.ts +141 -0
  173. package/skills/jitter/utils/snapshot.ts +154 -0
  174. package/skills/jitter/utils/traverse.ts +246 -0
  175. package/skills/jitter/utils/types.ts +279 -0
  176. package/skills/jitter/utils/wait.ts +133 -0
  177. package/skills/playwriter/SKILL.md +31 -0
  178. package/skills/security-review/SKILL.md +208 -0
  179. package/skills/simplify/SKILL.md +58 -0
  180. package/skills/termcast/SKILL.md +945 -0
  181. package/skills/tuistory/SKILL.md +250 -0
  182. package/skills/zustand-centralized-state/SKILL.md +582 -0
  183. package/src/__snapshots__/compact-session-context-no-system.md +35 -0
  184. package/src/__snapshots__/compact-session-context.md +41 -0
  185. package/src/__snapshots__/first-session-no-info.md +17 -0
  186. package/src/__snapshots__/first-session-with-info.md +23 -0
  187. package/src/__snapshots__/session-1.md +17 -0
  188. package/src/__snapshots__/session-2.md +5871 -0
  189. package/src/__snapshots__/session-3.md +17 -0
  190. package/src/__snapshots__/session-with-tools.md +5871 -0
  191. package/src/ai-tool-to-genai.test.ts +296 -0
  192. package/src/ai-tool-to-genai.ts +282 -0
  193. package/src/ai-tool.ts +39 -0
  194. package/src/bin.ts +108 -0
  195. package/src/bot-token.test.ts +171 -0
  196. package/src/bot-token.ts +159 -0
  197. package/src/channel-management.ts +172 -0
  198. package/src/cli-parsing.test.ts +132 -0
  199. package/src/cli.ts +3605 -0
  200. package/src/commands/abort.ts +112 -0
  201. package/src/commands/action-buttons.ts +376 -0
  202. package/src/commands/add-project.ts +152 -0
  203. package/src/commands/agent.ts +404 -0
  204. package/src/commands/ask-question.ts +330 -0
  205. package/src/commands/compact.ts +157 -0
  206. package/src/commands/context-usage.ts +199 -0
  207. package/src/commands/create-new-project.ts +179 -0
  208. package/src/commands/diff.ts +165 -0
  209. package/src/commands/file-upload.ts +389 -0
  210. package/src/commands/fork.ts +320 -0
  211. package/src/commands/gemini-apikey.ts +104 -0
  212. package/src/commands/login.ts +634 -0
  213. package/src/commands/mention-mode.ts +77 -0
  214. package/src/commands/merge-worktree.ts +177 -0
  215. package/src/commands/model.ts +961 -0
  216. package/src/commands/permissions.ts +261 -0
  217. package/src/commands/queue.ts +296 -0
  218. package/src/commands/remove-project.ts +155 -0
  219. package/src/commands/restart-opencode-server.ts +162 -0
  220. package/src/commands/resume.ts +242 -0
  221. package/src/commands/run-command.ts +123 -0
  222. package/src/commands/session-id.ts +109 -0
  223. package/src/commands/session.ts +250 -0
  224. package/src/commands/share.ts +106 -0
  225. package/src/commands/types.ts +25 -0
  226. package/src/commands/undo-redo.ts +221 -0
  227. package/src/commands/unset-model.ts +189 -0
  228. package/src/commands/upgrade.ts +52 -0
  229. package/src/commands/user-command.ts +193 -0
  230. package/src/commands/verbosity.ts +88 -0
  231. package/src/commands/worktree-settings.ts +79 -0
  232. package/src/commands/worktree.ts +431 -0
  233. package/src/condense-memory.ts +36 -0
  234. package/src/config.ts +148 -0
  235. package/src/database.ts +1530 -0
  236. package/src/db.test.ts +60 -0
  237. package/src/db.ts +190 -0
  238. package/src/discord-api.ts +35 -0
  239. package/src/discord-bot.ts +1316 -0
  240. package/src/discord-utils.test.ts +132 -0
  241. package/src/discord-utils.ts +767 -0
  242. package/src/errors.ts +213 -0
  243. package/src/escape-backticks.test.ts +469 -0
  244. package/src/format-tables.test.ts +223 -0
  245. package/src/format-tables.ts +145 -0
  246. package/src/forum-sync/config.ts +92 -0
  247. package/src/forum-sync/discord-operations.ts +241 -0
  248. package/src/forum-sync/index.ts +9 -0
  249. package/src/forum-sync/markdown.ts +176 -0
  250. package/src/forum-sync/sync-to-discord.ts +595 -0
  251. package/src/forum-sync/sync-to-files.ts +294 -0
  252. package/src/forum-sync/types.ts +175 -0
  253. package/src/forum-sync/watchers.ts +454 -0
  254. package/src/genai-worker-wrapper.ts +164 -0
  255. package/src/genai-worker.ts +386 -0
  256. package/src/genai.ts +321 -0
  257. package/src/generated/browser.ts +109 -0
  258. package/src/generated/client.ts +131 -0
  259. package/src/generated/commonInputTypes.ts +512 -0
  260. package/src/generated/enums.ts +46 -0
  261. package/src/generated/internal/class.ts +362 -0
  262. package/src/generated/internal/prismaNamespace.ts +2251 -0
  263. package/src/generated/internal/prismaNamespaceBrowser.ts +308 -0
  264. package/src/generated/models/bot_api_keys.ts +1288 -0
  265. package/src/generated/models/bot_tokens.ts +1577 -0
  266. package/src/generated/models/channel_agents.ts +1256 -0
  267. package/src/generated/models/channel_directories.ts +2104 -0
  268. package/src/generated/models/channel_mention_mode.ts +1300 -0
  269. package/src/generated/models/channel_models.ts +1288 -0
  270. package/src/generated/models/channel_verbosity.ts +1224 -0
  271. package/src/generated/models/channel_worktrees.ts +1308 -0
  272. package/src/generated/models/forum_sync_configs.ts +1452 -0
  273. package/src/generated/models/global_models.ts +1288 -0
  274. package/src/generated/models/ipc_requests.ts +1485 -0
  275. package/src/generated/models/part_messages.ts +1302 -0
  276. package/src/generated/models/scheduled_tasks.ts +2320 -0
  277. package/src/generated/models/session_agents.ts +1086 -0
  278. package/src/generated/models/session_models.ts +1114 -0
  279. package/src/generated/models/session_start_sources.ts +1408 -0
  280. package/src/generated/models/thread_sessions.ts +1599 -0
  281. package/src/generated/models/thread_worktrees.ts +1352 -0
  282. package/src/generated/models.ts +29 -0
  283. package/src/heap-monitor.ts +121 -0
  284. package/src/hrana-server.test.ts +428 -0
  285. package/src/hrana-server.ts +547 -0
  286. package/src/image-utils.ts +149 -0
  287. package/src/interaction-handler.ts +461 -0
  288. package/src/ipc-polling.ts +325 -0
  289. package/src/kimaki-digital-twin.e2e.test.ts +201 -0
  290. package/src/limit-heading-depth.test.ts +116 -0
  291. package/src/limit-heading-depth.ts +26 -0
  292. package/src/logger.ts +203 -0
  293. package/src/markdown.test.ts +360 -0
  294. package/src/markdown.ts +410 -0
  295. package/src/message-formatting.test.ts +81 -0
  296. package/src/message-formatting.ts +549 -0
  297. package/src/openai-realtime.ts +362 -0
  298. package/src/opencode-plugin-loading.e2e.test.ts +112 -0
  299. package/src/opencode-plugin.test.ts +108 -0
  300. package/src/opencode-plugin.ts +652 -0
  301. package/src/opencode.ts +554 -0
  302. package/src/privacy-sanitizer.ts +142 -0
  303. package/src/schema.sql +158 -0
  304. package/src/sentry.ts +137 -0
  305. package/src/session-handler/state.ts +232 -0
  306. package/src/session-handler.ts +2668 -0
  307. package/src/session-search.test.ts +50 -0
  308. package/src/session-search.ts +148 -0
  309. package/src/startup-service.ts +200 -0
  310. package/src/system-message.ts +568 -0
  311. package/src/task-runner.ts +425 -0
  312. package/src/task-schedule.test.ts +84 -0
  313. package/src/task-schedule.ts +287 -0
  314. package/src/thinking-utils.ts +61 -0
  315. package/src/thread-message-queue.e2e.test.ts +997 -0
  316. package/src/tools.ts +432 -0
  317. package/src/unnest-code-blocks.test.ts +679 -0
  318. package/src/unnest-code-blocks.ts +168 -0
  319. package/src/upgrade.ts +127 -0
  320. package/src/utils.ts +145 -0
  321. package/src/voice-handler.ts +852 -0
  322. package/src/voice.test.ts +219 -0
  323. package/src/voice.ts +444 -0
  324. package/src/wait-session.ts +147 -0
  325. package/src/worker-types.ts +64 -0
  326. package/src/worktree-utils.ts +988 -0
  327. package/src/xml.test.ts +38 -0
  328. package/src/xml.ts +121 -0
package/src/schema.sql ADDED
@@ -0,0 +1,158 @@
1
+ -- This file is generated by pnpm generate:sql. Do not edit manually.
2
+ CREATE TABLE IF NOT EXISTS "thread_sessions" (
3
+ "thread_id" TEXT NOT NULL PRIMARY KEY,
4
+ "session_id" TEXT NOT NULL,
5
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP
6
+ );
7
+ CREATE TABLE IF NOT EXISTS "part_messages" (
8
+ "part_id" TEXT NOT NULL PRIMARY KEY,
9
+ "message_id" TEXT NOT NULL,
10
+ "thread_id" TEXT NOT NULL,
11
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
12
+ CONSTRAINT "part_messages_thread_id_fkey" FOREIGN KEY ("thread_id") REFERENCES "thread_sessions" ("thread_id") ON DELETE RESTRICT ON UPDATE CASCADE
13
+ );
14
+ CREATE TABLE IF NOT EXISTS "bot_tokens" (
15
+ "app_id" TEXT NOT NULL PRIMARY KEY,
16
+ "token" TEXT NOT NULL,
17
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP
18
+ );
19
+ CREATE TABLE IF NOT EXISTS "channel_directories" (
20
+ "channel_id" TEXT NOT NULL PRIMARY KEY,
21
+ "directory" TEXT NOT NULL,
22
+ "channel_type" TEXT NOT NULL,
23
+ "app_id" TEXT,
24
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
25
+ CONSTRAINT "channel_directories_app_id_fkey" FOREIGN KEY ("app_id") REFERENCES "bot_tokens" ("app_id") ON DELETE SET NULL ON UPDATE CASCADE
26
+ );
27
+ CREATE TABLE IF NOT EXISTS "bot_api_keys" (
28
+ "app_id" TEXT NOT NULL PRIMARY KEY,
29
+ "gemini_api_key" TEXT,
30
+ "openai_api_key" TEXT,
31
+ "xai_api_key" TEXT,
32
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
33
+ CONSTRAINT "bot_api_keys_app_id_fkey" FOREIGN KEY ("app_id") REFERENCES "bot_tokens" ("app_id") ON DELETE RESTRICT ON UPDATE CASCADE
34
+ );
35
+ CREATE TABLE IF NOT EXISTS "thread_worktrees" (
36
+ "thread_id" TEXT NOT NULL PRIMARY KEY,
37
+ "worktree_name" TEXT NOT NULL,
38
+ "worktree_directory" TEXT,
39
+ "project_directory" TEXT NOT NULL,
40
+ "status" TEXT DEFAULT 'pending',
41
+ "error_message" TEXT,
42
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
43
+ CONSTRAINT "thread_worktrees_thread_id_fkey" FOREIGN KEY ("thread_id") REFERENCES "thread_sessions" ("thread_id") ON DELETE RESTRICT ON UPDATE CASCADE
44
+ );
45
+ CREATE TABLE IF NOT EXISTS "channel_models" (
46
+ "channel_id" TEXT NOT NULL PRIMARY KEY,
47
+ "model_id" TEXT NOT NULL,
48
+ "variant" TEXT,
49
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
50
+ "updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
51
+ CONSTRAINT "channel_models_channel_id_fkey" FOREIGN KEY ("channel_id") REFERENCES "channel_directories" ("channel_id") ON DELETE RESTRICT ON UPDATE CASCADE
52
+ );
53
+ CREATE TABLE IF NOT EXISTS "session_models" (
54
+ "session_id" TEXT NOT NULL PRIMARY KEY,
55
+ "model_id" TEXT NOT NULL,
56
+ "variant" TEXT,
57
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP
58
+ );
59
+ CREATE TABLE IF NOT EXISTS "channel_agents" (
60
+ "channel_id" TEXT NOT NULL PRIMARY KEY,
61
+ "agent_name" TEXT NOT NULL,
62
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
63
+ "updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
64
+ CONSTRAINT "channel_agents_channel_id_fkey" FOREIGN KEY ("channel_id") REFERENCES "channel_directories" ("channel_id") ON DELETE RESTRICT ON UPDATE CASCADE
65
+ );
66
+ CREATE TABLE IF NOT EXISTS "session_agents" (
67
+ "session_id" TEXT NOT NULL PRIMARY KEY,
68
+ "agent_name" TEXT NOT NULL,
69
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP
70
+ );
71
+ CREATE TABLE IF NOT EXISTS "channel_worktrees" (
72
+ "channel_id" TEXT NOT NULL PRIMARY KEY,
73
+ "enabled" INTEGER NOT NULL DEFAULT 0,
74
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
75
+ "updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
76
+ CONSTRAINT "channel_worktrees_channel_id_fkey" FOREIGN KEY ("channel_id") REFERENCES "channel_directories" ("channel_id") ON DELETE RESTRICT ON UPDATE CASCADE
77
+ );
78
+ CREATE TABLE IF NOT EXISTS "channel_verbosity" (
79
+ "channel_id" TEXT NOT NULL PRIMARY KEY,
80
+ "verbosity" TEXT NOT NULL DEFAULT 'tools-and-text',
81
+ "updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
82
+ CONSTRAINT "channel_verbosity_channel_id_fkey" FOREIGN KEY ("channel_id") REFERENCES "channel_directories" ("channel_id") ON DELETE RESTRICT ON UPDATE CASCADE
83
+ );
84
+ CREATE TABLE IF NOT EXISTS "channel_mention_mode" (
85
+ "channel_id" TEXT NOT NULL PRIMARY KEY,
86
+ "enabled" INTEGER NOT NULL DEFAULT 0,
87
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
88
+ "updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
89
+ CONSTRAINT "channel_mention_mode_channel_id_fkey" FOREIGN KEY ("channel_id") REFERENCES "channel_directories" ("channel_id") ON DELETE RESTRICT ON UPDATE CASCADE
90
+ );
91
+ CREATE TABLE IF NOT EXISTS "global_models" (
92
+ "app_id" TEXT NOT NULL PRIMARY KEY,
93
+ "model_id" TEXT NOT NULL,
94
+ "variant" TEXT,
95
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
96
+ "updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
97
+ CONSTRAINT "global_models_app_id_fkey" FOREIGN KEY ("app_id") REFERENCES "bot_tokens" ("app_id") ON DELETE RESTRICT ON UPDATE CASCADE
98
+ );
99
+ CREATE TABLE IF NOT EXISTS "scheduled_tasks" (
100
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
101
+ "status" TEXT NOT NULL DEFAULT 'planned',
102
+ "schedule_kind" TEXT NOT NULL,
103
+ "run_at" DATETIME,
104
+ "cron_expr" TEXT,
105
+ "timezone" TEXT,
106
+ "next_run_at" DATETIME NOT NULL,
107
+ "running_started_at" DATETIME,
108
+ "last_run_at" DATETIME,
109
+ "last_error" TEXT,
110
+ "attempts" INTEGER NOT NULL DEFAULT 0,
111
+ "payload_json" TEXT NOT NULL,
112
+ "prompt_preview" TEXT NOT NULL,
113
+ "channel_id" TEXT,
114
+ "thread_id" TEXT,
115
+ "session_id" TEXT,
116
+ "project_directory" TEXT,
117
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
118
+ "updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
119
+ CONSTRAINT "scheduled_tasks_channel_id_fkey" FOREIGN KEY ("channel_id") REFERENCES "channel_directories" ("channel_id") ON DELETE SET NULL ON UPDATE CASCADE,
120
+ CONSTRAINT "scheduled_tasks_thread_id_fkey" FOREIGN KEY ("thread_id") REFERENCES "thread_sessions" ("thread_id") ON DELETE SET NULL ON UPDATE CASCADE
121
+ );
122
+ CREATE TABLE sqlite_sequence(name,seq);
123
+ CREATE TABLE IF NOT EXISTS "session_start_sources" (
124
+ "session_id" TEXT NOT NULL PRIMARY KEY,
125
+ "schedule_kind" TEXT NOT NULL,
126
+ "scheduled_task_id" INTEGER,
127
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
128
+ "updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
129
+ CONSTRAINT "session_start_sources_scheduled_task_id_fkey" FOREIGN KEY ("scheduled_task_id") REFERENCES "scheduled_tasks" ("id") ON DELETE SET NULL ON UPDATE CASCADE
130
+ );
131
+ CREATE TABLE IF NOT EXISTS "forum_sync_configs" (
132
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
133
+ "app_id" TEXT NOT NULL,
134
+ "forum_channel_id" TEXT NOT NULL,
135
+ "output_dir" TEXT NOT NULL,
136
+ "direction" TEXT NOT NULL DEFAULT 'bidirectional',
137
+ "created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
138
+ "updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
139
+ CONSTRAINT "forum_sync_configs_app_id_fkey" FOREIGN KEY ("app_id") REFERENCES "bot_tokens" ("app_id") ON DELETE CASCADE ON UPDATE CASCADE
140
+ );
141
+ CREATE TABLE IF NOT EXISTS "ipc_requests" (
142
+ "id" TEXT NOT NULL PRIMARY KEY,
143
+ "type" TEXT NOT NULL,
144
+ "session_id" TEXT NOT NULL,
145
+ "thread_id" TEXT NOT NULL,
146
+ "payload" TEXT NOT NULL,
147
+ "response" TEXT,
148
+ "status" TEXT NOT NULL DEFAULT 'pending',
149
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
150
+ "updated_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
151
+ CONSTRAINT "ipc_requests_thread_id_fkey" FOREIGN KEY ("thread_id") REFERENCES "thread_sessions" ("thread_id") ON DELETE RESTRICT ON UPDATE CASCADE
152
+ );
153
+ CREATE INDEX "scheduled_tasks_status_next_run_at_idx" ON "scheduled_tasks"("status", "next_run_at");
154
+ CREATE INDEX "scheduled_tasks_channel_id_status_idx" ON "scheduled_tasks"("channel_id", "status");
155
+ CREATE INDEX "scheduled_tasks_thread_id_status_idx" ON "scheduled_tasks"("thread_id", "status");
156
+ CREATE INDEX "session_start_sources_scheduled_task_id_idx" ON "session_start_sources"("scheduled_task_id");
157
+ CREATE UNIQUE INDEX "forum_sync_configs_app_id_forum_channel_id_key" ON "forum_sync_configs"("app_id", "forum_channel_id");
158
+ CREATE INDEX "ipc_requests_status_created_at_idx" ON "ipc_requests"("status", "created_at");
package/src/sentry.ts ADDED
@@ -0,0 +1,137 @@
1
+ // Sentry error tracking initialization and notifyError helper.
2
+ // Uses @sentry/node for the Node.js runtime (bot process, plugin process, worker threads).
3
+ // Must be initialized early in both the bot process (cli.ts) and plugin process
4
+ // (opencode-plugin.ts). The plugin process receives the DSN via KIMAKI_SENTRY_DSN env var.
5
+
6
+ import * as Sentry from '@sentry/node'
7
+ import * as errore from 'errore'
8
+ import { createRequire } from 'node:module'
9
+ import { sanitizeSensitiveText, sanitizeUnknownValue } from './privacy-sanitizer.js'
10
+
11
+ // DSN placeholder — replace with your Sentry project DSN.
12
+ // Users can also set KIMAKI_SENTRY_DSN env var.
13
+ const HARDCODED_DSN = 'https://3b87e21ac01cb9c66225719ea65111d2@o4510952031715328.ingest.us.sentry.io/4510952088469504'
14
+
15
+ function readKimakiVersion(): string {
16
+ try {
17
+ const require = createRequire(import.meta.url)
18
+ const pkg = require('../package.json') as { version?: string }
19
+ const version = pkg.version
20
+ if (!version) {
21
+ return 'unknown'
22
+ }
23
+ return version
24
+ } catch {
25
+ return 'unknown'
26
+ }
27
+ }
28
+
29
+ const kimakiVersion = readKimakiVersion()
30
+ const kimakiRelease = `kimaki@${kimakiVersion}`
31
+
32
+ let initialized = false
33
+
34
+ /**
35
+ * Initialize Sentry. Call once at process startup.
36
+ * No-op if DSN is empty or --no-sentry was passed.
37
+ */
38
+ export function initSentry({ dsn }: { dsn?: string } = {}): void {
39
+ if (process.env.KIMAKI_SENTRY_DISABLED === '1') {
40
+ return
41
+ }
42
+
43
+ const resolvedDsn = dsn || process.env.KIMAKI_SENTRY_DSN || HARDCODED_DSN
44
+ if (!resolvedDsn || initialized) {
45
+ return
46
+ }
47
+
48
+ Sentry.init({
49
+ dsn: resolvedDsn,
50
+ release: kimakiRelease,
51
+ integrations: [],
52
+ tracesSampleRate: 0,
53
+ sendDefaultPii: false,
54
+ profilesSampleRate: 0,
55
+ beforeSend(event, hint) {
56
+ // Skip in development — too noisy, errors appear in terminal
57
+ if (process.env.NODE_ENV === 'development') {
58
+ return null
59
+ }
60
+ // Skip abort errors — walks the cause chain so wrapped aborts are caught
61
+ if (errore.isAbortError(hint.originalException)) {
62
+ return null
63
+ }
64
+
65
+ try {
66
+ const sanitizedEvent = sanitizeUnknownValue(event, {
67
+ redactPaths: false,
68
+ })
69
+ if (sanitizedEvent && typeof sanitizedEvent === 'object') {
70
+ return sanitizedEvent as typeof event
71
+ }
72
+ } catch {
73
+ return event
74
+ }
75
+ return event
76
+ },
77
+ })
78
+
79
+ Sentry.setTag('kimaki_version', kimakiVersion)
80
+
81
+ initialized = true
82
+ }
83
+
84
+ /**
85
+ * Report an unexpected error to Sentry.
86
+ * Safe to call even if Sentry is not initialized.
87
+ * Fire-and-forget only: use `void notifyError(error, msg)` and never await it.
88
+ * This helper must never throw.
89
+ * Use this at terminal error handlers — the "last catch" in a chain
90
+ * where the error would otherwise be invisible.
91
+ */
92
+ export function notifyError(error: unknown, msg?: string): void {
93
+ try {
94
+ if (!initialized) {
95
+ return
96
+ }
97
+
98
+ const safeMsg = (() => {
99
+ if (!msg) {
100
+ return undefined
101
+ }
102
+ try {
103
+ return sanitizeSensitiveText(msg, { redactPaths: false })
104
+ } catch {
105
+ return msg
106
+ }
107
+ })()
108
+ const safeError = (() => {
109
+ try {
110
+ return sanitizeUnknownValue(error, { redactPaths: false })
111
+ } catch {
112
+ return error
113
+ }
114
+ })()
115
+
116
+ Sentry.captureException(error, {
117
+ tags: { kimaki_version: kimakiVersion },
118
+ extra: { msg: safeMsg, kimakiVersion, error: safeError },
119
+ })
120
+ void Sentry.flush(1000).catch(() => {
121
+ return
122
+ })
123
+ } catch {
124
+ return
125
+ }
126
+ }
127
+
128
+ /**
129
+ * User-readable error class. Messages from AppError instances
130
+ * are forwarded to the user as-is; regular Error messages may be obfuscated.
131
+ */
132
+ export class AppError extends Error {
133
+ constructor(message: string) {
134
+ super(message)
135
+ this.name = 'AppError'
136
+ }
137
+ }
@@ -0,0 +1,232 @@
1
+ // Session handler run-state store and transitions.
2
+ // Centralizes prompt/idle race state so interrupt handling stays consistent.
3
+
4
+ import { createStore, type StoreApi } from 'zustand/vanilla'
5
+
6
+ export type MainRunPhase =
7
+ | 'waiting-dispatch'
8
+ | 'collecting-baseline'
9
+ | 'dispatching'
10
+ | 'prompt-resolved'
11
+ | 'finished'
12
+ | 'aborted'
13
+
14
+ export type MainIdleState = 'none' | 'deferred'
15
+
16
+ export type MainRunState = {
17
+ phase: MainRunPhase
18
+ idleState: MainIdleState
19
+ baselineAssistantIds: Set<string>
20
+ currentAssistantMessageId: string | undefined
21
+ eventSeq: number
22
+ evidenceSeq: number | undefined
23
+ deferredIdleSeq: number | undefined
24
+ }
25
+
26
+ export type MainRunStore = StoreApi<MainRunState>
27
+
28
+ export type MainSessionIdleDecision =
29
+ | 'deferred'
30
+ | 'ignore-no-evidence'
31
+ | 'process'
32
+
33
+ export type DeferredIdleDecision =
34
+ | 'none'
35
+ | 'ignore-no-evidence'
36
+ | 'ignore-before-evidence'
37
+ | 'process'
38
+
39
+ function initialMainRunState(): MainRunState {
40
+ return {
41
+ phase: 'waiting-dispatch',
42
+ idleState: 'none',
43
+ baselineAssistantIds: new Set<string>(),
44
+ currentAssistantMessageId: undefined,
45
+ eventSeq: 0,
46
+ evidenceSeq: undefined,
47
+ deferredIdleSeq: undefined,
48
+ }
49
+ }
50
+
51
+ export function createMainRunStore(): MainRunStore {
52
+ return createStore<MainRunState>(() => {
53
+ return initialMainRunState()
54
+ })
55
+ }
56
+
57
+ export function beginPromptCycle({ store }: { store: MainRunStore }): void {
58
+ store.setState((state) => {
59
+ return {
60
+ ...state,
61
+ phase: 'collecting-baseline',
62
+ idleState: 'none',
63
+ baselineAssistantIds: new Set<string>(),
64
+ currentAssistantMessageId: undefined,
65
+ eventSeq: 0,
66
+ evidenceSeq: undefined,
67
+ deferredIdleSeq: undefined,
68
+ }
69
+ })
70
+ }
71
+
72
+ export function setBaselineAssistantIds({
73
+ store,
74
+ messageIds,
75
+ }: {
76
+ store: MainRunStore
77
+ messageIds: Set<string>
78
+ }): void {
79
+ store.setState((state) => {
80
+ return {
81
+ ...state,
82
+ baselineAssistantIds: new Set<string>(messageIds),
83
+ }
84
+ })
85
+ }
86
+
87
+ export function markDispatching({ store }: { store: MainRunStore }): void {
88
+ store.setState((state) => {
89
+ return {
90
+ ...state,
91
+ phase: 'dispatching',
92
+ }
93
+ })
94
+ }
95
+
96
+ export function markCurrentPromptEvidence({
97
+ store,
98
+ messageId,
99
+ }: {
100
+ store: MainRunStore
101
+ messageId: string
102
+ }): void {
103
+ store.setState((state) => {
104
+ const eventSeq = state.eventSeq + 1
105
+ const canTrackCurrentPrompt =
106
+ state.phase === 'dispatching' || state.phase === 'prompt-resolved'
107
+ if (!canTrackCurrentPrompt) {
108
+ return {
109
+ ...state,
110
+ eventSeq,
111
+ }
112
+ }
113
+ if (state.baselineAssistantIds.has(messageId)) {
114
+ return {
115
+ ...state,
116
+ eventSeq,
117
+ }
118
+ }
119
+ return {
120
+ ...state,
121
+ eventSeq,
122
+ currentAssistantMessageId: messageId,
123
+ evidenceSeq: state.evidenceSeq ?? eventSeq,
124
+ }
125
+ })
126
+ }
127
+
128
+ export function handleMainSessionIdle({
129
+ store,
130
+ }: {
131
+ store: MainRunStore
132
+ }): MainSessionIdleDecision {
133
+ const state = store.getState()
134
+ const idleSeq = state.eventSeq + 1
135
+
136
+ if (state.phase !== 'prompt-resolved') {
137
+ store.setState((current) => {
138
+ return {
139
+ ...current,
140
+ eventSeq: idleSeq,
141
+ idleState: 'deferred',
142
+ deferredIdleSeq: idleSeq,
143
+ }
144
+ })
145
+ return 'deferred'
146
+ }
147
+
148
+ if (!state.currentAssistantMessageId) {
149
+ store.setState((current) => {
150
+ return {
151
+ ...current,
152
+ eventSeq: idleSeq,
153
+ }
154
+ })
155
+ return 'ignore-no-evidence'
156
+ }
157
+
158
+ store.setState((current) => {
159
+ return {
160
+ ...current,
161
+ eventSeq: idleSeq,
162
+ }
163
+ })
164
+ return 'process'
165
+ }
166
+
167
+ export function markPromptResolvedAndConsumeDeferredIdle({
168
+ store,
169
+ }: {
170
+ store: MainRunStore
171
+ }): DeferredIdleDecision {
172
+ const state = store.getState()
173
+
174
+ const nextState: MainRunState = {
175
+ ...state,
176
+ phase: 'prompt-resolved',
177
+ }
178
+
179
+ if (state.idleState !== 'deferred') {
180
+ store.setState(nextState)
181
+ return 'none'
182
+ }
183
+
184
+ nextState.idleState = 'none'
185
+ nextState.deferredIdleSeq = undefined
186
+
187
+ if (!state.currentAssistantMessageId) {
188
+ store.setState(nextState)
189
+ return 'ignore-no-evidence'
190
+ }
191
+
192
+ if (
193
+ typeof state.deferredIdleSeq === 'number' &&
194
+ typeof state.evidenceSeq === 'number' &&
195
+ state.deferredIdleSeq <= state.evidenceSeq
196
+ ) {
197
+ store.setState(nextState)
198
+ return 'ignore-before-evidence'
199
+ }
200
+
201
+ store.setState(nextState)
202
+ return 'process'
203
+ }
204
+
205
+ export function markFinished({ store }: { store: MainRunStore }): void {
206
+ store.setState((state) => {
207
+ return {
208
+ ...state,
209
+ phase: 'finished',
210
+ }
211
+ })
212
+ }
213
+
214
+ export function markAborted({ store }: { store: MainRunStore }): void {
215
+ store.setState((state) => {
216
+ if (state.phase === 'finished') {
217
+ return state
218
+ }
219
+ return {
220
+ ...state,
221
+ phase: 'aborted',
222
+ }
223
+ })
224
+ }
225
+
226
+ export function hasCurrentPromptEvidence({
227
+ store,
228
+ }: {
229
+ store: MainRunStore
230
+ }): boolean {
231
+ return Boolean(store.getState().currentAssistantMessageId)
232
+ }