Skip to content

Commit 3099a3b

Browse files
SonAIengineclaude
andcommitted
feat: graph-tool-call PyInstaller sidecar 번들링 — 앱 빌트인
graph-tool-call을 PyInstaller로 단일 바이너리 빌드하여 Tauri sidecar로 번들: - CI에서 macOS/Windows 각각 PyInstaller 빌드 (Python 3.12) - src-tauri/binaries/graph-tool-call-{target_triple} 형태로 배치 - tauri.conf.json externalBin 설정 추가 - tool_search.rs: 번들 sidecar 우선 탐색, PATH fallback 사용자 PC에 Python 설치 불필요 — 앱 설치만으로 동적 tool 검색/실행 가능 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c90392c commit 3099a3b

4 files changed

Lines changed: 64 additions & 7 deletions

File tree

.github/workflows/build-windows.yml

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,37 @@ env:
1313
TAURI_ENV: "true"
1414
NEXT_PUBLIC_BACKEND_HOST: "https://xgen.x2bee.com"
1515
NEXT_PUBLIC_BACKEND_PORT: ""
16+
GRAPH_TOOL_CALL_VERSION: "0.13.1"
1617

1718
jobs:
1819
build-windows:
1920
runs-on: windows-latest
20-
timeout-minutes: 60
21+
timeout-minutes: 90
2122

2223
steps:
2324
- name: Checkout
2425
uses: actions/checkout@v4
2526

27+
# --- PyInstaller: graph-tool-call sidecar ---
28+
- name: Setup Python
29+
uses: actions/setup-python@v5
30+
with:
31+
python-version: '3.12'
32+
33+
- name: Build graph-tool-call sidecar (Windows)
34+
shell: bash
35+
run: |
36+
pip install "graph-tool-call[mcp]==$GRAPH_TOOL_CALL_VERSION" pyinstaller
37+
# Find the entry point
38+
ENTRY=$(python -c "import graph_tool_call.__main__; print(graph_tool_call.__main__.__file__)")
39+
echo "Entry point: $ENTRY"
40+
pyinstaller --onefile --name graph-tool-call --hidden-import graph_tool_call "$ENTRY"
41+
# Copy to Tauri sidecar directory with target triple suffix
42+
mkdir -p src-tauri/binaries
43+
cp dist/graph-tool-call.exe "src-tauri/binaries/graph-tool-call-x86_64-pc-windows-msvc.exe"
44+
echo "Sidecar built: $(ls -lh src-tauri/binaries/)"
45+
46+
# --- Frontend: xgen-frontend clone & build ---
2647
- name: Setup Node.js
2748
uses: actions/setup-node@v4
2849
with:
@@ -56,6 +77,7 @@ jobs:
5677
if (!(Test-Path "frontend/out")) { Write-Error "frontend/out not found"; exit 1 }
5778
Write-Host "Frontend build OK: $(Get-ChildItem -Recurse frontend/out -File | Measure-Object | Select-Object -ExpandProperty Count) files"
5879
80+
# --- Tauri: Rust build ---
5981
- name: Setup Rust
6082
uses: dtolnay/rust-toolchain@stable
6183

@@ -88,12 +110,32 @@ jobs:
88110

89111
build-macos:
90112
runs-on: macos-latest
91-
timeout-minutes: 60
113+
timeout-minutes: 90
92114

93115
steps:
94116
- name: Checkout
95117
uses: actions/checkout@v4
96118

119+
# --- PyInstaller: graph-tool-call sidecar ---
120+
- name: Setup Python
121+
uses: actions/setup-python@v5
122+
with:
123+
python-version: '3.12'
124+
125+
- name: Build graph-tool-call sidecar (macOS)
126+
run: |
127+
pip install "graph-tool-call[mcp]==$GRAPH_TOOL_CALL_VERSION" pyinstaller
128+
# Find the entry point
129+
ENTRY=$(python -c "import graph_tool_call.__main__; print(graph_tool_call.__main__.__file__)")
130+
echo "Entry point: $ENTRY"
131+
pyinstaller --onefile --name graph-tool-call --hidden-import graph_tool_call "$ENTRY"
132+
# Copy to Tauri sidecar directory with target triple suffix
133+
mkdir -p src-tauri/binaries
134+
cp dist/graph-tool-call "src-tauri/binaries/graph-tool-call-aarch64-apple-darwin"
135+
chmod +x "src-tauri/binaries/graph-tool-call-aarch64-apple-darwin"
136+
echo "Sidecar built: $(ls -lh src-tauri/binaries/)"
137+
138+
# --- Frontend ---
97139
- name: Setup Node.js
98140
uses: actions/setup-node@v4
99141
with:
@@ -122,6 +164,7 @@ jobs:
122164
test -d frontend/out || (echo "frontend/out not found" && exit 1)
123165
echo "Frontend build OK: $(find frontend/out -type f | wc -l) files"
124166
167+
# --- Tauri ---
125168
- name: Setup Rust
126169
uses: dtolnay/rust-toolchain@stable
127170

src-tauri/binaries/.gitkeep

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Placeholder - CI에서 PyInstaller 빌드 결과물이 여기에 배치됩니다

src-tauri/src/services/tool_search.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,49 @@ use crate::error::{AppError, Result};
1818
const DEFAULT_TOP_K: usize = 5;
1919

2020
/// graph-tool-call sidecar 경로 찾기
21+
/// Tauri externalBin으로 번들된 바이너리를 우선 사용, 없으면 PATH에서 찾기
2122
fn find_binary() -> Result<String> {
22-
// 1. 환경변수
23+
// 1. 환경변수 (개발/테스트용)
2324
if let Ok(path) = std::env::var("GRAPH_TOOL_CALL_BIN") {
2425
if std::path::Path::new(&path).exists() {
2526
return Ok(path);
2627
}
2728
}
2829

29-
// 2. 실행 파일 옆 (Tauri 번들)
30+
// 2. Tauri 번들 sidecar (externalBin)
31+
// 빌드 시 binaries/graph-tool-call-{target_triple} 형태로 번들됨
32+
// 실행 시 앱 리소스 디렉토리에 graph-tool-call[-suffix] 로 배치
3033
if let Ok(exe) = std::env::current_exe() {
3134
if let Some(dir) = exe.parent() {
32-
for name in &["graph-tool-call", "graph-tool-call.exe", "graph-tool-call-bin", "graph-tool-call-bin.exe"] {
35+
for name in &[
36+
"graph-tool-call",
37+
"graph-tool-call.exe",
38+
// Tauri sidecar naming convention
39+
&format!("graph-tool-call-{}", std::env::consts::ARCH),
40+
] {
3341
let p = dir.join(name);
3442
if p.exists() {
43+
log::info!("Found bundled graph-tool-call: {}", p.display());
3544
return Ok(p.to_string_lossy().to_string());
3645
}
3746
}
3847
}
3948
}
4049

41-
// 3. 시스템 PATH
50+
// 3. 시스템 PATH (개발 환경 fallback)
4251
for cmd in &["which", "where"] {
4352
if let Ok(output) = std::process::Command::new(cmd).arg("graph-tool-call").output() {
4453
if output.status.success() {
4554
let path = String::from_utf8_lossy(&output.stdout).lines().next().unwrap_or("").trim().to_string();
4655
if !path.is_empty() && std::path::Path::new(&path).exists() {
56+
log::info!("Found graph-tool-call in PATH: {}", path);
4757
return Ok(path);
4858
}
4959
}
5060
}
5161
}
5262

53-
Err(AppError::Cli("graph-tool-call 바이너리를 찾을 수 없습니다".into()))
63+
Err(AppError::Cli("graph-tool-call 바이너리를 찾을 수 없습니다. 앱을 재설치하세요.".into()))
5464
}
5565

5666
/// graph 캐시 파일 경로

src-tauri/tauri.conf.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
"bundle": {
2525
"active": true,
2626
"targets": "all",
27+
"externalBin": [
28+
"binaries/graph-tool-call"
29+
],
2730
"icon": [
2831
"icons/32x32.png",
2932
"icons/128x128.png",

0 commit comments

Comments
 (0)