pi-neutrasearch 0.2.0 → 0.2.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 +7 -1
- package/assets/neutrasearch.svg +7 -0
- package/index.js +6 -1
- package/package.json +3 -1
- package/shortcuts.js +123 -0
package/README.md
CHANGED
|
@@ -20,7 +20,13 @@ Inside Pi, run:
|
|
|
20
20
|
/neutrasearch-setup
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
This opens the bundled Neutrasearch app
|
|
23
|
+
This installs convenient shortcuts and opens the bundled Neutrasearch app:
|
|
24
|
+
|
|
25
|
+
- Linux: application menu, Desktop, and `~/.local/bin` CLI links
|
|
26
|
+
- Windows: Start Menu and Desktop shortcuts
|
|
27
|
+
- macOS: `~/Applications/Neutrasearch.app` and a Desktop alias
|
|
28
|
+
|
|
29
|
+
Approve local indexing in the app, then return to Pi. Indexing remains an explicit user action; package installation never scans disks or requests privileges.
|
|
24
30
|
|
|
25
31
|
Use `/neutrasearch` to inspect installation and index status.
|
|
26
32
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
+
<rect width="64" height="64" rx="11" fill="#111512"/>
|
|
3
|
+
<path d="M16 17h23l9 9v21H16z" fill="#1d241f" stroke="#a8ff60" stroke-width="3"/>
|
|
4
|
+
<path d="M39 17v10h9" fill="none" stroke="#a8ff60" stroke-width="3"/>
|
|
5
|
+
<circle cx="29" cy="36" r="8" fill="none" stroke="#f2f5f1" stroke-width="3"/>
|
|
6
|
+
<path d="m35 42 8 8" stroke="#f2f5f1" stroke-width="4" stroke-linecap="square"/>
|
|
7
|
+
</svg>
|
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { installShortcuts } from "./shortcuts.js";
|
|
2
3
|
import {
|
|
3
4
|
compactSearchResult,
|
|
4
5
|
limits,
|
|
@@ -181,13 +182,17 @@ export default function register(pi) {
|
|
|
181
182
|
return;
|
|
182
183
|
}
|
|
183
184
|
try {
|
|
185
|
+
const shortcuts = installShortcuts(application);
|
|
184
186
|
const child = spawn(application, [], {
|
|
185
187
|
detached: true,
|
|
186
188
|
stdio: "ignore",
|
|
187
189
|
windowsHide: false,
|
|
188
190
|
});
|
|
189
191
|
child.unref();
|
|
190
|
-
ctx.ui.notify(
|
|
192
|
+
ctx.ui.notify(
|
|
193
|
+
`Neutrasearch opened and ${shortcuts.length} shortcuts were installed. Approve local indexing in the app, then return to Pi.`,
|
|
194
|
+
"info",
|
|
195
|
+
);
|
|
191
196
|
} catch (error) {
|
|
192
197
|
ctx.ui.notify(`Could not open Neutrasearch: ${shortError(error)}`, "error");
|
|
193
198
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-neutrasearch",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Token-efficient native indexed filename and path search for Pi agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"index.js",
|
|
27
27
|
"lib.js",
|
|
28
|
+
"shortcuts.js",
|
|
29
|
+
"assets",
|
|
28
30
|
"README.md",
|
|
29
31
|
"LICENSE",
|
|
30
32
|
"skills"
|
package/shortcuts.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
function quoteDesktop(value) {
|
|
8
|
+
return `"${String(value).replace(/(["`$\\])/g, "\\$1")}"`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function shellQuote(value) {
|
|
12
|
+
return `'${String(value).replaceAll("'", "'\\''")}'`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function writeExecutable(file, content) {
|
|
16
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
17
|
+
fs.writeFileSync(file, content, { mode: 0o755 });
|
|
18
|
+
fs.chmodSync(file, 0o755);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function installLinux(application, home, packageRoot) {
|
|
22
|
+
const binRoot = path.dirname(application);
|
|
23
|
+
const icon = path.join(packageRoot, "assets", "neutrasearch.svg");
|
|
24
|
+
const applications = path.join(home, ".local", "share", "applications");
|
|
25
|
+
const desktopEntry = path.join(applications, "neutrasearch.desktop");
|
|
26
|
+
fs.mkdirSync(applications, { recursive: true });
|
|
27
|
+
const content = [
|
|
28
|
+
"[Desktop Entry]",
|
|
29
|
+
"Type=Application",
|
|
30
|
+
"Version=1.0",
|
|
31
|
+
"Name=Neutrasearch",
|
|
32
|
+
"GenericName=Indexed File Search",
|
|
33
|
+
"Comment=Search indexed filenames and paths without walking folders",
|
|
34
|
+
`Exec=${quoteDesktop(application)}`,
|
|
35
|
+
`Icon=${icon}`,
|
|
36
|
+
"Terminal=false",
|
|
37
|
+
"Categories=Utility;FileTools;System;",
|
|
38
|
+
"Keywords=search;files;index;filename;",
|
|
39
|
+
"StartupNotify=true",
|
|
40
|
+
"StartupWMClass=neutrasearch",
|
|
41
|
+
"",
|
|
42
|
+
].join("\n");
|
|
43
|
+
writeExecutable(desktopEntry, content);
|
|
44
|
+
|
|
45
|
+
const created = [desktopEntry];
|
|
46
|
+
const desktop = path.join(home, "Desktop");
|
|
47
|
+
if (fs.existsSync(desktop)) {
|
|
48
|
+
const desktopShortcut = path.join(desktop, "Neutrasearch.desktop");
|
|
49
|
+
writeExecutable(desktopShortcut, content);
|
|
50
|
+
created.push(desktopShortcut);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const localBin = path.join(home, ".local", "bin");
|
|
54
|
+
fs.mkdirSync(localBin, { recursive: true });
|
|
55
|
+
for (const name of ["neutrasearch", "neutrasearch-query", "neutrasearch-helper", "neutrasearch-mcp"]) {
|
|
56
|
+
const source = path.join(binRoot, name);
|
|
57
|
+
if (!fs.existsSync(source)) continue;
|
|
58
|
+
const destination = path.join(localBin, name);
|
|
59
|
+
try { fs.rmSync(destination, { force: true }); } catch {}
|
|
60
|
+
fs.symlinkSync(source, destination);
|
|
61
|
+
created.push(destination);
|
|
62
|
+
}
|
|
63
|
+
return created;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function installWindows(application, home, runPowerShell) {
|
|
67
|
+
const script = [
|
|
68
|
+
"$ErrorActionPreference = 'Stop'",
|
|
69
|
+
"$shell = New-Object -ComObject WScript.Shell",
|
|
70
|
+
"$targets = @(",
|
|
71
|
+
" [Environment]::GetFolderPath('Programs') + '\\Neutrasearch.lnk',",
|
|
72
|
+
" [Environment]::GetFolderPath('Desktop') + '\\Neutrasearch.lnk'",
|
|
73
|
+
")",
|
|
74
|
+
"foreach ($target in $targets) {",
|
|
75
|
+
" $shortcut = $shell.CreateShortcut($target)",
|
|
76
|
+
" $shortcut.TargetPath = $env:NEUTRASEARCH_APP",
|
|
77
|
+
" $shortcut.WorkingDirectory = Split-Path $env:NEUTRASEARCH_APP",
|
|
78
|
+
" $shortcut.IconLocation = $env:NEUTRASEARCH_APP",
|
|
79
|
+
" $shortcut.Description = 'Indexed filename and path search'",
|
|
80
|
+
" $shortcut.Save()",
|
|
81
|
+
"}",
|
|
82
|
+
].join("\n");
|
|
83
|
+
runPowerShell("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], {
|
|
84
|
+
env: { ...process.env, HOME: home, NEUTRASEARCH_APP: application },
|
|
85
|
+
stdio: "ignore",
|
|
86
|
+
});
|
|
87
|
+
return ["Windows Start Menu/Neutrasearch.lnk", "Windows Desktop/Neutrasearch.lnk"];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function installMac(application, home) {
|
|
91
|
+
const app = path.join(home, "Applications", "Neutrasearch.app");
|
|
92
|
+
const contents = path.join(app, "Contents");
|
|
93
|
+
const launcher = path.join(contents, "MacOS", "Neutrasearch");
|
|
94
|
+
writeExecutable(launcher, `#!/bin/sh\nexec ${shellQuote(application)} "$@"\n`);
|
|
95
|
+
fs.writeFileSync(
|
|
96
|
+
path.join(contents, "Info.plist"),
|
|
97
|
+
`<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0"><dict><key>CFBundleName</key><string>Neutrasearch</string><key>CFBundleDisplayName</key><string>Neutrasearch</string><key>CFBundleIdentifier</key><string>dev.pi.neutrasearch</string><key>CFBundleExecutable</key><string>Neutrasearch</string><key>CFBundlePackageType</key><string>APPL</string></dict></plist>\n`,
|
|
98
|
+
);
|
|
99
|
+
const created = [app];
|
|
100
|
+
const desktop = path.join(home, "Desktop");
|
|
101
|
+
if (fs.existsSync(desktop)) {
|
|
102
|
+
const link = path.join(desktop, "Neutrasearch.app");
|
|
103
|
+
try { fs.rmSync(link, { recursive: true, force: true }); } catch {}
|
|
104
|
+
fs.symlinkSync(app, link);
|
|
105
|
+
created.push(link);
|
|
106
|
+
}
|
|
107
|
+
return created;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function installShortcuts(application, options = {}) {
|
|
111
|
+
if (!application || !path.isAbsolute(application) || !fs.existsSync(application)) {
|
|
112
|
+
throw new Error("Neutrasearch application is missing");
|
|
113
|
+
}
|
|
114
|
+
const platform = options.platform || process.platform;
|
|
115
|
+
const home = options.home || os.homedir();
|
|
116
|
+
const packageRoot = options.packageRoot || path.dirname(fileURLToPath(import.meta.url));
|
|
117
|
+
if (platform === "linux") return installLinux(application, home, packageRoot);
|
|
118
|
+
if (platform === "win32") {
|
|
119
|
+
return installWindows(application, home, options.runPowerShell || execFileSync);
|
|
120
|
+
}
|
|
121
|
+
if (platform === "darwin") return installMac(application, home);
|
|
122
|
+
throw new Error(`shortcut installation is unsupported on ${platform}`);
|
|
123
|
+
}
|