File size: 7,685 Bytes
0dfbd72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
#!/usr/bin/env node

/**
 * Creates placeholder sidecar binaries for development mode.
 *
 * In dev mode, Tauri requires the sidecar binary files to exist at compile time,
 * even though developers typically run the Python server manually.
 *
 * This script creates minimal placeholder binaries that allow Tauri to compile.
 * The actual server should be started separately with `bun run dev:server`.
 */

import { execSync } from 'child_process';
import { existsSync, mkdirSync, statSync, writeFileSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const BINARIES_DIR = join(__dirname, '..', 'tauri', 'src-tauri', 'binaries');

// Minimum size to consider a binary "real" (placeholder is ~256 bytes, real is MBs)
const MIN_REAL_BINARY_SIZE = 10000;

// Get the current platform's target triple
function getTargetTriple() {
  try {
    const triple = execSync('rustc --print host-tuple', { encoding: 'utf-8' }).trim();
    return triple;
  } catch {
    // Fallback detection
    const platform = process.platform;
    const arch = process.arch;

    if (platform === 'win32') {
      return arch === 'x64' ? 'x86_64-pc-windows-msvc' : 'i686-pc-windows-msvc';
    } else if (platform === 'darwin') {
      return arch === 'arm64' ? 'aarch64-apple-darwin' : 'x86_64-apple-darwin';
    } else if (platform === 'linux') {
      return arch === 'x64' ? 'x86_64-unknown-linux-gnu' : 'aarch64-unknown-linux-gnu';
    }

    throw new Error(`Unsupported platform: ${platform}/${arch}`);
  }
}

// Create a minimal executable for the platform. ``baseName`` is the
// sidecar identifier as declared in tauri.conf.json's ``externalBin``
// (e.g. "voicebox-server", "voicebox-mcp"). Tauri appends the target
// triple to that name at compile time.
function createPlaceholderBinary(targetTriple, baseName) {
  const isWindows = targetTriple.includes('windows');
  const binaryName = `${baseName}-${targetTriple}${isWindows ? '.exe' : ''}`;
  const binaryPath = join(BINARIES_DIR, binaryName);

  // Check if real binary already exists (larger than our placeholder)
  if (existsSync(binaryPath)) {
    try {
      const stats = statSync(binaryPath);
      if (stats.size > MIN_REAL_BINARY_SIZE) {
        console.log(
          `Real binary already exists: ${binaryName} (${(stats.size / 1024 / 1024).toFixed(1)} MB)`,
        );
        return;
      }
    } catch {
      // File exists but can't stat - try to replace it
    }
  }

  // Ensure binaries directory exists
  if (!existsSync(BINARIES_DIR)) {
    mkdirSync(BINARIES_DIR, { recursive: true });
  }

  if (isWindows) {
    // Create a minimal valid Windows PE executable that exits with code 1
    // This is the smallest valid PE that Windows will accept
    const minimalPE = Buffer.from([
      // DOS Header
      0x4d,
      0x5a,
      0x90,
      0x00,
      0x03,
      0x00,
      0x00,
      0x00,
      0x04,
      0x00,
      0x00,
      0x00,
      0xff,
      0xff,
      0x00,
      0x00,
      0xb8,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x40,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x80,
      0x00,
      0x00,
      0x00,
      // DOS Stub
      0x0e,
      0x1f,
      0xba,
      0x0e,
      0x00,
      0xb4,
      0x09,
      0xcd,
      0x21,
      0xb8,
      0x01,
      0x4c,
      0xcd,
      0x21,
      0x54,
      0x68,
      0x69,
      0x73,
      0x20,
      0x70,
      0x72,
      0x6f,
      0x67,
      0x72,
      0x61,
      0x6d,
      0x20,
      0x63,
      0x61,
      0x6e,
      0x6e,
      0x6f,
      0x74,
      0x20,
      0x62,
      0x65,
      0x20,
      0x72,
      0x75,
      0x6e,
      0x20,
      0x69,
      0x6e,
      0x20,
      0x44,
      0x4f,
      0x53,
      0x20,
      0x6d,
      0x6f,
      0x64,
      0x65,
      0x2e,
      0x0d,
      0x0d,
      0x0a,
      0x24,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      // PE Signature
      0x50,
      0x45,
      0x00,
      0x00,
      // COFF Header (x64)
      0x64,
      0x86, // Machine: AMD64
      0x01,
      0x00, // NumberOfSections: 1
      0x00,
      0x00,
      0x00,
      0x00, // TimeDateStamp
      0x00,
      0x00,
      0x00,
      0x00, // PointerToSymbolTable
      0x00,
      0x00,
      0x00,
      0x00, // NumberOfSymbols
      0xf0,
      0x00, // SizeOfOptionalHeader
      0x22,
      0x00, // Characteristics: EXECUTABLE_IMAGE | LARGE_ADDRESS_AWARE
      // Optional Header (PE32+)
      0x0b,
      0x02, // Magic: PE32+
      0x00,
      0x00, // Linker version
      0x00,
      0x00,
      0x00,
      0x00, // SizeOfCode
      0x00,
      0x00,
      0x00,
      0x00, // SizeOfInitializedData
      0x00,
      0x00,
      0x00,
      0x00, // SizeOfUninitializedData
      0x00,
      0x10,
      0x00,
      0x00, // AddressOfEntryPoint
      0x00,
      0x00,
      0x00,
      0x00, // BaseOfCode
      0x00,
      0x00,
      0x00,
      0x40,
      0x01,
      0x00,
      0x00,
      0x00, // ImageBase
      0x00,
      0x10,
      0x00,
      0x00, // SectionAlignment
      0x00,
      0x02,
      0x00,
      0x00, // FileAlignment
      0x06,
      0x00,
      0x00,
      0x00, // OS version
      0x00,
      0x00,
      0x00,
      0x00, // Image version
      0x06,
      0x00,
      0x00,
      0x00, // Subsystem version
      0x00,
      0x00,
      0x00,
      0x00, // Win32VersionValue
      0x00,
      0x20,
      0x00,
      0x00, // SizeOfImage
      0x00,
      0x02,
      0x00,
      0x00, // SizeOfHeaders
      0x00,
      0x00,
      0x00,
      0x00, // CheckSum
      0x03,
      0x00, // Subsystem: CONSOLE
      0x60,
      0x01, // DllCharacteristics
      // Stack/Heap sizes (8 bytes each for PE32+)
      0x00,
      0x00,
      0x10,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x10,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00, // LoaderFlags
      0x10,
      0x00,
      0x00,
      0x00, // NumberOfRvaAndSizes
    ]);

    // Pad to 512 bytes minimum for valid PE
    const paddedPE = Buffer.alloc(512);
    minimalPE.copy(paddedPE);
    writeFileSync(binaryPath, paddedPE);
  } else {
    // Create a minimal shell script for Unix-like systems
    const script = `#!/bin/sh
echo "[${baseName}] Dev mode placeholder - start the real server with: bun run dev:server"
exit 1
`;
    writeFileSync(binaryPath, script, { mode: 0o755 });
  }

  console.log(`Created dev placeholder: ${binaryName}`);
}

// Every sidecar listed in tauri.conf.json's ``externalBin`` needs a
// file on disk at compile time, even in dev. Add to this list whenever
// a new sidecar is introduced.
const SIDECAR_BASE_NAMES = ['voicebox-server', 'voicebox-mcp'];

function main() {
  const targetTriple = getTargetTriple();
  for (const baseName of SIDECAR_BASE_NAMES) {
    createPlaceholderBinary(targetTriple, baseName);
  }
}

main();