@duheso/zerocli 0.8.1 → 0.8.3
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/chrome-extension/README.md +147 -0
- package/chrome-extension/background.js +912 -0
- package/chrome-extension/content.js +26 -0
- package/chrome-extension/icons/icon128.png +0 -0
- package/chrome-extension/icons/icon16.png +0 -0
- package/chrome-extension/icons/icon48.png +0 -0
- package/chrome-extension/manifest.json +56 -0
- package/chrome-extension/offscreen.html +7 -0
- package/chrome-extension/offscreen.js +28 -0
- package/chrome-extension/popup.css +190 -0
- package/chrome-extension/popup.html +65 -0
- package/chrome-extension/popup.js +76 -0
- package/dist/cli.mjs +81 -100
- package/package.json +3 -1
- package/scripts/setup-chrome-native-host.mjs +228 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duheso/zerocli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Zero Cli to any LLM — OpenAI, Gemini, DeepSeek, Ollama, and 200+ models",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
"bin/",
|
|
11
11
|
"dist/cli.mjs",
|
|
12
12
|
"dist/vendor/ripgrep",
|
|
13
|
+
"chrome-extension/",
|
|
14
|
+
"scripts/setup-chrome-native-host.mjs",
|
|
13
15
|
"README.md"
|
|
14
16
|
],
|
|
15
17
|
"scripts": {
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ZeroCLI — Chrome Native Host Setup Script
|
|
4
|
+
*
|
|
5
|
+
* Registers the native messaging host for the ZeroCLI Browser Extension.
|
|
6
|
+
* Run this ONCE before using the chrome extension:
|
|
7
|
+
*
|
|
8
|
+
* node scripts/setup-chrome-native-host.mjs
|
|
9
|
+
* (or: bun scripts/setup-chrome-native-host.mjs)
|
|
10
|
+
*
|
|
11
|
+
* What it does:
|
|
12
|
+
* - Finds (or creates) the native host wrapper script
|
|
13
|
+
* - Writes the native host manifest JSON
|
|
14
|
+
* - On Windows: registers it in the Windows Registry
|
|
15
|
+
* - On macOS/Linux: writes to NativeMessagingHosts directories
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { execSync, spawnSync } from 'child_process'
|
|
19
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs'
|
|
20
|
+
import { homedir, platform } from 'os'
|
|
21
|
+
import { dirname, join, resolve } from 'path'
|
|
22
|
+
import { fileURLToPath } from 'url'
|
|
23
|
+
|
|
24
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
25
|
+
const ROOT = resolve(__dirname, '..')
|
|
26
|
+
|
|
27
|
+
const NATIVE_HOST_NAME = 'com.duheso.zerocli_browser_extension'
|
|
28
|
+
const ZEROCLI_EXTENSION_ID = 'ccmaidbdaocjoeceanhlkafcokhmiolf'
|
|
29
|
+
|
|
30
|
+
// ─── Find the zero executable ─────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
function findZeroExecutable() {
|
|
33
|
+
// Priority: use node + dist/cli.mjs directly, which is the most reliable
|
|
34
|
+
// path for Chrome native messaging (avoids wrapper chain issues).
|
|
35
|
+
|
|
36
|
+
// 1. dist/cli.mjs in this repo (dev mode / cloned repo)
|
|
37
|
+
const devCli = join(ROOT, 'dist', 'cli.mjs')
|
|
38
|
+
if (existsSync(devCli)) {
|
|
39
|
+
return { node: process.execPath, cli: devCli }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 2. Find globally installed @duheso/zerocli — locate its dist/cli.mjs
|
|
43
|
+
// by resolving from the zero bin script location
|
|
44
|
+
const which = platform() === 'win32'
|
|
45
|
+
? spawnSync('where', ['zero'], { shell: true })
|
|
46
|
+
: spawnSync('which', ['zero'])
|
|
47
|
+
if (which.status === 0) {
|
|
48
|
+
const zeroBin = which.stdout.toString().trim().split('\n')[0].trim()
|
|
49
|
+
.replace(/\r/g, '')
|
|
50
|
+
// zero bin is at: <pkg_root>/bin/zero(.cmd)
|
|
51
|
+
// dist/cli.mjs is at: <pkg_root>/dist/cli.mjs
|
|
52
|
+
const pkgRoot = resolve(dirname(zeroBin), '..')
|
|
53
|
+
const globalCli = join(pkgRoot, 'dist', 'cli.mjs')
|
|
54
|
+
if (existsSync(globalCli)) {
|
|
55
|
+
return { node: process.execPath, cli: globalCli }
|
|
56
|
+
}
|
|
57
|
+
// On Windows, zero.cmd might be in %APPDATA%\npm\, and the actual package
|
|
58
|
+
// might be in %APPDATA%\npm\node_modules\@duheso\zerocli\
|
|
59
|
+
const winModules = join(dirname(zeroBin), 'node_modules', '@duheso', 'zerocli', 'dist', 'cli.mjs')
|
|
60
|
+
if (existsSync(winModules)) {
|
|
61
|
+
return { node: process.execPath, cli: winModules }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 3. Common Windows npm global path
|
|
66
|
+
if (platform() === 'win32') {
|
|
67
|
+
const appData = process.env.APPDATA ?? join(homedir(), 'AppData', 'Roaming')
|
|
68
|
+
const winCli = join(appData, 'npm', 'node_modules', '@duheso', 'zerocli', 'dist', 'cli.mjs')
|
|
69
|
+
if (existsSync(winCli)) {
|
|
70
|
+
return { node: process.execPath, cli: winCli }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ─── Create wrapper script (Windows .cmd / Unix shell) ────────────────────────
|
|
78
|
+
|
|
79
|
+
function createWrapperScript({ node, cli }) {
|
|
80
|
+
const chromeDir = join(homedir(), '.zerocli', 'chrome')
|
|
81
|
+
mkdirSync(chromeDir, { recursive: true })
|
|
82
|
+
|
|
83
|
+
if (platform() === 'win32') {
|
|
84
|
+
const wrapperPath = join(chromeDir, 'zerocli-native-host.cmd')
|
|
85
|
+
const content = `@echo off\r\n"${node}" "${cli}" --chrome-native-host\r\n`
|
|
86
|
+
writeFileSync(wrapperPath, content, 'utf8')
|
|
87
|
+
console.log(` ✓ Wrapper script: ${wrapperPath}`)
|
|
88
|
+
return wrapperPath
|
|
89
|
+
} else {
|
|
90
|
+
const wrapperPath = join(chromeDir, 'zerocli-native-host.sh')
|
|
91
|
+
const content = `#!/bin/sh\nexec "${node}" "${cli}" --chrome-native-host\n`
|
|
92
|
+
writeFileSync(wrapperPath, content, { encoding: 'utf8', mode: 0o755 })
|
|
93
|
+
console.log(` ✓ Wrapper script: ${wrapperPath}`)
|
|
94
|
+
return wrapperPath
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ─── Write manifest JSON ───────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
function writeManifest(wrapperPath) {
|
|
101
|
+
const manifest = {
|
|
102
|
+
name: NATIVE_HOST_NAME,
|
|
103
|
+
description: 'ZeroCLI Browser Extension Native Host',
|
|
104
|
+
path: wrapperPath,
|
|
105
|
+
type: 'stdio',
|
|
106
|
+
allowed_origins: [
|
|
107
|
+
`chrome-extension://${ZEROCLI_EXTENSION_ID}/`,
|
|
108
|
+
],
|
|
109
|
+
}
|
|
110
|
+
const manifestContent = JSON.stringify(manifest, null, 2)
|
|
111
|
+
|
|
112
|
+
if (platform() === 'win32') {
|
|
113
|
+
// On Windows, path is given directly via registry — we still write the JSON next to the wrapper
|
|
114
|
+
const manifestPath = join(dirname(wrapperPath), `${NATIVE_HOST_NAME}.json`)
|
|
115
|
+
writeFileSync(manifestPath, manifestContent, 'utf8')
|
|
116
|
+
console.log(` ✓ Manifest JSON: ${manifestPath}`)
|
|
117
|
+
return manifestPath
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// macOS / Linux: write to all browser NativeMessagingHosts dirs
|
|
121
|
+
const dirs = getNativeMessagingDirs()
|
|
122
|
+
let written = 0
|
|
123
|
+
for (const dir of dirs) {
|
|
124
|
+
try {
|
|
125
|
+
mkdirSync(dir, { recursive: true })
|
|
126
|
+
const manifestPath = join(dir, `${NATIVE_HOST_NAME}.json`)
|
|
127
|
+
writeFileSync(manifestPath, manifestContent, 'utf8')
|
|
128
|
+
console.log(` ✓ Manifest: ${manifestPath}`)
|
|
129
|
+
written++
|
|
130
|
+
} catch (e) {
|
|
131
|
+
console.warn(` ⚠ Could not write to ${dir}: ${e.message}`)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (written === 0) throw new Error('Could not write manifest to any browser directory')
|
|
135
|
+
return null
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function getNativeMessagingDirs() {
|
|
139
|
+
if (platform() === 'darwin') {
|
|
140
|
+
return [
|
|
141
|
+
join(homedir(), 'Library', 'Application Support', 'Google', 'Chrome', 'NativeMessagingHosts'),
|
|
142
|
+
join(homedir(), 'Library', 'Application Support', 'Microsoft Edge', 'NativeMessagingHosts'),
|
|
143
|
+
join(homedir(), 'Library', 'Application Support', 'BraveSoftware', 'Brave-Browser', 'NativeMessagingHosts'),
|
|
144
|
+
join(homedir(), 'Library', 'Application Support', 'Chromium', 'NativeMessagingHosts'),
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
// Linux
|
|
148
|
+
return [
|
|
149
|
+
join(homedir(), '.config', 'google-chrome', 'NativeMessagingHosts'),
|
|
150
|
+
join(homedir(), '.config', 'microsoft-edge', 'NativeMessagingHosts'),
|
|
151
|
+
join(homedir(), '.config', 'BraveSoftware', 'Brave-Browser', 'NativeMessagingHosts'),
|
|
152
|
+
join(homedir(), '.config', 'chromium', 'NativeMessagingHosts'),
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ─── Windows Registry ─────────────────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
function registerWindows(manifestJsonPath) {
|
|
159
|
+
const browsers = {
|
|
160
|
+
Chrome: `HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${NATIVE_HOST_NAME}`,
|
|
161
|
+
Edge: `HKCU\\Software\\Microsoft\\Edge\\NativeMessagingHosts\\${NATIVE_HOST_NAME}`,
|
|
162
|
+
Brave: `HKCU\\Software\\BraveSoftware\\Brave-Browser\\NativeMessagingHosts\\${NATIVE_HOST_NAME}`,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (const [browser, regKey] of Object.entries(browsers)) {
|
|
166
|
+
try {
|
|
167
|
+
const result = spawnSync('reg', [
|
|
168
|
+
'add', regKey,
|
|
169
|
+
'/ve',
|
|
170
|
+
'/t', 'REG_SZ',
|
|
171
|
+
'/d', manifestJsonPath,
|
|
172
|
+
'/f',
|
|
173
|
+
], { shell: true })
|
|
174
|
+
if (result.status === 0) {
|
|
175
|
+
console.log(` ✓ Registry (${browser}): ${regKey}`)
|
|
176
|
+
} else {
|
|
177
|
+
console.warn(` ⚠ Registry (${browser}) failed: ${result.stderr?.toString()}`)
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
console.warn(` ⚠ Registry (${browser}) error: ${e.message}`)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ─── Main ─────────────────────────────────────────────────────────────────────
|
|
186
|
+
|
|
187
|
+
console.log('\n🔧 ZeroCLI Chrome Native Host Setup\n')
|
|
188
|
+
|
|
189
|
+
console.log('1. Locating ZeroCLI dist/cli.mjs...')
|
|
190
|
+
const found = findZeroExecutable()
|
|
191
|
+
if (!found) {
|
|
192
|
+
console.error(`
|
|
193
|
+
✗ Could not find ZeroCLI dist/cli.mjs.
|
|
194
|
+
|
|
195
|
+
Options:
|
|
196
|
+
a) Run this script from the ZeroCLI repo root: node scripts/setup-chrome-native-host.mjs
|
|
197
|
+
b) Install globally: npm install -g @duheso/zerocli
|
|
198
|
+
c) Set PATH to include the folder containing 'zero'
|
|
199
|
+
`)
|
|
200
|
+
process.exit(1)
|
|
201
|
+
}
|
|
202
|
+
console.log(` ✓ Node: ${found.node}`)
|
|
203
|
+
console.log(` ✓ CLI script: ${found.cli}\n`)
|
|
204
|
+
|
|
205
|
+
console.log('2. Creating wrapper script...')
|
|
206
|
+
const wrapperPath = createWrapperScript(found)
|
|
207
|
+
console.log()
|
|
208
|
+
|
|
209
|
+
console.log('3. Writing native host manifest...')
|
|
210
|
+
const manifestJsonPath = writeManifest(wrapperPath)
|
|
211
|
+
console.log()
|
|
212
|
+
|
|
213
|
+
if (platform() === 'win32') {
|
|
214
|
+
console.log('4. Registering in Windows Registry...')
|
|
215
|
+
registerWindows(manifestJsonPath)
|
|
216
|
+
console.log()
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
console.log(`✅ Setup complete!
|
|
220
|
+
|
|
221
|
+
Next steps:
|
|
222
|
+
1. Make sure the ZeroCLI Browser Extension is loaded in Chrome:
|
|
223
|
+
chrome://extensions → Developer mode ON → Load unpacked → select chrome-extension/
|
|
224
|
+
|
|
225
|
+
2. Reload the extension (click the reload ↺ button on chrome://extensions)
|
|
226
|
+
|
|
227
|
+
3. The extension popup should now show "Connected"
|
|
228
|
+
`)
|