@akiojin/gwt 4.11.6 → 4.12.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 (199) hide show
  1. package/bin/gwt.js +36 -10
  2. package/dist/claude.d.ts +1 -0
  3. package/dist/claude.d.ts.map +1 -1
  4. package/dist/claude.js +81 -24
  5. package/dist/claude.js.map +1 -1
  6. package/dist/cli/ui/App.solid.d.ts.map +1 -1
  7. package/dist/cli/ui/App.solid.js +280 -50
  8. package/dist/cli/ui/App.solid.js.map +1 -1
  9. package/dist/cli/ui/components/solid/QuickStartStep.d.ts.map +1 -1
  10. package/dist/cli/ui/components/solid/QuickStartStep.js +35 -22
  11. package/dist/cli/ui/components/solid/QuickStartStep.js.map +1 -1
  12. package/dist/cli/ui/components/solid/SelectInput.d.ts.map +1 -1
  13. package/dist/cli/ui/components/solid/SelectInput.js +2 -1
  14. package/dist/cli/ui/components/solid/SelectInput.js.map +1 -1
  15. package/dist/cli/ui/components/solid/WizardController.d.ts.map +1 -1
  16. package/dist/cli/ui/components/solid/WizardController.js +67 -13
  17. package/dist/cli/ui/components/solid/WizardController.js.map +1 -1
  18. package/dist/cli/ui/components/solid/WizardSteps.d.ts +5 -0
  19. package/dist/cli/ui/components/solid/WizardSteps.d.ts.map +1 -1
  20. package/dist/cli/ui/components/solid/WizardSteps.js +50 -70
  21. package/dist/cli/ui/components/solid/WizardSteps.js.map +1 -1
  22. package/dist/cli/ui/core/theme.d.ts +9 -0
  23. package/dist/cli/ui/core/theme.d.ts.map +1 -1
  24. package/dist/cli/ui/core/theme.js +21 -0
  25. package/dist/cli/ui/core/theme.js.map +1 -1
  26. package/dist/cli/ui/screens/solid/BranchListScreen.d.ts +9 -2
  27. package/dist/cli/ui/screens/solid/BranchListScreen.d.ts.map +1 -1
  28. package/dist/cli/ui/screens/solid/BranchListScreen.js +101 -28
  29. package/dist/cli/ui/screens/solid/BranchListScreen.js.map +1 -1
  30. package/dist/cli/ui/screens/solid/ConfirmScreen.d.ts +2 -1
  31. package/dist/cli/ui/screens/solid/ConfirmScreen.d.ts.map +1 -1
  32. package/dist/cli/ui/screens/solid/ConfirmScreen.js +11 -3
  33. package/dist/cli/ui/screens/solid/ConfirmScreen.js.map +1 -1
  34. package/dist/cli/ui/screens/solid/EnvironmentScreen.d.ts.map +1 -1
  35. package/dist/cli/ui/screens/solid/EnvironmentScreen.js +9 -10
  36. package/dist/cli/ui/screens/solid/EnvironmentScreen.js.map +1 -1
  37. package/dist/cli/ui/screens/solid/LogScreen.d.ts +7 -1
  38. package/dist/cli/ui/screens/solid/LogScreen.d.ts.map +1 -1
  39. package/dist/cli/ui/screens/solid/LogScreen.js +254 -16
  40. package/dist/cli/ui/screens/solid/LogScreen.js.map +1 -1
  41. package/dist/cli/ui/screens/solid/ProfileEnvScreen.d.ts.map +1 -1
  42. package/dist/cli/ui/screens/solid/ProfileEnvScreen.js +8 -5
  43. package/dist/cli/ui/screens/solid/ProfileEnvScreen.js.map +1 -1
  44. package/dist/cli/ui/screens/solid/SelectorScreen.d.ts.map +1 -1
  45. package/dist/cli/ui/screens/solid/SelectorScreen.js +12 -4
  46. package/dist/cli/ui/screens/solid/SelectorScreen.js.map +1 -1
  47. package/dist/cli/ui/types.d.ts +1 -0
  48. package/dist/cli/ui/types.d.ts.map +1 -1
  49. package/dist/cli/ui/utils/branchFormatter.d.ts +1 -0
  50. package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
  51. package/dist/cli/ui/utils/branchFormatter.js +29 -7
  52. package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
  53. package/dist/cli/ui/utils/continueSession.d.ts +14 -0
  54. package/dist/cli/ui/utils/continueSession.d.ts.map +1 -1
  55. package/dist/cli/ui/utils/continueSession.js +61 -3
  56. package/dist/cli/ui/utils/continueSession.js.map +1 -1
  57. package/dist/cli/ui/utils/installedVersionCache.d.ts +33 -0
  58. package/dist/cli/ui/utils/installedVersionCache.d.ts.map +1 -0
  59. package/dist/cli/ui/utils/installedVersionCache.js +59 -0
  60. package/dist/cli/ui/utils/installedVersionCache.js.map +1 -0
  61. package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -1
  62. package/dist/cli/ui/utils/modelOptions.js +16 -0
  63. package/dist/cli/ui/utils/modelOptions.js.map +1 -1
  64. package/dist/cli/ui/utils/versionCache.d.ts +37 -0
  65. package/dist/cli/ui/utils/versionCache.d.ts.map +1 -0
  66. package/dist/cli/ui/utils/versionCache.js +70 -0
  67. package/dist/cli/ui/utils/versionCache.js.map +1 -0
  68. package/dist/cli/ui/utils/versionFetcher.d.ts +41 -0
  69. package/dist/cli/ui/utils/versionFetcher.d.ts.map +1 -0
  70. package/dist/cli/ui/utils/versionFetcher.js +89 -0
  71. package/dist/cli/ui/utils/versionFetcher.js.map +1 -0
  72. package/dist/codex.d.ts +1 -0
  73. package/dist/codex.d.ts.map +1 -1
  74. package/dist/codex.js +95 -25
  75. package/dist/codex.js.map +1 -1
  76. package/dist/config/index.d.ts.map +1 -1
  77. package/dist/config/index.js +10 -1
  78. package/dist/config/index.js.map +1 -1
  79. package/dist/gemini.d.ts +1 -0
  80. package/dist/gemini.d.ts.map +1 -1
  81. package/dist/gemini.js +36 -3
  82. package/dist/gemini.js.map +1 -1
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +35 -2
  85. package/dist/index.js.map +1 -1
  86. package/dist/launcher.d.ts.map +1 -1
  87. package/dist/launcher.js +43 -8
  88. package/dist/launcher.js.map +1 -1
  89. package/dist/logging/agentOutput.d.ts +21 -0
  90. package/dist/logging/agentOutput.d.ts.map +1 -0
  91. package/dist/logging/agentOutput.js +164 -0
  92. package/dist/logging/agentOutput.js.map +1 -0
  93. package/dist/logging/formatter.d.ts.map +1 -1
  94. package/dist/logging/formatter.js +18 -4
  95. package/dist/logging/formatter.js.map +1 -1
  96. package/dist/logging/logger.d.ts.map +1 -1
  97. package/dist/logging/logger.js +2 -0
  98. package/dist/logging/logger.js.map +1 -1
  99. package/dist/logging/reader.d.ts +22 -0
  100. package/dist/logging/reader.d.ts.map +1 -1
  101. package/dist/logging/reader.js +116 -1
  102. package/dist/logging/reader.js.map +1 -1
  103. package/dist/opentui/index.solid.js +2575 -888
  104. package/dist/services/codingAgentResolver.d.ts.map +1 -1
  105. package/dist/services/codingAgentResolver.js +8 -6
  106. package/dist/services/codingAgentResolver.js.map +1 -1
  107. package/dist/services/dependency-installer.js +2 -2
  108. package/dist/services/dependency-installer.js.map +1 -1
  109. package/dist/shared/codingAgentConstants.d.ts +3 -0
  110. package/dist/shared/codingAgentConstants.d.ts.map +1 -1
  111. package/dist/shared/codingAgentConstants.js +66 -0
  112. package/dist/shared/codingAgentConstants.js.map +1 -1
  113. package/dist/utils/bun-runtime.d.ts +12 -0
  114. package/dist/utils/bun-runtime.d.ts.map +1 -0
  115. package/dist/utils/bun-runtime.js +13 -0
  116. package/dist/utils/bun-runtime.js.map +1 -0
  117. package/dist/utils/session/common.d.ts +8 -0
  118. package/dist/utils/session/common.d.ts.map +1 -1
  119. package/dist/utils/session/common.js +22 -0
  120. package/dist/utils/session/common.js.map +1 -1
  121. package/dist/utils/session/parsers/claude.d.ts +10 -4
  122. package/dist/utils/session/parsers/claude.d.ts.map +1 -1
  123. package/dist/utils/session/parsers/claude.js +64 -18
  124. package/dist/utils/session/parsers/claude.js.map +1 -1
  125. package/dist/utils/session/parsers/codex.d.ts.map +1 -1
  126. package/dist/utils/session/parsers/codex.js +47 -28
  127. package/dist/utils/session/parsers/codex.js.map +1 -1
  128. package/dist/utils/session/parsers/gemini.d.ts.map +1 -1
  129. package/dist/utils/session/parsers/gemini.js +43 -6
  130. package/dist/utils/session/parsers/gemini.js.map +1 -1
  131. package/dist/utils/session/parsers/opencode.d.ts.map +1 -1
  132. package/dist/utils/session/parsers/opencode.js +43 -6
  133. package/dist/utils/session/parsers/opencode.js.map +1 -1
  134. package/dist/utils/session/types.d.ts +7 -0
  135. package/dist/utils/session/types.d.ts.map +1 -1
  136. package/dist/web/client/src/components/ui/alert.d.ts +1 -1
  137. package/dist/worktree.d.ts +4 -1
  138. package/dist/worktree.d.ts.map +1 -1
  139. package/dist/worktree.js +21 -15
  140. package/dist/worktree.js.map +1 -1
  141. package/package.json +2 -1
  142. package/src/claude.ts +99 -28
  143. package/src/cli/ui/App.solid.tsx +373 -51
  144. package/src/cli/ui/__tests__/solid/AppSolid.cleanup.test.tsx +921 -1
  145. package/src/cli/ui/__tests__/solid/BranchListScreen.test.tsx +105 -5
  146. package/src/cli/ui/__tests__/solid/ConfirmScreen.test.tsx +77 -0
  147. package/src/cli/ui/__tests__/solid/LogScreen.test.tsx +351 -0
  148. package/src/cli/ui/__tests__/solid/components/QuickStartStep.test.tsx +73 -2
  149. package/src/cli/ui/__tests__/solid/components/WizardController.test.tsx +71 -0
  150. package/src/cli/ui/__tests__/solid/components/WizardSteps.test.tsx +95 -2
  151. package/src/cli/ui/__tests__/utils/branchFormatter.test.ts +72 -45
  152. package/src/cli/ui/components/solid/QuickStartStep.tsx +35 -23
  153. package/src/cli/ui/components/solid/SearchInput.tsx +1 -1
  154. package/src/cli/ui/components/solid/SelectInput.tsx +4 -0
  155. package/src/cli/ui/components/solid/WizardController.tsx +85 -12
  156. package/src/cli/ui/components/solid/WizardSteps.tsx +78 -90
  157. package/src/cli/ui/core/theme.ts +32 -0
  158. package/src/cli/ui/hooks/solid/useAsyncOperation.ts +8 -6
  159. package/src/cli/ui/hooks/solid/useGitOperations.ts +6 -5
  160. package/src/cli/ui/screens/solid/BranchListScreen.tsx +135 -32
  161. package/src/cli/ui/screens/solid/ConfirmScreen.tsx +20 -8
  162. package/src/cli/ui/screens/solid/EnvironmentScreen.tsx +22 -20
  163. package/src/cli/ui/screens/solid/LogScreen.tsx +364 -35
  164. package/src/cli/ui/screens/solid/ProfileEnvScreen.tsx +19 -15
  165. package/src/cli/ui/screens/solid/SelectorScreen.tsx +25 -14
  166. package/src/cli/ui/screens/solid/SettingsScreen.tsx +5 -3
  167. package/src/cli/ui/types.ts +1 -0
  168. package/src/cli/ui/utils/__tests__/branchFormatter.test.ts +53 -6
  169. package/src/cli/ui/utils/__tests__/installedVersionCache.test.ts +46 -0
  170. package/src/cli/ui/utils/branchFormatter.ts +35 -7
  171. package/src/cli/ui/utils/continueSession.ts +90 -3
  172. package/src/cli/ui/utils/installedVersionCache.ts +84 -0
  173. package/src/cli/ui/utils/modelOptions.test.ts +6 -0
  174. package/src/cli/ui/utils/modelOptions.ts +16 -0
  175. package/src/cli/ui/utils/versionCache.ts +93 -0
  176. package/src/cli/ui/utils/versionFetcher.ts +120 -0
  177. package/src/codex.ts +124 -26
  178. package/src/config/__tests__/saveSession.test.ts +2 -2
  179. package/src/config/index.ts +11 -1
  180. package/src/gemini.ts +50 -4
  181. package/src/index.test.ts +16 -10
  182. package/src/index.ts +41 -1
  183. package/src/launcher.ts +49 -8
  184. package/src/logging/agentOutput.ts +216 -0
  185. package/src/logging/formatter.ts +23 -4
  186. package/src/logging/logger.ts +2 -0
  187. package/src/logging/reader.ts +165 -1
  188. package/src/services/__tests__/BatchMergeService.test.ts +34 -14
  189. package/src/services/codingAgentResolver.ts +12 -5
  190. package/src/services/dependency-installer.ts +2 -2
  191. package/src/shared/codingAgentConstants.ts +73 -0
  192. package/src/utils/bun-runtime.ts +29 -0
  193. package/src/utils/session/common.ts +28 -0
  194. package/src/utils/session/parsers/claude.ts +79 -29
  195. package/src/utils/session/parsers/codex.ts +49 -26
  196. package/src/utils/session/parsers/gemini.ts +46 -5
  197. package/src/utils/session/parsers/opencode.ts +46 -5
  198. package/src/utils/session/types.ts +4 -0
  199. package/src/worktree.ts +28 -15
@@ -28,6 +28,164 @@ var __export = (target, all) => {
28
28
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
29
29
  var __require = import.meta.require;
30
30
 
31
+ // src/utils/npmRegistry.ts
32
+ function isPrerelease(version) {
33
+ return /-(alpha|beta|rc|canary|next|dev|pre)\b/i.test(version);
34
+ }
35
+ async function fetchPackageVersions(packageName, limit = DEFAULT_LIMIT, timeoutMs = DEFAULT_TIMEOUT_MS) {
36
+ try {
37
+ const controller = new AbortController;
38
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
39
+ const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, {
40
+ signal: controller.signal,
41
+ headers: {
42
+ Accept: "application/json"
43
+ }
44
+ });
45
+ clearTimeout(timeoutId);
46
+ if (!response.ok) {
47
+ return [];
48
+ }
49
+ const data = await response.json();
50
+ if (!data.versions || !data.time) {
51
+ return [];
52
+ }
53
+ const versionsWithTime = [];
54
+ for (const version of Object.keys(data.versions)) {
55
+ const publishedAt = data.time[version];
56
+ if (publishedAt) {
57
+ versionsWithTime.push({ version, publishedAt });
58
+ }
59
+ }
60
+ versionsWithTime.sort((a, b) => {
61
+ const dateA = new Date(a.publishedAt).getTime();
62
+ const dateB = new Date(b.publishedAt).getTime();
63
+ return dateB - dateA;
64
+ });
65
+ const topVersions = versionsWithTime.slice(0, limit);
66
+ return topVersions.map((v) => ({
67
+ version: v.version,
68
+ isPrerelease: isPrerelease(v.version),
69
+ publishedAt: v.publishedAt
70
+ }));
71
+ } catch {
72
+ return [];
73
+ }
74
+ }
75
+ function parsePackageCommand(command) {
76
+ if (command.startsWith("@")) {
77
+ const firstSlash = command.indexOf("/");
78
+ if (firstSlash === -1) {
79
+ return { packageName: command, version: null };
80
+ }
81
+ const afterScope = command.substring(firstSlash + 1);
82
+ const atIndex2 = afterScope.indexOf("@");
83
+ if (atIndex2 === -1) {
84
+ return { packageName: command, version: null };
85
+ }
86
+ const packageName2 = command.substring(0, firstSlash + 1 + atIndex2);
87
+ const version2 = afterScope.substring(atIndex2 + 1);
88
+ return { packageName: packageName2, version: version2 };
89
+ }
90
+ const atIndex = command.indexOf("@");
91
+ if (atIndex === -1) {
92
+ return { packageName: command, version: null };
93
+ }
94
+ const packageName = command.substring(0, atIndex);
95
+ const version = command.substring(atIndex + 1);
96
+ return { packageName, version };
97
+ }
98
+ var DEFAULT_TIMEOUT_MS = 3000, DEFAULT_LIMIT = 10;
99
+
100
+ // src/shared/codingAgentConstants.ts
101
+ var CLAUDE_PERMISSION_SKIP_ARGS, CODEX_DEFAULT_ARGS;
102
+ var init_codingAgentConstants = __esm(() => {
103
+ CLAUDE_PERMISSION_SKIP_ARGS = [
104
+ "--dangerously-skip-permissions"
105
+ ];
106
+ CODEX_DEFAULT_ARGS = [
107
+ "--enable",
108
+ "web_search_request",
109
+ "--model=gpt-5.2-codex",
110
+ "--sandbox",
111
+ "workspace-write",
112
+ "-c",
113
+ "model_reasoning_effort=high",
114
+ "-c",
115
+ "model_reasoning_summaries=detailed",
116
+ "-c",
117
+ "sandbox_workspace_write.network_access=true",
118
+ "-c",
119
+ "shell_environment_policy.inherit=all",
120
+ "-c",
121
+ "shell_environment_policy.ignore_default_excludes=true",
122
+ "-c",
123
+ "shell_environment_policy.experimental_use_profile=true"
124
+ ];
125
+ });
126
+
127
+ // src/config/builtin-coding-agents.ts
128
+ var CLAUDE_CODE_TOOL, CODEX_CLI_TOOL, GEMINI_CLI_TOOL, OPENCODE_TOOL, BUILTIN_CODING_AGENTS;
129
+ var init_builtin_coding_agents = __esm(() => {
130
+ init_codingAgentConstants();
131
+ CLAUDE_CODE_TOOL = {
132
+ id: "claude-code",
133
+ displayName: "Claude Code",
134
+ type: "bunx",
135
+ command: "@anthropic-ai/claude-code",
136
+ modeArgs: {
137
+ normal: [],
138
+ continue: ["-c"],
139
+ resume: ["-r"]
140
+ },
141
+ permissionSkipArgs: Array.from(CLAUDE_PERMISSION_SKIP_ARGS),
142
+ env: {
143
+ ENABLE_LSP_TOOL: "true"
144
+ }
145
+ };
146
+ CODEX_CLI_TOOL = {
147
+ id: "codex-cli",
148
+ displayName: "Codex",
149
+ type: "bunx",
150
+ command: "@openai/codex",
151
+ defaultArgs: Array.from(CODEX_DEFAULT_ARGS),
152
+ modeArgs: {
153
+ normal: [],
154
+ continue: ["resume", "--last"],
155
+ resume: ["resume"]
156
+ }
157
+ };
158
+ GEMINI_CLI_TOOL = {
159
+ id: "gemini-cli",
160
+ displayName: "Gemini",
161
+ type: "bunx",
162
+ command: "@google/gemini-cli",
163
+ modeArgs: {
164
+ normal: [],
165
+ continue: ["-r", "latest"],
166
+ resume: ["-r", "latest"]
167
+ },
168
+ permissionSkipArgs: ["-y"]
169
+ };
170
+ OPENCODE_TOOL = {
171
+ id: "opencode",
172
+ displayName: "OpenCode",
173
+ type: "bunx",
174
+ command: "opencode-ai",
175
+ modeArgs: {
176
+ normal: [],
177
+ continue: ["-c"],
178
+ resume: ["-s"]
179
+ }
180
+ };
181
+ BUILTIN_CODING_AGENTS = [
182
+ CLAUDE_CODE_TOOL,
183
+ CODEX_CLI_TOOL,
184
+ GEMINI_CLI_TOOL,
185
+ OPENCODE_TOOL
186
+ ];
187
+ });
188
+
31
189
  // node_modules/is-plain-obj/index.js
32
190
  function isPlainObject(value) {
33
191
  if (typeof value !== "object" || value === null) {
@@ -3129,12 +3287,12 @@ var init_exports = __esm(() => {
3129
3287
  });
3130
3288
 
3131
3289
  // node_modules/get-stream/source/index.js
3132
- import { on } from "events";
3290
+ import { on as on2 } from "events";
3133
3291
  import { finished } from "stream/promises";
3134
3292
  var init_source = __esm(() => {
3135
3293
  init_stream();
3136
3294
  init_exports();
3137
- Object.assign(nodeImports, { on, finished });
3295
+ Object.assign(nodeImports, { on: on2, finished });
3138
3296
  });
3139
3297
 
3140
3298
  // node_modules/execa/lib/io/max-buffer.js
@@ -5044,7 +5202,7 @@ var init_main_sync = __esm(() => {
5044
5202
  });
5045
5203
 
5046
5204
  // node_modules/execa/lib/ipc/get-one.js
5047
- import { once as once5, on as on2 } from "events";
5205
+ import { once as once5, on as on3 } from "events";
5048
5206
  var getOneMessage = ({ anyProcess, channel, isSubprocess, ipc }, { reference = true, filter } = {}) => {
5049
5207
  validateIpcMethod({
5050
5208
  methodName: "getOneMessage",
@@ -5081,7 +5239,7 @@ var getOneMessage = ({ anyProcess, channel, isSubprocess, ipc }, { reference = t
5081
5239
  const [message] = await once5(ipcEmitter, "message", { signal });
5082
5240
  return message;
5083
5241
  }
5084
- for await (const [message] of on2(ipcEmitter, "message", { signal })) {
5242
+ for await (const [message] of on3(ipcEmitter, "message", { signal })) {
5085
5243
  if (filter(message)) {
5086
5244
  return message;
5087
5245
  }
@@ -5099,7 +5257,7 @@ var init_get_one = __esm(() => {
5099
5257
  });
5100
5258
 
5101
5259
  // node_modules/execa/lib/ipc/get-each.js
5102
- import { once as once6, on as on3 } from "events";
5260
+ import { once as once6, on as on4 } from "events";
5103
5261
  var getEachMessage = ({ anyProcess, channel, isSubprocess, ipc }, { reference = true } = {}) => loopOnMessages({
5104
5262
  anyProcess,
5105
5263
  channel,
@@ -5148,7 +5306,7 @@ var getEachMessage = ({ anyProcess, channel, isSubprocess, ipc }, { reference =
5148
5306
  } catch {}
5149
5307
  }, iterateOnMessages = async function* ({ anyProcess, channel, ipcEmitter, isSubprocess, shouldAwait, controller, state, reference }) {
5150
5308
  try {
5151
- for await (const [message] of on3(ipcEmitter, "message", { signal: controller.signal })) {
5309
+ for await (const [message] of on4(ipcEmitter, "message", { signal: controller.signal })) {
5152
5310
  throwIfStrictError(state);
5153
5311
  yield message;
5154
5312
  }
@@ -5316,7 +5474,7 @@ var init_handle_async = __esm(() => {
5316
5474
  });
5317
5475
 
5318
5476
  // node_modules/@sindresorhus/merge-streams/index.js
5319
- import { on as on4, once as once7 } from "events";
5477
+ import { on as on5, once as once7 } from "events";
5320
5478
  import { PassThrough as PassThroughStream, getDefaultHighWaterMark as getDefaultHighWaterMark2 } from "stream";
5321
5479
  import { finished as finished2 } from "stream/promises";
5322
5480
  function mergeStreams(streams) {
@@ -5364,7 +5522,7 @@ var getHighWaterMark = (streams, objectMode) => {
5364
5522
  throw error;
5365
5523
  }
5366
5524
  }, onInputStreamsUnpipe = async (passThroughStream, streams, unpipeEvent, { signal }) => {
5367
- for await (const [unpipedStream] of on4(passThroughStream, "unpipe", { signal })) {
5525
+ for await (const [unpipedStream] of on5(passThroughStream, "unpipe", { signal })) {
5368
5526
  if (streams.has(unpipedStream)) {
5369
5527
  unpipedStream.emit(unpipeEvent);
5370
5528
  }
@@ -6087,7 +6245,7 @@ var init_setup = __esm(() => {
6087
6245
  });
6088
6246
 
6089
6247
  // node_modules/execa/lib/io/iterate.js
6090
- import { on as on5 } from "events";
6248
+ import { on as on6 } from "events";
6091
6249
  import { getDefaultHighWaterMark as getDefaultHighWaterMark3 } from "stream";
6092
6250
  var iterateOnSubprocessStream = ({ subprocessStdout, subprocess, binary, shouldEncode, encoding, preserveNewlines }) => {
6093
6251
  const controller = new AbortController;
@@ -6129,7 +6287,7 @@ var iterateOnSubprocessStream = ({ subprocessStdout, subprocess, binary, shouldE
6129
6287
  controller.abort();
6130
6288
  }
6131
6289
  }, iterateOnStream = ({ stream, controller, binary, shouldEncode, encoding, shouldSplit, preserveNewlines }) => {
6132
- const onStdoutChunk = on5(stream, "data", {
6290
+ const onStdoutChunk = on6(stream, "data", {
6133
6291
  signal: controller.signal,
6134
6292
  highWaterMark: HIGH_WATER_MARK,
6135
6293
  highWatermark: HIGH_WATER_MARK
@@ -7209,6 +7367,182 @@ var init_execa = __esm(() => {
7209
7367
  } = getIpcExport());
7210
7368
  });
7211
7369
 
7370
+ // src/utils/command.ts
7371
+ import { existsSync as existsSync3 } from "fs";
7372
+ import { homedir } from "os";
7373
+ import { join as join2 } from "path";
7374
+ async function getCommandVersion(commandPath) {
7375
+ try {
7376
+ const result = await execa(commandPath, ["--version"], {
7377
+ timeout: 3000,
7378
+ stdin: "ignore",
7379
+ stdout: "pipe",
7380
+ stderr: "ignore"
7381
+ });
7382
+ const match = result.stdout.match(/(\d+\.\d+(?:\.\d+)?(?:-[\w.]+)?)/);
7383
+ return match ? `v${match[1]}` : null;
7384
+ } catch {
7385
+ return null;
7386
+ }
7387
+ }
7388
+ async function findCommand(commandName) {
7389
+ const cached = commandLookupCache.get(commandName);
7390
+ if (cached) {
7391
+ return cached;
7392
+ }
7393
+ let lookupResult = null;
7394
+ try {
7395
+ const lookupCommand = process.platform === "win32" ? "where" : "which";
7396
+ const execResult = await execa(lookupCommand, [commandName], {
7397
+ shell: true,
7398
+ stdin: "ignore",
7399
+ stdout: "pipe",
7400
+ stderr: "ignore"
7401
+ });
7402
+ const foundPath = execResult.stdout.trim().split(`
7403
+ `)[0];
7404
+ if (foundPath) {
7405
+ lookupResult = { available: true, path: foundPath, source: "installed" };
7406
+ }
7407
+ } catch {}
7408
+ if (!lookupResult) {
7409
+ const knownPaths = KNOWN_INSTALL_PATHS[commandName];
7410
+ if (knownPaths) {
7411
+ const pathsToCheck = process.platform === "win32" ? knownPaths.win32 : knownPaths.unix;
7412
+ for (const p of pathsToCheck) {
7413
+ if (p && existsSync3(p)) {
7414
+ lookupResult = { available: true, path: p, source: "installed" };
7415
+ break;
7416
+ }
7417
+ }
7418
+ }
7419
+ }
7420
+ if (!lookupResult) {
7421
+ lookupResult = { available: true, path: null, source: "bunx" };
7422
+ }
7423
+ if (lookupResult.source === "installed" && lookupResult.path) {
7424
+ lookupResult.version = await getCommandVersion(lookupResult.path);
7425
+ } else {
7426
+ lookupResult.version = null;
7427
+ }
7428
+ commandLookupCache.set(commandName, lookupResult);
7429
+ return lookupResult;
7430
+ }
7431
+ var KNOWN_INSTALL_PATHS, commandLookupCache;
7432
+ var init_command3 = __esm(() => {
7433
+ init_execa();
7434
+ KNOWN_INSTALL_PATHS = {
7435
+ claude: {
7436
+ unix: [
7437
+ join2(homedir(), ".bun", "bin", "claude"),
7438
+ join2(homedir(), ".local", "bin", "claude"),
7439
+ "/usr/local/bin/claude"
7440
+ ],
7441
+ win32: [
7442
+ join2(process.env.LOCALAPPDATA ?? "", "Programs", "claude", "claude.exe"),
7443
+ join2(homedir(), ".bun", "bin", "claude.exe")
7444
+ ]
7445
+ },
7446
+ codex: {
7447
+ unix: [
7448
+ join2(homedir(), ".bun", "bin", "codex"),
7449
+ join2(homedir(), ".local", "bin", "codex"),
7450
+ "/usr/local/bin/codex"
7451
+ ],
7452
+ win32: [join2(homedir(), ".bun", "bin", "codex.exe")]
7453
+ },
7454
+ gemini: {
7455
+ unix: [
7456
+ join2(homedir(), ".bun", "bin", "gemini"),
7457
+ join2(homedir(), ".local", "bin", "gemini"),
7458
+ "/usr/local/bin/gemini"
7459
+ ],
7460
+ win32: [join2(homedir(), ".bun", "bin", "gemini.exe")]
7461
+ },
7462
+ opencode: {
7463
+ unix: [
7464
+ join2(homedir(), ".bun", "bin", "opencode"),
7465
+ join2(homedir(), ".local", "bin", "opencode"),
7466
+ "/usr/local/bin/opencode"
7467
+ ],
7468
+ win32: [join2(homedir(), ".bun", "bin", "opencode.exe")]
7469
+ }
7470
+ };
7471
+ commandLookupCache = new Map;
7472
+ });
7473
+
7474
+ // src/cli/ui/utils/versionFetcher.ts
7475
+ var exports_versionFetcher = {};
7476
+ __export(exports_versionFetcher, {
7477
+ versionInfoToSelectItem: () => versionInfoToSelectItem,
7478
+ getPackageNameForAgent: () => getPackageNameForAgent,
7479
+ getBunxAgentIds: () => getBunxAgentIds,
7480
+ fetchVersionOptionsForAgent: () => fetchVersionOptionsForAgent,
7481
+ fetchInstalledVersionForAgent: () => fetchInstalledVersionForAgent,
7482
+ createInstalledOption: () => createInstalledOption
7483
+ });
7484
+ function getPackageNameForAgent(agentId) {
7485
+ const agent = BUILTIN_CODING_AGENTS.find((a2) => a2.id === agentId);
7486
+ if (!agent || agent.type !== "bunx") {
7487
+ return null;
7488
+ }
7489
+ const { packageName } = parsePackageCommand(agent.command);
7490
+ return packageName;
7491
+ }
7492
+ async function fetchVersionOptionsForAgent(agentId) {
7493
+ const packageName = getPackageNameForAgent(agentId);
7494
+ if (!packageName) {
7495
+ return [];
7496
+ }
7497
+ return fetchPackageVersions(packageName);
7498
+ }
7499
+ async function fetchInstalledVersionForAgent(agentId) {
7500
+ const commandName = AGENT_COMMAND_MAP[agentId];
7501
+ if (!commandName) {
7502
+ return null;
7503
+ }
7504
+ const result = await findCommand(commandName);
7505
+ if (result.source !== "installed" || !result.path) {
7506
+ return null;
7507
+ }
7508
+ const version = result.version?.replace(/^v/, "") ?? "unknown";
7509
+ return {
7510
+ version,
7511
+ path: result.path
7512
+ };
7513
+ }
7514
+ function versionInfoToSelectItem(v) {
7515
+ const item = {
7516
+ label: v.isPrerelease ? `${v.version} (pre)` : v.version,
7517
+ value: v.version
7518
+ };
7519
+ if (v.publishedAt) {
7520
+ item.description = new Date(v.publishedAt).toLocaleDateString();
7521
+ }
7522
+ return item;
7523
+ }
7524
+ function createInstalledOption(installed) {
7525
+ return {
7526
+ label: `installed@${installed.version}`,
7527
+ value: "installed",
7528
+ description: installed.path
7529
+ };
7530
+ }
7531
+ function getBunxAgentIds() {
7532
+ return BUILTIN_CODING_AGENTS.filter((a2) => a2.type === "bunx").map((a2) => a2.id);
7533
+ }
7534
+ var AGENT_COMMAND_MAP;
7535
+ var init_versionFetcher = __esm(() => {
7536
+ init_builtin_coding_agents();
7537
+ init_command3();
7538
+ AGENT_COMMAND_MAP = {
7539
+ "claude-code": "claude",
7540
+ "codex-cli": "codex",
7541
+ "gemini-cli": "gemini",
7542
+ opencode: "opencode"
7543
+ };
7544
+ });
7545
+
7212
7546
  // node_modules/pino-std-serializers/lib/err-helpers.js
7213
7547
  var require_err_helpers = __commonJS((exports, module2) => {
7214
7548
  var isErrorLike = (err) => {
@@ -42550,7 +42884,6 @@ var UNOWNED = {
42550
42884
  context: null,
42551
42885
  owner: null
42552
42886
  };
42553
- var NO_INIT = {};
42554
42887
  var Owner = null;
42555
42888
  var Transition = null;
42556
42889
  var Scheduler = null;
@@ -42594,13 +42927,6 @@ function createSignal(value, options) {
42594
42927
  };
42595
42928
  return [readSignal.bind(s), setter];
42596
42929
  }
42597
- function createComputed(fn, value, options) {
42598
- const c = createComputation(fn, value, true, STALE);
42599
- if (Scheduler && Transition && Transition.running)
42600
- Updates.push(c);
42601
- else
42602
- updateComputation(c);
42603
- }
42604
42930
  function createRenderEffect(fn, value, options) {
42605
42931
  const c = createComputation(fn, value, false, STALE);
42606
42932
  if (Scheduler && Transition && Transition.running)
@@ -42630,163 +42956,8 @@ function createMemo(fn, value, options) {
42630
42956
  updateComputation(c);
42631
42957
  return readSignal.bind(c);
42632
42958
  }
42633
- function isPromise(v) {
42634
- return v && typeof v === "object" && "then" in v;
42635
- }
42636
- function createResource(pSource, pFetcher, pOptions) {
42637
- let source;
42638
- let fetcher;
42639
- let options;
42640
- if (typeof pFetcher === "function") {
42641
- source = pSource;
42642
- fetcher = pFetcher;
42643
- options = pOptions || {};
42644
- } else {
42645
- source = true;
42646
- fetcher = pSource;
42647
- options = pFetcher || {};
42648
- }
42649
- let pr = null, initP = NO_INIT, id = null, loadedUnderTransition = false, scheduled = false, resolved = "initialValue" in options, dynamic = typeof source === "function" && createMemo(source);
42650
- const contexts = new Set, [value, setValue] = (options.storage || createSignal)(options.initialValue), [error, setError] = createSignal(undefined), [track, trigger] = createSignal(undefined, {
42651
- equals: false
42652
- }), [state, setState] = createSignal(resolved ? "ready" : "unresolved");
42653
- if (sharedConfig.context) {
42654
- id = sharedConfig.getNextContextId();
42655
- if (options.ssrLoadFrom === "initial")
42656
- initP = options.initialValue;
42657
- else if (sharedConfig.load && sharedConfig.has(id))
42658
- initP = sharedConfig.load(id);
42659
- }
42660
- function loadEnd(p, v, error2, key) {
42661
- if (pr === p) {
42662
- pr = null;
42663
- key !== undefined && (resolved = true);
42664
- if ((p === initP || v === initP) && options.onHydrated)
42665
- queueMicrotask(() => options.onHydrated(key, {
42666
- value: v
42667
- }));
42668
- initP = NO_INIT;
42669
- if (Transition && p && loadedUnderTransition) {
42670
- Transition.promises.delete(p);
42671
- loadedUnderTransition = false;
42672
- runUpdates(() => {
42673
- Transition.running = true;
42674
- completeLoad(v, error2);
42675
- }, false);
42676
- } else
42677
- completeLoad(v, error2);
42678
- }
42679
- return v;
42680
- }
42681
- function completeLoad(v, err) {
42682
- runUpdates(() => {
42683
- if (err === undefined)
42684
- setValue(() => v);
42685
- setState(err !== undefined ? "errored" : resolved ? "ready" : "unresolved");
42686
- setError(err);
42687
- for (const c of contexts.keys())
42688
- c.decrement();
42689
- contexts.clear();
42690
- }, false);
42691
- }
42692
- function read() {
42693
- const c = SuspenseContext && useContext(SuspenseContext), v = value(), err = error();
42694
- if (err !== undefined && !pr)
42695
- throw err;
42696
- if (Listener && !Listener.user && c) {
42697
- createComputed(() => {
42698
- track();
42699
- if (pr) {
42700
- if (c.resolved && Transition && loadedUnderTransition)
42701
- Transition.promises.add(pr);
42702
- else if (!contexts.has(c)) {
42703
- c.increment();
42704
- contexts.add(c);
42705
- }
42706
- }
42707
- });
42708
- }
42709
- return v;
42710
- }
42711
- function load(refetching = true) {
42712
- if (refetching !== false && scheduled)
42713
- return;
42714
- scheduled = false;
42715
- const lookup = dynamic ? dynamic() : source;
42716
- loadedUnderTransition = Transition && Transition.running;
42717
- if (lookup == null || lookup === false) {
42718
- loadEnd(pr, untrack(value));
42719
- return;
42720
- }
42721
- if (Transition && pr)
42722
- Transition.promises.delete(pr);
42723
- let error2;
42724
- const p = initP !== NO_INIT ? initP : untrack(() => {
42725
- try {
42726
- return fetcher(lookup, {
42727
- value: value(),
42728
- refetching
42729
- });
42730
- } catch (fetcherError) {
42731
- error2 = fetcherError;
42732
- }
42733
- });
42734
- if (error2 !== undefined) {
42735
- loadEnd(pr, undefined, castError(error2), lookup);
42736
- return;
42737
- } else if (!isPromise(p)) {
42738
- loadEnd(pr, p, undefined, lookup);
42739
- return p;
42740
- }
42741
- pr = p;
42742
- if ("v" in p) {
42743
- if (p.s === 1)
42744
- loadEnd(pr, p.v, undefined, lookup);
42745
- else
42746
- loadEnd(pr, undefined, castError(p.v), lookup);
42747
- return p;
42748
- }
42749
- scheduled = true;
42750
- queueMicrotask(() => scheduled = false);
42751
- runUpdates(() => {
42752
- setState(resolved ? "refreshing" : "pending");
42753
- trigger();
42754
- }, false);
42755
- return p.then((v) => loadEnd(p, v, undefined, lookup), (e) => loadEnd(p, undefined, castError(e), lookup));
42756
- }
42757
- Object.defineProperties(read, {
42758
- state: {
42759
- get: () => state()
42760
- },
42761
- error: {
42762
- get: () => error()
42763
- },
42764
- loading: {
42765
- get() {
42766
- const s = state();
42767
- return s === "pending" || s === "refreshing";
42768
- }
42769
- },
42770
- latest: {
42771
- get() {
42772
- if (!resolved)
42773
- return read();
42774
- const err = error();
42775
- if (err && !pr)
42776
- throw err;
42777
- return value();
42778
- }
42779
- }
42780
- });
42781
- let owner = Owner;
42782
- if (dynamic)
42783
- createComputed(() => (owner = Owner, load(false)));
42784
- else
42785
- load(false);
42786
- return [read, {
42787
- refetch: (info) => runWithOwner(owner, () => load(info)),
42788
- mutate: setValue
42789
- }];
42959
+ function batch(fn) {
42960
+ return runUpdates(fn, false);
42790
42961
  }
42791
42962
  function untrack(fn) {
42792
42963
  if (!ExternalSourceConfig && Listener === null)
@@ -42801,6 +42972,27 @@ function untrack(fn) {
42801
42972
  Listener = listener;
42802
42973
  }
42803
42974
  }
42975
+ function on(deps, fn, options) {
42976
+ const isArray = Array.isArray(deps);
42977
+ let prevInput;
42978
+ let defer = options && options.defer;
42979
+ return (prevValue) => {
42980
+ let input;
42981
+ if (isArray) {
42982
+ input = Array(deps.length);
42983
+ for (let i = 0;i < deps.length; i++)
42984
+ input[i] = deps[i]();
42985
+ } else
42986
+ input = deps();
42987
+ if (defer) {
42988
+ defer = false;
42989
+ return prevValue;
42990
+ }
42991
+ const result = untrack(() => fn(input, prevInput, prevValue));
42992
+ prevInput = input;
42993
+ return result;
42994
+ };
42995
+ }
42804
42996
  function onMount(fn) {
42805
42997
  createEffect(() => untrack(fn));
42806
42998
  }
@@ -42813,20 +43005,6 @@ function onCleanup(fn) {
42813
43005
  Owner.cleanups.push(fn);
42814
43006
  return fn;
42815
43007
  }
42816
- function runWithOwner(o, fn) {
42817
- const prev = Owner;
42818
- const prevListener = Listener;
42819
- Owner = o;
42820
- Listener = null;
42821
- try {
42822
- return runUpdates(fn, true);
42823
- } catch (err) {
42824
- handleError(err);
42825
- } finally {
42826
- Owner = prev;
42827
- Listener = prevListener;
42828
- }
42829
- }
42830
43008
  function startTransition(fn) {
42831
43009
  if (Transition && Transition.running) {
42832
43010
  fn();
@@ -44312,14 +44490,36 @@ function mapToolLabel(toolId, toolLabel) {
44312
44490
  return toolLabel;
44313
44491
  return "Custom";
44314
44492
  }
44493
+ var LOCAL_DATE_TIME_FORMATTER = new Intl.DateTimeFormat(undefined, {
44494
+ year: "numeric",
44495
+ month: "2-digit",
44496
+ day: "2-digit",
44497
+ hour: "2-digit",
44498
+ minute: "2-digit",
44499
+ hour12: false
44500
+ });
44501
+ var formatLocalDateTimeParts = (date) => {
44502
+ const parts = LOCAL_DATE_TIME_FORMATTER.formatToParts(date);
44503
+ const get = (type) => parts.find((part) => part.type === type)?.value;
44504
+ const year = get("year");
44505
+ const month = get("month");
44506
+ const day = get("day");
44507
+ const hour = get("hour");
44508
+ const minute = get("minute");
44509
+ if (!year || !month || !day || !hour || !minute) {
44510
+ return LOCAL_DATE_TIME_FORMATTER.format(date);
44511
+ }
44512
+ return `${year}-${month}-${day} ${hour}:${minute}`;
44513
+ };
44514
+ function formatLocalDateTime(timestampMs) {
44515
+ const date = new Date(timestampMs);
44516
+ if (Number.isNaN(date.getTime())) {
44517
+ return "";
44518
+ }
44519
+ return formatLocalDateTimeParts(date);
44520
+ }
44315
44521
  function formatTimestamp(ts) {
44316
- const date = new Date(ts);
44317
- const year = date.getFullYear();
44318
- const month = String(date.getMonth() + 1).padStart(2, "0");
44319
- const day = String(date.getDate()).padStart(2, "0");
44320
- const hours = String(date.getHours()).padStart(2, "0");
44321
- const minutes = String(date.getMinutes()).padStart(2, "0");
44322
- return `${year}-${month}-${day} ${hours}:${minutes}`;
44522
+ return formatLocalDateTime(ts);
44323
44523
  }
44324
44524
  function buildLastToolUsageLabel(usage) {
44325
44525
  if (!usage)
@@ -44616,6 +44816,98 @@ function Header({
44616
44816
  })();
44617
44817
  }
44618
44818
 
44819
+ // src/cli/ui/core/theme.ts
44820
+ var colors = {
44821
+ primary: "cyan",
44822
+ secondary: "gray",
44823
+ success: "green",
44824
+ warning: "yellow",
44825
+ error: "red",
44826
+ info: "blue",
44827
+ text: "white",
44828
+ textDim: "gray",
44829
+ textMuted: "gray",
44830
+ selected: "cyan",
44831
+ highlighted: "cyan",
44832
+ disabled: "gray",
44833
+ selectionBackground: "cyan",
44834
+ selectionText: "black",
44835
+ branchFeature: "green",
44836
+ branchBugfix: "yellow",
44837
+ branchHotfix: "red",
44838
+ branchRelease: "magenta",
44839
+ branchMain: "cyan",
44840
+ branchDevelop: "blue",
44841
+ branchOther: "gray",
44842
+ syncUpToDate: "green",
44843
+ syncAhead: "cyan",
44844
+ syncBehind: "yellow",
44845
+ syncDiverged: "red",
44846
+ syncNoUpstream: "gray",
44847
+ worktreeActive: "green",
44848
+ worktreeInaccessible: "red",
44849
+ progressFilled: "green",
44850
+ progressEmpty: "gray",
44851
+ progressPhase: "yellow",
44852
+ progressTime: "magenta"
44853
+ };
44854
+ var logLevelColors = {
44855
+ TRACE: colors.textDim,
44856
+ DEBUG: colors.info,
44857
+ INFO: colors.success,
44858
+ WARN: colors.warning,
44859
+ ERROR: colors.error,
44860
+ FATAL: colors.error
44861
+ };
44862
+ var selectionStyle = {
44863
+ fg: colors.selectionText,
44864
+ bg: colors.selectionBackground
44865
+ };
44866
+ var getLogLevelColor = (label) => {
44867
+ if (!label) {
44868
+ return colors.text;
44869
+ }
44870
+ const normalized = label.toUpperCase();
44871
+ return logLevelColors[normalized] ?? colors.text;
44872
+ };
44873
+ var icons = {
44874
+ pointer: ">",
44875
+ pointerBold: ">",
44876
+ arrowUp: "^",
44877
+ arrowDown: "v",
44878
+ arrowLeft: "<",
44879
+ arrowRight: ">",
44880
+ success: "OK",
44881
+ error: "X",
44882
+ warning: "!",
44883
+ info: "i",
44884
+ skipped: "-",
44885
+ worktree: "W",
44886
+ worktreeActive: "A",
44887
+ worktreeInaccessible: "X",
44888
+ changes: "C",
44889
+ unpushed: "U",
44890
+ current: "*",
44891
+ pr: "PR",
44892
+ merged: "M",
44893
+ syncUpToDate: "=",
44894
+ syncAhead: ">",
44895
+ syncBehind: "<",
44896
+ syncDiverged: "!",
44897
+ spinnerFrames: ["|", "/", "-", "\\"],
44898
+ bullet: "*",
44899
+ divider: "-",
44900
+ verticalLine: "|",
44901
+ corner: "+",
44902
+ branch: "+"
44903
+ };
44904
+ var statsItemsConfig = {
44905
+ local: { label: "Local", icon: "L", color: colors.primary },
44906
+ remote: { label: "Remote", icon: "R", color: colors.info },
44907
+ worktree: { label: "Worktrees", icon: icons.worktree, color: colors.success },
44908
+ changes: { label: "Changes", icon: icons.changes, color: colors.warning }
44909
+ };
44910
+
44619
44911
  // src/cli/ui/screens/solid/BranchListScreen.tsx
44620
44912
  var VIEW_MODES = ["all", "local", "remote"];
44621
44913
  var getCharWidth = (char) => stringWidth(char);
@@ -44724,8 +45016,8 @@ var fitSegmentsToWidth = (segments, width) => {
44724
45016
  };
44725
45017
  var applySelectionStyle = (segments) => segments.map((segment) => ({
44726
45018
  text: segment.text,
44727
- fg: "black",
44728
- bg: "cyan"
45019
+ fg: selectionStyle.fg,
45020
+ bg: selectionStyle.bg
44729
45021
  }));
44730
45022
  var CLEANUP_SPINNER_FRAMES = ["-", "\\", "|", "/"];
44731
45023
  var CURSOR_FRAMES = ["|", " "];
@@ -44805,7 +45097,13 @@ function BranchListScreen(props) {
44805
45097
  const [filterQuery, setFilterQuery] = createSignal("");
44806
45098
  const [filterMode, setFilterMode] = createSignal(false);
44807
45099
  const [viewMode, setViewMode] = createSignal("all");
44808
- const [selectedIndex, setSelectedIndex] = createSignal(0);
45100
+ const [internalSelectedIndex, setInternalSelectedIndex] = createSignal(props.cursorPosition ?? 0);
45101
+ const selectedIndex = () => props.cursorPosition ?? internalSelectedIndex();
45102
+ const setSelectedIndex = (value) => {
45103
+ const newValue = typeof value === "function" ? value(selectedIndex()) : value;
45104
+ setInternalSelectedIndex(newValue);
45105
+ props.onCursorPositionChange?.(newValue);
45106
+ };
44809
45107
  const [scrollOffset, setScrollOffset] = createSignal(0);
44810
45108
  const [cleanupSpinnerIndex, setCleanupSpinnerIndex] = createSignal(0);
44811
45109
  const [cursorIndex, setCursorIndex] = createSignal(0);
@@ -44833,7 +45131,14 @@ function BranchListScreen(props) {
44833
45131
  return Object.values(props.cleanupUI.indicators).some((indicator) => indicator.isSpinning);
44834
45132
  });
44835
45133
  const hasSpinningFooter = createMemo(() => props.cleanupUI?.footerMessage?.isSpinning ?? false);
44836
- const cleanupSpinnerActive = createMemo(() => hasSpinningIndicator() || hasSpinningFooter() || props.cleanupUI?.safetyLoading === true);
45134
+ const safetyPendingActive = createMemo(() => {
45135
+ const pending = props.cleanupUI?.safetyPendingBranches;
45136
+ if (pending) {
45137
+ return pending.size > 0;
45138
+ }
45139
+ return props.cleanupUI?.safetyLoading === true;
45140
+ });
45141
+ const cleanupSpinnerActive = createMemo(() => hasSpinningIndicator() || hasSpinningFooter() || safetyPendingActive());
44837
45142
  createEffect(() => {
44838
45143
  let intervalTimer;
44839
45144
  if (cleanupSpinnerActive()) {
@@ -44884,12 +45189,12 @@ function BranchListScreen(props) {
44884
45189
  }
44885
45190
  return maxWidth;
44886
45191
  });
44887
- createEffect(() => {
44888
- filterQuery();
44889
- viewMode();
45192
+ createEffect(on(() => [filterQuery(), viewMode()], () => {
44890
45193
  setSelectedIndex(0);
44891
45194
  setScrollOffset(0);
44892
- });
45195
+ }, {
45196
+ defer: true
45197
+ }));
44893
45198
  createEffect(() => {
44894
45199
  const total = filteredBranches().length;
44895
45200
  if (total === 0) {
@@ -44937,18 +45242,16 @@ function BranchListScreen(props) {
44937
45242
  if (!timestamp || Number.isNaN(timestamp)) {
44938
45243
  return "---";
44939
45244
  }
44940
- const date = new Date(timestamp * 1000);
44941
- const year = date.getFullYear();
44942
- const month = String(date.getMonth() + 1).padStart(2, "0");
44943
- const day = String(date.getDate()).padStart(2, "0");
44944
- const hours = String(date.getHours()).padStart(2, "0");
44945
- const minutes = String(date.getMinutes()).padStart(2, "0");
44946
- return `${year}-${month}-${day} ${hours}:${minutes}`;
45245
+ const formatted = formatLocalDateTime(timestamp * 1000);
45246
+ return formatted || "---";
44947
45247
  };
44948
45248
  useKeyboard((key) => {
44949
45249
  if (props.wizardVisible) {
44950
45250
  return;
44951
45251
  }
45252
+ if (props.confirmVisible) {
45253
+ return;
45254
+ }
44952
45255
  if (props.helpVisible) {
44953
45256
  return;
44954
45257
  }
@@ -45054,7 +45357,8 @@ function BranchListScreen(props) {
45054
45357
  } else if (key.name === "p" || key.sequence === "p") {
45055
45358
  props.onOpenProfiles?.();
45056
45359
  } else if (key.name === "l" || key.sequence === "l") {
45057
- props.onOpenLogs?.();
45360
+ const selected = filteredBranches()[selectedIndex()] ?? null;
45361
+ props.onOpenLogs?.(selected);
45058
45362
  }
45059
45363
  });
45060
45364
  const visibleBranches = createMemo(() => {
@@ -45082,19 +45386,24 @@ function BranchListScreen(props) {
45082
45386
  let worktreeColor = "gray";
45083
45387
  if (branch.worktreeStatus === "active") {
45084
45388
  worktreeIcon = "w";
45085
- worktreeColor = "green";
45389
+ worktreeColor = "brightGreen";
45086
45390
  } else if (branch.worktreeStatus === "inaccessible") {
45087
45391
  worktreeIcon = "x";
45088
45392
  worktreeColor = "red";
45089
45393
  }
45090
45394
  const isRemoteBranch = branch.type === "remote";
45091
45395
  const safetyLoading = props.cleanupUI?.safetyLoading === true;
45396
+ const safetyPendingBranches = props.cleanupUI?.safetyPendingBranches;
45397
+ const isSafetyPending = safetyPendingBranches ? safetyPendingBranches.has(branch.name) : safetyLoading;
45092
45398
  const spinnerFrame = cleanupSpinnerFrame();
45093
45399
  let safeIcon = " ";
45094
45400
  let safeColor;
45095
45401
  if (isRemoteBranch) {
45096
45402
  safeIcon = " ";
45097
45403
  safeColor = undefined;
45404
+ } else if (isSafetyPending) {
45405
+ safeIcon = spinnerFrame ?? "-";
45406
+ safeColor = undefined;
45098
45407
  } else if (hasUncommitted) {
45099
45408
  safeIcon = "!";
45100
45409
  safeColor = "red";
@@ -45104,12 +45413,9 @@ function BranchListScreen(props) {
45104
45413
  } else if (branch.isUnmerged) {
45105
45414
  safeIcon = "*";
45106
45415
  safeColor = "yellow";
45107
- } else if (safetyLoading) {
45108
- safeIcon = spinnerFrame ?? "-";
45109
- safeColor = undefined;
45110
45416
  } else if (branch.safeToCleanup === true) {
45111
- safeIcon = " ";
45112
- safeColor = undefined;
45417
+ safeIcon = "o";
45418
+ safeColor = "brightGreen";
45113
45419
  } else {
45114
45420
  safeIcon = "!";
45115
45421
  safeColor = "red";
@@ -45316,6 +45622,63 @@ function BranchListScreen(props) {
45316
45622
  }
45317
45623
  return fitSegmentsToWidth(segments, layoutWidth());
45318
45624
  });
45625
+ const statusLegendSegments = createMemo(() => {
45626
+ const segments = [];
45627
+ const separator = " ";
45628
+ appendSegment(segments, {
45629
+ text: "Legend: ",
45630
+ attributes: TextAttributes.DIM
45631
+ });
45632
+ appendSegment(segments, {
45633
+ text: "o",
45634
+ fg: "brightGreen",
45635
+ attributes: TextAttributes.BOLD
45636
+ });
45637
+ appendSegment(segments, {
45638
+ text: " Safe",
45639
+ fg: "brightGreen"
45640
+ });
45641
+ appendSegment(segments, {
45642
+ text: separator,
45643
+ attributes: TextAttributes.DIM
45644
+ });
45645
+ appendSegment(segments, {
45646
+ text: "!",
45647
+ fg: "red",
45648
+ attributes: TextAttributes.BOLD
45649
+ });
45650
+ appendSegment(segments, {
45651
+ text: " Uncommitted",
45652
+ fg: "red"
45653
+ });
45654
+ appendSegment(segments, {
45655
+ text: separator,
45656
+ attributes: TextAttributes.DIM
45657
+ });
45658
+ appendSegment(segments, {
45659
+ text: "!",
45660
+ fg: "yellow",
45661
+ attributes: TextAttributes.BOLD
45662
+ });
45663
+ appendSegment(segments, {
45664
+ text: " Unpushed",
45665
+ fg: "yellow"
45666
+ });
45667
+ appendSegment(segments, {
45668
+ text: separator,
45669
+ attributes: TextAttributes.DIM
45670
+ });
45671
+ appendSegment(segments, {
45672
+ text: "*",
45673
+ fg: "yellow",
45674
+ attributes: TextAttributes.BOLD
45675
+ });
45676
+ appendSegment(segments, {
45677
+ text: " Unmerged",
45678
+ fg: "yellow"
45679
+ });
45680
+ return fitSegmentsToWidth(segments, layoutWidth());
45681
+ });
45319
45682
  const footerSegments = createMemo(() => {
45320
45683
  const segments = [];
45321
45684
  const separator = " ";
@@ -45411,50 +45774,46 @@ function BranchListScreen(props) {
45411
45774
  }
45412
45775
  }, () => props.loadingIndicatorDelay !== undefined ? {
45413
45776
  delay: props.loadingIndicatorDelay
45414
- } : {})) : (() => {
45415
- var _el$7 = createElement("text");
45416
- insert(_el$7, () => padLine("", layoutWidth()));
45417
- return _el$7;
45418
- })();
45777
+ } : {})) : renderSegmentLine(statusLegendSegments());
45419
45778
  })(), null);
45420
45779
  insert(_el$5, (() => {
45421
45780
  var _c$2 = memo2(() => !!props.error);
45422
45781
  return () => _c$2() && [(() => {
45782
+ var _el$7 = createElement("text");
45783
+ setProp(_el$7, "fg", "red");
45784
+ insert(_el$7, () => padLine(`Error: ${props.error.message}`, layoutWidth()));
45785
+ effect((_$p) => setProp(_el$7, "attributes", TextAttributes.BOLD, _$p));
45786
+ return _el$7;
45787
+ })(), memo2(() => memo2(() => !!(process.env.DEBUG && props.error.stack))() && [(() => {
45423
45788
  var _el$8 = createElement("text");
45424
- setProp(_el$8, "fg", "red");
45425
- insert(_el$8, () => padLine(`Error: ${props.error.message}`, layoutWidth()));
45426
- effect((_$p) => setProp(_el$8, "attributes", TextAttributes.BOLD, _$p));
45789
+ insert(_el$8, () => padLine("", layoutWidth()));
45790
+ effect((_$p) => setProp(_el$8, "attributes", TextAttributes.DIM, _$p));
45427
45791
  return _el$8;
45428
- })(), memo2(() => memo2(() => !!(process.env.DEBUG && props.error.stack))() && [(() => {
45792
+ })(), memo2(() => props.error.stack.split(`
45793
+ `).map((line) => (() => {
45429
45794
  var _el$9 = createElement("text");
45430
- insert(_el$9, () => padLine("", layoutWidth()));
45795
+ setProp(_el$9, "fg", "gray");
45796
+ insert(_el$9, () => padLine(line, layoutWidth()));
45431
45797
  effect((_$p) => setProp(_el$9, "attributes", TextAttributes.DIM, _$p));
45432
45798
  return _el$9;
45433
- })(), memo2(() => props.error.stack.split(`
45434
- `).map((line) => (() => {
45435
- var _el$0 = createElement("text");
45436
- setProp(_el$0, "fg", "gray");
45437
- insert(_el$0, () => padLine(line, layoutWidth()));
45438
- effect((_$p) => setProp(_el$0, "attributes", TextAttributes.DIM, _$p));
45439
- return _el$0;
45440
45799
  })()))])];
45441
45800
  })(), null);
45442
45801
  insert(_el$5, (() => {
45443
45802
  var _c$3 = memo2(() => !!(!props.loading && !props.error && props.branches.length === 0));
45444
45803
  return () => _c$3() && (() => {
45445
- var _el$1 = createElement("text");
45446
- insert(_el$1, () => padLine("No branches found", layoutWidth()));
45447
- effect((_$p) => setProp(_el$1, "attributes", TextAttributes.DIM, _$p));
45448
- return _el$1;
45804
+ var _el$0 = createElement("text");
45805
+ insert(_el$0, () => padLine("No branches found", layoutWidth()));
45806
+ effect((_$p) => setProp(_el$0, "attributes", TextAttributes.DIM, _$p));
45807
+ return _el$0;
45449
45808
  })();
45450
45809
  })(), null);
45451
45810
  insert(_el$5, (() => {
45452
45811
  var _c$4 = memo2(() => !!(!props.loading && !props.error && props.branches.length > 0 && filteredBranches().length === 0 && filterQuery()));
45453
45812
  return () => _c$4() && (() => {
45454
- var _el$10 = createElement("text");
45455
- insert(_el$10, () => padLine("No branches match your filter", layoutWidth()));
45456
- effect((_$p) => setProp(_el$10, "attributes", TextAttributes.DIM, _$p));
45457
- return _el$10;
45813
+ var _el$1 = createElement("text");
45814
+ insert(_el$1, () => padLine("No branches match your filter", layoutWidth()));
45815
+ effect((_$p) => setProp(_el$1, "attributes", TextAttributes.DIM, _$p));
45816
+ return _el$1;
45458
45817
  })();
45459
45818
  })(), null);
45460
45819
  insert(_el$5, (() => {
@@ -45465,20 +45824,20 @@ function BranchListScreen(props) {
45465
45824
  })), memo2(() => Array.from({
45466
45825
  length: Math.max(0, contentHeight() - visibleBranches().length)
45467
45826
  }).map(() => (() => {
45468
- var _el$11 = createElement("text");
45469
- insert(_el$11, () => padLine("", listWidth()));
45470
- return _el$11;
45827
+ var _el$10 = createElement("text");
45828
+ insert(_el$10, () => padLine("", listWidth()));
45829
+ return _el$10;
45471
45830
  })()))];
45472
45831
  })(), null);
45473
45832
  insert(_el$4, (() => {
45474
45833
  var _c$6 = memo2(() => !!props.cleanupUI?.footerMessage);
45475
45834
  return () => _c$6() && (() => {
45476
- var _el$12 = createElement("text");
45477
- spread(_el$12, mergeProps3(() => props.cleanupUI.footerMessage.color ? {
45835
+ var _el$11 = createElement("text");
45836
+ spread(_el$11, mergeProps3(() => props.cleanupUI.footerMessage.color ? {
45478
45837
  fg: props.cleanupUI.footerMessage.color
45479
45838
  } : {}), true);
45480
- insert(_el$12, () => padLine(props.cleanupUI.footerMessage.isSpinning && cleanupSpinnerFrame() ? `${cleanupSpinnerFrame()} ${props.cleanupUI.footerMessage.text}` : props.cleanupUI.footerMessage.text, layoutWidth()));
45481
- return _el$12;
45839
+ insert(_el$11, () => padLine(props.cleanupUI.footerMessage.isSpinning && cleanupSpinnerFrame() ? `${cleanupSpinnerFrame()} ${props.cleanupUI.footerMessage.text}` : props.cleanupUI.footerMessage.text, layoutWidth()));
45840
+ return _el$11;
45482
45841
  })();
45483
45842
  })(), _el$6);
45484
45843
  insert(_el$6, () => padLine(`Worktree: ${selectedWorktreeLabel()}`, layoutWidth()));
@@ -46009,6 +46368,15 @@ function SelectInput(props) {
46009
46368
  },
46010
46369
  get height() {
46011
46370
  return computedHeight();
46371
+ },
46372
+ get selectedBackgroundColor() {
46373
+ return selectionStyle.bg;
46374
+ },
46375
+ get selectedTextColor() {
46376
+ return selectionStyle.fg;
46377
+ },
46378
+ get selectedDescriptionColor() {
46379
+ return selectionStyle.fg;
46012
46380
  }
46013
46381
  }, () => props.selectedIndex !== undefined && {
46014
46382
  selectedIndex: props.selectedIndex
@@ -46040,30 +46408,46 @@ function QuickStartStep(props) {
46040
46408
  props.onChooseDifferent();
46041
46409
  }
46042
46410
  });
46043
- const latestEntry = createMemo(() => props.history[0] ?? null);
46411
+ const buildSettingsDescription = (entry) => {
46412
+ const parts = [];
46413
+ if (entry.toolLabel) {
46414
+ parts.push(entry.toolLabel);
46415
+ } else if (entry.toolId) {
46416
+ parts.push(entry.toolId);
46417
+ }
46418
+ if (entry.model) {
46419
+ parts.push(entry.model);
46420
+ }
46421
+ if (entry.toolId === "codex-cli" && entry.reasoningLevel) {
46422
+ parts.push(entry.reasoningLevel);
46423
+ }
46424
+ return parts.join(", ");
46425
+ };
46044
46426
  const items = createMemo(() => {
46045
46427
  const result = [];
46046
- const entry = latestEntry();
46047
- if (entry) {
46048
- const reasoningInfo = entry.reasoningLevel ? `, ${entry.reasoningLevel}` : "";
46049
- const versionInfo = entry.toolVersion ? `@${entry.toolVersion}` : "";
46050
- const settingsDesc = `${entry.toolLabel}${versionInfo}, ${entry.model}${reasoningInfo}`;
46051
- const resumeDesc = entry.sessionId ? `${settingsDesc}, session ${entry.sessionId}` : settingsDesc;
46052
- result.push({
46053
- label: "Resume session (previous settings)",
46054
- value: `resume-${entry.toolId}`,
46055
- description: resumeDesc,
46056
- action: "resume",
46057
- entry
46058
- });
46428
+ props.history.forEach((entry, index) => {
46429
+ if (!entry)
46430
+ return;
46431
+ const settingsDesc = buildSettingsDescription(entry);
46432
+ const sessionId = entry.sessionId && entry.sessionId.trim().length > 0 ? entry.sessionId.trim() : null;
46433
+ const suffix = `${entry.toolId ?? "tool"}-${index}`;
46434
+ if (sessionId) {
46435
+ result.push({
46436
+ label: "Resume session (previous settings)",
46437
+ value: `resume-${suffix}`,
46438
+ description: `${settingsDesc} | Session: ${sessionId}`,
46439
+ action: "resume",
46440
+ entry
46441
+ });
46442
+ }
46059
46443
  result.push({
46060
46444
  label: "Start new (previous settings)",
46061
- value: `start-new-${entry.toolId}`,
46445
+ value: `start-new-${suffix}`,
46062
46446
  description: settingsDesc,
46063
46447
  action: "start-new",
46064
46448
  entry
46065
46449
  });
46066
- }
46450
+ });
46067
46451
  result.push({
46068
46452
  label: "Choose different settings...",
46069
46453
  value: "choose-different",
@@ -46327,6 +46711,19 @@ var MODEL_OPTIONS = {
46327
46711
  label: "Flash-Lite (gemini-2.5-flash-lite)",
46328
46712
  description: "Fastest for simple tasks"
46329
46713
  }
46714
+ ],
46715
+ opencode: [
46716
+ {
46717
+ id: "",
46718
+ label: "Default (Auto)",
46719
+ description: "Use OpenCode default model",
46720
+ isDefault: true
46721
+ },
46722
+ {
46723
+ id: "__custom__",
46724
+ label: "Custom (provider/model)",
46725
+ description: "Enter a provider/model identifier"
46726
+ }
46330
46727
  ]
46331
46728
  };
46332
46729
  function getModelOptions(tool) {
@@ -46356,6 +46753,9 @@ function normalizeModelId(tool, model) {
46356
46753
  const trimmed = model.trim();
46357
46754
  if (!trimmed)
46358
46755
  return null;
46756
+ if (tool === "opencode" && trimmed === "__custom__") {
46757
+ return null;
46758
+ }
46359
46759
  if (tool === "claude-code") {
46360
46760
  const lower = trimmed.toLowerCase();
46361
46761
  if (lower === "opuss")
@@ -46366,257 +46766,55 @@ function normalizeModelId(tool, model) {
46366
46766
  return trimmed;
46367
46767
  }
46368
46768
 
46369
- // src/utils/npmRegistry.ts
46370
- var DEFAULT_TIMEOUT_MS = 3000;
46371
- var DEFAULT_LIMIT = 10;
46372
- function isPrerelease(version) {
46373
- return /-(alpha|beta|rc|canary|next|dev|pre)\b/i.test(version);
46374
- }
46375
- async function fetchPackageVersions(packageName, limit = DEFAULT_LIMIT, timeoutMs = DEFAULT_TIMEOUT_MS) {
46376
- try {
46377
- const controller = new AbortController;
46378
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
46379
- const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, {
46380
- signal: controller.signal,
46381
- headers: {
46382
- Accept: "application/json"
46383
- }
46384
- });
46385
- clearTimeout(timeoutId);
46386
- if (!response.ok) {
46387
- return [];
46388
- }
46389
- const data = await response.json();
46390
- if (!data.versions || !data.time) {
46391
- return [];
46392
- }
46393
- const versionsWithTime = [];
46394
- for (const version of Object.keys(data.versions)) {
46395
- const publishedAt = data.time[version];
46396
- if (publishedAt) {
46397
- versionsWithTime.push({ version, publishedAt });
46398
- }
46399
- }
46400
- versionsWithTime.sort((a, b) => {
46401
- const dateA = new Date(a.publishedAt).getTime();
46402
- const dateB = new Date(b.publishedAt).getTime();
46403
- return dateB - dateA;
46404
- });
46405
- const topVersions = versionsWithTime.slice(0, limit);
46406
- return topVersions.map((v) => ({
46407
- version: v.version,
46408
- isPrerelease: isPrerelease(v.version),
46409
- publishedAt: v.publishedAt
46410
- }));
46411
- } catch {
46412
- return [];
46413
- }
46769
+ // src/cli/ui/utils/versionCache.ts
46770
+ var versionCache = new Map;
46771
+ function getVersionCache(agentId) {
46772
+ const cached = versionCache.get(agentId);
46773
+ return cached !== undefined ? cached : null;
46414
46774
  }
46415
- function parsePackageCommand(command) {
46416
- if (command.startsWith("@")) {
46417
- const firstSlash = command.indexOf("/");
46418
- if (firstSlash === -1) {
46419
- return { packageName: command, version: null };
46420
- }
46421
- const afterScope = command.substring(firstSlash + 1);
46422
- const atIndex2 = afterScope.indexOf("@");
46423
- if (atIndex2 === -1) {
46424
- return { packageName: command, version: null };
46425
- }
46426
- const packageName2 = command.substring(0, firstSlash + 1 + atIndex2);
46427
- const version2 = afterScope.substring(atIndex2 + 1);
46428
- return { packageName: packageName2, version: version2 };
46429
- }
46430
- const atIndex = command.indexOf("@");
46431
- if (atIndex === -1) {
46432
- return { packageName: command, version: null };
46775
+ async function prefetchAgentVersions(agentIds, fetchFn) {
46776
+ const fetcher = fetchFn ?? (async (agentId) => {
46777
+ const { fetchVersionOptionsForAgent: fetchVersionOptionsForAgent2 } = await Promise.resolve().then(() => (init_versionFetcher(), exports_versionFetcher));
46778
+ return fetchVersionOptionsForAgent2(agentId);
46779
+ });
46780
+ const results = await Promise.allSettled(agentIds.map(async (agentId) => {
46781
+ try {
46782
+ const versions = await fetcher(agentId);
46783
+ versionCache.set(agentId, versions);
46784
+ } catch {}
46785
+ }));
46786
+ for (let i2 = 0;i2 < results.length; i2++) {
46787
+ const result = results[i2];
46788
+ if (result && result.status === "rejected") {}
46433
46789
  }
46434
- const packageName = command.substring(0, atIndex);
46435
- const version = command.substring(atIndex + 1);
46436
- return { packageName, version };
46437
46790
  }
46438
46791
 
46439
- // src/shared/codingAgentConstants.ts
46440
- var CLAUDE_PERMISSION_SKIP_ARGS = [
46441
- "--dangerously-skip-permissions"
46442
- ];
46443
- var CODEX_DEFAULT_ARGS = [
46444
- "--enable",
46445
- "web_search_request",
46446
- "--model=gpt-5.2-codex",
46447
- "--sandbox",
46448
- "workspace-write",
46449
- "-c",
46450
- "model_reasoning_effort=high",
46451
- "-c",
46452
- "model_reasoning_summaries=detailed",
46453
- "-c",
46454
- "sandbox_workspace_write.network_access=true",
46455
- "-c",
46456
- "shell_environment_policy.inherit=all",
46457
- "-c",
46458
- "shell_environment_policy.ignore_default_excludes=true",
46459
- "-c",
46460
- "shell_environment_policy.experimental_use_profile=true"
46461
- ];
46462
-
46463
- // src/config/builtin-coding-agents.ts
46464
- var CLAUDE_CODE_TOOL = {
46465
- id: "claude-code",
46466
- displayName: "Claude Code",
46467
- type: "bunx",
46468
- command: "@anthropic-ai/claude-code",
46469
- modeArgs: {
46470
- normal: [],
46471
- continue: ["-c"],
46472
- resume: ["-r"]
46473
- },
46474
- permissionSkipArgs: Array.from(CLAUDE_PERMISSION_SKIP_ARGS),
46475
- env: {
46476
- ENABLE_LSP_TOOL: "true"
46477
- }
46478
- };
46479
- var CODEX_CLI_TOOL = {
46480
- id: "codex-cli",
46481
- displayName: "Codex",
46482
- type: "bunx",
46483
- command: "@openai/codex",
46484
- defaultArgs: Array.from(CODEX_DEFAULT_ARGS),
46485
- modeArgs: {
46486
- normal: [],
46487
- continue: ["resume", "--last"],
46488
- resume: ["resume"]
46489
- }
46490
- };
46491
- var GEMINI_CLI_TOOL = {
46492
- id: "gemini-cli",
46493
- displayName: "Gemini",
46494
- type: "bunx",
46495
- command: "@google/gemini-cli",
46496
- modeArgs: {
46497
- normal: [],
46498
- continue: ["-r", "latest"],
46499
- resume: ["-r", "latest"]
46500
- },
46501
- permissionSkipArgs: ["-y"]
46502
- };
46503
- var OPENCODE_TOOL = {
46504
- id: "opencode",
46505
- displayName: "OpenCode",
46506
- type: "bunx",
46507
- command: "opencode-ai",
46508
- modeArgs: {
46509
- normal: [],
46510
- continue: ["-c"],
46511
- resume: ["-s"]
46512
- }
46513
- };
46514
- var BUILTIN_CODING_AGENTS = [
46515
- CLAUDE_CODE_TOOL,
46516
- CODEX_CLI_TOOL,
46517
- GEMINI_CLI_TOOL,
46518
- OPENCODE_TOOL
46519
- ];
46792
+ // src/cli/ui/components/solid/WizardSteps.tsx
46793
+ init_versionFetcher();
46520
46794
 
46521
- // src/utils/command.ts
46522
- init_execa();
46523
- import { existsSync as existsSync3 } from "fs";
46524
- import { homedir } from "os";
46525
- import { join as join2 } from "path";
46526
- var KNOWN_INSTALL_PATHS = {
46527
- claude: {
46528
- unix: [
46529
- join2(homedir(), ".bun", "bin", "claude"),
46530
- join2(homedir(), ".local", "bin", "claude"),
46531
- "/usr/local/bin/claude"
46532
- ],
46533
- win32: [
46534
- join2(process.env.LOCALAPPDATA ?? "", "Programs", "claude", "claude.exe"),
46535
- join2(homedir(), ".bun", "bin", "claude.exe")
46536
- ]
46537
- },
46538
- codex: {
46539
- unix: [
46540
- join2(homedir(), ".bun", "bin", "codex"),
46541
- join2(homedir(), ".local", "bin", "codex"),
46542
- "/usr/local/bin/codex"
46543
- ],
46544
- win32: [join2(homedir(), ".bun", "bin", "codex.exe")]
46545
- },
46546
- gemini: {
46547
- unix: [
46548
- join2(homedir(), ".bun", "bin", "gemini"),
46549
- join2(homedir(), ".local", "bin", "gemini"),
46550
- "/usr/local/bin/gemini"
46551
- ],
46552
- win32: [join2(homedir(), ".bun", "bin", "gemini.exe")]
46553
- },
46554
- opencode: {
46555
- unix: [
46556
- join2(homedir(), ".bun", "bin", "opencode"),
46557
- join2(homedir(), ".local", "bin", "opencode"),
46558
- "/usr/local/bin/opencode"
46559
- ],
46560
- win32: [join2(homedir(), ".bun", "bin", "opencode.exe")]
46561
- }
46562
- };
46563
- var commandLookupCache = new Map;
46564
- async function getCommandVersion(commandPath) {
46565
- try {
46566
- const result = await execa(commandPath, ["--version"], {
46567
- timeout: 3000,
46568
- stdin: "ignore",
46569
- stdout: "pipe",
46570
- stderr: "ignore"
46571
- });
46572
- const match = result.stdout.match(/(\d+\.\d+(?:\.\d+)?(?:-[\w.]+)?)/);
46573
- return match ? `v${match[1]}` : null;
46574
- } catch {
46575
- return null;
46576
- }
46795
+ // src/cli/ui/utils/installedVersionCache.ts
46796
+ init_versionFetcher();
46797
+ var installedVersionCache = new Map;
46798
+ function getInstalledVersionCache(agentId) {
46799
+ const cached = installedVersionCache.get(agentId);
46800
+ return cached ?? null;
46577
46801
  }
46578
- async function findCommand(commandName) {
46579
- const cached = commandLookupCache.get(commandName);
46580
- if (cached) {
46581
- return cached;
46582
- }
46583
- let lookupResult = null;
46584
- try {
46585
- const lookupCommand = process.platform === "win32" ? "where" : "which";
46586
- const execResult = await execa(lookupCommand, [commandName], {
46587
- shell: true,
46588
- stdin: "ignore",
46589
- stdout: "pipe",
46590
- stderr: "ignore"
46591
- });
46592
- const foundPath = execResult.stdout.trim().split(`
46593
- `)[0];
46594
- if (foundPath) {
46595
- lookupResult = { available: true, path: foundPath, source: "installed" };
46596
- }
46597
- } catch {}
46598
- if (!lookupResult) {
46599
- const knownPaths = KNOWN_INSTALL_PATHS[commandName];
46600
- if (knownPaths) {
46601
- const pathsToCheck = process.platform === "win32" ? knownPaths.win32 : knownPaths.unix;
46602
- for (const p of pathsToCheck) {
46603
- if (p && existsSync3(p)) {
46604
- lookupResult = { available: true, path: p, source: "installed" };
46605
- break;
46606
- }
46607
- }
46802
+ function setInstalledVersionCache(agentId, installed) {
46803
+ installedVersionCache.set(agentId, installed);
46804
+ }
46805
+ async function prefetchInstalledVersions(agentIds, fetchFn) {
46806
+ const fetcher = fetchFn ?? (async (agentId) => fetchInstalledVersionForAgent(agentId));
46807
+ const results = await Promise.allSettled(agentIds.map(async (agentId) => {
46808
+ try {
46809
+ const installed = await fetcher(agentId);
46810
+ setInstalledVersionCache(agentId, installed);
46811
+ } catch {
46812
+ setInstalledVersionCache(agentId, null);
46608
46813
  }
46814
+ }));
46815
+ for (const result of results) {
46816
+ if (result.status === "rejected") {}
46609
46817
  }
46610
- if (!lookupResult) {
46611
- lookupResult = { available: true, path: null, source: "bunx" };
46612
- }
46613
- if (lookupResult.source === "installed" && lookupResult.path) {
46614
- lookupResult.version = await getCommandVersion(lookupResult.path);
46615
- } else {
46616
- lookupResult.version = null;
46617
- }
46618
- commandLookupCache.set(commandName, lookupResult);
46619
- return lookupResult;
46620
46818
  }
46621
46819
 
46622
46820
  // src/cli/ui/components/solid/WizardSteps.tsx
@@ -46929,9 +47127,16 @@ function AgentSelectStep(props) {
46929
47127
  return isSelected() ? (() => {
46930
47128
  var _el$39 = createElement("text"), _el$40 = createTextNode(`> `);
46931
47129
  insertNode(_el$39, _el$40);
46932
- setProp(_el$39, "bg", "cyan");
46933
- setProp(_el$39, "fg", "black");
46934
47130
  insert(_el$39, () => agent.label, null);
47131
+ effect((_p$) => {
47132
+ var _v$9 = selectionStyle.bg, _v$0 = selectionStyle.fg;
47133
+ _v$9 !== _p$.e && (_p$.e = setProp(_el$39, "bg", _v$9, _p$.e));
47134
+ _v$0 !== _p$.t && (_p$.t = setProp(_el$39, "fg", _v$0, _p$.t));
47135
+ return _p$;
47136
+ }, {
47137
+ e: undefined,
47138
+ t: undefined
47139
+ });
46935
47140
  return _el$39;
46936
47141
  })() : (() => {
46937
47142
  var _el$41 = createElement("text"), _el$42 = createTextNode(` `);
@@ -47023,9 +47228,9 @@ function ModelSelectStep(props) {
47023
47228
  insertNode(_el$48, createTextNode(` `));
47024
47229
  insertNode(_el$50, createTextNode(`[Enter] Select [Esc] Back`));
47025
47230
  effect((_p$) => {
47026
- var _v$9 = TextAttributes.BOLD, _v$0 = TextAttributes.DIM;
47027
- _v$9 !== _p$.e && (_p$.e = setProp(_el$44, "attributes", _v$9, _p$.e));
47028
- _v$0 !== _p$.t && (_p$.t = setProp(_el$50, "attributes", _v$0, _p$.t));
47231
+ var _v$1 = TextAttributes.BOLD, _v$10 = TextAttributes.DIM;
47232
+ _v$1 !== _p$.e && (_p$.e = setProp(_el$44, "attributes", _v$1, _p$.e));
47233
+ _v$10 !== _p$.t && (_p$.t = setProp(_el$50, "attributes", _v$10, _p$.t));
47029
47234
  return _p$;
47030
47235
  }, {
47031
47236
  e: undefined,
@@ -47034,6 +47239,61 @@ function ModelSelectStep(props) {
47034
47239
  return _el$43;
47035
47240
  })();
47036
47241
  }
47242
+ function ModelInputStep(props) {
47243
+ const [value, setValue] = createSignal("");
47244
+ const scroll = useWizardScroll();
47245
+ const placeholder = props.agentId === "opencode" ? "provider/model" : "model";
47246
+ createEffect(() => {
47247
+ if (props.focused === false) {
47248
+ return;
47249
+ }
47250
+ if (!scroll) {
47251
+ return;
47252
+ }
47253
+ scroll.ensureLineVisible(2);
47254
+ });
47255
+ const handleSubmit = (next) => {
47256
+ const trimmed = next.trim();
47257
+ if (!trimmed) {
47258
+ return;
47259
+ }
47260
+ props.onSubmit(trimmed);
47261
+ };
47262
+ return (() => {
47263
+ var _el$52 = createElement("box"), _el$53 = createElement("text"), _el$55 = createElement("text"), _el$57 = createElement("text"), _el$59 = createElement("text");
47264
+ insertNode(_el$52, _el$53);
47265
+ insertNode(_el$52, _el$55);
47266
+ insertNode(_el$52, _el$57);
47267
+ insertNode(_el$52, _el$59);
47268
+ setProp(_el$52, "flexDirection", "column");
47269
+ insertNode(_el$53, createTextNode(`Enter custom model:`));
47270
+ setProp(_el$53, "fg", "cyan");
47271
+ insertNode(_el$55, createTextNode(` `));
47272
+ insert(_el$52, createComponent2(TextInput, {
47273
+ get value() {
47274
+ return value();
47275
+ },
47276
+ onChange: setValue,
47277
+ onSubmit: handleSubmit,
47278
+ placeholder,
47279
+ get focused() {
47280
+ return props.focused ?? true;
47281
+ }
47282
+ }), _el$57);
47283
+ insertNode(_el$57, createTextNode(` `));
47284
+ insertNode(_el$59, createTextNode(`[Enter] Submit [Esc] Back`));
47285
+ effect((_p$) => {
47286
+ var _v$11 = TextAttributes.BOLD, _v$12 = TextAttributes.DIM;
47287
+ _v$11 !== _p$.e && (_p$.e = setProp(_el$53, "attributes", _v$11, _p$.e));
47288
+ _v$12 !== _p$.t && (_p$.t = setProp(_el$59, "attributes", _v$12, _p$.t));
47289
+ return _p$;
47290
+ }, {
47291
+ e: undefined,
47292
+ t: undefined
47293
+ });
47294
+ return _el$52;
47295
+ })();
47296
+ }
47037
47297
  var REASONING_LEVELS = [{
47038
47298
  label: "low",
47039
47299
  value: "low",
@@ -47071,16 +47331,16 @@ function ReasoningLevelStep(props) {
47071
47331
  }
47072
47332
  };
47073
47333
  return (() => {
47074
- var _el$52 = createElement("box"), _el$53 = createElement("text"), _el$55 = createElement("text"), _el$57 = createElement("text"), _el$59 = createElement("text");
47075
- insertNode(_el$52, _el$53);
47076
- insertNode(_el$52, _el$55);
47077
- insertNode(_el$52, _el$57);
47078
- insertNode(_el$52, _el$59);
47079
- setProp(_el$52, "flexDirection", "column");
47080
- insertNode(_el$53, createTextNode(`Select reasoning level:`));
47081
- setProp(_el$53, "fg", "cyan");
47082
- insertNode(_el$55, createTextNode(` `));
47083
- insert(_el$52, createComponent2(SelectInput, {
47334
+ var _el$61 = createElement("box"), _el$62 = createElement("text"), _el$64 = createElement("text"), _el$66 = createElement("text"), _el$68 = createElement("text");
47335
+ insertNode(_el$61, _el$62);
47336
+ insertNode(_el$61, _el$64);
47337
+ insertNode(_el$61, _el$66);
47338
+ insertNode(_el$61, _el$68);
47339
+ setProp(_el$61, "flexDirection", "column");
47340
+ insertNode(_el$62, createTextNode(`Select reasoning level:`));
47341
+ setProp(_el$62, "fg", "cyan");
47342
+ insertNode(_el$64, createTextNode(` `));
47343
+ insert(_el$61, createComponent2(SelectInput, {
47084
47344
  items: REASONING_LEVELS,
47085
47345
  onSelect: (item) => props.onSelect(item.value),
47086
47346
  onChange: handleChange,
@@ -47088,19 +47348,19 @@ function ReasoningLevelStep(props) {
47088
47348
  return props.focused ?? true;
47089
47349
  },
47090
47350
  selectRef: setSelectRef
47091
- }), _el$57);
47092
- insertNode(_el$57, createTextNode(` `));
47093
- insertNode(_el$59, createTextNode(`[Enter] Select [Esc] Back`));
47351
+ }), _el$66);
47352
+ insertNode(_el$66, createTextNode(` `));
47353
+ insertNode(_el$68, createTextNode(`[Enter] Select [Esc] Back`));
47094
47354
  effect((_p$) => {
47095
- var _v$1 = TextAttributes.BOLD, _v$10 = TextAttributes.DIM;
47096
- _v$1 !== _p$.e && (_p$.e = setProp(_el$53, "attributes", _v$1, _p$.e));
47097
- _v$10 !== _p$.t && (_p$.t = setProp(_el$59, "attributes", _v$10, _p$.t));
47355
+ var _v$13 = TextAttributes.BOLD, _v$14 = TextAttributes.DIM;
47356
+ _v$13 !== _p$.e && (_p$.e = setProp(_el$62, "attributes", _v$13, _p$.e));
47357
+ _v$14 !== _p$.t && (_p$.t = setProp(_el$68, "attributes", _v$14, _p$.t));
47098
47358
  return _p$;
47099
47359
  }, {
47100
47360
  e: undefined,
47101
47361
  t: undefined
47102
47362
  });
47103
- return _el$52;
47363
+ return _el$61;
47104
47364
  })();
47105
47365
  }
47106
47366
  var EXECUTION_MODES = [{
@@ -47136,16 +47396,16 @@ function ExecutionModeStep(props) {
47136
47396
  }
47137
47397
  };
47138
47398
  return (() => {
47139
- var _el$61 = createElement("box"), _el$62 = createElement("text"), _el$64 = createElement("text"), _el$66 = createElement("text"), _el$68 = createElement("text");
47140
- insertNode(_el$61, _el$62);
47141
- insertNode(_el$61, _el$64);
47142
- insertNode(_el$61, _el$66);
47143
- insertNode(_el$61, _el$68);
47144
- setProp(_el$61, "flexDirection", "column");
47145
- insertNode(_el$62, createTextNode(`Select execution mode:`));
47146
- setProp(_el$62, "fg", "cyan");
47147
- insertNode(_el$64, createTextNode(` `));
47148
- insert(_el$61, createComponent2(SelectInput, {
47399
+ var _el$70 = createElement("box"), _el$71 = createElement("text"), _el$73 = createElement("text"), _el$75 = createElement("text"), _el$77 = createElement("text");
47400
+ insertNode(_el$70, _el$71);
47401
+ insertNode(_el$70, _el$73);
47402
+ insertNode(_el$70, _el$75);
47403
+ insertNode(_el$70, _el$77);
47404
+ setProp(_el$70, "flexDirection", "column");
47405
+ insertNode(_el$71, createTextNode(`Select execution mode:`));
47406
+ setProp(_el$71, "fg", "cyan");
47407
+ insertNode(_el$73, createTextNode(` `));
47408
+ insert(_el$70, createComponent2(SelectInput, {
47149
47409
  items: EXECUTION_MODES,
47150
47410
  onSelect: (item) => props.onSelect(item.value),
47151
47411
  onChange: handleChange,
@@ -47153,19 +47413,19 @@ function ExecutionModeStep(props) {
47153
47413
  return props.focused ?? true;
47154
47414
  },
47155
47415
  selectRef: setSelectRef
47156
- }), _el$66);
47157
- insertNode(_el$66, createTextNode(` `));
47158
- insertNode(_el$68, createTextNode(`[Enter] Select [Esc] Back`));
47416
+ }), _el$75);
47417
+ insertNode(_el$75, createTextNode(` `));
47418
+ insertNode(_el$77, createTextNode(`[Enter] Select [Esc] Back`));
47159
47419
  effect((_p$) => {
47160
- var _v$11 = TextAttributes.BOLD, _v$12 = TextAttributes.DIM;
47161
- _v$11 !== _p$.e && (_p$.e = setProp(_el$62, "attributes", _v$11, _p$.e));
47162
- _v$12 !== _p$.t && (_p$.t = setProp(_el$68, "attributes", _v$12, _p$.t));
47420
+ var _v$15 = TextAttributes.BOLD, _v$16 = TextAttributes.DIM;
47421
+ _v$15 !== _p$.e && (_p$.e = setProp(_el$71, "attributes", _v$15, _p$.e));
47422
+ _v$16 !== _p$.t && (_p$.t = setProp(_el$77, "attributes", _v$16, _p$.t));
47163
47423
  return _p$;
47164
47424
  }, {
47165
47425
  e: undefined,
47166
47426
  t: undefined
47167
47427
  });
47168
- return _el$61;
47428
+ return _el$70;
47169
47429
  })();
47170
47430
  }
47171
47431
  var SKIP_OPTIONS = [{
@@ -47197,16 +47457,16 @@ function SkipPermissionsStep(props) {
47197
47457
  }
47198
47458
  };
47199
47459
  return (() => {
47200
- var _el$70 = createElement("box"), _el$71 = createElement("text"), _el$73 = createElement("text"), _el$75 = createElement("text"), _el$77 = createElement("text");
47201
- insertNode(_el$70, _el$71);
47202
- insertNode(_el$70, _el$73);
47203
- insertNode(_el$70, _el$75);
47204
- insertNode(_el$70, _el$77);
47205
- setProp(_el$70, "flexDirection", "column");
47206
- insertNode(_el$71, createTextNode(`Skip permission prompts?`));
47207
- setProp(_el$71, "fg", "cyan");
47208
- insertNode(_el$73, createTextNode(` `));
47209
- insert(_el$70, createComponent2(SelectInput, {
47460
+ var _el$79 = createElement("box"), _el$80 = createElement("text"), _el$82 = createElement("text"), _el$84 = createElement("text"), _el$86 = createElement("text");
47461
+ insertNode(_el$79, _el$80);
47462
+ insertNode(_el$79, _el$82);
47463
+ insertNode(_el$79, _el$84);
47464
+ insertNode(_el$79, _el$86);
47465
+ setProp(_el$79, "flexDirection", "column");
47466
+ insertNode(_el$80, createTextNode(`Skip permission prompts?`));
47467
+ setProp(_el$80, "fg", "cyan");
47468
+ insertNode(_el$82, createTextNode(` `));
47469
+ insert(_el$79, createComponent2(SelectInput, {
47210
47470
  items: SKIP_OPTIONS,
47211
47471
  onSelect: (item) => props.onSelect(item.value === "true"),
47212
47472
  onChange: handleChange,
@@ -47214,19 +47474,19 @@ function SkipPermissionsStep(props) {
47214
47474
  return props.focused ?? true;
47215
47475
  },
47216
47476
  selectRef: setSelectRef
47217
- }), _el$75);
47218
- insertNode(_el$75, createTextNode(` `));
47219
- insertNode(_el$77, createTextNode(`[Enter] Select [Esc] Back`));
47477
+ }), _el$84);
47478
+ insertNode(_el$84, createTextNode(` `));
47479
+ insertNode(_el$86, createTextNode(`[Enter] Select [Esc] Back`));
47220
47480
  effect((_p$) => {
47221
- var _v$13 = TextAttributes.BOLD, _v$14 = TextAttributes.DIM;
47222
- _v$13 !== _p$.e && (_p$.e = setProp(_el$71, "attributes", _v$13, _p$.e));
47223
- _v$14 !== _p$.t && (_p$.t = setProp(_el$77, "attributes", _v$14, _p$.t));
47481
+ var _v$17 = TextAttributes.BOLD, _v$18 = TextAttributes.DIM;
47482
+ _v$17 !== _p$.e && (_p$.e = setProp(_el$80, "attributes", _v$17, _p$.e));
47483
+ _v$18 !== _p$.t && (_p$.t = setProp(_el$86, "attributes", _v$18, _p$.t));
47224
47484
  return _p$;
47225
47485
  }, {
47226
47486
  e: undefined,
47227
47487
  t: undefined
47228
47488
  });
47229
- return _el$70;
47489
+ return _el$79;
47230
47490
  })();
47231
47491
  }
47232
47492
  var LATEST_OPTION = {
@@ -47234,60 +47494,20 @@ var LATEST_OPTION = {
47234
47494
  value: "latest",
47235
47495
  description: "Always fetch latest version"
47236
47496
  };
47237
- function getPackageNameForAgent(agentId) {
47238
- const agent = BUILTIN_CODING_AGENTS.find((a2) => a2.id === agentId);
47239
- if (!agent || agent.type !== "bunx") {
47240
- return null;
47241
- }
47242
- const {
47243
- packageName
47244
- } = parsePackageCommand(agent.command);
47245
- return packageName;
47246
- }
47247
- async function fetchVersionOptions(agentId) {
47248
- const packageName = getPackageNameForAgent(agentId);
47249
- if (!packageName) {
47250
- return [];
47251
- }
47252
- const versions = await fetchPackageVersions(packageName);
47253
- return versions.map((v) => {
47254
- const item = {
47255
- label: v.isPrerelease ? `${v.version} (pre)` : v.version,
47256
- value: v.version
47257
- };
47258
- if (v.publishedAt) {
47259
- item.description = new Date(v.publishedAt).toLocaleDateString();
47260
- }
47261
- return item;
47262
- });
47263
- }
47264
- var AGENT_COMMAND_MAP = {
47265
- "claude-code": "claude",
47266
- "codex-cli": "codex",
47267
- "gemini-cli": "gemini",
47268
- opencode: "opencode"
47269
- };
47270
- async function fetchInstalledOption(agentId) {
47271
- const commandName = AGENT_COMMAND_MAP[agentId];
47272
- if (!commandName) {
47273
- return null;
47274
- }
47275
- const result = await findCommand(commandName);
47276
- if (result.source !== "installed" || !result.path) {
47277
- return null;
47278
- }
47279
- const version = result.version?.replace(/^v/, "") ?? "unknown";
47280
- return {
47281
- label: `installed@${version}`,
47282
- value: "installed",
47283
- description: result.path
47284
- };
47285
- }
47286
47497
  function VersionSelectStep(props) {
47287
47498
  const [selectedIndex, setSelectedIndex] = createSignal(0);
47288
47499
  const [selectRef, setSelectRef] = createSignal(undefined);
47289
- const [versionOptions] = createResource(() => props.agentId, fetchVersionOptions);
47290
- const [installedOption] = createResource(() => props.agentId, fetchInstalledOption);
47500
+ const cachedVersions = () => {
47501
+ const cached = getVersionCache(props.agentId);
47502
+ if (!cached) {
47503
+ return [];
47504
+ }
47505
+ return cached.map(versionInfoToSelectItem);
47506
+ };
47507
+ const installedOption = () => {
47508
+ const installed = getInstalledVersionCache(props.agentId);
47509
+ return installed ? createInstalledOption(installed) : null;
47510
+ };
47291
47511
  const allOptions = () => {
47292
47512
  const options = [];
47293
47513
  const installed = installedOption();
@@ -47295,8 +47515,8 @@ function VersionSelectStep(props) {
47295
47515
  options.push(installed);
47296
47516
  }
47297
47517
  options.push(LATEST_OPTION);
47298
- const dynamic = versionOptions() ?? [];
47299
- options.push(...dynamic);
47518
+ const cached = cachedVersions();
47519
+ options.push(...cached);
47300
47520
  return options;
47301
47521
  };
47302
47522
  useEnsureSelectionVisible({
@@ -47327,34 +47547,32 @@ function VersionSelectStep(props) {
47327
47547
  }
47328
47548
  };
47329
47549
  const statusText = () => {
47330
- if (versionOptions.loading) {
47331
- return "Fetching versions...";
47332
- }
47333
- if (versionOptions.error) {
47334
- return "Could not fetch versions";
47550
+ const cached = cachedVersions();
47551
+ if (cached.length === 0) {
47552
+ return "Version list unavailable (using latest)";
47335
47553
  }
47336
47554
  return null;
47337
47555
  };
47338
47556
  return (() => {
47339
- var _el$79 = createElement("box"), _el$80 = createElement("text"), _el$82 = createElement("text"), _el$84 = createElement("text"), _el$86 = createElement("text");
47340
- insertNode(_el$79, _el$80);
47341
- insertNode(_el$79, _el$82);
47342
- insertNode(_el$79, _el$84);
47343
- insertNode(_el$79, _el$86);
47344
- setProp(_el$79, "flexDirection", "column");
47345
- insertNode(_el$80, createTextNode(`Select version:`));
47346
- setProp(_el$80, "fg", "cyan");
47347
- insert(_el$79, (() => {
47557
+ var _el$88 = createElement("box"), _el$89 = createElement("text"), _el$91 = createElement("text"), _el$93 = createElement("text"), _el$95 = createElement("text");
47558
+ insertNode(_el$88, _el$89);
47559
+ insertNode(_el$88, _el$91);
47560
+ insertNode(_el$88, _el$93);
47561
+ insertNode(_el$88, _el$95);
47562
+ setProp(_el$88, "flexDirection", "column");
47563
+ insertNode(_el$89, createTextNode(`Select version:`));
47564
+ setProp(_el$89, "fg", "cyan");
47565
+ insert(_el$88, (() => {
47348
47566
  var _c$ = memo2(() => !!statusText());
47349
47567
  return () => _c$() && (() => {
47350
- var _el$88 = createElement("text");
47351
- insert(_el$88, statusText);
47352
- effect((_$p) => setProp(_el$88, "attributes", TextAttributes.DIM, _$p));
47353
- return _el$88;
47568
+ var _el$97 = createElement("text");
47569
+ insert(_el$97, statusText);
47570
+ effect((_$p) => setProp(_el$97, "attributes", TextAttributes.DIM, _$p));
47571
+ return _el$97;
47354
47572
  })();
47355
- })(), _el$82);
47356
- insertNode(_el$82, createTextNode(` `));
47357
- insert(_el$79, createComponent2(SelectInput, {
47573
+ })(), _el$91);
47574
+ insertNode(_el$91, createTextNode(` `));
47575
+ insert(_el$88, createComponent2(SelectInput, {
47358
47576
  get items() {
47359
47577
  return allOptions();
47360
47578
  },
@@ -47364,19 +47582,19 @@ function VersionSelectStep(props) {
47364
47582
  return props.focused ?? true;
47365
47583
  },
47366
47584
  selectRef: setSelectRef
47367
- }), _el$84);
47368
- insertNode(_el$84, createTextNode(` `));
47369
- insertNode(_el$86, createTextNode(`[Enter] Select [Esc] Back`));
47585
+ }), _el$93);
47586
+ insertNode(_el$93, createTextNode(` `));
47587
+ insertNode(_el$95, createTextNode(`[Enter] Select [Esc] Back`));
47370
47588
  effect((_p$) => {
47371
- var _v$15 = TextAttributes.BOLD, _v$16 = TextAttributes.DIM;
47372
- _v$15 !== _p$.e && (_p$.e = setProp(_el$80, "attributes", _v$15, _p$.e));
47373
- _v$16 !== _p$.t && (_p$.t = setProp(_el$86, "attributes", _v$16, _p$.t));
47589
+ var _v$19 = TextAttributes.BOLD, _v$20 = TextAttributes.DIM;
47590
+ _v$19 !== _p$.e && (_p$.e = setProp(_el$89, "attributes", _v$19, _p$.e));
47591
+ _v$20 !== _p$.t && (_p$.t = setProp(_el$95, "attributes", _v$20, _p$.t));
47374
47592
  return _p$;
47375
47593
  }, {
47376
47594
  e: undefined,
47377
47595
  t: undefined
47378
47596
  });
47379
- return _el$79;
47597
+ return _el$88;
47380
47598
  })();
47381
47599
  }
47382
47600
 
@@ -47392,7 +47610,9 @@ function WizardController(props) {
47392
47610
  const [selectedModel, setSelectedModel] = createSignal("");
47393
47611
  const [reasoningLevel, setReasoningLevel] = createSignal(undefined);
47394
47612
  const [executionMode, setExecutionMode] = createSignal("normal");
47395
- const [isInitialFrame, setIsInitialFrame] = createSignal(true);
47613
+ const [versionSelectionReady, setVersionSelectionReady] = createSignal(false);
47614
+ const [isTransitioning, setIsTransitioning] = createSignal(true);
47615
+ let versionSelectionTimer = null;
47396
47616
  function getInitialStep() {
47397
47617
  if (props.history.length > 0) {
47398
47618
  return "quick-start";
@@ -47411,20 +47631,23 @@ function WizardController(props) {
47411
47631
  setReasoningLevel(undefined);
47412
47632
  setExecutionMode("normal");
47413
47633
  };
47634
+ const startTransition2 = () => {
47635
+ setIsTransitioning(true);
47636
+ setTimeout(() => setIsTransitioning(false), 50);
47637
+ };
47414
47638
  let prevVisible = false;
47415
47639
  createEffect(() => {
47416
47640
  const visible = props.visible;
47417
47641
  if (visible && !prevVisible) {
47418
47642
  resetWizard();
47419
- setIsInitialFrame(true);
47420
- setTimeout(() => setIsInitialFrame(false), 150);
47643
+ startTransition2();
47421
47644
  }
47422
47645
  prevVisible = visible;
47423
47646
  });
47424
47647
  useKeyboard((key) => {
47425
47648
  if (!props.visible)
47426
47649
  return;
47427
- if (isInitialFrame() && key.name === "return") {
47650
+ if (isTransitioning() && key.name === "return") {
47428
47651
  return;
47429
47652
  }
47430
47653
  if (key.name === "escape") {
@@ -47434,6 +47657,7 @@ function WizardController(props) {
47434
47657
  const goToStep = (nextStep) => {
47435
47658
  setStepHistory((prev) => [...prev, step()]);
47436
47659
  setStep(nextStep);
47660
+ startTransition2();
47437
47661
  };
47438
47662
  const goBack = () => {
47439
47663
  const history = stepHistory();
@@ -47444,7 +47668,28 @@ function WizardController(props) {
47444
47668
  const previousStep = history[history.length - 1] ?? "agent-select";
47445
47669
  setStepHistory(history.slice(0, -1));
47446
47670
  setStep(previousStep);
47671
+ startTransition2();
47447
47672
  };
47673
+ createEffect(() => {
47674
+ const currentStep = step();
47675
+ if (versionSelectionTimer) {
47676
+ clearTimeout(versionSelectionTimer);
47677
+ versionSelectionTimer = null;
47678
+ }
47679
+ if (currentStep === "version-select") {
47680
+ setVersionSelectionReady(false);
47681
+ versionSelectionTimer = setTimeout(() => {
47682
+ setVersionSelectionReady(true);
47683
+ }, 50);
47684
+ return;
47685
+ }
47686
+ setVersionSelectionReady(false);
47687
+ });
47688
+ onCleanup(() => {
47689
+ if (versionSelectionTimer) {
47690
+ clearTimeout(versionSelectionTimer);
47691
+ }
47692
+ });
47448
47693
  const needsReasoningLevel = createMemo(() => {
47449
47694
  return selectedAgent() === "codex-cli";
47450
47695
  });
@@ -47479,10 +47724,18 @@ function WizardController(props) {
47479
47724
  goToStep("version-select");
47480
47725
  };
47481
47726
  const handleVersionSelect = (version) => {
47482
- setSelectedVersion(version === "installed" ? null : version);
47727
+ if (!versionSelectionReady() || step() !== "version-select") {
47728
+ return;
47729
+ }
47730
+ setSelectedVersion(version);
47483
47731
  goToStep("model-select");
47484
47732
  };
47485
47733
  const handleModelSelect = (model) => {
47734
+ const agent = selectedAgent();
47735
+ if (agent === "opencode" && model === "__custom__") {
47736
+ goToStep("model-input");
47737
+ return;
47738
+ }
47486
47739
  setSelectedModel(model);
47487
47740
  if (needsReasoningLevel()) {
47488
47741
  goToStep("reasoning-level");
@@ -47490,6 +47743,18 @@ function WizardController(props) {
47490
47743
  goToStep("execution-mode");
47491
47744
  }
47492
47745
  };
47746
+ const handleModelInputSubmit = (value) => {
47747
+ const trimmed = value.trim();
47748
+ if (!trimmed) {
47749
+ return;
47750
+ }
47751
+ setSelectedModel(trimmed);
47752
+ if (needsReasoningLevel()) {
47753
+ goToStep("reasoning-level");
47754
+ } else {
47755
+ goToStep("execution-mode");
47756
+ }
47757
+ };
47493
47758
  const handleReasoningLevelSelect = (level) => {
47494
47759
  setReasoningLevel(level);
47495
47760
  goToStep("execution-mode");
@@ -47526,7 +47791,7 @@ function WizardController(props) {
47526
47791
  };
47527
47792
  const renderStep = () => {
47528
47793
  const currentStep = step();
47529
- const focused = !isInitialFrame();
47794
+ const focused = !isTransitioning();
47530
47795
  if (currentStep === "action-select") {
47531
47796
  return createComponent2(ActionSelectStep, {
47532
47797
  get branchName() {
@@ -47593,6 +47858,16 @@ function WizardController(props) {
47593
47858
  focused
47594
47859
  });
47595
47860
  }
47861
+ if (currentStep === "model-input") {
47862
+ return createComponent2(ModelInputStep, {
47863
+ get agentId() {
47864
+ return selectedAgent() ?? "claude-code";
47865
+ },
47866
+ onSubmit: handleModelInputSubmit,
47867
+ onBack: goBack,
47868
+ focused
47869
+ });
47870
+ }
47596
47871
  if (currentStep === "reasoning-level") {
47597
47872
  return createComponent2(ReasoningLevelStep, {
47598
47873
  onSelect: handleReasoningLevelSelect,
@@ -47780,6 +48055,10 @@ function useScrollableList(options) {
47780
48055
 
47781
48056
  // src/cli/ui/screens/solid/SelectorScreen.tsx
47782
48057
  var clamp2 = (value, min, max) => Math.min(Math.max(value, min), max);
48058
+ var padLine2 = (value, width) => {
48059
+ const padding = Math.max(0, width - stringWidth(value));
48060
+ return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
48061
+ };
47783
48062
  function SelectorScreen({
47784
48063
  title,
47785
48064
  description,
@@ -47898,30 +48177,34 @@ function SelectorScreen({
47898
48177
  insert(_el$5, () => list.visibleItems().map((item, index) => {
47899
48178
  const absoluteIndex = list.scrollOffset() + index;
47900
48179
  const isSelected = absoluteIndex === selectedIndex();
48180
+ const descriptionText = showDescription && item.description ? ` - ${item.description}` : "";
48181
+ const fullLine = `${item.label}${descriptionText}`;
47901
48182
  return (() => {
47902
- var _el$6 = createElement("box"), _el$7 = createElement("text");
47903
- insertNode(_el$6, _el$7);
48183
+ var _el$6 = createElement("box");
47904
48184
  setProp(_el$6, "flexDirection", "row");
47905
- spread(_el$7, mergeProps3(() => isSelected ? {
47906
- fg: "cyan",
47907
- attributes: TextAttributes.BOLD
47908
- } : {}), true);
47909
- insert(_el$7, () => item.label);
47910
- insert(_el$6, (() => {
47911
- var _c$2 = memo2(() => !!(showDescription && item.description));
47912
- return () => _c$2() ? (() => {
47913
- var _el$8 = createElement("text");
47914
- spread(_el$8, mergeProps3({
47915
- get attributes() {
47916
- return TextAttributes.DIM;
47917
- }
47918
- }, isSelected ? {
47919
- fg: "cyan"
47920
- } : {}), true);
47921
- insert(_el$8, () => ` - ${item.description}`);
47922
- return _el$8;
47923
- })() : null;
47924
- })(), null);
48185
+ insert(_el$6, isSelected ? (() => {
48186
+ var _el$7 = createElement("text");
48187
+ insert(_el$7, () => padLine2(fullLine, terminal().columns));
48188
+ effect((_p$) => {
48189
+ var _v$ = selectionStyle.fg, _v$2 = selectionStyle.bg;
48190
+ _v$ !== _p$.e && (_p$.e = setProp(_el$7, "fg", _v$, _p$.e));
48191
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$7, "bg", _v$2, _p$.t));
48192
+ return _p$;
48193
+ }, {
48194
+ e: undefined,
48195
+ t: undefined
48196
+ });
48197
+ return _el$7;
48198
+ })() : [(() => {
48199
+ var _el$8 = createElement("text");
48200
+ insert(_el$8, () => item.label);
48201
+ return _el$8;
48202
+ })(), memo2(() => memo2(() => !!(showDescription && item.description))() ? (() => {
48203
+ var _el$9 = createElement("text");
48204
+ insert(_el$9, () => ` - ${item.description}`);
48205
+ effect((_$p) => setProp(_el$9, "attributes", TextAttributes.DIM, _$p));
48206
+ return _el$9;
48207
+ })() : null)]);
47925
48208
  return _el$6;
47926
48209
  })();
47927
48210
  }));
@@ -47939,53 +48222,237 @@ function SelectorScreen({
47939
48222
  }
47940
48223
 
47941
48224
  // src/cli/ui/screens/solid/LogScreen.tsx
47942
- function LogScreen({
47943
- entries,
47944
- loading = false,
47945
- error = null,
47946
- onBack,
47947
- onSelect,
47948
- onCopy,
47949
- onPickDate,
47950
- notification,
47951
- version,
47952
- selectedDate,
47953
- helpVisible = false
47954
- }) {
48225
+ var LEVEL_ORDER = ["ALL", "INFO+", "WARN+", "ERROR+"];
48226
+ var LEVEL_THRESHOLDS = {
48227
+ ALL: 0,
48228
+ "INFO+": 30,
48229
+ "WARN+": 40,
48230
+ "ERROR+": 50
48231
+ };
48232
+ var LEVEL_LABEL_VALUES = {
48233
+ TRACE: 10,
48234
+ DEBUG: 20,
48235
+ INFO: 30,
48236
+ WARN: 40,
48237
+ ERROR: 50,
48238
+ FATAL: 60
48239
+ };
48240
+ var measureWidth2 = (value) => stringWidth(value);
48241
+ var truncateToWidth3 = (value, maxWidth) => {
48242
+ if (maxWidth <= 0) {
48243
+ return "";
48244
+ }
48245
+ if (measureWidth2(value) <= maxWidth) {
48246
+ return value;
48247
+ }
48248
+ const ellipsis = "...";
48249
+ const ellipsisWidth = measureWidth2(ellipsis);
48250
+ if (ellipsisWidth >= maxWidth) {
48251
+ return ellipsis.slice(0, maxWidth);
48252
+ }
48253
+ let currentWidth = 0;
48254
+ let result = "";
48255
+ for (const char of Array.from(value)) {
48256
+ const charWidth = measureWidth2(char);
48257
+ if (currentWidth + charWidth + ellipsisWidth > maxWidth) {
48258
+ break;
48259
+ }
48260
+ result += char;
48261
+ currentWidth += charWidth;
48262
+ }
48263
+ return `${result}${ellipsis}`;
48264
+ };
48265
+ var padToWidth = (value, width) => {
48266
+ if (width <= 0) {
48267
+ return "";
48268
+ }
48269
+ const truncated = truncateToWidth3(value, width);
48270
+ const padding = Math.max(0, width - measureWidth2(truncated));
48271
+ return `${truncated}${" ".repeat(padding)}`;
48272
+ };
48273
+ var appendSegment2 = (segments, segment) => {
48274
+ if (!segment.text) {
48275
+ return;
48276
+ }
48277
+ segments.push(segment);
48278
+ };
48279
+ var measureSegmentsWidth2 = (segments) => segments.reduce((total, segment) => total + measureWidth2(segment.text), 0);
48280
+ var truncateSegmentsToWidth2 = (segments, maxWidth) => {
48281
+ if (maxWidth <= 0) {
48282
+ return [];
48283
+ }
48284
+ const result = [];
48285
+ let currentWidth = 0;
48286
+ for (const segment of segments) {
48287
+ if (currentWidth >= maxWidth) {
48288
+ break;
48289
+ }
48290
+ const segmentWidth = measureWidth2(segment.text);
48291
+ if (currentWidth + segmentWidth <= maxWidth) {
48292
+ result.push(segment);
48293
+ currentWidth += segmentWidth;
48294
+ continue;
48295
+ }
48296
+ const remaining = maxWidth - currentWidth;
48297
+ const truncated = truncateToWidth3(segment.text, remaining);
48298
+ if (truncated) {
48299
+ result.push({
48300
+ ...segment,
48301
+ text: truncated
48302
+ });
48303
+ currentWidth += measureWidth2(truncated);
48304
+ }
48305
+ break;
48306
+ }
48307
+ return result;
48308
+ };
48309
+ var segmentsToText = (segments) => segments.map((segment) => segment.text).join("");
48310
+ var padLine3 = (value, width) => {
48311
+ const padding = Math.max(0, width - measureWidth2(value));
48312
+ return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
48313
+ };
48314
+ var resolveEntryLevel = (entry) => {
48315
+ const rawLevel = entry.raw?.level;
48316
+ if (typeof rawLevel === "number") {
48317
+ return rawLevel;
48318
+ }
48319
+ const label = entry.levelLabel?.toUpperCase() ?? "";
48320
+ return LEVEL_LABEL_VALUES[label] ?? 0;
48321
+ };
48322
+ function LogScreen(props) {
48323
+ const merged = mergeProps({
48324
+ loading: false,
48325
+ error: null,
48326
+ branchLabel: null,
48327
+ sourceLabel: null,
48328
+ tailing: false,
48329
+ helpVisible: false
48330
+ }, props);
47955
48331
  const terminal = useTerminalSize();
48332
+ const [filterQuery, setFilterQuery] = createSignal("");
48333
+ const [filterMode, setFilterMode] = createSignal(false);
48334
+ const [levelMode, setLevelMode] = createSignal("ALL");
48335
+ const filteredEntries = createMemo(() => {
48336
+ let result = merged.entries;
48337
+ const threshold = LEVEL_THRESHOLDS[levelMode()];
48338
+ if (threshold > 0) {
48339
+ result = result.filter((entry) => resolveEntryLevel(entry) >= threshold);
48340
+ }
48341
+ const query = filterQuery().trim().toLowerCase();
48342
+ if (!query) {
48343
+ return result;
48344
+ }
48345
+ return result.filter((entry) => {
48346
+ const target = `${entry.category} ${entry.levelLabel} ${entry.message}`.toLowerCase();
48347
+ return target.includes(query);
48348
+ });
48349
+ });
48350
+ const totalCount = createMemo(() => merged.entries.length);
48351
+ const filteredCount = createMemo(() => filteredEntries().length);
48352
+ const showFilterCount = createMemo(() => filterMode() || filterQuery().trim().length > 0);
48353
+ const levelWidth = createMemo(() => {
48354
+ const MIN = 5;
48355
+ return Math.max(MIN, ...filteredEntries().map((entry) => measureWidth2(entry.levelLabel)));
48356
+ });
48357
+ const categoryWidth = createMemo(() => {
48358
+ const MIN = 4;
48359
+ const MAX = 20;
48360
+ const maxWidth = Math.max(MIN, ...filteredEntries().map((entry) => measureWidth2(entry.category)));
48361
+ return Math.min(MAX, maxWidth);
48362
+ });
47956
48363
  const listHeight = createMemo(() => {
47957
48364
  const headerRows = 2;
47958
- const infoRows = 1;
48365
+ const infoRows = 3;
47959
48366
  const footerRows = 1;
47960
- const notificationRows = notification ? 1 : 0;
48367
+ const notificationRows = merged.notification ? 1 : 0;
47961
48368
  const reserved = headerRows + infoRows + footerRows + notificationRows;
47962
48369
  return Math.max(1, terminal().rows - reserved);
47963
48370
  });
47964
48371
  const list = useScrollableList({
47965
- items: () => entries,
48372
+ items: filteredEntries,
47966
48373
  visibleCount: listHeight
47967
48374
  });
47968
- const currentEntry = createMemo(() => entries[list.selectedIndex()]);
48375
+ const currentEntry = createMemo(() => filteredEntries()[list.selectedIndex()]);
48376
+ createEffect(() => {
48377
+ filterQuery();
48378
+ levelMode();
48379
+ list.setSelectedIndex(0);
48380
+ list.setScrollOffset(0);
48381
+ });
47969
48382
  const updateSelectedIndex = (value) => {
47970
48383
  list.setSelectedIndex(value);
47971
48384
  };
47972
48385
  useKeyboard((key) => {
47973
- if (helpVisible) {
48386
+ if (merged.helpVisible) {
48387
+ return;
48388
+ }
48389
+ if (filterMode()) {
48390
+ if (key.name === "down") {
48391
+ updateSelectedIndex((prev) => prev + 1);
48392
+ return;
48393
+ }
48394
+ if (key.name === "up") {
48395
+ updateSelectedIndex((prev) => prev - 1);
48396
+ return;
48397
+ }
48398
+ if (key.name === "escape") {
48399
+ if (filterQuery()) {
48400
+ setFilterQuery("");
48401
+ } else {
48402
+ setFilterMode(false);
48403
+ }
48404
+ return;
48405
+ }
48406
+ if (key.name === "backspace") {
48407
+ setFilterQuery((prev) => prev.slice(0, -1));
48408
+ return;
48409
+ }
48410
+ if (key.name === "return" || key.name === "linefeed") {
48411
+ setFilterMode(false);
48412
+ return;
48413
+ }
48414
+ if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && !key.super && !key.hyper) {
48415
+ setFilterQuery((prev) => prev + key.sequence);
48416
+ }
47974
48417
  return;
47975
48418
  }
47976
48419
  if (key.name === "escape" || key.name === "q") {
47977
- onBack();
48420
+ merged.onBack();
47978
48421
  return;
47979
48422
  }
47980
48423
  if (key.name === "c") {
47981
48424
  const entry = currentEntry();
47982
48425
  if (entry) {
47983
- onCopy(entry);
48426
+ merged.onCopy(entry);
47984
48427
  }
47985
48428
  return;
47986
48429
  }
47987
48430
  if (key.name === "d") {
47988
- onPickDate?.();
48431
+ merged.onPickDate?.();
48432
+ return;
48433
+ }
48434
+ if (key.name === "f") {
48435
+ setFilterMode(true);
48436
+ return;
48437
+ }
48438
+ if (key.name === "v") {
48439
+ setLevelMode((prev) => {
48440
+ const index = LEVEL_ORDER.indexOf(prev);
48441
+ const nextIndex = (index + 1) % LEVEL_ORDER.length;
48442
+ return LEVEL_ORDER[nextIndex] ?? "ALL";
48443
+ });
48444
+ return;
48445
+ }
48446
+ if (key.name === "r") {
48447
+ merged.onReload?.();
48448
+ return;
48449
+ }
48450
+ if (key.name === "t") {
48451
+ merged.onToggleTail?.();
48452
+ return;
48453
+ }
48454
+ if (key.name === "x") {
48455
+ merged.onReset?.();
47989
48456
  return;
47990
48457
  }
47991
48458
  if (key.name === "down") {
@@ -48009,13 +48476,13 @@ function LogScreen({
48009
48476
  return;
48010
48477
  }
48011
48478
  if (key.name === "end") {
48012
- updateSelectedIndex(entries.length - 1);
48479
+ updateSelectedIndex(filteredEntries().length - 1);
48013
48480
  return;
48014
48481
  }
48015
48482
  if (key.name === "return" || key.name === "linefeed") {
48016
48483
  const entry = currentEntry();
48017
48484
  if (entry) {
48018
- onSelect(entry);
48485
+ merged.onSelect(entry);
48019
48486
  }
48020
48487
  }
48021
48488
  });
@@ -48029,92 +48496,227 @@ function LogScreen({
48029
48496
  }, {
48030
48497
  key: "d",
48031
48498
  description: "Date"
48499
+ }, {
48500
+ key: "f",
48501
+ description: "Filter"
48502
+ }, {
48503
+ key: "v",
48504
+ description: "Level"
48505
+ }, {
48506
+ key: "r",
48507
+ description: "Reload"
48508
+ }, {
48509
+ key: "t",
48510
+ description: "Tail"
48511
+ }, {
48512
+ key: "x",
48513
+ description: "Reset"
48032
48514
  }, {
48033
48515
  key: "esc",
48034
48516
  description: "Back"
48035
48517
  }];
48036
48518
  return actions;
48037
48519
  });
48520
+ const formatEntrySegments = (entry) => {
48521
+ const levelText = padToWidth(entry.levelLabel, levelWidth());
48522
+ const categoryText = padToWidth(entry.category, categoryWidth());
48523
+ const segments = [];
48524
+ appendSegment2(segments, {
48525
+ text: `[${entry.timeLabel}] `
48526
+ });
48527
+ appendSegment2(segments, {
48528
+ text: "["
48529
+ });
48530
+ appendSegment2(segments, {
48531
+ text: levelText,
48532
+ fg: getLogLevelColor(entry.levelLabel)
48533
+ });
48534
+ appendSegment2(segments, {
48535
+ text: "] "
48536
+ });
48537
+ appendSegment2(segments, {
48538
+ text: "["
48539
+ });
48540
+ appendSegment2(segments, {
48541
+ text: categoryText
48542
+ });
48543
+ appendSegment2(segments, {
48544
+ text: "] "
48545
+ });
48546
+ appendSegment2(segments, {
48547
+ text: entry.message
48548
+ });
48549
+ const maxWidth = terminal().columns;
48550
+ if (measureSegmentsWidth2(segments) <= maxWidth) {
48551
+ return segments;
48552
+ }
48553
+ return truncateSegmentsToWidth2(segments, maxWidth);
48554
+ };
48555
+ const filterLabel = createMemo(() => {
48556
+ if (filterQuery()) {
48557
+ return filterQuery();
48558
+ }
48559
+ return filterMode() ? "(type to filter)" : "(press f to filter)";
48560
+ });
48038
48561
  return (() => {
48039
- var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$5 = createElement("text"), _el$6 = createElement("text"), _el$8 = createElement("text"), _el$9 = createElement("box");
48562
+ var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$5 = createElement("text"), _el$6 = createElement("text"), _el$8 = createElement("text"), _el$9 = createElement("box"), _el$0 = createElement("text"), _el$10 = createElement("text"), _el$11 = createElement("text"), _el$13 = createElement("text"), _el$14 = createElement("text"), _el$16 = createElement("text"), _el$17 = createElement("text"), _el$19 = createElement("text"), _el$20 = createElement("box"), _el$21 = createElement("text"), _el$23 = createElement("text"), _el$24 = createElement("box");
48040
48563
  insertNode(_el$, _el$2);
48041
48564
  insertNode(_el$, _el$9);
48565
+ insertNode(_el$, _el$20);
48566
+ insertNode(_el$, _el$24);
48042
48567
  setProp(_el$, "flexDirection", "column");
48043
48568
  insert(_el$, createComponent2(Header, {
48044
48569
  title: "gwt - Log Viewer",
48045
48570
  titleColor: "cyan",
48046
- version
48571
+ get version() {
48572
+ return merged.version;
48573
+ }
48047
48574
  }), _el$2);
48048
- insert(_el$, notification ? (() => {
48049
- var _el$0 = createElement("text");
48050
- insert(_el$0, () => notification.message);
48051
- effect((_$p) => setProp(_el$0, "fg", notification.tone === "error" ? "red" : "green", _$p));
48052
- return _el$0;
48053
- })() : null, _el$2);
48575
+ insert(_el$, (() => {
48576
+ var _c$ = memo2(() => !!merged.notification);
48577
+ return () => _c$() ? (() => {
48578
+ var _el$25 = createElement("text");
48579
+ insert(_el$25, () => merged.notification.message);
48580
+ effect((_$p) => setProp(_el$25, "fg", merged.notification.tone === "error" ? "red" : "green", _$p));
48581
+ return _el$25;
48582
+ })() : null;
48583
+ })(), _el$2);
48054
48584
  insertNode(_el$2, _el$3);
48055
48585
  insertNode(_el$2, _el$5);
48056
48586
  insertNode(_el$2, _el$6);
48057
48587
  insertNode(_el$2, _el$8);
48058
48588
  setProp(_el$2, "flexDirection", "row");
48059
- insertNode(_el$3, createTextNode(`Date: `));
48060
- insert(_el$5, selectedDate ?? "---");
48061
- insertNode(_el$6, createTextNode(` Total: `));
48062
- insert(_el$8, () => entries.length);
48063
- setProp(_el$9, "flexDirection", "column");
48064
- setProp(_el$9, "flexGrow", 1);
48065
- insert(_el$9, () => loading ? (() => {
48066
- var _el$1 = createElement("text");
48067
- insertNode(_el$1, createTextNode(`Loading logs...`));
48068
- setProp(_el$1, "fg", "gray");
48069
- return _el$1;
48070
- })() : entries.length === 0 ? (() => {
48071
- var _el$11 = createElement("text");
48072
- insertNode(_el$11, createTextNode(`No logs available.`));
48073
- setProp(_el$11, "fg", "gray");
48074
- return _el$11;
48075
- })() : (() => {
48076
- var _el$13 = createElement("box");
48077
- setProp(_el$13, "flexDirection", "column");
48078
- insert(_el$13, () => list.visibleItems().map((entry, index) => {
48079
- const absoluteIndex = list.scrollOffset() + index;
48080
- const isSelected = absoluteIndex === list.selectedIndex();
48081
- return (() => {
48082
- var _el$14 = createElement("text");
48083
- spread(_el$14, mergeProps3(() => isSelected ? {
48084
- fg: "cyan",
48085
- attributes: TextAttributes.BOLD
48086
- } : {}), true);
48087
- insert(_el$14, () => entry.summary);
48088
- return _el$14;
48089
- })();
48090
- }));
48091
- return _el$13;
48589
+ insertNode(_el$3, createTextNode(`Branch: `));
48590
+ insert(_el$5, () => merged.branchLabel ?? "(none)");
48591
+ insertNode(_el$6, createTextNode(` Source: `));
48592
+ insert(_el$8, () => merged.sourceLabel ?? "(none)");
48593
+ insertNode(_el$9, _el$0);
48594
+ insertNode(_el$9, _el$10);
48595
+ insertNode(_el$9, _el$11);
48596
+ insertNode(_el$9, _el$13);
48597
+ insertNode(_el$9, _el$14);
48598
+ insertNode(_el$9, _el$16);
48599
+ insertNode(_el$9, _el$17);
48600
+ insertNode(_el$9, _el$19);
48601
+ setProp(_el$9, "flexDirection", "row");
48602
+ insertNode(_el$0, createTextNode(`Date: `));
48603
+ insert(_el$10, () => merged.selectedDate ?? "---");
48604
+ insertNode(_el$11, createTextNode(` Total: `));
48605
+ insert(_el$13, totalCount);
48606
+ insertNode(_el$14, createTextNode(` Level: `));
48607
+ insert(_el$16, levelMode);
48608
+ insertNode(_el$17, createTextNode(` Tail: `));
48609
+ insert(_el$19, () => merged.tailing ? "ON" : "OFF");
48610
+ insertNode(_el$20, _el$21);
48611
+ insertNode(_el$20, _el$23);
48612
+ setProp(_el$20, "flexDirection", "row");
48613
+ insertNode(_el$21, createTextNode(`Filter: `));
48614
+ insert(_el$23, filterLabel);
48615
+ insert(_el$20, (() => {
48616
+ var _c$2 = memo2(() => !!showFilterCount());
48617
+ return () => _c$2() ? (() => {
48618
+ var _el$26 = createElement("text");
48619
+ insert(_el$26, () => ` (Showing ${filteredCount()} of ${totalCount()})`);
48620
+ effect((_$p) => setProp(_el$26, "attributes", TextAttributes.DIM, _$p));
48621
+ return _el$26;
48622
+ })() : null;
48623
+ })(), null);
48624
+ setProp(_el$24, "flexDirection", "column");
48625
+ setProp(_el$24, "flexGrow", 1);
48626
+ insert(_el$24, (() => {
48627
+ var _c$3 = memo2(() => !!merged.loading);
48628
+ return () => _c$3() ? (() => {
48629
+ var _el$27 = createElement("text");
48630
+ insertNode(_el$27, createTextNode(`Loading logs...`));
48631
+ setProp(_el$27, "fg", "gray");
48632
+ return _el$27;
48633
+ })() : memo2(() => filteredEntries().length === 0)() ? (() => {
48634
+ var _el$29 = createElement("text");
48635
+ insertNode(_el$29, createTextNode(`No logs available.`));
48636
+ setProp(_el$29, "fg", "gray");
48637
+ return _el$29;
48638
+ })() : (() => {
48639
+ var _el$31 = createElement("box");
48640
+ setProp(_el$31, "flexDirection", "column");
48641
+ insert(_el$31, () => list.visibleItems().map((entry, index) => {
48642
+ const absoluteIndex = list.scrollOffset() + index;
48643
+ const isSelected = absoluteIndex === list.selectedIndex();
48644
+ const segments = formatEntrySegments(entry);
48645
+ const lineText = segmentsToText(segments);
48646
+ const selectedContent = padLine3(lineText, terminal().columns);
48647
+ return (() => {
48648
+ var _el$32 = createElement("text");
48649
+ spread(_el$32, mergeProps3(() => isSelected ? {
48650
+ fg: selectionStyle.fg,
48651
+ bg: selectionStyle.bg
48652
+ } : {}, {
48653
+ wrapMode: "none",
48654
+ get width() {
48655
+ return terminal().columns;
48656
+ }
48657
+ }), true);
48658
+ insert(_el$32, () => isSelected ? selectedContent : segments.map((segment) => segment.fg ? (() => {
48659
+ var _el$33 = createElement("span");
48660
+ insert(_el$33, () => segment.text);
48661
+ effect((_$p) => setProp(_el$33, "style", {
48662
+ fg: segment.fg
48663
+ }, _$p));
48664
+ return _el$33;
48665
+ })() : segment.text));
48666
+ return _el$32;
48667
+ })();
48668
+ }));
48669
+ return _el$31;
48670
+ })();
48671
+ })(), null);
48672
+ insert(_el$24, (() => {
48673
+ var _c$4 = memo2(() => !!merged.error);
48674
+ return () => _c$4() ? (() => {
48675
+ var _el$34 = createElement("text");
48676
+ setProp(_el$34, "fg", "red");
48677
+ insert(_el$34, () => merged.error);
48678
+ return _el$34;
48679
+ })() : null;
48092
48680
  })(), null);
48093
- insert(_el$9, error ? (() => {
48094
- var _el$15 = createElement("text");
48095
- setProp(_el$15, "fg", "red");
48096
- insert(_el$15, error);
48097
- return _el$15;
48098
- })() : null, null);
48099
48681
  insert(_el$, createComponent2(Footer, {
48100
48682
  get actions() {
48101
48683
  return footerActions();
48102
48684
  }
48103
48685
  }), null);
48104
48686
  effect((_p$) => {
48105
- var _v$ = terminal().rows, _v$2 = TextAttributes.DIM, _v$3 = TextAttributes.BOLD, _v$4 = TextAttributes.DIM, _v$5 = TextAttributes.BOLD;
48687
+ var _v$ = terminal().rows, _v$2 = TextAttributes.DIM, _v$3 = TextAttributes.BOLD, _v$4 = TextAttributes.DIM, _v$5 = TextAttributes.BOLD, _v$6 = TextAttributes.DIM, _v$7 = TextAttributes.BOLD, _v$8 = TextAttributes.DIM, _v$9 = TextAttributes.BOLD, _v$0 = TextAttributes.DIM, _v$1 = TextAttributes.BOLD, _v$10 = TextAttributes.DIM, _v$11 = TextAttributes.BOLD, _v$12 = TextAttributes.DIM, _v$13 = TextAttributes.BOLD;
48106
48688
  _v$ !== _p$.e && (_p$.e = setProp(_el$, "height", _v$, _p$.e));
48107
48689
  _v$2 !== _p$.t && (_p$.t = setProp(_el$3, "attributes", _v$2, _p$.t));
48108
48690
  _v$3 !== _p$.a && (_p$.a = setProp(_el$5, "attributes", _v$3, _p$.a));
48109
48691
  _v$4 !== _p$.o && (_p$.o = setProp(_el$6, "attributes", _v$4, _p$.o));
48110
48692
  _v$5 !== _p$.i && (_p$.i = setProp(_el$8, "attributes", _v$5, _p$.i));
48693
+ _v$6 !== _p$.n && (_p$.n = setProp(_el$0, "attributes", _v$6, _p$.n));
48694
+ _v$7 !== _p$.s && (_p$.s = setProp(_el$10, "attributes", _v$7, _p$.s));
48695
+ _v$8 !== _p$.h && (_p$.h = setProp(_el$11, "attributes", _v$8, _p$.h));
48696
+ _v$9 !== _p$.r && (_p$.r = setProp(_el$13, "attributes", _v$9, _p$.r));
48697
+ _v$0 !== _p$.d && (_p$.d = setProp(_el$14, "attributes", _v$0, _p$.d));
48698
+ _v$1 !== _p$.l && (_p$.l = setProp(_el$16, "attributes", _v$1, _p$.l));
48699
+ _v$10 !== _p$.u && (_p$.u = setProp(_el$17, "attributes", _v$10, _p$.u));
48700
+ _v$11 !== _p$.c && (_p$.c = setProp(_el$19, "attributes", _v$11, _p$.c));
48701
+ _v$12 !== _p$.w && (_p$.w = setProp(_el$21, "attributes", _v$12, _p$.w));
48702
+ _v$13 !== _p$.m && (_p$.m = setProp(_el$23, "attributes", _v$13, _p$.m));
48111
48703
  return _p$;
48112
48704
  }, {
48113
48705
  e: undefined,
48114
48706
  t: undefined,
48115
48707
  a: undefined,
48116
48708
  o: undefined,
48117
- i: undefined
48709
+ i: undefined,
48710
+ n: undefined,
48711
+ s: undefined,
48712
+ h: undefined,
48713
+ r: undefined,
48714
+ d: undefined,
48715
+ l: undefined,
48716
+ u: undefined,
48717
+ c: undefined,
48718
+ w: undefined,
48719
+ m: undefined
48118
48720
  });
48119
48721
  return _el$;
48120
48722
  })();
@@ -48473,9 +49075,16 @@ function ConfirmScreen({
48473
49075
  yesLabel = "Yes",
48474
49076
  noLabel = "No",
48475
49077
  defaultNo = false,
48476
- helpVisible = false
49078
+ helpVisible = false,
49079
+ width
48477
49080
  }) {
48478
49081
  const [selectedIndex, setSelectedIndex] = createSignal(defaultNo ? 1 : 0);
49082
+ const terminal = useTerminalSize();
49083
+ const contentWidth = () => Math.max(0, width ?? terminal().columns);
49084
+ const padLine4 = (value, width2) => {
49085
+ const padding = Math.max(0, width2 - stringWidth(value));
49086
+ return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
49087
+ };
48479
49088
  const confirm = (confirmed) => {
48480
49089
  onConfirm(confirmed);
48481
49090
  };
@@ -48502,25 +49111,34 @@ function ConfirmScreen({
48502
49111
  confirm(selectedIndex() === 0);
48503
49112
  }
48504
49113
  });
48505
- const renderOption = (label, isSelected) => (() => {
49114
+ const renderOption = (label, isSelected) => isSelected ? (() => {
48506
49115
  var _el$ = createElement("text");
48507
- spread(_el$, mergeProps3(() => isSelected ? {
48508
- fg: "cyan",
48509
- attributes: TextAttributes.BOLD
48510
- } : {}), true);
48511
- insert(_el$, label);
49116
+ insert(_el$, () => padLine4(label, contentWidth()));
49117
+ effect((_p$) => {
49118
+ var _v$ = selectionStyle.fg, _v$2 = selectionStyle.bg;
49119
+ _v$ !== _p$.e && (_p$.e = setProp(_el$, "fg", _v$, _p$.e));
49120
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$, "bg", _v$2, _p$.t));
49121
+ return _p$;
49122
+ }, {
49123
+ e: undefined,
49124
+ t: undefined
49125
+ });
48512
49126
  return _el$;
49127
+ })() : (() => {
49128
+ var _el$2 = createElement("text");
49129
+ insert(_el$2, label);
49130
+ return _el$2;
48513
49131
  })();
48514
49132
  return (() => {
48515
- var _el$2 = createElement("box"), _el$3 = createElement("text"), _el$4 = createElement("box");
48516
- insertNode(_el$2, _el$3);
48517
- insertNode(_el$2, _el$4);
48518
- setProp(_el$2, "flexDirection", "column");
48519
- insert(_el$3, message);
48520
- setProp(_el$4, "flexDirection", "column");
48521
- insert(_el$4, () => renderOption(yesLabel, selectedIndex() === 0), null);
48522
- insert(_el$4, () => renderOption(noLabel, selectedIndex() === 1), null);
48523
- return _el$2;
49133
+ var _el$3 = createElement("box"), _el$4 = createElement("text"), _el$5 = createElement("box");
49134
+ insertNode(_el$3, _el$4);
49135
+ insertNode(_el$3, _el$5);
49136
+ setProp(_el$3, "flexDirection", "column");
49137
+ insert(_el$4, message);
49138
+ setProp(_el$5, "flexDirection", "column");
49139
+ insert(_el$5, () => renderOption(yesLabel, selectedIndex() === 0), null);
49140
+ insert(_el$5, () => renderOption(noLabel, selectedIndex() === 1), null);
49141
+ return _el$3;
48524
49142
  })();
48525
49143
  }
48526
49144
 
@@ -48535,6 +49153,10 @@ function EnvironmentScreen({
48535
49153
  helpVisible = false
48536
49154
  }) {
48537
49155
  const terminal = useTerminalSize();
49156
+ const padLine4 = (value, width) => {
49157
+ const padding = Math.max(0, width - stringWidth(value));
49158
+ return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
49159
+ };
48538
49160
  const listHeight = createMemo(() => {
48539
49161
  const headerRows = 2;
48540
49162
  const footerRows = 1;
@@ -48630,27 +49252,36 @@ function EnvironmentScreen({
48630
49252
  const absoluteIndex = list.scrollOffset() + index;
48631
49253
  const isSelected = absoluteIndex === list.selectedIndex();
48632
49254
  const isHighlighted = highlightSet().has(variable.key);
48633
- const attributes = isSelected ? TextAttributes.BOLD : undefined;
48634
- const keyColor = isSelected ? "cyan" : isHighlighted ? "yellow" : undefined;
48635
- const valueColor = isSelected ? "cyan" : undefined;
49255
+ const keyColor = isHighlighted ? "yellow" : undefined;
48636
49256
  return (() => {
48637
- var _el$6 = createElement("box"), _el$7 = createElement("text"), _el$8 = createElement("text"), _el$9 = createTextNode(`=`);
48638
- insertNode(_el$6, _el$7);
48639
- insertNode(_el$6, _el$8);
49257
+ var _el$6 = createElement("box");
48640
49258
  setProp(_el$6, "flexDirection", "row");
48641
- spread(_el$7, mergeProps3(keyColor ? {
48642
- fg: keyColor
48643
- } : {}, attributes !== undefined ? {
48644
- attributes
48645
- } : {}), true);
48646
- insert(_el$7, () => variable.key);
48647
- insertNode(_el$8, _el$9);
48648
- spread(_el$8, mergeProps3(valueColor ? {
48649
- fg: valueColor
48650
- } : {}, attributes !== undefined ? {
48651
- attributes
48652
- } : {}), true);
48653
- insert(_el$8, () => variable.value, null);
49259
+ insert(_el$6, isSelected ? (() => {
49260
+ var _el$7 = createElement("text");
49261
+ insert(_el$7, () => padLine4(`${variable.key}=${variable.value}`, terminal().columns));
49262
+ effect((_p$) => {
49263
+ var _v$ = selectionStyle.fg, _v$2 = selectionStyle.bg;
49264
+ _v$ !== _p$.e && (_p$.e = setProp(_el$7, "fg", _v$, _p$.e));
49265
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$7, "bg", _v$2, _p$.t));
49266
+ return _p$;
49267
+ }, {
49268
+ e: undefined,
49269
+ t: undefined
49270
+ });
49271
+ return _el$7;
49272
+ })() : [(() => {
49273
+ var _el$8 = createElement("text");
49274
+ spread(_el$8, keyColor ? {
49275
+ fg: keyColor
49276
+ } : {}, true);
49277
+ insert(_el$8, () => variable.key);
49278
+ return _el$8;
49279
+ })(), (() => {
49280
+ var _el$9 = createElement("text"), _el$0 = createTextNode(`=`);
49281
+ insertNode(_el$9, _el$0);
49282
+ insert(_el$9, () => variable.value, null);
49283
+ return _el$9;
49284
+ })()]);
48654
49285
  return _el$6;
48655
49286
  })();
48656
49287
  }));
@@ -48752,6 +49383,10 @@ function ProfileEnvScreen({
48752
49383
  helpVisible = false
48753
49384
  }) {
48754
49385
  const terminal = useTerminalSize();
49386
+ const padLine4 = (value, width) => {
49387
+ const padding = Math.max(0, width - stringWidth(value));
49388
+ return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
49389
+ };
48755
49390
  const listHeight = createMemo(() => {
48756
49391
  const headerRows = 2;
48757
49392
  const footerRows = 1;
@@ -48882,26 +49517,32 @@ function ProfileEnvScreen({
48882
49517
  insert(_el$5, () => list.visibleItems().map((variable, index) => {
48883
49518
  const absoluteIndex = list.scrollOffset() + index;
48884
49519
  const isSelected = absoluteIndex === list.selectedIndex();
48885
- const attributes = isSelected ? TextAttributes.BOLD : undefined;
48886
- const color = isSelected ? "cyan" : undefined;
48887
49520
  return (() => {
48888
- var _el$6 = createElement("box"), _el$7 = createElement("text"), _el$8 = createElement("text"), _el$9 = createTextNode(`=`);
48889
- insertNode(_el$6, _el$7);
48890
- insertNode(_el$6, _el$8);
49521
+ var _el$6 = createElement("box");
48891
49522
  setProp(_el$6, "flexDirection", "row");
48892
- spread(_el$7, mergeProps3(color ? {
48893
- fg: color
48894
- } : {}, attributes !== undefined ? {
48895
- attributes
48896
- } : {}), true);
48897
- insert(_el$7, () => variable.key);
48898
- insertNode(_el$8, _el$9);
48899
- spread(_el$8, mergeProps3(color ? {
48900
- fg: color
48901
- } : {}, attributes !== undefined ? {
48902
- attributes
48903
- } : {}), true);
48904
- insert(_el$8, () => variable.value, null);
49523
+ insert(_el$6, isSelected ? (() => {
49524
+ var _el$7 = createElement("text");
49525
+ insert(_el$7, () => padLine4(`${variable.key}=${variable.value}`, terminal().columns));
49526
+ effect((_p$) => {
49527
+ var _v$ = selectionStyle.fg, _v$2 = selectionStyle.bg;
49528
+ _v$ !== _p$.e && (_p$.e = setProp(_el$7, "fg", _v$, _p$.e));
49529
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$7, "bg", _v$2, _p$.t));
49530
+ return _p$;
49531
+ }, {
49532
+ e: undefined,
49533
+ t: undefined
49534
+ });
49535
+ return _el$7;
49536
+ })() : [(() => {
49537
+ var _el$8 = createElement("text");
49538
+ insert(_el$8, () => variable.key);
49539
+ return _el$8;
49540
+ })(), (() => {
49541
+ var _el$9 = createElement("text"), _el$0 = createTextNode(`=`);
49542
+ insertNode(_el$9, _el$0);
49543
+ insert(_el$9, () => variable.value, null);
49544
+ return _el$9;
49545
+ })()]);
48905
49546
  return _el$6;
48906
49547
  })();
48907
49548
  }));
@@ -49000,7 +49641,8 @@ function createLogger(config = {}) {
49000
49641
  if (config.sync) {
49001
49642
  const destinationStream2 = import_pino.default.destination({
49002
49643
  dest: destination,
49003
- sync: true
49644
+ sync: true,
49645
+ append: true
49004
49646
  });
49005
49647
  return import_pino.default(options, destinationStream2);
49006
49648
  }
@@ -49024,7 +49666,8 @@ function createLogger(config = {}) {
49024
49666
  }
49025
49667
  const destinationStream = import_pino.default.destination({
49026
49668
  dest: destination,
49027
- sync: false
49669
+ sync: false,
49670
+ append: true
49028
49671
  });
49029
49672
  return import_pino.default(options, destinationStream);
49030
49673
  }
@@ -49819,6 +50462,9 @@ async function listWorktrees() {
49819
50462
  throw new WorktreeError("Failed to list worktrees", error);
49820
50463
  }
49821
50464
  }
50465
+ async function listAllWorktrees() {
50466
+ return listWorktrees();
50467
+ }
49822
50468
  async function listAdditionalWorktrees() {
49823
50469
  try {
49824
50470
  const [allWorktrees, repoRoot] = await Promise.all([
@@ -49962,7 +50608,8 @@ async function getWorktreesWithPRStatus() {
49962
50608
  }
49963
50609
  async function getOrphanedLocalBranchStatuses({
49964
50610
  baseBranch,
49965
- repoRoot
50611
+ repoRoot,
50612
+ onProgress
49966
50613
  }) {
49967
50614
  try {
49968
50615
  const [localBranches, worktrees] = await Promise.all([
@@ -49991,8 +50638,7 @@ async function getOrphanedLocalBranchStatuses({
49991
50638
  hasUnpushed = true;
49992
50639
  }
49993
50640
  const { upstream, hasUpstream } = await resolveUpstreamStatus(localBranch.name, repoRoot);
49994
- const comparisonBase = upstream ?? baseBranch;
49995
- const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(localBranch.name, comparisonBase, repoRoot);
50641
+ const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(localBranch.name, baseBranch, repoRoot);
49996
50642
  const reasons = buildCleanupReasons({
49997
50643
  hasUniqueCommits,
49998
50644
  hasUncommitted: false,
@@ -50002,7 +50648,7 @@ async function getOrphanedLocalBranchStatuses({
50002
50648
  if (process.env.DEBUG_CLEANUP) {
50003
50649
  console.log(source_default.gray(`Debug: Checking orphaned branch ${localBranch.name} -> reasons: ${reasons.join(", ")}`));
50004
50650
  }
50005
- statuses.push({
50651
+ const status = {
50006
50652
  worktreePath: null,
50007
50653
  branch: localBranch.name,
50008
50654
  hasUncommittedChanges: false,
@@ -50013,7 +50659,9 @@ async function getOrphanedLocalBranchStatuses({
50013
50659
  hasUpstream,
50014
50660
  upstream,
50015
50661
  reasons
50016
- });
50662
+ };
50663
+ statuses.push(status);
50664
+ onProgress?.(status);
50017
50665
  }
50018
50666
  }
50019
50667
  if (process.env.DEBUG_CLEANUP) {
@@ -50028,7 +50676,9 @@ async function getOrphanedLocalBranchStatuses({
50028
50676
  return [];
50029
50677
  }
50030
50678
  }
50031
- async function getCleanupStatus() {
50679
+ async function getCleanupStatus({
50680
+ onProgress
50681
+ } = {}) {
50032
50682
  const [config, repoRoot, worktreesWithPR] = await Promise.all([
50033
50683
  getConfig(),
50034
50684
  getRepositoryRoot(),
@@ -50037,7 +50687,8 @@ async function getCleanupStatus() {
50037
50687
  const baseBranch = config.defaultBaseBranch || GIT_CONFIG.DEFAULT_BASE_BRANCH;
50038
50688
  const orphanedStatuses = await getOrphanedLocalBranchStatuses({
50039
50689
  baseBranch,
50040
- repoRoot
50690
+ repoRoot,
50691
+ ...onProgress ? { onProgress } : {}
50041
50692
  });
50042
50693
  const statuses = [];
50043
50694
  if (process.env.DEBUG_CLEANUP) {
@@ -50066,8 +50717,7 @@ async function getCleanupStatus() {
50066
50717
  }
50067
50718
  }
50068
50719
  const { upstream, hasUpstream } = await resolveUpstreamStatus(worktree.branch, repoRoot);
50069
- const comparisonBase = upstream ?? baseBranch;
50070
- const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(worktree.branch, comparisonBase, repoRoot);
50720
+ const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(worktree.branch, baseBranch, repoRoot);
50071
50721
  const reasons = buildCleanupReasons({
50072
50722
  hasUniqueCommits,
50073
50723
  hasUncommitted,
@@ -50077,7 +50727,7 @@ async function getCleanupStatus() {
50077
50727
  if (process.env.DEBUG_CLEANUP) {
50078
50728
  console.log(source_default.gray(`Debug: Cleanup reasons for ${worktree.branch}: ${reasons.length > 0 ? reasons.join(", ") : "none"}`));
50079
50729
  }
50080
- statuses.push({
50730
+ const status = {
50081
50731
  worktreePath: worktree.worktreePath,
50082
50732
  branch: worktree.branch,
50083
50733
  hasUncommittedChanges: hasUncommitted,
@@ -50090,7 +50740,9 @@ async function getCleanupStatus() {
50090
50740
  isAccessible,
50091
50741
  reasons,
50092
50742
  ...isAccessible ? {} : { invalidReason: "Path not accessible in current environment" }
50093
- });
50743
+ };
50744
+ statuses.push(status);
50745
+ onProgress?.(status);
50094
50746
  }
50095
50747
  statuses.push(...orphanedStatuses);
50096
50748
  if (process.env.DEBUG_CLEANUP) {
@@ -50101,22 +50753,643 @@ async function getCleanupStatus() {
50101
50753
  return statuses;
50102
50754
  }
50103
50755
 
50104
- // src/config/tools.ts
50105
- import { homedir as homedir4 } from "os";
50756
+ // src/utils/session/common.ts
50757
+ import path14 from "path";
50758
+ import { readdir, readFile as readFile2, stat } from "fs/promises";
50759
+ var UUID_REGEX = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
50760
+ function isValidUuidSessionId(id) {
50761
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
50762
+ }
50763
+ function pickSessionIdFromObject(obj) {
50764
+ if (!obj || typeof obj !== "object")
50765
+ return null;
50766
+ const candidate = obj;
50767
+ const keys = ["sessionId", "session_id", "id", "conversation_id"];
50768
+ for (const key of keys) {
50769
+ const value = candidate[key];
50770
+ if (typeof value === "string" && value.trim().length > 0) {
50771
+ const trimmed = value.trim();
50772
+ if (isValidUuidSessionId(trimmed)) {
50773
+ return trimmed;
50774
+ }
50775
+ }
50776
+ }
50777
+ return null;
50778
+ }
50779
+ function pickCwdFromObject(obj) {
50780
+ if (!obj || typeof obj !== "object")
50781
+ return null;
50782
+ const candidate = obj;
50783
+ const keys = [
50784
+ "cwd",
50785
+ "workingDirectory",
50786
+ "workdir",
50787
+ "directory",
50788
+ "projectPath"
50789
+ ];
50790
+ for (const key of keys) {
50791
+ const value = candidate[key];
50792
+ if (typeof value === "string" && value.trim().length > 0) {
50793
+ return value;
50794
+ }
50795
+ }
50796
+ const payload = candidate["payload"];
50797
+ if (payload && typeof payload === "object") {
50798
+ const nested = pickCwdFromObject(payload);
50799
+ if (nested)
50800
+ return nested;
50801
+ }
50802
+ return null;
50803
+ }
50804
+ function pickSessionIdFromText(content) {
50805
+ try {
50806
+ const parsed = JSON.parse(content);
50807
+ const fromObject = pickSessionIdFromObject(parsed);
50808
+ if (fromObject)
50809
+ return fromObject;
50810
+ } catch {}
50811
+ const lines = content.split(/\r?\n/);
50812
+ for (const line of lines) {
50813
+ const trimmed = line.trim();
50814
+ if (!trimmed)
50815
+ continue;
50816
+ try {
50817
+ const parsedLine = JSON.parse(trimmed);
50818
+ const fromLine = pickSessionIdFromObject(parsedLine);
50819
+ if (fromLine)
50820
+ return fromLine;
50821
+ } catch {}
50822
+ const match2 = trimmed.match(UUID_REGEX);
50823
+ if (match2)
50824
+ return match2[0];
50825
+ }
50826
+ const match = content.match(UUID_REGEX);
50827
+ return match ? match[0] : null;
50828
+ }
50829
+ async function collectFilesIterative(dir, filter) {
50830
+ const results = [];
50831
+ const queue = [dir];
50832
+ while (queue.length > 0) {
50833
+ const currentDir = queue.shift();
50834
+ if (!currentDir)
50835
+ break;
50836
+ try {
50837
+ const entries = await readdir(currentDir, { withFileTypes: true });
50838
+ for (const entry of entries) {
50839
+ const fullPath = path14.join(currentDir, entry.name);
50840
+ if (entry.isDirectory()) {
50841
+ queue.push(fullPath);
50842
+ } else if (entry.isFile() && filter(entry.name)) {
50843
+ try {
50844
+ const info = await stat(fullPath);
50845
+ results.push({ fullPath, mtime: info.mtimeMs });
50846
+ } catch {}
50847
+ }
50848
+ }
50849
+ } catch {}
50850
+ }
50851
+ return results;
50852
+ }
50853
+ async function readSessionIdFromFile(filePath) {
50854
+ try {
50855
+ const basename2 = path14.basename(filePath);
50856
+ const filenameWithoutExt = basename2.replace(/\.(json|jsonl)$/i, "");
50857
+ if (isValidUuidSessionId(filenameWithoutExt)) {
50858
+ return filenameWithoutExt;
50859
+ }
50860
+ const content = await readFile2(filePath, "utf-8");
50861
+ const fromContent = pickSessionIdFromText(content);
50862
+ if (fromContent)
50863
+ return fromContent;
50864
+ const filenameMatch = basename2.match(UUID_REGEX);
50865
+ return filenameMatch ? filenameMatch[0] : null;
50866
+ } catch {
50867
+ return null;
50868
+ }
50869
+ }
50870
+ async function readSessionInfoFromFile(filePath) {
50871
+ try {
50872
+ const content = await readFile2(filePath, "utf-8");
50873
+ try {
50874
+ const parsed = JSON.parse(content);
50875
+ const id = pickSessionIdFromObject(parsed);
50876
+ const cwd = pickCwdFromObject(parsed);
50877
+ if (id || cwd)
50878
+ return { id, cwd };
50879
+ } catch {}
50880
+ const lines = content.split(/\r?\n/);
50881
+ for (const line of lines) {
50882
+ const trimmed = line.trim();
50883
+ if (!trimmed)
50884
+ continue;
50885
+ try {
50886
+ const parsedLine = JSON.parse(trimmed);
50887
+ const id = pickSessionIdFromObject(parsedLine);
50888
+ const cwd = pickCwdFromObject(parsedLine);
50889
+ if (id || cwd)
50890
+ return { id, cwd };
50891
+ } catch {}
50892
+ }
50893
+ const filenameMatch = path14.basename(filePath).match(UUID_REGEX);
50894
+ if (filenameMatch)
50895
+ return { id: filenameMatch[0], cwd: null };
50896
+ } catch {}
50897
+ return { id: null, cwd: null };
50898
+ }
50899
+ async function findNewestSessionIdFromDir(dir, recursive, options = {}) {
50900
+ try {
50901
+ const files = [];
50902
+ const queue = [dir];
50903
+ while (queue.length > 0) {
50904
+ const currentDir = queue.shift();
50905
+ if (!currentDir)
50906
+ break;
50907
+ try {
50908
+ const entries = await readdir(currentDir, { withFileTypes: true });
50909
+ for (const entry of entries) {
50910
+ const fullPath = path14.join(currentDir, entry.name);
50911
+ if (entry.isDirectory()) {
50912
+ if (recursive) {
50913
+ queue.push(fullPath);
50914
+ }
50915
+ continue;
50916
+ }
50917
+ if (!entry.isFile())
50918
+ continue;
50919
+ if (!entry.name.endsWith(".json") && !entry.name.endsWith(".jsonl"))
50920
+ continue;
50921
+ try {
50922
+ const info = await stat(fullPath);
50923
+ files.push({ fullPath, mtime: info.mtimeMs });
50924
+ } catch {}
50925
+ }
50926
+ } catch {}
50927
+ }
50928
+ const filtered = files.filter((f) => {
50929
+ if (options.since !== undefined && f.mtime < options.since)
50930
+ return false;
50931
+ if (options.until !== undefined && f.mtime > options.until)
50932
+ return false;
50933
+ return true;
50934
+ });
50935
+ if (!filtered.length)
50936
+ return null;
50937
+ let pool = filtered.sort((a2, b) => b.mtime - a2.mtime);
50938
+ const ref = options.preferClosestTo;
50939
+ if (typeof ref === "number") {
50940
+ const window = options.windowMs ?? 30 * 60 * 1000;
50941
+ const withinWindow = pool.filter((f) => Math.abs(f.mtime - ref) <= window);
50942
+ if (withinWindow.length) {
50943
+ pool = withinWindow.sort((a2, b) => b.mtime - a2.mtime);
50944
+ }
50945
+ }
50946
+ for (const file of pool) {
50947
+ const id = await readSessionIdFromFile(file.fullPath);
50948
+ if (id)
50949
+ return { id, mtime: file.mtime };
50950
+ }
50951
+ } catch {}
50952
+ return null;
50953
+ }
50954
+ async function readFileContent(filePath) {
50955
+ return readFile2(filePath, "utf-8");
50956
+ }
50957
+ async function checkFileStat(filePath) {
50958
+ try {
50959
+ const info = await stat(filePath);
50960
+ return { mtimeMs: info.mtimeMs };
50961
+ } catch {
50962
+ return null;
50963
+ }
50964
+ }
50965
+ function normalizePath(p) {
50966
+ return path14.normalize(p).replace(/\\/g, "/");
50967
+ }
50968
+ function isPathPrefix(prefix, full) {
50969
+ if (!full.startsWith(prefix))
50970
+ return false;
50971
+ if (full.length === prefix.length)
50972
+ return true;
50973
+ return full[prefix.length] === "/";
50974
+ }
50975
+ function matchesCwd(sessionCwd, targetCwd) {
50976
+ if (!sessionCwd)
50977
+ return false;
50978
+ const normalizedSession = normalizePath(sessionCwd);
50979
+ const normalizedTarget = normalizePath(targetCwd);
50980
+ return normalizedSession === normalizedTarget || isPathPrefix(normalizedTarget, normalizedSession) || isPathPrefix(normalizedSession, normalizedTarget);
50981
+ }
50982
+ function resolveBranchFromCwd(sessionCwd, worktrees) {
50983
+ if (!sessionCwd)
50984
+ return null;
50985
+ const normalizedSession = normalizePath(sessionCwd);
50986
+ let bestMatch = null;
50987
+ for (const worktree of worktrees) {
50988
+ if (!worktree?.path || !worktree.branch)
50989
+ continue;
50990
+ const normalizedPath = normalizePath(worktree.path);
50991
+ if (normalizedSession === normalizedPath || isPathPrefix(normalizedPath, normalizedSession)) {
50992
+ if (!bestMatch || normalizedPath.length > bestMatch.path.length) {
50993
+ bestMatch = { branch: worktree.branch, path: normalizedPath };
50994
+ }
50995
+ }
50996
+ }
50997
+ return bestMatch?.branch ?? null;
50998
+ }
50999
+ // src/utils/session/parsers/claude.ts
50106
51000
  import path15 from "path";
50107
- import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, rename as rename2 } from "fs/promises";
51001
+ import { homedir as homedir3 } from "os";
51002
+ function encodeClaudeProjectPath(cwd) {
51003
+ const normalized = cwd.replace(/\\/g, "/").replace(/:/g, "");
51004
+ return normalized.replace(/_/g, "-").replace(/\//g, "-");
51005
+ }
51006
+ function generateClaudeProjectPathCandidates(cwd) {
51007
+ const base2 = encodeClaudeProjectPath(cwd);
51008
+ const dotToDash = cwd.replace(/\\/g, "/").replace(/:/g, "").replace(/\./g, "-").replace(/_/g, "-").replace(/\//g, "-");
51009
+ const collapsed = dotToDash.replace(/-+/g, "-");
51010
+ const candidates = [base2, dotToDash, collapsed];
51011
+ return Array.from(new Set(candidates));
51012
+ }
51013
+ function getClaudeRootCandidates() {
51014
+ const roots = [];
51015
+ if (process.env.CLAUDE_CONFIG_DIR) {
51016
+ roots.push(process.env.CLAUDE_CONFIG_DIR);
51017
+ }
51018
+ roots.push(path15.join(homedir3(), ".claude"), path15.join(homedir3(), ".config", "claude"));
51019
+ return roots;
51020
+ }
51021
+ async function findLatestClaudeSession(cwd, options = {}) {
51022
+ const rootCandidates = getClaudeRootCandidates();
51023
+ const branchFilter = typeof options.branch === "string" && options.branch.trim().length > 0 ? options.branch.trim() : null;
51024
+ let cwdCandidates = [];
51025
+ if (branchFilter) {
51026
+ let worktrees = [];
51027
+ if (Array.isArray(options.worktrees) && options.worktrees.length > 0) {
51028
+ worktrees = options.worktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
51029
+ } else {
51030
+ try {
51031
+ const allWorktrees = await listAllWorktrees();
51032
+ worktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
51033
+ } catch {
51034
+ worktrees = [];
51035
+ }
51036
+ }
51037
+ const matches = worktrees.filter((entry) => entry.branch === branchFilter).map((entry) => entry.path);
51038
+ if (!matches.length)
51039
+ return null;
51040
+ cwdCandidates = matches;
51041
+ } else {
51042
+ const baseCwd = options.cwd ?? cwd;
51043
+ if (!baseCwd)
51044
+ return null;
51045
+ cwdCandidates = [baseCwd];
51046
+ }
51047
+ const uniqueCwds = Array.from(new Set(cwdCandidates));
51048
+ for (const candidateCwd of uniqueCwds) {
51049
+ const encodedPaths = generateClaudeProjectPathCandidates(candidateCwd);
51050
+ for (const claudeRoot of rootCandidates) {
51051
+ for (const encoded of encodedPaths) {
51052
+ const projectDir = path15.join(claudeRoot, "projects", encoded);
51053
+ const sessionsDir = path15.join(projectDir, "sessions");
51054
+ const session = await findNewestSessionIdFromDir(sessionsDir, false, options);
51055
+ if (session)
51056
+ return session;
51057
+ const rootSession = await findNewestSessionIdFromDir(projectDir, true, options);
51058
+ if (rootSession)
51059
+ return rootSession;
51060
+ }
51061
+ }
51062
+ }
51063
+ try {
51064
+ const historyPath = path15.join(homedir3(), ".claude", "history.jsonl");
51065
+ const historyStat = await checkFileStat(historyPath);
51066
+ if (!historyStat)
51067
+ return null;
51068
+ const content = await readFileContent(historyPath);
51069
+ const lines = content.split(/\r?\n/).filter(Boolean);
51070
+ for (let i2 = lines.length - 1;i2 >= 0; i2 -= 1) {
51071
+ try {
51072
+ const line = lines[i2] ?? "";
51073
+ const parsed = JSON.parse(line);
51074
+ const project = typeof parsed.project === "string" ? parsed.project : null;
51075
+ const sessionId = typeof parsed.sessionId === "string" ? parsed.sessionId : null;
51076
+ const matchesProject = uniqueCwds.some((candidate) => matchesCwd(project, candidate));
51077
+ if (project && sessionId && matchesProject) {
51078
+ return { id: sessionId, mtime: historyStat.mtimeMs };
51079
+ }
51080
+ } catch {}
51081
+ }
51082
+ } catch {}
51083
+ return null;
51084
+ }
51085
+ // src/utils/session/parsers/codex.ts
51086
+ import path16 from "path";
51087
+ import { homedir as homedir4 } from "os";
51088
+ async function findLatestCodexSession(options = {}) {
51089
+ const codexHome = process.env.CODEX_HOME ?? path16.join(homedir4(), ".codex");
51090
+ const baseDir = path16.join(codexHome, "sessions");
51091
+ const candidates = await collectFilesIterative(baseDir, (name) => name.endsWith(".json") || name.endsWith(".jsonl"));
51092
+ if (!candidates.length)
51093
+ return null;
51094
+ let pool = candidates;
51095
+ const sinceVal = options.since;
51096
+ const untilVal = options.until;
51097
+ if (sinceVal !== undefined) {
51098
+ pool = pool.filter((c3) => c3.mtime >= sinceVal);
51099
+ }
51100
+ if (untilVal !== undefined) {
51101
+ pool = pool.filter((c3) => c3.mtime <= untilVal);
51102
+ }
51103
+ if (!pool.length)
51104
+ return null;
51105
+ const ref = options.preferClosestTo;
51106
+ const window = options.windowMs ?? 30 * 60 * 1000;
51107
+ const ordered = [...pool].sort((a2, b) => {
51108
+ if (typeof ref === "number") {
51109
+ const da = Math.abs(a2.mtime - ref);
51110
+ const db = Math.abs(b.mtime - ref);
51111
+ if (da === db)
51112
+ return b.mtime - a2.mtime;
51113
+ if (da <= window || db <= window)
51114
+ return da - db;
51115
+ }
51116
+ return b.mtime - a2.mtime;
51117
+ });
51118
+ const branchFilter = typeof options.branch === "string" && options.branch.trim().length > 0 ? options.branch.trim() : null;
51119
+ const shouldCheckBranch = Boolean(branchFilter);
51120
+ const shouldCheckCwd = Boolean(options.cwd) && !shouldCheckBranch;
51121
+ let worktrees = [];
51122
+ if (shouldCheckBranch) {
51123
+ if (Array.isArray(options.worktrees) && options.worktrees.length > 0) {
51124
+ worktrees = options.worktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
51125
+ } else {
51126
+ try {
51127
+ const allWorktrees = await listAllWorktrees();
51128
+ worktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
51129
+ } catch {
51130
+ worktrees = [];
51131
+ }
51132
+ }
51133
+ if (!worktrees.length)
51134
+ return null;
51135
+ }
51136
+ for (const file of ordered) {
51137
+ const filenameMatch = path16.basename(file.fullPath).match(UUID_REGEX);
51138
+ const idFromName = filenameMatch?.[0] ?? null;
51139
+ const needsInfo = shouldCheckBranch || shouldCheckCwd || !idFromName;
51140
+ const info = needsInfo ? await readSessionInfoFromFile(file.fullPath) : null;
51141
+ const sessionCwd = info?.cwd ?? null;
51142
+ if (shouldCheckBranch) {
51143
+ const resolvedBranch = resolveBranchFromCwd(sessionCwd, worktrees);
51144
+ if (resolvedBranch !== branchFilter) {
51145
+ continue;
51146
+ }
51147
+ }
51148
+ if (shouldCheckCwd && options.cwd) {
51149
+ if (!matchesCwd(sessionCwd, options.cwd)) {
51150
+ continue;
51151
+ }
51152
+ }
51153
+ const sessionId = idFromName ?? info?.id ?? null;
51154
+ if (sessionId) {
51155
+ return { id: sessionId, mtime: file.mtime };
51156
+ }
51157
+ }
51158
+ return null;
51159
+ }
51160
+ // src/utils/session/parsers/gemini.ts
51161
+ import path17 from "path";
51162
+ import { homedir as homedir5 } from "os";
51163
+ async function findLatestGeminiSession(options = {}) {
51164
+ const baseDir = path17.join(homedir5(), ".gemini", "tmp");
51165
+ const files = await collectFilesIterative(baseDir, (name) => name.endsWith(".json") || name.endsWith(".jsonl"));
51166
+ if (!files.length)
51167
+ return null;
51168
+ let pool = files;
51169
+ const sinceVal = options.since;
51170
+ if (sinceVal !== undefined) {
51171
+ pool = pool.filter((f) => f.mtime >= sinceVal);
51172
+ }
51173
+ const untilVal = options.until;
51174
+ if (untilVal !== undefined) {
51175
+ pool = pool.filter((f) => f.mtime <= untilVal);
51176
+ }
51177
+ if (!pool.length)
51178
+ return null;
51179
+ const ref = options.preferClosestTo;
51180
+ const window = options.windowMs ?? 30 * 60 * 1000;
51181
+ pool = pool.slice().sort((a2, b) => {
51182
+ if (typeof ref === "number") {
51183
+ const da = Math.abs(a2.mtime - ref);
51184
+ const db = Math.abs(b.mtime - ref);
51185
+ if (da === db)
51186
+ return b.mtime - a2.mtime;
51187
+ if (da <= window || db <= window)
51188
+ return da - db;
51189
+ }
51190
+ return b.mtime - a2.mtime;
51191
+ });
51192
+ const branchFilter = typeof options.branch === "string" && options.branch.trim().length > 0 ? options.branch.trim() : null;
51193
+ const shouldCheckBranch = Boolean(branchFilter);
51194
+ const shouldCheckCwd = Boolean(options.cwd) && !shouldCheckBranch;
51195
+ let worktrees = [];
51196
+ if (shouldCheckBranch) {
51197
+ if (Array.isArray(options.worktrees) && options.worktrees.length > 0) {
51198
+ worktrees = options.worktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
51199
+ } else {
51200
+ try {
51201
+ const allWorktrees = await listAllWorktrees();
51202
+ worktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
51203
+ } catch {
51204
+ worktrees = [];
51205
+ }
51206
+ }
51207
+ if (!worktrees.length)
51208
+ return null;
51209
+ }
51210
+ for (const file of pool) {
51211
+ const info = await readSessionInfoFromFile(file.fullPath);
51212
+ if (!info.id)
51213
+ continue;
51214
+ const sessionCwd = info.cwd ?? null;
51215
+ if (shouldCheckBranch) {
51216
+ const resolvedBranch = resolveBranchFromCwd(sessionCwd, worktrees);
51217
+ if (resolvedBranch !== branchFilter) {
51218
+ continue;
51219
+ }
51220
+ }
51221
+ if (shouldCheckCwd && options.cwd) {
51222
+ if (!matchesCwd(sessionCwd, options.cwd)) {
51223
+ continue;
51224
+ }
51225
+ }
51226
+ return { id: info.id, mtime: file.mtime };
51227
+ }
51228
+ return null;
51229
+ }
51230
+ // src/utils/session/parsers/opencode.ts
51231
+ import path18 from "path";
51232
+ import { homedir as homedir6 } from "os";
51233
+ function getOpenCodeSessionDir() {
51234
+ return path18.join(homedir6(), ".local", "share", "opencode", "storage", "session");
51235
+ }
51236
+ async function findLatestOpenCodeSession(options = {}) {
51237
+ const baseDir = getOpenCodeSessionDir();
51238
+ const files = await collectFilesIterative(baseDir, (name) => name.endsWith(".json") || name.endsWith(".jsonl"));
51239
+ if (!files.length)
51240
+ return null;
51241
+ let pool = files;
51242
+ const sinceVal = options.since;
51243
+ if (sinceVal !== undefined) {
51244
+ pool = pool.filter((f) => f.mtime >= sinceVal);
51245
+ }
51246
+ const untilVal = options.until;
51247
+ if (untilVal !== undefined) {
51248
+ pool = pool.filter((f) => f.mtime <= untilVal);
51249
+ }
51250
+ if (!pool.length)
51251
+ return null;
51252
+ const ref = options.preferClosestTo;
51253
+ const window = options.windowMs ?? 30 * 60 * 1000;
51254
+ pool = pool.slice().sort((a2, b) => {
51255
+ if (typeof ref === "number") {
51256
+ const da = Math.abs(a2.mtime - ref);
51257
+ const db = Math.abs(b.mtime - ref);
51258
+ if (da === db)
51259
+ return b.mtime - a2.mtime;
51260
+ if (da <= window || db <= window)
51261
+ return da - db;
51262
+ }
51263
+ return b.mtime - a2.mtime;
51264
+ });
51265
+ const branchFilter = typeof options.branch === "string" && options.branch.trim().length > 0 ? options.branch.trim() : null;
51266
+ const shouldCheckBranch = Boolean(branchFilter);
51267
+ const shouldCheckCwd = Boolean(options.cwd) && !shouldCheckBranch;
51268
+ let worktrees = [];
51269
+ if (shouldCheckBranch) {
51270
+ if (Array.isArray(options.worktrees) && options.worktrees.length > 0) {
51271
+ worktrees = options.worktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
51272
+ } else {
51273
+ try {
51274
+ const allWorktrees = await listAllWorktrees();
51275
+ worktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
51276
+ } catch {
51277
+ worktrees = [];
51278
+ }
51279
+ }
51280
+ if (!worktrees.length)
51281
+ return null;
51282
+ }
51283
+ for (const file of pool) {
51284
+ const info = await readSessionInfoFromFile(file.fullPath);
51285
+ if (!info.id)
51286
+ continue;
51287
+ const sessionCwd = info.cwd ?? null;
51288
+ if (shouldCheckBranch) {
51289
+ const resolvedBranch = resolveBranchFromCwd(sessionCwd, worktrees);
51290
+ if (resolvedBranch !== branchFilter) {
51291
+ continue;
51292
+ }
51293
+ }
51294
+ if (shouldCheckCwd && options.cwd) {
51295
+ if (!matchesCwd(sessionCwd, options.cwd)) {
51296
+ continue;
51297
+ }
51298
+ }
51299
+ return { id: info.id, mtime: file.mtime };
51300
+ }
51301
+ return null;
51302
+ }
51303
+ // src/cli/ui/utils/continueSession.ts
51304
+ function findLatestBranchSessionsByTool(history, branch, worktreePath) {
51305
+ const byBranch = history.filter((entry) => entry && entry.branch === branch);
51306
+ if (!byBranch.length)
51307
+ return [];
51308
+ const source = worktreePath ? byBranch.filter((entry) => entry.worktreePath === worktreePath) : byBranch;
51309
+ if (!source.length)
51310
+ return [];
51311
+ const latestByTool = new Map;
51312
+ for (const entry of source) {
51313
+ if (!entry.toolId)
51314
+ continue;
51315
+ const current = latestByTool.get(entry.toolId);
51316
+ const currentTs = current?.timestamp ?? 0;
51317
+ const entryTs = entry.timestamp ?? 0;
51318
+ if (!current || entryTs >= currentTs) {
51319
+ latestByTool.set(entry.toolId, entry);
51320
+ }
51321
+ }
51322
+ return Array.from(latestByTool.values()).sort((a2, b) => (b.timestamp ?? 0) - (a2.timestamp ?? 0));
51323
+ }
51324
+ async function refreshQuickStartEntries(entries, context, lookups = {}) {
51325
+ if (!entries.length)
51326
+ return entries;
51327
+ const worktreePath = context.worktreePath ?? null;
51328
+ if (!worktreePath)
51329
+ return entries;
51330
+ const lookupWorktrees = lookups.listAllWorktrees ?? listAllWorktrees;
51331
+ let resolvedWorktrees = null;
51332
+ try {
51333
+ const allWorktrees = await lookupWorktrees();
51334
+ resolvedWorktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
51335
+ } catch {
51336
+ resolvedWorktrees = null;
51337
+ }
51338
+ const searchOptions = {
51339
+ branch: context.branch,
51340
+ ...resolvedWorktrees && resolvedWorktrees.length > 0 ? { worktrees: resolvedWorktrees } : {}
51341
+ };
51342
+ const lookupCodex = lookups.findLatestCodexSession ?? findLatestCodexSession;
51343
+ const lookupClaude = lookups.findLatestClaudeSession ?? findLatestClaudeSession;
51344
+ const lookupGemini = lookups.findLatestGeminiSession ?? findLatestGeminiSession;
51345
+ const lookupOpenCode = lookups.findLatestOpenCodeSession ?? findLatestOpenCodeSession;
51346
+ const updated = await Promise.all(entries.map(async (entry) => {
51347
+ let latest = null;
51348
+ switch (entry.toolId) {
51349
+ case "codex-cli":
51350
+ latest = await lookupCodex(searchOptions);
51351
+ break;
51352
+ case "claude-code":
51353
+ latest = await lookupClaude(worktreePath, searchOptions);
51354
+ break;
51355
+ case "gemini-cli":
51356
+ latest = await lookupGemini(searchOptions);
51357
+ break;
51358
+ case "opencode":
51359
+ latest = await lookupOpenCode(searchOptions);
51360
+ break;
51361
+ default:
51362
+ return entry;
51363
+ }
51364
+ if (!latest?.id)
51365
+ return entry;
51366
+ const updatedTimestamp = Math.max(entry.timestamp ?? 0, latest.mtime);
51367
+ return {
51368
+ ...entry,
51369
+ sessionId: latest.id,
51370
+ timestamp: updatedTimestamp
51371
+ };
51372
+ }));
51373
+ return updated.sort((a2, b) => (b.timestamp ?? 0) - (a2.timestamp ?? 0));
51374
+ }
51375
+
51376
+ // src/config/tools.ts
51377
+ init_builtin_coding_agents();
51378
+ import { homedir as homedir8 } from "os";
51379
+ import path20 from "path";
51380
+ import { readFile as readFile4, writeFile as writeFile3, mkdir as mkdir3, rename as rename2 } from "fs/promises";
50108
51381
 
50109
51382
  // src/config/profiles.ts
50110
51383
  import {
50111
51384
  mkdir as mkdir2,
50112
51385
  open,
50113
- readFile as readFile2,
51386
+ readFile as readFile3,
50114
51387
  rename,
50115
- stat,
51388
+ stat as stat2,
50116
51389
  unlink,
50117
51390
  writeFile as writeFile2
50118
51391
  } from "fs/promises";
50119
- import path14 from "path";
51392
+ import path19 from "path";
50120
51393
 
50121
51394
  // node_modules/yaml/dist/index.js
50122
51395
  var composer = require_composer();
@@ -50165,7 +51438,7 @@ var $visit = visit.visit;
50165
51438
  var $visitAsync = visit.visitAsync;
50166
51439
 
50167
51440
  // src/config/profiles.ts
50168
- import { homedir as homedir3 } from "os";
51441
+ import { homedir as homedir7 } from "os";
50169
51442
 
50170
51443
  // src/types/profiles.ts
50171
51444
  var DEFAULT_PROFILES_CONFIG = Object.freeze({
@@ -50180,11 +51453,11 @@ function isValidProfileName(name) {
50180
51453
 
50181
51454
  // src/config/profiles.ts
50182
51455
  function getConfigDir() {
50183
- const worktreeHome = process.env.GWT_HOME && process.env.GWT_HOME.trim().length > 0 ? process.env.GWT_HOME : homedir3();
50184
- return path14.join(worktreeHome, ".gwt");
51456
+ const worktreeHome = process.env.GWT_HOME && process.env.GWT_HOME.trim().length > 0 ? process.env.GWT_HOME : homedir7();
51457
+ return path19.join(worktreeHome, ".gwt");
50185
51458
  }
50186
51459
  function getProfilesConfigPath() {
50187
- return path14.join(getConfigDir(), "profiles.yaml");
51460
+ return path19.join(getConfigDir(), "profiles.yaml");
50188
51461
  }
50189
51462
  var LOCK_RETRY_INTERVAL_MS = 50;
50190
51463
  var LOCK_TIMEOUT_MS = 3000;
@@ -50194,7 +51467,7 @@ function getProfilesLockPath() {
50194
51467
  }
50195
51468
  async function withProfilesLock(fn) {
50196
51469
  const lockPath = getProfilesLockPath();
50197
- await mkdir2(path14.dirname(lockPath), { recursive: true });
51470
+ await mkdir2(path19.dirname(lockPath), { recursive: true });
50198
51471
  const startedAt = Date.now();
50199
51472
  while (true) {
50200
51473
  try {
@@ -50213,7 +51486,7 @@ async function withProfilesLock(fn) {
50213
51486
  throw error;
50214
51487
  }
50215
51488
  try {
50216
- const lockStat = await stat(lockPath);
51489
+ const lockStat = await stat2(lockPath);
50217
51490
  const isStale = Date.now() - lockStat.mtimeMs > LOCK_STALE_MS;
50218
51491
  if (isStale) {
50219
51492
  await unlink(lockPath).catch(() => {});
@@ -50243,7 +51516,7 @@ var PROFILES_CONFIG_PATH = getProfilesConfigPath();
50243
51516
  async function loadProfiles() {
50244
51517
  try {
50245
51518
  const configPath = getProfilesConfigPath();
50246
- const content = await readFile2(configPath, "utf-8");
51519
+ const content = await readFile3(configPath, "utf-8");
50247
51520
  const config = $parse(content);
50248
51521
  if (!config.version || typeof config.version !== "string") {
50249
51522
  throw new Error("version field is required and must be a string");
@@ -50328,9 +51601,9 @@ async function deleteProfile(name) {
50328
51601
 
50329
51602
  // src/config/tools.ts
50330
51603
  var logger3 = createLogger({ category: "config" });
50331
- var WORKTREE_HOME = process.env.GWT_HOME && process.env.GWT_HOME.trim().length > 0 ? process.env.GWT_HOME : homedir4();
50332
- var CONFIG_DIR = path15.join(WORKTREE_HOME, ".gwt");
50333
- var TOOLS_CONFIG_PATH = path15.join(CONFIG_DIR, "tools.json");
51604
+ var WORKTREE_HOME = process.env.GWT_HOME && process.env.GWT_HOME.trim().length > 0 ? process.env.GWT_HOME : homedir8();
51605
+ var CONFIG_DIR = path20.join(WORKTREE_HOME, ".gwt");
51606
+ var TOOLS_CONFIG_PATH = path20.join(CONFIG_DIR, "tools.json");
50334
51607
  var TEMP_CONFIG_PATH = `${TOOLS_CONFIG_PATH}.tmp`;
50335
51608
  var DEFAULT_CONFIG2 = {
50336
51609
  version: "1.0.0",
@@ -50339,7 +51612,7 @@ var DEFAULT_CONFIG2 = {
50339
51612
  };
50340
51613
  async function loadCodingAgentsConfig() {
50341
51614
  try {
50342
- const content = await readFile3(TOOLS_CONFIG_PATH, "utf-8");
51615
+ const content = await readFile4(TOOLS_CONFIG_PATH, "utf-8");
50343
51616
  const config = JSON.parse(content);
50344
51617
  const legacyConfig = config;
50345
51618
  if (!config.customCodingAgents && legacyConfig.customTools) {
@@ -50423,7 +51696,7 @@ function validateCodingAgent(agent) {
50423
51696
  throw new Error(`Invalid type: "${a2.type}"
50424
51697
  ` + `Type must be one of: ${validTypes.join(", ")}`);
50425
51698
  }
50426
- if (a2.type === "path" && !path15.isAbsolute(a2.command)) {
51699
+ if (a2.type === "path" && !path20.isAbsolute(a2.command)) {
50427
51700
  throw new Error(`For type="path", command must be an absolute path: "${a2.command}"`);
50428
51701
  }
50429
51702
  if (!a2.modeArgs.normal && !a2.modeArgs.continue && !a2.modeArgs.resume) {
@@ -50450,14 +51723,45 @@ async function getAllCodingAgents() {
50450
51723
 
50451
51724
  // src/logging/reader.ts
50452
51725
  import fs4 from "fs/promises";
50453
- import path16 from "path";
51726
+ import path21 from "path";
50454
51727
  import os4 from "os";
51728
+ var LOG_FILENAME_PATTERN = /^\d{4}-\d{2}-\d{2}\.jsonl$/;
50455
51729
  function resolveLogDir(cwd = process.cwd()) {
50456
- const cwdBase = path16.basename(cwd) || "workspace";
50457
- return path16.join(os4.homedir(), ".gwt", "logs", cwdBase);
51730
+ const cwdBase = path21.basename(cwd) || "workspace";
51731
+ return path21.join(os4.homedir(), ".gwt", "logs", cwdBase);
50458
51732
  }
50459
- function buildLogFilePath(logDir, date) {
50460
- return path16.join(logDir, `${date}.jsonl`);
51733
+ function resolveLogTarget(branch, workingDirectory = process.cwd()) {
51734
+ if (!branch) {
51735
+ return {
51736
+ logDir: resolveLogDir(workingDirectory),
51737
+ sourcePath: workingDirectory,
51738
+ reason: "working-directory"
51739
+ };
51740
+ }
51741
+ const worktreePath = branch.worktree?.path;
51742
+ if (worktreePath) {
51743
+ const accessible = branch.worktree?.isAccessible !== false;
51744
+ if (accessible) {
51745
+ return {
51746
+ logDir: resolveLogDir(worktreePath),
51747
+ sourcePath: worktreePath,
51748
+ reason: "worktree"
51749
+ };
51750
+ }
51751
+ return {
51752
+ logDir: null,
51753
+ sourcePath: worktreePath,
51754
+ reason: "worktree-inaccessible"
51755
+ };
51756
+ }
51757
+ if (branch.isCurrent) {
51758
+ return {
51759
+ logDir: resolveLogDir(workingDirectory),
51760
+ sourcePath: workingDirectory,
51761
+ reason: "current-working-directory"
51762
+ };
51763
+ }
51764
+ return { logDir: null, sourcePath: null, reason: "no-worktree" };
50461
51765
  }
50462
51766
  function getTodayLogDate() {
50463
51767
  return formatDate(new Date);
@@ -50475,6 +51779,111 @@ async function readLogFileLines(filePath) {
50475
51779
  throw error;
50476
51780
  }
50477
51781
  }
51782
+ async function listLogFiles(logDir) {
51783
+ try {
51784
+ const entries = await fs4.readdir(logDir, { withFileTypes: true });
51785
+ const files = [];
51786
+ for (const entry of entries) {
51787
+ if (!entry.isFile())
51788
+ continue;
51789
+ if (!LOG_FILENAME_PATTERN.test(entry.name))
51790
+ continue;
51791
+ const date = entry.name.replace(/\.jsonl$/, "");
51792
+ const fullPath = path21.join(logDir, entry.name);
51793
+ try {
51794
+ const stat3 = await fs4.stat(fullPath);
51795
+ files.push({ date, path: fullPath, mtimeMs: stat3.mtimeMs });
51796
+ } catch {}
51797
+ }
51798
+ return files.sort((a2, b) => b.mtimeMs - a2.mtimeMs);
51799
+ } catch (error) {
51800
+ const err = error;
51801
+ if (err.code === "ENOENT") {
51802
+ return [];
51803
+ }
51804
+ throw error;
51805
+ }
51806
+ }
51807
+ var getLatestLogMtimeWithContent = async (logDir) => {
51808
+ const files = await listLogFiles(logDir);
51809
+ for (const file of files) {
51810
+ const lines = await readLogFileLines(file.path);
51811
+ if (lines.length > 0) {
51812
+ return file.mtimeMs;
51813
+ }
51814
+ }
51815
+ return null;
51816
+ };
51817
+ async function selectLogTargetByRecency(primary, fallback) {
51818
+ if (!primary.logDir || !primary.sourcePath) {
51819
+ return primary;
51820
+ }
51821
+ if (!fallback.logDir || !fallback.sourcePath) {
51822
+ return primary;
51823
+ }
51824
+ if (primary.logDir === fallback.logDir) {
51825
+ return primary;
51826
+ }
51827
+ if (primary.reason !== "worktree") {
51828
+ return primary;
51829
+ }
51830
+ const [primaryMtime, fallbackMtime] = await Promise.all([
51831
+ getLatestLogMtimeWithContent(primary.logDir),
51832
+ getLatestLogMtimeWithContent(fallback.logDir)
51833
+ ]);
51834
+ if (fallbackMtime !== null && (primaryMtime === null || fallbackMtime > primaryMtime)) {
51835
+ return {
51836
+ ...fallback,
51837
+ reason: "working-directory-fallback"
51838
+ };
51839
+ }
51840
+ return primary;
51841
+ }
51842
+ async function clearLogFiles(logDir) {
51843
+ const files = await listLogFiles(logDir);
51844
+ let cleared = 0;
51845
+ for (const file of files) {
51846
+ try {
51847
+ await fs4.truncate(file.path, 0);
51848
+ cleared += 1;
51849
+ } catch (error) {
51850
+ const err = error;
51851
+ if (err.code !== "ENOENT") {
51852
+ throw error;
51853
+ }
51854
+ }
51855
+ }
51856
+ return cleared;
51857
+ }
51858
+ async function readLogLinesForDate(logDir, preferredDate) {
51859
+ const files = await listLogFiles(logDir);
51860
+ if (files.length === 0) {
51861
+ return null;
51862
+ }
51863
+ const ordered = [];
51864
+ const preferred = files.find((file) => file.date === preferredDate);
51865
+ if (preferred) {
51866
+ ordered.push(preferred);
51867
+ }
51868
+ for (const file of files) {
51869
+ if (preferred && file.date === preferred.date) {
51870
+ continue;
51871
+ }
51872
+ ordered.push(file);
51873
+ }
51874
+ for (const file of ordered) {
51875
+ const lines = await readLogFileLines(file.path);
51876
+ if (lines.length > 0) {
51877
+ return { date: file.date, lines };
51878
+ }
51879
+ }
51880
+ const fallback = files[0];
51881
+ if (!fallback) {
51882
+ return { date: preferredDate, lines: [] };
51883
+ }
51884
+ const fallbackDate = preferred?.date ?? fallback.date;
51885
+ return { date: fallbackDate, lines: [] };
51886
+ }
50478
51887
 
50479
51888
  // src/logging/formatter.ts
50480
51889
  var LEVEL_LABELS = {
@@ -50485,15 +51894,29 @@ var LEVEL_LABELS = {
50485
51894
  50: "ERROR",
50486
51895
  60: "FATAL"
50487
51896
  };
51897
+ var LOCAL_TIME_FORMATTER = new Intl.DateTimeFormat(undefined, {
51898
+ hour: "2-digit",
51899
+ minute: "2-digit",
51900
+ second: "2-digit",
51901
+ hour12: false
51902
+ });
51903
+ var formatLocalTimeParts = (date) => {
51904
+ const parts = LOCAL_TIME_FORMATTER.formatToParts(date);
51905
+ const get = (type) => parts.find((part) => part.type === type)?.value;
51906
+ const hour = get("hour");
51907
+ const minute = get("minute");
51908
+ const second = get("second");
51909
+ if (!hour || !minute || !second) {
51910
+ return LOCAL_TIME_FORMATTER.format(date);
51911
+ }
51912
+ return `${hour}:${minute}:${second}`;
51913
+ };
50488
51914
  var formatTimeLabel = (value) => {
50489
51915
  if (typeof value === "string" || typeof value === "number") {
50490
51916
  const date = new Date(value);
50491
51917
  if (!Number.isNaN(date.getTime())) {
50492
- const hours = String(date.getHours()).padStart(2, "0");
50493
- const minutes = String(date.getMinutes()).padStart(2, "0");
50494
- const seconds = String(date.getSeconds()).padStart(2, "0");
50495
51918
  return {
50496
- label: `${hours}:${minutes}:${seconds}`,
51919
+ label: formatLocalTimeParts(date),
50497
51920
  timestamp: date.getTime()
50498
51921
  };
50499
51922
  }
@@ -50577,17 +52000,17 @@ async function copyToClipboard(text, options = {}) {
50577
52000
  }
50578
52001
 
50579
52002
  // src/utils.ts
50580
- import path17 from "path";
52003
+ import path22 from "path";
50581
52004
  import { fileURLToPath as fileURLToPath4 } from "url";
50582
- import { readFile as readFile4 } from "fs/promises";
52005
+ import { readFile as readFile5 } from "fs/promises";
50583
52006
  function getCurrentDirname() {
50584
- return path17.dirname(fileURLToPath4(import.meta.url));
52007
+ return path22.dirname(fileURLToPath4(import.meta.url));
50585
52008
  }
50586
52009
  async function getPackageVersion() {
50587
52010
  try {
50588
52011
  const currentDir = getCurrentDirname();
50589
- const packageJsonPath = path17.resolve(currentDir, "..", "package.json");
50590
- const packageJsonContent = await readFile4(packageJsonPath, "utf-8");
52012
+ const packageJsonPath = path22.resolve(currentDir, "..", "package.json");
52013
+ const packageJsonContent = await readFile5(packageJsonPath, "utf-8");
50591
52014
  const packageJson = JSON.parse(packageJsonContent);
50592
52015
  return packageJson.version || null;
50593
52016
  } catch {
@@ -50597,9 +52020,12 @@ async function getPackageVersion() {
50597
52020
 
50598
52021
  // src/cli/ui/App.solid.tsx
50599
52022
  init_constants();
52023
+ init_versionFetcher();
50600
52024
  var logger4 = createLogger({
50601
52025
  category: "app"
50602
52026
  });
52027
+ var UNSAFE_SELECTION_MESSAGE = "Unsafe branch selected. Select anyway?";
52028
+ var SAFETY_PENDING_MESSAGE = "Safety check in progress. Select anyway?";
50603
52029
  var DEFAULT_SCREEN = "branch-list";
50604
52030
  var buildStats = (branches) => calculateStatistics(branches);
50605
52031
  var applyCleanupStatus = (items, statusByBranch) => items.map((branch) => {
@@ -50630,6 +52056,23 @@ var applyCleanupStatus = (items, statusByBranch) => items.map((branch) => {
50630
52056
  worktree
50631
52057
  } : base2;
50632
52058
  });
52059
+ var buildCleanupSafetyPending = (items) => {
52060
+ const pending = new Set;
52061
+ for (const branch of items) {
52062
+ if (branch.type === "remote") {
52063
+ continue;
52064
+ }
52065
+ if (branch.worktree) {
52066
+ pending.add(branch.name);
52067
+ continue;
52068
+ }
52069
+ if (isProtectedBranchName(branch.name)) {
52070
+ continue;
52071
+ }
52072
+ pending.add(branch.name);
52073
+ }
52074
+ return pending;
52075
+ };
50633
52076
  var toLocalBranchName = (name) => {
50634
52077
  const segments = name.split("/");
50635
52078
  if (segments.length <= 1) {
@@ -50645,6 +52088,7 @@ var toSelectedBranchState = (branch) => {
50645
52088
  displayName: branch.name,
50646
52089
  branchType: branch.type,
50647
52090
  branchCategory: branch.branchType,
52091
+ worktreePath: branch.worktree?.path ?? null,
50648
52092
  ...isRemote ? {
50649
52093
  remoteBranch: branch.name
50650
52094
  } : {}
@@ -50652,6 +52096,7 @@ var toSelectedBranchState = (branch) => {
50652
52096
  };
50653
52097
  function AppSolid(props) {
50654
52098
  const renderer = useRenderer();
52099
+ const terminal = useTerminalSize();
50655
52100
  let hasExited = false;
50656
52101
  const exitApp = (result) => {
50657
52102
  if (hasExited)
@@ -50668,6 +52113,7 @@ function AppSolid(props) {
50668
52113
  const [stats, setStats] = createSignal(props.stats ?? buildStats(props.branches ?? []));
50669
52114
  const [loading, setLoading] = createSignal(!props.branches);
50670
52115
  const [error, setError] = createSignal(null);
52116
+ const [branchCursorPosition, setBranchCursorPosition] = createSignal(0);
50671
52117
  const [toolItems, setToolItems] = createSignal([]);
50672
52118
  const [toolError, setToolError] = createSignal(null);
50673
52119
  const [version, setVersion] = createSignal(props.version ?? null);
@@ -50676,11 +52122,16 @@ function AppSolid(props) {
50676
52122
  const [selectedTool, setSelectedTool] = createSignal(null);
50677
52123
  const [selectedMode, setSelectedMode] = createSignal("normal");
50678
52124
  const [selectedBranches, setSelectedBranches] = createSignal([]);
52125
+ const [unsafeSelectionConfirmVisible, setUnsafeSelectionConfirmVisible] = createSignal(false);
52126
+ const [unsafeConfirmInputLocked, setUnsafeConfirmInputLocked] = createSignal(false);
52127
+ const [unsafeSelectionTarget, setUnsafeSelectionTarget] = createSignal(null);
52128
+ const [unsafeSelectionMessage, setUnsafeSelectionMessage] = createSignal(UNSAFE_SELECTION_MESSAGE);
50679
52129
  const [branchFooterMessage, setBranchFooterMessage] = createSignal(null);
50680
52130
  const [branchInputLocked, setBranchInputLocked] = createSignal(false);
50681
52131
  const [cleanupIndicators, setCleanupIndicators] = createSignal({});
50682
52132
  const [cleanupStatusByBranch, setCleanupStatusByBranch] = createSignal(new Map);
50683
52133
  const [cleanupSafetyLoading, setCleanupSafetyLoading] = createSignal(false);
52134
+ const [cleanupSafetyPending, setCleanupSafetyPending] = createSignal(new Set);
50684
52135
  const [isNewBranch, setIsNewBranch] = createSignal(false);
50685
52136
  const [newBranchBaseRef, setNewBranchBaseRef] = createSignal(null);
50686
52137
  const [creationSource, setCreationSource] = createSignal(null);
@@ -50689,20 +52140,59 @@ function AppSolid(props) {
50689
52140
  });
50690
52141
  const [suppressCreateKey, setSuppressCreateKey] = createSignal(null);
50691
52142
  const [defaultBaseBranch, setDefaultBaseBranch] = createSignal("main");
52143
+ const suppressBranchInputOnce = () => {
52144
+ setUnsafeConfirmInputLocked(true);
52145
+ queueMicrotask(() => {
52146
+ setUnsafeConfirmInputLocked(false);
52147
+ });
52148
+ };
52149
+ const unsafeConfirmBoxWidth = createMemo(() => {
52150
+ const columns = terminal().columns || 80;
52151
+ return Math.max(1, Math.floor(columns * 0.6));
52152
+ });
52153
+ const unsafeConfirmContentWidth = createMemo(() => Math.max(0, unsafeConfirmBoxWidth() - 4));
50692
52154
  const [sessionHistory, setSessionHistory] = createSignal([]);
52155
+ const [quickStartHistory, setQuickStartHistory] = createSignal([]);
50693
52156
  const historyForBranch = createMemo(() => {
50694
52157
  const history = sessionHistory();
50695
52158
  const branch = selectedBranch();
50696
52159
  if (!branch)
50697
52160
  return [];
50698
- return history.filter((entry) => entry.branch === branch.name).sort((a2, b) => (b.timestamp ?? 0) - (a2.timestamp ?? 0));
52161
+ return findLatestBranchSessionsByTool(history, branch.name, branch.worktreePath ?? null);
52162
+ });
52163
+ createEffect(() => {
52164
+ setQuickStartHistory(historyForBranch());
52165
+ });
52166
+ createEffect(() => {
52167
+ const branch = selectedBranch();
52168
+ const baseHistory = historyForBranch();
52169
+ if (!wizardVisible() || !branch || baseHistory.length === 0) {
52170
+ return;
52171
+ }
52172
+ const worktreePath = branch.worktreePath ?? null;
52173
+ if (!worktreePath) {
52174
+ return;
52175
+ }
52176
+ const branchName = branch.name;
52177
+ (async () => {
52178
+ const refreshed = await refreshQuickStartEntries(baseHistory, {
52179
+ branch: branchName,
52180
+ worktreePath
52181
+ });
52182
+ if (selectedBranch()?.name !== branchName) {
52183
+ return;
52184
+ }
52185
+ setQuickStartHistory(refreshed);
52186
+ })();
50699
52187
  });
50700
52188
  const [logEntries, setLogEntries] = createSignal([]);
50701
52189
  const [logLoading, setLogLoading] = createSignal(false);
50702
52190
  const [logError2, setLogError] = createSignal(null);
50703
52191
  const [logSelectedEntry, setLogSelectedEntry] = createSignal(null);
50704
- const [logSelectedDate, _setLogSelectedDate] = createSignal(getTodayLogDate());
52192
+ const [logSelectedDate, setLogSelectedDate] = createSignal(getTodayLogDate());
50705
52193
  const [logNotification, setLogNotification] = createSignal(null);
52194
+ const [logTailEnabled, setLogTailEnabled] = createSignal(false);
52195
+ const [logTargetBranch, setLogTargetBranch] = createSignal(null);
50706
52196
  const [profileItems, setProfileItems] = createSignal([]);
50707
52197
  const [activeProfile, setActiveProfileName] = createSignal(null);
50708
52198
  const [profileError, setProfileError] = createSignal(null);
@@ -50717,7 +52207,31 @@ function AppSolid(props) {
50717
52207
  const [profileInputSuppressKey, setProfileInputSuppressKey] = createSignal(null);
50718
52208
  const [profileEnvKey, setProfileEnvKey] = createSignal(null);
50719
52209
  const [profileConfirmMode, setProfileConfirmMode] = createSignal("delete-profile");
50720
- const logDir = createMemo(() => resolveLogDir(workingDirectory()));
52210
+ const [logEffectiveTarget, setLogEffectiveTarget] = createSignal(null);
52211
+ const logPrimaryTarget = createMemo(() => resolveLogTarget(logTargetBranch(), workingDirectory()));
52212
+ const logFallbackTarget = createMemo(() => resolveLogTarget(null, workingDirectory()));
52213
+ const logActiveTarget = createMemo(() => logEffectiveTarget() ?? logPrimaryTarget());
52214
+ const logBranchLabel = createMemo(() => logTargetBranch()?.label ?? null);
52215
+ const logSourceLabel = createMemo(() => {
52216
+ const target = logActiveTarget();
52217
+ if (!target.sourcePath) {
52218
+ return "(none)";
52219
+ }
52220
+ if (target.reason === "current-working-directory" || target.reason === "working-directory") {
52221
+ return `${target.sourcePath} (cwd)`;
52222
+ }
52223
+ if (target.reason === "working-directory-fallback") {
52224
+ return `${target.sourcePath} (cwd fallback)`;
52225
+ }
52226
+ if (target.reason === "worktree-inaccessible") {
52227
+ return `${target.sourcePath} (inaccessible)`;
52228
+ }
52229
+ return target.sourcePath;
52230
+ });
52231
+ createEffect(() => {
52232
+ logPrimaryTarget();
52233
+ setLogEffectiveTarget(null);
52234
+ });
50721
52235
  const selectedProfileConfig = createMemo(() => {
50722
52236
  const name = selectedProfileName();
50723
52237
  const config = profilesConfig();
@@ -50746,15 +52260,42 @@ function AppSolid(props) {
50746
52260
  let cleanupSafetyRequestId = 0;
50747
52261
  const refreshCleanupSafety = async () => {
50748
52262
  const requestId = ++cleanupSafetyRequestId;
50749
- setCleanupSafetyLoading(true);
52263
+ const pendingBranches = buildCleanupSafetyPending(branchItems());
52264
+ setCleanupSafetyPending(pendingBranches);
52265
+ setCleanupSafetyLoading(pendingBranches.size > 0);
52266
+ const statusByBranch = new Map;
52267
+ const applyProgress = (status) => {
52268
+ if (requestId !== cleanupSafetyRequestId) {
52269
+ return;
52270
+ }
52271
+ statusByBranch.set(status.branch, status);
52272
+ batch(() => {
52273
+ setCleanupStatusByBranch(new Map(statusByBranch));
52274
+ setBranchItems((items) => applyCleanupStatus(items, statusByBranch));
52275
+ setCleanupSafetyPending((prev) => {
52276
+ if (!prev.has(status.branch)) {
52277
+ return prev;
52278
+ }
52279
+ const next = new Set(prev);
52280
+ next.delete(status.branch);
52281
+ return next;
52282
+ });
52283
+ });
52284
+ };
50750
52285
  try {
50751
- const cleanupStatuses = await getCleanupStatus();
52286
+ const cleanupStatuses = await getCleanupStatus({
52287
+ onProgress: applyProgress
52288
+ });
50752
52289
  if (requestId !== cleanupSafetyRequestId) {
50753
52290
  return;
50754
52291
  }
50755
- const statusByBranch = new Map(cleanupStatuses.map((status) => [status.branch, status]));
50756
- setCleanupStatusByBranch(statusByBranch);
50757
- setBranchItems((items) => applyCleanupStatus(items, statusByBranch));
52292
+ if (cleanupStatuses.length > statusByBranch.size) {
52293
+ cleanupStatuses.forEach((status) => {
52294
+ if (!statusByBranch.has(status.branch)) {
52295
+ applyProgress(status);
52296
+ }
52297
+ });
52298
+ }
50758
52299
  } catch (err) {
50759
52300
  if (requestId !== cleanupSafetyRequestId) {
50760
52301
  return;
@@ -50763,15 +52304,19 @@ function AppSolid(props) {
50763
52304
  err
50764
52305
  }, "Failed to refresh cleanup safety indicators");
50765
52306
  const empty = new Map;
50766
- setCleanupStatusByBranch(empty);
50767
- setBranchItems((items) => applyCleanupStatus(items, empty));
52307
+ batch(() => {
52308
+ setCleanupStatusByBranch(empty);
52309
+ setBranchItems((items) => applyCleanupStatus(items, empty));
52310
+ });
50768
52311
  } finally {
50769
52312
  if (requestId === cleanupSafetyRequestId) {
50770
52313
  setCleanupSafetyLoading(false);
52314
+ setCleanupSafetyPending(new Set);
50771
52315
  }
50772
52316
  }
50773
52317
  };
50774
52318
  let logNotificationTimer = null;
52319
+ let logTailTimer = null;
50775
52320
  let branchFooterTimer = null;
50776
52321
  const BRANCH_LOAD_TIMEOUT_MS = 3000;
50777
52322
  const BRANCH_FULL_LOAD_TIMEOUT_MS = 8000;
@@ -50838,9 +52383,23 @@ function AppSolid(props) {
50838
52383
  setLogLoading(true);
50839
52384
  setLogError(null);
50840
52385
  try {
50841
- const filePath = buildLogFilePath(logDir(), targetDate);
50842
- const lines = await readLogFileLines(filePath);
50843
- const parsed = parseLogLines(lines, {
52386
+ const primaryTarget = logPrimaryTarget();
52387
+ const fallbackTarget = logFallbackTarget();
52388
+ const target = await selectLogTargetByRecency(primaryTarget, fallbackTarget);
52389
+ setLogEffectiveTarget(target);
52390
+ if (!target.logDir) {
52391
+ setLogEntries([]);
52392
+ setLogSelectedDate(targetDate);
52393
+ return;
52394
+ }
52395
+ const result = await readLogLinesForDate(target.logDir, targetDate);
52396
+ if (!result) {
52397
+ setLogEntries([]);
52398
+ setLogSelectedDate(targetDate);
52399
+ return;
52400
+ }
52401
+ setLogSelectedDate(result.date);
52402
+ const parsed = parseLogLines(result.lines, {
50844
52403
  limit: 100
50845
52404
  });
50846
52405
  setLogEntries(parsed);
@@ -50851,10 +52410,39 @@ function AppSolid(props) {
50851
52410
  setLogLoading(false);
50852
52411
  }
50853
52412
  };
52413
+ const clearLogTailTimer = () => {
52414
+ if (logTailTimer) {
52415
+ clearInterval(logTailTimer);
52416
+ logTailTimer = null;
52417
+ }
52418
+ };
52419
+ const toggleLogTail = () => {
52420
+ setLogTailEnabled((prev) => !prev);
52421
+ };
52422
+ const resetLogFiles = async () => {
52423
+ const target = logActiveTarget();
52424
+ if (!target.logDir) {
52425
+ showLogNotification("No logs available.", "error");
52426
+ return;
52427
+ }
52428
+ try {
52429
+ const cleared = await clearLogFiles(target.logDir);
52430
+ if (cleared === 0) {
52431
+ showLogNotification("No logs to reset.", "error");
52432
+ } else {
52433
+ showLogNotification("Logs cleared.", "success");
52434
+ }
52435
+ await loadLogEntries(logSelectedDate());
52436
+ } catch (err) {
52437
+ logger4.warn({
52438
+ err
52439
+ }, "Failed to clear log files");
52440
+ showLogNotification("Failed to reset logs.", "error");
52441
+ }
52442
+ };
50854
52443
  const refreshBranches = async () => {
50855
52444
  setLoading(true);
50856
52445
  setError(null);
50857
- refreshCleanupSafety();
50858
52446
  try {
50859
52447
  const repoRoot = await getRepositoryRoot();
50860
52448
  const worktreesPromise = listAdditionalWorktrees();
@@ -50873,7 +52461,11 @@ function AppSolid(props) {
50873
52461
  const initialItems = applyCleanupStatus(initial.items, cleanupStatusByBranch());
50874
52462
  setBranchItems(initialItems);
50875
52463
  setStats(buildStats(initialItems));
52464
+ refreshCleanupSafety();
50876
52465
  (async () => {
52466
+ await withTimeout(fetchAllRemotes({
52467
+ cwd: repoRoot
52468
+ }), BRANCH_FULL_LOAD_TIMEOUT_MS).catch(() => {});
50877
52469
  const [branches, latestWorktrees] = await Promise.all([withTimeout(getAllBranches(repoRoot), BRANCH_FULL_LOAD_TIMEOUT_MS).catch(() => localBranches), withTimeout(listAdditionalWorktrees(), BRANCH_FULL_LOAD_TIMEOUT_MS).catch(() => worktrees)]);
50878
52470
  const full = buildBranchList(branches, latestWorktrees, lastToolUsageMap);
50879
52471
  const fullItems = applyCleanupStatus(full.items, cleanupStatusByBranch());
@@ -50954,15 +52546,32 @@ function AppSolid(props) {
50954
52546
  setToolError(err instanceof Error ? err : new Error(String(err)));
50955
52547
  });
50956
52548
  });
52549
+ onMount(() => {
52550
+ const bunxAgentIds = getBunxAgentIds();
52551
+ prefetchAgentVersions(bunxAgentIds).catch(() => {});
52552
+ prefetchInstalledVersions(bunxAgentIds).catch(() => {});
52553
+ });
50957
52554
  createEffect(() => {
50958
52555
  if (currentScreen() === "log-list") {
52556
+ logPrimaryTarget();
50959
52557
  loadLogEntries(logSelectedDate());
50960
52558
  }
50961
52559
  });
52560
+ createEffect(() => {
52561
+ if (currentScreen() !== "log-list" || !logTailEnabled()) {
52562
+ clearLogTailTimer();
52563
+ return;
52564
+ }
52565
+ clearLogTailTimer();
52566
+ logTailTimer = setInterval(() => {
52567
+ loadLogEntries(logSelectedDate());
52568
+ }, 1500);
52569
+ });
50962
52570
  onCleanup(() => {
50963
52571
  if (logNotificationTimer) {
50964
52572
  clearTimeout(logNotificationTimer);
50965
52573
  }
52574
+ clearLogTailTimer();
50966
52575
  if (branchFooterTimer) {
50967
52576
  clearTimeout(branchFooterTimer);
50968
52577
  }
@@ -51058,6 +52667,10 @@ function AppSolid(props) {
51058
52667
  });
51059
52668
  };
51060
52669
  const handleWizardResume = (entry) => {
52670
+ if (!entry.sessionId) {
52671
+ handleWizardStartNew(entry);
52672
+ return;
52673
+ }
51061
52674
  setWizardVisible(false);
51062
52675
  const branch = selectedBranch();
51063
52676
  if (!branch) {
@@ -51166,24 +52779,10 @@ function AppSolid(props) {
51166
52779
  skipCounts.remote += 1;
51167
52780
  continue;
51168
52781
  }
51169
- if (isProtectedBranchName(branch.name)) {
51170
- skipCounts.protected += 1;
51171
- continue;
51172
- }
51173
52782
  if (branch.isCurrent) {
51174
52783
  skipCounts.current += 1;
51175
52784
  continue;
51176
52785
  }
51177
- const hasUncommitted = branch.worktree?.hasUncommittedChanges === true;
51178
- const hasUnpushed = branch.hasUnpushedCommits === true;
51179
- if (hasUncommitted || hasUnpushed) {
51180
- skipCounts.unsafe += 1;
51181
- continue;
51182
- }
51183
- if (branch.safeToCleanup !== true) {
51184
- skipCounts.unsafe += 1;
51185
- continue;
51186
- }
51187
52786
  const worktreePath = branch.worktree?.path ?? null;
51188
52787
  const cleanupType = worktreePath ? "worktree-and-branch" : "branch-only";
51189
52788
  const baseTask = {
@@ -51274,7 +52873,7 @@ function AppSolid(props) {
51274
52873
  return;
51275
52874
  }
51276
52875
  const selectionSet = new Set(selection);
51277
- const targets = branchItems().filter((branch) => selectionSet.has(branch.name) && branch.worktreeStatus === "inaccessible").map((branch) => branch.name);
52876
+ const targets = branchItems().filter((branch) => selectionSet.has(branch.name) && branch.type !== "remote" && branch.worktreeStatus !== undefined).map((branch) => branch.name);
51278
52877
  if (targets.length === 0) {
51279
52878
  showBranchFooterMessage("No worktrees to repair.", "yellow");
51280
52879
  return;
@@ -51485,15 +53084,49 @@ function AppSolid(props) {
51485
53084
  }
51486
53085
  };
51487
53086
  const toggleSelectedBranch = (branchName) => {
51488
- setSelectedBranches((prev) => {
51489
- const next = new Set(prev);
51490
- if (next.has(branchName)) {
51491
- next.delete(branchName);
51492
- } else {
51493
- next.add(branchName);
51494
- }
51495
- return Array.from(next);
51496
- });
53087
+ if (unsafeSelectionConfirmVisible()) {
53088
+ return;
53089
+ }
53090
+ const currentSelection = new Set(selectedBranches());
53091
+ if (currentSelection.has(branchName)) {
53092
+ currentSelection.delete(branchName);
53093
+ setSelectedBranches(Array.from(currentSelection));
53094
+ return;
53095
+ }
53096
+ const branch = branchItems().find((item) => item.name === branchName);
53097
+ const pending = cleanupSafetyPending();
53098
+ const hasSafetyPending = pending.has(branchName);
53099
+ const hasUncommitted = branch?.worktree?.hasUncommittedChanges === true;
53100
+ const hasUnpushed = branch?.hasUnpushedCommits === true;
53101
+ const isUnmerged = branch?.isUnmerged === true;
53102
+ const safeToCleanup = branch?.safeToCleanup === true;
53103
+ const isRemoteBranch = branch?.type === "remote";
53104
+ const isUnsafe = Boolean(branch) && !isRemoteBranch && !hasSafetyPending && (hasUncommitted || hasUnpushed || isUnmerged || !safeToCleanup);
53105
+ if (branch && hasSafetyPending) {
53106
+ setUnsafeSelectionTarget(branch.name);
53107
+ setUnsafeSelectionMessage(SAFETY_PENDING_MESSAGE);
53108
+ setUnsafeSelectionConfirmVisible(true);
53109
+ return;
53110
+ }
53111
+ if (branch && isUnsafe) {
53112
+ setUnsafeSelectionTarget(branch.name);
53113
+ setUnsafeSelectionMessage(UNSAFE_SELECTION_MESSAGE);
53114
+ setUnsafeSelectionConfirmVisible(true);
53115
+ return;
53116
+ }
53117
+ currentSelection.add(branchName);
53118
+ setSelectedBranches(Array.from(currentSelection));
53119
+ };
53120
+ const confirmUnsafeSelection = (confirmed) => {
53121
+ suppressBranchInputOnce();
53122
+ const target = unsafeSelectionTarget();
53123
+ setUnsafeSelectionConfirmVisible(false);
53124
+ setUnsafeSelectionTarget(null);
53125
+ setUnsafeSelectionMessage(UNSAFE_SELECTION_MESSAGE);
53126
+ if (!confirmed || !target) {
53127
+ return;
53128
+ }
53129
+ setSelectedBranches((prev) => prev.includes(target) ? prev : [...prev, target]);
51497
53130
  };
51498
53131
  const handleToolSelect = (item) => {
51499
53132
  setSelectedTool(item.value);
@@ -51544,8 +53177,9 @@ function AppSolid(props) {
51544
53177
  const cleanupUI = {
51545
53178
  indicators: cleanupIndicators(),
51546
53179
  footerMessage: branchFooterMessage(),
51547
- inputLocked: branchInputLocked(),
51548
- safetyLoading: cleanupSafetyLoading()
53180
+ inputLocked: branchInputLocked() || unsafeConfirmInputLocked(),
53181
+ safetyLoading: cleanupSafetyLoading(),
53182
+ safetyPendingBranches: cleanupSafetyPending()
51549
53183
  };
51550
53184
  return createComponent2(BranchListScreen, {
51551
53185
  get branches() {
@@ -51580,7 +53214,13 @@ function AppSolid(props) {
51580
53214
  get activeProfile() {
51581
53215
  return activeProfile();
51582
53216
  },
51583
- onOpenLogs: () => navigateTo("log-list"),
53217
+ onOpenLogs: (branch) => {
53218
+ setLogTargetBranch(branch);
53219
+ setLogSelectedEntry(null);
53220
+ setLogSelectedDate(getTodayLogDate());
53221
+ setLogTailEnabled(false);
53222
+ navigateTo("log-list");
53223
+ },
51584
53224
  onOpenProfiles: () => navigateTo("profile"),
51585
53225
  get selectedBranches() {
51586
53226
  return selectedBranches();
@@ -51593,7 +53233,14 @@ function AppSolid(props) {
51593
53233
  },
51594
53234
  get wizardVisible() {
51595
53235
  return wizardVisible();
51596
- }
53236
+ },
53237
+ get confirmVisible() {
53238
+ return unsafeSelectionConfirmVisible();
53239
+ },
53240
+ get cursorPosition() {
53241
+ return branchCursorPosition();
53242
+ },
53243
+ onCursorPositionChange: setBranchCursorPosition
51597
53244
  });
51598
53245
  }
51599
53246
  if (screen === "tool-select") {
@@ -51679,6 +53326,9 @@ function AppSolid(props) {
51679
53326
  showLogNotification("Failed to copy to clipboard.", "error");
51680
53327
  }
51681
53328
  },
53329
+ onReload: () => void loadLogEntries(logSelectedDate()),
53330
+ onToggleTail: toggleLogTail,
53331
+ onReset: () => void resetLogFiles(),
51682
53332
  get notification() {
51683
53333
  return logNotification();
51684
53334
  },
@@ -51688,6 +53338,15 @@ function AppSolid(props) {
51688
53338
  get selectedDate() {
51689
53339
  return logSelectedDate();
51690
53340
  },
53341
+ get branchLabel() {
53342
+ return logBranchLabel();
53343
+ },
53344
+ get sourceLabel() {
53345
+ return logSourceLabel();
53346
+ },
53347
+ get tailing() {
53348
+ return logTailEnabled();
53349
+ },
51691
53350
  get helpVisible() {
51692
53351
  return helpVisible();
51693
53352
  }
@@ -51932,7 +53591,35 @@ function AppSolid(props) {
51932
53591
  }
51933
53592
  });
51934
53593
  };
51935
- return [memo2(renderCurrentScreen), createComponent2(HelpOverlay, {
53594
+ return [memo2(renderCurrentScreen), memo2(() => memo2(() => !!unsafeSelectionConfirmVisible())() && (() => {
53595
+ var _el$ = createElement("box");
53596
+ setProp(_el$, "position", "absolute");
53597
+ setProp(_el$, "top", "30%");
53598
+ setProp(_el$, "left", "20%");
53599
+ setProp(_el$, "zIndex", 110);
53600
+ setProp(_el$, "border", true);
53601
+ setProp(_el$, "borderStyle", "single");
53602
+ setProp(_el$, "borderColor", "yellow");
53603
+ setProp(_el$, "backgroundColor", "black");
53604
+ setProp(_el$, "padding", 1);
53605
+ insert(_el$, createComponent2(ConfirmScreen, {
53606
+ get message() {
53607
+ return unsafeSelectionMessage();
53608
+ },
53609
+ onConfirm: confirmUnsafeSelection,
53610
+ yesLabel: "OK",
53611
+ noLabel: "Cancel",
53612
+ defaultNo: true,
53613
+ get helpVisible() {
53614
+ return helpVisible();
53615
+ },
53616
+ get width() {
53617
+ return unsafeConfirmContentWidth();
53618
+ }
53619
+ }));
53620
+ effect((_$p) => setProp(_el$, "width", unsafeConfirmBoxWidth(), _$p));
53621
+ return _el$;
53622
+ })()), createComponent2(HelpOverlay, {
51936
53623
  get visible() {
51937
53624
  return helpVisible();
51938
53625
  },
@@ -51947,7 +53634,7 @@ function AppSolid(props) {
51947
53634
  return selectedBranch()?.name ?? "";
51948
53635
  },
51949
53636
  get history() {
51950
- return historyForBranch();
53637
+ return quickStartHistory();
51951
53638
  },
51952
53639
  onClose: handleWizardClose,
51953
53640
  onComplete: handleWizardComplete,