@hanzo/browser-extension 1.7.2
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/.github/workflows/docs.yml +44 -0
- package/.github/workflows/release.yml +55 -0
- package/LICENSE +21 -0
- package/README.md +126 -0
- package/dist/browser-extension/README.md +43 -0
- package/dist/browser-extension/ai-worker.js +30 -0
- package/dist/browser-extension/background-firefox.js +617 -0
- package/dist/browser-extension/background.js +2737 -0
- package/dist/browser-extension/browser-control.js +683 -0
- package/dist/browser-extension/cdp-bridge-server.js +444 -0
- package/dist/browser-extension/chrome/ai-worker.js +571 -0
- package/dist/browser-extension/chrome/background.js +2737 -0
- package/dist/browser-extension/chrome/callback.html +17 -0
- package/dist/browser-extension/chrome/content-script.js +1270 -0
- package/dist/browser-extension/chrome/icon128.png +0 -0
- package/dist/browser-extension/chrome/icon16.png +0 -0
- package/dist/browser-extension/chrome/icon32.png +0 -0
- package/dist/browser-extension/chrome/icon48.png +0 -0
- package/dist/browser-extension/chrome/manifest.json +57 -0
- package/dist/browser-extension/chrome/popup.css +519 -0
- package/dist/browser-extension/chrome/popup.html +242 -0
- package/dist/browser-extension/chrome/popup.js +267 -0
- package/dist/browser-extension/chrome/sidebar.css +1176 -0
- package/dist/browser-extension/chrome/sidebar.html +280 -0
- package/dist/browser-extension/chrome/sidebar.js +778 -0
- package/dist/browser-extension/cli.js +233 -0
- package/dist/browser-extension/content-script.js +1270 -0
- package/dist/browser-extension/firefox/ai-worker.js +571 -0
- package/dist/browser-extension/firefox/background.js +617 -0
- package/dist/browser-extension/firefox/callback.html +17 -0
- package/dist/browser-extension/firefox/content-script.js +1270 -0
- package/dist/browser-extension/firefox/icon128.png +0 -0
- package/dist/browser-extension/firefox/icon16.png +0 -0
- package/dist/browser-extension/firefox/icon32.png +0 -0
- package/dist/browser-extension/firefox/icon48.png +0 -0
- package/dist/browser-extension/firefox/manifest.json +66 -0
- package/dist/browser-extension/firefox/popup.css +519 -0
- package/dist/browser-extension/firefox/popup.html +242 -0
- package/dist/browser-extension/firefox/popup.js +267 -0
- package/dist/browser-extension/firefox/sidebar.css +1176 -0
- package/dist/browser-extension/firefox/sidebar.html +280 -0
- package/dist/browser-extension/firefox/sidebar.js +778 -0
- package/dist/browser-extension/hanzo-browser-extension-firefox-1.1.0.zip +0 -0
- package/dist/browser-extension/icon128.png +0 -0
- package/dist/browser-extension/icon16.png +0 -0
- package/dist/browser-extension/icon32.png +0 -0
- package/dist/browser-extension/icon48.png +0 -0
- package/dist/browser-extension/manifest.json +57 -0
- package/dist/browser-extension/package.json +41 -0
- package/dist/browser-extension/popup.css +468 -0
- package/dist/browser-extension/popup.html +191 -0
- package/dist/browser-extension/popup.js +267 -0
- package/dist/browser-extension/safari/Info.plist +21 -0
- package/dist/browser-extension/safari/ai-worker.js +571 -0
- package/dist/browser-extension/safari/background.js +2737 -0
- package/dist/browser-extension/safari/callback.html +17 -0
- package/dist/browser-extension/safari/content-script.js +1270 -0
- package/dist/browser-extension/safari/icon128.png +0 -0
- package/dist/browser-extension/safari/icon16.png +0 -0
- package/dist/browser-extension/safari/icon32.png +0 -0
- package/dist/browser-extension/safari/icon48.png +0 -0
- package/dist/browser-extension/safari/popup.css +519 -0
- package/dist/browser-extension/safari/popup.html +242 -0
- package/dist/browser-extension/safari/popup.js +267 -0
- package/dist/browser-extension/safari/sidebar.css +1176 -0
- package/dist/browser-extension/safari/sidebar.html +280 -0
- package/dist/browser-extension/safari/sidebar.js +778 -0
- package/dist/browser-extension/sidebar.css +718 -0
- package/dist/browser-extension/sidebar.html +184 -0
- package/dist/browser-extension/sidebar.js +778 -0
- package/dist/browser-extension/webgpu-ai.js +495 -0
- package/dist/cdp-bridge-server.js +411 -0
- package/dist/safari/Hanzo AI/Hanzo AI.xcodeproj/project.pbxproj +1047 -0
- package/dist/safari/Hanzo AI/Hanzo AI.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/Contents.json +98 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-128@1x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-128@2x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-16@1x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-16@2x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-256@1x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-256@2x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-32@1x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-32@2x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-512@1x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-512@2x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/AppIcon.appiconset/universal-icon-1024@1x.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/Contents.json +6 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/LargeIcon.imageset/Contents.json +21 -0
- package/dist/safari/Hanzo AI/Shared (App)/Assets.xcassets/LargeIcon.imageset/icon128.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Resources/Base.lproj/Main.html +20 -0
- package/dist/safari/Hanzo AI/Shared (App)/Resources/Icon.png +0 -0
- package/dist/safari/Hanzo AI/Shared (App)/Resources/Script.js +24 -0
- package/dist/safari/Hanzo AI/Shared (App)/Resources/Style.css +61 -0
- package/dist/safari/Hanzo AI/Shared (App)/ViewController.swift +81 -0
- package/dist/safari/Hanzo AI/Shared (Extension)/SafariWebExtensionHandler.swift +42 -0
- package/dist/safari/Hanzo AI/iOS (App)/AppDelegate.swift +24 -0
- package/dist/safari/Hanzo AI/iOS (App)/Base.lproj/LaunchScreen.storyboard +36 -0
- package/dist/safari/Hanzo AI/iOS (App)/Base.lproj/Main.storyboard +38 -0
- package/dist/safari/Hanzo AI/iOS (App)/Info.plist +27 -0
- package/dist/safari/Hanzo AI/iOS (App)/SceneDelegate.swift +18 -0
- package/dist/safari/Hanzo AI/iOS (Extension)/Info.plist +13 -0
- package/dist/safari/Hanzo AI/macOS (App)/AppDelegate.swift +21 -0
- package/dist/safari/Hanzo AI/macOS (App)/Base.lproj/Main.storyboard +124 -0
- package/dist/safari/Hanzo AI/macOS (App)/Info.plist +8 -0
- package/dist/safari/Hanzo AI/macOS (Extension)/Info.plist +13 -0
- package/docs/_config.yml +13 -0
- package/docs/_layouts/default.html +435 -0
- package/docs/index.md +54 -0
- package/install-extension.sh +75 -0
- package/manifest.json +29 -0
- package/package.json +32 -0
- package/src/ai-worker.js +571 -0
- package/src/callback.html +17 -0
- package/src/chat-widget.tsx +93 -0
- package/src/icon128.png +0 -0
- package/src/icon16.png +0 -0
- package/src/icon32.png +0 -0
- package/src/icon48.png +0 -0
- package/src/manifest-firefox.json +66 -0
- package/src/manifest.json +57 -0
- package/src/package.json +41 -0
- package/src/popup.css +519 -0
- package/src/popup.html +242 -0
- package/src/popup.js +192 -0
- package/src/sidebar.css +1176 -0
- package/src/sidebar.html +280 -0
- package/src/sidebar.js +884 -0
- package/src/webgpu.d.ts +131 -0
- package/test/claude-integration.test.ts +251 -0
- package/test/server-frameworks-edge-cases.test.ts +145 -0
- package/test/server-frameworks.test.ts +395 -0
- package/test-cdp-connection.js +140 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/cli.ts
|
|
27
|
+
var import_commander = require("commander");
|
|
28
|
+
|
|
29
|
+
// src/browser-extension-server.ts
|
|
30
|
+
var import_ws = require("ws");
|
|
31
|
+
var import_events = require("events");
|
|
32
|
+
var path = __toESM(require("path"));
|
|
33
|
+
var fs = __toESM(require("fs"));
|
|
34
|
+
var BrowserExtensionServer = class extends import_events.EventEmitter {
|
|
35
|
+
constructor(port = 3001, projectRoot = process.cwd()) {
|
|
36
|
+
super();
|
|
37
|
+
this.projectRoot = projectRoot;
|
|
38
|
+
this.wss = new import_ws.WebSocketServer({
|
|
39
|
+
port,
|
|
40
|
+
path: "/browser-extension"
|
|
41
|
+
});
|
|
42
|
+
this.setupWebSocket();
|
|
43
|
+
console.log(`[Hanzo] Browser extension server listening on ws://localhost:${port}/browser-extension`);
|
|
44
|
+
}
|
|
45
|
+
setupWebSocket() {
|
|
46
|
+
this.wss.on("connection", (ws) => {
|
|
47
|
+
console.log("[Hanzo] Browser extension connected");
|
|
48
|
+
ws.on("message", async (data) => {
|
|
49
|
+
try {
|
|
50
|
+
const payload = JSON.parse(data.toString());
|
|
51
|
+
if (payload.event === "elementSelected") {
|
|
52
|
+
const fileInfo = await this.resolveFileLocation(payload);
|
|
53
|
+
if (fileInfo) {
|
|
54
|
+
this.emit("elementSelected", {
|
|
55
|
+
file: fileInfo.file,
|
|
56
|
+
line: fileInfo.line,
|
|
57
|
+
column: fileInfo.column,
|
|
58
|
+
framework: payload.framework,
|
|
59
|
+
domPath: payload.domPath
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error("[Hanzo] Error processing browser message:", error);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
ws.on("close", () => {
|
|
68
|
+
console.log("[Hanzo] Browser extension disconnected");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async resolveFileLocation(payload) {
|
|
73
|
+
if (payload.source) {
|
|
74
|
+
const resolvedPath = this.resolveSourcePath(payload.source.file);
|
|
75
|
+
return {
|
|
76
|
+
file: resolvedPath || payload.source.file,
|
|
77
|
+
line: payload.source.line,
|
|
78
|
+
column: payload.source.column
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
if (payload.fallbackId) {
|
|
82
|
+
const location = await this.lookupByHanzoId(payload.fallbackId);
|
|
83
|
+
if (location) return location;
|
|
84
|
+
}
|
|
85
|
+
console.warn("[Hanzo] Could not resolve file location for element");
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
resolveSourcePath(sourcePath) {
|
|
89
|
+
if (sourcePath.startsWith("webpack://")) {
|
|
90
|
+
sourcePath = sourcePath.replace(/^webpack:\/\/[^\/]+\//, "");
|
|
91
|
+
}
|
|
92
|
+
const candidates = [
|
|
93
|
+
path.join(this.projectRoot, sourcePath),
|
|
94
|
+
path.join(this.projectRoot, "src", sourcePath),
|
|
95
|
+
path.join(this.projectRoot, sourcePath.replace(/^\.\//, "")),
|
|
96
|
+
sourcePath
|
|
97
|
+
// absolute path
|
|
98
|
+
];
|
|
99
|
+
for (const candidate of candidates) {
|
|
100
|
+
if (fs.existsSync(candidate)) {
|
|
101
|
+
return candidate;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
async lookupByHanzoId(hanzoId) {
|
|
107
|
+
try {
|
|
108
|
+
const mapFile = path.join(this.projectRoot, ".hanzo", "id-map.json");
|
|
109
|
+
if (fs.existsSync(mapFile)) {
|
|
110
|
+
const idMap = JSON.parse(fs.readFileSync(mapFile, "utf-8"));
|
|
111
|
+
return idMap[hanzoId] || null;
|
|
112
|
+
}
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error("[Hanzo] Error reading ID map:", error);
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
close() {
|
|
119
|
+
this.wss.close();
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// src/cli.ts
|
|
124
|
+
var import_chalk = __toESM(require("chalk"));
|
|
125
|
+
var path2 = __toESM(require("path"));
|
|
126
|
+
var import_child_process = require("child_process");
|
|
127
|
+
var program = new import_commander.Command();
|
|
128
|
+
program.name("hanzo-browser-server").description("Start the Hanzo browser extension server for click-to-code navigation").version("1.0.0");
|
|
129
|
+
program.command("start").description("Start the browser extension WebSocket server").option("-p, --port <port>", "Port to run the server on", "3001").option("-r, --root <path>", "Project root directory", process.cwd()).option("--install-extension", "Build and show instructions for installing the browser extension").action(async (options) => {
|
|
130
|
+
const port = parseInt(options.port);
|
|
131
|
+
const projectRoot = path2.resolve(options.root);
|
|
132
|
+
console.log(import_chalk.default.blue("\u{1F680} Starting Hanzo Browser Extension Server"));
|
|
133
|
+
console.log(import_chalk.default.gray(` Port: ${port}`));
|
|
134
|
+
console.log(import_chalk.default.gray(` Project root: ${projectRoot}`));
|
|
135
|
+
const server = new BrowserExtensionServer(port, projectRoot);
|
|
136
|
+
server.on("elementSelected", (data) => {
|
|
137
|
+
console.log(import_chalk.default.green("\u2713 Element selected:"));
|
|
138
|
+
console.log(import_chalk.default.gray(` File: ${data.file}`));
|
|
139
|
+
console.log(import_chalk.default.gray(` Line: ${data.line}`));
|
|
140
|
+
if (data.column) console.log(import_chalk.default.gray(` Column: ${data.column}`));
|
|
141
|
+
console.log(import_chalk.default.gray(` Framework: ${data.framework || "unknown"}`));
|
|
142
|
+
});
|
|
143
|
+
console.log(import_chalk.default.green(`\u2713 Server running at ws://localhost:${port}/browser-extension`));
|
|
144
|
+
console.log(import_chalk.default.yellow("\n\u{1F4DD} Instructions:"));
|
|
145
|
+
console.log("1. Install the browser extension (run with --install-extension flag)");
|
|
146
|
+
console.log("2. Alt+Click any element in your browser to navigate to its source code");
|
|
147
|
+
console.log("3. The server will output the file location for your editor/MCP to handle\n");
|
|
148
|
+
if (options.installExtension) {
|
|
149
|
+
await installExtension();
|
|
150
|
+
}
|
|
151
|
+
process.on("SIGINT", () => {
|
|
152
|
+
console.log(import_chalk.default.red("\n\u23F9 Shutting down server..."));
|
|
153
|
+
server.close();
|
|
154
|
+
process.exit(0);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
program.command("install-extension").description("Build and install the browser extension").action(async () => {
|
|
158
|
+
await installExtension();
|
|
159
|
+
});
|
|
160
|
+
program.command("test").description("Run integration tests with mock browser events").action(async () => {
|
|
161
|
+
console.log(import_chalk.default.blue("\u{1F9EA} Running integration tests..."));
|
|
162
|
+
const server = new BrowserExtensionServer(3001);
|
|
163
|
+
const testEvents = [
|
|
164
|
+
{
|
|
165
|
+
event: "elementSelected",
|
|
166
|
+
framework: "react",
|
|
167
|
+
domPath: "div#root > div.App > header > h1",
|
|
168
|
+
source: {
|
|
169
|
+
file: "src/components/Header.tsx",
|
|
170
|
+
line: 15,
|
|
171
|
+
column: 8
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
event: "elementSelected",
|
|
176
|
+
framework: "vue",
|
|
177
|
+
domPath: "div#app > main > button.primary",
|
|
178
|
+
source: {
|
|
179
|
+
file: "src/components/Button.vue",
|
|
180
|
+
line: 23
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
event: "elementSelected",
|
|
185
|
+
framework: null,
|
|
186
|
+
domPath: "body > div > p",
|
|
187
|
+
fallbackId: "hanzo-id-12345"
|
|
188
|
+
}
|
|
189
|
+
];
|
|
190
|
+
console.log(import_chalk.default.gray("Sending test events...\n"));
|
|
191
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
192
|
+
const WebSocket = require("ws");
|
|
193
|
+
const ws = new WebSocket("ws://localhost:3001/browser-extension");
|
|
194
|
+
ws.on("open", () => {
|
|
195
|
+
testEvents.forEach((event, index) => {
|
|
196
|
+
setTimeout(() => {
|
|
197
|
+
console.log(import_chalk.default.blue(`\u2192 Sending test event ${index + 1}:`));
|
|
198
|
+
console.log(import_chalk.default.gray(JSON.stringify(event, null, 2)));
|
|
199
|
+
ws.send(JSON.stringify(event));
|
|
200
|
+
}, index * 1e3);
|
|
201
|
+
});
|
|
202
|
+
setTimeout(() => {
|
|
203
|
+
ws.close();
|
|
204
|
+
server.close();
|
|
205
|
+
console.log(import_chalk.default.green("\n\u2713 Integration tests completed"));
|
|
206
|
+
process.exit(0);
|
|
207
|
+
}, testEvents.length * 1e3 + 500);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
async function installExtension() {
|
|
211
|
+
console.log(import_chalk.default.blue("\u{1F4E6} Building browser extension..."));
|
|
212
|
+
const buildScript = path2.join(__dirname, "..", "browser-extension", "build.js");
|
|
213
|
+
return new Promise((resolve2, reject) => {
|
|
214
|
+
const build = (0, import_child_process.spawn)("node", [buildScript], {
|
|
215
|
+
stdio: "inherit"
|
|
216
|
+
});
|
|
217
|
+
build.on("close", (code) => {
|
|
218
|
+
if (code === 0) {
|
|
219
|
+
console.log(import_chalk.default.green("\n\u2713 Extension built successfully!"));
|
|
220
|
+
console.log(import_chalk.default.yellow("\n\u{1F4DD} Installation instructions:"));
|
|
221
|
+
console.log("1. Open Chrome and navigate to chrome://extensions/");
|
|
222
|
+
console.log('2. Enable "Developer mode" (toggle in top right)');
|
|
223
|
+
console.log('3. Click "Load unpacked"');
|
|
224
|
+
console.log(`4. Select the folder: ${path2.join(__dirname, "..", "..", "dist", "browser-extension")}`);
|
|
225
|
+
console.log("5. The extension is now installed! Alt+Click elements to navigate to source.\n");
|
|
226
|
+
resolve2();
|
|
227
|
+
} else {
|
|
228
|
+
reject(new Error(`Build failed with code ${code}`));
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
program.parse();
|