kimaki 0.4.46 → 0.4.48

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 (85) hide show
  1. package/dist/cli.js +69 -21
  2. package/dist/commands/abort.js +4 -2
  3. package/dist/commands/add-project.js +2 -2
  4. package/dist/commands/agent.js +4 -4
  5. package/dist/commands/ask-question.js +9 -8
  6. package/dist/commands/compact.js +126 -0
  7. package/dist/commands/create-new-project.js +60 -30
  8. package/dist/commands/fork.js +3 -3
  9. package/dist/commands/merge-worktree.js +23 -10
  10. package/dist/commands/model.js +5 -5
  11. package/dist/commands/permissions.js +5 -3
  12. package/dist/commands/queue.js +2 -2
  13. package/dist/commands/remove-project.js +2 -2
  14. package/dist/commands/resume.js +2 -2
  15. package/dist/commands/session.js +6 -3
  16. package/dist/commands/share.js +2 -2
  17. package/dist/commands/undo-redo.js +2 -2
  18. package/dist/commands/user-command.js +2 -2
  19. package/dist/commands/verbosity.js +5 -5
  20. package/dist/commands/worktree-settings.js +2 -2
  21. package/dist/commands/worktree.js +18 -8
  22. package/dist/config.js +7 -0
  23. package/dist/database.js +10 -7
  24. package/dist/discord-bot.js +30 -12
  25. package/dist/discord-utils.js +2 -2
  26. package/dist/genai-worker-wrapper.js +3 -3
  27. package/dist/genai-worker.js +2 -2
  28. package/dist/genai.js +2 -2
  29. package/dist/interaction-handler.js +6 -2
  30. package/dist/logger.js +57 -9
  31. package/dist/markdown.js +2 -2
  32. package/dist/message-formatting.js +91 -6
  33. package/dist/openai-realtime.js +2 -2
  34. package/dist/opencode.js +19 -25
  35. package/dist/session-handler.js +89 -29
  36. package/dist/system-message.js +11 -9
  37. package/dist/tools.js +3 -2
  38. package/dist/utils.js +1 -0
  39. package/dist/voice-handler.js +2 -2
  40. package/dist/voice.js +2 -2
  41. package/dist/worktree-utils.js +91 -7
  42. package/dist/xml.js +2 -2
  43. package/package.json +3 -3
  44. package/src/cli.ts +108 -21
  45. package/src/commands/abort.ts +4 -2
  46. package/src/commands/add-project.ts +2 -2
  47. package/src/commands/agent.ts +4 -4
  48. package/src/commands/ask-question.ts +9 -8
  49. package/src/commands/compact.ts +148 -0
  50. package/src/commands/create-new-project.ts +87 -36
  51. package/src/commands/fork.ts +3 -3
  52. package/src/commands/merge-worktree.ts +47 -10
  53. package/src/commands/model.ts +5 -5
  54. package/src/commands/permissions.ts +6 -2
  55. package/src/commands/queue.ts +2 -2
  56. package/src/commands/remove-project.ts +2 -2
  57. package/src/commands/resume.ts +2 -2
  58. package/src/commands/session.ts +6 -3
  59. package/src/commands/share.ts +2 -2
  60. package/src/commands/undo-redo.ts +2 -2
  61. package/src/commands/user-command.ts +2 -2
  62. package/src/commands/verbosity.ts +5 -5
  63. package/src/commands/worktree-settings.ts +2 -2
  64. package/src/commands/worktree.ts +20 -7
  65. package/src/config.ts +14 -0
  66. package/src/database.ts +13 -7
  67. package/src/discord-bot.ts +45 -12
  68. package/src/discord-utils.ts +2 -2
  69. package/src/genai-worker-wrapper.ts +3 -3
  70. package/src/genai-worker.ts +2 -2
  71. package/src/genai.ts +2 -2
  72. package/src/interaction-handler.ts +7 -2
  73. package/src/logger.ts +64 -10
  74. package/src/markdown.ts +2 -2
  75. package/src/message-formatting.ts +100 -6
  76. package/src/openai-realtime.ts +2 -2
  77. package/src/opencode.ts +19 -26
  78. package/src/session-handler.ts +102 -29
  79. package/src/system-message.ts +11 -9
  80. package/src/tools.ts +3 -2
  81. package/src/utils.ts +1 -0
  82. package/src/voice-handler.ts +2 -2
  83. package/src/voice.ts +2 -2
  84. package/src/worktree-utils.ts +111 -7
  85. package/src/xml.ts +2 -2
@@ -1,14 +1,15 @@
1
1
  // Worktree utility functions.
2
2
  // Wrapper for OpenCode worktree creation that also initializes git submodules.
3
+ // Also handles capturing and applying git diffs when creating worktrees from threads.
3
4
 
4
- import { exec } from 'node:child_process'
5
+ import { exec, spawn } from 'node:child_process'
5
6
  import { promisify } from 'node:util'
6
- import { createLogger } from './logger.js'
7
+ import { createLogger, LogPrefix } from './logger.js'
7
8
  import type { getOpencodeClientV2 } from './opencode.js'
8
9
 
9
10
  export const execAsync = promisify(exec)
10
11
 
11
- const logger = createLogger('WORKTREE-UTILS')
12
+ const logger = createLogger(LogPrefix.WORKTREE)
12
13
 
13
14
  type OpencodeClientV2 = NonNullable<ReturnType<typeof getOpencodeClientV2>>
14
15
 
@@ -20,16 +21,21 @@ type WorktreeResult = {
20
21
  /**
21
22
  * Create a worktree using OpenCode SDK and initialize git submodules.
22
23
  * This wrapper ensures submodules are properly set up in new worktrees.
24
+ *
25
+ * If diff is provided, it's applied BEFORE submodule update to ensure
26
+ * any submodule pointer changes in the diff are respected.
23
27
  */
24
28
  export async function createWorktreeWithSubmodules({
25
29
  clientV2,
26
30
  directory,
27
31
  name,
32
+ diff,
28
33
  }: {
29
34
  clientV2: OpencodeClientV2
30
35
  directory: string
31
36
  name: string
32
- }): Promise<WorktreeResult | Error> {
37
+ diff?: CapturedDiff | null
38
+ }): Promise<WorktreeResult & { diffApplied: boolean } | Error> {
33
39
  // 1. Create worktree via OpenCode SDK
34
40
  const response = await clientV2.worktree.create({
35
41
  directory,
@@ -45,8 +51,19 @@ export async function createWorktreeWithSubmodules({
45
51
  }
46
52
 
47
53
  const worktreeDir = response.data.directory
54
+ let diffApplied = false
48
55
 
49
- // 2. Init submodules in new worktree (don't block on failure)
56
+ // 2. Apply diff BEFORE submodule update (if provided)
57
+ // This ensures any submodule pointer changes in the diff are applied first,
58
+ // so submodule update checks out the correct commits.
59
+ if (diff) {
60
+ logger.log(`Applying diff to ${worktreeDir} before submodule init`)
61
+ diffApplied = await applyGitDiff(worktreeDir, diff)
62
+ }
63
+
64
+ // 3. Init submodules in new worktree (don't block on failure)
65
+ // Uses --init to initialize, --recursive for nested submodules.
66
+ // Submodules will be checked out at the commit specified by the (possibly updated) index.
50
67
  try {
51
68
  logger.log(`Initializing submodules in ${worktreeDir}`)
52
69
  await execAsync('git submodule update --init --recursive', {
@@ -60,7 +77,7 @@ export async function createWorktreeWithSubmodules({
60
77
  )
61
78
  }
62
79
 
63
- // 3. Install dependencies using ni (detects package manager from lockfile)
80
+ // 4. Install dependencies using ni (detects package manager from lockfile)
64
81
  try {
65
82
  logger.log(`Installing dependencies in ${worktreeDir}`)
66
83
  await execAsync('npx -y ni', {
@@ -74,5 +91,92 @@ export async function createWorktreeWithSubmodules({
74
91
  )
75
92
  }
76
93
 
77
- return response.data
94
+ return { ...response.data, diffApplied }
95
+ }
96
+
97
+ /**
98
+ * Captured git diff (both staged and unstaged changes).
99
+ */
100
+ export type CapturedDiff = {
101
+ unstaged: string
102
+ staged: string
103
+ }
104
+
105
+ /**
106
+ * Capture git diff from a directory (both staged and unstaged changes).
107
+ * Returns null if no changes or on error.
108
+ */
109
+ export async function captureGitDiff(directory: string): Promise<CapturedDiff | null> {
110
+ try {
111
+ // Capture unstaged changes
112
+ const unstagedResult = await execAsync('git diff', { cwd: directory })
113
+ const unstaged = unstagedResult.stdout.trim()
114
+
115
+ // Capture staged changes
116
+ const stagedResult = await execAsync('git diff --staged', { cwd: directory })
117
+ const staged = stagedResult.stdout.trim()
118
+
119
+ if (!unstaged && !staged) {
120
+ return null
121
+ }
122
+
123
+ return { unstaged, staged }
124
+ } catch (e) {
125
+ logger.warn(`Failed to capture git diff from ${directory}: ${e instanceof Error ? e.message : String(e)}`)
126
+ return null
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Run a git command with stdin input.
132
+ * Uses spawn to pipe the diff content to git apply.
133
+ */
134
+ function runGitWithStdin(args: string[], cwd: string, input: string): Promise<void> {
135
+ return new Promise((resolve, reject) => {
136
+ const child = spawn('git', args, { cwd, stdio: ['pipe', 'pipe', 'pipe'] })
137
+
138
+ let stderr = ''
139
+ child.stderr?.on('data', (data) => {
140
+ stderr += data.toString()
141
+ })
142
+
143
+ child.on('close', (code) => {
144
+ if (code === 0) {
145
+ resolve()
146
+ } else {
147
+ reject(new Error(stderr || `git ${args.join(' ')} failed with code ${code}`))
148
+ }
149
+ })
150
+
151
+ child.on('error', reject)
152
+
153
+ child.stdin?.write(input)
154
+ child.stdin?.end()
155
+ })
156
+ }
157
+
158
+ /**
159
+ * Apply a captured git diff to a directory.
160
+ * Applies staged changes first, then unstaged.
161
+ */
162
+ export async function applyGitDiff(directory: string, diff: CapturedDiff): Promise<boolean> {
163
+ try {
164
+ // Apply staged changes first (and stage them)
165
+ if (diff.staged) {
166
+ logger.log(`Applying staged diff to ${directory}`)
167
+ await runGitWithStdin(['apply', '--index'], directory, diff.staged)
168
+ }
169
+
170
+ // Apply unstaged changes (don't stage them)
171
+ if (diff.unstaged) {
172
+ logger.log(`Applying unstaged diff to ${directory}`)
173
+ await runGitWithStdin(['apply'], directory, diff.unstaged)
174
+ }
175
+
176
+ logger.log(`Successfully applied diff to ${directory}`)
177
+ return true
178
+ } catch (e) {
179
+ logger.warn(`Failed to apply git diff to ${directory}: ${e instanceof Error ? e.message : String(e)}`)
180
+ return false
181
+ }
78
182
  }
package/src/xml.ts CHANGED
@@ -4,9 +4,9 @@
4
4
 
5
5
  import { DomHandler, Parser, ElementType } from 'htmlparser2'
6
6
  import type { ChildNode, Element, Text } from 'domhandler'
7
- import { createLogger } from './logger.js'
7
+ import { createLogger, LogPrefix } from './logger.js'
8
8
 
9
- const xmlLogger = createLogger('XML')
9
+ const xmlLogger = createLogger(LogPrefix.XML)
10
10
 
11
11
  export function extractTagsArrays<T extends string>({
12
12
  xml,