@akiojin/gwt 4.1.1 → 4.3.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 (135) hide show
  1. package/README.md +28 -3
  2. package/dist/claude.d.ts +4 -0
  3. package/dist/claude.d.ts.map +1 -1
  4. package/dist/claude.js +13 -1
  5. package/dist/claude.js.map +1 -1
  6. package/dist/cli/ui/components/App.d.ts.map +1 -1
  7. package/dist/cli/ui/components/App.js +68 -68
  8. package/dist/cli/ui/components/App.js.map +1 -1
  9. package/dist/cli/ui/components/common/Select.d.ts +3 -1
  10. package/dist/cli/ui/components/common/Select.d.ts.map +1 -1
  11. package/dist/cli/ui/components/common/Select.js +13 -2
  12. package/dist/cli/ui/components/common/Select.js.map +1 -1
  13. package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
  14. package/dist/cli/ui/components/screens/BranchListScreen.js +6 -1
  15. package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
  16. package/dist/client/assets/index-ChHC-Puh.css +1 -0
  17. package/dist/client/assets/index-PqK9jkug.js +78 -0
  18. package/dist/client/index.html +2 -2
  19. package/dist/config/builtin-tools.d.ts.map +1 -1
  20. package/dist/config/builtin-tools.js +3 -0
  21. package/dist/config/builtin-tools.js.map +1 -1
  22. package/dist/config/tools.d.ts.map +1 -1
  23. package/dist/config/tools.js +10 -1
  24. package/dist/config/tools.js.map +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +37 -4
  27. package/dist/index.js.map +1 -1
  28. package/dist/launcher.d.ts.map +1 -1
  29. package/dist/launcher.js +15 -0
  30. package/dist/launcher.js.map +1 -1
  31. package/dist/services/aiToolResolver.d.ts.map +1 -1
  32. package/dist/services/aiToolResolver.js +55 -8
  33. package/dist/services/aiToolResolver.js.map +1 -1
  34. package/dist/services/customToolResolver.d.ts.map +1 -1
  35. package/dist/services/customToolResolver.js +22 -17
  36. package/dist/services/customToolResolver.js.map +1 -1
  37. package/dist/utils/prompt.d.ts +12 -0
  38. package/dist/utils/prompt.d.ts.map +1 -1
  39. package/dist/utils/prompt.js +60 -10
  40. package/dist/utils/prompt.js.map +1 -1
  41. package/dist/utils/webui.js +1 -1
  42. package/dist/web/client/src/components/BranchGraph.d.ts +5 -0
  43. package/dist/web/client/src/components/BranchGraph.d.ts.map +1 -1
  44. package/dist/web/client/src/components/BranchGraph.js +35 -108
  45. package/dist/web/client/src/components/BranchGraph.js.map +1 -1
  46. package/dist/web/client/src/components/graph/BranchDetailPanel.d.ts +15 -0
  47. package/dist/web/client/src/components/graph/BranchDetailPanel.d.ts.map +1 -0
  48. package/dist/web/client/src/components/graph/BranchDetailPanel.js +57 -0
  49. package/dist/web/client/src/components/graph/BranchDetailPanel.js.map +1 -0
  50. package/dist/web/client/src/components/graph/BranchNode.d.ts +13 -0
  51. package/dist/web/client/src/components/graph/BranchNode.d.ts.map +1 -0
  52. package/dist/web/client/src/components/graph/BranchNode.js +103 -0
  53. package/dist/web/client/src/components/graph/BranchNode.js.map +1 -0
  54. package/dist/web/client/src/components/graph/ClusterNode.d.ts +13 -0
  55. package/dist/web/client/src/components/graph/ClusterNode.d.ts.map +1 -0
  56. package/dist/web/client/src/components/graph/ClusterNode.js +109 -0
  57. package/dist/web/client/src/components/graph/ClusterNode.js.map +1 -0
  58. package/dist/web/client/src/components/graph/SynapticCanvas.d.ts +17 -0
  59. package/dist/web/client/src/components/graph/SynapticCanvas.d.ts.map +1 -0
  60. package/dist/web/client/src/components/graph/SynapticCanvas.js +94 -0
  61. package/dist/web/client/src/components/graph/SynapticCanvas.js.map +1 -0
  62. package/dist/web/client/src/components/graph/SynapticEdge.d.ts +13 -0
  63. package/dist/web/client/src/components/graph/SynapticEdge.d.ts.map +1 -0
  64. package/dist/web/client/src/components/graph/SynapticEdge.js +113 -0
  65. package/dist/web/client/src/components/graph/SynapticEdge.js.map +1 -0
  66. package/dist/web/client/src/components/graph/graphUtils.d.ts +67 -0
  67. package/dist/web/client/src/components/graph/graphUtils.d.ts.map +1 -0
  68. package/dist/web/client/src/components/graph/graphUtils.js +175 -0
  69. package/dist/web/client/src/components/graph/graphUtils.js.map +1 -0
  70. package/dist/web/client/src/components/graph/index.d.ts +10 -0
  71. package/dist/web/client/src/components/graph/index.d.ts.map +1 -0
  72. package/dist/web/client/src/components/graph/index.js +10 -0
  73. package/dist/web/client/src/components/graph/index.js.map +1 -0
  74. package/dist/web/client/src/lib/websocket.d.ts.map +1 -1
  75. package/dist/web/client/src/lib/websocket.js +2 -1
  76. package/dist/web/client/src/lib/websocket.js.map +1 -1
  77. package/dist/web/client/vite.config.js +1 -1
  78. package/dist/web/server/env/importer.d.ts.map +1 -1
  79. package/dist/web/server/env/importer.js +4 -0
  80. package/dist/web/server/env/importer.js.map +1 -1
  81. package/dist/web/server/index.d.ts.map +1 -1
  82. package/dist/web/server/index.js +9 -0
  83. package/dist/web/server/index.js.map +1 -1
  84. package/dist/web/server/pty/manager.d.ts.map +1 -1
  85. package/dist/web/server/pty/manager.js +24 -1
  86. package/dist/web/server/pty/manager.js.map +1 -1
  87. package/dist/web/server/routes/sessions.d.ts.map +1 -1
  88. package/dist/web/server/routes/sessions.js +7 -0
  89. package/dist/web/server/routes/sessions.js.map +1 -1
  90. package/dist/web/server/tray.d.ts +1 -1
  91. package/dist/web/server/tray.d.ts.map +1 -1
  92. package/dist/web/server/tray.js +52 -34
  93. package/dist/web/server/tray.js.map +1 -1
  94. package/dist/web/server/websocket/handler.d.ts.map +1 -1
  95. package/dist/web/server/websocket/handler.js +4 -0
  96. package/dist/web/server/websocket/handler.js.map +1 -1
  97. package/package.json +6 -3
  98. package/src/claude.ts +15 -1
  99. package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +2 -1
  100. package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +142 -8
  101. package/src/cli/ui/__tests__/components/App.test.tsx +4 -3
  102. package/src/cli/ui/__tests__/components/ModelSelectorScreen.initial.test.tsx +1 -0
  103. package/src/cli/ui/__tests__/components/common/Select.test.tsx +45 -0
  104. package/src/cli/ui/components/App.tsx +91 -81
  105. package/src/cli/ui/components/common/Select.tsx +14 -1
  106. package/src/cli/ui/components/screens/BranchListScreen.tsx +6 -1
  107. package/src/cli/ui/types.ts +1 -1
  108. package/src/config/builtin-tools.ts +3 -0
  109. package/src/config/tools.ts +24 -1
  110. package/src/index.ts +50 -3
  111. package/src/launcher.ts +26 -0
  112. package/src/services/aiToolResolver.ts +75 -9
  113. package/src/services/customToolResolver.ts +32 -17
  114. package/src/utils/__tests__/prompt.test.ts +72 -35
  115. package/src/utils/prompt.ts +79 -10
  116. package/src/utils/webui.ts +1 -1
  117. package/src/web/client/src/components/BranchGraph.tsx +51 -208
  118. package/src/web/client/src/components/graph/BranchDetailPanel.tsx +152 -0
  119. package/src/web/client/src/components/graph/BranchNode.tsx +200 -0
  120. package/src/web/client/src/components/graph/ClusterNode.tsx +211 -0
  121. package/src/web/client/src/components/graph/SynapticCanvas.tsx +171 -0
  122. package/src/web/client/src/components/graph/SynapticEdge.tsx +311 -0
  123. package/src/web/client/src/components/graph/graphUtils.ts +265 -0
  124. package/src/web/client/src/components/graph/index.ts +10 -0
  125. package/src/web/client/src/index.css +314 -29
  126. package/src/web/client/src/lib/websocket.ts +2 -1
  127. package/src/web/client/vite.config.ts +1 -1
  128. package/src/web/server/env/importer.ts +5 -0
  129. package/src/web/server/index.ts +10 -0
  130. package/src/web/server/pty/manager.ts +43 -1
  131. package/src/web/server/routes/sessions.ts +15 -0
  132. package/src/web/server/tray.ts +62 -46
  133. package/src/web/server/websocket/handler.ts +13 -0
  134. package/dist/client/assets/index-DsDNCy5f.css +0 -1
  135. package/dist/client/assets/index-v8smkNOL.js +0 -72
@@ -1,9 +1,14 @@
1
1
  import { execa } from "execa";
2
+ import { createRequire } from "node:module";
2
3
  import { createLogger } from "../../logging/logger.js";
3
- const TRAY_ICON_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAJ1BMVEUAAAAAvNQAvNQAvNQAvNQAvNQAvNQAvNQAvNQAvNQAvNQAvNT////J1ubyAAAAC3RSTlMAJYTcgyQJnJ3U3WXfUogAAAABYktHRAyBs1FjAAAAB3RJTUUH6QwMCRccbOpRBQAAAFdJREFUCNdjYEAARuXNriCarXr37t1tQEYmkN69M4GBoRvE2F3AwAqmd29kYIEwNjEwQxibGbghjN0MXDARJpgaqK6tDAzVUHMQJoPtKgPZyuq8S5WBAQBeRj51tvdhawAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyNS0xMi0xMlQwOToyMzoyOCswMDowMBPEA5UAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjUtMTItMTJUMDk6MjM6MjgrMDA6MDBimbspAAAAAElFTkSuQmCC";
4
+ const require = createRequire(import.meta.url);
5
+ // PNG icon (16x16) for macOS/Linux - Base64 encoded
6
+ const TRAY_ICON_PNG_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAdgAAAHYBTnsmCAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADLSURBVDiNpZMxDoJAEEXfLhYewMrOxsLKG3gDj+ANPIKFtScwHoHOxmN4AysLL0BlQ0Ji4W6yLLAgfslkZnbm/0wmA/9G6CogIr4F7IAbcAYOqpoEJBYD+3UADVYAiMgZOAKvboAFwFLENoAtsAdGwAw4qepZRN7A2LIIWCngCjy7t1bVF/D05QBT4K6qOxH5dOwjuwrYApdMvC3wBHzWBTwAr6p6c+wFSBJvEeDsehLVNwZ0sQDqv+kl3xjQxcKNSaZ/s+irNK1fXfwA7LE/RA3w5ggAAAAASUVORK5CYII=";
7
+ // ICO icon for Windows - Base64 encoded
8
+ const TRAY_ICON_ICO_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAJ1BMVEUAAAAAvNQAvNQAvNQAvNQAvNQAvNQAvNQAvNQAvNQAvNQAvNT////J1ubyAAAAC3RSTlMAJYTcgyQJnJ3U3WXfUogAAAABYktHRAyBs1FjAAAAB3RJTUUH6QwMCRccbOpRBQAAAFdJREFUCNdjYEAARuXNriCarXr37t1tQEYmkN69M4GBoRvE2F3AwAqmd29kYIEwNjEwQxibGbghjN0MXDARJpgaqK6tDAzVUHMQJoPtKgPZyuq8S5WBAQBeRj51tvdhawAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyNS0xMi0xMlQwOToyMzoyOCswMDowMBPEA5UAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjUtMTItMTJUMDk6MjM6MjgrMDA6MDBimbspAAAAAElFTkSuQmCC";
4
9
  let trayInitAttempted = false;
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
11
  let trayInstance = null;
6
- let trayInitPromise = null;
7
12
  function shouldEnableTray(platform = process.platform) {
8
13
  // NOTE: `trayicon` is a win32-only dependency.
9
14
  if (platform !== "win32")
@@ -39,7 +44,7 @@ export async function openUrl(url) {
39
44
  }
40
45
  /**
41
46
  * システムトレイアイコンを初期化
42
- * @param url - Web UI のURL(ダブルクリック時に開く)
47
+ * @param url - Web UI のURL(メニューから開く)
43
48
  * @param opts - オプション設定
44
49
  * @param opts.openUrl - URL を開くカスタム関数(テスト用)
45
50
  */
@@ -48,37 +53,48 @@ export async function startSystemTray(url, opts) {
48
53
  return;
49
54
  trayInitAttempted = true;
50
55
  const logger = createLogger({ category: "tray" });
56
+ const open = opts?.openUrl ?? openUrl;
51
57
  try {
52
- const mod = (await import("trayicon"));
53
- const create = mod.create ?? mod.default?.create;
54
- if (typeof create !== "function") {
55
- throw new Error("trayicon.create not available");
56
- }
57
- const icon = Buffer.from(TRAY_ICON_BASE64, "base64");
58
- const open = opts?.openUrl ?? openUrl;
59
- const initPromise = Promise.resolve(create({
60
- icon,
61
- title: "gwt Web UI",
62
- tooltip: "Double-click to open Web UI",
63
- action: async () => {
64
- await open(url);
58
+ // systray2 をCommonJS requireでインポート(ESM互換性のため)
59
+ const SysTray = require("systray2").default;
60
+ const isWindows = process.platform === "win32";
61
+ const isMacOS = process.platform === "darwin";
62
+ // プラットフォームに応じたアイコンを選択
63
+ const iconBase64 = isWindows ? TRAY_ICON_ICO_BASE64 : TRAY_ICON_PNG_BASE64;
64
+ const openDashboardItem = {
65
+ title: "Open Web UI",
66
+ tooltip: "Open gwt Web UI in browser",
67
+ checked: false,
68
+ enabled: true,
69
+ };
70
+ const exitItem = {
71
+ title: "Exit",
72
+ tooltip: "Close the tray icon",
73
+ checked: false,
74
+ enabled: true,
75
+ };
76
+ trayInstance = new SysTray({
77
+ menu: {
78
+ icon: iconBase64,
79
+ isTemplateIcon: isMacOS,
80
+ title: "gwt",
81
+ tooltip: `gwt Web UI - ${url}`,
82
+ items: [openDashboardItem, SysTray.separator, exitItem],
65
83
  },
66
- }));
67
- trayInitPromise = initPromise;
68
- void initPromise
69
- .then((tray) => {
70
- if (trayInitPromise !== initPromise) {
71
- tray.dispose?.();
72
- tray.kill?.();
73
- return;
84
+ debug: false,
85
+ copyDir: false,
86
+ });
87
+ trayInstance.onClick((action) => {
88
+ if (action.item.title === "Open Web UI") {
89
+ open(url);
90
+ }
91
+ else if (action.item.title === "Exit") {
92
+ trayInstance?.kill(false);
93
+ trayInstance = null;
74
94
  }
75
- trayInstance = tray;
76
- })
77
- .catch((err) => {
78
- if (trayInitPromise !== initPromise)
79
- return;
80
- logger.warn({ err }, "System tray failed to initialize");
81
95
  });
96
+ await trayInstance.ready();
97
+ logger.info("System tray initialized");
82
98
  }
83
99
  catch (err) {
84
100
  logger.warn({ err }, "System tray failed to initialize");
@@ -88,11 +104,13 @@ export async function startSystemTray(url, opts) {
88
104
  * システムトレイアイコンを破棄
89
105
  */
90
106
  export function disposeSystemTray() {
91
- trayInitPromise = null;
92
- const instance = trayInstance;
107
+ try {
108
+ trayInstance?.kill?.(false);
109
+ }
110
+ catch {
111
+ // Ignore errors during cleanup
112
+ }
93
113
  trayInstance = null;
94
- instance?.dispose?.();
95
- instance?.kill?.();
96
114
  trayInitAttempted = false;
97
115
  }
98
116
  //# sourceMappingURL=tray.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tray.js","sourceRoot":"","sources":["../../../src/web/server/tray.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tray.js","sourceRoot":"","sources":["../../../src/web/server/tray.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../src/web/server/websocket/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWpD;;GAEG;AACH,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,MAAM;IAJhB,OAAO,CAAC,aAAa,CAA0C;gBAGrD,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,iBAAiB;IAGnC;;OAEG;IACI,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IAsFnE;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAsC3B;;OAEG;IACH,OAAO,CAAC,UAAU;IASlB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAchB;;OAEG;IACH,OAAO,CAAC,SAAS;IAWjB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,iBAAiB;CAQ1B;AAID,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;CACzC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,cAAc,GAAG,WAAW,GACpC,MAAM,GAAG,IAAI,CAqBf"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../src/web/server/websocket/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWpD;;GAEG;AACH,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,MAAM;IAJhB,OAAO,CAAC,aAAa,CAA0C;gBAGrD,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,iBAAiB;IAGnC;;OAEG;IACI,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IAmGnE;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAsC3B;;OAEG;IACH,OAAO,CAAC,UAAU;IASlB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAchB;;OAEG;IACH,OAAO,CAAC,SAAS;IAWjB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,iBAAiB;CAQ1B;AAID,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;CACzC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,cAAc,GAAG,WAAW,GACpC,MAAM,GAAG,IAAI,CAqBf"}
@@ -21,12 +21,14 @@ export class WebSocketHandler {
21
21
  handle(connection, request) {
22
22
  const sessionId = resolveSessionId(request);
23
23
  if (!sessionId) {
24
+ this.logger.warn({ error: "Missing sessionId" }, "WebSocket session resolution failed");
24
25
  this.sendError(connection, "Missing sessionId parameter");
25
26
  connection.close();
26
27
  return;
27
28
  }
28
29
  const instance = this.ptyManager.get(sessionId);
29
30
  if (!instance) {
31
+ this.logger.warn({ sessionId, error: "not found" }, "WebSocket session not found");
30
32
  this.sendError(connection, `Session not found: ${sessionId}`);
31
33
  connection.close();
32
34
  return;
@@ -44,6 +46,7 @@ export class WebSocketHandler {
44
46
  // PTYプロセス終了時の処理
45
47
  ptyProcess.onExit(({ exitCode, signal }) => {
46
48
  hasExited = true;
49
+ this.logger.info({ sessionId, exitCode, signal }, "PTY process exited");
47
50
  this.clearCleanupTimer(sessionId);
48
51
  this.ptyManager.updateStatus(sessionId, "completed", exitCode);
49
52
  this.sendExit(connection, exitCode, signal);
@@ -61,6 +64,7 @@ export class WebSocketHandler {
61
64
  }
62
65
  catch (error) {
63
66
  const errorMsg = error instanceof Error ? error.message : String(error);
67
+ this.logger.warn({ sessionId, error: errorMsg }, "WebSocket message parse error");
64
68
  this.sendError(connection, `Invalid message format: ${errorMsg}`);
65
69
  }
66
70
  });
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../src/web/server/websocket/handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../src/web/server/websocket/handler.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akiojin/gwt",
3
- "version": "4.1.1",
3
+ "version": "4.3.0",
4
4
  "description": "Interactive Git worktree manager for Claude Code with graphical branch selection",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -64,7 +64,9 @@
64
64
  "@radix-ui/react-tooltip": "^1.2.8",
65
65
  "@tailwindcss/vite": "^4.1.18",
66
66
  "@tanstack/react-query": "^5.66.1",
67
+ "@xyflow/react": "^12.10.0",
67
68
  "chalk": "^5.4.1",
69
+ "d3-force": "^3.0.0",
68
70
  "execa": "^9.6.0",
69
71
  "fastify": "^5.2.1",
70
72
  "ink": "^6.3.1",
@@ -77,8 +79,8 @@
77
79
  "react-router": "^7.2.0",
78
80
  "react-router-dom": "^7.2.0",
79
81
  "string-width": "^8.1.0",
82
+ "systray2": "^2.1.4",
80
83
  "tailwindcss": "^4.1.18",
81
- "trayicon": "^1.2.2",
82
84
  "ws": "^8.18.0",
83
85
  "xterm": "^5.4.0-beta.37",
84
86
  "xterm-addon-fit": "^0.9.0-beta.37",
@@ -91,6 +93,7 @@
91
93
  "@playwright/test": "^1.51.0",
92
94
  "@testing-library/jest-dom": "^6.9.1",
93
95
  "@testing-library/react": "^16.3.0",
96
+ "@types/d3-force": "^3.0.10",
94
97
  "@types/node": "^25.0.2",
95
98
  "@types/react": "^19.2.2",
96
99
  "@types/react-dom": "^19.0.3",
@@ -120,7 +123,7 @@
120
123
  "vitest": "^4.0.8"
121
124
  },
122
125
  "lint-staged": {
123
- "*.md": "bunx --bun markdownlint-cli -c .markdownlint.json",
126
+ "**/*.md": "bunx --bun markdownlint-cli -c .markdownlint.json --ignore CHANGELOG.md --ignore node_modules",
124
127
  "*.{ts,tsx}": [
125
128
  "bunx eslint --max-warnings=0 --no-warn-ignored",
126
129
  "bunx prettier --check"
package/src/claude.ts CHANGED
@@ -37,6 +37,7 @@ export class ClaudeError extends Error {
37
37
  *
38
38
  * @param worktreePath - Worktree directory to run Claude Code in
39
39
  * @param options - Launch options (mode/session/model/permissions/env)
40
+ * @param options.chrome - Enable Chrome extension integration (adds --chrome flag)
40
41
  * @returns Captured session id when available
41
42
  */
42
43
  export async function launchClaudeCode(
@@ -48,6 +49,7 @@ export async function launchClaudeCode(
48
49
  envOverrides?: Record<string, string>;
49
50
  model?: string;
50
51
  sessionId?: string | null;
52
+ chrome?: boolean;
51
53
  } = {},
52
54
  ): Promise<{ sessionId?: string | null }> {
53
55
  const terminal = getTerminalStreams();
@@ -169,6 +171,12 @@ export async function launchClaudeCode(
169
171
  break;
170
172
  }
171
173
 
174
+ // Handle Chrome extension integration
175
+ if (options.chrome) {
176
+ args.push("--chrome");
177
+ console.log(chalk.green(" 🌐 Chrome integration enabled"));
178
+ }
179
+
172
180
  // Detect root user for Docker/sandbox environments
173
181
  let isRoot = false;
174
182
  try {
@@ -201,7 +209,11 @@ export async function launchClaudeCode(
201
209
  terminal.exitRawMode();
202
210
  resetTerminalModes(terminal.stdout);
203
211
 
204
- const baseEnv = { ...process.env, ...(options.envOverrides ?? {}) };
212
+ const baseEnv: Record<string, string | undefined> = {
213
+ ...process.env,
214
+ ...(options.envOverrides ?? {}),
215
+ ENABLE_LSP_TOOL: "true", // Enable TypeScript LSP support in Claude Code
216
+ };
205
217
  const launchEnvSource =
206
218
  options.skipPermissions && !baseEnv.IS_SANDBOX
207
219
  ? { ...baseEnv, IS_SANDBOX: "1" }
@@ -407,6 +419,8 @@ async function isNpxCommandAvailable(): Promise<boolean> {
407
419
 
408
420
  /**
409
421
  * Checks whether Claude Code is available via `bunx` in the current environment.
422
+ *
423
+ * @returns true if Claude Code can be resolved via bunx, false otherwise.
410
424
  */
411
425
  export async function isClaudeCodeAvailable(): Promise<boolean> {
412
426
  try {
@@ -103,6 +103,7 @@ describe("App protected branch handling", () => {
103
103
  branchListProps.length = 0;
104
104
  branchActionProps.length = 0;
105
105
  aiToolProps.length = 0;
106
+ branchQuickStartProps.length = 0;
106
107
 
107
108
  useGitDataMock.mockReset();
108
109
  switchToProtectedBranchMock.mockReset();
@@ -194,7 +195,6 @@ describe("App protected branch handling", () => {
194
195
  await act(async () => {
195
196
  actionProps?.onUseExisting();
196
197
  await Promise.resolve();
197
- await Promise.resolve();
198
198
  });
199
199
 
200
200
  expect(switchToProtectedBranchMock).toHaveBeenCalledWith({
@@ -206,6 +206,7 @@ describe("App protected branch handling", () => {
206
206
  expect(navigateToMock).toHaveBeenCalledWith("branch-action-selector");
207
207
  // When branchQuickStart is empty, navigates to ai-tool-selector instead of branch-quick-start
208
208
  // So AIToolSelectorScreen should be rendered, not BranchQuickStartScreen
209
+ expect(branchQuickStartProps).toHaveLength(0);
209
210
  expect(aiToolProps).not.toHaveLength(0);
210
211
  });
211
212
  });
@@ -35,10 +35,10 @@ vi.mock("../../hooks/useScreenState.js", () => ({
35
35
  useScreenState: (...args: unknown[]) => useScreenStateMock(...args),
36
36
  }));
37
37
 
38
- vi.mock("../../../../worktree.js", async () => {
38
+ vi.mock("../../../../worktree.ts", async () => {
39
39
  const actual = await vi.importActual<
40
- typeof import("../../../../worktree.js")
41
- >("../../../../worktree.js");
40
+ typeof import("../../../../worktree.ts")
41
+ >("../../../../worktree.ts");
42
42
  return {
43
43
  ...actual,
44
44
  getMergedPRWorktrees: getMergedPRWorktreesMock,
@@ -48,10 +48,10 @@ vi.mock("../../../../worktree.js", async () => {
48
48
  };
49
49
  });
50
50
 
51
- vi.mock("../../../../git.js", async () => {
51
+ vi.mock("../../../../git.ts", async () => {
52
52
  const actual =
53
- await vi.importActual<typeof import("../../../../git.js")>(
54
- "../../../../git.js",
53
+ await vi.importActual<typeof import("../../../../git.ts")>(
54
+ "../../../../git.ts",
55
55
  );
56
56
  return {
57
57
  ...actual,
@@ -92,8 +92,33 @@ describe("App shortcuts integration", () => {
92
92
  goBackMock.mockClear();
93
93
  resetMock.mockClear();
94
94
  useGitDataMock.mockReturnValue({
95
- branches: [],
95
+ branches: [
96
+ {
97
+ name: "feature/add-new-feature",
98
+ type: "local",
99
+ branchType: "feature",
100
+ isCurrent: false,
101
+ },
102
+ {
103
+ name: "hotfix/urgent-fix",
104
+ type: "local",
105
+ branchType: "hotfix",
106
+ isCurrent: false,
107
+ },
108
+ ],
96
109
  worktrees: [
110
+ {
111
+ branch: "feature/add-new-feature",
112
+ path: "/worktrees/feature-add-new-feature",
113
+ isAccessible: true,
114
+ hasUncommittedChanges: false,
115
+ },
116
+ {
117
+ branch: "hotfix/urgent-fix",
118
+ path: "/worktrees/hotfix-urgent-fix",
119
+ isAccessible: true,
120
+ hasUncommittedChanges: true,
121
+ },
97
122
  {
98
123
  branch: "feature/existing",
99
124
  path: "/worktrees/feature-existing",
@@ -195,8 +220,102 @@ describe("App shortcuts integration", () => {
195
220
  expect(navigateToMock).toHaveBeenCalledWith("ai-tool-selector");
196
221
  });
197
222
 
223
+ it("shows warning when cleanup runs without selection", async () => {
224
+ const onExit = vi.fn();
225
+
226
+ render(<App onExit={onExit} />);
227
+
228
+ const initialProps = branchListProps.at(-1);
229
+ expect(initialProps).toBeDefined();
230
+
231
+ act(() => {
232
+ initialProps?.onCleanupCommand?.();
233
+ });
234
+
235
+ await act(async () => {
236
+ await Promise.resolve();
237
+ });
238
+
239
+ const latestProps = branchListProps.at(-1);
240
+ expect(latestProps?.cleanupUI?.footerMessage?.text).toBe(
241
+ "クリーンアップ対象が選択されていません",
242
+ );
243
+ expect(removeWorktreeMock).not.toHaveBeenCalled();
244
+ expect(deleteBranchMock).not.toHaveBeenCalled();
245
+ });
246
+
247
+ it("marks branches safe only when merged and clean", () => {
248
+ const onExit = vi.fn();
249
+ const refresh = vi.fn();
250
+ useGitDataMock.mockReturnValue({
251
+ branches: [
252
+ {
253
+ name: "feature/merged-clean",
254
+ type: "local",
255
+ branchType: "feature",
256
+ isCurrent: false,
257
+ mergedPR: { number: 101, mergedAt: "2025-01-02T10:00:00Z" },
258
+ },
259
+ {
260
+ name: "feature/merged-unpushed",
261
+ type: "local",
262
+ branchType: "feature",
263
+ isCurrent: false,
264
+ hasUnpushedCommits: true,
265
+ mergedPR: { number: 102, mergedAt: "2025-01-03T10:00:00Z" },
266
+ },
267
+ {
268
+ name: "feature/unmerged",
269
+ type: "local",
270
+ branchType: "feature",
271
+ isCurrent: false,
272
+ },
273
+ ],
274
+ worktrees: [
275
+ {
276
+ branch: "feature/merged-clean",
277
+ path: "/worktrees/merged-clean",
278
+ isAccessible: true,
279
+ hasUncommittedChanges: false,
280
+ },
281
+ {
282
+ branch: "feature/merged-unpushed",
283
+ path: "/worktrees/merged-unpushed",
284
+ isAccessible: true,
285
+ hasUncommittedChanges: false,
286
+ },
287
+ {
288
+ branch: "feature/unmerged",
289
+ path: "/worktrees/unmerged",
290
+ isAccessible: true,
291
+ hasUncommittedChanges: false,
292
+ },
293
+ ],
294
+ loading: false,
295
+ error: null,
296
+ refresh,
297
+ lastUpdated: null,
298
+ });
299
+
300
+ render(<App onExit={onExit} />);
301
+
302
+ const latestProps = branchListProps.at(-1);
303
+ const safeMap = new Map(
304
+ latestProps?.branches?.map((branch: BranchItem) => [
305
+ branch.name,
306
+ branch.safeToCleanup,
307
+ ]),
308
+ );
309
+
310
+ expect(safeMap.get("feature/merged-clean")).toBe(true);
311
+ expect(safeMap.get("feature/merged-unpushed")).toBe(false);
312
+ expect(safeMap.get("feature/unmerged")).toBe(false);
313
+ });
314
+
198
315
  it("displays per-branch cleanup indicators and waits before clearing results", async () => {
199
316
  vi.useFakeTimers();
317
+ const originalNodeEnv = process.env.NODE_ENV;
318
+ process.env.NODE_ENV = "production";
200
319
 
201
320
  try {
202
321
  const onExit = vi.fn();
@@ -234,8 +353,22 @@ describe("App shortcuts integration", () => {
234
353
  throw new Error("BranchListScreen props missing");
235
354
  }
236
355
 
356
+ await act(async () => {
357
+ initialProps.onToggleSelect?.("feature/add-new-feature");
358
+ initialProps.onToggleSelect?.("hotfix/urgent-fix");
359
+ });
360
+
361
+ await act(async () => {
362
+ await Promise.resolve();
363
+ });
364
+
365
+ const selectedProps = branchListProps.at(-1);
366
+ expect(selectedProps?.selectedBranches).toEqual([
367
+ "feature/add-new-feature",
368
+ "hotfix/urgent-fix",
369
+ ]);
237
370
  act(() => {
238
- initialProps.onCleanupCommand?.();
371
+ selectedProps?.onCleanupCommand?.();
239
372
  });
240
373
 
241
374
  await act(async () => {
@@ -296,6 +429,7 @@ describe("App shortcuts integration", () => {
296
429
  ),
297
430
  ).toBe(false);
298
431
  } finally {
432
+ process.env.NODE_ENV = originalNodeEnv;
299
433
  vi.useRealTimers();
300
434
  }
301
435
  });
@@ -251,6 +251,7 @@ describe("App", () => {
251
251
  });
252
252
 
253
253
  describe("BranchActionSelectorScreen integration", () => {
254
+ // TODO: replace placeholder assertions with real integration checks.
254
255
  it("should show BranchActionSelectorScreen after branch selection", () => {
255
256
  useGitDataMock.mockImplementation(() => ({
256
257
  branches: mockBranches,
@@ -263,7 +264,7 @@ describe("App", () => {
263
264
  const onExit = vi.fn();
264
265
  const { container } = render(<App onExit={onExit} />);
265
266
 
266
- // After implementation, should verify BranchActionSelectorScreen appears
267
+ // TODO: verify BranchActionSelectorScreen appears
267
268
  expect(container).toBeDefined();
268
269
  });
269
270
 
@@ -279,7 +280,7 @@ describe("App", () => {
279
280
  const onExit = vi.fn();
280
281
  const { container } = render(<App onExit={onExit} />);
281
282
 
282
- // After implementation, should verify navigation to AIToolSelectorScreen
283
+ // TODO: verify navigation to AIToolSelectorScreen
283
284
  expect(container).toBeDefined();
284
285
  });
285
286
 
@@ -295,7 +296,7 @@ describe("App", () => {
295
296
  const onExit = vi.fn();
296
297
  const { container } = render(<App onExit={onExit} />);
297
298
 
298
- // After implementation, should verify navigation to BranchCreatorScreen
299
+ // TODO: verify navigation to BranchCreatorScreen
299
300
  expect(container).toBeDefined();
300
301
  });
301
302
  });
@@ -54,6 +54,7 @@ describe("ModelSelectorScreen initial selection", () => {
54
54
 
55
55
  await waitFor(() => expect(selectMocks.length).toBeGreaterThan(0));
56
56
  const modelSelect = selectMocks.at(-1);
57
+ expect(modelSelect).toBeDefined();
57
58
  const index = modelSelect.initialIndex as number;
58
59
  // codex-cli models: ["", gpt-5.2-codex, gpt-5.1-codex-max, gpt-5.1-codex-mini, gpt-5.2]
59
60
  // (index 0 = Default/Auto, index 2 = gpt-5.1-codex-max)
@@ -12,6 +12,9 @@ interface TestItem {
12
12
  value: string;
13
13
  }
14
14
 
15
+ const delay = (ms = 0): Promise<void> =>
16
+ new Promise((resolve) => setTimeout(resolve, ms));
17
+
15
18
  describe("Select", () => {
16
19
  const mockItems: TestItem[] = [
17
20
  { label: "Option 1", value: "opt1" },
@@ -281,4 +284,46 @@ describe("Select", () => {
281
284
  expect(onSelect).not.toHaveBeenCalled();
282
285
  });
283
286
  });
287
+
288
+ describe('Space/Escape handlers', () => {
289
+ it('should call onSpace with the currently highlighted item', async () => {
290
+ const onSelect = vi.fn();
291
+ const onSpace = vi.fn();
292
+ const { stdin } = render(
293
+ <Select items={mockItems} onSelect={onSelect} onSpace={onSpace} />
294
+ );
295
+
296
+ stdin.write(' ');
297
+ await delay(10);
298
+
299
+ expect(onSpace).toHaveBeenCalledTimes(1);
300
+ expect(onSpace).toHaveBeenCalledWith(mockItems[0]);
301
+ });
302
+
303
+ it('should not trigger onSpace when disabled', async () => {
304
+ const onSelect = vi.fn();
305
+ const onSpace = vi.fn();
306
+ const { stdin } = render(
307
+ <Select items={mockItems} onSelect={onSelect} onSpace={onSpace} disabled />
308
+ );
309
+
310
+ stdin.write(' ');
311
+ await delay(10);
312
+
313
+ expect(onSpace).not.toHaveBeenCalled();
314
+ });
315
+
316
+ it('should call onEscape when escape key is pressed', async () => {
317
+ const onSelect = vi.fn();
318
+ const onEscape = vi.fn();
319
+ const { stdin } = render(
320
+ <Select items={mockItems} onSelect={onSelect} onEscape={onEscape} />
321
+ );
322
+
323
+ stdin.write('\u001B');
324
+ await delay(30);
325
+
326
+ expect(onEscape).toHaveBeenCalledTimes(1);
327
+ });
328
+ });
284
329
  });