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.
Files changed (264) hide show
  1. package/LICENSE +21 -0
  2. package/dist/anthropic-auth-plugin.js +7 -0
  3. package/dist/cli.js +51 -7
  4. package/dist/commands/abort.js +5 -16
  5. package/dist/commands/action-buttons.js +3 -3
  6. package/dist/commands/add-project.js +1 -1
  7. package/dist/commands/ask-question.js +3 -3
  8. package/dist/commands/context-usage.js +1 -1
  9. package/dist/commands/create-new-project.js +1 -1
  10. package/dist/commands/fork.js +11 -8
  11. package/dist/commands/merge-worktree.js +1 -1
  12. package/dist/commands/new-worktree.js +63 -44
  13. package/dist/commands/remove-project.js +1 -1
  14. package/dist/commands/resume.js +11 -8
  15. package/dist/commands/screenshare.js +14 -6
  16. package/dist/commands/screenshare.test.js +20 -0
  17. package/dist/commands/session.js +1 -1
  18. package/dist/commands/undo-redo.js +91 -7
  19. package/dist/commands/user-command.js +1 -1
  20. package/dist/config.js +16 -1
  21. package/dist/database.js +53 -2
  22. package/dist/db.js +6 -0
  23. package/dist/discord-bot.js +48 -85
  24. package/dist/discord-command-registration.js +1 -1
  25. package/dist/external-opencode-sync.js +515 -0
  26. package/dist/external-opencode-sync.test.js +151 -0
  27. package/dist/gateway-proxy.e2e.test.js +8 -5
  28. package/dist/genai.js +1 -1
  29. package/dist/generated/enums.js +4 -0
  30. package/dist/generated/internal/class.js +4 -4
  31. package/dist/generated/internal/prismaNamespace.js +1 -0
  32. package/dist/generated/internal/prismaNamespaceBrowser.js +1 -0
  33. package/dist/generated/models/external_session_pending_prompts.js +1 -0
  34. package/dist/hrana-server.js +14 -285
  35. package/dist/hrana-server.test.js +4 -2
  36. package/dist/kimaki-opencode-plugin-loading.e2e.test.js +7 -0
  37. package/dist/kimaki-opencode-plugin.js +2 -0
  38. package/dist/kitty-graphics-parser.js +3 -0
  39. package/dist/kitty-graphics-parser.test.js +276 -0
  40. package/dist/kitty-graphics-plugin.js +3 -0
  41. package/dist/markdown.js +4 -4
  42. package/dist/markdown.test.js +1 -1
  43. package/dist/message-formatting.js +54 -15
  44. package/dist/onboarding-tutorial.js +1 -1
  45. package/dist/openai-realtime.js +9 -13
  46. package/dist/opencode.js +28 -5
  47. package/dist/queue-advanced-e2e-setup.js +89 -0
  48. package/dist/queue-advanced-permissions-typing.e2e.test.js +5 -5
  49. package/dist/queue-advanced-typing.e2e.test.js +9 -22
  50. package/dist/queue-question-select-drain.e2e.test.js +117 -0
  51. package/dist/session-handler/event-stream-state.js +101 -7
  52. package/dist/session-handler/event-stream-state.test.js +7 -3
  53. package/dist/session-handler/thread-session-runtime.js +120 -9
  54. package/dist/store.js +1 -0
  55. package/dist/system-message.js +22 -4
  56. package/dist/system-message.test.js +19 -0
  57. package/dist/task-runner.js +1 -1
  58. package/dist/thread-message-queue.e2e.test.js +8 -14
  59. package/dist/tools.js +1 -1
  60. package/dist/undo-redo.e2e.test.js +20 -25
  61. package/package.json +10 -6
  62. package/schema.prisma +6 -0
  63. package/skills/errore/SKILL.md +40 -13
  64. package/skills/goke/SKILL.md +12 -0
  65. package/skills/lintcn/SKILL.md +868 -0
  66. package/skills/npm-package/SKILL.md +1 -0
  67. package/skills/proxyman/SKILL.md +215 -0
  68. package/skills/spiceflow/SKILL.md +1 -1
  69. package/skills/usecomputer/SKILL.md +339 -0
  70. package/src/ai-tool-to-genai.ts +1 -0
  71. package/src/anthropic-auth-plugin.ts +7 -0
  72. package/src/cli.ts +59 -6
  73. package/src/commands/abort.ts +6 -16
  74. package/src/commands/action-buttons.ts +5 -1
  75. package/src/commands/add-project.ts +1 -1
  76. package/src/commands/ask-question.ts +5 -2
  77. package/src/commands/context-usage.ts +1 -1
  78. package/src/commands/create-new-project.ts +1 -1
  79. package/src/commands/fork.ts +12 -11
  80. package/src/commands/merge-worktree.ts +1 -1
  81. package/src/commands/new-worktree.ts +74 -55
  82. package/src/commands/remove-project.ts +1 -1
  83. package/src/commands/resume.ts +12 -10
  84. package/src/commands/screenshare.test.ts +30 -0
  85. package/src/commands/screenshare.ts +18 -6
  86. package/src/commands/session.ts +1 -1
  87. package/src/commands/undo-redo.ts +108 -10
  88. package/src/commands/user-command.ts +1 -1
  89. package/src/config.ts +19 -1
  90. package/src/database.ts +72 -3
  91. package/src/db.ts +8 -0
  92. package/src/discord-bot.ts +58 -93
  93. package/src/discord-command-registration.ts +1 -1
  94. package/src/external-opencode-sync.ts +729 -0
  95. package/src/gateway-proxy.e2e.test.ts +9 -5
  96. package/src/genai.ts +3 -3
  97. package/src/generated/commonInputTypes.ts +34 -0
  98. package/src/generated/enums.ts +8 -0
  99. package/src/generated/internal/class.ts +4 -4
  100. package/src/generated/internal/prismaNamespace.ts +8 -0
  101. package/src/generated/internal/prismaNamespaceBrowser.ts +1 -0
  102. package/src/generated/models/thread_sessions.ts +53 -1
  103. package/src/hrana-server.test.ts +8 -2
  104. package/src/hrana-server.ts +18 -390
  105. package/src/kimaki-opencode-plugin-loading.e2e.test.ts +7 -0
  106. package/src/kimaki-opencode-plugin.ts +2 -0
  107. package/src/markdown.test.ts +1 -1
  108. package/src/markdown.ts +4 -4
  109. package/src/message-formatting.ts +66 -17
  110. package/src/onboarding-tutorial.ts +1 -1
  111. package/src/openai-realtime.ts +6 -10
  112. package/src/opencode.ts +31 -7
  113. package/src/queue-advanced-e2e-setup.ts +92 -0
  114. package/src/queue-advanced-permissions-typing.e2e.test.ts +5 -5
  115. package/src/queue-advanced-typing.e2e.test.ts +9 -22
  116. package/src/queue-question-select-drain.e2e.test.ts +149 -0
  117. package/src/schema.sql +1 -0
  118. package/src/session-handler/event-stream-state.test.ts +7 -2
  119. package/src/session-handler/event-stream-state.ts +128 -7
  120. package/src/session-handler/thread-runtime-state.ts +5 -0
  121. package/src/session-handler/thread-session-runtime.ts +153 -11
  122. package/src/store.ts +8 -0
  123. package/src/system-message.ts +27 -4
  124. package/src/task-runner.ts +1 -1
  125. package/src/thread-message-queue.e2e.test.ts +8 -14
  126. package/src/tools.ts +1 -1
  127. package/src/undo-redo.e2e.test.ts +28 -26
  128. package/skills/jitter/node_modules/.bin/esbuild +0 -21
  129. package/skills/jitter/node_modules/.bin/tsc +0 -21
  130. package/skills/jitter/node_modules/.bin/tsserver +0 -21
  131. package/skills/jitter/node_modules/typescript/LICENSE.txt +0 -55
  132. package/skills/jitter/node_modules/typescript/README.md +0 -50
  133. package/skills/jitter/node_modules/typescript/SECURITY.md +0 -41
  134. package/skills/jitter/node_modules/typescript/ThirdPartyNoticeText.txt +0 -193
  135. package/skills/jitter/node_modules/typescript/bin/tsc +0 -2
  136. package/skills/jitter/node_modules/typescript/bin/tsserver +0 -2
  137. package/skills/jitter/node_modules/typescript/lib/_tsc.js +0 -133792
  138. package/skills/jitter/node_modules/typescript/lib/_tsserver.js +0 -659
  139. package/skills/jitter/node_modules/typescript/lib/_typingsInstaller.js +0 -222
  140. package/skills/jitter/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +0 -2122
  141. package/skills/jitter/node_modules/typescript/lib/de/diagnosticMessages.generated.json +0 -2122
  142. package/skills/jitter/node_modules/typescript/lib/es/diagnosticMessages.generated.json +0 -2122
  143. package/skills/jitter/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +0 -2122
  144. package/skills/jitter/node_modules/typescript/lib/it/diagnosticMessages.generated.json +0 -2122
  145. package/skills/jitter/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +0 -2122
  146. package/skills/jitter/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +0 -2122
  147. package/skills/jitter/node_modules/typescript/lib/lib.d.ts +0 -22
  148. package/skills/jitter/node_modules/typescript/lib/lib.decorators.d.ts +0 -384
  149. package/skills/jitter/node_modules/typescript/lib/lib.decorators.legacy.d.ts +0 -22
  150. package/skills/jitter/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +0 -41
  151. package/skills/jitter/node_modules/typescript/lib/lib.dom.d.ts +0 -39429
  152. package/skills/jitter/node_modules/typescript/lib/lib.dom.iterable.d.ts +0 -571
  153. package/skills/jitter/node_modules/typescript/lib/lib.es2015.collection.d.ts +0 -147
  154. package/skills/jitter/node_modules/typescript/lib/lib.es2015.core.d.ts +0 -597
  155. package/skills/jitter/node_modules/typescript/lib/lib.es2015.d.ts +0 -28
  156. package/skills/jitter/node_modules/typescript/lib/lib.es2015.generator.d.ts +0 -77
  157. package/skills/jitter/node_modules/typescript/lib/lib.es2015.iterable.d.ts +0 -605
  158. package/skills/jitter/node_modules/typescript/lib/lib.es2015.promise.d.ts +0 -81
  159. package/skills/jitter/node_modules/typescript/lib/lib.es2015.proxy.d.ts +0 -128
  160. package/skills/jitter/node_modules/typescript/lib/lib.es2015.reflect.d.ts +0 -144
  161. package/skills/jitter/node_modules/typescript/lib/lib.es2015.symbol.d.ts +0 -46
  162. package/skills/jitter/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +0 -326
  163. package/skills/jitter/node_modules/typescript/lib/lib.es2016.array.include.d.ts +0 -116
  164. package/skills/jitter/node_modules/typescript/lib/lib.es2016.d.ts +0 -21
  165. package/skills/jitter/node_modules/typescript/lib/lib.es2016.full.d.ts +0 -23
  166. package/skills/jitter/node_modules/typescript/lib/lib.es2016.intl.d.ts +0 -31
  167. package/skills/jitter/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +0 -21
  168. package/skills/jitter/node_modules/typescript/lib/lib.es2017.d.ts +0 -26
  169. package/skills/jitter/node_modules/typescript/lib/lib.es2017.date.d.ts +0 -31
  170. package/skills/jitter/node_modules/typescript/lib/lib.es2017.full.d.ts +0 -23
  171. package/skills/jitter/node_modules/typescript/lib/lib.es2017.intl.d.ts +0 -44
  172. package/skills/jitter/node_modules/typescript/lib/lib.es2017.object.d.ts +0 -49
  173. package/skills/jitter/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +0 -135
  174. package/skills/jitter/node_modules/typescript/lib/lib.es2017.string.d.ts +0 -45
  175. package/skills/jitter/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +0 -53
  176. package/skills/jitter/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +0 -77
  177. package/skills/jitter/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +0 -53
  178. package/skills/jitter/node_modules/typescript/lib/lib.es2018.d.ts +0 -24
  179. package/skills/jitter/node_modules/typescript/lib/lib.es2018.full.d.ts +0 -24
  180. package/skills/jitter/node_modules/typescript/lib/lib.es2018.intl.d.ts +0 -83
  181. package/skills/jitter/node_modules/typescript/lib/lib.es2018.promise.d.ts +0 -30
  182. package/skills/jitter/node_modules/typescript/lib/lib.es2018.regexp.d.ts +0 -37
  183. package/skills/jitter/node_modules/typescript/lib/lib.es2019.array.d.ts +0 -79
  184. package/skills/jitter/node_modules/typescript/lib/lib.es2019.d.ts +0 -24
  185. package/skills/jitter/node_modules/typescript/lib/lib.es2019.full.d.ts +0 -24
  186. package/skills/jitter/node_modules/typescript/lib/lib.es2019.intl.d.ts +0 -23
  187. package/skills/jitter/node_modules/typescript/lib/lib.es2019.object.d.ts +0 -33
  188. package/skills/jitter/node_modules/typescript/lib/lib.es2019.string.d.ts +0 -37
  189. package/skills/jitter/node_modules/typescript/lib/lib.es2019.symbol.d.ts +0 -24
  190. package/skills/jitter/node_modules/typescript/lib/lib.es2020.bigint.d.ts +0 -765
  191. package/skills/jitter/node_modules/typescript/lib/lib.es2020.d.ts +0 -27
  192. package/skills/jitter/node_modules/typescript/lib/lib.es2020.date.d.ts +0 -42
  193. package/skills/jitter/node_modules/typescript/lib/lib.es2020.full.d.ts +0 -24
  194. package/skills/jitter/node_modules/typescript/lib/lib.es2020.intl.d.ts +0 -474
  195. package/skills/jitter/node_modules/typescript/lib/lib.es2020.number.d.ts +0 -28
  196. package/skills/jitter/node_modules/typescript/lib/lib.es2020.promise.d.ts +0 -47
  197. package/skills/jitter/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +0 -99
  198. package/skills/jitter/node_modules/typescript/lib/lib.es2020.string.d.ts +0 -44
  199. package/skills/jitter/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +0 -41
  200. package/skills/jitter/node_modules/typescript/lib/lib.es2021.d.ts +0 -23
  201. package/skills/jitter/node_modules/typescript/lib/lib.es2021.full.d.ts +0 -24
  202. package/skills/jitter/node_modules/typescript/lib/lib.es2021.intl.d.ts +0 -166
  203. package/skills/jitter/node_modules/typescript/lib/lib.es2021.promise.d.ts +0 -48
  204. package/skills/jitter/node_modules/typescript/lib/lib.es2021.string.d.ts +0 -33
  205. package/skills/jitter/node_modules/typescript/lib/lib.es2021.weakref.d.ts +0 -78
  206. package/skills/jitter/node_modules/typescript/lib/lib.es2022.array.d.ts +0 -121
  207. package/skills/jitter/node_modules/typescript/lib/lib.es2022.d.ts +0 -25
  208. package/skills/jitter/node_modules/typescript/lib/lib.es2022.error.d.ts +0 -75
  209. package/skills/jitter/node_modules/typescript/lib/lib.es2022.full.d.ts +0 -24
  210. package/skills/jitter/node_modules/typescript/lib/lib.es2022.intl.d.ts +0 -145
  211. package/skills/jitter/node_modules/typescript/lib/lib.es2022.object.d.ts +0 -26
  212. package/skills/jitter/node_modules/typescript/lib/lib.es2022.regexp.d.ts +0 -39
  213. package/skills/jitter/node_modules/typescript/lib/lib.es2022.string.d.ts +0 -25
  214. package/skills/jitter/node_modules/typescript/lib/lib.es2023.array.d.ts +0 -924
  215. package/skills/jitter/node_modules/typescript/lib/lib.es2023.collection.d.ts +0 -21
  216. package/skills/jitter/node_modules/typescript/lib/lib.es2023.d.ts +0 -22
  217. package/skills/jitter/node_modules/typescript/lib/lib.es2023.full.d.ts +0 -24
  218. package/skills/jitter/node_modules/typescript/lib/lib.es2023.intl.d.ts +0 -56
  219. package/skills/jitter/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +0 -65
  220. package/skills/jitter/node_modules/typescript/lib/lib.es2024.collection.d.ts +0 -29
  221. package/skills/jitter/node_modules/typescript/lib/lib.es2024.d.ts +0 -26
  222. package/skills/jitter/node_modules/typescript/lib/lib.es2024.full.d.ts +0 -24
  223. package/skills/jitter/node_modules/typescript/lib/lib.es2024.object.d.ts +0 -29
  224. package/skills/jitter/node_modules/typescript/lib/lib.es2024.promise.d.ts +0 -35
  225. package/skills/jitter/node_modules/typescript/lib/lib.es2024.regexp.d.ts +0 -25
  226. package/skills/jitter/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +0 -68
  227. package/skills/jitter/node_modules/typescript/lib/lib.es2024.string.d.ts +0 -29
  228. package/skills/jitter/node_modules/typescript/lib/lib.es5.d.ts +0 -4601
  229. package/skills/jitter/node_modules/typescript/lib/lib.es6.d.ts +0 -23
  230. package/skills/jitter/node_modules/typescript/lib/lib.esnext.array.d.ts +0 -35
  231. package/skills/jitter/node_modules/typescript/lib/lib.esnext.collection.d.ts +0 -96
  232. package/skills/jitter/node_modules/typescript/lib/lib.esnext.d.ts +0 -29
  233. package/skills/jitter/node_modules/typescript/lib/lib.esnext.decorators.d.ts +0 -28
  234. package/skills/jitter/node_modules/typescript/lib/lib.esnext.disposable.d.ts +0 -193
  235. package/skills/jitter/node_modules/typescript/lib/lib.esnext.error.d.ts +0 -24
  236. package/skills/jitter/node_modules/typescript/lib/lib.esnext.float16.d.ts +0 -443
  237. package/skills/jitter/node_modules/typescript/lib/lib.esnext.full.d.ts +0 -24
  238. package/skills/jitter/node_modules/typescript/lib/lib.esnext.intl.d.ts +0 -21
  239. package/skills/jitter/node_modules/typescript/lib/lib.esnext.iterator.d.ts +0 -148
  240. package/skills/jitter/node_modules/typescript/lib/lib.esnext.promise.d.ts +0 -34
  241. package/skills/jitter/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +0 -25
  242. package/skills/jitter/node_modules/typescript/lib/lib.scripthost.d.ts +0 -322
  243. package/skills/jitter/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +0 -41
  244. package/skills/jitter/node_modules/typescript/lib/lib.webworker.d.ts +0 -13150
  245. package/skills/jitter/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +0 -23
  246. package/skills/jitter/node_modules/typescript/lib/lib.webworker.iterable.d.ts +0 -340
  247. package/skills/jitter/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +0 -2122
  248. package/skills/jitter/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +0 -2122
  249. package/skills/jitter/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +0 -2122
  250. package/skills/jitter/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +0 -2122
  251. package/skills/jitter/node_modules/typescript/lib/tsc.js +0 -8
  252. package/skills/jitter/node_modules/typescript/lib/tsserver.js +0 -8
  253. package/skills/jitter/node_modules/typescript/lib/tsserverlibrary.d.ts +0 -17
  254. package/skills/jitter/node_modules/typescript/lib/tsserverlibrary.js +0 -21
  255. package/skills/jitter/node_modules/typescript/lib/typesMap.json +0 -497
  256. package/skills/jitter/node_modules/typescript/lib/typescript.d.ts +0 -11438
  257. package/skills/jitter/node_modules/typescript/lib/typescript.js +0 -200253
  258. package/skills/jitter/node_modules/typescript/lib/typingsInstaller.js +0 -8
  259. package/skills/jitter/node_modules/typescript/lib/watchGuard.js +0 -53
  260. package/skills/jitter/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +0 -2122
  261. package/skills/jitter/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +0 -2122
  262. package/skills/jitter/node_modules/typescript/node_modules/.bin/tsc +0 -21
  263. package/skills/jitter/node_modules/typescript/node_modules/.bin/tsserver +0 -21
  264. 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
- syntheticContext += `<discord-user name="${input.username}" />`
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
- syntheticContext += `<discord-user name="${input.username}" />`
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 (!('tokens' in m.info) || !m.info.tokens) {
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: queuedNext ? SILENT_MESSAGE_FLAGS : NOTIFY_MESSAGE_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,
@@ -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
@@ -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
- cliThreadPrompt: true,
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: 4_000,
488
+ timeout: 8_000,
489
489
  afterMessageIncludes: 'beta',
490
490
  afterAuthorId: TEST_USER_ID,
491
491
  })
492
492
 
493
- expect(await th.text()).toMatchInlineSnapshot(`
494
- "--- from: user (queue-tester)
495
- Reply with exactly: alpha
496
- --- from: assistant (TestBot)
497
- ok
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
- 8_000,
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
@@ -141,7 +141,7 @@ export async function getTools({
141
141
 
142
142
  try {
143
143
  const session = await getClient().session.create({
144
- title: title || message.slice(0, 50),
144
+ ...(title ? { title } : {}),
145
145
  })
146
146
 
147
147
  if (!session.data) {
@@ -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 { waitForFooterMessage } from './test-utils.js'
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: 'Reply with exactly: undo-test-message',
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: 4_000,
62
+ timeout: 8_000,
52
63
  predicate: (t) => {
53
- return t.name === 'Reply with exactly: undo-test-message'
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: 4_000 })
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: 4_000,
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
- // Wait for the undo reply to appear (deferred reply gets edited)
113
- if (undoAck.messageId) {
114
- const start = Date.now()
115
- while (Date.now() - start < 4_000) {
116
- const messages = await th.getMessages()
117
- const undoMessage = messages.find((m) => {
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: 4_000,
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
- Reply with exactly: undo-test-message
194
+ UNDO_FILE_MARKER
194
195
  --- from: assistant (TestBot)
195
- ok
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