@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.
Files changed (36) hide show
  1. package/README.ja.md +4 -4
  2. package/README.md +4 -4
  3. package/dist/cli/ui/components/screens/BranchListScreen.js +1 -1
  4. package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
  5. package/dist/cli/ui/components/screens/BranchQuickStartScreen.d.ts.map +1 -1
  6. package/dist/cli/ui/components/screens/BranchQuickStartScreen.js +26 -11
  7. package/dist/cli/ui/components/screens/BranchQuickStartScreen.js.map +1 -1
  8. package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts.map +1 -1
  9. package/dist/cli/ui/components/screens/ModelSelectorScreen.js +0 -5
  10. package/dist/cli/ui/components/screens/ModelSelectorScreen.js.map +1 -1
  11. package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -1
  12. package/dist/cli/ui/utils/modelOptions.js +25 -16
  13. package/dist/cli/ui/utils/modelOptions.js.map +1 -1
  14. package/dist/config/builtin-tools.d.ts +2 -0
  15. package/dist/config/builtin-tools.d.ts.map +1 -1
  16. package/dist/config/builtin-tools.js +2 -0
  17. package/dist/config/builtin-tools.js.map +1 -1
  18. package/dist/config/tools.d.ts.map +1 -1
  19. package/dist/config/tools.js +4 -1
  20. package/dist/config/tools.js.map +1 -1
  21. package/dist/gemini.d.ts.map +1 -1
  22. package/dist/gemini.js +22 -40
  23. package/dist/gemini.js.map +1 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +5 -20
  26. package/dist/index.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/cli/ui/components/screens/BranchListScreen.tsx +1 -1
  29. package/src/cli/ui/components/screens/BranchQuickStartScreen.tsx +40 -22
  30. package/src/cli/ui/components/screens/ModelSelectorScreen.tsx +0 -8
  31. package/src/cli/ui/utils/modelOptions.test.ts +9 -6
  32. package/src/cli/ui/utils/modelOptions.ts +25 -18
  33. package/src/config/builtin-tools.ts +2 -0
  34. package/src/config/tools.ts +5 -1
  35. package/src/gemini.ts +22 -47
  36. 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
- // Capture session ID from Gemini's exit summary
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
- runArgs: string[],
162
- ): Promise<string | undefined> => {
163
- // Capture stdout while passing through to terminal
164
- // Store chunks to extract session ID after process exits
165
- const outputChunks: string[] = [];
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 runWithCapture = async (cmd: string, args: string[]) => {
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: "pipe",
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 runWithCapture("gemini", runArgs);
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 runWithCapture("bunx", [GEMINI_CLI_PACKAGE, ...runArgs]);
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
- output = await runGemini(argsPrimary);
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
- output = await runGemini(argsFallback);
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}`);