@akiojin/gwt 3.1.2 → 4.0.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/README.ja.md +4 -4
- package/README.md +4 -4
- package/dist/cli/ui/components/screens/BranchListScreen.js +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.js +26 -11
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/ModelSelectorScreen.js +0 -5
- package/dist/cli/ui/components/screens/ModelSelectorScreen.js.map +1 -1
- package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -1
- package/dist/cli/ui/utils/modelOptions.js +25 -16
- package/dist/cli/ui/utils/modelOptions.js.map +1 -1
- package/dist/config/builtin-tools.d.ts +2 -0
- package/dist/config/builtin-tools.d.ts.map +1 -1
- package/dist/config/builtin-tools.js +2 -0
- package/dist/config/builtin-tools.js.map +1 -1
- package/dist/config/tools.d.ts.map +1 -1
- package/dist/config/tools.js +4 -1
- package/dist/config/tools.js.map +1 -1
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +22 -40
- package/dist/gemini.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/ui/components/screens/BranchListScreen.tsx +1 -1
- package/src/cli/ui/components/screens/BranchQuickStartScreen.tsx +40 -22
- package/src/cli/ui/components/screens/ModelSelectorScreen.tsx +0 -8
- package/src/cli/ui/utils/modelOptions.test.ts +9 -6
- package/src/cli/ui/utils/modelOptions.ts +25 -18
- package/src/config/builtin-tools.ts +2 -0
- package/src/config/tools.ts +5 -1
- package/src/gemini.ts +22 -47
- package/src/index.ts +6 -26
package/src/gemini.ts
CHANGED
|
@@ -134,62 +134,41 @@ export async function launchGeminiCLI(
|
|
|
134
134
|
// Auto-detect locally installed gemini command
|
|
135
135
|
const hasLocalGemini = await isGeminiCommandAvailable();
|
|
136
136
|
|
|
137
|
-
//
|
|
137
|
+
// Preserve TTY for interactive UI (colors/width) by inheriting stdout/stderr.
|
|
138
|
+
// Session ID is determined via file-based detection after exit.
|
|
138
139
|
let capturedSessionId: string | null = null;
|
|
139
|
-
const extractSessionId = (output: string | undefined) => {
|
|
140
|
-
if (!output) return;
|
|
141
|
-
// Gemini outputs "Session ID: <uuid>" in exit summary
|
|
142
|
-
// UUID may be split across lines due to terminal width
|
|
143
|
-
// First, find "Session ID:" and extract following hex characters
|
|
144
|
-
const sessionIdIndex = output.indexOf("Session ID:");
|
|
145
|
-
if (sessionIdIndex === -1) return;
|
|
146
|
-
|
|
147
|
-
// Extract text after "Session ID:" until we have enough hex chars for UUID
|
|
148
|
-
const afterLabel = output.slice(sessionIdIndex + "Session ID:".length);
|
|
149
|
-
// Remove all non-hex characters except dash, then extract UUID pattern
|
|
150
|
-
const hexOnly = afterLabel.replace(/[^0-9a-fA-F-]/g, "");
|
|
151
|
-
// UUID format: 8-4-4-4-12 = 32 hex chars + 4 dashes
|
|
152
|
-
const uuidMatch = hexOnly.match(
|
|
153
|
-
/^([0-9a-f]{8})-?([0-9a-f]{4})-?([0-9a-f]{4})-?([0-9a-f]{4})-?([0-9a-f]{12})/i,
|
|
154
|
-
);
|
|
155
|
-
if (uuidMatch) {
|
|
156
|
-
capturedSessionId = `${uuidMatch[1]}-${uuidMatch[2]}-${uuidMatch[3]}-${uuidMatch[4]}-${uuidMatch[5]}`;
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
140
|
|
|
160
|
-
const runGemini = async (
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
141
|
+
const runGemini = async (runArgs: string[]): Promise<void> => {
|
|
142
|
+
const execChild = async (child: Promise<unknown>) => {
|
|
143
|
+
try {
|
|
144
|
+
await child;
|
|
145
|
+
} catch (execError: unknown) {
|
|
146
|
+
// Treat SIGINT/SIGTERM as normal exit (user pressed Ctrl+C)
|
|
147
|
+
const signal = (execError as { signal?: unknown })?.signal;
|
|
148
|
+
if (signal === "SIGINT" || signal === "SIGTERM") {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
throw execError;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
166
154
|
|
|
167
|
-
const
|
|
155
|
+
const run = async (cmd: string, args: string[]) => {
|
|
168
156
|
const child = execa(cmd, args, {
|
|
169
157
|
cwd: worktreePath,
|
|
170
158
|
shell: true,
|
|
171
159
|
stdin: childStdio.stdin,
|
|
172
|
-
stdout:
|
|
160
|
+
stdout: childStdio.stdout,
|
|
173
161
|
stderr: childStdio.stderr,
|
|
174
162
|
env: baseEnv,
|
|
175
163
|
});
|
|
176
|
-
|
|
177
|
-
// Pass stdout through to terminal while capturing
|
|
178
|
-
child.stdout?.on("data", (chunk: Buffer) => {
|
|
179
|
-
const text = chunk.toString("utf8");
|
|
180
|
-
outputChunks.push(text);
|
|
181
|
-
terminal.stdout.write(chunk);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
await child;
|
|
185
|
-
return outputChunks.join("");
|
|
164
|
+
await execChild(child);
|
|
186
165
|
};
|
|
187
166
|
|
|
188
167
|
if (hasLocalGemini) {
|
|
189
168
|
console.log(
|
|
190
169
|
chalk.green(" ✨ Using locally installed gemini command"),
|
|
191
170
|
);
|
|
192
|
-
return await
|
|
171
|
+
return await run("gemini", runArgs);
|
|
193
172
|
}
|
|
194
173
|
console.log(
|
|
195
174
|
chalk.cyan(" 🔄 Falling back to bunx @google/gemini-cli@latest"),
|
|
@@ -202,15 +181,14 @@ export async function launchGeminiCLI(
|
|
|
202
181
|
console.log(chalk.yellow(" npm install -g @google/gemini-cli"));
|
|
203
182
|
console.log("");
|
|
204
183
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
205
|
-
return await
|
|
184
|
+
return await run("bunx", [GEMINI_CLI_PACKAGE, ...runArgs]);
|
|
206
185
|
};
|
|
207
186
|
|
|
208
|
-
let output: string | undefined;
|
|
209
187
|
let fellBackToLatest = false;
|
|
210
188
|
try {
|
|
211
189
|
// Try with explicit session ID first (if any), then fallback to --resume (latest) once
|
|
212
190
|
try {
|
|
213
|
-
|
|
191
|
+
await runGemini(argsPrimary);
|
|
214
192
|
} catch (err) {
|
|
215
193
|
const shouldRetry =
|
|
216
194
|
(options.mode === "resume" || options.mode === "continue") &&
|
|
@@ -222,7 +200,7 @@ export async function launchGeminiCLI(
|
|
|
222
200
|
` ⚠️ Failed to resume session ${resumeSessionId}. Retrying with latest session...`,
|
|
223
201
|
),
|
|
224
202
|
);
|
|
225
|
-
|
|
203
|
+
await runGemini(argsFallback);
|
|
226
204
|
} else {
|
|
227
205
|
throw err;
|
|
228
206
|
}
|
|
@@ -231,9 +209,6 @@ export async function launchGeminiCLI(
|
|
|
231
209
|
childStdio.cleanup();
|
|
232
210
|
}
|
|
233
211
|
|
|
234
|
-
// Extract session ID from Gemini's exit summary output
|
|
235
|
-
extractSessionId(output);
|
|
236
|
-
|
|
237
212
|
const explicitResumeSucceeded = usedExplicitSessionId && !fellBackToLatest;
|
|
238
213
|
|
|
239
214
|
// If we explicitly resumed a specific session (and did not fall back), keep that ID.
|
package/src/index.ts
CHANGED
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
type CodexReasoningEffort,
|
|
17
17
|
} from "./codex.js";
|
|
18
18
|
import { launchGeminiCLI, GeminiError } from "./gemini.js";
|
|
19
|
-
import { launchQwenCLI, QwenError } from "./qwen.js";
|
|
20
19
|
import {
|
|
21
20
|
WorktreeOrchestrator,
|
|
22
21
|
type EnsureWorktreeOptions,
|
|
@@ -117,7 +116,6 @@ function isRecoverableError(error: unknown): boolean {
|
|
|
117
116
|
error instanceof WorktreeError ||
|
|
118
117
|
error instanceof CodexError ||
|
|
119
118
|
error instanceof GeminiError ||
|
|
120
|
-
error instanceof QwenError ||
|
|
121
119
|
error instanceof DependencyInstallError
|
|
122
120
|
) {
|
|
123
121
|
return true;
|
|
@@ -129,7 +127,6 @@ function isRecoverableError(error: unknown): boolean {
|
|
|
129
127
|
error.name === "WorktreeError" ||
|
|
130
128
|
error.name === "CodexError" ||
|
|
131
129
|
error.name === "GeminiError" ||
|
|
132
|
-
error.name === "QwenError" ||
|
|
133
130
|
error.name === "DependencyInstallError"
|
|
134
131
|
);
|
|
135
132
|
}
|
|
@@ -144,7 +141,6 @@ function isRecoverableError(error: unknown): boolean {
|
|
|
144
141
|
name === "WorktreeError" ||
|
|
145
142
|
name === "CodexError" ||
|
|
146
143
|
name === "GeminiError" ||
|
|
147
|
-
name === "QwenError" ||
|
|
148
144
|
name === "DependencyInstallError"
|
|
149
145
|
);
|
|
150
146
|
}
|
|
@@ -311,6 +307,12 @@ export async function handleAIToolWorkflow(
|
|
|
311
307
|
`Selected: ${branchLabel} with ${tool} (${mode} mode${modelInfo}, skipPermissions: ${skipPermissions})`,
|
|
312
308
|
);
|
|
313
309
|
|
|
310
|
+
if (tool === "qwen-cli") {
|
|
311
|
+
printError("Qwen CLI is currently unsupported.");
|
|
312
|
+
await waitForErrorAcknowledgement();
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
314
316
|
try {
|
|
315
317
|
// Get repository root
|
|
316
318
|
const repoRootResult = await runGitStep("retrieve repository root", () =>
|
|
@@ -658,28 +660,6 @@ export async function handleAIToolWorkflow(
|
|
|
658
660
|
launchOptions.model = model;
|
|
659
661
|
}
|
|
660
662
|
launchResult = await launchGeminiCLI(worktreePath, launchOptions);
|
|
661
|
-
} else if (tool === "qwen-cli") {
|
|
662
|
-
const launchOptions: {
|
|
663
|
-
mode?: "normal" | "continue" | "resume";
|
|
664
|
-
skipPermissions?: boolean;
|
|
665
|
-
envOverrides?: Record<string, string>;
|
|
666
|
-
model?: string;
|
|
667
|
-
sessionId?: string | null;
|
|
668
|
-
} = {
|
|
669
|
-
mode:
|
|
670
|
-
mode === "resume"
|
|
671
|
-
? "resume"
|
|
672
|
-
: mode === "continue"
|
|
673
|
-
? "continue"
|
|
674
|
-
: "normal",
|
|
675
|
-
skipPermissions,
|
|
676
|
-
envOverrides: sharedEnv,
|
|
677
|
-
sessionId: resumeSessionId,
|
|
678
|
-
};
|
|
679
|
-
if (model) {
|
|
680
|
-
launchOptions.model = model;
|
|
681
|
-
}
|
|
682
|
-
launchResult = await launchQwenCLI(worktreePath, launchOptions);
|
|
683
663
|
} else {
|
|
684
664
|
// Custom tool
|
|
685
665
|
printInfo(`Launching custom tool: ${toolConfig.displayName}`);
|