droid-patch 0.13.5 → 0.14.1

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.md CHANGED
@@ -65,7 +65,7 @@ npx droid-patch --skip-login -o /path/to/dir my-droid
65
65
  | `--websearch` | External providers mode: Smithery, Google PSE, Tavily, Serper, Brave, SearXNG, DuckDuckGo |
66
66
  | `--websearch-proxy` | Native provider mode: use model's built-in web_search (requires proxy plugin) |
67
67
  | `--standalone` | Standalone mode: mock non-LLM Factory APIs (use with `--websearch` or `--websearch-proxy`) |
68
- | `--reasoning-effort` | Enable reasoning effort UI selector for custom models (set to high) |
68
+ | `--reasoning-effort` | Enable reasoning effort UI selector for custom models (default `high`; options: `high`, `max`, `xhigh`) |
69
69
  | `--disable-telemetry` | Disable telemetry and Sentry error reporting |
70
70
  | `--dry-run` | Verify patches without actually modifying the binary |
71
71
  | `-p, --path <path>` | Path to the droid binary (default: `~/.droid/bin/droid`) |
@@ -341,7 +341,7 @@ Configure your custom model in `~/.factory/settings.json`:
341
341
 
342
342
  Enables reasoning effort control for custom models by patching the binary to:
343
343
 
344
- 1. Set `supportedReasoningEfforts` from `["none"]` to `["high"]`
344
+ 1. Set `supportedReasoningEfforts` from `["none"]` to `["high","max","xhigh"]`
345
345
  2. Set `defaultReasoningEffort` from `"none"` to `"high"`
346
346
  3. Enable the reasoning effort UI selector (normally hidden for custom models)
347
347
  4. Bypass validation to allow `xhigh` via settings.json
@@ -352,7 +352,7 @@ Enables reasoning effort control for custom models by patching the binary to:
352
352
 
353
353
  - The droid UI shows a reasoning effort selector when `supportedReasoningEfforts.length > 1`
354
354
  - Custom models are hardcoded with `["none"]`, hiding the selector
355
- - This patch changes the value to `["high"]` and modifies the UI condition to show the selector
355
+ - This patch changes the value to `["high","max","xhigh"]` and modifies the UI condition to show the selector
356
356
  - The reasoning effort setting will be sent to your custom model's API
357
357
 
358
358
  **Usage**:
@@ -382,9 +382,8 @@ Available values:
382
382
  | Value | Description |
383
383
  |-------|-------------|
384
384
  | `high` | High reasoning effort (default after patching) |
385
+ | `max` | Maximum reasoning effort |
385
386
  | `xhigh` | Extra high reasoning effort |
386
- | `medium` | Medium reasoning effort |
387
- | `low` | Low reasoning effort |
388
387
 
389
388
  **Note**: The `xhigh` value bypasses validation and is sent directly to your API. Make sure your custom model/proxy supports this parameter.
390
389
 
package/README.zh-CN.md CHANGED
@@ -65,7 +65,7 @@ npx droid-patch --skip-login -o /path/to/dir my-droid
65
65
  | `--websearch` | 外部搜索模式:使用 Smithery、Google PSE、Tavily、Serper、Brave、SearXNG、DuckDuckGo |
66
66
  | `--websearch-proxy` | 原生搜索模式:使用模型内置的 web_search 能力(需要 proxy 插件) |
67
67
  | `--standalone` | 独立模式:mock 非 LLM 的 Factory API(与 `--websearch` 或 `--websearch-proxy` 配合使用) |
68
- | `--reasoning-effort` | 为自定义模型启用推理强度 UI 选择器(设置为 high|
68
+ | `--reasoning-effort` | 为自定义模型启用推理强度 UI 选择器(默认 `high`;可选:`high`、`max`、`xhigh`) |
69
69
  | `--disable-telemetry` | 禁用遥测数据上传和 Sentry 错误报告 |
70
70
  | `--dry-run` | 验证修补但不实际修改二进制文件 |
71
71
  | `-p, --path <path>` | droid 二进制文件路径(默认:`~/.droid/bin/droid`) |
@@ -335,7 +335,7 @@ pnpm dev
335
335
 
336
336
  通过修补二进制文件为自定义模型启用推理强度控制:
337
337
 
338
- 1. 将 `supportedReasoningEfforts` 从 `["none"]` 改为 `["high"]`
338
+ 1. 将 `supportedReasoningEfforts` 从 `["none"]` 改为 `["high","max","xhigh"]`
339
339
  2. 将 `defaultReasoningEffort` 从 `"none"` 改为 `"high"`
340
340
  3. 启用推理强度 UI 选择器(通常对自定义模型隐藏)
341
341
  4. 绕过验证以允许通过 settings.json 设置 `xhigh`
@@ -346,7 +346,7 @@ pnpm dev
346
346
 
347
347
  - 当 `supportedReasoningEfforts.length > 1` 时,droid UI 会显示推理强度选择器
348
348
  - 自定义模型硬编码为 `["none"]`,隐藏了选择器
349
- - 此补丁将值改为 `["high"]` 并修改 UI 条件以显示选择器
349
+ - 此补丁将值改为 `["high","max","xhigh"]` 并修改 UI 条件以显示选择器
350
350
  - 推理强度设置将发送到您的自定义模型 API
351
351
 
352
352
  **使用方法**:
@@ -376,9 +376,8 @@ npx droid-patch --is-custom --reasoning-effort droid-full
376
376
  | 值 | 描述 |
377
377
  |-------|-------------|
378
378
  | `high` | 高推理强度(补丁后的默认值) |
379
+ | `max` | 最大推理强度 |
379
380
  | `xhigh` | 超高推理强度 |
380
- | `medium` | 中等推理强度 |
381
- | `low` | 低推理强度 |
382
381
 
383
382
  **注意**:`xhigh` 值会绕过验证直接发送到 API。请确保您的自定义模型/代理支持此参数。
384
383
 
@@ -19,9 +19,34 @@ async function patchDroid(options) {
19
19
  const buffer = Buffer.from(data);
20
20
  const workingBuffer = Buffer.from(buffer);
21
21
  const results = [];
22
+ const resultByName = /* @__PURE__ */ new Map();
22
23
  for (const patch of patches) {
23
- console.log(styleText("white", `[*] Checking patch: ${styleText("yellow", patch.name)}`));
24
- console.log(styleText("gray", ` ${patch.description}`));
24
+ if (patch.skipIfAnySucceeded?.some((dependencyName) => {
25
+ const dependencyResult = resultByName.get(dependencyName);
26
+ return !!dependencyResult && (dependencyResult.found > 0 || dependencyResult.alreadyPatched);
27
+ }) ?? false) {
28
+ const skippedResult = {
29
+ name: patch.name,
30
+ found: 0,
31
+ success: true,
32
+ alreadyPatched: true,
33
+ hidden: true,
34
+ skipped: true
35
+ };
36
+ results.push(skippedResult);
37
+ resultByName.set(patch.name, skippedResult);
38
+ continue;
39
+ }
40
+ const suppressCheckUnlessFound = !!patch.suppressCheckUnlessFound;
41
+ let checkLogged = false;
42
+ const logCheckHeader = () => {
43
+ if (!checkLogged) {
44
+ console.log(styleText("white", `[*] Checking patch: ${styleText("yellow", patch.name)}`));
45
+ console.log(styleText("gray", ` ${patch.description}`));
46
+ checkLogged = true;
47
+ }
48
+ };
49
+ if (!suppressCheckUnlessFound) logCheckHeader();
25
50
  if (patch.regexPattern && patch.regexReplacement) {
26
51
  const content = workingBuffer.toString("utf-8");
27
52
  const regex = new RegExp(patch.regexPattern.source, "g");
@@ -36,36 +61,44 @@ async function patchDroid(options) {
36
61
  });
37
62
  }
38
63
  if (matches.length === 0) {
39
- console.log(styleText("yellow", ` ! Pattern not found - may already be patched`));
40
64
  let alreadyPatched = false;
41
65
  if (patch.alreadyPatchedRegexPattern) alreadyPatched = new RegExp(patch.alreadyPatchedRegexPattern.source, "g").test(content);
42
66
  else {
43
67
  const sampleReplacement = patch.regexReplacement.replace(/\$\d+/g, "X");
44
68
  alreadyPatched = content.includes(sampleReplacement.slice(0, 20));
45
69
  }
46
- results.push({
70
+ if (!suppressCheckUnlessFound || alreadyPatched) logCheckHeader();
71
+ if (!suppressCheckUnlessFound) console.log(styleText("yellow", ` ! Pattern not found - may already be patched`));
72
+ const missIsHidden = suppressCheckUnlessFound && !alreadyPatched;
73
+ const result = {
47
74
  name: patch.name,
48
75
  found: 0,
49
- success: alreadyPatched,
50
- alreadyPatched
51
- });
76
+ success: alreadyPatched || missIsHidden,
77
+ alreadyPatched,
78
+ hidden: missIsHidden
79
+ };
80
+ results.push(result);
81
+ resultByName.set(patch.name, result);
52
82
  if (alreadyPatched) console.log(styleText("blue", ` ✓ Binary appears to be already patched`));
53
83
  continue;
54
84
  }
85
+ logCheckHeader();
55
86
  console.log(styleText("green", ` ✓ Found ${matches.length} occurrences (regex)`));
56
- if (!dryRun) for (const { match: match$1, replacement } of matches) {
57
- const matchBuffer = Buffer.from(match$1, "utf-8");
87
+ if (!dryRun) for (const { match, replacement } of matches) {
88
+ const matchBuffer = Buffer.from(match, "utf-8");
58
89
  const replacementBuffer = Buffer.from(replacement, "utf-8");
59
90
  if (matchBuffer.length !== replacementBuffer.length) console.log(styleText("yellow", ` ! Warning: Length mismatch: ${matchBuffer.length} vs ${replacementBuffer.length}`));
60
91
  const bytePos = workingBuffer.indexOf(matchBuffer);
61
92
  if (bytePos !== -1) replacementBuffer.copy(workingBuffer, bytePos, 0, replacementBuffer.length);
62
93
  }
63
- results.push({
94
+ const result = {
64
95
  name: patch.name,
65
96
  found: matches.length,
66
97
  positions: matches.map((m) => m.charIndex),
67
98
  success: true
68
- });
99
+ };
100
+ results.push(result);
101
+ resultByName.set(patch.name, result);
69
102
  continue;
70
103
  }
71
104
  const variants = [{
@@ -82,24 +115,32 @@ async function patchDroid(options) {
82
115
  }
83
116
  }
84
117
  if (positions.length === 0) {
85
- console.log(styleText("yellow", ` ! Pattern not found - may already be patched`));
86
- results.push({
118
+ const alreadyPatched = variants.some((v) => workingBuffer.includes(v.replacement));
119
+ const missIsHidden = suppressCheckUnlessFound && !alreadyPatched;
120
+ if (!suppressCheckUnlessFound || alreadyPatched) logCheckHeader();
121
+ if (!suppressCheckUnlessFound) console.log(styleText("yellow", ` ! Pattern not found - may already be patched`));
122
+ const result = {
87
123
  name: patch.name,
88
124
  found: 0,
89
- success: false,
90
- alreadyPatched: variants.some((v) => workingBuffer.includes(v.replacement))
91
- });
125
+ success: alreadyPatched || missIsHidden,
126
+ alreadyPatched,
127
+ hidden: missIsHidden
128
+ };
129
+ results.push(result);
92
130
  let totalReplacementPositions = 0;
93
131
  for (const variant of variants) totalReplacementPositions += findAllPositions(workingBuffer, variant.replacement).length;
94
132
  if (totalReplacementPositions > 0) {
133
+ logCheckHeader();
95
134
  console.log(styleText("blue", ` ✓ Found ${totalReplacementPositions} occurrences of patched pattern`));
96
135
  console.log(styleText("blue", ` ✓ Binary appears to be already patched`));
97
136
  results[results.length - 1].alreadyPatched = true;
98
137
  results[results.length - 1].success = true;
99
138
  }
139
+ resultByName.set(patch.name, results[results.length - 1]);
100
140
  continue;
101
141
  }
102
142
  if (!matchedVariant) throw new Error(`Internal error: matchedVariant not set for patch ${patch.name}`);
143
+ logCheckHeader();
103
144
  console.log(styleText("green", ` ✓ Found ${positions.length} occurrences`));
104
145
  if (verbose) {
105
146
  for (const pos of positions.slice(0, 5)) {
@@ -109,12 +150,14 @@ async function patchDroid(options) {
109
150
  if (positions.length > 5) console.log(styleText("gray", ` ... and ${positions.length - 5} more`));
110
151
  }
111
152
  if (!dryRun) for (const pos of positions) matchedVariant.replacement.copy(workingBuffer, pos);
112
- results.push({
153
+ const result = {
113
154
  name: patch.name,
114
155
  found: positions.length,
115
156
  positions,
116
157
  success: true
117
- });
158
+ };
159
+ results.push(result);
160
+ resultByName.set(patch.name, result);
118
161
  }
119
162
  console.log();
120
163
  if (dryRun) {
@@ -122,9 +165,12 @@ async function patchDroid(options) {
122
165
  console.log(styleText(["blue", "bold"], " DRY RUN RESULTS"));
123
166
  console.log(styleText("blue", "─".repeat(60)));
124
167
  console.log();
125
- for (const result of results) if (result.alreadyPatched) console.log(styleText("blue", ` [✓] ${result.name}: Already patched`));
126
- else if (result.found > 0) console.log(styleText("green", ` [✓] ${result.name}: ${result.found} occurrences will be patched`));
127
- else console.log(styleText("yellow", ` [!] ${result.name}: Pattern not found`));
168
+ for (const result of results) {
169
+ if (result.hidden || result.skipped) continue;
170
+ if (result.alreadyPatched) console.log(styleText("blue", ` [] ${result.name}: Already patched`));
171
+ else if (result.found > 0) console.log(styleText("green", ` [✓] ${result.name}: ${result.found} occurrences will be patched`));
172
+ else console.log(styleText("yellow", ` [!] ${result.name}: Pattern not found`));
173
+ }
128
174
  return {
129
175
  success: results.every((r) => r.success || r.alreadyPatched),
130
176
  dryRun: true,
@@ -176,7 +222,9 @@ async function patchDroid(options) {
176
222
  console.log(styleText("white", "[*] Verifying patches..."));
177
223
  const verifyBuffer = await readFile(actualOutputPath);
178
224
  let allVerified = true;
179
- for (const patch of patches) {
225
+ for (let i = 0; i < patches.length; i++) {
226
+ const patch = patches[i];
227
+ if (results[i]?.hidden || results[i]?.skipped) continue;
180
228
  if (patch.regexPattern && patch.regexReplacement) {
181
229
  const oldMatches = [...verifyBuffer.toString("utf-8").matchAll(new RegExp(patch.regexPattern.source, "g"))];
182
230
  if (oldMatches.length === 0) console.log(styleText("green", ` ✓ ${patch.name}: Verified (regex)`));
@@ -486,28 +534,28 @@ async function createAlias(patchedBinaryPath, aliasName, verbose = false) {
486
534
  const writablePathDir = findWritablePathDir();
487
535
  if (writablePathDir) {
488
536
  const targetPath = join(writablePathDir, aliasName);
489
- const binaryDest$1 = join(BINS_DIR, `${aliasName}-patched`);
490
- await copyFile(patchedBinaryPath, binaryDest$1);
491
- await chmod(binaryDest$1, 493);
492
- if (verbose) console.log(styleText("gray", ` Stored binary: ${binaryDest$1}`));
537
+ const binaryDest = join(BINS_DIR, `${aliasName}-patched`);
538
+ await copyFile(patchedBinaryPath, binaryDest);
539
+ await chmod(binaryDest, 493);
540
+ if (verbose) console.log(styleText("gray", ` Stored binary: ${binaryDest}`));
493
541
  if (existsSync(targetPath)) {
494
542
  await unlink(targetPath);
495
543
  if (verbose) console.log(styleText("gray", ` Removed existing: ${targetPath}`));
496
544
  }
497
- await symlink(binaryDest$1, targetPath);
545
+ await symlink(binaryDest, targetPath);
498
546
  if (process.platform === "darwin") {
499
547
  try {
500
548
  console.log(styleText("gray", "[*] Re-signing binary for macOS..."));
501
- execSync(`codesign --force --deep --sign - "${binaryDest$1}"`, { stdio: "pipe" });
549
+ execSync(`codesign --force --deep --sign - "${binaryDest}"`, { stdio: "pipe" });
502
550
  console.log(styleText("green", "[*] Binary re-signed successfully"));
503
551
  } catch {
504
552
  console.log(styleText("yellow", "[!] Could not re-sign binary"));
505
553
  }
506
554
  try {
507
- execSync(`xattr -cr "${binaryDest$1}"`, { stdio: "pipe" });
555
+ execSync(`xattr -cr "${binaryDest}"`, { stdio: "pipe" });
508
556
  } catch {}
509
557
  }
510
- console.log(styleText("green", `[*] Created: ${targetPath} -> ${binaryDest$1}`));
558
+ console.log(styleText("green", `[*] Created: ${targetPath} -> ${binaryDest}`));
511
559
  console.log();
512
560
  console.log(styleText("green", "─".repeat(60)));
513
561
  console.log(styleText(["green", "bold"], " ALIAS READY - NO ACTION REQUIRED!"));
@@ -517,7 +565,7 @@ async function createAlias(patchedBinaryPath, aliasName, verbose = false) {
517
565
  console.log(styleText("gray", `(Installed to: ${writablePathDir})`));
518
566
  return {
519
567
  aliasPath: targetPath,
520
- binaryPath: binaryDest$1,
568
+ binaryPath: binaryDest,
521
569
  immediate: true
522
570
  };
523
571
  }
@@ -1300,4 +1348,4 @@ async function clearAllAliases() {
1300
1348
 
1301
1349
  //#endregion
1302
1350
  export { removeAlias as a, restoreOriginal as c, listAllMetadata as d, loadAliasMetadata as f, listAliases as i, createMetadata as l, patchDroid as m, createAlias as n, removeAliasesByFilter as o, saveAliasMetadata as p, createAliasForWrapper as r, replaceOriginal as s, clearAllAliases as t, formatPatches as u };
1303
- //# sourceMappingURL=alias-DTf8YAYU.mjs.map
1351
+ //# sourceMappingURL=alias-DgX_0sGe.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alias-DgX_0sGe.mjs","names":["IS_WINDOWS"],"sources":["../src/patcher.ts","../src/metadata.ts","../src/alias.ts"],"sourcesContent":["import { readFile, writeFile, copyFile, chmod, stat } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { execSync } from \"node:child_process\";\nimport { styleText } from \"node:util\";\nimport { platform } from \"node:os\";\n\nconst IS_WINDOWS = platform() === \"win32\";\n\nexport interface Patch {\n name: string;\n description: string;\n pattern: Buffer;\n replacement: Buffer;\n variants?: Array<{\n pattern: Buffer;\n replacement: Buffer;\n }>;\n // Regex-based matching: use $1, $2, etc. in regexReplacement for capture groups\n regexPattern?: RegExp;\n regexReplacement?: string;\n // Optional regex to detect already-patched binaries when regexPattern is not found.\n alreadyPatchedRegexPattern?: RegExp;\n // Skip this patch when any named patch has already matched or is already patched.\n skipIfAnySucceeded?: string[];\n // Only show check logs when this patch actually matches or is already patched.\n suppressCheckUnlessFound?: boolean;\n}\n\nexport interface PatchOptions {\n inputPath: string;\n outputPath?: string;\n patches: Patch[];\n dryRun?: boolean;\n backup?: boolean;\n verbose?: boolean;\n}\n\ninterface PatchResult {\n name: string;\n found: number;\n positions?: number[];\n success: boolean;\n alreadyPatched?: boolean;\n hidden?: boolean;\n skipped?: boolean;\n}\n\nexport interface PatchDroidResult {\n success: boolean;\n dryRun?: boolean;\n results: PatchResult[];\n outputPath?: string;\n noPatchNeeded?: boolean;\n patchedCount?: number;\n}\n\nexport async function patchDroid(options: PatchOptions): Promise<PatchDroidResult> {\n const {\n inputPath,\n outputPath,\n patches,\n dryRun = false,\n backup = true,\n verbose = false,\n } = options;\n\n const finalOutputPath = outputPath || `${inputPath}.patched`;\n\n if (!existsSync(inputPath)) {\n throw new Error(`Binary not found: ${inputPath}`);\n }\n\n const stats = await stat(inputPath);\n const fileSizeMB = (stats.size / (1024 * 1024)).toFixed(2);\n\n console.log(styleText(\"white\", `[*] Reading binary: ${styleText(\"cyan\", inputPath)}`));\n console.log(styleText(\"white\", `[*] File size: ${styleText(\"cyan\", fileSizeMB)} MB`));\n console.log();\n\n const data = await readFile(inputPath);\n const buffer = Buffer.from(data);\n\n // Use a working buffer that gets updated after each patch application\n // This ensures later patches search against the already-patched content\n const workingBuffer = Buffer.from(buffer);\n\n const results: PatchResult[] = [];\n const resultByName = new Map<string, PatchResult>();\n\n for (const patch of patches) {\n const shouldSkip =\n patch.skipIfAnySucceeded?.some((dependencyName) => {\n const dependencyResult = resultByName.get(dependencyName);\n return (\n !!dependencyResult && (dependencyResult.found > 0 || dependencyResult.alreadyPatched)\n );\n }) ?? false;\n\n if (shouldSkip) {\n const skippedResult: PatchResult = {\n name: patch.name,\n found: 0,\n success: true,\n alreadyPatched: true,\n hidden: true,\n skipped: true,\n };\n results.push(skippedResult);\n resultByName.set(patch.name, skippedResult);\n continue;\n }\n\n const suppressCheckUnlessFound = !!patch.suppressCheckUnlessFound;\n let checkLogged = false;\n const logCheckHeader = () => {\n if (!checkLogged) {\n console.log(styleText(\"white\", `[*] Checking patch: ${styleText(\"yellow\", patch.name)}`));\n console.log(styleText(\"gray\", ` ${patch.description}`));\n checkLogged = true;\n }\n };\n\n if (!suppressCheckUnlessFound) {\n logCheckHeader();\n }\n\n // Handle regex-based matching\n // For binary files, convert pattern/replacement to Buffer and use findAllPositions\n if (patch.regexPattern && patch.regexReplacement) {\n const content = workingBuffer.toString(\"utf-8\");\n const regex = new RegExp(patch.regexPattern.source, \"g\");\n const matches: Array<{ charIndex: number; match: string; replacement: string }> = [];\n\n let match;\n while ((match = regex.exec(content)) !== null) {\n const replacement = match[0].replace(\n new RegExp(patch.regexPattern.source),\n patch.regexReplacement,\n );\n matches.push({\n charIndex: match.index,\n match: match[0],\n replacement,\n });\n }\n\n if (matches.length === 0) {\n let alreadyPatched = false;\n if (patch.alreadyPatchedRegexPattern) {\n const alreadyPatchedRegex = new RegExp(patch.alreadyPatchedRegexPattern.source, \"g\");\n alreadyPatched = alreadyPatchedRegex.test(content);\n } else {\n // Fallback: look for a sample replacement pattern (best-effort heuristic).\n const sampleReplacement = patch.regexReplacement.replace(/\\$\\d+/g, \"X\");\n alreadyPatched = content.includes(sampleReplacement.slice(0, 20));\n }\n if (!suppressCheckUnlessFound || alreadyPatched) {\n logCheckHeader();\n }\n if (!suppressCheckUnlessFound) {\n console.log(styleText(\"yellow\", ` ! Pattern not found - may already be patched`));\n }\n const missIsHidden = suppressCheckUnlessFound && !alreadyPatched;\n const result = {\n name: patch.name,\n found: 0,\n success: alreadyPatched || missIsHidden,\n alreadyPatched,\n hidden: missIsHidden,\n };\n results.push(result);\n resultByName.set(patch.name, result);\n if (alreadyPatched) {\n console.log(styleText(\"blue\", ` ✓ Binary appears to be already patched`));\n }\n continue;\n }\n\n logCheckHeader();\n console.log(styleText(\"green\", ` ✓ Found ${matches.length} occurrences (regex)`));\n\n if (!dryRun) {\n // Apply regex replacement using Buffer.indexOf for accurate byte positions\n for (const { match, replacement } of matches) {\n const matchBuffer = Buffer.from(match, \"utf-8\");\n const replacementBuffer = Buffer.from(replacement, \"utf-8\");\n\n if (matchBuffer.length !== replacementBuffer.length) {\n console.log(\n styleText(\n \"yellow\",\n ` ! Warning: Length mismatch: ${matchBuffer.length} vs ${replacementBuffer.length}`,\n ),\n );\n }\n\n // Find the actual byte position in the buffer\n const bytePos = workingBuffer.indexOf(matchBuffer);\n if (bytePos !== -1) {\n replacementBuffer.copy(workingBuffer, bytePos, 0, replacementBuffer.length);\n }\n }\n }\n\n const result = {\n name: patch.name,\n found: matches.length,\n positions: matches.map((m) => m.charIndex),\n success: true,\n };\n results.push(result);\n resultByName.set(patch.name, result);\n continue;\n }\n\n const variants = [\n { pattern: patch.pattern, replacement: patch.replacement },\n ...(patch.variants || []),\n ];\n\n // Search in the working buffer (which may have earlier patches applied)\n let positions: number[] = [];\n let matchedVariant: (typeof variants)[number] | undefined;\n for (const variant of variants) {\n positions = findAllPositions(workingBuffer, variant.pattern);\n if (positions.length > 0) {\n matchedVariant = variant;\n break;\n }\n }\n\n if (positions.length === 0) {\n const alreadyPatched = variants.some((v) => workingBuffer.includes(v.replacement));\n const missIsHidden = suppressCheckUnlessFound && !alreadyPatched;\n if (!suppressCheckUnlessFound || alreadyPatched) {\n logCheckHeader();\n }\n if (!suppressCheckUnlessFound) {\n console.log(styleText(\"yellow\", ` ! Pattern not found - may already be patched`));\n }\n const result = {\n name: patch.name,\n found: 0,\n success: alreadyPatched || missIsHidden,\n alreadyPatched,\n hidden: missIsHidden,\n };\n results.push(result);\n\n let totalReplacementPositions = 0;\n for (const variant of variants) {\n totalReplacementPositions += findAllPositions(workingBuffer, variant.replacement).length;\n }\n if (totalReplacementPositions > 0) {\n logCheckHeader();\n console.log(\n styleText(\n \"blue\",\n ` ✓ Found ${totalReplacementPositions} occurrences of patched pattern`,\n ),\n );\n console.log(styleText(\"blue\", ` ✓ Binary appears to be already patched`));\n results[results.length - 1].alreadyPatched = true;\n results[results.length - 1].success = true;\n }\n resultByName.set(patch.name, results[results.length - 1]);\n continue;\n }\n\n if (!matchedVariant) {\n throw new Error(`Internal error: matchedVariant not set for patch ${patch.name}`);\n }\n\n logCheckHeader();\n console.log(styleText(\"green\", ` ✓ Found ${positions.length} occurrences`));\n\n if (verbose) {\n for (const pos of positions.slice(0, 5)) {\n const context = getContext(workingBuffer, pos, matchedVariant.pattern.length, 25);\n console.log(\n styleText(\"gray\", ` @ 0x${pos.toString(16).padStart(8, \"0\")}: ...${context}...`),\n );\n }\n if (positions.length > 5) {\n console.log(styleText(\"gray\", ` ... and ${positions.length - 5} more`));\n }\n }\n\n // Apply patch immediately to working buffer so later patches see updated content\n if (!dryRun) {\n for (const pos of positions) {\n matchedVariant.replacement.copy(workingBuffer, pos);\n }\n }\n\n const result = {\n name: patch.name,\n found: positions.length,\n positions,\n success: true,\n };\n results.push(result);\n resultByName.set(patch.name, result);\n }\n\n console.log();\n\n if (dryRun) {\n console.log(styleText(\"blue\", \"─\".repeat(60)));\n console.log(styleText([\"blue\", \"bold\"], \" DRY RUN RESULTS\"));\n console.log(styleText(\"blue\", \"─\".repeat(60)));\n console.log();\n\n for (const result of results) {\n if (result.hidden || result.skipped) {\n continue;\n }\n if (result.alreadyPatched) {\n console.log(styleText(\"blue\", ` [✓] ${result.name}: Already patched`));\n } else if (result.found > 0) {\n console.log(\n styleText(\"green\", ` [✓] ${result.name}: ${result.found} occurrences will be patched`),\n );\n } else {\n console.log(styleText(\"yellow\", ` [!] ${result.name}: Pattern not found`));\n }\n }\n\n return {\n success: results.every((r) => r.success || r.alreadyPatched),\n dryRun: true,\n results,\n };\n }\n\n const patchesNeeded = results.filter((r) => r.found > 0 && !r.alreadyPatched);\n\n if (patchesNeeded.length === 0) {\n const allPatched = results.every((r) => r.alreadyPatched);\n if (allPatched) {\n console.log(styleText(\"blue\", \"[*] All patches already applied. Binary is up to date.\"));\n return {\n success: true,\n outputPath: inputPath,\n results,\n noPatchNeeded: true,\n };\n }\n console.log(styleText(\"yellow\", \"[!] No patches could be applied.\"));\n return { success: false, results };\n }\n\n if (backup) {\n const backupPath = `${inputPath}.backup`;\n if (!existsSync(backupPath)) {\n await copyFile(inputPath, backupPath);\n console.log(styleText(\"white\", `[*] Created backup: ${styleText(\"cyan\", backupPath)}`));\n } else {\n console.log(styleText(\"gray\", `[*] Backup already exists: ${backupPath}`));\n }\n }\n\n console.log(styleText(\"white\", \"[*] Applying patches...\"));\n // Patches have already been applied to workingBuffer during the check phase\n // Count total patches applied\n const totalPatched = results.reduce((sum, r) => sum + (r.positions?.length || 0), 0);\n\n console.log(styleText(\"green\", `[*] Applied ${totalPatched} patches`));\n\n // Handle Windows file locking - if file is locked, use a new filename\n let actualOutputPath = finalOutputPath;\n try {\n await writeFile(finalOutputPath, workingBuffer);\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === \"EBUSY\" && IS_WINDOWS) {\n // File is locked, generate new filename with timestamp\n const timestamp = Date.now();\n const ext = finalOutputPath.endsWith(\".exe\") ? \".exe\" : \"\";\n const basePath = finalOutputPath\n .replace(/\\.exe$/, \"\")\n .replace(/\\.patched$/, \"\")\n .replace(/-\\d+$/, \"\");\n actualOutputPath = `${basePath}-${timestamp}${ext ? ext : \".patched\"}`;\n console.log(styleText(\"yellow\", `[!] Original file locked, saving to: ${actualOutputPath}`));\n await writeFile(actualOutputPath, workingBuffer);\n } else {\n throw error;\n }\n }\n console.log(\n styleText(\"white\", `[*] Patched binary saved: ${styleText(\"cyan\", actualOutputPath)}`),\n );\n\n await chmod(actualOutputPath, 0o755);\n console.log(styleText(\"gray\", \"[*] Set executable permission\"));\n\n console.log();\n console.log(styleText(\"white\", \"[*] Verifying patches...\"));\n const verifyBuffer = await readFile(actualOutputPath);\n\n let allVerified = true;\n for (let i = 0; i < patches.length; i++) {\n const patch = patches[i];\n if (results[i]?.hidden || results[i]?.skipped) {\n continue;\n }\n // Handle regex-based patches\n if (patch.regexPattern && patch.regexReplacement) {\n const content = verifyBuffer.toString(\"utf-8\");\n const oldMatches = [...content.matchAll(new RegExp(patch.regexPattern.source, \"g\"))];\n // For verification, just check that the original pattern is no longer present\n if (oldMatches.length === 0) {\n console.log(styleText(\"green\", ` ✓ ${patch.name}: Verified (regex)`));\n } else {\n console.log(\n styleText(\"red\", ` ✗ ${patch.name}: ${oldMatches.length} occurrences not patched`),\n );\n allVerified = false;\n }\n continue;\n }\n\n const variants = [\n { pattern: patch.pattern, replacement: patch.replacement },\n ...(patch.variants || []),\n ];\n\n let oldCount = 0;\n let newCount = 0;\n for (const variant of variants) {\n if (variant.pattern.length > 0) {\n oldCount += findAllPositions(verifyBuffer, variant.pattern).length;\n }\n if (variant.replacement.length > 0) {\n newCount += findAllPositions(verifyBuffer, variant.replacement).length;\n }\n }\n\n if (oldCount === 0) {\n console.log(styleText(\"green\", ` ✓ ${patch.name}: Verified (${newCount} patched)`));\n } else {\n console.log(styleText(\"red\", ` ✗ ${patch.name}: ${oldCount} occurrences not patched`));\n allVerified = false;\n }\n }\n\n if (allVerified) {\n console.log();\n console.log(styleText(\"green\", \"[+] All patches verified successfully!\"));\n }\n\n if (process.platform === \"darwin\") {\n console.log();\n try {\n console.log(styleText(\"gray\", \"[*] Re-signing binary for macOS...\"));\n execSync(`codesign --force --deep --sign - \"${finalOutputPath}\"`, {\n stdio: \"pipe\",\n });\n console.log(styleText(\"green\", \"[*] Binary re-signed successfully\"));\n } catch {\n console.log(styleText(\"yellow\", \"[!] Could not re-sign binary\"));\n console.log(\n styleText(\n \"gray\",\n ` You may need to run: codesign --force --deep --sign - ${finalOutputPath}`,\n ),\n );\n }\n\n try {\n execSync(`xattr -cr \"${finalOutputPath}\"`, { stdio: \"pipe\" });\n } catch {\n // Ignore\n }\n }\n\n return {\n success: allVerified,\n outputPath: actualOutputPath,\n results,\n patchedCount: totalPatched,\n };\n}\n\nfunction findAllPositions(buffer: Buffer, pattern: Buffer): number[] {\n const positions: number[] = [];\n let pos = 0;\n\n while (true) {\n pos = buffer.indexOf(pattern, pos);\n if (pos === -1) break;\n positions.push(pos);\n pos += pattern.length;\n }\n\n return positions;\n}\n\nfunction getContext(\n buffer: Buffer,\n position: number,\n patternLength: number,\n contextSize: number,\n): string {\n const start = Math.max(0, position - contextSize);\n const end = Math.min(buffer.length, position + patternLength + contextSize);\n const slice = buffer.slice(start, end);\n\n let str = \"\";\n for (let i = 0; i < slice.length; i++) {\n const c = slice[i];\n if (c >= 32 && c < 127) {\n str += String.fromCharCode(c);\n } else {\n str += \".\";\n }\n }\n return str;\n}\n","/**\n * Alias Metadata Management\n *\n * Stores and retrieves metadata about created aliases, including\n * which patches were applied. This enables the `update` command\n * to re-apply the same patches when the original droid binary is updated.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, unlink, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/**\n * Metadata structure for an alias\n */\nexport interface AliasMetadata {\n /** Alias name */\n name: string;\n /** ISO timestamp when created */\n createdAt: string;\n /** ISO timestamp when last updated */\n updatedAt: string;\n /** Path to the original droid binary used for patching */\n originalBinaryPath: string;\n /** Path where the alias symlink was created */\n aliasPath?: string;\n /** droid-patch version used to create this alias */\n droidPatchVersion?: string;\n /** droid binary version */\n droidVersion?: string;\n /** Patches that were applied */\n patches: {\n isCustom: boolean;\n skipLogin: boolean;\n /** API base URL for binary patching or websearch forward target */\n apiBase: string | null;\n /** Whether websearch is enabled (external providers mode) */\n websearch: boolean;\n /** Whether websearch-proxy is enabled (native provider mode) */\n websearchProxy?: boolean;\n /** @deprecated Old proxy field, kept for backward compatibility */\n proxy?: string | null;\n reasoningEffort: boolean;\n /** Whether telemetry/Sentry is disabled */\n noTelemetry?: boolean;\n /** Standalone mode: mock non-LLM Factory APIs */\n standalone?: boolean;\n };\n}\n\n// Directory for storing metadata files\nconst META_DIR = join(homedir(), \".droid-patch\", \"meta\");\n\n/**\n * Ensure metadata directory exists\n */\nasync function ensureMetaDir(): Promise<void> {\n if (!existsSync(META_DIR)) {\n await mkdir(META_DIR, { recursive: true });\n }\n}\n\n/**\n * Get the path to a metadata file for an alias\n */\nfunction getMetaPath(aliasName: string): string {\n return join(META_DIR, `${aliasName}.json`);\n}\n\n/**\n * Save alias metadata to disk\n */\nexport async function saveAliasMetadata(meta: AliasMetadata): Promise<void> {\n await ensureMetaDir();\n const metaPath = getMetaPath(meta.name);\n await writeFile(metaPath, JSON.stringify(meta, null, 2));\n}\n\n/**\n * Load alias metadata from disk\n * Returns null if metadata doesn't exist\n */\nexport async function loadAliasMetadata(aliasName: string): Promise<AliasMetadata | null> {\n const metaPath = getMetaPath(aliasName);\n if (!existsSync(metaPath)) {\n return null;\n }\n try {\n const content = await readFile(metaPath, \"utf-8\");\n return JSON.parse(content) as AliasMetadata;\n } catch {\n return null;\n }\n}\n\n/**\n * List all alias metadata\n */\nexport async function listAllMetadata(): Promise<AliasMetadata[]> {\n await ensureMetaDir();\n\n const files = await readdir(META_DIR);\n const metaList: AliasMetadata[] = [];\n\n for (const file of files) {\n if (!file.endsWith(\".json\")) continue;\n\n const aliasName = file.replace(/\\.json$/, \"\");\n const meta = await loadAliasMetadata(aliasName);\n if (meta) {\n metaList.push(meta);\n }\n }\n\n return metaList;\n}\n\n/**\n * Remove alias metadata\n */\nexport async function removeAliasMetadata(aliasName: string): Promise<boolean> {\n const metaPath = getMetaPath(aliasName);\n if (!existsSync(metaPath)) {\n return false;\n }\n try {\n await unlink(metaPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Create a new metadata object with current timestamp\n */\nexport function createMetadata(\n name: string,\n originalBinaryPath: string,\n patches: AliasMetadata[\"patches\"],\n options?: {\n droidPatchVersion?: string;\n droidVersion?: string;\n aliasPath?: string;\n },\n): AliasMetadata {\n const now = new Date().toISOString();\n return {\n name,\n createdAt: now,\n updatedAt: now,\n originalBinaryPath,\n aliasPath: options?.aliasPath,\n droidPatchVersion: options?.droidPatchVersion,\n droidVersion: options?.droidVersion,\n patches,\n };\n}\n\n/**\n * Format patches for display\n */\nexport function formatPatches(patches: AliasMetadata[\"patches\"]): string {\n const applied: string[] = [];\n if (patches.isCustom) applied.push(\"isCustom\");\n if (patches.skipLogin) applied.push(\"skipLogin\");\n // Show apiBase only when not using websearch (binary patch mode)\n if (patches.apiBase && !patches.websearch && !patches.websearchProxy)\n applied.push(`apiBase(${patches.apiBase})`);\n // Show websearch with optional custom target (external providers mode)\n if (patches.websearch) {\n const target = patches.apiBase || \"api.factory.ai\";\n applied.push(`websearch(${target})`);\n }\n // Show websearchProxy (native provider mode)\n if (patches.websearchProxy) {\n applied.push(\"websearchProxy(native)\");\n }\n // Support old proxy field for backward compatibility\n if (patches.proxy && !patches.websearch && !patches.websearchProxy)\n applied.push(`websearch(${patches.proxy})`);\n if (patches.reasoningEffort) applied.push(\"reasoningEffort\");\n if (patches.noTelemetry) applied.push(\"noTelemetry\");\n if (patches.standalone) applied.push(\"standalone\");\n return applied.length > 0 ? applied.join(\", \") : \"(none)\";\n}\n","import {\n existsSync,\n mkdirSync,\n readdirSync,\n unlinkSync,\n lstatSync,\n readFileSync,\n appendFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { symlink, readlink, unlink, copyFile, chmod } from \"node:fs/promises\";\nimport { join, basename, dirname, delimiter } from \"node:path\";\nimport { homedir, platform } from \"node:os\";\nimport { execSync } from \"node:child_process\";\nimport { styleText } from \"node:util\";\nimport { removeAliasMetadata, loadAliasMetadata, formatPatches } from \"./metadata.ts\";\n\nconst IS_WINDOWS = platform() === \"win32\";\n\nconst DROID_PATCH_DIR = join(homedir(), \".droid-patch\");\nconst ALIASES_DIR = join(DROID_PATCH_DIR, \"aliases\");\nconst BINS_DIR = join(DROID_PATCH_DIR, \"bins\");\n\n// Unix common PATH directories\nconst UNIX_PATH_DIRS = [\n join(homedir(), \".local/bin\"),\n join(homedir(), \"bin\"),\n join(homedir(), \".bin\"),\n \"/opt/homebrew/bin\",\n \"/usr/local/bin\",\n join(homedir(), \".npm-global/bin\"),\n join(homedir(), \".npm/bin\"),\n join(homedir(), \".pnpm-global/bin\"),\n join(homedir(), \".yarn/bin\"),\n join(homedir(), \".config/yarn/global/node_modules/.bin\"),\n join(homedir(), \".cargo/bin\"),\n join(homedir(), \"go/bin\"),\n join(homedir(), \".deno/bin\"),\n join(homedir(), \".bun/bin\"),\n join(homedir(), \".local/share/mise/shims\"),\n join(homedir(), \".asdf/shims\"),\n join(homedir(), \".nvm/current/bin\"),\n join(homedir(), \".volta/bin\"),\n join(homedir(), \".fnm/current/bin\"),\n];\n\n// Windows common PATH directories\nconst WINDOWS_PATH_DIRS = [\n join(homedir(), \".droid-patch\", \"bin\"),\n join(homedir(), \"scoop\", \"shims\"),\n join(homedir(), \"AppData\", \"Local\", \"Programs\", \"bin\"),\n];\n\nconst COMMON_PATH_DIRS = IS_WINDOWS ? WINDOWS_PATH_DIRS : UNIX_PATH_DIRS;\n\nfunction ensureDirectories(): void {\n if (!existsSync(DROID_PATCH_DIR)) {\n mkdirSync(DROID_PATCH_DIR, { recursive: true });\n }\n if (!existsSync(ALIASES_DIR)) {\n mkdirSync(ALIASES_DIR, { recursive: true });\n }\n if (!existsSync(BINS_DIR)) {\n mkdirSync(BINS_DIR, { recursive: true });\n }\n}\n\nfunction checkPathInclusion(): boolean {\n const pathEnv = process.env.PATH || \"\";\n return pathEnv.split(delimiter).some((p) => p.toLowerCase() === ALIASES_DIR.toLowerCase());\n}\n\nexport function findWritablePathDir(): string | null {\n const pathEnv = process.env.PATH || \"\";\n const pathDirs = pathEnv.split(delimiter);\n\n for (const dir of COMMON_PATH_DIRS) {\n // Case-insensitive comparison for Windows\n const isInPath = pathDirs.some((p) => p.toLowerCase() === dir.toLowerCase());\n if (isInPath) {\n try {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n const testFile = join(dir, `.droid-patch-test-${Date.now()}`);\n writeFileSync(testFile, \"\");\n unlinkSync(testFile);\n return dir;\n } catch {\n continue;\n }\n }\n }\n\n return null;\n}\n\nfunction getShellConfigPath(): string {\n if (IS_WINDOWS) {\n // Windows doesn't use shell config files for PATH\n return \"\";\n }\n const shell = process.env.SHELL || \"/bin/bash\";\n const shellName = basename(shell);\n\n switch (shellName) {\n case \"zsh\":\n return join(homedir(), \".zshrc\");\n case \"bash\": {\n const bashProfile = join(homedir(), \".bash_profile\");\n if (existsSync(bashProfile)) return bashProfile;\n return join(homedir(), \".bashrc\");\n }\n case \"fish\":\n return join(homedir(), \".config/fish/config.fish\");\n default:\n return join(homedir(), \".profile\");\n }\n}\n\nfunction isPathConfigured(shellConfigPath: string): boolean {\n if (IS_WINDOWS || !shellConfigPath) {\n return false;\n }\n\n if (!existsSync(shellConfigPath)) {\n return false;\n }\n\n try {\n const content = readFileSync(shellConfigPath, \"utf-8\");\n return content.includes(\".droid-patch/aliases\") || content.includes(\"droid-patch/aliases\");\n } catch {\n return false;\n }\n}\n\n/**\n * Add directory to Windows user PATH using setx command\n * This modifies the user's PATH permanently (requires terminal restart)\n */\nfunction addToWindowsUserPath(dir: string): boolean {\n try {\n // Get current user PATH from registry\n let existingPath = \"\";\n try {\n const result = execSync('reg query \"HKCU\\\\Environment\" /v Path 2>nul', {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const match = result.match(/Path\\s+REG_(?:EXPAND_)?SZ\\s+(.+)/);\n existingPath = match ? match[1].trim() : \"\";\n } catch {\n // PATH not set yet, that's fine\n }\n\n // Check if already in PATH (case-insensitive)\n const paths = existingPath.split(\";\").map((p) => p.toLowerCase().trim());\n if (paths.includes(dir.toLowerCase())) {\n return true; // Already in PATH\n }\n\n // Add to PATH\n const newPath = existingPath ? `${existingPath};${dir}` : dir;\n execSync(`setx PATH \"${newPath}\"`, { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Generate Windows .cmd launcher script\n */\nfunction generateWindowsLauncher(targetPath: string): string {\n return `@echo off\\r\\n\"${targetPath}\" %*\\r\\n`;\n}\n\nfunction addPathToShellConfig(shellConfigPath: string, verbose = false): boolean {\n const shell = process.env.SHELL || \"/bin/bash\";\n const shellName = basename(shell);\n\n let exportLine: string;\n if (shellName === \"fish\") {\n exportLine = `\\n# Added by droid-patch\\nfish_add_path \"${ALIASES_DIR}\"\\n`;\n } else {\n exportLine = `\\n# Added by droid-patch\\nexport PATH=\"${ALIASES_DIR}:$PATH\"\\n`;\n }\n\n try {\n appendFileSync(shellConfigPath, exportLine);\n if (verbose) {\n console.log(styleText(\"gray\", ` Added PATH export to: ${shellConfigPath}`));\n }\n return true;\n } catch (error) {\n console.log(\n styleText(\"yellow\", `[!] Could not write to ${shellConfigPath}: ${(error as Error).message}`),\n );\n return false;\n }\n}\n\nexport interface CreateAliasResult {\n aliasPath: string;\n binaryPath: string;\n immediate?: boolean;\n}\n\nexport async function createAlias(\n patchedBinaryPath: string,\n aliasName: string,\n verbose = false,\n): Promise<CreateAliasResult> {\n ensureDirectories();\n\n console.log(styleText(\"white\", `[*] Creating alias: ${styleText(\"cyan\", aliasName)}`));\n\n // Windows: use .cmd launcher instead of symlink\n if (IS_WINDOWS) {\n return createWindowsAlias(patchedBinaryPath, aliasName, verbose);\n }\n\n const writablePathDir = findWritablePathDir();\n\n if (writablePathDir) {\n const targetPath = join(writablePathDir, aliasName);\n const binaryDest = join(BINS_DIR, `${aliasName}-patched`);\n await copyFile(patchedBinaryPath, binaryDest);\n await chmod(binaryDest, 0o755);\n\n if (verbose) {\n console.log(styleText(\"gray\", ` Stored binary: ${binaryDest}`));\n }\n\n if (existsSync(targetPath)) {\n await unlink(targetPath);\n if (verbose) {\n console.log(styleText(\"gray\", ` Removed existing: ${targetPath}`));\n }\n }\n\n await symlink(binaryDest, targetPath);\n\n if (process.platform === \"darwin\") {\n try {\n console.log(styleText(\"gray\", \"[*] Re-signing binary for macOS...\"));\n execSync(`codesign --force --deep --sign - \"${binaryDest}\"`, {\n stdio: \"pipe\",\n });\n console.log(styleText(\"green\", \"[*] Binary re-signed successfully\"));\n } catch {\n console.log(styleText(\"yellow\", \"[!] Could not re-sign binary\"));\n }\n\n try {\n execSync(`xattr -cr \"${binaryDest}\"`, { stdio: \"pipe\" });\n } catch {\n // Ignore\n }\n }\n\n console.log(styleText(\"green\", `[*] Created: ${targetPath} -> ${binaryDest}`));\n console.log();\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log(styleText([\"green\", \"bold\"], \" ALIAS READY - NO ACTION REQUIRED!\"));\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log();\n console.log(\n styleText(\n \"white\",\n `The alias \"${styleText([\"cyan\", \"bold\"], aliasName)}\" is now available in ALL terminals.`,\n ),\n );\n console.log(styleText(\"gray\", `(Installed to: ${writablePathDir})`));\n\n return {\n aliasPath: targetPath,\n binaryPath: binaryDest,\n immediate: true,\n };\n }\n\n console.log(styleText(\"yellow\", \"[*] No writable PATH directory found, using fallback...\"));\n\n const binaryDest = join(BINS_DIR, `${aliasName}-patched`);\n await copyFile(patchedBinaryPath, binaryDest);\n await chmod(binaryDest, 0o755);\n\n if (verbose) {\n console.log(styleText(\"gray\", ` Copied binary to: ${binaryDest}`));\n }\n\n if (process.platform === \"darwin\") {\n try {\n console.log(styleText(\"gray\", \"[*] Re-signing binary for macOS...\"));\n execSync(`codesign --force --deep --sign - \"${binaryDest}\"`, {\n stdio: \"pipe\",\n });\n console.log(styleText(\"green\", \"[*] Binary re-signed successfully\"));\n } catch {\n console.log(\n styleText(\"yellow\", \"[!] Could not re-sign binary. You may need to do this manually:\"),\n );\n console.log(styleText(\"gray\", ` codesign --force --deep --sign - \"${binaryDest}\"`));\n }\n\n try {\n execSync(`xattr -cr \"${binaryDest}\"`, { stdio: \"pipe\" });\n } catch {\n // Ignore\n }\n }\n\n const symlinkPath = join(ALIASES_DIR, aliasName);\n\n if (existsSync(symlinkPath)) {\n await unlink(symlinkPath);\n if (verbose) {\n console.log(styleText(\"gray\", ` Removed existing symlink`));\n }\n }\n\n await symlink(binaryDest, symlinkPath);\n await chmod(symlinkPath, 0o755);\n\n console.log(styleText(\"green\", `[*] Created symlink: ${symlinkPath} -> ${binaryDest}`));\n\n const shellConfig = getShellConfigPath();\n\n if (!checkPathInclusion()) {\n if (!isPathConfigured(shellConfig)) {\n console.log(styleText(\"white\", `[*] Configuring PATH in ${shellConfig}...`));\n\n if (addPathToShellConfig(shellConfig, verbose)) {\n console.log(styleText(\"green\", `[*] PATH configured successfully!`));\n console.log();\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log(styleText([\"yellow\", \"bold\"], \" ACTION REQUIRED\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log();\n console.log(styleText(\"white\", \"To use the alias in this terminal, run:\"));\n console.log();\n console.log(styleText(\"cyan\", ` source ${shellConfig}`));\n console.log();\n console.log(styleText(\"gray\", \"Or simply open a new terminal window.\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n } else {\n const exportLine = `export PATH=\"${ALIASES_DIR}:$PATH\"`;\n console.log();\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log(styleText([\"yellow\", \"bold\"], \" Manual PATH Configuration Required\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log();\n console.log(styleText(\"white\", \"Add this line to your shell config:\"));\n console.log(styleText(\"cyan\", ` ${exportLine}`));\n console.log();\n console.log(styleText(\"gray\", `Shell config file: ${shellConfig}`));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n }\n } else {\n console.log(styleText(\"green\", `[*] PATH already configured in ${shellConfig}`));\n console.log();\n console.log(\n styleText(\n \"yellow\",\n `Note: Run \\`source ${shellConfig}\\` or open a new terminal to use the alias.`,\n ),\n );\n }\n } else {\n console.log(styleText(\"green\", `[*] PATH already includes aliases directory`));\n console.log();\n console.log(\n styleText(\n \"green\",\n `You can now use \"${styleText([\"cyan\", \"bold\"], aliasName)}\" command directly!`,\n ),\n );\n }\n\n return {\n aliasPath: symlinkPath,\n binaryPath: binaryDest,\n };\n}\n\n/**\n * Create alias on Windows using .cmd launcher and setx for PATH\n */\n/**\n * Try to copy file, handling Windows file locking\n * If target is locked, use a new filename with timestamp\n */\nasync function copyFileWithLockHandling(\n src: string,\n dest: string,\n verbose = false,\n): Promise<string> {\n try {\n await copyFile(src, dest);\n return dest;\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n // EBUSY = file is locked/in use (Windows)\n if (err.code === \"EBUSY\" && IS_WINDOWS) {\n // Generate new filename with timestamp\n const timestamp = Date.now();\n const ext = dest.endsWith(\".exe\") ? \".exe\" : \"\";\n const baseName = dest.replace(/\\.exe$/, \"\").replace(/-\\d+$/, \"\"); // Remove old timestamp if any\n const newDest = `${baseName}-${timestamp}${ext}`;\n\n if (verbose) {\n console.log(styleText(\"yellow\", ` [!] File locked, using new path: ${newDest}`));\n }\n\n await copyFile(src, newDest);\n return newDest;\n }\n throw error;\n }\n}\n\nasync function createWindowsAlias(\n patchedBinaryPath: string,\n aliasName: string,\n verbose = false,\n): Promise<CreateAliasResult> {\n const binDir = join(DROID_PATCH_DIR, \"bin\");\n if (!existsSync(binDir)) {\n mkdirSync(binDir, { recursive: true });\n }\n\n // Copy binary to bins directory, handling file locking\n const targetPath = join(BINS_DIR, `${aliasName}-patched.exe`);\n const binaryDest = await copyFileWithLockHandling(patchedBinaryPath, targetPath, verbose);\n\n if (verbose) {\n console.log(styleText(\"gray\", ` Stored binary: ${binaryDest}`));\n }\n\n // Create .cmd launcher in bin directory\n const cmdPath = join(binDir, `${aliasName}.cmd`);\n const cmdContent = generateWindowsLauncher(binaryDest);\n writeFileSync(cmdPath, cmdContent);\n\n if (verbose) {\n console.log(styleText(\"gray\", ` Created launcher: ${cmdPath}`));\n }\n\n // Try to add bin directory to user PATH\n const pathAdded = addToWindowsUserPath(binDir);\n\n console.log(styleText(\"green\", `[*] Created: ${cmdPath}`));\n console.log();\n\n if (pathAdded) {\n if (checkPathInclusion()) {\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log(styleText([\"green\", \"bold\"], \" ALIAS READY!\"));\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log();\n console.log(\n styleText(\n \"white\",\n `The alias \"${styleText([\"cyan\", \"bold\"], aliasName)}\" is now available.`,\n ),\n );\n console.log(styleText(\"gray\", `(Installed to: ${binDir})`));\n\n return {\n aliasPath: cmdPath,\n binaryPath: binaryDest,\n immediate: true,\n };\n }\n\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log(styleText([\"yellow\", \"bold\"], \" PATH Updated - Restart Terminal\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log();\n console.log(styleText(\"white\", \"PATH has been updated. Please restart your terminal.\"));\n console.log(\n styleText(\n \"white\",\n `Then you can use \"${styleText([\"cyan\", \"bold\"], aliasName)}\" command directly.`,\n ),\n );\n console.log();\n console.log(styleText(\"gray\", `Installed to: ${binDir}`));\n } else {\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log(styleText([\"yellow\", \"bold\"], \" Manual PATH Configuration Required\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log();\n console.log(styleText(\"white\", \"Add this directory to your PATH:\"));\n console.log(styleText(\"cyan\", ` ${binDir}`));\n console.log();\n console.log(styleText(\"gray\", \"Or run directly:\"));\n console.log(styleText(\"cyan\", ` \"${cmdPath}\"`));\n }\n\n return {\n aliasPath: cmdPath,\n binaryPath: binaryDest,\n immediate: false,\n };\n}\n\nexport async function removeAlias(aliasName: string): Promise<void> {\n console.log(styleText(\"white\", `[*] Removing alias: ${styleText(\"cyan\", aliasName)}`));\n\n let removed = false;\n\n // Windows: check for .cmd launcher\n if (IS_WINDOWS) {\n const binDir = join(DROID_PATCH_DIR, \"bin\");\n const cmdPath = join(binDir, `${aliasName}.cmd`);\n if (existsSync(cmdPath)) {\n await unlink(cmdPath);\n console.log(styleText(\"green\", ` Removed: ${cmdPath}`));\n removed = true;\n }\n\n // Remove Windows binary (.exe)\n const exePath = join(BINS_DIR, `${aliasName}-patched.exe`);\n if (existsSync(exePath)) {\n await unlink(exePath);\n console.log(styleText(\"green\", ` Removed binary: ${exePath}`));\n removed = true;\n }\n\n // Also check for wrapper .cmd in proxy directory\n const proxyDir = join(DROID_PATCH_DIR, \"proxy\");\n const proxyWrapperCmd = join(proxyDir, `${aliasName}.cmd`);\n if (existsSync(proxyWrapperCmd)) {\n await unlink(proxyWrapperCmd);\n console.log(styleText(\"green\", ` Removed wrapper: ${proxyWrapperCmd}`));\n removed = true;\n }\n }\n\n // Check common PATH directories for symlinks (Unix)\n if (!IS_WINDOWS) {\n for (const pathDir of COMMON_PATH_DIRS) {\n const pathSymlink = join(pathDir, aliasName);\n if (existsSync(pathSymlink)) {\n try {\n const stats = lstatSync(pathSymlink);\n if (stats.isSymbolicLink()) {\n const target = await readlink(pathSymlink);\n // Support regular aliases, old websearch wrappers, and new proxy wrappers\n if (\n target.includes(\".droid-patch/bins\") ||\n target.includes(\".droid-patch/websearch\") ||\n target.includes(\".droid-patch/proxy\") ||\n target.includes(\".droid-patch/statusline\")\n ) {\n await unlink(pathSymlink);\n console.log(styleText(\"green\", ` Removed: ${pathSymlink}`));\n removed = true;\n }\n }\n } catch {\n // Ignore\n }\n }\n }\n }\n\n // Check aliases directory\n const symlinkPath = join(ALIASES_DIR, aliasName);\n if (existsSync(symlinkPath)) {\n await unlink(symlinkPath);\n console.log(styleText(\"green\", ` Removed: ${symlinkPath}`));\n removed = true;\n }\n\n // Remove binary if exists (Unix style without .exe)\n const binaryPath = join(BINS_DIR, `${aliasName}-patched`);\n if (existsSync(binaryPath)) {\n await unlink(binaryPath);\n console.log(styleText(\"green\", ` Removed binary: ${binaryPath}`));\n removed = true;\n }\n\n // Remove new proxy wrapper and related files if exist\n const proxyDir = join(DROID_PATCH_DIR, \"proxy\");\n const proxyWrapperPath = join(proxyDir, aliasName);\n const proxyScriptPath = join(proxyDir, `${aliasName}-proxy.js`);\n\n if (existsSync(proxyWrapperPath)) {\n await unlink(proxyWrapperPath);\n console.log(styleText(\"green\", ` Removed wrapper: ${proxyWrapperPath}`));\n removed = true;\n }\n\n if (existsSync(proxyScriptPath)) {\n await unlink(proxyScriptPath);\n console.log(styleText(\"green\", ` Removed proxy script: ${proxyScriptPath}`));\n removed = true;\n }\n\n // Remove old websearch wrapper and related files if exist (backward compatibility)\n const websearchDir = join(DROID_PATCH_DIR, \"websearch\");\n const wrapperPath = join(websearchDir, aliasName);\n const oldProxyPath = join(websearchDir, `${aliasName}-proxy.js`);\n const preloadPath = join(websearchDir, `${aliasName}-preload.js`);\n\n if (existsSync(wrapperPath)) {\n await unlink(wrapperPath);\n console.log(styleText(\"green\", ` Removed legacy wrapper: ${wrapperPath}`));\n removed = true;\n }\n\n if (existsSync(oldProxyPath)) {\n await unlink(oldProxyPath);\n console.log(styleText(\"green\", ` Removed legacy proxy: ${oldProxyPath}`));\n removed = true;\n }\n\n if (existsSync(preloadPath)) {\n await unlink(preloadPath);\n console.log(styleText(\"green\", ` Removed legacy preload: ${preloadPath}`));\n removed = true;\n }\n\n // Remove statusline wrapper and monitor script if exist\n const statuslineDir = join(DROID_PATCH_DIR, \"statusline\");\n const statuslineWrapperPath = join(statuslineDir, aliasName);\n const statuslineMonitorPath = join(statuslineDir, `${aliasName}-statusline.js`);\n const statuslineSessionsPath = join(statuslineDir, `${aliasName}-sessions.js`);\n\n if (existsSync(statuslineWrapperPath)) {\n await unlink(statuslineWrapperPath);\n console.log(styleText(\"green\", ` Removed statusline wrapper: ${statuslineWrapperPath}`));\n removed = true;\n }\n\n if (existsSync(statuslineMonitorPath)) {\n await unlink(statuslineMonitorPath);\n console.log(styleText(\"green\", ` Removed statusline monitor: ${statuslineMonitorPath}`));\n removed = true;\n }\n\n if (existsSync(statuslineSessionsPath)) {\n await unlink(statuslineSessionsPath);\n console.log(styleText(\"green\", ` Removed sessions browser: ${statuslineSessionsPath}`));\n removed = true;\n }\n\n // Remove metadata\n const metaRemoved = await removeAliasMetadata(aliasName);\n if (metaRemoved) {\n console.log(styleText(\"green\", ` Removed metadata`));\n removed = true;\n }\n\n if (!removed) {\n console.log(styleText(\"yellow\", ` Alias \"${aliasName}\" not found`));\n } else {\n console.log(styleText(\"green\", `[*] Alias \"${aliasName}\" removed successfully`));\n }\n}\n\nexport async function listAliases(): Promise<void> {\n ensureDirectories();\n\n console.log(styleText(\"cyan\", \"═\".repeat(60)));\n console.log(styleText([\"cyan\", \"bold\"], \" Droid-Patch Aliases\"));\n console.log(styleText(\"cyan\", \"═\".repeat(60)));\n console.log();\n\n interface AliasInfo {\n name: string;\n target: string;\n location: string;\n immediate: boolean;\n }\n\n const aliases: AliasInfo[] = [];\n\n // Windows: check for .cmd launchers in bin directory\n if (IS_WINDOWS) {\n const binDir = join(DROID_PATCH_DIR, \"bin\");\n if (existsSync(binDir)) {\n try {\n const files = readdirSync(binDir);\n for (const file of files) {\n if (file.endsWith(\".cmd\")) {\n const aliasName = file.replace(/\\.cmd$/, \"\");\n const fullPath = join(binDir, file);\n // Read .cmd to find target\n try {\n const content = readFileSync(fullPath, \"utf-8\");\n const match = content.match(/\"([^\"]+)\"/);\n const target = match ? match[1] : fullPath;\n aliases.push({\n name: aliasName,\n target,\n location: binDir,\n immediate: checkPathInclusion(),\n });\n } catch {\n aliases.push({\n name: aliasName,\n target: fullPath,\n location: binDir,\n immediate: false,\n });\n }\n }\n }\n } catch {\n // Directory can't be read\n }\n }\n\n // Also check proxy directory for wrapper .cmd files\n const proxyDir = join(DROID_PATCH_DIR, \"proxy\");\n if (existsSync(proxyDir)) {\n try {\n const files = readdirSync(proxyDir);\n for (const file of files) {\n if (file.endsWith(\".cmd\")) {\n const aliasName = file.replace(/\\.cmd$/, \"\");\n if (!aliases.find((a) => a.name === aliasName)) {\n const fullPath = join(proxyDir, file);\n aliases.push({\n name: aliasName,\n target: fullPath,\n location: proxyDir,\n immediate: false,\n });\n }\n }\n }\n } catch {\n // Ignore\n }\n }\n } else {\n // Unix: check for symlinks\n for (const pathDir of COMMON_PATH_DIRS) {\n if (!existsSync(pathDir)) continue;\n\n try {\n const files = readdirSync(pathDir);\n for (const file of files) {\n const fullPath = join(pathDir, file);\n try {\n const stats = lstatSync(fullPath);\n if (stats.isSymbolicLink()) {\n const target = await readlink(fullPath);\n // Support regular aliases, old websearch wrappers, and new proxy wrappers\n if (\n target.includes(\".droid-patch/bins\") ||\n target.includes(\".droid-patch/websearch\") ||\n target.includes(\".droid-patch/proxy\") ||\n target.includes(\".droid-patch/statusline\")\n ) {\n aliases.push({\n name: file,\n target,\n location: pathDir,\n immediate: true,\n });\n }\n }\n } catch {\n // Ignore\n }\n }\n } catch {\n // Directory can't be read\n }\n }\n\n try {\n const files = readdirSync(ALIASES_DIR);\n\n for (const file of files) {\n const fullPath = join(ALIASES_DIR, file);\n try {\n const stats = lstatSync(fullPath);\n if (stats.isSymbolicLink()) {\n const target = await readlink(fullPath);\n if (!aliases.find((a) => a.name === file)) {\n aliases.push({\n name: file,\n target,\n location: ALIASES_DIR,\n immediate: false,\n });\n }\n }\n } catch {\n // Ignore\n }\n }\n } catch {\n // Directory doesn't exist or can't be read\n }\n }\n\n if (aliases.length === 0) {\n console.log(styleText(\"gray\", \" No aliases configured.\"));\n console.log();\n console.log(styleText(\"gray\", \" Create one with: npx droid-patch --is-custom <alias-name>\"));\n } else {\n console.log(styleText(\"white\", ` Found ${aliases.length} alias(es):`));\n console.log();\n for (const alias of aliases) {\n const status = alias.immediate\n ? styleText(\"green\", \"✓ immediate\")\n : styleText(\"yellow\", \"requires source\");\n console.log(styleText(\"green\", ` • ${styleText([\"cyan\", \"bold\"], alias.name)} [${status}]`));\n console.log(styleText(\"gray\", ` → ${alias.target}`));\n\n // Load and display metadata\n const meta = await loadAliasMetadata(alias.name);\n if (meta) {\n // Version info\n const patchVer = meta.droidPatchVersion\n ? `droid-patch@${meta.droidPatchVersion}`\n : \"unknown\";\n const droidVer = meta.droidVersion ? `droid@${meta.droidVersion}` : \"unknown\";\n console.log(styleText(\"gray\", ` Versions: ${patchVer}, ${droidVer}`));\n\n // Flags/patches\n const flags = formatPatches(meta.patches);\n console.log(styleText(\"gray\", ` Flags: ${flags}`));\n\n // Created time\n if (meta.createdAt) {\n const date = new Date(meta.createdAt).toLocaleString();\n console.log(styleText(\"gray\", ` Created: ${date}`));\n }\n } else {\n console.log(styleText(\"yellow\", ` (no metadata - created by older version)`));\n }\n console.log();\n }\n }\n\n console.log();\n console.log(styleText(\"gray\", ` Aliases directory: ${ALIASES_DIR}`));\n console.log(\n styleText(\n \"gray\",\n ` PATH configured: ${checkPathInclusion() ? styleText(\"green\", \"Yes\") : styleText(\"yellow\", \"No\")}`,\n ),\n );\n console.log();\n}\n\nexport interface ReplaceOriginalResult {\n originalPath: string;\n backupPath: string;\n}\n\nexport async function replaceOriginal(\n patchedBinaryPath: string,\n originalPath: string,\n verbose = false,\n): Promise<ReplaceOriginalResult> {\n ensureDirectories();\n\n console.log(\n styleText(\"white\", `[*] Replacing original binary: ${styleText(\"cyan\", originalPath)}`),\n );\n\n const latestBackupPath = join(BINS_DIR, \"droid-original-latest\");\n\n if (!existsSync(latestBackupPath)) {\n await copyFile(originalPath, latestBackupPath);\n console.log(styleText(\"green\", `[*] Created backup: ${latestBackupPath}`));\n } else {\n if (verbose) {\n console.log(styleText(\"gray\", ` Backup already exists: ${latestBackupPath}`));\n }\n }\n\n await copyFile(patchedBinaryPath, originalPath);\n await chmod(originalPath, 0o755);\n console.log(styleText(\"green\", `[*] Replaced: ${originalPath}`));\n\n if (process.platform === \"darwin\") {\n try {\n console.log(styleText(\"gray\", \"[*] Re-signing binary for macOS...\"));\n execSync(`codesign --force --deep --sign - \"${originalPath}\"`, {\n stdio: \"pipe\",\n });\n console.log(styleText(\"green\", \"[*] Binary re-signed successfully\"));\n } catch {\n console.log(styleText(\"yellow\", \"[!] Could not re-sign binary. You may need to run:\"));\n console.log(styleText(\"gray\", ` codesign --force --deep --sign - \"${originalPath}\"`));\n }\n\n try {\n execSync(`xattr -cr \"${originalPath}\"`, { stdio: \"pipe\" });\n } catch {\n // Ignore\n }\n }\n\n console.log();\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log(styleText([\"green\", \"bold\"], \" REPLACEMENT COMPLETE\"));\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log();\n console.log(styleText(\"white\", \"The patched binary is now active in all terminals.\"));\n console.log(styleText(\"white\", \"No need to restart or source anything!\"));\n console.log();\n console.log(styleText(\"gray\", `To restore the original, run:`));\n console.log(styleText(\"cyan\", ` npx droid-patch restore`));\n\n return {\n originalPath,\n backupPath: latestBackupPath,\n };\n}\n\n/**\n * Create alias for wrapper script\n * Unlike createAlias, this function creates symlink pointing to wrapper script\n * Used for features like websearch that require preprocessing\n */\nexport async function createAliasForWrapper(\n wrapperPath: string,\n aliasName: string,\n verbose = false,\n): Promise<CreateAliasResult> {\n ensureDirectories();\n\n console.log(styleText(\"white\", `[*] Creating alias: ${styleText(\"cyan\", aliasName)}`));\n\n // Windows: create .cmd launcher pointing to wrapper\n if (IS_WINDOWS) {\n return createWindowsWrapperAlias(wrapperPath, aliasName, verbose);\n }\n\n const writablePathDir = findWritablePathDir();\n\n if (writablePathDir) {\n const targetPath = join(writablePathDir, aliasName);\n\n if (verbose) {\n console.log(styleText(\"gray\", ` Wrapper: ${wrapperPath}`));\n }\n\n if (existsSync(targetPath)) {\n await unlink(targetPath);\n if (verbose) {\n console.log(styleText(\"gray\", ` Removed existing: ${targetPath}`));\n }\n }\n\n await symlink(wrapperPath, targetPath);\n\n console.log(styleText(\"green\", `[*] Created: ${targetPath} -> ${wrapperPath}`));\n console.log();\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log(styleText([\"green\", \"bold\"], \" ALIAS READY - NO ACTION REQUIRED!\"));\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log();\n console.log(\n styleText(\n \"white\",\n `The alias \"${styleText([\"cyan\", \"bold\"], aliasName)}\" is now available in ALL terminals.`,\n ),\n );\n console.log(styleText(\"gray\", `(Installed to: ${writablePathDir})`));\n\n return {\n aliasPath: targetPath,\n binaryPath: wrapperPath,\n immediate: true,\n };\n }\n\n // Fallback: use ~/.droid-patch/aliases\n console.log(styleText(\"yellow\", \"[*] No writable PATH directory found, using fallback...\"));\n\n const symlinkPath = join(ALIASES_DIR, aliasName);\n\n if (existsSync(symlinkPath)) {\n await unlink(symlinkPath);\n if (verbose) {\n console.log(styleText(\"gray\", ` Removed existing symlink`));\n }\n }\n\n await symlink(wrapperPath, symlinkPath);\n\n console.log(styleText(\"green\", `[*] Created symlink: ${symlinkPath} -> ${wrapperPath}`));\n\n const shellConfig = getShellConfigPath();\n\n if (!checkPathInclusion()) {\n if (!isPathConfigured(shellConfig)) {\n console.log(styleText(\"white\", `[*] Configuring PATH in ${shellConfig}...`));\n\n if (addPathToShellConfig(shellConfig, verbose)) {\n console.log(styleText(\"green\", `[*] PATH configured successfully!`));\n console.log();\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log(styleText([\"yellow\", \"bold\"], \" ACTION REQUIRED\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log();\n console.log(styleText(\"white\", \"To use the alias in this terminal, run:\"));\n console.log();\n console.log(styleText(\"cyan\", ` source ${shellConfig}`));\n console.log();\n console.log(styleText(\"gray\", \"Or simply open a new terminal window.\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n } else {\n const exportLine = `export PATH=\"${ALIASES_DIR}:$PATH\"`;\n console.log();\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log(styleText([\"yellow\", \"bold\"], \" Manual PATH Configuration Required\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log();\n console.log(styleText(\"white\", \"Add this line to your shell config:\"));\n console.log(styleText(\"cyan\", ` ${exportLine}`));\n console.log();\n console.log(styleText(\"gray\", `Shell config file: ${shellConfig}`));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n }\n } else {\n console.log(styleText(\"green\", `[*] PATH already configured in ${shellConfig}`));\n console.log();\n console.log(\n styleText(\n \"yellow\",\n `Note: Run \\`source ${shellConfig}\\` or open a new terminal to use the alias.`,\n ),\n );\n }\n } else {\n console.log(styleText(\"green\", `[*] PATH already includes aliases directory`));\n console.log();\n console.log(\n styleText(\n \"green\",\n `You can now use \"${styleText([\"cyan\", \"bold\"], aliasName)}\" command directly!`,\n ),\n );\n }\n\n return {\n aliasPath: symlinkPath,\n binaryPath: wrapperPath,\n };\n}\n\n/**\n * Create Windows alias for wrapper script (.cmd pointing to wrapper .cmd)\n */\nasync function createWindowsWrapperAlias(\n wrapperPath: string,\n aliasName: string,\n verbose = false,\n): Promise<CreateAliasResult> {\n const binDir = join(DROID_PATCH_DIR, \"bin\");\n if (!existsSync(binDir)) {\n mkdirSync(binDir, { recursive: true });\n }\n\n if (verbose) {\n console.log(styleText(\"gray\", ` Wrapper: ${wrapperPath}`));\n }\n\n // Create .cmd launcher in bin directory that calls the wrapper\n const cmdPath = join(binDir, `${aliasName}.cmd`);\n const cmdContent = generateWindowsLauncher(wrapperPath);\n writeFileSync(cmdPath, cmdContent);\n\n if (verbose) {\n console.log(styleText(\"gray\", ` Created launcher: ${cmdPath}`));\n }\n\n // Try to add bin directory to user PATH\n const pathAdded = addToWindowsUserPath(binDir);\n\n console.log(styleText(\"green\", `[*] Created: ${cmdPath}`));\n console.log();\n\n if (pathAdded) {\n if (checkPathInclusion()) {\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log(styleText([\"green\", \"bold\"], \" ALIAS READY!\"));\n console.log(styleText(\"green\", \"─\".repeat(60)));\n console.log();\n console.log(\n styleText(\n \"white\",\n `The alias \"${styleText([\"cyan\", \"bold\"], aliasName)}\" is now available.`,\n ),\n );\n console.log(styleText(\"gray\", `(Installed to: ${binDir})`));\n\n return {\n aliasPath: cmdPath,\n binaryPath: wrapperPath,\n immediate: true,\n };\n }\n\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log(styleText([\"yellow\", \"bold\"], \" PATH Updated - Restart Terminal\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log();\n console.log(styleText(\"white\", \"PATH has been updated. Please restart your terminal.\"));\n console.log(\n styleText(\n \"white\",\n `Then you can use \"${styleText([\"cyan\", \"bold\"], aliasName)}\" command directly.`,\n ),\n );\n console.log();\n console.log(styleText(\"gray\", `Installed to: ${binDir}`));\n } else {\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log(styleText([\"yellow\", \"bold\"], \" Manual PATH Configuration Required\"));\n console.log(styleText(\"yellow\", \"─\".repeat(60)));\n console.log();\n console.log(styleText(\"white\", \"Add this directory to your PATH:\"));\n console.log(styleText(\"cyan\", ` ${binDir}`));\n console.log();\n console.log(styleText(\"gray\", \"Or run directly:\"));\n console.log(styleText(\"cyan\", ` \"${cmdPath}\"`));\n }\n\n return {\n aliasPath: cmdPath,\n binaryPath: wrapperPath,\n immediate: false,\n };\n}\n\nexport async function restoreOriginal(originalPath: string): Promise<void> {\n ensureDirectories();\n\n const latestBackupPath = join(BINS_DIR, \"droid-original-latest\");\n\n console.log(styleText(\"cyan\", \"═\".repeat(60)));\n console.log(styleText([\"cyan\", \"bold\"], \" Restore Original Droid\"));\n console.log(styleText(\"cyan\", \"═\".repeat(60)));\n console.log();\n\n if (!existsSync(latestBackupPath)) {\n const localBackup = `${originalPath}.backup`;\n if (existsSync(localBackup)) {\n console.log(styleText(\"white\", `[*] Found local backup: ${localBackup}`));\n console.log(styleText(\"white\", `[*] Restoring to: ${originalPath}`));\n\n await copyFile(localBackup, originalPath);\n await chmod(originalPath, 0o755);\n\n if (process.platform === \"darwin\") {\n try {\n execSync(`codesign --force --deep --sign - \"${originalPath}\"`, {\n stdio: \"pipe\",\n });\n execSync(`xattr -cr \"${originalPath}\"`, { stdio: \"pipe\" });\n } catch {\n // Ignore\n }\n }\n\n console.log();\n console.log(styleText(\"green\", \"═\".repeat(60)));\n console.log(styleText([\"green\", \"bold\"], \" RESTORE COMPLETE\"));\n console.log(styleText(\"green\", \"═\".repeat(60)));\n console.log();\n console.log(styleText(\"green\", \"Original droid binary has been restored from local backup.\"));\n return;\n }\n\n console.log(styleText(\"red\", \"[!] No backup found.\"));\n console.log(styleText(\"gray\", ` Checked: ${latestBackupPath}`));\n console.log(styleText(\"gray\", ` Checked: ${localBackup}`));\n console.log();\n console.log(styleText(\"gray\", \"If you have a manual backup, restore it with:\"));\n console.log(styleText(\"cyan\", ` cp /path/to/backup ${originalPath}`));\n return;\n }\n\n console.log(styleText(\"white\", `[*] Restoring from: ${latestBackupPath}`));\n console.log(styleText(\"white\", `[*] Restoring to: ${originalPath}`));\n\n const targetDir = dirname(originalPath);\n if (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n }\n\n await copyFile(latestBackupPath, originalPath);\n await chmod(originalPath, 0o755);\n\n if (process.platform === \"darwin\") {\n try {\n execSync(`codesign --force --deep --sign - \"${originalPath}\"`, {\n stdio: \"pipe\",\n });\n execSync(`xattr -cr \"${originalPath}\"`, { stdio: \"pipe\" });\n } catch {\n // Ignore\n }\n }\n\n console.log();\n console.log(styleText(\"green\", \"═\".repeat(60)));\n console.log(styleText([\"green\", \"bold\"], \" RESTORE COMPLETE\"));\n console.log(styleText(\"green\", \"═\".repeat(60)));\n console.log();\n console.log(styleText(\"green\", \"Original droid binary has been restored.\"));\n console.log(styleText(\"green\", \"All terminals will now use the original version.\"));\n}\n\n/**\n * Filter options for removing aliases\n * Uses the same names as CLI options for consistency\n */\nexport type FilterFlag =\n | \"is-custom\"\n | \"skip-login\"\n | \"websearch\"\n | \"api-base\"\n | \"reasoning-effort\"\n | \"disable-telemetry\"\n | \"standalone\";\n\nexport interface RemoveFilterOptions {\n /** Remove aliases created by this droid-patch version */\n patchVersion?: string;\n /** Remove aliases for this droid version */\n droidVersion?: string;\n /** Remove aliases that have these flags enabled (all must match) */\n flags?: FilterFlag[];\n}\n\n/**\n * Remove aliases matching filter criteria\n */\nexport async function removeAliasesByFilter(filter: RemoveFilterOptions): Promise<void> {\n console.log(styleText(\"cyan\", \"═\".repeat(60)));\n console.log(styleText([\"cyan\", \"bold\"], \" Remove Aliases by Filter\"));\n console.log(styleText(\"cyan\", \"═\".repeat(60)));\n console.log();\n\n // Show filter criteria\n if (filter.patchVersion) {\n console.log(styleText(\"white\", ` Filter: droid-patch version = ${filter.patchVersion}`));\n }\n if (filter.droidVersion) {\n console.log(styleText(\"white\", ` Filter: droid version = ${filter.droidVersion}`));\n }\n if (filter.flags && filter.flags.length > 0) {\n console.log(styleText(\"white\", ` Filter: flags = ${filter.flags.join(\", \")}`));\n }\n console.log();\n\n // Collect all alias names\n const aliasNames = new Set<string>();\n\n // Check common PATH directories for symlinks\n for (const pathDir of COMMON_PATH_DIRS) {\n if (!existsSync(pathDir)) continue;\n\n try {\n const files = readdirSync(pathDir);\n for (const file of files) {\n const fullPath = join(pathDir, file);\n try {\n const stats = lstatSync(fullPath);\n if (stats.isSymbolicLink()) {\n const target = await readlink(fullPath);\n if (\n target.includes(\".droid-patch/bins\") ||\n target.includes(\".droid-patch/websearch\") ||\n target.includes(\".droid-patch/proxy\") ||\n target.includes(\".droid-patch/statusline\")\n ) {\n aliasNames.add(file);\n }\n }\n } catch {\n // Ignore\n }\n }\n } catch {\n // Directory can't be read\n }\n }\n\n // Check aliases directory\n if (existsSync(ALIASES_DIR)) {\n try {\n const files = readdirSync(ALIASES_DIR);\n for (const file of files) {\n const fullPath = join(ALIASES_DIR, file);\n try {\n const stats = lstatSync(fullPath);\n if (stats.isSymbolicLink()) {\n aliasNames.add(file);\n }\n } catch {\n // Ignore\n }\n }\n } catch {\n // Directory can't be read\n }\n }\n\n // Filter aliases by metadata\n const matchingAliases: string[] = [];\n\n for (const aliasName of aliasNames) {\n const meta = await loadAliasMetadata(aliasName);\n\n // If no metadata, skip (can't filter without metadata)\n if (!meta) {\n continue;\n }\n\n let matches = true;\n\n // Check droid-patch version\n if (filter.patchVersion && meta.droidPatchVersion !== filter.patchVersion) {\n matches = false;\n }\n\n // Check droid version\n if (filter.droidVersion && meta.droidVersion !== filter.droidVersion) {\n matches = false;\n }\n\n // Check flags (all specified flags must match)\n if (filter.flags && filter.flags.length > 0) {\n const patches = meta.patches;\n for (const flag of filter.flags) {\n switch (flag) {\n case \"is-custom\":\n if (!patches.isCustom) matches = false;\n break;\n case \"skip-login\":\n if (!patches.skipLogin) matches = false;\n break;\n case \"websearch\":\n if (!patches.websearch) matches = false;\n break;\n case \"reasoning-effort\":\n if (!patches.reasoningEffort) matches = false;\n break;\n case \"api-base\":\n if (!patches.apiBase) matches = false;\n break;\n case \"disable-telemetry\":\n if (!patches.noTelemetry) matches = false;\n break;\n case \"standalone\":\n if (!patches.standalone) matches = false;\n break;\n }\n if (!matches) break;\n }\n }\n\n if (matches) {\n matchingAliases.push(aliasName);\n }\n }\n\n if (matchingAliases.length === 0) {\n console.log(styleText(\"yellow\", \" No aliases match the filter criteria.\"));\n console.log();\n return;\n }\n\n console.log(styleText(\"white\", ` Found ${matchingAliases.length} matching alias(es):`));\n for (const name of matchingAliases) {\n console.log(styleText(\"gray\", ` • ${name}`));\n }\n console.log();\n\n // Remove each matching alias\n for (const aliasName of matchingAliases) {\n await removeAlias(aliasName);\n console.log();\n }\n\n console.log(styleText(\"green\", `[*] Removed ${matchingAliases.length} alias(es)`));\n}\n\n/**\n * Clear all droid-patch aliases and related files\n */\nexport async function clearAllAliases(): Promise<void> {\n console.log(styleText(\"cyan\", \"═\".repeat(60)));\n console.log(styleText([\"cyan\", \"bold\"], \" Clearing All Droid-Patch Data\"));\n console.log(styleText(\"cyan\", \"═\".repeat(60)));\n console.log();\n\n // Collect all alias names\n const aliasNames = new Set<string>();\n\n // Check common PATH directories for symlinks\n for (const pathDir of COMMON_PATH_DIRS) {\n if (!existsSync(pathDir)) continue;\n\n try {\n const files = readdirSync(pathDir);\n for (const file of files) {\n const fullPath = join(pathDir, file);\n try {\n const stats = lstatSync(fullPath);\n if (stats.isSymbolicLink()) {\n const target = await readlink(fullPath);\n if (\n target.includes(\".droid-patch/bins\") ||\n target.includes(\".droid-patch/websearch\") ||\n target.includes(\".droid-patch/proxy\") ||\n target.includes(\".droid-patch/statusline\")\n ) {\n aliasNames.add(file);\n }\n }\n } catch {\n // Ignore\n }\n }\n } catch {\n // Directory can't be read\n }\n }\n\n // Check aliases directory\n if (existsSync(ALIASES_DIR)) {\n try {\n const files = readdirSync(ALIASES_DIR);\n for (const file of files) {\n const fullPath = join(ALIASES_DIR, file);\n try {\n const stats = lstatSync(fullPath);\n if (stats.isSymbolicLink()) {\n aliasNames.add(file);\n }\n } catch {\n // Ignore\n }\n }\n } catch {\n // Directory can't be read\n }\n }\n\n if (aliasNames.size === 0) {\n console.log(styleText(\"yellow\", \" No aliases found.\"));\n } else {\n console.log(styleText(\"white\", ` Found ${aliasNames.size} alias(es) to remove:`));\n for (const name of aliasNames) {\n console.log(styleText(\"gray\", ` • ${name}`));\n }\n console.log();\n\n // Remove each alias\n for (const aliasName of aliasNames) {\n await removeAlias(aliasName);\n console.log();\n }\n }\n\n // Clean up directories (including legacy files)\n console.log(styleText(\"white\", \" Cleaning up directories...\"));\n const dirsToClean = [\n join(DROID_PATCH_DIR, \"bins\"),\n join(DROID_PATCH_DIR, \"aliases\"),\n join(DROID_PATCH_DIR, \"proxy\"),\n join(DROID_PATCH_DIR, \"websearch\"),\n join(DROID_PATCH_DIR, \"statusline\"),\n ];\n\n for (const dir of dirsToClean) {\n if (existsSync(dir)) {\n try {\n const files = readdirSync(dir);\n for (const file of files) {\n const fullPath = join(dir, file);\n try {\n await unlink(fullPath);\n console.log(styleText(\"green\", ` Removed: ${fullPath}`));\n } catch {\n // Ignore\n }\n }\n } catch {\n // Ignore\n }\n }\n }\n\n // Clean up legacy temp files from old versions\n const legacyTempFiles = [\"/tmp/droid-search-proxy.pid\", \"/tmp/droid-search-proxy.log\"];\n\n for (const tempFile of legacyTempFiles) {\n if (existsSync(tempFile)) {\n try {\n await unlink(tempFile);\n console.log(styleText(\"green\", ` Removed legacy: ${tempFile}`));\n } catch {\n // Ignore\n }\n }\n }\n\n // Clean up temp port files (pattern: /tmp/droid-websearch-*.port)\n try {\n const tmpFiles = readdirSync(\"/tmp\");\n for (const file of tmpFiles) {\n if (file.startsWith(\"droid-websearch-\") && file.endsWith(\".port\")) {\n const fullPath = join(\"/tmp\", file);\n try {\n await unlink(fullPath);\n console.log(styleText(\"green\", ` Removed temp: ${fullPath}`));\n } catch {\n // Ignore\n }\n }\n // Also clean old droid-search-proxy-*.port files\n if (file.startsWith(\"droid-search-proxy-\") && file.endsWith(\".port\")) {\n const fullPath = join(\"/tmp\", file);\n try {\n await unlink(fullPath);\n console.log(styleText(\"green\", ` Removed legacy temp: ${fullPath}`));\n } catch {\n // Ignore\n }\n }\n }\n } catch {\n // Ignore\n }\n\n // Clean up metadata file\n const metadataFile = join(DROID_PATCH_DIR, \"metadata.json\");\n if (existsSync(metadataFile)) {\n try {\n await unlink(metadataFile);\n console.log(styleText(\"green\", ` Removed: ${metadataFile}`));\n } catch {\n // Ignore\n }\n }\n\n console.log();\n console.log(styleText(\"green\", \"[*] All droid-patch data cleared successfully\"));\n}\n"],"mappings":"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"}