@akiojin/gwt 4.11.6 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/gwt.js +1 -1
- package/dist/claude.d.ts +1 -0
- package/dist/claude.d.ts.map +1 -1
- package/dist/claude.js +50 -24
- package/dist/claude.js.map +1 -1
- package/dist/cli/ui/App.solid.d.ts.map +1 -1
- package/dist/cli/ui/App.solid.js +247 -49
- package/dist/cli/ui/App.solid.js.map +1 -1
- package/dist/cli/ui/components/solid/QuickStartStep.d.ts.map +1 -1
- package/dist/cli/ui/components/solid/QuickStartStep.js +35 -22
- package/dist/cli/ui/components/solid/QuickStartStep.js.map +1 -1
- package/dist/cli/ui/components/solid/SelectInput.d.ts.map +1 -1
- package/dist/cli/ui/components/solid/SelectInput.js +2 -1
- package/dist/cli/ui/components/solid/SelectInput.js.map +1 -1
- package/dist/cli/ui/components/solid/WizardController.d.ts.map +1 -1
- package/dist/cli/ui/components/solid/WizardController.js +19 -11
- package/dist/cli/ui/components/solid/WizardController.js.map +1 -1
- package/dist/cli/ui/components/solid/WizardSteps.d.ts.map +1 -1
- package/dist/cli/ui/components/solid/WizardSteps.js +26 -69
- package/dist/cli/ui/components/solid/WizardSteps.js.map +1 -1
- package/dist/cli/ui/core/theme.d.ts +9 -0
- package/dist/cli/ui/core/theme.d.ts.map +1 -1
- package/dist/cli/ui/core/theme.js +21 -0
- package/dist/cli/ui/core/theme.js.map +1 -1
- package/dist/cli/ui/screens/solid/BranchListScreen.d.ts +9 -2
- package/dist/cli/ui/screens/solid/BranchListScreen.d.ts.map +1 -1
- package/dist/cli/ui/screens/solid/BranchListScreen.js +101 -28
- package/dist/cli/ui/screens/solid/BranchListScreen.js.map +1 -1
- package/dist/cli/ui/screens/solid/ConfirmScreen.d.ts +2 -1
- package/dist/cli/ui/screens/solid/ConfirmScreen.d.ts.map +1 -1
- package/dist/cli/ui/screens/solid/ConfirmScreen.js +11 -3
- package/dist/cli/ui/screens/solid/ConfirmScreen.js.map +1 -1
- package/dist/cli/ui/screens/solid/EnvironmentScreen.d.ts.map +1 -1
- package/dist/cli/ui/screens/solid/EnvironmentScreen.js +9 -10
- package/dist/cli/ui/screens/solid/EnvironmentScreen.js.map +1 -1
- package/dist/cli/ui/screens/solid/LogScreen.d.ts +7 -1
- package/dist/cli/ui/screens/solid/LogScreen.d.ts.map +1 -1
- package/dist/cli/ui/screens/solid/LogScreen.js +254 -16
- package/dist/cli/ui/screens/solid/LogScreen.js.map +1 -1
- package/dist/cli/ui/screens/solid/ProfileEnvScreen.d.ts.map +1 -1
- package/dist/cli/ui/screens/solid/ProfileEnvScreen.js +8 -5
- package/dist/cli/ui/screens/solid/ProfileEnvScreen.js.map +1 -1
- package/dist/cli/ui/screens/solid/SelectorScreen.d.ts.map +1 -1
- package/dist/cli/ui/screens/solid/SelectorScreen.js +12 -4
- package/dist/cli/ui/screens/solid/SelectorScreen.js.map +1 -1
- package/dist/cli/ui/types.d.ts +1 -0
- package/dist/cli/ui/types.d.ts.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.d.ts +1 -0
- package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.js +29 -7
- package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
- package/dist/cli/ui/utils/continueSession.d.ts +14 -0
- package/dist/cli/ui/utils/continueSession.d.ts.map +1 -1
- package/dist/cli/ui/utils/continueSession.js +61 -3
- package/dist/cli/ui/utils/continueSession.js.map +1 -1
- package/dist/cli/ui/utils/versionCache.d.ts +37 -0
- package/dist/cli/ui/utils/versionCache.d.ts.map +1 -0
- package/dist/cli/ui/utils/versionCache.js +70 -0
- package/dist/cli/ui/utils/versionCache.js.map +1 -0
- package/dist/cli/ui/utils/versionFetcher.d.ts +41 -0
- package/dist/cli/ui/utils/versionFetcher.d.ts.map +1 -0
- package/dist/cli/ui/utils/versionFetcher.js +89 -0
- package/dist/cli/ui/utils/versionFetcher.js.map +1 -0
- package/dist/codex.d.ts +1 -0
- package/dist/codex.d.ts.map +1 -1
- package/dist/codex.js +48 -19
- package/dist/codex.js.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +10 -1
- package/dist/config/index.js.map +1 -1
- package/dist/gemini.d.ts +1 -0
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +36 -3
- package/dist/gemini.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -2
- package/dist/index.js.map +1 -1
- package/dist/launcher.d.ts.map +1 -1
- package/dist/launcher.js +43 -8
- package/dist/launcher.js.map +1 -1
- package/dist/logging/agentOutput.d.ts +21 -0
- package/dist/logging/agentOutput.d.ts.map +1 -0
- package/dist/logging/agentOutput.js +164 -0
- package/dist/logging/agentOutput.js.map +1 -0
- package/dist/logging/formatter.d.ts.map +1 -1
- package/dist/logging/formatter.js +18 -4
- package/dist/logging/formatter.js.map +1 -1
- package/dist/logging/logger.d.ts.map +1 -1
- package/dist/logging/logger.js +2 -0
- package/dist/logging/logger.js.map +1 -1
- package/dist/logging/reader.d.ts +21 -0
- package/dist/logging/reader.d.ts.map +1 -1
- package/dist/logging/reader.js +79 -0
- package/dist/logging/reader.js.map +1 -1
- package/dist/opentui/index.solid.js +2306 -653
- package/dist/services/dependency-installer.js +2 -2
- package/dist/services/dependency-installer.js.map +1 -1
- package/dist/utils/session/common.d.ts +8 -0
- package/dist/utils/session/common.d.ts.map +1 -1
- package/dist/utils/session/common.js +22 -0
- package/dist/utils/session/common.js.map +1 -1
- package/dist/utils/session/parsers/claude.d.ts +10 -4
- package/dist/utils/session/parsers/claude.d.ts.map +1 -1
- package/dist/utils/session/parsers/claude.js +64 -18
- package/dist/utils/session/parsers/claude.js.map +1 -1
- package/dist/utils/session/parsers/codex.d.ts.map +1 -1
- package/dist/utils/session/parsers/codex.js +48 -28
- package/dist/utils/session/parsers/codex.js.map +1 -1
- package/dist/utils/session/parsers/gemini.d.ts.map +1 -1
- package/dist/utils/session/parsers/gemini.js +43 -6
- package/dist/utils/session/parsers/gemini.js.map +1 -1
- package/dist/utils/session/parsers/opencode.d.ts.map +1 -1
- package/dist/utils/session/parsers/opencode.js +43 -6
- package/dist/utils/session/parsers/opencode.js.map +1 -1
- package/dist/utils/session/types.d.ts +7 -0
- package/dist/utils/session/types.d.ts.map +1 -1
- package/dist/web/client/src/components/ui/alert.d.ts +1 -1
- package/dist/worktree.d.ts +4 -1
- package/dist/worktree.d.ts.map +1 -1
- package/dist/worktree.js +21 -15
- package/dist/worktree.js.map +1 -1
- package/package.json +2 -1
- package/src/claude.ts +64 -28
- package/src/cli/ui/App.solid.tsx +324 -51
- package/src/cli/ui/__tests__/solid/AppSolid.cleanup.test.tsx +830 -1
- package/src/cli/ui/__tests__/solid/BranchListScreen.test.tsx +105 -5
- package/src/cli/ui/__tests__/solid/ConfirmScreen.test.tsx +77 -0
- package/src/cli/ui/__tests__/solid/LogScreen.test.tsx +351 -0
- package/src/cli/ui/__tests__/solid/components/QuickStartStep.test.tsx +73 -2
- package/src/cli/ui/__tests__/solid/components/WizardSteps.test.tsx +4 -1
- package/src/cli/ui/__tests__/utils/branchFormatter.test.ts +72 -45
- package/src/cli/ui/components/solid/QuickStartStep.tsx +35 -23
- package/src/cli/ui/components/solid/SearchInput.tsx +1 -1
- package/src/cli/ui/components/solid/SelectInput.tsx +4 -0
- package/src/cli/ui/components/solid/WizardController.tsx +20 -11
- package/src/cli/ui/components/solid/WizardSteps.tsx +29 -86
- package/src/cli/ui/core/theme.ts +32 -0
- package/src/cli/ui/hooks/solid/useAsyncOperation.ts +8 -6
- package/src/cli/ui/hooks/solid/useGitOperations.ts +6 -5
- package/src/cli/ui/screens/solid/BranchListScreen.tsx +135 -32
- package/src/cli/ui/screens/solid/ConfirmScreen.tsx +20 -8
- package/src/cli/ui/screens/solid/EnvironmentScreen.tsx +22 -20
- package/src/cli/ui/screens/solid/LogScreen.tsx +364 -35
- package/src/cli/ui/screens/solid/ProfileEnvScreen.tsx +19 -15
- package/src/cli/ui/screens/solid/SelectorScreen.tsx +25 -14
- package/src/cli/ui/screens/solid/SettingsScreen.tsx +5 -3
- package/src/cli/ui/types.ts +1 -0
- package/src/cli/ui/utils/__tests__/branchFormatter.test.ts +53 -6
- package/src/cli/ui/utils/branchFormatter.ts +35 -7
- package/src/cli/ui/utils/continueSession.ts +90 -3
- package/src/cli/ui/utils/versionCache.ts +93 -0
- package/src/cli/ui/utils/versionFetcher.ts +120 -0
- package/src/codex.ts +62 -20
- package/src/config/__tests__/saveSession.test.ts +2 -2
- package/src/config/index.ts +11 -1
- package/src/gemini.ts +50 -4
- package/src/index.test.ts +16 -10
- package/src/index.ts +38 -1
- package/src/launcher.ts +49 -8
- package/src/logging/agentOutput.ts +216 -0
- package/src/logging/formatter.ts +23 -4
- package/src/logging/logger.ts +2 -0
- package/src/logging/reader.ts +117 -0
- package/src/services/__tests__/BatchMergeService.test.ts +34 -14
- package/src/services/dependency-installer.ts +2 -2
- package/src/utils/session/common.ts +28 -0
- package/src/utils/session/parsers/claude.ts +79 -29
- package/src/utils/session/parsers/codex.ts +50 -26
- package/src/utils/session/parsers/gemini.ts +46 -5
- package/src/utils/session/parsers/opencode.ts +46 -5
- package/src/utils/session/types.ts +4 -0
- 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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) => {
|
|
@@ -42788,6 +43122,9 @@ function createResource(pSource, pFetcher, pOptions) {
|
|
|
42788
43122
|
mutate: setValue
|
|
42789
43123
|
}];
|
|
42790
43124
|
}
|
|
43125
|
+
function batch(fn) {
|
|
43126
|
+
return runUpdates(fn, false);
|
|
43127
|
+
}
|
|
42791
43128
|
function untrack(fn) {
|
|
42792
43129
|
if (!ExternalSourceConfig && Listener === null)
|
|
42793
43130
|
return fn();
|
|
@@ -42801,6 +43138,27 @@ function untrack(fn) {
|
|
|
42801
43138
|
Listener = listener;
|
|
42802
43139
|
}
|
|
42803
43140
|
}
|
|
43141
|
+
function on(deps, fn, options) {
|
|
43142
|
+
const isArray = Array.isArray(deps);
|
|
43143
|
+
let prevInput;
|
|
43144
|
+
let defer = options && options.defer;
|
|
43145
|
+
return (prevValue) => {
|
|
43146
|
+
let input;
|
|
43147
|
+
if (isArray) {
|
|
43148
|
+
input = Array(deps.length);
|
|
43149
|
+
for (let i = 0;i < deps.length; i++)
|
|
43150
|
+
input[i] = deps[i]();
|
|
43151
|
+
} else
|
|
43152
|
+
input = deps();
|
|
43153
|
+
if (defer) {
|
|
43154
|
+
defer = false;
|
|
43155
|
+
return prevValue;
|
|
43156
|
+
}
|
|
43157
|
+
const result = untrack(() => fn(input, prevInput, prevValue));
|
|
43158
|
+
prevInput = input;
|
|
43159
|
+
return result;
|
|
43160
|
+
};
|
|
43161
|
+
}
|
|
42804
43162
|
function onMount(fn) {
|
|
42805
43163
|
createEffect(() => untrack(fn));
|
|
42806
43164
|
}
|
|
@@ -44312,14 +44670,36 @@ function mapToolLabel(toolId, toolLabel) {
|
|
|
44312
44670
|
return toolLabel;
|
|
44313
44671
|
return "Custom";
|
|
44314
44672
|
}
|
|
44673
|
+
var LOCAL_DATE_TIME_FORMATTER = new Intl.DateTimeFormat(undefined, {
|
|
44674
|
+
year: "numeric",
|
|
44675
|
+
month: "2-digit",
|
|
44676
|
+
day: "2-digit",
|
|
44677
|
+
hour: "2-digit",
|
|
44678
|
+
minute: "2-digit",
|
|
44679
|
+
hour12: false
|
|
44680
|
+
});
|
|
44681
|
+
var formatLocalDateTimeParts = (date) => {
|
|
44682
|
+
const parts = LOCAL_DATE_TIME_FORMATTER.formatToParts(date);
|
|
44683
|
+
const get = (type) => parts.find((part) => part.type === type)?.value;
|
|
44684
|
+
const year = get("year");
|
|
44685
|
+
const month = get("month");
|
|
44686
|
+
const day = get("day");
|
|
44687
|
+
const hour = get("hour");
|
|
44688
|
+
const minute = get("minute");
|
|
44689
|
+
if (!year || !month || !day || !hour || !minute) {
|
|
44690
|
+
return LOCAL_DATE_TIME_FORMATTER.format(date);
|
|
44691
|
+
}
|
|
44692
|
+
return `${year}-${month}-${day} ${hour}:${minute}`;
|
|
44693
|
+
};
|
|
44694
|
+
function formatLocalDateTime(timestampMs) {
|
|
44695
|
+
const date = new Date(timestampMs);
|
|
44696
|
+
if (Number.isNaN(date.getTime())) {
|
|
44697
|
+
return "";
|
|
44698
|
+
}
|
|
44699
|
+
return formatLocalDateTimeParts(date);
|
|
44700
|
+
}
|
|
44315
44701
|
function formatTimestamp(ts) {
|
|
44316
|
-
|
|
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}`;
|
|
44702
|
+
return formatLocalDateTime(ts);
|
|
44323
44703
|
}
|
|
44324
44704
|
function buildLastToolUsageLabel(usage) {
|
|
44325
44705
|
if (!usage)
|
|
@@ -44616,6 +44996,98 @@ function Header({
|
|
|
44616
44996
|
})();
|
|
44617
44997
|
}
|
|
44618
44998
|
|
|
44999
|
+
// src/cli/ui/core/theme.ts
|
|
45000
|
+
var colors = {
|
|
45001
|
+
primary: "cyan",
|
|
45002
|
+
secondary: "gray",
|
|
45003
|
+
success: "green",
|
|
45004
|
+
warning: "yellow",
|
|
45005
|
+
error: "red",
|
|
45006
|
+
info: "blue",
|
|
45007
|
+
text: "white",
|
|
45008
|
+
textDim: "gray",
|
|
45009
|
+
textMuted: "gray",
|
|
45010
|
+
selected: "cyan",
|
|
45011
|
+
highlighted: "cyan",
|
|
45012
|
+
disabled: "gray",
|
|
45013
|
+
selectionBackground: "cyan",
|
|
45014
|
+
selectionText: "black",
|
|
45015
|
+
branchFeature: "green",
|
|
45016
|
+
branchBugfix: "yellow",
|
|
45017
|
+
branchHotfix: "red",
|
|
45018
|
+
branchRelease: "magenta",
|
|
45019
|
+
branchMain: "cyan",
|
|
45020
|
+
branchDevelop: "blue",
|
|
45021
|
+
branchOther: "gray",
|
|
45022
|
+
syncUpToDate: "green",
|
|
45023
|
+
syncAhead: "cyan",
|
|
45024
|
+
syncBehind: "yellow",
|
|
45025
|
+
syncDiverged: "red",
|
|
45026
|
+
syncNoUpstream: "gray",
|
|
45027
|
+
worktreeActive: "green",
|
|
45028
|
+
worktreeInaccessible: "red",
|
|
45029
|
+
progressFilled: "green",
|
|
45030
|
+
progressEmpty: "gray",
|
|
45031
|
+
progressPhase: "yellow",
|
|
45032
|
+
progressTime: "magenta"
|
|
45033
|
+
};
|
|
45034
|
+
var logLevelColors = {
|
|
45035
|
+
TRACE: colors.textDim,
|
|
45036
|
+
DEBUG: colors.info,
|
|
45037
|
+
INFO: colors.success,
|
|
45038
|
+
WARN: colors.warning,
|
|
45039
|
+
ERROR: colors.error,
|
|
45040
|
+
FATAL: colors.error
|
|
45041
|
+
};
|
|
45042
|
+
var selectionStyle = {
|
|
45043
|
+
fg: colors.selectionText,
|
|
45044
|
+
bg: colors.selectionBackground
|
|
45045
|
+
};
|
|
45046
|
+
var getLogLevelColor = (label) => {
|
|
45047
|
+
if (!label) {
|
|
45048
|
+
return colors.text;
|
|
45049
|
+
}
|
|
45050
|
+
const normalized = label.toUpperCase();
|
|
45051
|
+
return logLevelColors[normalized] ?? colors.text;
|
|
45052
|
+
};
|
|
45053
|
+
var icons = {
|
|
45054
|
+
pointer: ">",
|
|
45055
|
+
pointerBold: ">",
|
|
45056
|
+
arrowUp: "^",
|
|
45057
|
+
arrowDown: "v",
|
|
45058
|
+
arrowLeft: "<",
|
|
45059
|
+
arrowRight: ">",
|
|
45060
|
+
success: "OK",
|
|
45061
|
+
error: "X",
|
|
45062
|
+
warning: "!",
|
|
45063
|
+
info: "i",
|
|
45064
|
+
skipped: "-",
|
|
45065
|
+
worktree: "W",
|
|
45066
|
+
worktreeActive: "A",
|
|
45067
|
+
worktreeInaccessible: "X",
|
|
45068
|
+
changes: "C",
|
|
45069
|
+
unpushed: "U",
|
|
45070
|
+
current: "*",
|
|
45071
|
+
pr: "PR",
|
|
45072
|
+
merged: "M",
|
|
45073
|
+
syncUpToDate: "=",
|
|
45074
|
+
syncAhead: ">",
|
|
45075
|
+
syncBehind: "<",
|
|
45076
|
+
syncDiverged: "!",
|
|
45077
|
+
spinnerFrames: ["|", "/", "-", "\\"],
|
|
45078
|
+
bullet: "*",
|
|
45079
|
+
divider: "-",
|
|
45080
|
+
verticalLine: "|",
|
|
45081
|
+
corner: "+",
|
|
45082
|
+
branch: "+"
|
|
45083
|
+
};
|
|
45084
|
+
var statsItemsConfig = {
|
|
45085
|
+
local: { label: "Local", icon: "L", color: colors.primary },
|
|
45086
|
+
remote: { label: "Remote", icon: "R", color: colors.info },
|
|
45087
|
+
worktree: { label: "Worktrees", icon: icons.worktree, color: colors.success },
|
|
45088
|
+
changes: { label: "Changes", icon: icons.changes, color: colors.warning }
|
|
45089
|
+
};
|
|
45090
|
+
|
|
44619
45091
|
// src/cli/ui/screens/solid/BranchListScreen.tsx
|
|
44620
45092
|
var VIEW_MODES = ["all", "local", "remote"];
|
|
44621
45093
|
var getCharWidth = (char) => stringWidth(char);
|
|
@@ -44724,8 +45196,8 @@ var fitSegmentsToWidth = (segments, width) => {
|
|
|
44724
45196
|
};
|
|
44725
45197
|
var applySelectionStyle = (segments) => segments.map((segment) => ({
|
|
44726
45198
|
text: segment.text,
|
|
44727
|
-
fg:
|
|
44728
|
-
bg:
|
|
45199
|
+
fg: selectionStyle.fg,
|
|
45200
|
+
bg: selectionStyle.bg
|
|
44729
45201
|
}));
|
|
44730
45202
|
var CLEANUP_SPINNER_FRAMES = ["-", "\\", "|", "/"];
|
|
44731
45203
|
var CURSOR_FRAMES = ["|", " "];
|
|
@@ -44805,7 +45277,13 @@ function BranchListScreen(props) {
|
|
|
44805
45277
|
const [filterQuery, setFilterQuery] = createSignal("");
|
|
44806
45278
|
const [filterMode, setFilterMode] = createSignal(false);
|
|
44807
45279
|
const [viewMode, setViewMode] = createSignal("all");
|
|
44808
|
-
const [
|
|
45280
|
+
const [internalSelectedIndex, setInternalSelectedIndex] = createSignal(props.cursorPosition ?? 0);
|
|
45281
|
+
const selectedIndex = () => props.cursorPosition ?? internalSelectedIndex();
|
|
45282
|
+
const setSelectedIndex = (value) => {
|
|
45283
|
+
const newValue = typeof value === "function" ? value(selectedIndex()) : value;
|
|
45284
|
+
setInternalSelectedIndex(newValue);
|
|
45285
|
+
props.onCursorPositionChange?.(newValue);
|
|
45286
|
+
};
|
|
44809
45287
|
const [scrollOffset, setScrollOffset] = createSignal(0);
|
|
44810
45288
|
const [cleanupSpinnerIndex, setCleanupSpinnerIndex] = createSignal(0);
|
|
44811
45289
|
const [cursorIndex, setCursorIndex] = createSignal(0);
|
|
@@ -44833,7 +45311,14 @@ function BranchListScreen(props) {
|
|
|
44833
45311
|
return Object.values(props.cleanupUI.indicators).some((indicator) => indicator.isSpinning);
|
|
44834
45312
|
});
|
|
44835
45313
|
const hasSpinningFooter = createMemo(() => props.cleanupUI?.footerMessage?.isSpinning ?? false);
|
|
44836
|
-
const
|
|
45314
|
+
const safetyPendingActive = createMemo(() => {
|
|
45315
|
+
const pending = props.cleanupUI?.safetyPendingBranches;
|
|
45316
|
+
if (pending) {
|
|
45317
|
+
return pending.size > 0;
|
|
45318
|
+
}
|
|
45319
|
+
return props.cleanupUI?.safetyLoading === true;
|
|
45320
|
+
});
|
|
45321
|
+
const cleanupSpinnerActive = createMemo(() => hasSpinningIndicator() || hasSpinningFooter() || safetyPendingActive());
|
|
44837
45322
|
createEffect(() => {
|
|
44838
45323
|
let intervalTimer;
|
|
44839
45324
|
if (cleanupSpinnerActive()) {
|
|
@@ -44884,12 +45369,12 @@ function BranchListScreen(props) {
|
|
|
44884
45369
|
}
|
|
44885
45370
|
return maxWidth;
|
|
44886
45371
|
});
|
|
44887
|
-
createEffect(() => {
|
|
44888
|
-
filterQuery();
|
|
44889
|
-
viewMode();
|
|
45372
|
+
createEffect(on(() => [filterQuery(), viewMode()], () => {
|
|
44890
45373
|
setSelectedIndex(0);
|
|
44891
45374
|
setScrollOffset(0);
|
|
44892
|
-
}
|
|
45375
|
+
}, {
|
|
45376
|
+
defer: true
|
|
45377
|
+
}));
|
|
44893
45378
|
createEffect(() => {
|
|
44894
45379
|
const total = filteredBranches().length;
|
|
44895
45380
|
if (total === 0) {
|
|
@@ -44937,18 +45422,16 @@ function BranchListScreen(props) {
|
|
|
44937
45422
|
if (!timestamp || Number.isNaN(timestamp)) {
|
|
44938
45423
|
return "---";
|
|
44939
45424
|
}
|
|
44940
|
-
const
|
|
44941
|
-
|
|
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}`;
|
|
45425
|
+
const formatted = formatLocalDateTime(timestamp * 1000);
|
|
45426
|
+
return formatted || "---";
|
|
44947
45427
|
};
|
|
44948
45428
|
useKeyboard((key) => {
|
|
44949
45429
|
if (props.wizardVisible) {
|
|
44950
45430
|
return;
|
|
44951
45431
|
}
|
|
45432
|
+
if (props.confirmVisible) {
|
|
45433
|
+
return;
|
|
45434
|
+
}
|
|
44952
45435
|
if (props.helpVisible) {
|
|
44953
45436
|
return;
|
|
44954
45437
|
}
|
|
@@ -45054,7 +45537,8 @@ function BranchListScreen(props) {
|
|
|
45054
45537
|
} else if (key.name === "p" || key.sequence === "p") {
|
|
45055
45538
|
props.onOpenProfiles?.();
|
|
45056
45539
|
} else if (key.name === "l" || key.sequence === "l") {
|
|
45057
|
-
|
|
45540
|
+
const selected = filteredBranches()[selectedIndex()] ?? null;
|
|
45541
|
+
props.onOpenLogs?.(selected);
|
|
45058
45542
|
}
|
|
45059
45543
|
});
|
|
45060
45544
|
const visibleBranches = createMemo(() => {
|
|
@@ -45082,19 +45566,24 @@ function BranchListScreen(props) {
|
|
|
45082
45566
|
let worktreeColor = "gray";
|
|
45083
45567
|
if (branch.worktreeStatus === "active") {
|
|
45084
45568
|
worktreeIcon = "w";
|
|
45085
|
-
worktreeColor = "
|
|
45569
|
+
worktreeColor = "brightGreen";
|
|
45086
45570
|
} else if (branch.worktreeStatus === "inaccessible") {
|
|
45087
45571
|
worktreeIcon = "x";
|
|
45088
45572
|
worktreeColor = "red";
|
|
45089
45573
|
}
|
|
45090
45574
|
const isRemoteBranch = branch.type === "remote";
|
|
45091
45575
|
const safetyLoading = props.cleanupUI?.safetyLoading === true;
|
|
45576
|
+
const safetyPendingBranches = props.cleanupUI?.safetyPendingBranches;
|
|
45577
|
+
const isSafetyPending = safetyPendingBranches ? safetyPendingBranches.has(branch.name) : safetyLoading;
|
|
45092
45578
|
const spinnerFrame = cleanupSpinnerFrame();
|
|
45093
45579
|
let safeIcon = " ";
|
|
45094
45580
|
let safeColor;
|
|
45095
45581
|
if (isRemoteBranch) {
|
|
45096
45582
|
safeIcon = " ";
|
|
45097
45583
|
safeColor = undefined;
|
|
45584
|
+
} else if (isSafetyPending) {
|
|
45585
|
+
safeIcon = spinnerFrame ?? "-";
|
|
45586
|
+
safeColor = undefined;
|
|
45098
45587
|
} else if (hasUncommitted) {
|
|
45099
45588
|
safeIcon = "!";
|
|
45100
45589
|
safeColor = "red";
|
|
@@ -45104,12 +45593,9 @@ function BranchListScreen(props) {
|
|
|
45104
45593
|
} else if (branch.isUnmerged) {
|
|
45105
45594
|
safeIcon = "*";
|
|
45106
45595
|
safeColor = "yellow";
|
|
45107
|
-
} else if (safetyLoading) {
|
|
45108
|
-
safeIcon = spinnerFrame ?? "-";
|
|
45109
|
-
safeColor = undefined;
|
|
45110
45596
|
} else if (branch.safeToCleanup === true) {
|
|
45111
|
-
safeIcon = "
|
|
45112
|
-
safeColor =
|
|
45597
|
+
safeIcon = "o";
|
|
45598
|
+
safeColor = "brightGreen";
|
|
45113
45599
|
} else {
|
|
45114
45600
|
safeIcon = "!";
|
|
45115
45601
|
safeColor = "red";
|
|
@@ -45316,6 +45802,63 @@ function BranchListScreen(props) {
|
|
|
45316
45802
|
}
|
|
45317
45803
|
return fitSegmentsToWidth(segments, layoutWidth());
|
|
45318
45804
|
});
|
|
45805
|
+
const statusLegendSegments = createMemo(() => {
|
|
45806
|
+
const segments = [];
|
|
45807
|
+
const separator = " ";
|
|
45808
|
+
appendSegment(segments, {
|
|
45809
|
+
text: "Legend: ",
|
|
45810
|
+
attributes: TextAttributes.DIM
|
|
45811
|
+
});
|
|
45812
|
+
appendSegment(segments, {
|
|
45813
|
+
text: "o",
|
|
45814
|
+
fg: "brightGreen",
|
|
45815
|
+
attributes: TextAttributes.BOLD
|
|
45816
|
+
});
|
|
45817
|
+
appendSegment(segments, {
|
|
45818
|
+
text: " Safe",
|
|
45819
|
+
fg: "brightGreen"
|
|
45820
|
+
});
|
|
45821
|
+
appendSegment(segments, {
|
|
45822
|
+
text: separator,
|
|
45823
|
+
attributes: TextAttributes.DIM
|
|
45824
|
+
});
|
|
45825
|
+
appendSegment(segments, {
|
|
45826
|
+
text: "!",
|
|
45827
|
+
fg: "red",
|
|
45828
|
+
attributes: TextAttributes.BOLD
|
|
45829
|
+
});
|
|
45830
|
+
appendSegment(segments, {
|
|
45831
|
+
text: " Uncommitted",
|
|
45832
|
+
fg: "red"
|
|
45833
|
+
});
|
|
45834
|
+
appendSegment(segments, {
|
|
45835
|
+
text: separator,
|
|
45836
|
+
attributes: TextAttributes.DIM
|
|
45837
|
+
});
|
|
45838
|
+
appendSegment(segments, {
|
|
45839
|
+
text: "!",
|
|
45840
|
+
fg: "yellow",
|
|
45841
|
+
attributes: TextAttributes.BOLD
|
|
45842
|
+
});
|
|
45843
|
+
appendSegment(segments, {
|
|
45844
|
+
text: " Unpushed",
|
|
45845
|
+
fg: "yellow"
|
|
45846
|
+
});
|
|
45847
|
+
appendSegment(segments, {
|
|
45848
|
+
text: separator,
|
|
45849
|
+
attributes: TextAttributes.DIM
|
|
45850
|
+
});
|
|
45851
|
+
appendSegment(segments, {
|
|
45852
|
+
text: "*",
|
|
45853
|
+
fg: "yellow",
|
|
45854
|
+
attributes: TextAttributes.BOLD
|
|
45855
|
+
});
|
|
45856
|
+
appendSegment(segments, {
|
|
45857
|
+
text: " Unmerged",
|
|
45858
|
+
fg: "yellow"
|
|
45859
|
+
});
|
|
45860
|
+
return fitSegmentsToWidth(segments, layoutWidth());
|
|
45861
|
+
});
|
|
45319
45862
|
const footerSegments = createMemo(() => {
|
|
45320
45863
|
const segments = [];
|
|
45321
45864
|
const separator = " ";
|
|
@@ -45411,50 +45954,46 @@ function BranchListScreen(props) {
|
|
|
45411
45954
|
}
|
|
45412
45955
|
}, () => props.loadingIndicatorDelay !== undefined ? {
|
|
45413
45956
|
delay: props.loadingIndicatorDelay
|
|
45414
|
-
} : {})) : (()
|
|
45415
|
-
var _el$7 = createElement("text");
|
|
45416
|
-
insert(_el$7, () => padLine("", layoutWidth()));
|
|
45417
|
-
return _el$7;
|
|
45418
|
-
})();
|
|
45957
|
+
} : {})) : renderSegmentLine(statusLegendSegments());
|
|
45419
45958
|
})(), null);
|
|
45420
45959
|
insert(_el$5, (() => {
|
|
45421
45960
|
var _c$2 = memo2(() => !!props.error);
|
|
45422
45961
|
return () => _c$2() && [(() => {
|
|
45962
|
+
var _el$7 = createElement("text");
|
|
45963
|
+
setProp(_el$7, "fg", "red");
|
|
45964
|
+
insert(_el$7, () => padLine(`Error: ${props.error.message}`, layoutWidth()));
|
|
45965
|
+
effect((_$p) => setProp(_el$7, "attributes", TextAttributes.BOLD, _$p));
|
|
45966
|
+
return _el$7;
|
|
45967
|
+
})(), memo2(() => memo2(() => !!(process.env.DEBUG && props.error.stack))() && [(() => {
|
|
45423
45968
|
var _el$8 = createElement("text");
|
|
45424
|
-
|
|
45425
|
-
|
|
45426
|
-
effect((_$p) => setProp(_el$8, "attributes", TextAttributes.BOLD, _$p));
|
|
45969
|
+
insert(_el$8, () => padLine("", layoutWidth()));
|
|
45970
|
+
effect((_$p) => setProp(_el$8, "attributes", TextAttributes.DIM, _$p));
|
|
45427
45971
|
return _el$8;
|
|
45428
|
-
})(), memo2(() =>
|
|
45972
|
+
})(), memo2(() => props.error.stack.split(`
|
|
45973
|
+
`).map((line) => (() => {
|
|
45429
45974
|
var _el$9 = createElement("text");
|
|
45430
|
-
|
|
45975
|
+
setProp(_el$9, "fg", "gray");
|
|
45976
|
+
insert(_el$9, () => padLine(line, layoutWidth()));
|
|
45431
45977
|
effect((_$p) => setProp(_el$9, "attributes", TextAttributes.DIM, _$p));
|
|
45432
45978
|
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
45979
|
})()))])];
|
|
45441
45980
|
})(), null);
|
|
45442
45981
|
insert(_el$5, (() => {
|
|
45443
45982
|
var _c$3 = memo2(() => !!(!props.loading && !props.error && props.branches.length === 0));
|
|
45444
45983
|
return () => _c$3() && (() => {
|
|
45445
|
-
var _el$
|
|
45446
|
-
insert(_el$
|
|
45447
|
-
effect((_$p) => setProp(_el$
|
|
45448
|
-
return _el$
|
|
45984
|
+
var _el$0 = createElement("text");
|
|
45985
|
+
insert(_el$0, () => padLine("No branches found", layoutWidth()));
|
|
45986
|
+
effect((_$p) => setProp(_el$0, "attributes", TextAttributes.DIM, _$p));
|
|
45987
|
+
return _el$0;
|
|
45449
45988
|
})();
|
|
45450
45989
|
})(), null);
|
|
45451
45990
|
insert(_el$5, (() => {
|
|
45452
45991
|
var _c$4 = memo2(() => !!(!props.loading && !props.error && props.branches.length > 0 && filteredBranches().length === 0 && filterQuery()));
|
|
45453
45992
|
return () => _c$4() && (() => {
|
|
45454
|
-
var _el$
|
|
45455
|
-
insert(_el$
|
|
45456
|
-
effect((_$p) => setProp(_el$
|
|
45457
|
-
return _el$
|
|
45993
|
+
var _el$1 = createElement("text");
|
|
45994
|
+
insert(_el$1, () => padLine("No branches match your filter", layoutWidth()));
|
|
45995
|
+
effect((_$p) => setProp(_el$1, "attributes", TextAttributes.DIM, _$p));
|
|
45996
|
+
return _el$1;
|
|
45458
45997
|
})();
|
|
45459
45998
|
})(), null);
|
|
45460
45999
|
insert(_el$5, (() => {
|
|
@@ -45465,20 +46004,20 @@ function BranchListScreen(props) {
|
|
|
45465
46004
|
})), memo2(() => Array.from({
|
|
45466
46005
|
length: Math.max(0, contentHeight() - visibleBranches().length)
|
|
45467
46006
|
}).map(() => (() => {
|
|
45468
|
-
var _el$
|
|
45469
|
-
insert(_el$
|
|
45470
|
-
return _el$
|
|
46007
|
+
var _el$10 = createElement("text");
|
|
46008
|
+
insert(_el$10, () => padLine("", listWidth()));
|
|
46009
|
+
return _el$10;
|
|
45471
46010
|
})()))];
|
|
45472
46011
|
})(), null);
|
|
45473
46012
|
insert(_el$4, (() => {
|
|
45474
46013
|
var _c$6 = memo2(() => !!props.cleanupUI?.footerMessage);
|
|
45475
46014
|
return () => _c$6() && (() => {
|
|
45476
|
-
var _el$
|
|
45477
|
-
spread(_el$
|
|
46015
|
+
var _el$11 = createElement("text");
|
|
46016
|
+
spread(_el$11, mergeProps3(() => props.cleanupUI.footerMessage.color ? {
|
|
45478
46017
|
fg: props.cleanupUI.footerMessage.color
|
|
45479
46018
|
} : {}), true);
|
|
45480
|
-
insert(_el$
|
|
45481
|
-
return _el$
|
|
46019
|
+
insert(_el$11, () => padLine(props.cleanupUI.footerMessage.isSpinning && cleanupSpinnerFrame() ? `${cleanupSpinnerFrame()} ${props.cleanupUI.footerMessage.text}` : props.cleanupUI.footerMessage.text, layoutWidth()));
|
|
46020
|
+
return _el$11;
|
|
45482
46021
|
})();
|
|
45483
46022
|
})(), _el$6);
|
|
45484
46023
|
insert(_el$6, () => padLine(`Worktree: ${selectedWorktreeLabel()}`, layoutWidth()));
|
|
@@ -46009,6 +46548,15 @@ function SelectInput(props) {
|
|
|
46009
46548
|
},
|
|
46010
46549
|
get height() {
|
|
46011
46550
|
return computedHeight();
|
|
46551
|
+
},
|
|
46552
|
+
get selectedBackgroundColor() {
|
|
46553
|
+
return selectionStyle.bg;
|
|
46554
|
+
},
|
|
46555
|
+
get selectedTextColor() {
|
|
46556
|
+
return selectionStyle.fg;
|
|
46557
|
+
},
|
|
46558
|
+
get selectedDescriptionColor() {
|
|
46559
|
+
return selectionStyle.fg;
|
|
46012
46560
|
}
|
|
46013
46561
|
}, () => props.selectedIndex !== undefined && {
|
|
46014
46562
|
selectedIndex: props.selectedIndex
|
|
@@ -46040,30 +46588,46 @@ function QuickStartStep(props) {
|
|
|
46040
46588
|
props.onChooseDifferent();
|
|
46041
46589
|
}
|
|
46042
46590
|
});
|
|
46043
|
-
const
|
|
46591
|
+
const buildSettingsDescription = (entry) => {
|
|
46592
|
+
const parts = [];
|
|
46593
|
+
if (entry.toolLabel) {
|
|
46594
|
+
parts.push(entry.toolLabel);
|
|
46595
|
+
} else if (entry.toolId) {
|
|
46596
|
+
parts.push(entry.toolId);
|
|
46597
|
+
}
|
|
46598
|
+
if (entry.model) {
|
|
46599
|
+
parts.push(entry.model);
|
|
46600
|
+
}
|
|
46601
|
+
if (entry.toolId === "codex-cli" && entry.reasoningLevel) {
|
|
46602
|
+
parts.push(entry.reasoningLevel);
|
|
46603
|
+
}
|
|
46604
|
+
return parts.join(", ");
|
|
46605
|
+
};
|
|
46044
46606
|
const items = createMemo(() => {
|
|
46045
46607
|
const result = [];
|
|
46046
|
-
|
|
46047
|
-
|
|
46048
|
-
|
|
46049
|
-
const
|
|
46050
|
-
const
|
|
46051
|
-
const
|
|
46052
|
-
|
|
46053
|
-
|
|
46054
|
-
|
|
46055
|
-
|
|
46056
|
-
|
|
46057
|
-
|
|
46058
|
-
|
|
46608
|
+
props.history.forEach((entry, index) => {
|
|
46609
|
+
if (!entry)
|
|
46610
|
+
return;
|
|
46611
|
+
const settingsDesc = buildSettingsDescription(entry);
|
|
46612
|
+
const sessionId = entry.sessionId && entry.sessionId.trim().length > 0 ? entry.sessionId.trim() : null;
|
|
46613
|
+
const suffix = `${entry.toolId ?? "tool"}-${index}`;
|
|
46614
|
+
if (sessionId) {
|
|
46615
|
+
result.push({
|
|
46616
|
+
label: "Resume session (previous settings)",
|
|
46617
|
+
value: `resume-${suffix}`,
|
|
46618
|
+
description: `${settingsDesc} | Session: ${sessionId}`,
|
|
46619
|
+
action: "resume",
|
|
46620
|
+
entry
|
|
46621
|
+
});
|
|
46622
|
+
}
|
|
46059
46623
|
result.push({
|
|
46060
46624
|
label: "Start new (previous settings)",
|
|
46061
|
-
value: `start-new-${
|
|
46625
|
+
value: `start-new-${suffix}`,
|
|
46062
46626
|
description: settingsDesc,
|
|
46063
46627
|
action: "start-new",
|
|
46064
46628
|
entry
|
|
46065
46629
|
});
|
|
46066
|
-
}
|
|
46630
|
+
});
|
|
46067
46631
|
result.push({
|
|
46068
46632
|
label: "Choose different settings...",
|
|
46069
46633
|
value: "choose-different",
|
|
@@ -46366,260 +46930,31 @@ function normalizeModelId(tool, model) {
|
|
|
46366
46930
|
return trimmed;
|
|
46367
46931
|
}
|
|
46368
46932
|
|
|
46369
|
-
// src/utils/
|
|
46370
|
-
var
|
|
46371
|
-
|
|
46372
|
-
|
|
46373
|
-
return
|
|
46933
|
+
// src/cli/ui/utils/versionCache.ts
|
|
46934
|
+
var versionCache = new Map;
|
|
46935
|
+
function getVersionCache(agentId) {
|
|
46936
|
+
const cached = versionCache.get(agentId);
|
|
46937
|
+
return cached !== undefined ? cached : null;
|
|
46374
46938
|
}
|
|
46375
|
-
async function
|
|
46376
|
-
|
|
46377
|
-
const
|
|
46378
|
-
|
|
46379
|
-
|
|
46380
|
-
|
|
46381
|
-
|
|
46382
|
-
|
|
46383
|
-
|
|
46384
|
-
}
|
|
46385
|
-
|
|
46386
|
-
|
|
46387
|
-
|
|
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
|
-
}
|
|
46414
|
-
}
|
|
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 };
|
|
46433
|
-
}
|
|
46434
|
-
const packageName = command.substring(0, atIndex);
|
|
46435
|
-
const version = command.substring(atIndex + 1);
|
|
46436
|
-
return { packageName, version };
|
|
46437
|
-
}
|
|
46438
|
-
|
|
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
|
-
];
|
|
46520
|
-
|
|
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
|
-
}
|
|
46577
|
-
}
|
|
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
|
-
}
|
|
46608
|
-
}
|
|
46609
|
-
}
|
|
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;
|
|
46939
|
+
async function prefetchAgentVersions(agentIds, fetchFn) {
|
|
46940
|
+
const fetcher = fetchFn ?? (async (agentId) => {
|
|
46941
|
+
const { fetchVersionOptionsForAgent: fetchVersionOptionsForAgent2 } = await Promise.resolve().then(() => (init_versionFetcher(), exports_versionFetcher));
|
|
46942
|
+
return fetchVersionOptionsForAgent2(agentId);
|
|
46943
|
+
});
|
|
46944
|
+
const results = await Promise.allSettled(agentIds.map(async (agentId) => {
|
|
46945
|
+
try {
|
|
46946
|
+
const versions = await fetcher(agentId);
|
|
46947
|
+
versionCache.set(agentId, versions);
|
|
46948
|
+
} catch {}
|
|
46949
|
+
}));
|
|
46950
|
+
for (let i2 = 0;i2 < results.length; i2++) {
|
|
46951
|
+
const result = results[i2];
|
|
46952
|
+
if (result && result.status === "rejected") {}
|
|
46617
46953
|
}
|
|
46618
|
-
commandLookupCache.set(commandName, lookupResult);
|
|
46619
|
-
return lookupResult;
|
|
46620
46954
|
}
|
|
46621
46955
|
|
|
46622
46956
|
// src/cli/ui/components/solid/WizardSteps.tsx
|
|
46957
|
+
init_versionFetcher();
|
|
46623
46958
|
var useEnsureSelectionVisible = (options) => {
|
|
46624
46959
|
const scroll = useWizardScroll();
|
|
46625
46960
|
const ensureIndexVisible = (index) => {
|
|
@@ -46929,9 +47264,16 @@ function AgentSelectStep(props) {
|
|
|
46929
47264
|
return isSelected() ? (() => {
|
|
46930
47265
|
var _el$39 = createElement("text"), _el$40 = createTextNode(`> `);
|
|
46931
47266
|
insertNode(_el$39, _el$40);
|
|
46932
|
-
setProp(_el$39, "bg", "cyan");
|
|
46933
|
-
setProp(_el$39, "fg", "black");
|
|
46934
47267
|
insert(_el$39, () => agent.label, null);
|
|
47268
|
+
effect((_p$) => {
|
|
47269
|
+
var _v$9 = selectionStyle.bg, _v$0 = selectionStyle.fg;
|
|
47270
|
+
_v$9 !== _p$.e && (_p$.e = setProp(_el$39, "bg", _v$9, _p$.e));
|
|
47271
|
+
_v$0 !== _p$.t && (_p$.t = setProp(_el$39, "fg", _v$0, _p$.t));
|
|
47272
|
+
return _p$;
|
|
47273
|
+
}, {
|
|
47274
|
+
e: undefined,
|
|
47275
|
+
t: undefined
|
|
47276
|
+
});
|
|
46935
47277
|
return _el$39;
|
|
46936
47278
|
})() : (() => {
|
|
46937
47279
|
var _el$41 = createElement("text"), _el$42 = createTextNode(` `);
|
|
@@ -47023,9 +47365,9 @@ function ModelSelectStep(props) {
|
|
|
47023
47365
|
insertNode(_el$48, createTextNode(` `));
|
|
47024
47366
|
insertNode(_el$50, createTextNode(`[Enter] Select [Esc] Back`));
|
|
47025
47367
|
effect((_p$) => {
|
|
47026
|
-
var _v$
|
|
47027
|
-
_v$
|
|
47028
|
-
_v$
|
|
47368
|
+
var _v$1 = TextAttributes.BOLD, _v$10 = TextAttributes.DIM;
|
|
47369
|
+
_v$1 !== _p$.e && (_p$.e = setProp(_el$44, "attributes", _v$1, _p$.e));
|
|
47370
|
+
_v$10 !== _p$.t && (_p$.t = setProp(_el$50, "attributes", _v$10, _p$.t));
|
|
47029
47371
|
return _p$;
|
|
47030
47372
|
}, {
|
|
47031
47373
|
e: undefined,
|
|
@@ -47092,9 +47434,9 @@ function ReasoningLevelStep(props) {
|
|
|
47092
47434
|
insertNode(_el$57, createTextNode(` `));
|
|
47093
47435
|
insertNode(_el$59, createTextNode(`[Enter] Select [Esc] Back`));
|
|
47094
47436
|
effect((_p$) => {
|
|
47095
|
-
var _v$
|
|
47096
|
-
_v$
|
|
47097
|
-
_v$
|
|
47437
|
+
var _v$11 = TextAttributes.BOLD, _v$12 = TextAttributes.DIM;
|
|
47438
|
+
_v$11 !== _p$.e && (_p$.e = setProp(_el$53, "attributes", _v$11, _p$.e));
|
|
47439
|
+
_v$12 !== _p$.t && (_p$.t = setProp(_el$59, "attributes", _v$12, _p$.t));
|
|
47098
47440
|
return _p$;
|
|
47099
47441
|
}, {
|
|
47100
47442
|
e: undefined,
|
|
@@ -47157,9 +47499,9 @@ function ExecutionModeStep(props) {
|
|
|
47157
47499
|
insertNode(_el$66, createTextNode(` `));
|
|
47158
47500
|
insertNode(_el$68, createTextNode(`[Enter] Select [Esc] Back`));
|
|
47159
47501
|
effect((_p$) => {
|
|
47160
|
-
var _v$
|
|
47161
|
-
_v$
|
|
47162
|
-
_v$
|
|
47502
|
+
var _v$13 = TextAttributes.BOLD, _v$14 = TextAttributes.DIM;
|
|
47503
|
+
_v$13 !== _p$.e && (_p$.e = setProp(_el$62, "attributes", _v$13, _p$.e));
|
|
47504
|
+
_v$14 !== _p$.t && (_p$.t = setProp(_el$68, "attributes", _v$14, _p$.t));
|
|
47163
47505
|
return _p$;
|
|
47164
47506
|
}, {
|
|
47165
47507
|
e: undefined,
|
|
@@ -47218,9 +47560,9 @@ function SkipPermissionsStep(props) {
|
|
|
47218
47560
|
insertNode(_el$75, createTextNode(` `));
|
|
47219
47561
|
insertNode(_el$77, createTextNode(`[Enter] Select [Esc] Back`));
|
|
47220
47562
|
effect((_p$) => {
|
|
47221
|
-
var _v$
|
|
47222
|
-
_v$
|
|
47223
|
-
_v$
|
|
47563
|
+
var _v$15 = TextAttributes.BOLD, _v$16 = TextAttributes.DIM;
|
|
47564
|
+
_v$15 !== _p$.e && (_p$.e = setProp(_el$71, "attributes", _v$15, _p$.e));
|
|
47565
|
+
_v$16 !== _p$.t && (_p$.t = setProp(_el$77, "attributes", _v$16, _p$.t));
|
|
47224
47566
|
return _p$;
|
|
47225
47567
|
}, {
|
|
47226
47568
|
e: undefined,
|
|
@@ -47234,60 +47576,20 @@ var LATEST_OPTION = {
|
|
|
47234
47576
|
value: "latest",
|
|
47235
47577
|
description: "Always fetch latest version"
|
|
47236
47578
|
};
|
|
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
47579
|
function VersionSelectStep(props) {
|
|
47287
47580
|
const [selectedIndex, setSelectedIndex] = createSignal(0);
|
|
47288
47581
|
const [selectRef, setSelectRef] = createSignal(undefined);
|
|
47289
|
-
const
|
|
47290
|
-
|
|
47582
|
+
const cachedVersions = () => {
|
|
47583
|
+
const cached = getVersionCache(props.agentId);
|
|
47584
|
+
if (!cached) {
|
|
47585
|
+
return [];
|
|
47586
|
+
}
|
|
47587
|
+
return cached.map(versionInfoToSelectItem);
|
|
47588
|
+
};
|
|
47589
|
+
const [installedOption] = createResource(() => props.agentId, async (agentId) => {
|
|
47590
|
+
const installed = await fetchInstalledVersionForAgent(agentId);
|
|
47591
|
+
return installed ? createInstalledOption(installed) : null;
|
|
47592
|
+
});
|
|
47291
47593
|
const allOptions = () => {
|
|
47292
47594
|
const options = [];
|
|
47293
47595
|
const installed = installedOption();
|
|
@@ -47295,8 +47597,8 @@ function VersionSelectStep(props) {
|
|
|
47295
47597
|
options.push(installed);
|
|
47296
47598
|
}
|
|
47297
47599
|
options.push(LATEST_OPTION);
|
|
47298
|
-
const
|
|
47299
|
-
options.push(...
|
|
47600
|
+
const cached = cachedVersions();
|
|
47601
|
+
options.push(...cached);
|
|
47300
47602
|
return options;
|
|
47301
47603
|
};
|
|
47302
47604
|
useEnsureSelectionVisible({
|
|
@@ -47327,11 +47629,9 @@ function VersionSelectStep(props) {
|
|
|
47327
47629
|
}
|
|
47328
47630
|
};
|
|
47329
47631
|
const statusText = () => {
|
|
47330
|
-
|
|
47331
|
-
|
|
47332
|
-
|
|
47333
|
-
if (versionOptions.error) {
|
|
47334
|
-
return "Could not fetch versions";
|
|
47632
|
+
const cached = cachedVersions();
|
|
47633
|
+
if (cached.length === 0) {
|
|
47634
|
+
return "Version list unavailable (using latest)";
|
|
47335
47635
|
}
|
|
47336
47636
|
return null;
|
|
47337
47637
|
};
|
|
@@ -47368,9 +47668,9 @@ function VersionSelectStep(props) {
|
|
|
47368
47668
|
insertNode(_el$84, createTextNode(` `));
|
|
47369
47669
|
insertNode(_el$86, createTextNode(`[Enter] Select [Esc] Back`));
|
|
47370
47670
|
effect((_p$) => {
|
|
47371
|
-
var _v$
|
|
47372
|
-
_v$
|
|
47373
|
-
_v$
|
|
47671
|
+
var _v$17 = TextAttributes.BOLD, _v$18 = TextAttributes.DIM;
|
|
47672
|
+
_v$17 !== _p$.e && (_p$.e = setProp(_el$80, "attributes", _v$17, _p$.e));
|
|
47673
|
+
_v$18 !== _p$.t && (_p$.t = setProp(_el$86, "attributes", _v$18, _p$.t));
|
|
47374
47674
|
return _p$;
|
|
47375
47675
|
}, {
|
|
47376
47676
|
e: undefined,
|
|
@@ -47392,7 +47692,7 @@ function WizardController(props) {
|
|
|
47392
47692
|
const [selectedModel, setSelectedModel] = createSignal("");
|
|
47393
47693
|
const [reasoningLevel, setReasoningLevel] = createSignal(undefined);
|
|
47394
47694
|
const [executionMode, setExecutionMode] = createSignal("normal");
|
|
47395
|
-
const [
|
|
47695
|
+
const [isTransitioning, setIsTransitioning] = createSignal(true);
|
|
47396
47696
|
function getInitialStep() {
|
|
47397
47697
|
if (props.history.length > 0) {
|
|
47398
47698
|
return "quick-start";
|
|
@@ -47411,20 +47711,23 @@ function WizardController(props) {
|
|
|
47411
47711
|
setReasoningLevel(undefined);
|
|
47412
47712
|
setExecutionMode("normal");
|
|
47413
47713
|
};
|
|
47714
|
+
const startTransition2 = () => {
|
|
47715
|
+
setIsTransitioning(true);
|
|
47716
|
+
setTimeout(() => setIsTransitioning(false), 50);
|
|
47717
|
+
};
|
|
47414
47718
|
let prevVisible = false;
|
|
47415
47719
|
createEffect(() => {
|
|
47416
47720
|
const visible = props.visible;
|
|
47417
47721
|
if (visible && !prevVisible) {
|
|
47418
47722
|
resetWizard();
|
|
47419
|
-
|
|
47420
|
-
setTimeout(() => setIsInitialFrame(false), 150);
|
|
47723
|
+
startTransition2();
|
|
47421
47724
|
}
|
|
47422
47725
|
prevVisible = visible;
|
|
47423
47726
|
});
|
|
47424
47727
|
useKeyboard((key) => {
|
|
47425
47728
|
if (!props.visible)
|
|
47426
47729
|
return;
|
|
47427
|
-
if (
|
|
47730
|
+
if (isTransitioning() && key.name === "return") {
|
|
47428
47731
|
return;
|
|
47429
47732
|
}
|
|
47430
47733
|
if (key.name === "escape") {
|
|
@@ -47434,6 +47737,7 @@ function WizardController(props) {
|
|
|
47434
47737
|
const goToStep = (nextStep) => {
|
|
47435
47738
|
setStepHistory((prev) => [...prev, step()]);
|
|
47436
47739
|
setStep(nextStep);
|
|
47740
|
+
startTransition2();
|
|
47437
47741
|
};
|
|
47438
47742
|
const goBack = () => {
|
|
47439
47743
|
const history = stepHistory();
|
|
@@ -47444,6 +47748,7 @@ function WizardController(props) {
|
|
|
47444
47748
|
const previousStep = history[history.length - 1] ?? "agent-select";
|
|
47445
47749
|
setStepHistory(history.slice(0, -1));
|
|
47446
47750
|
setStep(previousStep);
|
|
47751
|
+
startTransition2();
|
|
47447
47752
|
};
|
|
47448
47753
|
const needsReasoningLevel = createMemo(() => {
|
|
47449
47754
|
return selectedAgent() === "codex-cli";
|
|
@@ -47479,7 +47784,7 @@ function WizardController(props) {
|
|
|
47479
47784
|
goToStep("version-select");
|
|
47480
47785
|
};
|
|
47481
47786
|
const handleVersionSelect = (version) => {
|
|
47482
|
-
setSelectedVersion(version
|
|
47787
|
+
setSelectedVersion(version);
|
|
47483
47788
|
goToStep("model-select");
|
|
47484
47789
|
};
|
|
47485
47790
|
const handleModelSelect = (model) => {
|
|
@@ -47526,7 +47831,7 @@ function WizardController(props) {
|
|
|
47526
47831
|
};
|
|
47527
47832
|
const renderStep = () => {
|
|
47528
47833
|
const currentStep = step();
|
|
47529
|
-
const focused = !
|
|
47834
|
+
const focused = !isTransitioning();
|
|
47530
47835
|
if (currentStep === "action-select") {
|
|
47531
47836
|
return createComponent2(ActionSelectStep, {
|
|
47532
47837
|
get branchName() {
|
|
@@ -47780,6 +48085,10 @@ function useScrollableList(options) {
|
|
|
47780
48085
|
|
|
47781
48086
|
// src/cli/ui/screens/solid/SelectorScreen.tsx
|
|
47782
48087
|
var clamp2 = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
48088
|
+
var padLine2 = (value, width) => {
|
|
48089
|
+
const padding = Math.max(0, width - stringWidth(value));
|
|
48090
|
+
return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
|
|
48091
|
+
};
|
|
47783
48092
|
function SelectorScreen({
|
|
47784
48093
|
title,
|
|
47785
48094
|
description,
|
|
@@ -47898,30 +48207,34 @@ function SelectorScreen({
|
|
|
47898
48207
|
insert(_el$5, () => list.visibleItems().map((item, index) => {
|
|
47899
48208
|
const absoluteIndex = list.scrollOffset() + index;
|
|
47900
48209
|
const isSelected = absoluteIndex === selectedIndex();
|
|
48210
|
+
const descriptionText = showDescription && item.description ? ` - ${item.description}` : "";
|
|
48211
|
+
const fullLine = `${item.label}${descriptionText}`;
|
|
47901
48212
|
return (() => {
|
|
47902
|
-
var _el$6 = createElement("box")
|
|
47903
|
-
insertNode(_el$6, _el$7);
|
|
48213
|
+
var _el$6 = createElement("box");
|
|
47904
48214
|
setProp(_el$6, "flexDirection", "row");
|
|
47905
|
-
|
|
47906
|
-
|
|
47907
|
-
|
|
47908
|
-
|
|
47909
|
-
|
|
47910
|
-
|
|
47911
|
-
|
|
47912
|
-
|
|
47913
|
-
|
|
47914
|
-
|
|
47915
|
-
|
|
47916
|
-
|
|
47917
|
-
|
|
47918
|
-
|
|
47919
|
-
|
|
47920
|
-
|
|
47921
|
-
|
|
47922
|
-
|
|
47923
|
-
|
|
47924
|
-
|
|
48215
|
+
insert(_el$6, isSelected ? (() => {
|
|
48216
|
+
var _el$7 = createElement("text");
|
|
48217
|
+
insert(_el$7, () => padLine2(fullLine, terminal().columns));
|
|
48218
|
+
effect((_p$) => {
|
|
48219
|
+
var _v$ = selectionStyle.fg, _v$2 = selectionStyle.bg;
|
|
48220
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$7, "fg", _v$, _p$.e));
|
|
48221
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$7, "bg", _v$2, _p$.t));
|
|
48222
|
+
return _p$;
|
|
48223
|
+
}, {
|
|
48224
|
+
e: undefined,
|
|
48225
|
+
t: undefined
|
|
48226
|
+
});
|
|
48227
|
+
return _el$7;
|
|
48228
|
+
})() : [(() => {
|
|
48229
|
+
var _el$8 = createElement("text");
|
|
48230
|
+
insert(_el$8, () => item.label);
|
|
48231
|
+
return _el$8;
|
|
48232
|
+
})(), memo2(() => memo2(() => !!(showDescription && item.description))() ? (() => {
|
|
48233
|
+
var _el$9 = createElement("text");
|
|
48234
|
+
insert(_el$9, () => ` - ${item.description}`);
|
|
48235
|
+
effect((_$p) => setProp(_el$9, "attributes", TextAttributes.DIM, _$p));
|
|
48236
|
+
return _el$9;
|
|
48237
|
+
})() : null)]);
|
|
47925
48238
|
return _el$6;
|
|
47926
48239
|
})();
|
|
47927
48240
|
}));
|
|
@@ -47939,53 +48252,237 @@ function SelectorScreen({
|
|
|
47939
48252
|
}
|
|
47940
48253
|
|
|
47941
48254
|
// src/cli/ui/screens/solid/LogScreen.tsx
|
|
47942
|
-
|
|
47943
|
-
|
|
47944
|
-
|
|
47945
|
-
|
|
47946
|
-
|
|
47947
|
-
|
|
47948
|
-
|
|
47949
|
-
|
|
47950
|
-
|
|
47951
|
-
|
|
47952
|
-
|
|
47953
|
-
|
|
47954
|
-
|
|
48255
|
+
var LEVEL_ORDER = ["ALL", "INFO+", "WARN+", "ERROR+"];
|
|
48256
|
+
var LEVEL_THRESHOLDS = {
|
|
48257
|
+
ALL: 0,
|
|
48258
|
+
"INFO+": 30,
|
|
48259
|
+
"WARN+": 40,
|
|
48260
|
+
"ERROR+": 50
|
|
48261
|
+
};
|
|
48262
|
+
var LEVEL_LABEL_VALUES = {
|
|
48263
|
+
TRACE: 10,
|
|
48264
|
+
DEBUG: 20,
|
|
48265
|
+
INFO: 30,
|
|
48266
|
+
WARN: 40,
|
|
48267
|
+
ERROR: 50,
|
|
48268
|
+
FATAL: 60
|
|
48269
|
+
};
|
|
48270
|
+
var measureWidth2 = (value) => stringWidth(value);
|
|
48271
|
+
var truncateToWidth3 = (value, maxWidth) => {
|
|
48272
|
+
if (maxWidth <= 0) {
|
|
48273
|
+
return "";
|
|
48274
|
+
}
|
|
48275
|
+
if (measureWidth2(value) <= maxWidth) {
|
|
48276
|
+
return value;
|
|
48277
|
+
}
|
|
48278
|
+
const ellipsis = "...";
|
|
48279
|
+
const ellipsisWidth = measureWidth2(ellipsis);
|
|
48280
|
+
if (ellipsisWidth >= maxWidth) {
|
|
48281
|
+
return ellipsis.slice(0, maxWidth);
|
|
48282
|
+
}
|
|
48283
|
+
let currentWidth = 0;
|
|
48284
|
+
let result = "";
|
|
48285
|
+
for (const char of Array.from(value)) {
|
|
48286
|
+
const charWidth = measureWidth2(char);
|
|
48287
|
+
if (currentWidth + charWidth + ellipsisWidth > maxWidth) {
|
|
48288
|
+
break;
|
|
48289
|
+
}
|
|
48290
|
+
result += char;
|
|
48291
|
+
currentWidth += charWidth;
|
|
48292
|
+
}
|
|
48293
|
+
return `${result}${ellipsis}`;
|
|
48294
|
+
};
|
|
48295
|
+
var padToWidth = (value, width) => {
|
|
48296
|
+
if (width <= 0) {
|
|
48297
|
+
return "";
|
|
48298
|
+
}
|
|
48299
|
+
const truncated = truncateToWidth3(value, width);
|
|
48300
|
+
const padding = Math.max(0, width - measureWidth2(truncated));
|
|
48301
|
+
return `${truncated}${" ".repeat(padding)}`;
|
|
48302
|
+
};
|
|
48303
|
+
var appendSegment2 = (segments, segment) => {
|
|
48304
|
+
if (!segment.text) {
|
|
48305
|
+
return;
|
|
48306
|
+
}
|
|
48307
|
+
segments.push(segment);
|
|
48308
|
+
};
|
|
48309
|
+
var measureSegmentsWidth2 = (segments) => segments.reduce((total, segment) => total + measureWidth2(segment.text), 0);
|
|
48310
|
+
var truncateSegmentsToWidth2 = (segments, maxWidth) => {
|
|
48311
|
+
if (maxWidth <= 0) {
|
|
48312
|
+
return [];
|
|
48313
|
+
}
|
|
48314
|
+
const result = [];
|
|
48315
|
+
let currentWidth = 0;
|
|
48316
|
+
for (const segment of segments) {
|
|
48317
|
+
if (currentWidth >= maxWidth) {
|
|
48318
|
+
break;
|
|
48319
|
+
}
|
|
48320
|
+
const segmentWidth = measureWidth2(segment.text);
|
|
48321
|
+
if (currentWidth + segmentWidth <= maxWidth) {
|
|
48322
|
+
result.push(segment);
|
|
48323
|
+
currentWidth += segmentWidth;
|
|
48324
|
+
continue;
|
|
48325
|
+
}
|
|
48326
|
+
const remaining = maxWidth - currentWidth;
|
|
48327
|
+
const truncated = truncateToWidth3(segment.text, remaining);
|
|
48328
|
+
if (truncated) {
|
|
48329
|
+
result.push({
|
|
48330
|
+
...segment,
|
|
48331
|
+
text: truncated
|
|
48332
|
+
});
|
|
48333
|
+
currentWidth += measureWidth2(truncated);
|
|
48334
|
+
}
|
|
48335
|
+
break;
|
|
48336
|
+
}
|
|
48337
|
+
return result;
|
|
48338
|
+
};
|
|
48339
|
+
var segmentsToText = (segments) => segments.map((segment) => segment.text).join("");
|
|
48340
|
+
var padLine3 = (value, width) => {
|
|
48341
|
+
const padding = Math.max(0, width - measureWidth2(value));
|
|
48342
|
+
return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
|
|
48343
|
+
};
|
|
48344
|
+
var resolveEntryLevel = (entry) => {
|
|
48345
|
+
const rawLevel = entry.raw?.level;
|
|
48346
|
+
if (typeof rawLevel === "number") {
|
|
48347
|
+
return rawLevel;
|
|
48348
|
+
}
|
|
48349
|
+
const label = entry.levelLabel?.toUpperCase() ?? "";
|
|
48350
|
+
return LEVEL_LABEL_VALUES[label] ?? 0;
|
|
48351
|
+
};
|
|
48352
|
+
function LogScreen(props) {
|
|
48353
|
+
const merged = mergeProps({
|
|
48354
|
+
loading: false,
|
|
48355
|
+
error: null,
|
|
48356
|
+
branchLabel: null,
|
|
48357
|
+
sourceLabel: null,
|
|
48358
|
+
tailing: false,
|
|
48359
|
+
helpVisible: false
|
|
48360
|
+
}, props);
|
|
47955
48361
|
const terminal = useTerminalSize();
|
|
48362
|
+
const [filterQuery, setFilterQuery] = createSignal("");
|
|
48363
|
+
const [filterMode, setFilterMode] = createSignal(false);
|
|
48364
|
+
const [levelMode, setLevelMode] = createSignal("ALL");
|
|
48365
|
+
const filteredEntries = createMemo(() => {
|
|
48366
|
+
let result = merged.entries;
|
|
48367
|
+
const threshold = LEVEL_THRESHOLDS[levelMode()];
|
|
48368
|
+
if (threshold > 0) {
|
|
48369
|
+
result = result.filter((entry) => resolveEntryLevel(entry) >= threshold);
|
|
48370
|
+
}
|
|
48371
|
+
const query = filterQuery().trim().toLowerCase();
|
|
48372
|
+
if (!query) {
|
|
48373
|
+
return result;
|
|
48374
|
+
}
|
|
48375
|
+
return result.filter((entry) => {
|
|
48376
|
+
const target = `${entry.category} ${entry.levelLabel} ${entry.message}`.toLowerCase();
|
|
48377
|
+
return target.includes(query);
|
|
48378
|
+
});
|
|
48379
|
+
});
|
|
48380
|
+
const totalCount = createMemo(() => merged.entries.length);
|
|
48381
|
+
const filteredCount = createMemo(() => filteredEntries().length);
|
|
48382
|
+
const showFilterCount = createMemo(() => filterMode() || filterQuery().trim().length > 0);
|
|
48383
|
+
const levelWidth = createMemo(() => {
|
|
48384
|
+
const MIN = 5;
|
|
48385
|
+
return Math.max(MIN, ...filteredEntries().map((entry) => measureWidth2(entry.levelLabel)));
|
|
48386
|
+
});
|
|
48387
|
+
const categoryWidth = createMemo(() => {
|
|
48388
|
+
const MIN = 4;
|
|
48389
|
+
const MAX = 20;
|
|
48390
|
+
const maxWidth = Math.max(MIN, ...filteredEntries().map((entry) => measureWidth2(entry.category)));
|
|
48391
|
+
return Math.min(MAX, maxWidth);
|
|
48392
|
+
});
|
|
47956
48393
|
const listHeight = createMemo(() => {
|
|
47957
48394
|
const headerRows = 2;
|
|
47958
|
-
const infoRows =
|
|
48395
|
+
const infoRows = 3;
|
|
47959
48396
|
const footerRows = 1;
|
|
47960
|
-
const notificationRows = notification ? 1 : 0;
|
|
48397
|
+
const notificationRows = merged.notification ? 1 : 0;
|
|
47961
48398
|
const reserved = headerRows + infoRows + footerRows + notificationRows;
|
|
47962
48399
|
return Math.max(1, terminal().rows - reserved);
|
|
47963
48400
|
});
|
|
47964
48401
|
const list = useScrollableList({
|
|
47965
|
-
items:
|
|
48402
|
+
items: filteredEntries,
|
|
47966
48403
|
visibleCount: listHeight
|
|
47967
48404
|
});
|
|
47968
|
-
const currentEntry = createMemo(() =>
|
|
48405
|
+
const currentEntry = createMemo(() => filteredEntries()[list.selectedIndex()]);
|
|
48406
|
+
createEffect(() => {
|
|
48407
|
+
filterQuery();
|
|
48408
|
+
levelMode();
|
|
48409
|
+
list.setSelectedIndex(0);
|
|
48410
|
+
list.setScrollOffset(0);
|
|
48411
|
+
});
|
|
47969
48412
|
const updateSelectedIndex = (value) => {
|
|
47970
48413
|
list.setSelectedIndex(value);
|
|
47971
48414
|
};
|
|
47972
48415
|
useKeyboard((key) => {
|
|
47973
|
-
if (helpVisible) {
|
|
48416
|
+
if (merged.helpVisible) {
|
|
48417
|
+
return;
|
|
48418
|
+
}
|
|
48419
|
+
if (filterMode()) {
|
|
48420
|
+
if (key.name === "down") {
|
|
48421
|
+
updateSelectedIndex((prev) => prev + 1);
|
|
48422
|
+
return;
|
|
48423
|
+
}
|
|
48424
|
+
if (key.name === "up") {
|
|
48425
|
+
updateSelectedIndex((prev) => prev - 1);
|
|
48426
|
+
return;
|
|
48427
|
+
}
|
|
48428
|
+
if (key.name === "escape") {
|
|
48429
|
+
if (filterQuery()) {
|
|
48430
|
+
setFilterQuery("");
|
|
48431
|
+
} else {
|
|
48432
|
+
setFilterMode(false);
|
|
48433
|
+
}
|
|
48434
|
+
return;
|
|
48435
|
+
}
|
|
48436
|
+
if (key.name === "backspace") {
|
|
48437
|
+
setFilterQuery((prev) => prev.slice(0, -1));
|
|
48438
|
+
return;
|
|
48439
|
+
}
|
|
48440
|
+
if (key.name === "return" || key.name === "linefeed") {
|
|
48441
|
+
setFilterMode(false);
|
|
48442
|
+
return;
|
|
48443
|
+
}
|
|
48444
|
+
if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && !key.super && !key.hyper) {
|
|
48445
|
+
setFilterQuery((prev) => prev + key.sequence);
|
|
48446
|
+
}
|
|
47974
48447
|
return;
|
|
47975
48448
|
}
|
|
47976
48449
|
if (key.name === "escape" || key.name === "q") {
|
|
47977
|
-
onBack();
|
|
48450
|
+
merged.onBack();
|
|
47978
48451
|
return;
|
|
47979
48452
|
}
|
|
47980
48453
|
if (key.name === "c") {
|
|
47981
48454
|
const entry = currentEntry();
|
|
47982
48455
|
if (entry) {
|
|
47983
|
-
onCopy(entry);
|
|
48456
|
+
merged.onCopy(entry);
|
|
47984
48457
|
}
|
|
47985
48458
|
return;
|
|
47986
48459
|
}
|
|
47987
48460
|
if (key.name === "d") {
|
|
47988
|
-
onPickDate?.();
|
|
48461
|
+
merged.onPickDate?.();
|
|
48462
|
+
return;
|
|
48463
|
+
}
|
|
48464
|
+
if (key.name === "f") {
|
|
48465
|
+
setFilterMode(true);
|
|
48466
|
+
return;
|
|
48467
|
+
}
|
|
48468
|
+
if (key.name === "v") {
|
|
48469
|
+
setLevelMode((prev) => {
|
|
48470
|
+
const index = LEVEL_ORDER.indexOf(prev);
|
|
48471
|
+
const nextIndex = (index + 1) % LEVEL_ORDER.length;
|
|
48472
|
+
return LEVEL_ORDER[nextIndex] ?? "ALL";
|
|
48473
|
+
});
|
|
48474
|
+
return;
|
|
48475
|
+
}
|
|
48476
|
+
if (key.name === "r") {
|
|
48477
|
+
merged.onReload?.();
|
|
48478
|
+
return;
|
|
48479
|
+
}
|
|
48480
|
+
if (key.name === "t") {
|
|
48481
|
+
merged.onToggleTail?.();
|
|
48482
|
+
return;
|
|
48483
|
+
}
|
|
48484
|
+
if (key.name === "x") {
|
|
48485
|
+
merged.onReset?.();
|
|
47989
48486
|
return;
|
|
47990
48487
|
}
|
|
47991
48488
|
if (key.name === "down") {
|
|
@@ -48009,13 +48506,13 @@ function LogScreen({
|
|
|
48009
48506
|
return;
|
|
48010
48507
|
}
|
|
48011
48508
|
if (key.name === "end") {
|
|
48012
|
-
updateSelectedIndex(
|
|
48509
|
+
updateSelectedIndex(filteredEntries().length - 1);
|
|
48013
48510
|
return;
|
|
48014
48511
|
}
|
|
48015
48512
|
if (key.name === "return" || key.name === "linefeed") {
|
|
48016
48513
|
const entry = currentEntry();
|
|
48017
48514
|
if (entry) {
|
|
48018
|
-
onSelect(entry);
|
|
48515
|
+
merged.onSelect(entry);
|
|
48019
48516
|
}
|
|
48020
48517
|
}
|
|
48021
48518
|
});
|
|
@@ -48029,92 +48526,227 @@ function LogScreen({
|
|
|
48029
48526
|
}, {
|
|
48030
48527
|
key: "d",
|
|
48031
48528
|
description: "Date"
|
|
48529
|
+
}, {
|
|
48530
|
+
key: "f",
|
|
48531
|
+
description: "Filter"
|
|
48532
|
+
}, {
|
|
48533
|
+
key: "v",
|
|
48534
|
+
description: "Level"
|
|
48535
|
+
}, {
|
|
48536
|
+
key: "r",
|
|
48537
|
+
description: "Reload"
|
|
48538
|
+
}, {
|
|
48539
|
+
key: "t",
|
|
48540
|
+
description: "Tail"
|
|
48541
|
+
}, {
|
|
48542
|
+
key: "x",
|
|
48543
|
+
description: "Reset"
|
|
48032
48544
|
}, {
|
|
48033
48545
|
key: "esc",
|
|
48034
48546
|
description: "Back"
|
|
48035
48547
|
}];
|
|
48036
48548
|
return actions;
|
|
48037
48549
|
});
|
|
48550
|
+
const formatEntrySegments = (entry) => {
|
|
48551
|
+
const levelText = padToWidth(entry.levelLabel, levelWidth());
|
|
48552
|
+
const categoryText = padToWidth(entry.category, categoryWidth());
|
|
48553
|
+
const segments = [];
|
|
48554
|
+
appendSegment2(segments, {
|
|
48555
|
+
text: `[${entry.timeLabel}] `
|
|
48556
|
+
});
|
|
48557
|
+
appendSegment2(segments, {
|
|
48558
|
+
text: "["
|
|
48559
|
+
});
|
|
48560
|
+
appendSegment2(segments, {
|
|
48561
|
+
text: levelText,
|
|
48562
|
+
fg: getLogLevelColor(entry.levelLabel)
|
|
48563
|
+
});
|
|
48564
|
+
appendSegment2(segments, {
|
|
48565
|
+
text: "] "
|
|
48566
|
+
});
|
|
48567
|
+
appendSegment2(segments, {
|
|
48568
|
+
text: "["
|
|
48569
|
+
});
|
|
48570
|
+
appendSegment2(segments, {
|
|
48571
|
+
text: categoryText
|
|
48572
|
+
});
|
|
48573
|
+
appendSegment2(segments, {
|
|
48574
|
+
text: "] "
|
|
48575
|
+
});
|
|
48576
|
+
appendSegment2(segments, {
|
|
48577
|
+
text: entry.message
|
|
48578
|
+
});
|
|
48579
|
+
const maxWidth = terminal().columns;
|
|
48580
|
+
if (measureSegmentsWidth2(segments) <= maxWidth) {
|
|
48581
|
+
return segments;
|
|
48582
|
+
}
|
|
48583
|
+
return truncateSegmentsToWidth2(segments, maxWidth);
|
|
48584
|
+
};
|
|
48585
|
+
const filterLabel = createMemo(() => {
|
|
48586
|
+
if (filterQuery()) {
|
|
48587
|
+
return filterQuery();
|
|
48588
|
+
}
|
|
48589
|
+
return filterMode() ? "(type to filter)" : "(press f to filter)";
|
|
48590
|
+
});
|
|
48038
48591
|
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");
|
|
48592
|
+
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
48593
|
insertNode(_el$, _el$2);
|
|
48041
48594
|
insertNode(_el$, _el$9);
|
|
48595
|
+
insertNode(_el$, _el$20);
|
|
48596
|
+
insertNode(_el$, _el$24);
|
|
48042
48597
|
setProp(_el$, "flexDirection", "column");
|
|
48043
48598
|
insert(_el$, createComponent2(Header, {
|
|
48044
48599
|
title: "gwt - Log Viewer",
|
|
48045
48600
|
titleColor: "cyan",
|
|
48046
|
-
version
|
|
48601
|
+
get version() {
|
|
48602
|
+
return merged.version;
|
|
48603
|
+
}
|
|
48047
48604
|
}), _el$2);
|
|
48048
|
-
insert(_el$,
|
|
48049
|
-
var
|
|
48050
|
-
|
|
48051
|
-
|
|
48052
|
-
|
|
48053
|
-
|
|
48605
|
+
insert(_el$, (() => {
|
|
48606
|
+
var _c$ = memo2(() => !!merged.notification);
|
|
48607
|
+
return () => _c$() ? (() => {
|
|
48608
|
+
var _el$25 = createElement("text");
|
|
48609
|
+
insert(_el$25, () => merged.notification.message);
|
|
48610
|
+
effect((_$p) => setProp(_el$25, "fg", merged.notification.tone === "error" ? "red" : "green", _$p));
|
|
48611
|
+
return _el$25;
|
|
48612
|
+
})() : null;
|
|
48613
|
+
})(), _el$2);
|
|
48054
48614
|
insertNode(_el$2, _el$3);
|
|
48055
48615
|
insertNode(_el$2, _el$5);
|
|
48056
48616
|
insertNode(_el$2, _el$6);
|
|
48057
48617
|
insertNode(_el$2, _el$8);
|
|
48058
48618
|
setProp(_el$2, "flexDirection", "row");
|
|
48059
|
-
insertNode(_el$3, createTextNode(`
|
|
48060
|
-
insert(_el$5,
|
|
48061
|
-
insertNode(_el$6, createTextNode(`
|
|
48062
|
-
insert(_el$8, () =>
|
|
48063
|
-
|
|
48064
|
-
|
|
48065
|
-
|
|
48066
|
-
|
|
48067
|
-
|
|
48068
|
-
|
|
48069
|
-
|
|
48070
|
-
|
|
48071
|
-
|
|
48072
|
-
|
|
48073
|
-
|
|
48074
|
-
|
|
48075
|
-
|
|
48076
|
-
|
|
48077
|
-
|
|
48078
|
-
|
|
48079
|
-
|
|
48080
|
-
|
|
48081
|
-
|
|
48082
|
-
|
|
48083
|
-
|
|
48084
|
-
|
|
48085
|
-
|
|
48086
|
-
|
|
48087
|
-
|
|
48088
|
-
|
|
48089
|
-
|
|
48090
|
-
|
|
48091
|
-
|
|
48619
|
+
insertNode(_el$3, createTextNode(`Branch: `));
|
|
48620
|
+
insert(_el$5, () => merged.branchLabel ?? "(none)");
|
|
48621
|
+
insertNode(_el$6, createTextNode(` Source: `));
|
|
48622
|
+
insert(_el$8, () => merged.sourceLabel ?? "(none)");
|
|
48623
|
+
insertNode(_el$9, _el$0);
|
|
48624
|
+
insertNode(_el$9, _el$10);
|
|
48625
|
+
insertNode(_el$9, _el$11);
|
|
48626
|
+
insertNode(_el$9, _el$13);
|
|
48627
|
+
insertNode(_el$9, _el$14);
|
|
48628
|
+
insertNode(_el$9, _el$16);
|
|
48629
|
+
insertNode(_el$9, _el$17);
|
|
48630
|
+
insertNode(_el$9, _el$19);
|
|
48631
|
+
setProp(_el$9, "flexDirection", "row");
|
|
48632
|
+
insertNode(_el$0, createTextNode(`Date: `));
|
|
48633
|
+
insert(_el$10, () => merged.selectedDate ?? "---");
|
|
48634
|
+
insertNode(_el$11, createTextNode(` Total: `));
|
|
48635
|
+
insert(_el$13, totalCount);
|
|
48636
|
+
insertNode(_el$14, createTextNode(` Level: `));
|
|
48637
|
+
insert(_el$16, levelMode);
|
|
48638
|
+
insertNode(_el$17, createTextNode(` Tail: `));
|
|
48639
|
+
insert(_el$19, () => merged.tailing ? "ON" : "OFF");
|
|
48640
|
+
insertNode(_el$20, _el$21);
|
|
48641
|
+
insertNode(_el$20, _el$23);
|
|
48642
|
+
setProp(_el$20, "flexDirection", "row");
|
|
48643
|
+
insertNode(_el$21, createTextNode(`Filter: `));
|
|
48644
|
+
insert(_el$23, filterLabel);
|
|
48645
|
+
insert(_el$20, (() => {
|
|
48646
|
+
var _c$2 = memo2(() => !!showFilterCount());
|
|
48647
|
+
return () => _c$2() ? (() => {
|
|
48648
|
+
var _el$26 = createElement("text");
|
|
48649
|
+
insert(_el$26, () => ` (Showing ${filteredCount()} of ${totalCount()})`);
|
|
48650
|
+
effect((_$p) => setProp(_el$26, "attributes", TextAttributes.DIM, _$p));
|
|
48651
|
+
return _el$26;
|
|
48652
|
+
})() : null;
|
|
48653
|
+
})(), null);
|
|
48654
|
+
setProp(_el$24, "flexDirection", "column");
|
|
48655
|
+
setProp(_el$24, "flexGrow", 1);
|
|
48656
|
+
insert(_el$24, (() => {
|
|
48657
|
+
var _c$3 = memo2(() => !!merged.loading);
|
|
48658
|
+
return () => _c$3() ? (() => {
|
|
48659
|
+
var _el$27 = createElement("text");
|
|
48660
|
+
insertNode(_el$27, createTextNode(`Loading logs...`));
|
|
48661
|
+
setProp(_el$27, "fg", "gray");
|
|
48662
|
+
return _el$27;
|
|
48663
|
+
})() : memo2(() => filteredEntries().length === 0)() ? (() => {
|
|
48664
|
+
var _el$29 = createElement("text");
|
|
48665
|
+
insertNode(_el$29, createTextNode(`No logs available.`));
|
|
48666
|
+
setProp(_el$29, "fg", "gray");
|
|
48667
|
+
return _el$29;
|
|
48668
|
+
})() : (() => {
|
|
48669
|
+
var _el$31 = createElement("box");
|
|
48670
|
+
setProp(_el$31, "flexDirection", "column");
|
|
48671
|
+
insert(_el$31, () => list.visibleItems().map((entry, index) => {
|
|
48672
|
+
const absoluteIndex = list.scrollOffset() + index;
|
|
48673
|
+
const isSelected = absoluteIndex === list.selectedIndex();
|
|
48674
|
+
const segments = formatEntrySegments(entry);
|
|
48675
|
+
const lineText = segmentsToText(segments);
|
|
48676
|
+
const selectedContent = padLine3(lineText, terminal().columns);
|
|
48677
|
+
return (() => {
|
|
48678
|
+
var _el$32 = createElement("text");
|
|
48679
|
+
spread(_el$32, mergeProps3(() => isSelected ? {
|
|
48680
|
+
fg: selectionStyle.fg,
|
|
48681
|
+
bg: selectionStyle.bg
|
|
48682
|
+
} : {}, {
|
|
48683
|
+
wrapMode: "none",
|
|
48684
|
+
get width() {
|
|
48685
|
+
return terminal().columns;
|
|
48686
|
+
}
|
|
48687
|
+
}), true);
|
|
48688
|
+
insert(_el$32, () => isSelected ? selectedContent : segments.map((segment) => segment.fg ? (() => {
|
|
48689
|
+
var _el$33 = createElement("span");
|
|
48690
|
+
insert(_el$33, () => segment.text);
|
|
48691
|
+
effect((_$p) => setProp(_el$33, "style", {
|
|
48692
|
+
fg: segment.fg
|
|
48693
|
+
}, _$p));
|
|
48694
|
+
return _el$33;
|
|
48695
|
+
})() : segment.text));
|
|
48696
|
+
return _el$32;
|
|
48697
|
+
})();
|
|
48698
|
+
}));
|
|
48699
|
+
return _el$31;
|
|
48700
|
+
})();
|
|
48701
|
+
})(), null);
|
|
48702
|
+
insert(_el$24, (() => {
|
|
48703
|
+
var _c$4 = memo2(() => !!merged.error);
|
|
48704
|
+
return () => _c$4() ? (() => {
|
|
48705
|
+
var _el$34 = createElement("text");
|
|
48706
|
+
setProp(_el$34, "fg", "red");
|
|
48707
|
+
insert(_el$34, () => merged.error);
|
|
48708
|
+
return _el$34;
|
|
48709
|
+
})() : null;
|
|
48092
48710
|
})(), 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
48711
|
insert(_el$, createComponent2(Footer, {
|
|
48100
48712
|
get actions() {
|
|
48101
48713
|
return footerActions();
|
|
48102
48714
|
}
|
|
48103
48715
|
}), null);
|
|
48104
48716
|
effect((_p$) => {
|
|
48105
|
-
var _v$ = terminal().rows, _v$2 = TextAttributes.DIM, _v$3 = TextAttributes.BOLD, _v$4 = TextAttributes.DIM, _v$5 = TextAttributes.BOLD;
|
|
48717
|
+
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
48718
|
_v$ !== _p$.e && (_p$.e = setProp(_el$, "height", _v$, _p$.e));
|
|
48107
48719
|
_v$2 !== _p$.t && (_p$.t = setProp(_el$3, "attributes", _v$2, _p$.t));
|
|
48108
48720
|
_v$3 !== _p$.a && (_p$.a = setProp(_el$5, "attributes", _v$3, _p$.a));
|
|
48109
48721
|
_v$4 !== _p$.o && (_p$.o = setProp(_el$6, "attributes", _v$4, _p$.o));
|
|
48110
48722
|
_v$5 !== _p$.i && (_p$.i = setProp(_el$8, "attributes", _v$5, _p$.i));
|
|
48723
|
+
_v$6 !== _p$.n && (_p$.n = setProp(_el$0, "attributes", _v$6, _p$.n));
|
|
48724
|
+
_v$7 !== _p$.s && (_p$.s = setProp(_el$10, "attributes", _v$7, _p$.s));
|
|
48725
|
+
_v$8 !== _p$.h && (_p$.h = setProp(_el$11, "attributes", _v$8, _p$.h));
|
|
48726
|
+
_v$9 !== _p$.r && (_p$.r = setProp(_el$13, "attributes", _v$9, _p$.r));
|
|
48727
|
+
_v$0 !== _p$.d && (_p$.d = setProp(_el$14, "attributes", _v$0, _p$.d));
|
|
48728
|
+
_v$1 !== _p$.l && (_p$.l = setProp(_el$16, "attributes", _v$1, _p$.l));
|
|
48729
|
+
_v$10 !== _p$.u && (_p$.u = setProp(_el$17, "attributes", _v$10, _p$.u));
|
|
48730
|
+
_v$11 !== _p$.c && (_p$.c = setProp(_el$19, "attributes", _v$11, _p$.c));
|
|
48731
|
+
_v$12 !== _p$.w && (_p$.w = setProp(_el$21, "attributes", _v$12, _p$.w));
|
|
48732
|
+
_v$13 !== _p$.m && (_p$.m = setProp(_el$23, "attributes", _v$13, _p$.m));
|
|
48111
48733
|
return _p$;
|
|
48112
48734
|
}, {
|
|
48113
48735
|
e: undefined,
|
|
48114
48736
|
t: undefined,
|
|
48115
48737
|
a: undefined,
|
|
48116
48738
|
o: undefined,
|
|
48117
|
-
i: undefined
|
|
48739
|
+
i: undefined,
|
|
48740
|
+
n: undefined,
|
|
48741
|
+
s: undefined,
|
|
48742
|
+
h: undefined,
|
|
48743
|
+
r: undefined,
|
|
48744
|
+
d: undefined,
|
|
48745
|
+
l: undefined,
|
|
48746
|
+
u: undefined,
|
|
48747
|
+
c: undefined,
|
|
48748
|
+
w: undefined,
|
|
48749
|
+
m: undefined
|
|
48118
48750
|
});
|
|
48119
48751
|
return _el$;
|
|
48120
48752
|
})();
|
|
@@ -48473,9 +49105,16 @@ function ConfirmScreen({
|
|
|
48473
49105
|
yesLabel = "Yes",
|
|
48474
49106
|
noLabel = "No",
|
|
48475
49107
|
defaultNo = false,
|
|
48476
|
-
helpVisible = false
|
|
49108
|
+
helpVisible = false,
|
|
49109
|
+
width
|
|
48477
49110
|
}) {
|
|
48478
49111
|
const [selectedIndex, setSelectedIndex] = createSignal(defaultNo ? 1 : 0);
|
|
49112
|
+
const terminal = useTerminalSize();
|
|
49113
|
+
const contentWidth = () => Math.max(0, width ?? terminal().columns);
|
|
49114
|
+
const padLine4 = (value, width2) => {
|
|
49115
|
+
const padding = Math.max(0, width2 - stringWidth(value));
|
|
49116
|
+
return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
|
|
49117
|
+
};
|
|
48479
49118
|
const confirm = (confirmed) => {
|
|
48480
49119
|
onConfirm(confirmed);
|
|
48481
49120
|
};
|
|
@@ -48502,25 +49141,34 @@ function ConfirmScreen({
|
|
|
48502
49141
|
confirm(selectedIndex() === 0);
|
|
48503
49142
|
}
|
|
48504
49143
|
});
|
|
48505
|
-
const renderOption = (label, isSelected) => (() => {
|
|
49144
|
+
const renderOption = (label, isSelected) => isSelected ? (() => {
|
|
48506
49145
|
var _el$ = createElement("text");
|
|
48507
|
-
|
|
48508
|
-
|
|
48509
|
-
|
|
48510
|
-
|
|
48511
|
-
|
|
49146
|
+
insert(_el$, () => padLine4(label, contentWidth()));
|
|
49147
|
+
effect((_p$) => {
|
|
49148
|
+
var _v$ = selectionStyle.fg, _v$2 = selectionStyle.bg;
|
|
49149
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$, "fg", _v$, _p$.e));
|
|
49150
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$, "bg", _v$2, _p$.t));
|
|
49151
|
+
return _p$;
|
|
49152
|
+
}, {
|
|
49153
|
+
e: undefined,
|
|
49154
|
+
t: undefined
|
|
49155
|
+
});
|
|
48512
49156
|
return _el$;
|
|
49157
|
+
})() : (() => {
|
|
49158
|
+
var _el$2 = createElement("text");
|
|
49159
|
+
insert(_el$2, label);
|
|
49160
|
+
return _el$2;
|
|
48513
49161
|
})();
|
|
48514
49162
|
return (() => {
|
|
48515
|
-
var _el$
|
|
48516
|
-
insertNode(_el$
|
|
48517
|
-
insertNode(_el$
|
|
48518
|
-
setProp(_el$
|
|
48519
|
-
insert(_el$
|
|
48520
|
-
setProp(_el$
|
|
48521
|
-
insert(_el$
|
|
48522
|
-
insert(_el$
|
|
48523
|
-
return _el$
|
|
49163
|
+
var _el$3 = createElement("box"), _el$4 = createElement("text"), _el$5 = createElement("box");
|
|
49164
|
+
insertNode(_el$3, _el$4);
|
|
49165
|
+
insertNode(_el$3, _el$5);
|
|
49166
|
+
setProp(_el$3, "flexDirection", "column");
|
|
49167
|
+
insert(_el$4, message);
|
|
49168
|
+
setProp(_el$5, "flexDirection", "column");
|
|
49169
|
+
insert(_el$5, () => renderOption(yesLabel, selectedIndex() === 0), null);
|
|
49170
|
+
insert(_el$5, () => renderOption(noLabel, selectedIndex() === 1), null);
|
|
49171
|
+
return _el$3;
|
|
48524
49172
|
})();
|
|
48525
49173
|
}
|
|
48526
49174
|
|
|
@@ -48535,6 +49183,10 @@ function EnvironmentScreen({
|
|
|
48535
49183
|
helpVisible = false
|
|
48536
49184
|
}) {
|
|
48537
49185
|
const terminal = useTerminalSize();
|
|
49186
|
+
const padLine4 = (value, width) => {
|
|
49187
|
+
const padding = Math.max(0, width - stringWidth(value));
|
|
49188
|
+
return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
|
|
49189
|
+
};
|
|
48538
49190
|
const listHeight = createMemo(() => {
|
|
48539
49191
|
const headerRows = 2;
|
|
48540
49192
|
const footerRows = 1;
|
|
@@ -48630,27 +49282,36 @@ function EnvironmentScreen({
|
|
|
48630
49282
|
const absoluteIndex = list.scrollOffset() + index;
|
|
48631
49283
|
const isSelected = absoluteIndex === list.selectedIndex();
|
|
48632
49284
|
const isHighlighted = highlightSet().has(variable.key);
|
|
48633
|
-
const
|
|
48634
|
-
const keyColor = isSelected ? "cyan" : isHighlighted ? "yellow" : undefined;
|
|
48635
|
-
const valueColor = isSelected ? "cyan" : undefined;
|
|
49285
|
+
const keyColor = isHighlighted ? "yellow" : undefined;
|
|
48636
49286
|
return (() => {
|
|
48637
|
-
var _el$6 = createElement("box")
|
|
48638
|
-
insertNode(_el$6, _el$7);
|
|
48639
|
-
insertNode(_el$6, _el$8);
|
|
49287
|
+
var _el$6 = createElement("box");
|
|
48640
49288
|
setProp(_el$6, "flexDirection", "row");
|
|
48641
|
-
|
|
48642
|
-
|
|
48643
|
-
|
|
48644
|
-
|
|
48645
|
-
|
|
48646
|
-
|
|
48647
|
-
|
|
48648
|
-
|
|
48649
|
-
|
|
48650
|
-
|
|
48651
|
-
|
|
48652
|
-
|
|
48653
|
-
|
|
49289
|
+
insert(_el$6, isSelected ? (() => {
|
|
49290
|
+
var _el$7 = createElement("text");
|
|
49291
|
+
insert(_el$7, () => padLine4(`${variable.key}=${variable.value}`, terminal().columns));
|
|
49292
|
+
effect((_p$) => {
|
|
49293
|
+
var _v$ = selectionStyle.fg, _v$2 = selectionStyle.bg;
|
|
49294
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$7, "fg", _v$, _p$.e));
|
|
49295
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$7, "bg", _v$2, _p$.t));
|
|
49296
|
+
return _p$;
|
|
49297
|
+
}, {
|
|
49298
|
+
e: undefined,
|
|
49299
|
+
t: undefined
|
|
49300
|
+
});
|
|
49301
|
+
return _el$7;
|
|
49302
|
+
})() : [(() => {
|
|
49303
|
+
var _el$8 = createElement("text");
|
|
49304
|
+
spread(_el$8, keyColor ? {
|
|
49305
|
+
fg: keyColor
|
|
49306
|
+
} : {}, true);
|
|
49307
|
+
insert(_el$8, () => variable.key);
|
|
49308
|
+
return _el$8;
|
|
49309
|
+
})(), (() => {
|
|
49310
|
+
var _el$9 = createElement("text"), _el$0 = createTextNode(`=`);
|
|
49311
|
+
insertNode(_el$9, _el$0);
|
|
49312
|
+
insert(_el$9, () => variable.value, null);
|
|
49313
|
+
return _el$9;
|
|
49314
|
+
})()]);
|
|
48654
49315
|
return _el$6;
|
|
48655
49316
|
})();
|
|
48656
49317
|
}));
|
|
@@ -48752,6 +49413,10 @@ function ProfileEnvScreen({
|
|
|
48752
49413
|
helpVisible = false
|
|
48753
49414
|
}) {
|
|
48754
49415
|
const terminal = useTerminalSize();
|
|
49416
|
+
const padLine4 = (value, width) => {
|
|
49417
|
+
const padding = Math.max(0, width - stringWidth(value));
|
|
49418
|
+
return padding > 0 ? `${value}${" ".repeat(padding)}` : value;
|
|
49419
|
+
};
|
|
48755
49420
|
const listHeight = createMemo(() => {
|
|
48756
49421
|
const headerRows = 2;
|
|
48757
49422
|
const footerRows = 1;
|
|
@@ -48882,26 +49547,32 @@ function ProfileEnvScreen({
|
|
|
48882
49547
|
insert(_el$5, () => list.visibleItems().map((variable, index) => {
|
|
48883
49548
|
const absoluteIndex = list.scrollOffset() + index;
|
|
48884
49549
|
const isSelected = absoluteIndex === list.selectedIndex();
|
|
48885
|
-
const attributes = isSelected ? TextAttributes.BOLD : undefined;
|
|
48886
|
-
const color = isSelected ? "cyan" : undefined;
|
|
48887
49550
|
return (() => {
|
|
48888
|
-
var _el$6 = createElement("box")
|
|
48889
|
-
insertNode(_el$6, _el$7);
|
|
48890
|
-
insertNode(_el$6, _el$8);
|
|
49551
|
+
var _el$6 = createElement("box");
|
|
48891
49552
|
setProp(_el$6, "flexDirection", "row");
|
|
48892
|
-
|
|
48893
|
-
|
|
48894
|
-
|
|
48895
|
-
|
|
48896
|
-
|
|
48897
|
-
|
|
48898
|
-
|
|
48899
|
-
|
|
48900
|
-
|
|
48901
|
-
|
|
48902
|
-
|
|
48903
|
-
|
|
48904
|
-
|
|
49553
|
+
insert(_el$6, isSelected ? (() => {
|
|
49554
|
+
var _el$7 = createElement("text");
|
|
49555
|
+
insert(_el$7, () => padLine4(`${variable.key}=${variable.value}`, terminal().columns));
|
|
49556
|
+
effect((_p$) => {
|
|
49557
|
+
var _v$ = selectionStyle.fg, _v$2 = selectionStyle.bg;
|
|
49558
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$7, "fg", _v$, _p$.e));
|
|
49559
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$7, "bg", _v$2, _p$.t));
|
|
49560
|
+
return _p$;
|
|
49561
|
+
}, {
|
|
49562
|
+
e: undefined,
|
|
49563
|
+
t: undefined
|
|
49564
|
+
});
|
|
49565
|
+
return _el$7;
|
|
49566
|
+
})() : [(() => {
|
|
49567
|
+
var _el$8 = createElement("text");
|
|
49568
|
+
insert(_el$8, () => variable.key);
|
|
49569
|
+
return _el$8;
|
|
49570
|
+
})(), (() => {
|
|
49571
|
+
var _el$9 = createElement("text"), _el$0 = createTextNode(`=`);
|
|
49572
|
+
insertNode(_el$9, _el$0);
|
|
49573
|
+
insert(_el$9, () => variable.value, null);
|
|
49574
|
+
return _el$9;
|
|
49575
|
+
})()]);
|
|
48905
49576
|
return _el$6;
|
|
48906
49577
|
})();
|
|
48907
49578
|
}));
|
|
@@ -49000,7 +49671,8 @@ function createLogger(config = {}) {
|
|
|
49000
49671
|
if (config.sync) {
|
|
49001
49672
|
const destinationStream2 = import_pino.default.destination({
|
|
49002
49673
|
dest: destination,
|
|
49003
|
-
sync: true
|
|
49674
|
+
sync: true,
|
|
49675
|
+
append: true
|
|
49004
49676
|
});
|
|
49005
49677
|
return import_pino.default(options, destinationStream2);
|
|
49006
49678
|
}
|
|
@@ -49024,7 +49696,8 @@ function createLogger(config = {}) {
|
|
|
49024
49696
|
}
|
|
49025
49697
|
const destinationStream = import_pino.default.destination({
|
|
49026
49698
|
dest: destination,
|
|
49027
|
-
sync: false
|
|
49699
|
+
sync: false,
|
|
49700
|
+
append: true
|
|
49028
49701
|
});
|
|
49029
49702
|
return import_pino.default(options, destinationStream);
|
|
49030
49703
|
}
|
|
@@ -49819,6 +50492,9 @@ async function listWorktrees() {
|
|
|
49819
50492
|
throw new WorktreeError("Failed to list worktrees", error);
|
|
49820
50493
|
}
|
|
49821
50494
|
}
|
|
50495
|
+
async function listAllWorktrees() {
|
|
50496
|
+
return listWorktrees();
|
|
50497
|
+
}
|
|
49822
50498
|
async function listAdditionalWorktrees() {
|
|
49823
50499
|
try {
|
|
49824
50500
|
const [allWorktrees, repoRoot] = await Promise.all([
|
|
@@ -49962,7 +50638,8 @@ async function getWorktreesWithPRStatus() {
|
|
|
49962
50638
|
}
|
|
49963
50639
|
async function getOrphanedLocalBranchStatuses({
|
|
49964
50640
|
baseBranch,
|
|
49965
|
-
repoRoot
|
|
50641
|
+
repoRoot,
|
|
50642
|
+
onProgress
|
|
49966
50643
|
}) {
|
|
49967
50644
|
try {
|
|
49968
50645
|
const [localBranches, worktrees] = await Promise.all([
|
|
@@ -49991,8 +50668,7 @@ async function getOrphanedLocalBranchStatuses({
|
|
|
49991
50668
|
hasUnpushed = true;
|
|
49992
50669
|
}
|
|
49993
50670
|
const { upstream, hasUpstream } = await resolveUpstreamStatus(localBranch.name, repoRoot);
|
|
49994
|
-
const
|
|
49995
|
-
const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(localBranch.name, comparisonBase, repoRoot);
|
|
50671
|
+
const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(localBranch.name, baseBranch, repoRoot);
|
|
49996
50672
|
const reasons = buildCleanupReasons({
|
|
49997
50673
|
hasUniqueCommits,
|
|
49998
50674
|
hasUncommitted: false,
|
|
@@ -50002,7 +50678,7 @@ async function getOrphanedLocalBranchStatuses({
|
|
|
50002
50678
|
if (process.env.DEBUG_CLEANUP) {
|
|
50003
50679
|
console.log(source_default.gray(`Debug: Checking orphaned branch ${localBranch.name} -> reasons: ${reasons.join(", ")}`));
|
|
50004
50680
|
}
|
|
50005
|
-
|
|
50681
|
+
const status = {
|
|
50006
50682
|
worktreePath: null,
|
|
50007
50683
|
branch: localBranch.name,
|
|
50008
50684
|
hasUncommittedChanges: false,
|
|
@@ -50013,7 +50689,9 @@ async function getOrphanedLocalBranchStatuses({
|
|
|
50013
50689
|
hasUpstream,
|
|
50014
50690
|
upstream,
|
|
50015
50691
|
reasons
|
|
50016
|
-
}
|
|
50692
|
+
};
|
|
50693
|
+
statuses.push(status);
|
|
50694
|
+
onProgress?.(status);
|
|
50017
50695
|
}
|
|
50018
50696
|
}
|
|
50019
50697
|
if (process.env.DEBUG_CLEANUP) {
|
|
@@ -50028,7 +50706,9 @@ async function getOrphanedLocalBranchStatuses({
|
|
|
50028
50706
|
return [];
|
|
50029
50707
|
}
|
|
50030
50708
|
}
|
|
50031
|
-
async function getCleanupStatus(
|
|
50709
|
+
async function getCleanupStatus({
|
|
50710
|
+
onProgress
|
|
50711
|
+
} = {}) {
|
|
50032
50712
|
const [config, repoRoot, worktreesWithPR] = await Promise.all([
|
|
50033
50713
|
getConfig(),
|
|
50034
50714
|
getRepositoryRoot(),
|
|
@@ -50037,7 +50717,8 @@ async function getCleanupStatus() {
|
|
|
50037
50717
|
const baseBranch = config.defaultBaseBranch || GIT_CONFIG.DEFAULT_BASE_BRANCH;
|
|
50038
50718
|
const orphanedStatuses = await getOrphanedLocalBranchStatuses({
|
|
50039
50719
|
baseBranch,
|
|
50040
|
-
repoRoot
|
|
50720
|
+
repoRoot,
|
|
50721
|
+
...onProgress ? { onProgress } : {}
|
|
50041
50722
|
});
|
|
50042
50723
|
const statuses = [];
|
|
50043
50724
|
if (process.env.DEBUG_CLEANUP) {
|
|
@@ -50066,8 +50747,7 @@ async function getCleanupStatus() {
|
|
|
50066
50747
|
}
|
|
50067
50748
|
}
|
|
50068
50749
|
const { upstream, hasUpstream } = await resolveUpstreamStatus(worktree.branch, repoRoot);
|
|
50069
|
-
const
|
|
50070
|
-
const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(worktree.branch, comparisonBase, repoRoot);
|
|
50750
|
+
const hasUniqueCommits = await branchHasUniqueCommitsComparedToBase(worktree.branch, baseBranch, repoRoot);
|
|
50071
50751
|
const reasons = buildCleanupReasons({
|
|
50072
50752
|
hasUniqueCommits,
|
|
50073
50753
|
hasUncommitted,
|
|
@@ -50077,7 +50757,7 @@ async function getCleanupStatus() {
|
|
|
50077
50757
|
if (process.env.DEBUG_CLEANUP) {
|
|
50078
50758
|
console.log(source_default.gray(`Debug: Cleanup reasons for ${worktree.branch}: ${reasons.length > 0 ? reasons.join(", ") : "none"}`));
|
|
50079
50759
|
}
|
|
50080
|
-
|
|
50760
|
+
const status = {
|
|
50081
50761
|
worktreePath: worktree.worktreePath,
|
|
50082
50762
|
branch: worktree.branch,
|
|
50083
50763
|
hasUncommittedChanges: hasUncommitted,
|
|
@@ -50090,7 +50770,9 @@ async function getCleanupStatus() {
|
|
|
50090
50770
|
isAccessible,
|
|
50091
50771
|
reasons,
|
|
50092
50772
|
...isAccessible ? {} : { invalidReason: "Path not accessible in current environment" }
|
|
50093
|
-
}
|
|
50773
|
+
};
|
|
50774
|
+
statuses.push(status);
|
|
50775
|
+
onProgress?.(status);
|
|
50094
50776
|
}
|
|
50095
50777
|
statuses.push(...orphanedStatuses);
|
|
50096
50778
|
if (process.env.DEBUG_CLEANUP) {
|
|
@@ -50101,22 +50783,643 @@ async function getCleanupStatus() {
|
|
|
50101
50783
|
return statuses;
|
|
50102
50784
|
}
|
|
50103
50785
|
|
|
50104
|
-
// src/
|
|
50105
|
-
import
|
|
50786
|
+
// src/utils/session/common.ts
|
|
50787
|
+
import path14 from "path";
|
|
50788
|
+
import { readdir, readFile as readFile2, stat } from "fs/promises";
|
|
50789
|
+
var UUID_REGEX = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
|
|
50790
|
+
function isValidUuidSessionId(id) {
|
|
50791
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
|
|
50792
|
+
}
|
|
50793
|
+
function pickSessionIdFromObject(obj) {
|
|
50794
|
+
if (!obj || typeof obj !== "object")
|
|
50795
|
+
return null;
|
|
50796
|
+
const candidate = obj;
|
|
50797
|
+
const keys = ["sessionId", "session_id", "id", "conversation_id"];
|
|
50798
|
+
for (const key of keys) {
|
|
50799
|
+
const value = candidate[key];
|
|
50800
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
50801
|
+
const trimmed = value.trim();
|
|
50802
|
+
if (isValidUuidSessionId(trimmed)) {
|
|
50803
|
+
return trimmed;
|
|
50804
|
+
}
|
|
50805
|
+
}
|
|
50806
|
+
}
|
|
50807
|
+
return null;
|
|
50808
|
+
}
|
|
50809
|
+
function pickCwdFromObject(obj) {
|
|
50810
|
+
if (!obj || typeof obj !== "object")
|
|
50811
|
+
return null;
|
|
50812
|
+
const candidate = obj;
|
|
50813
|
+
const keys = [
|
|
50814
|
+
"cwd",
|
|
50815
|
+
"workingDirectory",
|
|
50816
|
+
"workdir",
|
|
50817
|
+
"directory",
|
|
50818
|
+
"projectPath"
|
|
50819
|
+
];
|
|
50820
|
+
for (const key of keys) {
|
|
50821
|
+
const value = candidate[key];
|
|
50822
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
50823
|
+
return value;
|
|
50824
|
+
}
|
|
50825
|
+
}
|
|
50826
|
+
const payload = candidate["payload"];
|
|
50827
|
+
if (payload && typeof payload === "object") {
|
|
50828
|
+
const nested = pickCwdFromObject(payload);
|
|
50829
|
+
if (nested)
|
|
50830
|
+
return nested;
|
|
50831
|
+
}
|
|
50832
|
+
return null;
|
|
50833
|
+
}
|
|
50834
|
+
function pickSessionIdFromText(content) {
|
|
50835
|
+
try {
|
|
50836
|
+
const parsed = JSON.parse(content);
|
|
50837
|
+
const fromObject = pickSessionIdFromObject(parsed);
|
|
50838
|
+
if (fromObject)
|
|
50839
|
+
return fromObject;
|
|
50840
|
+
} catch {}
|
|
50841
|
+
const lines = content.split(/\r?\n/);
|
|
50842
|
+
for (const line of lines) {
|
|
50843
|
+
const trimmed = line.trim();
|
|
50844
|
+
if (!trimmed)
|
|
50845
|
+
continue;
|
|
50846
|
+
try {
|
|
50847
|
+
const parsedLine = JSON.parse(trimmed);
|
|
50848
|
+
const fromLine = pickSessionIdFromObject(parsedLine);
|
|
50849
|
+
if (fromLine)
|
|
50850
|
+
return fromLine;
|
|
50851
|
+
} catch {}
|
|
50852
|
+
const match2 = trimmed.match(UUID_REGEX);
|
|
50853
|
+
if (match2)
|
|
50854
|
+
return match2[0];
|
|
50855
|
+
}
|
|
50856
|
+
const match = content.match(UUID_REGEX);
|
|
50857
|
+
return match ? match[0] : null;
|
|
50858
|
+
}
|
|
50859
|
+
async function collectFilesIterative(dir, filter) {
|
|
50860
|
+
const results = [];
|
|
50861
|
+
const queue = [dir];
|
|
50862
|
+
while (queue.length > 0) {
|
|
50863
|
+
const currentDir = queue.shift();
|
|
50864
|
+
if (!currentDir)
|
|
50865
|
+
break;
|
|
50866
|
+
try {
|
|
50867
|
+
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
50868
|
+
for (const entry of entries) {
|
|
50869
|
+
const fullPath = path14.join(currentDir, entry.name);
|
|
50870
|
+
if (entry.isDirectory()) {
|
|
50871
|
+
queue.push(fullPath);
|
|
50872
|
+
} else if (entry.isFile() && filter(entry.name)) {
|
|
50873
|
+
try {
|
|
50874
|
+
const info = await stat(fullPath);
|
|
50875
|
+
results.push({ fullPath, mtime: info.mtimeMs });
|
|
50876
|
+
} catch {}
|
|
50877
|
+
}
|
|
50878
|
+
}
|
|
50879
|
+
} catch {}
|
|
50880
|
+
}
|
|
50881
|
+
return results;
|
|
50882
|
+
}
|
|
50883
|
+
async function readSessionIdFromFile(filePath) {
|
|
50884
|
+
try {
|
|
50885
|
+
const basename2 = path14.basename(filePath);
|
|
50886
|
+
const filenameWithoutExt = basename2.replace(/\.(json|jsonl)$/i, "");
|
|
50887
|
+
if (isValidUuidSessionId(filenameWithoutExt)) {
|
|
50888
|
+
return filenameWithoutExt;
|
|
50889
|
+
}
|
|
50890
|
+
const content = await readFile2(filePath, "utf-8");
|
|
50891
|
+
const fromContent = pickSessionIdFromText(content);
|
|
50892
|
+
if (fromContent)
|
|
50893
|
+
return fromContent;
|
|
50894
|
+
const filenameMatch = basename2.match(UUID_REGEX);
|
|
50895
|
+
return filenameMatch ? filenameMatch[0] : null;
|
|
50896
|
+
} catch {
|
|
50897
|
+
return null;
|
|
50898
|
+
}
|
|
50899
|
+
}
|
|
50900
|
+
async function readSessionInfoFromFile(filePath) {
|
|
50901
|
+
try {
|
|
50902
|
+
const content = await readFile2(filePath, "utf-8");
|
|
50903
|
+
try {
|
|
50904
|
+
const parsed = JSON.parse(content);
|
|
50905
|
+
const id = pickSessionIdFromObject(parsed);
|
|
50906
|
+
const cwd = pickCwdFromObject(parsed);
|
|
50907
|
+
if (id || cwd)
|
|
50908
|
+
return { id, cwd };
|
|
50909
|
+
} catch {}
|
|
50910
|
+
const lines = content.split(/\r?\n/);
|
|
50911
|
+
for (const line of lines) {
|
|
50912
|
+
const trimmed = line.trim();
|
|
50913
|
+
if (!trimmed)
|
|
50914
|
+
continue;
|
|
50915
|
+
try {
|
|
50916
|
+
const parsedLine = JSON.parse(trimmed);
|
|
50917
|
+
const id = pickSessionIdFromObject(parsedLine);
|
|
50918
|
+
const cwd = pickCwdFromObject(parsedLine);
|
|
50919
|
+
if (id || cwd)
|
|
50920
|
+
return { id, cwd };
|
|
50921
|
+
} catch {}
|
|
50922
|
+
}
|
|
50923
|
+
const filenameMatch = path14.basename(filePath).match(UUID_REGEX);
|
|
50924
|
+
if (filenameMatch)
|
|
50925
|
+
return { id: filenameMatch[0], cwd: null };
|
|
50926
|
+
} catch {}
|
|
50927
|
+
return { id: null, cwd: null };
|
|
50928
|
+
}
|
|
50929
|
+
async function findNewestSessionIdFromDir(dir, recursive, options = {}) {
|
|
50930
|
+
try {
|
|
50931
|
+
const files = [];
|
|
50932
|
+
const queue = [dir];
|
|
50933
|
+
while (queue.length > 0) {
|
|
50934
|
+
const currentDir = queue.shift();
|
|
50935
|
+
if (!currentDir)
|
|
50936
|
+
break;
|
|
50937
|
+
try {
|
|
50938
|
+
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
50939
|
+
for (const entry of entries) {
|
|
50940
|
+
const fullPath = path14.join(currentDir, entry.name);
|
|
50941
|
+
if (entry.isDirectory()) {
|
|
50942
|
+
if (recursive) {
|
|
50943
|
+
queue.push(fullPath);
|
|
50944
|
+
}
|
|
50945
|
+
continue;
|
|
50946
|
+
}
|
|
50947
|
+
if (!entry.isFile())
|
|
50948
|
+
continue;
|
|
50949
|
+
if (!entry.name.endsWith(".json") && !entry.name.endsWith(".jsonl"))
|
|
50950
|
+
continue;
|
|
50951
|
+
try {
|
|
50952
|
+
const info = await stat(fullPath);
|
|
50953
|
+
files.push({ fullPath, mtime: info.mtimeMs });
|
|
50954
|
+
} catch {}
|
|
50955
|
+
}
|
|
50956
|
+
} catch {}
|
|
50957
|
+
}
|
|
50958
|
+
const filtered = files.filter((f) => {
|
|
50959
|
+
if (options.since !== undefined && f.mtime < options.since)
|
|
50960
|
+
return false;
|
|
50961
|
+
if (options.until !== undefined && f.mtime > options.until)
|
|
50962
|
+
return false;
|
|
50963
|
+
return true;
|
|
50964
|
+
});
|
|
50965
|
+
if (!filtered.length)
|
|
50966
|
+
return null;
|
|
50967
|
+
let pool = filtered.sort((a2, b) => b.mtime - a2.mtime);
|
|
50968
|
+
const ref = options.preferClosestTo;
|
|
50969
|
+
if (typeof ref === "number") {
|
|
50970
|
+
const window = options.windowMs ?? 30 * 60 * 1000;
|
|
50971
|
+
const withinWindow = pool.filter((f) => Math.abs(f.mtime - ref) <= window);
|
|
50972
|
+
if (withinWindow.length) {
|
|
50973
|
+
pool = withinWindow.sort((a2, b) => b.mtime - a2.mtime);
|
|
50974
|
+
}
|
|
50975
|
+
}
|
|
50976
|
+
for (const file of pool) {
|
|
50977
|
+
const id = await readSessionIdFromFile(file.fullPath);
|
|
50978
|
+
if (id)
|
|
50979
|
+
return { id, mtime: file.mtime };
|
|
50980
|
+
}
|
|
50981
|
+
} catch {}
|
|
50982
|
+
return null;
|
|
50983
|
+
}
|
|
50984
|
+
async function readFileContent(filePath) {
|
|
50985
|
+
return readFile2(filePath, "utf-8");
|
|
50986
|
+
}
|
|
50987
|
+
async function checkFileStat(filePath) {
|
|
50988
|
+
try {
|
|
50989
|
+
const info = await stat(filePath);
|
|
50990
|
+
return { mtimeMs: info.mtimeMs };
|
|
50991
|
+
} catch {
|
|
50992
|
+
return null;
|
|
50993
|
+
}
|
|
50994
|
+
}
|
|
50995
|
+
function normalizePath(p) {
|
|
50996
|
+
return path14.normalize(p).replace(/\\/g, "/");
|
|
50997
|
+
}
|
|
50998
|
+
function isPathPrefix(prefix, full) {
|
|
50999
|
+
if (!full.startsWith(prefix))
|
|
51000
|
+
return false;
|
|
51001
|
+
if (full.length === prefix.length)
|
|
51002
|
+
return true;
|
|
51003
|
+
return full[prefix.length] === "/";
|
|
51004
|
+
}
|
|
51005
|
+
function matchesCwd(sessionCwd, targetCwd) {
|
|
51006
|
+
if (!sessionCwd)
|
|
51007
|
+
return false;
|
|
51008
|
+
const normalizedSession = normalizePath(sessionCwd);
|
|
51009
|
+
const normalizedTarget = normalizePath(targetCwd);
|
|
51010
|
+
return normalizedSession === normalizedTarget || isPathPrefix(normalizedTarget, normalizedSession) || isPathPrefix(normalizedSession, normalizedTarget);
|
|
51011
|
+
}
|
|
51012
|
+
function resolveBranchFromCwd(sessionCwd, worktrees) {
|
|
51013
|
+
if (!sessionCwd)
|
|
51014
|
+
return null;
|
|
51015
|
+
const normalizedSession = normalizePath(sessionCwd);
|
|
51016
|
+
let bestMatch = null;
|
|
51017
|
+
for (const worktree of worktrees) {
|
|
51018
|
+
if (!worktree?.path || !worktree.branch)
|
|
51019
|
+
continue;
|
|
51020
|
+
const normalizedPath = normalizePath(worktree.path);
|
|
51021
|
+
if (normalizedSession === normalizedPath || isPathPrefix(normalizedPath, normalizedSession)) {
|
|
51022
|
+
if (!bestMatch || normalizedPath.length > bestMatch.path.length) {
|
|
51023
|
+
bestMatch = { branch: worktree.branch, path: normalizedPath };
|
|
51024
|
+
}
|
|
51025
|
+
}
|
|
51026
|
+
}
|
|
51027
|
+
return bestMatch?.branch ?? null;
|
|
51028
|
+
}
|
|
51029
|
+
// src/utils/session/parsers/claude.ts
|
|
50106
51030
|
import path15 from "path";
|
|
50107
|
-
import {
|
|
51031
|
+
import { homedir as homedir3 } from "os";
|
|
51032
|
+
function encodeClaudeProjectPath(cwd) {
|
|
51033
|
+
const normalized = cwd.replace(/\\/g, "/").replace(/:/g, "");
|
|
51034
|
+
return normalized.replace(/_/g, "-").replace(/\//g, "-");
|
|
51035
|
+
}
|
|
51036
|
+
function generateClaudeProjectPathCandidates(cwd) {
|
|
51037
|
+
const base2 = encodeClaudeProjectPath(cwd);
|
|
51038
|
+
const dotToDash = cwd.replace(/\\/g, "/").replace(/:/g, "").replace(/\./g, "-").replace(/_/g, "-").replace(/\//g, "-");
|
|
51039
|
+
const collapsed = dotToDash.replace(/-+/g, "-");
|
|
51040
|
+
const candidates = [base2, dotToDash, collapsed];
|
|
51041
|
+
return Array.from(new Set(candidates));
|
|
51042
|
+
}
|
|
51043
|
+
function getClaudeRootCandidates() {
|
|
51044
|
+
const roots = [];
|
|
51045
|
+
if (process.env.CLAUDE_CONFIG_DIR) {
|
|
51046
|
+
roots.push(process.env.CLAUDE_CONFIG_DIR);
|
|
51047
|
+
}
|
|
51048
|
+
roots.push(path15.join(homedir3(), ".claude"), path15.join(homedir3(), ".config", "claude"));
|
|
51049
|
+
return roots;
|
|
51050
|
+
}
|
|
51051
|
+
async function findLatestClaudeSession(cwd, options = {}) {
|
|
51052
|
+
const rootCandidates = getClaudeRootCandidates();
|
|
51053
|
+
const branchFilter = typeof options.branch === "string" && options.branch.trim().length > 0 ? options.branch.trim() : null;
|
|
51054
|
+
let cwdCandidates = [];
|
|
51055
|
+
if (branchFilter) {
|
|
51056
|
+
let worktrees = [];
|
|
51057
|
+
if (Array.isArray(options.worktrees) && options.worktrees.length > 0) {
|
|
51058
|
+
worktrees = options.worktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
|
|
51059
|
+
} else {
|
|
51060
|
+
try {
|
|
51061
|
+
const allWorktrees = await listAllWorktrees();
|
|
51062
|
+
worktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
|
|
51063
|
+
} catch {
|
|
51064
|
+
worktrees = [];
|
|
51065
|
+
}
|
|
51066
|
+
}
|
|
51067
|
+
const matches = worktrees.filter((entry) => entry.branch === branchFilter).map((entry) => entry.path);
|
|
51068
|
+
if (!matches.length)
|
|
51069
|
+
return null;
|
|
51070
|
+
cwdCandidates = matches;
|
|
51071
|
+
} else {
|
|
51072
|
+
const baseCwd = options.cwd ?? cwd;
|
|
51073
|
+
if (!baseCwd)
|
|
51074
|
+
return null;
|
|
51075
|
+
cwdCandidates = [baseCwd];
|
|
51076
|
+
}
|
|
51077
|
+
const uniqueCwds = Array.from(new Set(cwdCandidates));
|
|
51078
|
+
for (const candidateCwd of uniqueCwds) {
|
|
51079
|
+
const encodedPaths = generateClaudeProjectPathCandidates(candidateCwd);
|
|
51080
|
+
for (const claudeRoot of rootCandidates) {
|
|
51081
|
+
for (const encoded of encodedPaths) {
|
|
51082
|
+
const projectDir = path15.join(claudeRoot, "projects", encoded);
|
|
51083
|
+
const sessionsDir = path15.join(projectDir, "sessions");
|
|
51084
|
+
const session = await findNewestSessionIdFromDir(sessionsDir, false, options);
|
|
51085
|
+
if (session)
|
|
51086
|
+
return session;
|
|
51087
|
+
const rootSession = await findNewestSessionIdFromDir(projectDir, true, options);
|
|
51088
|
+
if (rootSession)
|
|
51089
|
+
return rootSession;
|
|
51090
|
+
}
|
|
51091
|
+
}
|
|
51092
|
+
}
|
|
51093
|
+
try {
|
|
51094
|
+
const historyPath = path15.join(homedir3(), ".claude", "history.jsonl");
|
|
51095
|
+
const historyStat = await checkFileStat(historyPath);
|
|
51096
|
+
if (!historyStat)
|
|
51097
|
+
return null;
|
|
51098
|
+
const content = await readFileContent(historyPath);
|
|
51099
|
+
const lines = content.split(/\r?\n/).filter(Boolean);
|
|
51100
|
+
for (let i2 = lines.length - 1;i2 >= 0; i2 -= 1) {
|
|
51101
|
+
try {
|
|
51102
|
+
const line = lines[i2] ?? "";
|
|
51103
|
+
const parsed = JSON.parse(line);
|
|
51104
|
+
const project = typeof parsed.project === "string" ? parsed.project : null;
|
|
51105
|
+
const sessionId = typeof parsed.sessionId === "string" ? parsed.sessionId : null;
|
|
51106
|
+
const matchesProject = uniqueCwds.some((candidate) => matchesCwd(project, candidate));
|
|
51107
|
+
if (project && sessionId && matchesProject) {
|
|
51108
|
+
return { id: sessionId, mtime: historyStat.mtimeMs };
|
|
51109
|
+
}
|
|
51110
|
+
} catch {}
|
|
51111
|
+
}
|
|
51112
|
+
} catch {}
|
|
51113
|
+
return null;
|
|
51114
|
+
}
|
|
51115
|
+
// src/utils/session/parsers/codex.ts
|
|
51116
|
+
import path16 from "path";
|
|
51117
|
+
import { homedir as homedir4 } from "os";
|
|
51118
|
+
async function findLatestCodexSession(options = {}) {
|
|
51119
|
+
const codexHome = process.env.CODEX_HOME ?? path16.join(homedir4(), ".codex");
|
|
51120
|
+
const baseDir = path16.join(codexHome, "sessions");
|
|
51121
|
+
const candidates = await collectFilesIterative(baseDir, (name) => name.endsWith(".json") || name.endsWith(".jsonl"));
|
|
51122
|
+
if (!candidates.length)
|
|
51123
|
+
return null;
|
|
51124
|
+
let pool = candidates;
|
|
51125
|
+
const sinceVal = options.since;
|
|
51126
|
+
const untilVal = options.until;
|
|
51127
|
+
if (sinceVal !== undefined) {
|
|
51128
|
+
pool = pool.filter((c3) => c3.mtime >= sinceVal);
|
|
51129
|
+
}
|
|
51130
|
+
if (untilVal !== undefined) {
|
|
51131
|
+
pool = pool.filter((c3) => c3.mtime <= untilVal);
|
|
51132
|
+
}
|
|
51133
|
+
if (!pool.length)
|
|
51134
|
+
return null;
|
|
51135
|
+
const ref = options.preferClosestTo;
|
|
51136
|
+
const window = options.windowMs ?? 30 * 60 * 1000;
|
|
51137
|
+
const ordered = [...pool].sort((a2, b) => {
|
|
51138
|
+
if (typeof ref === "number") {
|
|
51139
|
+
const da = Math.abs(a2.mtime - ref);
|
|
51140
|
+
const db = Math.abs(b.mtime - ref);
|
|
51141
|
+
if (da === db)
|
|
51142
|
+
return b.mtime - a2.mtime;
|
|
51143
|
+
if (da <= window || db <= window)
|
|
51144
|
+
return da - db;
|
|
51145
|
+
}
|
|
51146
|
+
return b.mtime - a2.mtime;
|
|
51147
|
+
});
|
|
51148
|
+
const branchFilter = typeof options.branch === "string" && options.branch.trim().length > 0 ? options.branch.trim() : null;
|
|
51149
|
+
const shouldCheckBranch = Boolean(branchFilter);
|
|
51150
|
+
const shouldCheckCwd = Boolean(options.cwd) && !shouldCheckBranch;
|
|
51151
|
+
let worktrees = [];
|
|
51152
|
+
if (shouldCheckBranch) {
|
|
51153
|
+
if (Array.isArray(options.worktrees) && options.worktrees.length > 0) {
|
|
51154
|
+
worktrees = options.worktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
|
|
51155
|
+
} else {
|
|
51156
|
+
try {
|
|
51157
|
+
const allWorktrees = await listAllWorktrees();
|
|
51158
|
+
worktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
|
|
51159
|
+
} catch {
|
|
51160
|
+
worktrees = [];
|
|
51161
|
+
}
|
|
51162
|
+
}
|
|
51163
|
+
if (!worktrees.length)
|
|
51164
|
+
return null;
|
|
51165
|
+
}
|
|
51166
|
+
for (const file of ordered) {
|
|
51167
|
+
const filenameMatch = path16.basename(file.fullPath).match(UUID_REGEX);
|
|
51168
|
+
const idFromName = filenameMatch?.[0] ?? null;
|
|
51169
|
+
const needsInfo = shouldCheckBranch || shouldCheckCwd || !idFromName;
|
|
51170
|
+
const info = needsInfo ? await readSessionInfoFromFile(file.fullPath) : null;
|
|
51171
|
+
const sessionCwd = info?.cwd ?? null;
|
|
51172
|
+
if (shouldCheckBranch) {
|
|
51173
|
+
const resolvedBranch = resolveBranchFromCwd(sessionCwd, worktrees);
|
|
51174
|
+
if (resolvedBranch !== branchFilter) {
|
|
51175
|
+
continue;
|
|
51176
|
+
}
|
|
51177
|
+
}
|
|
51178
|
+
if (shouldCheckCwd && options.cwd) {
|
|
51179
|
+
if (!matchesCwd(sessionCwd, options.cwd)) {
|
|
51180
|
+
continue;
|
|
51181
|
+
}
|
|
51182
|
+
}
|
|
51183
|
+
const sessionId = idFromName ?? info?.id ?? null;
|
|
51184
|
+
if (sessionId) {
|
|
51185
|
+
return { id: sessionId, mtime: file.mtime };
|
|
51186
|
+
}
|
|
51187
|
+
}
|
|
51188
|
+
return null;
|
|
51189
|
+
}
|
|
51190
|
+
// src/utils/session/parsers/gemini.ts
|
|
51191
|
+
import path17 from "path";
|
|
51192
|
+
import { homedir as homedir5 } from "os";
|
|
51193
|
+
async function findLatestGeminiSession(options = {}) {
|
|
51194
|
+
const baseDir = path17.join(homedir5(), ".gemini", "tmp");
|
|
51195
|
+
const files = await collectFilesIterative(baseDir, (name) => name.endsWith(".json") || name.endsWith(".jsonl"));
|
|
51196
|
+
if (!files.length)
|
|
51197
|
+
return null;
|
|
51198
|
+
let pool = files;
|
|
51199
|
+
const sinceVal = options.since;
|
|
51200
|
+
if (sinceVal !== undefined) {
|
|
51201
|
+
pool = pool.filter((f) => f.mtime >= sinceVal);
|
|
51202
|
+
}
|
|
51203
|
+
const untilVal = options.until;
|
|
51204
|
+
if (untilVal !== undefined) {
|
|
51205
|
+
pool = pool.filter((f) => f.mtime <= untilVal);
|
|
51206
|
+
}
|
|
51207
|
+
if (!pool.length)
|
|
51208
|
+
return null;
|
|
51209
|
+
const ref = options.preferClosestTo;
|
|
51210
|
+
const window = options.windowMs ?? 30 * 60 * 1000;
|
|
51211
|
+
pool = pool.slice().sort((a2, b) => {
|
|
51212
|
+
if (typeof ref === "number") {
|
|
51213
|
+
const da = Math.abs(a2.mtime - ref);
|
|
51214
|
+
const db = Math.abs(b.mtime - ref);
|
|
51215
|
+
if (da === db)
|
|
51216
|
+
return b.mtime - a2.mtime;
|
|
51217
|
+
if (da <= window || db <= window)
|
|
51218
|
+
return da - db;
|
|
51219
|
+
}
|
|
51220
|
+
return b.mtime - a2.mtime;
|
|
51221
|
+
});
|
|
51222
|
+
const branchFilter = typeof options.branch === "string" && options.branch.trim().length > 0 ? options.branch.trim() : null;
|
|
51223
|
+
const shouldCheckBranch = Boolean(branchFilter);
|
|
51224
|
+
const shouldCheckCwd = Boolean(options.cwd) && !shouldCheckBranch;
|
|
51225
|
+
let worktrees = [];
|
|
51226
|
+
if (shouldCheckBranch) {
|
|
51227
|
+
if (Array.isArray(options.worktrees) && options.worktrees.length > 0) {
|
|
51228
|
+
worktrees = options.worktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
|
|
51229
|
+
} else {
|
|
51230
|
+
try {
|
|
51231
|
+
const allWorktrees = await listAllWorktrees();
|
|
51232
|
+
worktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
|
|
51233
|
+
} catch {
|
|
51234
|
+
worktrees = [];
|
|
51235
|
+
}
|
|
51236
|
+
}
|
|
51237
|
+
if (!worktrees.length)
|
|
51238
|
+
return null;
|
|
51239
|
+
}
|
|
51240
|
+
for (const file of pool) {
|
|
51241
|
+
const info = await readSessionInfoFromFile(file.fullPath);
|
|
51242
|
+
if (!info.id)
|
|
51243
|
+
continue;
|
|
51244
|
+
const sessionCwd = info.cwd ?? null;
|
|
51245
|
+
if (shouldCheckBranch) {
|
|
51246
|
+
const resolvedBranch = resolveBranchFromCwd(sessionCwd, worktrees);
|
|
51247
|
+
if (resolvedBranch !== branchFilter) {
|
|
51248
|
+
continue;
|
|
51249
|
+
}
|
|
51250
|
+
}
|
|
51251
|
+
if (shouldCheckCwd && options.cwd) {
|
|
51252
|
+
if (!matchesCwd(sessionCwd, options.cwd)) {
|
|
51253
|
+
continue;
|
|
51254
|
+
}
|
|
51255
|
+
}
|
|
51256
|
+
return { id: info.id, mtime: file.mtime };
|
|
51257
|
+
}
|
|
51258
|
+
return null;
|
|
51259
|
+
}
|
|
51260
|
+
// src/utils/session/parsers/opencode.ts
|
|
51261
|
+
import path18 from "path";
|
|
51262
|
+
import { homedir as homedir6 } from "os";
|
|
51263
|
+
function getOpenCodeSessionDir() {
|
|
51264
|
+
return path18.join(homedir6(), ".local", "share", "opencode", "storage", "session");
|
|
51265
|
+
}
|
|
51266
|
+
async function findLatestOpenCodeSession(options = {}) {
|
|
51267
|
+
const baseDir = getOpenCodeSessionDir();
|
|
51268
|
+
const files = await collectFilesIterative(baseDir, (name) => name.endsWith(".json") || name.endsWith(".jsonl"));
|
|
51269
|
+
if (!files.length)
|
|
51270
|
+
return null;
|
|
51271
|
+
let pool = files;
|
|
51272
|
+
const sinceVal = options.since;
|
|
51273
|
+
if (sinceVal !== undefined) {
|
|
51274
|
+
pool = pool.filter((f) => f.mtime >= sinceVal);
|
|
51275
|
+
}
|
|
51276
|
+
const untilVal = options.until;
|
|
51277
|
+
if (untilVal !== undefined) {
|
|
51278
|
+
pool = pool.filter((f) => f.mtime <= untilVal);
|
|
51279
|
+
}
|
|
51280
|
+
if (!pool.length)
|
|
51281
|
+
return null;
|
|
51282
|
+
const ref = options.preferClosestTo;
|
|
51283
|
+
const window = options.windowMs ?? 30 * 60 * 1000;
|
|
51284
|
+
pool = pool.slice().sort((a2, b) => {
|
|
51285
|
+
if (typeof ref === "number") {
|
|
51286
|
+
const da = Math.abs(a2.mtime - ref);
|
|
51287
|
+
const db = Math.abs(b.mtime - ref);
|
|
51288
|
+
if (da === db)
|
|
51289
|
+
return b.mtime - a2.mtime;
|
|
51290
|
+
if (da <= window || db <= window)
|
|
51291
|
+
return da - db;
|
|
51292
|
+
}
|
|
51293
|
+
return b.mtime - a2.mtime;
|
|
51294
|
+
});
|
|
51295
|
+
const branchFilter = typeof options.branch === "string" && options.branch.trim().length > 0 ? options.branch.trim() : null;
|
|
51296
|
+
const shouldCheckBranch = Boolean(branchFilter);
|
|
51297
|
+
const shouldCheckCwd = Boolean(options.cwd) && !shouldCheckBranch;
|
|
51298
|
+
let worktrees = [];
|
|
51299
|
+
if (shouldCheckBranch) {
|
|
51300
|
+
if (Array.isArray(options.worktrees) && options.worktrees.length > 0) {
|
|
51301
|
+
worktrees = options.worktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
|
|
51302
|
+
} else {
|
|
51303
|
+
try {
|
|
51304
|
+
const allWorktrees = await listAllWorktrees();
|
|
51305
|
+
worktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
|
|
51306
|
+
} catch {
|
|
51307
|
+
worktrees = [];
|
|
51308
|
+
}
|
|
51309
|
+
}
|
|
51310
|
+
if (!worktrees.length)
|
|
51311
|
+
return null;
|
|
51312
|
+
}
|
|
51313
|
+
for (const file of pool) {
|
|
51314
|
+
const info = await readSessionInfoFromFile(file.fullPath);
|
|
51315
|
+
if (!info.id)
|
|
51316
|
+
continue;
|
|
51317
|
+
const sessionCwd = info.cwd ?? null;
|
|
51318
|
+
if (shouldCheckBranch) {
|
|
51319
|
+
const resolvedBranch = resolveBranchFromCwd(sessionCwd, worktrees);
|
|
51320
|
+
if (resolvedBranch !== branchFilter) {
|
|
51321
|
+
continue;
|
|
51322
|
+
}
|
|
51323
|
+
}
|
|
51324
|
+
if (shouldCheckCwd && options.cwd) {
|
|
51325
|
+
if (!matchesCwd(sessionCwd, options.cwd)) {
|
|
51326
|
+
continue;
|
|
51327
|
+
}
|
|
51328
|
+
}
|
|
51329
|
+
return { id: info.id, mtime: file.mtime };
|
|
51330
|
+
}
|
|
51331
|
+
return null;
|
|
51332
|
+
}
|
|
51333
|
+
// src/cli/ui/utils/continueSession.ts
|
|
51334
|
+
function findLatestBranchSessionsByTool(history, branch, worktreePath) {
|
|
51335
|
+
const byBranch = history.filter((entry) => entry && entry.branch === branch);
|
|
51336
|
+
if (!byBranch.length)
|
|
51337
|
+
return [];
|
|
51338
|
+
const source = worktreePath ? byBranch.filter((entry) => entry.worktreePath === worktreePath) : byBranch;
|
|
51339
|
+
if (!source.length)
|
|
51340
|
+
return [];
|
|
51341
|
+
const latestByTool = new Map;
|
|
51342
|
+
for (const entry of source) {
|
|
51343
|
+
if (!entry.toolId)
|
|
51344
|
+
continue;
|
|
51345
|
+
const current = latestByTool.get(entry.toolId);
|
|
51346
|
+
const currentTs = current?.timestamp ?? 0;
|
|
51347
|
+
const entryTs = entry.timestamp ?? 0;
|
|
51348
|
+
if (!current || entryTs >= currentTs) {
|
|
51349
|
+
latestByTool.set(entry.toolId, entry);
|
|
51350
|
+
}
|
|
51351
|
+
}
|
|
51352
|
+
return Array.from(latestByTool.values()).sort((a2, b) => (b.timestamp ?? 0) - (a2.timestamp ?? 0));
|
|
51353
|
+
}
|
|
51354
|
+
async function refreshQuickStartEntries(entries, context, lookups = {}) {
|
|
51355
|
+
if (!entries.length)
|
|
51356
|
+
return entries;
|
|
51357
|
+
const worktreePath = context.worktreePath ?? null;
|
|
51358
|
+
if (!worktreePath)
|
|
51359
|
+
return entries;
|
|
51360
|
+
const lookupWorktrees = lookups.listAllWorktrees ?? listAllWorktrees;
|
|
51361
|
+
let resolvedWorktrees = null;
|
|
51362
|
+
try {
|
|
51363
|
+
const allWorktrees = await lookupWorktrees();
|
|
51364
|
+
resolvedWorktrees = allWorktrees.filter((entry) => entry?.path && entry?.branch).map((entry) => ({ path: entry.path, branch: entry.branch }));
|
|
51365
|
+
} catch {
|
|
51366
|
+
resolvedWorktrees = null;
|
|
51367
|
+
}
|
|
51368
|
+
const searchOptions = {
|
|
51369
|
+
branch: context.branch,
|
|
51370
|
+
...resolvedWorktrees && resolvedWorktrees.length > 0 ? { worktrees: resolvedWorktrees } : {}
|
|
51371
|
+
};
|
|
51372
|
+
const lookupCodex = lookups.findLatestCodexSession ?? findLatestCodexSession;
|
|
51373
|
+
const lookupClaude = lookups.findLatestClaudeSession ?? findLatestClaudeSession;
|
|
51374
|
+
const lookupGemini = lookups.findLatestGeminiSession ?? findLatestGeminiSession;
|
|
51375
|
+
const lookupOpenCode = lookups.findLatestOpenCodeSession ?? findLatestOpenCodeSession;
|
|
51376
|
+
const updated = await Promise.all(entries.map(async (entry) => {
|
|
51377
|
+
let latest = null;
|
|
51378
|
+
switch (entry.toolId) {
|
|
51379
|
+
case "codex-cli":
|
|
51380
|
+
latest = await lookupCodex(searchOptions);
|
|
51381
|
+
break;
|
|
51382
|
+
case "claude-code":
|
|
51383
|
+
latest = await lookupClaude(worktreePath, searchOptions);
|
|
51384
|
+
break;
|
|
51385
|
+
case "gemini-cli":
|
|
51386
|
+
latest = await lookupGemini(searchOptions);
|
|
51387
|
+
break;
|
|
51388
|
+
case "opencode":
|
|
51389
|
+
latest = await lookupOpenCode(searchOptions);
|
|
51390
|
+
break;
|
|
51391
|
+
default:
|
|
51392
|
+
return entry;
|
|
51393
|
+
}
|
|
51394
|
+
if (!latest?.id)
|
|
51395
|
+
return entry;
|
|
51396
|
+
const updatedTimestamp = Math.max(entry.timestamp ?? 0, latest.mtime);
|
|
51397
|
+
return {
|
|
51398
|
+
...entry,
|
|
51399
|
+
sessionId: latest.id,
|
|
51400
|
+
timestamp: updatedTimestamp
|
|
51401
|
+
};
|
|
51402
|
+
}));
|
|
51403
|
+
return updated.sort((a2, b) => (b.timestamp ?? 0) - (a2.timestamp ?? 0));
|
|
51404
|
+
}
|
|
51405
|
+
|
|
51406
|
+
// src/config/tools.ts
|
|
51407
|
+
init_builtin_coding_agents();
|
|
51408
|
+
import { homedir as homedir8 } from "os";
|
|
51409
|
+
import path20 from "path";
|
|
51410
|
+
import { readFile as readFile4, writeFile as writeFile3, mkdir as mkdir3, rename as rename2 } from "fs/promises";
|
|
50108
51411
|
|
|
50109
51412
|
// src/config/profiles.ts
|
|
50110
51413
|
import {
|
|
50111
51414
|
mkdir as mkdir2,
|
|
50112
51415
|
open,
|
|
50113
|
-
readFile as
|
|
51416
|
+
readFile as readFile3,
|
|
50114
51417
|
rename,
|
|
50115
|
-
stat,
|
|
51418
|
+
stat as stat2,
|
|
50116
51419
|
unlink,
|
|
50117
51420
|
writeFile as writeFile2
|
|
50118
51421
|
} from "fs/promises";
|
|
50119
|
-
import
|
|
51422
|
+
import path19 from "path";
|
|
50120
51423
|
|
|
50121
51424
|
// node_modules/yaml/dist/index.js
|
|
50122
51425
|
var composer = require_composer();
|
|
@@ -50165,7 +51468,7 @@ var $visit = visit.visit;
|
|
|
50165
51468
|
var $visitAsync = visit.visitAsync;
|
|
50166
51469
|
|
|
50167
51470
|
// src/config/profiles.ts
|
|
50168
|
-
import { homedir as
|
|
51471
|
+
import { homedir as homedir7 } from "os";
|
|
50169
51472
|
|
|
50170
51473
|
// src/types/profiles.ts
|
|
50171
51474
|
var DEFAULT_PROFILES_CONFIG = Object.freeze({
|
|
@@ -50180,11 +51483,11 @@ function isValidProfileName(name) {
|
|
|
50180
51483
|
|
|
50181
51484
|
// src/config/profiles.ts
|
|
50182
51485
|
function getConfigDir() {
|
|
50183
|
-
const worktreeHome = process.env.GWT_HOME && process.env.GWT_HOME.trim().length > 0 ? process.env.GWT_HOME :
|
|
50184
|
-
return
|
|
51486
|
+
const worktreeHome = process.env.GWT_HOME && process.env.GWT_HOME.trim().length > 0 ? process.env.GWT_HOME : homedir7();
|
|
51487
|
+
return path19.join(worktreeHome, ".gwt");
|
|
50185
51488
|
}
|
|
50186
51489
|
function getProfilesConfigPath() {
|
|
50187
|
-
return
|
|
51490
|
+
return path19.join(getConfigDir(), "profiles.yaml");
|
|
50188
51491
|
}
|
|
50189
51492
|
var LOCK_RETRY_INTERVAL_MS = 50;
|
|
50190
51493
|
var LOCK_TIMEOUT_MS = 3000;
|
|
@@ -50194,7 +51497,7 @@ function getProfilesLockPath() {
|
|
|
50194
51497
|
}
|
|
50195
51498
|
async function withProfilesLock(fn) {
|
|
50196
51499
|
const lockPath = getProfilesLockPath();
|
|
50197
|
-
await mkdir2(
|
|
51500
|
+
await mkdir2(path19.dirname(lockPath), { recursive: true });
|
|
50198
51501
|
const startedAt = Date.now();
|
|
50199
51502
|
while (true) {
|
|
50200
51503
|
try {
|
|
@@ -50213,7 +51516,7 @@ async function withProfilesLock(fn) {
|
|
|
50213
51516
|
throw error;
|
|
50214
51517
|
}
|
|
50215
51518
|
try {
|
|
50216
|
-
const lockStat = await
|
|
51519
|
+
const lockStat = await stat2(lockPath);
|
|
50217
51520
|
const isStale = Date.now() - lockStat.mtimeMs > LOCK_STALE_MS;
|
|
50218
51521
|
if (isStale) {
|
|
50219
51522
|
await unlink(lockPath).catch(() => {});
|
|
@@ -50243,7 +51546,7 @@ var PROFILES_CONFIG_PATH = getProfilesConfigPath();
|
|
|
50243
51546
|
async function loadProfiles() {
|
|
50244
51547
|
try {
|
|
50245
51548
|
const configPath = getProfilesConfigPath();
|
|
50246
|
-
const content = await
|
|
51549
|
+
const content = await readFile3(configPath, "utf-8");
|
|
50247
51550
|
const config = $parse(content);
|
|
50248
51551
|
if (!config.version || typeof config.version !== "string") {
|
|
50249
51552
|
throw new Error("version field is required and must be a string");
|
|
@@ -50328,9 +51631,9 @@ async function deleteProfile(name) {
|
|
|
50328
51631
|
|
|
50329
51632
|
// src/config/tools.ts
|
|
50330
51633
|
var logger3 = createLogger({ category: "config" });
|
|
50331
|
-
var WORKTREE_HOME = process.env.GWT_HOME && process.env.GWT_HOME.trim().length > 0 ? process.env.GWT_HOME :
|
|
50332
|
-
var CONFIG_DIR =
|
|
50333
|
-
var TOOLS_CONFIG_PATH =
|
|
51634
|
+
var WORKTREE_HOME = process.env.GWT_HOME && process.env.GWT_HOME.trim().length > 0 ? process.env.GWT_HOME : homedir8();
|
|
51635
|
+
var CONFIG_DIR = path20.join(WORKTREE_HOME, ".gwt");
|
|
51636
|
+
var TOOLS_CONFIG_PATH = path20.join(CONFIG_DIR, "tools.json");
|
|
50334
51637
|
var TEMP_CONFIG_PATH = `${TOOLS_CONFIG_PATH}.tmp`;
|
|
50335
51638
|
var DEFAULT_CONFIG2 = {
|
|
50336
51639
|
version: "1.0.0",
|
|
@@ -50339,7 +51642,7 @@ var DEFAULT_CONFIG2 = {
|
|
|
50339
51642
|
};
|
|
50340
51643
|
async function loadCodingAgentsConfig() {
|
|
50341
51644
|
try {
|
|
50342
|
-
const content = await
|
|
51645
|
+
const content = await readFile4(TOOLS_CONFIG_PATH, "utf-8");
|
|
50343
51646
|
const config = JSON.parse(content);
|
|
50344
51647
|
const legacyConfig = config;
|
|
50345
51648
|
if (!config.customCodingAgents && legacyConfig.customTools) {
|
|
@@ -50423,7 +51726,7 @@ function validateCodingAgent(agent) {
|
|
|
50423
51726
|
throw new Error(`Invalid type: "${a2.type}"
|
|
50424
51727
|
` + `Type must be one of: ${validTypes.join(", ")}`);
|
|
50425
51728
|
}
|
|
50426
|
-
if (a2.type === "path" && !
|
|
51729
|
+
if (a2.type === "path" && !path20.isAbsolute(a2.command)) {
|
|
50427
51730
|
throw new Error(`For type="path", command must be an absolute path: "${a2.command}"`);
|
|
50428
51731
|
}
|
|
50429
51732
|
if (!a2.modeArgs.normal && !a2.modeArgs.continue && !a2.modeArgs.resume) {
|
|
@@ -50450,14 +51753,45 @@ async function getAllCodingAgents() {
|
|
|
50450
51753
|
|
|
50451
51754
|
// src/logging/reader.ts
|
|
50452
51755
|
import fs4 from "fs/promises";
|
|
50453
|
-
import
|
|
51756
|
+
import path21 from "path";
|
|
50454
51757
|
import os4 from "os";
|
|
51758
|
+
var LOG_FILENAME_PATTERN = /^\d{4}-\d{2}-\d{2}\.jsonl$/;
|
|
50455
51759
|
function resolveLogDir(cwd = process.cwd()) {
|
|
50456
|
-
const cwdBase =
|
|
50457
|
-
return
|
|
51760
|
+
const cwdBase = path21.basename(cwd) || "workspace";
|
|
51761
|
+
return path21.join(os4.homedir(), ".gwt", "logs", cwdBase);
|
|
50458
51762
|
}
|
|
50459
|
-
function
|
|
50460
|
-
|
|
51763
|
+
function resolveLogTarget(branch, workingDirectory = process.cwd()) {
|
|
51764
|
+
if (!branch) {
|
|
51765
|
+
return {
|
|
51766
|
+
logDir: resolveLogDir(workingDirectory),
|
|
51767
|
+
sourcePath: workingDirectory,
|
|
51768
|
+
reason: "working-directory"
|
|
51769
|
+
};
|
|
51770
|
+
}
|
|
51771
|
+
const worktreePath = branch.worktree?.path;
|
|
51772
|
+
if (worktreePath) {
|
|
51773
|
+
const accessible = branch.worktree?.isAccessible !== false;
|
|
51774
|
+
if (accessible) {
|
|
51775
|
+
return {
|
|
51776
|
+
logDir: resolveLogDir(worktreePath),
|
|
51777
|
+
sourcePath: worktreePath,
|
|
51778
|
+
reason: "worktree"
|
|
51779
|
+
};
|
|
51780
|
+
}
|
|
51781
|
+
return {
|
|
51782
|
+
logDir: null,
|
|
51783
|
+
sourcePath: worktreePath,
|
|
51784
|
+
reason: "worktree-inaccessible"
|
|
51785
|
+
};
|
|
51786
|
+
}
|
|
51787
|
+
if (branch.isCurrent) {
|
|
51788
|
+
return {
|
|
51789
|
+
logDir: resolveLogDir(workingDirectory),
|
|
51790
|
+
sourcePath: workingDirectory,
|
|
51791
|
+
reason: "current-working-directory"
|
|
51792
|
+
};
|
|
51793
|
+
}
|
|
51794
|
+
return { logDir: null, sourcePath: null, reason: "no-worktree" };
|
|
50461
51795
|
}
|
|
50462
51796
|
function getTodayLogDate() {
|
|
50463
51797
|
return formatDate(new Date);
|
|
@@ -50475,6 +51809,76 @@ async function readLogFileLines(filePath) {
|
|
|
50475
51809
|
throw error;
|
|
50476
51810
|
}
|
|
50477
51811
|
}
|
|
51812
|
+
async function listLogFiles(logDir) {
|
|
51813
|
+
try {
|
|
51814
|
+
const entries = await fs4.readdir(logDir, { withFileTypes: true });
|
|
51815
|
+
const files = [];
|
|
51816
|
+
for (const entry of entries) {
|
|
51817
|
+
if (!entry.isFile())
|
|
51818
|
+
continue;
|
|
51819
|
+
if (!LOG_FILENAME_PATTERN.test(entry.name))
|
|
51820
|
+
continue;
|
|
51821
|
+
const date = entry.name.replace(/\.jsonl$/, "");
|
|
51822
|
+
const fullPath = path21.join(logDir, entry.name);
|
|
51823
|
+
try {
|
|
51824
|
+
const stat3 = await fs4.stat(fullPath);
|
|
51825
|
+
files.push({ date, path: fullPath, mtimeMs: stat3.mtimeMs });
|
|
51826
|
+
} catch {}
|
|
51827
|
+
}
|
|
51828
|
+
return files.sort((a2, b) => b.date.localeCompare(a2.date));
|
|
51829
|
+
} catch (error) {
|
|
51830
|
+
const err = error;
|
|
51831
|
+
if (err.code === "ENOENT") {
|
|
51832
|
+
return [];
|
|
51833
|
+
}
|
|
51834
|
+
throw error;
|
|
51835
|
+
}
|
|
51836
|
+
}
|
|
51837
|
+
async function clearLogFiles(logDir) {
|
|
51838
|
+
const files = await listLogFiles(logDir);
|
|
51839
|
+
let cleared = 0;
|
|
51840
|
+
for (const file of files) {
|
|
51841
|
+
try {
|
|
51842
|
+
await fs4.truncate(file.path, 0);
|
|
51843
|
+
cleared += 1;
|
|
51844
|
+
} catch (error) {
|
|
51845
|
+
const err = error;
|
|
51846
|
+
if (err.code !== "ENOENT") {
|
|
51847
|
+
throw error;
|
|
51848
|
+
}
|
|
51849
|
+
}
|
|
51850
|
+
}
|
|
51851
|
+
return cleared;
|
|
51852
|
+
}
|
|
51853
|
+
async function readLogLinesForDate(logDir, preferredDate) {
|
|
51854
|
+
const files = await listLogFiles(logDir);
|
|
51855
|
+
if (files.length === 0) {
|
|
51856
|
+
return null;
|
|
51857
|
+
}
|
|
51858
|
+
const ordered = [];
|
|
51859
|
+
const preferred = files.find((file) => file.date === preferredDate);
|
|
51860
|
+
if (preferred) {
|
|
51861
|
+
ordered.push(preferred);
|
|
51862
|
+
}
|
|
51863
|
+
for (const file of files) {
|
|
51864
|
+
if (preferred && file.date === preferred.date) {
|
|
51865
|
+
continue;
|
|
51866
|
+
}
|
|
51867
|
+
ordered.push(file);
|
|
51868
|
+
}
|
|
51869
|
+
for (const file of ordered) {
|
|
51870
|
+
const lines = await readLogFileLines(file.path);
|
|
51871
|
+
if (lines.length > 0) {
|
|
51872
|
+
return { date: file.date, lines };
|
|
51873
|
+
}
|
|
51874
|
+
}
|
|
51875
|
+
const fallback = files[0];
|
|
51876
|
+
if (!fallback) {
|
|
51877
|
+
return { date: preferredDate, lines: [] };
|
|
51878
|
+
}
|
|
51879
|
+
const fallbackDate = preferred?.date ?? fallback.date;
|
|
51880
|
+
return { date: fallbackDate, lines: [] };
|
|
51881
|
+
}
|
|
50478
51882
|
|
|
50479
51883
|
// src/logging/formatter.ts
|
|
50480
51884
|
var LEVEL_LABELS = {
|
|
@@ -50485,15 +51889,29 @@ var LEVEL_LABELS = {
|
|
|
50485
51889
|
50: "ERROR",
|
|
50486
51890
|
60: "FATAL"
|
|
50487
51891
|
};
|
|
51892
|
+
var LOCAL_TIME_FORMATTER = new Intl.DateTimeFormat(undefined, {
|
|
51893
|
+
hour: "2-digit",
|
|
51894
|
+
minute: "2-digit",
|
|
51895
|
+
second: "2-digit",
|
|
51896
|
+
hour12: false
|
|
51897
|
+
});
|
|
51898
|
+
var formatLocalTimeParts = (date) => {
|
|
51899
|
+
const parts = LOCAL_TIME_FORMATTER.formatToParts(date);
|
|
51900
|
+
const get = (type) => parts.find((part) => part.type === type)?.value;
|
|
51901
|
+
const hour = get("hour");
|
|
51902
|
+
const minute = get("minute");
|
|
51903
|
+
const second = get("second");
|
|
51904
|
+
if (!hour || !minute || !second) {
|
|
51905
|
+
return LOCAL_TIME_FORMATTER.format(date);
|
|
51906
|
+
}
|
|
51907
|
+
return `${hour}:${minute}:${second}`;
|
|
51908
|
+
};
|
|
50488
51909
|
var formatTimeLabel = (value) => {
|
|
50489
51910
|
if (typeof value === "string" || typeof value === "number") {
|
|
50490
51911
|
const date = new Date(value);
|
|
50491
51912
|
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
51913
|
return {
|
|
50496
|
-
label:
|
|
51914
|
+
label: formatLocalTimeParts(date),
|
|
50497
51915
|
timestamp: date.getTime()
|
|
50498
51916
|
};
|
|
50499
51917
|
}
|
|
@@ -50577,17 +51995,17 @@ async function copyToClipboard(text, options = {}) {
|
|
|
50577
51995
|
}
|
|
50578
51996
|
|
|
50579
51997
|
// src/utils.ts
|
|
50580
|
-
import
|
|
51998
|
+
import path22 from "path";
|
|
50581
51999
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
50582
|
-
import { readFile as
|
|
52000
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
50583
52001
|
function getCurrentDirname() {
|
|
50584
|
-
return
|
|
52002
|
+
return path22.dirname(fileURLToPath4(import.meta.url));
|
|
50585
52003
|
}
|
|
50586
52004
|
async function getPackageVersion() {
|
|
50587
52005
|
try {
|
|
50588
52006
|
const currentDir = getCurrentDirname();
|
|
50589
|
-
const packageJsonPath =
|
|
50590
|
-
const packageJsonContent = await
|
|
52007
|
+
const packageJsonPath = path22.resolve(currentDir, "..", "package.json");
|
|
52008
|
+
const packageJsonContent = await readFile5(packageJsonPath, "utf-8");
|
|
50591
52009
|
const packageJson = JSON.parse(packageJsonContent);
|
|
50592
52010
|
return packageJson.version || null;
|
|
50593
52011
|
} catch {
|
|
@@ -50597,9 +52015,11 @@ async function getPackageVersion() {
|
|
|
50597
52015
|
|
|
50598
52016
|
// src/cli/ui/App.solid.tsx
|
|
50599
52017
|
init_constants();
|
|
52018
|
+
init_versionFetcher();
|
|
50600
52019
|
var logger4 = createLogger({
|
|
50601
52020
|
category: "app"
|
|
50602
52021
|
});
|
|
52022
|
+
var UNSAFE_SELECTION_MESSAGE = "Unsafe branch selected. Select anyway?";
|
|
50603
52023
|
var DEFAULT_SCREEN = "branch-list";
|
|
50604
52024
|
var buildStats = (branches) => calculateStatistics(branches);
|
|
50605
52025
|
var applyCleanupStatus = (items, statusByBranch) => items.map((branch) => {
|
|
@@ -50630,6 +52050,23 @@ var applyCleanupStatus = (items, statusByBranch) => items.map((branch) => {
|
|
|
50630
52050
|
worktree
|
|
50631
52051
|
} : base2;
|
|
50632
52052
|
});
|
|
52053
|
+
var buildCleanupSafetyPending = (items) => {
|
|
52054
|
+
const pending = new Set;
|
|
52055
|
+
for (const branch of items) {
|
|
52056
|
+
if (branch.type === "remote") {
|
|
52057
|
+
continue;
|
|
52058
|
+
}
|
|
52059
|
+
if (branch.worktree) {
|
|
52060
|
+
pending.add(branch.name);
|
|
52061
|
+
continue;
|
|
52062
|
+
}
|
|
52063
|
+
if (isProtectedBranchName(branch.name)) {
|
|
52064
|
+
continue;
|
|
52065
|
+
}
|
|
52066
|
+
pending.add(branch.name);
|
|
52067
|
+
}
|
|
52068
|
+
return pending;
|
|
52069
|
+
};
|
|
50633
52070
|
var toLocalBranchName = (name) => {
|
|
50634
52071
|
const segments = name.split("/");
|
|
50635
52072
|
if (segments.length <= 1) {
|
|
@@ -50645,6 +52082,7 @@ var toSelectedBranchState = (branch) => {
|
|
|
50645
52082
|
displayName: branch.name,
|
|
50646
52083
|
branchType: branch.type,
|
|
50647
52084
|
branchCategory: branch.branchType,
|
|
52085
|
+
worktreePath: branch.worktree?.path ?? null,
|
|
50648
52086
|
...isRemote ? {
|
|
50649
52087
|
remoteBranch: branch.name
|
|
50650
52088
|
} : {}
|
|
@@ -50652,6 +52090,7 @@ var toSelectedBranchState = (branch) => {
|
|
|
50652
52090
|
};
|
|
50653
52091
|
function AppSolid(props) {
|
|
50654
52092
|
const renderer = useRenderer();
|
|
52093
|
+
const terminal = useTerminalSize();
|
|
50655
52094
|
let hasExited = false;
|
|
50656
52095
|
const exitApp = (result) => {
|
|
50657
52096
|
if (hasExited)
|
|
@@ -50668,6 +52107,7 @@ function AppSolid(props) {
|
|
|
50668
52107
|
const [stats, setStats] = createSignal(props.stats ?? buildStats(props.branches ?? []));
|
|
50669
52108
|
const [loading, setLoading] = createSignal(!props.branches);
|
|
50670
52109
|
const [error, setError] = createSignal(null);
|
|
52110
|
+
const [branchCursorPosition, setBranchCursorPosition] = createSignal(0);
|
|
50671
52111
|
const [toolItems, setToolItems] = createSignal([]);
|
|
50672
52112
|
const [toolError, setToolError] = createSignal(null);
|
|
50673
52113
|
const [version, setVersion] = createSignal(props.version ?? null);
|
|
@@ -50676,11 +52116,15 @@ function AppSolid(props) {
|
|
|
50676
52116
|
const [selectedTool, setSelectedTool] = createSignal(null);
|
|
50677
52117
|
const [selectedMode, setSelectedMode] = createSignal("normal");
|
|
50678
52118
|
const [selectedBranches, setSelectedBranches] = createSignal([]);
|
|
52119
|
+
const [unsafeSelectionConfirmVisible, setUnsafeSelectionConfirmVisible] = createSignal(false);
|
|
52120
|
+
const [unsafeConfirmInputLocked, setUnsafeConfirmInputLocked] = createSignal(false);
|
|
52121
|
+
const [unsafeSelectionTarget, setUnsafeSelectionTarget] = createSignal(null);
|
|
50679
52122
|
const [branchFooterMessage, setBranchFooterMessage] = createSignal(null);
|
|
50680
52123
|
const [branchInputLocked, setBranchInputLocked] = createSignal(false);
|
|
50681
52124
|
const [cleanupIndicators, setCleanupIndicators] = createSignal({});
|
|
50682
52125
|
const [cleanupStatusByBranch, setCleanupStatusByBranch] = createSignal(new Map);
|
|
50683
52126
|
const [cleanupSafetyLoading, setCleanupSafetyLoading] = createSignal(false);
|
|
52127
|
+
const [cleanupSafetyPending, setCleanupSafetyPending] = createSignal(new Set);
|
|
50684
52128
|
const [isNewBranch, setIsNewBranch] = createSignal(false);
|
|
50685
52129
|
const [newBranchBaseRef, setNewBranchBaseRef] = createSignal(null);
|
|
50686
52130
|
const [creationSource, setCreationSource] = createSignal(null);
|
|
@@ -50689,20 +52133,59 @@ function AppSolid(props) {
|
|
|
50689
52133
|
});
|
|
50690
52134
|
const [suppressCreateKey, setSuppressCreateKey] = createSignal(null);
|
|
50691
52135
|
const [defaultBaseBranch, setDefaultBaseBranch] = createSignal("main");
|
|
52136
|
+
const suppressBranchInputOnce = () => {
|
|
52137
|
+
setUnsafeConfirmInputLocked(true);
|
|
52138
|
+
queueMicrotask(() => {
|
|
52139
|
+
setUnsafeConfirmInputLocked(false);
|
|
52140
|
+
});
|
|
52141
|
+
};
|
|
52142
|
+
const unsafeConfirmBoxWidth = createMemo(() => {
|
|
52143
|
+
const columns = terminal().columns || 80;
|
|
52144
|
+
return Math.max(1, Math.floor(columns * 0.6));
|
|
52145
|
+
});
|
|
52146
|
+
const unsafeConfirmContentWidth = createMemo(() => Math.max(0, unsafeConfirmBoxWidth() - 4));
|
|
50692
52147
|
const [sessionHistory, setSessionHistory] = createSignal([]);
|
|
52148
|
+
const [quickStartHistory, setQuickStartHistory] = createSignal([]);
|
|
50693
52149
|
const historyForBranch = createMemo(() => {
|
|
50694
52150
|
const history = sessionHistory();
|
|
50695
52151
|
const branch = selectedBranch();
|
|
50696
52152
|
if (!branch)
|
|
50697
52153
|
return [];
|
|
50698
|
-
return history
|
|
52154
|
+
return findLatestBranchSessionsByTool(history, branch.name, branch.worktreePath ?? null);
|
|
52155
|
+
});
|
|
52156
|
+
createEffect(() => {
|
|
52157
|
+
setQuickStartHistory(historyForBranch());
|
|
52158
|
+
});
|
|
52159
|
+
createEffect(() => {
|
|
52160
|
+
const branch = selectedBranch();
|
|
52161
|
+
const baseHistory = historyForBranch();
|
|
52162
|
+
if (!wizardVisible() || !branch || baseHistory.length === 0) {
|
|
52163
|
+
return;
|
|
52164
|
+
}
|
|
52165
|
+
const worktreePath = branch.worktreePath ?? null;
|
|
52166
|
+
if (!worktreePath) {
|
|
52167
|
+
return;
|
|
52168
|
+
}
|
|
52169
|
+
const branchName = branch.name;
|
|
52170
|
+
(async () => {
|
|
52171
|
+
const refreshed = await refreshQuickStartEntries(baseHistory, {
|
|
52172
|
+
branch: branchName,
|
|
52173
|
+
worktreePath
|
|
52174
|
+
});
|
|
52175
|
+
if (selectedBranch()?.name !== branchName) {
|
|
52176
|
+
return;
|
|
52177
|
+
}
|
|
52178
|
+
setQuickStartHistory(refreshed);
|
|
52179
|
+
})();
|
|
50699
52180
|
});
|
|
50700
52181
|
const [logEntries, setLogEntries] = createSignal([]);
|
|
50701
52182
|
const [logLoading, setLogLoading] = createSignal(false);
|
|
50702
52183
|
const [logError2, setLogError] = createSignal(null);
|
|
50703
52184
|
const [logSelectedEntry, setLogSelectedEntry] = createSignal(null);
|
|
50704
|
-
const [logSelectedDate,
|
|
52185
|
+
const [logSelectedDate, setLogSelectedDate] = createSignal(getTodayLogDate());
|
|
50705
52186
|
const [logNotification, setLogNotification] = createSignal(null);
|
|
52187
|
+
const [logTailEnabled, setLogTailEnabled] = createSignal(false);
|
|
52188
|
+
const [logTargetBranch, setLogTargetBranch] = createSignal(null);
|
|
50706
52189
|
const [profileItems, setProfileItems] = createSignal([]);
|
|
50707
52190
|
const [activeProfile, setActiveProfileName] = createSignal(null);
|
|
50708
52191
|
const [profileError, setProfileError] = createSignal(null);
|
|
@@ -50717,7 +52200,21 @@ function AppSolid(props) {
|
|
|
50717
52200
|
const [profileInputSuppressKey, setProfileInputSuppressKey] = createSignal(null);
|
|
50718
52201
|
const [profileEnvKey, setProfileEnvKey] = createSignal(null);
|
|
50719
52202
|
const [profileConfirmMode, setProfileConfirmMode] = createSignal("delete-profile");
|
|
50720
|
-
const
|
|
52203
|
+
const logTarget = createMemo(() => resolveLogTarget(logTargetBranch(), workingDirectory()));
|
|
52204
|
+
const logBranchLabel = createMemo(() => logTargetBranch()?.label ?? null);
|
|
52205
|
+
const logSourceLabel = createMemo(() => {
|
|
52206
|
+
const target = logTarget();
|
|
52207
|
+
if (!target.sourcePath) {
|
|
52208
|
+
return "(none)";
|
|
52209
|
+
}
|
|
52210
|
+
if (target.reason === "current-working-directory" || target.reason === "working-directory") {
|
|
52211
|
+
return `${target.sourcePath} (cwd)`;
|
|
52212
|
+
}
|
|
52213
|
+
if (target.reason === "worktree-inaccessible") {
|
|
52214
|
+
return `${target.sourcePath} (inaccessible)`;
|
|
52215
|
+
}
|
|
52216
|
+
return target.sourcePath;
|
|
52217
|
+
});
|
|
50721
52218
|
const selectedProfileConfig = createMemo(() => {
|
|
50722
52219
|
const name = selectedProfileName();
|
|
50723
52220
|
const config = profilesConfig();
|
|
@@ -50746,15 +52243,42 @@ function AppSolid(props) {
|
|
|
50746
52243
|
let cleanupSafetyRequestId = 0;
|
|
50747
52244
|
const refreshCleanupSafety = async () => {
|
|
50748
52245
|
const requestId = ++cleanupSafetyRequestId;
|
|
50749
|
-
|
|
52246
|
+
const pendingBranches = buildCleanupSafetyPending(branchItems());
|
|
52247
|
+
setCleanupSafetyPending(pendingBranches);
|
|
52248
|
+
setCleanupSafetyLoading(pendingBranches.size > 0);
|
|
52249
|
+
const statusByBranch = new Map;
|
|
52250
|
+
const applyProgress = (status) => {
|
|
52251
|
+
if (requestId !== cleanupSafetyRequestId) {
|
|
52252
|
+
return;
|
|
52253
|
+
}
|
|
52254
|
+
statusByBranch.set(status.branch, status);
|
|
52255
|
+
batch(() => {
|
|
52256
|
+
setCleanupStatusByBranch(new Map(statusByBranch));
|
|
52257
|
+
setBranchItems((items) => applyCleanupStatus(items, statusByBranch));
|
|
52258
|
+
setCleanupSafetyPending((prev) => {
|
|
52259
|
+
if (!prev.has(status.branch)) {
|
|
52260
|
+
return prev;
|
|
52261
|
+
}
|
|
52262
|
+
const next = new Set(prev);
|
|
52263
|
+
next.delete(status.branch);
|
|
52264
|
+
return next;
|
|
52265
|
+
});
|
|
52266
|
+
});
|
|
52267
|
+
};
|
|
50750
52268
|
try {
|
|
50751
|
-
const cleanupStatuses = await getCleanupStatus(
|
|
52269
|
+
const cleanupStatuses = await getCleanupStatus({
|
|
52270
|
+
onProgress: applyProgress
|
|
52271
|
+
});
|
|
50752
52272
|
if (requestId !== cleanupSafetyRequestId) {
|
|
50753
52273
|
return;
|
|
50754
52274
|
}
|
|
50755
|
-
|
|
50756
|
-
|
|
50757
|
-
|
|
52275
|
+
if (cleanupStatuses.length > statusByBranch.size) {
|
|
52276
|
+
cleanupStatuses.forEach((status) => {
|
|
52277
|
+
if (!statusByBranch.has(status.branch)) {
|
|
52278
|
+
applyProgress(status);
|
|
52279
|
+
}
|
|
52280
|
+
});
|
|
52281
|
+
}
|
|
50758
52282
|
} catch (err) {
|
|
50759
52283
|
if (requestId !== cleanupSafetyRequestId) {
|
|
50760
52284
|
return;
|
|
@@ -50763,15 +52287,19 @@ function AppSolid(props) {
|
|
|
50763
52287
|
err
|
|
50764
52288
|
}, "Failed to refresh cleanup safety indicators");
|
|
50765
52289
|
const empty = new Map;
|
|
50766
|
-
|
|
50767
|
-
|
|
52290
|
+
batch(() => {
|
|
52291
|
+
setCleanupStatusByBranch(empty);
|
|
52292
|
+
setBranchItems((items) => applyCleanupStatus(items, empty));
|
|
52293
|
+
});
|
|
50768
52294
|
} finally {
|
|
50769
52295
|
if (requestId === cleanupSafetyRequestId) {
|
|
50770
52296
|
setCleanupSafetyLoading(false);
|
|
52297
|
+
setCleanupSafetyPending(new Set);
|
|
50771
52298
|
}
|
|
50772
52299
|
}
|
|
50773
52300
|
};
|
|
50774
52301
|
let logNotificationTimer = null;
|
|
52302
|
+
let logTailTimer = null;
|
|
50775
52303
|
let branchFooterTimer = null;
|
|
50776
52304
|
const BRANCH_LOAD_TIMEOUT_MS = 3000;
|
|
50777
52305
|
const BRANCH_FULL_LOAD_TIMEOUT_MS = 8000;
|
|
@@ -50838,9 +52366,20 @@ function AppSolid(props) {
|
|
|
50838
52366
|
setLogLoading(true);
|
|
50839
52367
|
setLogError(null);
|
|
50840
52368
|
try {
|
|
50841
|
-
const
|
|
50842
|
-
|
|
50843
|
-
|
|
52369
|
+
const target = logTarget();
|
|
52370
|
+
if (!target.logDir) {
|
|
52371
|
+
setLogEntries([]);
|
|
52372
|
+
setLogSelectedDate(targetDate);
|
|
52373
|
+
return;
|
|
52374
|
+
}
|
|
52375
|
+
const result = await readLogLinesForDate(target.logDir, targetDate);
|
|
52376
|
+
if (!result) {
|
|
52377
|
+
setLogEntries([]);
|
|
52378
|
+
setLogSelectedDate(targetDate);
|
|
52379
|
+
return;
|
|
52380
|
+
}
|
|
52381
|
+
setLogSelectedDate(result.date);
|
|
52382
|
+
const parsed = parseLogLines(result.lines, {
|
|
50844
52383
|
limit: 100
|
|
50845
52384
|
});
|
|
50846
52385
|
setLogEntries(parsed);
|
|
@@ -50851,10 +52390,39 @@ function AppSolid(props) {
|
|
|
50851
52390
|
setLogLoading(false);
|
|
50852
52391
|
}
|
|
50853
52392
|
};
|
|
52393
|
+
const clearLogTailTimer = () => {
|
|
52394
|
+
if (logTailTimer) {
|
|
52395
|
+
clearInterval(logTailTimer);
|
|
52396
|
+
logTailTimer = null;
|
|
52397
|
+
}
|
|
52398
|
+
};
|
|
52399
|
+
const toggleLogTail = () => {
|
|
52400
|
+
setLogTailEnabled((prev) => !prev);
|
|
52401
|
+
};
|
|
52402
|
+
const resetLogFiles = async () => {
|
|
52403
|
+
const target = logTarget();
|
|
52404
|
+
if (!target.logDir) {
|
|
52405
|
+
showLogNotification("No logs available.", "error");
|
|
52406
|
+
return;
|
|
52407
|
+
}
|
|
52408
|
+
try {
|
|
52409
|
+
const cleared = await clearLogFiles(target.logDir);
|
|
52410
|
+
if (cleared === 0) {
|
|
52411
|
+
showLogNotification("No logs to reset.", "error");
|
|
52412
|
+
} else {
|
|
52413
|
+
showLogNotification("Logs cleared.", "success");
|
|
52414
|
+
}
|
|
52415
|
+
await loadLogEntries(logSelectedDate());
|
|
52416
|
+
} catch (err) {
|
|
52417
|
+
logger4.warn({
|
|
52418
|
+
err
|
|
52419
|
+
}, "Failed to clear log files");
|
|
52420
|
+
showLogNotification("Failed to reset logs.", "error");
|
|
52421
|
+
}
|
|
52422
|
+
};
|
|
50854
52423
|
const refreshBranches = async () => {
|
|
50855
52424
|
setLoading(true);
|
|
50856
52425
|
setError(null);
|
|
50857
|
-
refreshCleanupSafety();
|
|
50858
52426
|
try {
|
|
50859
52427
|
const repoRoot = await getRepositoryRoot();
|
|
50860
52428
|
const worktreesPromise = listAdditionalWorktrees();
|
|
@@ -50873,6 +52441,7 @@ function AppSolid(props) {
|
|
|
50873
52441
|
const initialItems = applyCleanupStatus(initial.items, cleanupStatusByBranch());
|
|
50874
52442
|
setBranchItems(initialItems);
|
|
50875
52443
|
setStats(buildStats(initialItems));
|
|
52444
|
+
refreshCleanupSafety();
|
|
50876
52445
|
(async () => {
|
|
50877
52446
|
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
52447
|
const full = buildBranchList(branches, latestWorktrees, lastToolUsageMap);
|
|
@@ -50954,15 +52523,31 @@ function AppSolid(props) {
|
|
|
50954
52523
|
setToolError(err instanceof Error ? err : new Error(String(err)));
|
|
50955
52524
|
});
|
|
50956
52525
|
});
|
|
52526
|
+
onMount(() => {
|
|
52527
|
+
const bunxAgentIds = getBunxAgentIds();
|
|
52528
|
+
prefetchAgentVersions(bunxAgentIds).catch(() => {});
|
|
52529
|
+
});
|
|
50957
52530
|
createEffect(() => {
|
|
50958
52531
|
if (currentScreen() === "log-list") {
|
|
52532
|
+
logTarget();
|
|
50959
52533
|
loadLogEntries(logSelectedDate());
|
|
50960
52534
|
}
|
|
50961
52535
|
});
|
|
52536
|
+
createEffect(() => {
|
|
52537
|
+
if (currentScreen() !== "log-list" || !logTailEnabled()) {
|
|
52538
|
+
clearLogTailTimer();
|
|
52539
|
+
return;
|
|
52540
|
+
}
|
|
52541
|
+
clearLogTailTimer();
|
|
52542
|
+
logTailTimer = setInterval(() => {
|
|
52543
|
+
loadLogEntries(logSelectedDate());
|
|
52544
|
+
}, 1500);
|
|
52545
|
+
});
|
|
50962
52546
|
onCleanup(() => {
|
|
50963
52547
|
if (logNotificationTimer) {
|
|
50964
52548
|
clearTimeout(logNotificationTimer);
|
|
50965
52549
|
}
|
|
52550
|
+
clearLogTailTimer();
|
|
50966
52551
|
if (branchFooterTimer) {
|
|
50967
52552
|
clearTimeout(branchFooterTimer);
|
|
50968
52553
|
}
|
|
@@ -51058,6 +52643,10 @@ function AppSolid(props) {
|
|
|
51058
52643
|
});
|
|
51059
52644
|
};
|
|
51060
52645
|
const handleWizardResume = (entry) => {
|
|
52646
|
+
if (!entry.sessionId) {
|
|
52647
|
+
handleWizardStartNew(entry);
|
|
52648
|
+
return;
|
|
52649
|
+
}
|
|
51061
52650
|
setWizardVisible(false);
|
|
51062
52651
|
const branch = selectedBranch();
|
|
51063
52652
|
if (!branch) {
|
|
@@ -51166,24 +52755,10 @@ function AppSolid(props) {
|
|
|
51166
52755
|
skipCounts.remote += 1;
|
|
51167
52756
|
continue;
|
|
51168
52757
|
}
|
|
51169
|
-
if (isProtectedBranchName(branch.name)) {
|
|
51170
|
-
skipCounts.protected += 1;
|
|
51171
|
-
continue;
|
|
51172
|
-
}
|
|
51173
52758
|
if (branch.isCurrent) {
|
|
51174
52759
|
skipCounts.current += 1;
|
|
51175
52760
|
continue;
|
|
51176
52761
|
}
|
|
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
52762
|
const worktreePath = branch.worktree?.path ?? null;
|
|
51188
52763
|
const cleanupType = worktreePath ? "worktree-and-branch" : "branch-only";
|
|
51189
52764
|
const baseTask = {
|
|
@@ -51274,7 +52849,7 @@ function AppSolid(props) {
|
|
|
51274
52849
|
return;
|
|
51275
52850
|
}
|
|
51276
52851
|
const selectionSet = new Set(selection);
|
|
51277
|
-
const targets = branchItems().filter((branch) => selectionSet.has(branch.name) && branch.
|
|
52852
|
+
const targets = branchItems().filter((branch) => selectionSet.has(branch.name) && branch.type !== "remote" && branch.worktreeStatus !== undefined).map((branch) => branch.name);
|
|
51278
52853
|
if (targets.length === 0) {
|
|
51279
52854
|
showBranchFooterMessage("No worktrees to repair.", "yellow");
|
|
51280
52855
|
return;
|
|
@@ -51485,15 +53060,41 @@ function AppSolid(props) {
|
|
|
51485
53060
|
}
|
|
51486
53061
|
};
|
|
51487
53062
|
const toggleSelectedBranch = (branchName) => {
|
|
51488
|
-
|
|
51489
|
-
|
|
51490
|
-
|
|
51491
|
-
|
|
51492
|
-
|
|
51493
|
-
|
|
51494
|
-
|
|
51495
|
-
return
|
|
51496
|
-
}
|
|
53063
|
+
if (unsafeSelectionConfirmVisible()) {
|
|
53064
|
+
return;
|
|
53065
|
+
}
|
|
53066
|
+
const currentSelection = new Set(selectedBranches());
|
|
53067
|
+
if (currentSelection.has(branchName)) {
|
|
53068
|
+
currentSelection.delete(branchName);
|
|
53069
|
+
setSelectedBranches(Array.from(currentSelection));
|
|
53070
|
+
return;
|
|
53071
|
+
}
|
|
53072
|
+
const branch = branchItems().find((item) => item.name === branchName);
|
|
53073
|
+
const pending = cleanupSafetyPending();
|
|
53074
|
+
const hasSafetyPending = pending.has(branchName);
|
|
53075
|
+
const hasUncommitted = branch?.worktree?.hasUncommittedChanges === true;
|
|
53076
|
+
const hasUnpushed = branch?.hasUnpushedCommits === true;
|
|
53077
|
+
const isUnmerged = branch?.isUnmerged === true;
|
|
53078
|
+
const safeToCleanup = branch?.safeToCleanup === true;
|
|
53079
|
+
const isRemoteBranch = branch?.type === "remote";
|
|
53080
|
+
const isUnsafe = Boolean(branch) && !isRemoteBranch && !hasSafetyPending && (hasUncommitted || hasUnpushed || isUnmerged || !safeToCleanup);
|
|
53081
|
+
if (branch && isUnsafe) {
|
|
53082
|
+
setUnsafeSelectionTarget(branch.name);
|
|
53083
|
+
setUnsafeSelectionConfirmVisible(true);
|
|
53084
|
+
return;
|
|
53085
|
+
}
|
|
53086
|
+
currentSelection.add(branchName);
|
|
53087
|
+
setSelectedBranches(Array.from(currentSelection));
|
|
53088
|
+
};
|
|
53089
|
+
const confirmUnsafeSelection = (confirmed) => {
|
|
53090
|
+
suppressBranchInputOnce();
|
|
53091
|
+
const target = unsafeSelectionTarget();
|
|
53092
|
+
setUnsafeSelectionConfirmVisible(false);
|
|
53093
|
+
setUnsafeSelectionTarget(null);
|
|
53094
|
+
if (!confirmed || !target) {
|
|
53095
|
+
return;
|
|
53096
|
+
}
|
|
53097
|
+
setSelectedBranches((prev) => prev.includes(target) ? prev : [...prev, target]);
|
|
51497
53098
|
};
|
|
51498
53099
|
const handleToolSelect = (item) => {
|
|
51499
53100
|
setSelectedTool(item.value);
|
|
@@ -51544,8 +53145,9 @@ function AppSolid(props) {
|
|
|
51544
53145
|
const cleanupUI = {
|
|
51545
53146
|
indicators: cleanupIndicators(),
|
|
51546
53147
|
footerMessage: branchFooterMessage(),
|
|
51547
|
-
inputLocked: branchInputLocked(),
|
|
51548
|
-
safetyLoading: cleanupSafetyLoading()
|
|
53148
|
+
inputLocked: branchInputLocked() || unsafeConfirmInputLocked(),
|
|
53149
|
+
safetyLoading: cleanupSafetyLoading(),
|
|
53150
|
+
safetyPendingBranches: cleanupSafetyPending()
|
|
51549
53151
|
};
|
|
51550
53152
|
return createComponent2(BranchListScreen, {
|
|
51551
53153
|
get branches() {
|
|
@@ -51580,7 +53182,13 @@ function AppSolid(props) {
|
|
|
51580
53182
|
get activeProfile() {
|
|
51581
53183
|
return activeProfile();
|
|
51582
53184
|
},
|
|
51583
|
-
onOpenLogs: () =>
|
|
53185
|
+
onOpenLogs: (branch) => {
|
|
53186
|
+
setLogTargetBranch(branch);
|
|
53187
|
+
setLogSelectedEntry(null);
|
|
53188
|
+
setLogSelectedDate(getTodayLogDate());
|
|
53189
|
+
setLogTailEnabled(false);
|
|
53190
|
+
navigateTo("log-list");
|
|
53191
|
+
},
|
|
51584
53192
|
onOpenProfiles: () => navigateTo("profile"),
|
|
51585
53193
|
get selectedBranches() {
|
|
51586
53194
|
return selectedBranches();
|
|
@@ -51593,7 +53201,14 @@ function AppSolid(props) {
|
|
|
51593
53201
|
},
|
|
51594
53202
|
get wizardVisible() {
|
|
51595
53203
|
return wizardVisible();
|
|
51596
|
-
}
|
|
53204
|
+
},
|
|
53205
|
+
get confirmVisible() {
|
|
53206
|
+
return unsafeSelectionConfirmVisible();
|
|
53207
|
+
},
|
|
53208
|
+
get cursorPosition() {
|
|
53209
|
+
return branchCursorPosition();
|
|
53210
|
+
},
|
|
53211
|
+
onCursorPositionChange: setBranchCursorPosition
|
|
51597
53212
|
});
|
|
51598
53213
|
}
|
|
51599
53214
|
if (screen === "tool-select") {
|
|
@@ -51679,6 +53294,9 @@ function AppSolid(props) {
|
|
|
51679
53294
|
showLogNotification("Failed to copy to clipboard.", "error");
|
|
51680
53295
|
}
|
|
51681
53296
|
},
|
|
53297
|
+
onReload: () => void loadLogEntries(logSelectedDate()),
|
|
53298
|
+
onToggleTail: toggleLogTail,
|
|
53299
|
+
onReset: () => void resetLogFiles(),
|
|
51682
53300
|
get notification() {
|
|
51683
53301
|
return logNotification();
|
|
51684
53302
|
},
|
|
@@ -51688,6 +53306,15 @@ function AppSolid(props) {
|
|
|
51688
53306
|
get selectedDate() {
|
|
51689
53307
|
return logSelectedDate();
|
|
51690
53308
|
},
|
|
53309
|
+
get branchLabel() {
|
|
53310
|
+
return logBranchLabel();
|
|
53311
|
+
},
|
|
53312
|
+
get sourceLabel() {
|
|
53313
|
+
return logSourceLabel();
|
|
53314
|
+
},
|
|
53315
|
+
get tailing() {
|
|
53316
|
+
return logTailEnabled();
|
|
53317
|
+
},
|
|
51691
53318
|
get helpVisible() {
|
|
51692
53319
|
return helpVisible();
|
|
51693
53320
|
}
|
|
@@ -51932,7 +53559,33 @@ function AppSolid(props) {
|
|
|
51932
53559
|
}
|
|
51933
53560
|
});
|
|
51934
53561
|
};
|
|
51935
|
-
return [memo2(renderCurrentScreen),
|
|
53562
|
+
return [memo2(renderCurrentScreen), memo2(() => memo2(() => !!unsafeSelectionConfirmVisible())() && (() => {
|
|
53563
|
+
var _el$ = createElement("box");
|
|
53564
|
+
setProp(_el$, "position", "absolute");
|
|
53565
|
+
setProp(_el$, "top", "30%");
|
|
53566
|
+
setProp(_el$, "left", "20%");
|
|
53567
|
+
setProp(_el$, "zIndex", 110);
|
|
53568
|
+
setProp(_el$, "border", true);
|
|
53569
|
+
setProp(_el$, "borderStyle", "single");
|
|
53570
|
+
setProp(_el$, "borderColor", "yellow");
|
|
53571
|
+
setProp(_el$, "backgroundColor", "black");
|
|
53572
|
+
setProp(_el$, "padding", 1);
|
|
53573
|
+
insert(_el$, createComponent2(ConfirmScreen, {
|
|
53574
|
+
message: UNSAFE_SELECTION_MESSAGE,
|
|
53575
|
+
onConfirm: confirmUnsafeSelection,
|
|
53576
|
+
yesLabel: "OK",
|
|
53577
|
+
noLabel: "Cancel",
|
|
53578
|
+
defaultNo: true,
|
|
53579
|
+
get helpVisible() {
|
|
53580
|
+
return helpVisible();
|
|
53581
|
+
},
|
|
53582
|
+
get width() {
|
|
53583
|
+
return unsafeConfirmContentWidth();
|
|
53584
|
+
}
|
|
53585
|
+
}));
|
|
53586
|
+
effect((_$p) => setProp(_el$, "width", unsafeConfirmBoxWidth(), _$p));
|
|
53587
|
+
return _el$;
|
|
53588
|
+
})()), createComponent2(HelpOverlay, {
|
|
51936
53589
|
get visible() {
|
|
51937
53590
|
return helpVisible();
|
|
51938
53591
|
},
|
|
@@ -51947,7 +53600,7 @@ function AppSolid(props) {
|
|
|
51947
53600
|
return selectedBranch()?.name ?? "";
|
|
51948
53601
|
},
|
|
51949
53602
|
get history() {
|
|
51950
|
-
return
|
|
53603
|
+
return quickStartHistory();
|
|
51951
53604
|
},
|
|
51952
53605
|
onClose: handleWizardClose,
|
|
51953
53606
|
onComplete: handleWizardComplete,
|