# Harmness Browser — JetBrains 插件 在 JetBrains IDE(IntelliJ IDEA / PyCharm / PhpStorm / WebStorm 等)的侧边栏内嵌一个 **可配置地址的浏览器窗口**。默认搭配本地 [Harness](https://harness.io/) 这类 AI 助手 Web 服务使用,让你不用切出 IDE 就能在代码区与 AI 界面之间来回操作。 本仓库已初始化: - **JetBrains 插件本体**(Kotlin + Gradle + IntelliJ Platform SDK,`src/`) - **TypeScript Web 前端脚手架**(Vite + React + TS,`web/`,用于构建/调试将被嵌入的页面) - **JS ↔ 插件双向桥** 示例(页面上直接调用 `window.harmnessBridge`) ## 项目结构 ``` . ├── build.gradle.kts # Gradle 构建(IntelliJ Platform plugin build) ├── settings.gradle.kts ├── gradle.properties ├── scripts/ │ └── setup-toolchain.sh # 一键下载 JDK17 + Gradle(无 root 环境) ├── src/main/ │ ├── kotlin/com/harmness/toolwindow/ │ │ ├── HarmnessBrowserPanel.kt # JCEF 内嵌浏览器 + JS↔Java 桥 │ │ ├── HarmnessToolWindowFactory.kt # 侧边栏工具窗口 │ │ ├── HarmnessSettingsConfigurable.kt # 设置页入口 │ │ ├── HarmnessBrowserConfigurablePanel.kt # 设置 UI(起始地址) │ │ ├── SettingsState.kt # 持久化设置存储 │ │ └── WindowFocusService.kt # 工具窗口焦点广播(预留) │ └── resources/ │ ├── META-INF/plugin.xml # 插件声明(扩展点注册) │ └── icons/harmness.svg # 工具窗口图标 └── web/ # (可选)被嵌入页面的前端脚手架 ├── package.json ├── vite.config.ts └── src/{main.tsx, App.tsx, bridge.ts, ...} ``` ## 本地构建 ### 1. 准备工具链(本机没有 JDK/Gradle 时) ```bash ./scripts/setup-toolchain.sh # 会下载 Temurin JDK 17 与 Gradle 8.11.1 到 .tools/ ``` 若本机已装 JDK 17+ 与 Gradle,可跳过,直接用系统的。 ### 2. 构建插件 zip ```bash export JAVA_HOME=/data/project/Plugin/harmness/.tools/jdk-17.0.12+7 # 若用脚本版 ./.tools/gradle-8.11.1/bin/gradle buildPlugin -x test ``` 产物:`build/distributions/harmness-toolwindow-0.1.0.zip` > 首次构建会下载 IntelliJ Platform SDK(约 1–2GB),请保持网络畅通。 ### 3. 在 IDE 里运行/调试 在 IDEA(Ultimate 或 Community 均可)中: 1. `File → Open` 打开本仓库根目录(Gradle 项目会自动识别)。 2. `Gradle → Tasks → intellij → runIde`,或运行主类 `com.intellij.idea.Main`(由 Gradle 任务 `runIde` 提供)。 3. 等 IDE 启动后,右侧边栏会出现 **Harmness Browser** 工具窗口。 ### 4. 前端(可选) ```bash cd web npm install npm run dev # 起一个位于 http://127.0.0.1:8888 的页面 ``` 然后在插件设置里把「起始地址」填成 `http://127.0.0.1:8888`,即可在 IDE 侧边栏里看到该页面。 ## 功能与使用 | 功能 | 说明 | | --- | --- | | 侧边栏浏览器 | 打开 IDE 后右侧出现可停靠/悬浮的工具窗口 | | 配置起始地址 | `Settings → Tools → Harmness Browser`(或点工具栏 ⚙) | | 地址栏 | 手动输入任意地址回车跳转 | | 前进/后退/刷新 | 工具栏 ← → ⟳ | | 外部浏览器打开 | 工具栏 ⧉ 把当前地址丢给系统浏览器 | | JS↔Java 桥 | 页面加载后注入 `window.harmnessBridge(payload)`,网页可调用插件能力(原型:`ping` / `getUrl` / `openExternal:*`) | ### JS↔Java 桥(给 Harness 前端用) `web/src/bridge.ts` 提供类型化封装: ```ts import { callPlugin, openInExternalBrowser, initBridge } from './bridge' initBridge(( ) => console.log('bridge ready')) const pong = await callPlugin('ping') // -> "pong" openInExternalBrowser('https://example.com') // 用系统浏览器打开 ``` 如果想要 Harness(或其前端)在收到网页请求时把代码插入编辑器、打开文件等, 需要在 `HarmnessBrowserPanel.setupBridge()` 的 handler 里扩展桥协议, 并通过 IntelliJ Platform API(`FileDocumentManager`、`EditorFactory`、`CodeInsightUtil` 等) 实现。IntelliJ 官方插件 SDK 不提供对 JCEF 页面 DOM 的直接访问,双向通信一律走 `JBCefJSQuery`(本插件已封装)。 ## 发布到 JetBrains Marketplace ### 1. 注册 JetBrains 账号 访问 注册/登录(可用 Google / GitHub 账号)。 ### 2. 申请插件仓库(只有一次) 1. 打开 并登录。 2. 右上角头像 → **Developer Console**(或直接 )。 3. 点击 **Create New Plugin**(第一次需要填组织/开发者信息 + 同意 [Plugin Hosting Terms](https://plugins.jetbrains.com/docs/marketplace/plugin-hosting-terms.html))。 4. 创建后会得到一个 **Plugin ID**,把 `plugin.xml` 里的 ``(当前为 `com.harmness.toolwindow`)改成该 ID(建议保持相同,便于后续关联)。 ### 3. 构建并本地验证产物 ```bash ./.tools/gradle-8.11.1/bin/gradle buildPlugin -x test ``` 生成的 `build/distributions/*.zip` 即发布物。 可选(推荐):在 IDE 里用 `Settings → Plugins → ⚙ → Install Plugin from Disk…` 选这个 zip 验证一次,再上传。 ### 4. 上传发布 1. 进入 ,选你的插件。 2. **Upload Plugin** 上传 zip。 3. 填写版本信息: - **Version**:与 `build.gradle.kts` 的 `version` 一致(如 `0.1.0`) - **Since / Until build**:对应 `plugin.xml` 的 `242 / 243.*` - **Changelog**:版本变更说明 - **Compatibility**:勾选目标 IDE(IDEA Community/Ultimate 等) 4. 提交后,若勾选 **Publish**(或之后手动点 Publish),插件会进入审核,一般几分钟到数小时; 审核通过后即可在 Marketplace 搜索到。 > 之后每次发新版,重复第 3–4 步即可。也可用 CI(GitHub Actions + JetBrains > [publish plugin task](https://plugins.jetbrains.com/docs/intellij/publishing-plugin.html), > `gradle publishPlugin`)自动化。 ### 5. 其他人安装使用 - **IDE 内**:`Settings → Plugins → Marketplace`,搜索 `Harmness Browser` 安装。 - **手动**:`Settings → Plugins → ⚙ → Install Plugin from Disk…` 选 zip。 - **下载**:(你的插件主页)。 安装后在右侧栏点开 **Harmness Browser**,到 `Settings → Tools → Harmness Browser` 把地址配置成你的 Harness 实例即可。 ## 与 Harness 的适配注意点(重要) 1. **嵌入限制**:目标 Web 应用(Harness)必须允许被嵌入渲染: - 不能返回 `X-Frame-Options: DENY/SAMEORIGIN`, - CSP 里不能有 `frame-ancestors 'none'`。 若 Harness 有这些限制,需要在其反向代理/HTTP 头里放行,或使用 Harness 专门的无 frame 限制入口。 2. **登录态**:cookie 与本地存储默认按 JCEF 的浏览器实例隔离,登录 Harness 后一般会保留 (IDE 重启后缓存仍有效,除非换 IDE/机器)。 3. **性能与授权**:JCEF 每次都会初始化一个 Chromium 实例,多个 IDE 窗口会占用较多内存; 老机器上建议只保留最需要的 IDE 窗口。 4. **桥接协议**:要把「网页请求 → 编辑代码/打开文件」打通,需按前面「JS↔Java 桥」一节扩展插件。 ## 关于「把 Harness 塞进侧边栏」的可行性评估(给决策用) 你的想法是合理的,也是目前社区常见的做法(例如在 IDE 里嵌入 ChatGPT / Copilot 网页版)。 优点: - 不用在两个窗口之间来回切换,交互摩擦小; - 利用 IDE 自带的 JCEF,不需要额外浏览器进程; - 可以做双向桥,网页 → 编辑器有原生 IPC 通路。 局限(需要接受或规避): - JCEF = 内置 Chromium,内存占用明显(每个 IDE 窗口一份); - 官方 SDK 不给页面 DOM 权限,需求超过「纯网页浏览 + 简单桥」就要自己维护桥协议 (本插件已铺好骨架); - 第三方网页的嵌入限制(X-Frame-Options / CSP)可能直接挡掉,需要 Harness 侧配合。 结论:**方向可行**。建议先把 `web/` 里替换成 Harness 实际前端,跑通「配置地址 → 侧边栏显示 → 桥接 ping」这条链路,再决定扩展哪些 IDE 能力。 ## License / 后续 - 当前版本为原型骨架(0.1.0),默认 `sinceBuild=242, untilBuild=243.*`,只覆盖 2024.2–2024.3。 - 后续可加:多地址书签、地址访问白名单(安全)、按 IDE 主题切换深/浅色、自动重连等。