tab-agent 0.4.0 → 0.4.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/CHANGELOG.md +10 -0
- package/README.md +27 -6
- package/cli/setup.js +42 -1
- package/extension/manifest.json +1 -1
- package/extension/manifest.safari.json +1 -1
- package/package.json +1 -1
- package/relay/install-native-host.sh +12 -5
- package/relay/server.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.1] - 2026-03-15
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- `setup` now installs the native host into a stable user-library location instead of pointing Chrome at the repo checkout
|
|
7
|
+
- Native host installation now copies the `ws` dependency from the packaged install, so fresh npm installs can launch reliably
|
|
8
|
+
- Relay server now accepts the current Chrome native-host client identifier, fixing cases where Chrome was connected but commands could not see an active browser
|
|
9
|
+
|
|
10
|
+
### Docs
|
|
11
|
+
- README now treats `status` as part of the setup flow and documents the native-host recovery steps that go with the new install path
|
|
12
|
+
|
|
3
13
|
## [0.4.0] - 2026-03-14
|
|
4
14
|
|
|
5
15
|
### Added
|
package/README.md
CHANGED
|
@@ -73,12 +73,15 @@ npx tab-agent@latest setup
|
|
|
73
73
|
# 3. Start relay
|
|
74
74
|
npx tab-agent@latest start
|
|
75
75
|
|
|
76
|
-
# 4.
|
|
76
|
+
# 4. Verify wiring
|
|
77
|
+
npx tab-agent@latest status
|
|
78
|
+
|
|
79
|
+
# 5. Activate & go
|
|
77
80
|
# Click extension icon on any tab (turns green)
|
|
78
81
|
# Ask Claude/Codex: "Search Amazon for mechanical keyboards and find the best rated"
|
|
79
82
|
```
|
|
80
83
|
|
|
81
|
-
If you have an older cached `npx` install, keep using `@latest` for `setup` and `
|
|
84
|
+
If you have an older cached `npx` install, keep using `@latest` for `setup`, `start`, and `status` so the CLI/runtime matches the current extension release.
|
|
82
85
|
|
|
83
86
|
<p align="center">
|
|
84
87
|
<img src="assets/toggle-demo.gif" alt="Pin extension and toggle on/off" width="600">
|
|
@@ -172,7 +175,7 @@ cd tab-agent
|
|
|
172
175
|
npx tab-agent@latest setup
|
|
173
176
|
```
|
|
174
177
|
|
|
175
|
-
This auto-detects unpacked and installed Tab Agent extensions,
|
|
178
|
+
This auto-detects unpacked and installed Tab Agent extensions, copies the native host into a stable per-user directory, and configures everything.
|
|
176
179
|
|
|
177
180
|
### 3. Start Relay
|
|
178
181
|
|
|
@@ -182,7 +185,19 @@ npx tab-agent@latest start
|
|
|
182
185
|
|
|
183
186
|
Keep this running in a terminal while you use `tab-agent` commands.
|
|
184
187
|
|
|
185
|
-
### 4.
|
|
188
|
+
### 4. Check Status
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
npx tab-agent@latest status
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Confirm that all three pieces are healthy before you start driving the browser:
|
|
195
|
+
|
|
196
|
+
- Native Host: Installed
|
|
197
|
+
- Extension: Detected
|
|
198
|
+
- Relay Server: Running
|
|
199
|
+
|
|
200
|
+
### 5. Activate Tabs
|
|
186
201
|
|
|
187
202
|
Click the Tab Agent icon on any tab you want to control. Green = active.
|
|
188
203
|
|
|
@@ -288,10 +303,16 @@ npx tab-agent tabs
|
|
|
288
303
|
**Commands not working?**
|
|
289
304
|
- Make sure relay is running: `npx tab-agent@latest start`
|
|
290
305
|
- Click the extension icon — must show green "ON"
|
|
291
|
-
- Run `npx tab-agent status` to check configuration
|
|
306
|
+
- Run `npx tab-agent@latest status` to check configuration
|
|
307
|
+
|
|
308
|
+
**Popup says "Native host has exited"?**
|
|
309
|
+
- Make sure the relay is running: `npx tab-agent@latest start`
|
|
310
|
+
- Reload the extension in `chrome://extensions`
|
|
311
|
+
- Run `npx tab-agent@latest status` to confirm the native host path and relay status
|
|
312
|
+
- If the extension ID changed, run `npx tab-agent@latest setup` again so Chrome is paired to the current extension
|
|
292
313
|
|
|
293
314
|
**Fresh machine install still acting like an older release?**
|
|
294
|
-
- Use `npx tab-agent@latest setup` and `npx tab-agent@latest
|
|
315
|
+
- Use `npx tab-agent@latest setup`, `npx tab-agent@latest start`, and `npx tab-agent@latest status` to bypass stale cached `npx` installs
|
|
295
316
|
- Make sure the unpacked extension and the CLI/runtime come from the same release family
|
|
296
317
|
|
|
297
318
|
**No active tabs?**
|
package/cli/setup.js
CHANGED
|
@@ -73,22 +73,34 @@ function installNativeHost(extensionId) {
|
|
|
73
73
|
const packageDir = path.dirname(__dirname);
|
|
74
74
|
|
|
75
75
|
let manifestDir;
|
|
76
|
+
let hostDir;
|
|
76
77
|
let wrapperName;
|
|
77
78
|
|
|
78
79
|
if (platform === 'darwin') {
|
|
79
80
|
manifestDir = path.join(home, 'Library/Application Support/Google/Chrome/NativeMessagingHosts');
|
|
81
|
+
hostDir = path.join(home, 'Library/Application Support/TabAgent');
|
|
80
82
|
wrapperName = 'native-host-wrapper.sh';
|
|
81
83
|
} else if (platform === 'linux') {
|
|
82
84
|
manifestDir = path.join(home, '.config/google-chrome/NativeMessagingHosts');
|
|
85
|
+
hostDir = path.join(home, '.config/tab-agent');
|
|
83
86
|
wrapperName = 'native-host-wrapper.sh';
|
|
84
87
|
} else if (platform === 'win32') {
|
|
85
88
|
manifestDir = path.join(home, 'AppData/Local/Google/Chrome/User Data/NativeMessagingHosts');
|
|
89
|
+
hostDir = path.join(home, 'AppData/Local/TabAgent');
|
|
86
90
|
wrapperName = 'native-host-wrapper.cmd';
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
fs.mkdirSync(manifestDir, { recursive: true });
|
|
94
|
+
fs.mkdirSync(hostDir, { recursive: true });
|
|
95
|
+
|
|
96
|
+
const relayDir = path.join(packageDir, 'relay');
|
|
97
|
+
const wrapperPath = path.join(hostDir, wrapperName);
|
|
98
|
+
const hostScriptPath = path.join(hostDir, 'native-host.js');
|
|
99
|
+
|
|
100
|
+
fs.copyFileSync(path.join(relayDir, 'native-host.js'), hostScriptPath);
|
|
101
|
+
fs.copyFileSync(path.join(relayDir, wrapperName), wrapperPath);
|
|
102
|
+
installHostDependency(packageDir, hostDir);
|
|
90
103
|
|
|
91
|
-
const wrapperPath = path.join(packageDir, 'relay', wrapperName);
|
|
92
104
|
const manifest = {
|
|
93
105
|
name: 'com.tabagent.relay',
|
|
94
106
|
description: 'Tab Agent Native Messaging Host',
|
|
@@ -103,6 +115,7 @@ function installNativeHost(extensionId) {
|
|
|
103
115
|
// Make wrapper executable (Unix only)
|
|
104
116
|
if (platform !== 'win32') {
|
|
105
117
|
fs.chmodSync(wrapperPath, '755');
|
|
118
|
+
fs.chmodSync(hostScriptPath, '755');
|
|
106
119
|
}
|
|
107
120
|
|
|
108
121
|
// Windows: also set registry key
|
|
@@ -113,6 +126,34 @@ function installNativeHost(extensionId) {
|
|
|
113
126
|
}
|
|
114
127
|
}
|
|
115
128
|
|
|
129
|
+
function installHostDependency(packageDir, hostDir) {
|
|
130
|
+
const wsSourceDir = findWsSourceDir(packageDir);
|
|
131
|
+
const nodeModulesDir = path.join(hostDir, 'node_modules');
|
|
132
|
+
const wsTargetDir = path.join(nodeModulesDir, 'ws');
|
|
133
|
+
|
|
134
|
+
fs.mkdirSync(nodeModulesDir, { recursive: true });
|
|
135
|
+
fs.rmSync(wsTargetDir, { recursive: true, force: true });
|
|
136
|
+
fs.cpSync(wsSourceDir, wsTargetDir, { recursive: true });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function findWsSourceDir(packageDir) {
|
|
140
|
+
const candidates = [
|
|
141
|
+
path.join(packageDir, 'node_modules', 'ws'),
|
|
142
|
+
path.join(packageDir, 'relay', 'node_modules', 'ws')
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
for (const candidate of candidates) {
|
|
146
|
+
if (fs.existsSync(path.join(candidate, 'package.json'))) {
|
|
147
|
+
return candidate;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const resolved = require.resolve('ws/package.json', {
|
|
152
|
+
paths: [packageDir, path.join(packageDir, 'relay')]
|
|
153
|
+
});
|
|
154
|
+
return path.dirname(resolved);
|
|
155
|
+
}
|
|
156
|
+
|
|
116
157
|
function installSkills() {
|
|
117
158
|
const home = os.homedir();
|
|
118
159
|
const packageDir = path.dirname(__dirname);
|
package/extension/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -3,18 +3,19 @@ set -e
|
|
|
3
3
|
|
|
4
4
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
5
|
HOST_NAME="com.tabagent.relay"
|
|
6
|
-
HOST_DIR="$HOME/Library/Application Support/TabAgent"
|
|
7
|
-
WRAPPER_PATH="$HOST_DIR/native-host-wrapper.sh"
|
|
8
6
|
|
|
9
7
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
10
8
|
MANIFEST_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts"
|
|
9
|
+
HOST_DIR="$HOME/Library/Application Support/TabAgent"
|
|
11
10
|
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
12
11
|
MANIFEST_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"
|
|
12
|
+
HOST_DIR="$HOME/.config/tab-agent"
|
|
13
13
|
else
|
|
14
14
|
echo "Unsupported OS: $OSTYPE"
|
|
15
15
|
exit 1
|
|
16
16
|
fi
|
|
17
17
|
|
|
18
|
+
WRAPPER_PATH="$HOST_DIR/native-host-wrapper.sh"
|
|
18
19
|
mkdir -p "$MANIFEST_DIR"
|
|
19
20
|
|
|
20
21
|
if [ -z "$1" ]; then
|
|
@@ -26,8 +27,13 @@ fi
|
|
|
26
27
|
|
|
27
28
|
EXTENSION_ID="$1"
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
WS_SOURCE_DIR=""
|
|
31
|
+
if [ -d "$SCRIPT_DIR/../node_modules/ws" ]; then
|
|
32
|
+
WS_SOURCE_DIR="$SCRIPT_DIR/../node_modules/ws"
|
|
33
|
+
elif [ -d "$SCRIPT_DIR/node_modules/ws" ]; then
|
|
34
|
+
WS_SOURCE_DIR="$SCRIPT_DIR/node_modules/ws"
|
|
35
|
+
else
|
|
36
|
+
echo "Dependencies missing: run 'npm install' in the package root first."
|
|
31
37
|
exit 1
|
|
32
38
|
fi
|
|
33
39
|
|
|
@@ -35,7 +41,8 @@ mkdir -p "$HOST_DIR"
|
|
|
35
41
|
rm -rf "$HOST_DIR/node_modules"
|
|
36
42
|
cp "$SCRIPT_DIR/native-host.js" "$HOST_DIR/native-host.js"
|
|
37
43
|
cp "$SCRIPT_DIR/native-host-wrapper.sh" "$HOST_DIR/native-host-wrapper.sh"
|
|
38
|
-
|
|
44
|
+
mkdir -p "$HOST_DIR/node_modules"
|
|
45
|
+
cp -R "$WS_SOURCE_DIR" "$HOST_DIR/node_modules/ws"
|
|
39
46
|
|
|
40
47
|
cat > "$MANIFEST_DIR/$HOST_NAME.json" << EOF
|
|
41
48
|
{
|
package/relay/server.js
CHANGED
|
@@ -91,8 +91,8 @@ function failPendingRequests(reason, browser) {
|
|
|
91
91
|
|
|
92
92
|
wss.on('connection', (ws, req) => {
|
|
93
93
|
const clientType = req.headers['x-client-type'];
|
|
94
|
-
// 'extension'
|
|
95
|
-
const isExtension = clientType === 'extension' || clientType === 'safari';
|
|
94
|
+
// 'extension' is the legacy chrome client name, 'chrome' is the current one.
|
|
95
|
+
const isExtension = clientType === 'extension' || clientType === 'chrome' || clientType === 'safari';
|
|
96
96
|
const browser = clientType === 'safari' ? 'safari' : 'chrome';
|
|
97
97
|
|
|
98
98
|
if (isExtension) {
|