opencode-idea 0.0.8 → 0.0.10

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 DELETED
@@ -1,80 +0,0 @@
1
- # Changelog
2
-
3
- ## 0.0.8
4
-
5
- - **撤销 0.0.7 的「skill 注册尽力而为」**。skill 是本插件的核心功能,不是可选知识:定义被 schema 拒绝就说明我们写错了,必须**立即失败**。原来那个 catch 会把「功能残缺」伪装成「运行正常」—— 正是 0.0.6 丢掉 `/open-in-idea` 却没人察觉的那种失败模式。现在恢复为直接注册 (无 try/catch)。
6
- - **补测试**:断言打包后的 skill 文档 (`src/ide-run-config-skill.md`) 真实存在,这样 `.md` 漏进 `package.json` 的 `files` 会在测试阶段暴露,而不是在 `setup` 时才炸。
7
- - **文档**:README 限制节写明 skill 字段名以 schema 为准 (`Skill.Info` 要 `path`,官方文档里的 `location` 不存在),用错会禁用整个插件。
8
-
9
- ## 0.0.7
10
-
11
- - **修复:0.0.6 因 skill schema 校验失败导致整个插件被禁用**。`idea-run-config` skill 的定义用了 `location` 字段,而 `Skill.Info` 要求的是 `path` (AbsolutePath);`ctx.skill.transform` 因此抛 `SchemaError(Missing key at ["path"])`。OpenCode 的策略是**任何 transform 失败都会禁用整个插件**,所以 0.0.6 里 `/open-in-idea` 命令和 IDE MCP 注册都没能生效 (日志:`disabled plugin after transform failure plugin.id=opencode-idea state=skill`)。现在改用 `path`,并在测试里钉死字段集合 (`content` / `description` / `id` / `name` / `path`)。
12
- - **skill 注册改为尽力而为**:`runConfigSkill()` 或 `ctx.skill.transform` 抛错时只放弃 skill,不再中断 `setup` —— 可选知识不该拖垮命令与 MCP 接线。
13
- - **新增回归测试**:skill transform 被拒时 `/open-in-idea` 仍然注册。
14
-
15
- ## 0.0.6
16
-
17
- - **修复:工具报错不再注销 IDE MCP**。旧实现在 `tool.execute.after` 里把**任何** `idea_*` 报错都当成「端点已死」并注销整个注册 —— 业务错误 (例如路径不存在返回 `File not found`) 和一次传输抖动都会触发;注销后紧跟的 `ctx.mcp.reload()` 还会掐断同一批正在执行的其他调用。现在插件**不注册**该钩子:连接状态以 OpenCode 自己维护的工具快照为准 (`context` 钩子收到的 `event.tools` 里有没有 `idea_*`),只有 `/open-in-idea` 会 (重新) 连接。
18
- - **隐藏 31 个用不到的 IDEA 工具** (`HIDDEN_IDEA_TOOLS`):VCS、Router 派发工具、Debugger (全部 `idea_xdebug_*`)、Dev Kit MCP、Inspection KTS MCP、Python Environment MCP、数据库建/改数据源、终端 `execute_terminal_command`。模型可见的 `idea_*` 从 64 降到 33。
19
- - **引导词重写**:边界从「所有操作」收窄为「**代码与文件操作**」(未暴露的领域自然走原生,不再列例外);新增数据库段 (走 IDEA Database 工具 + 用户配数据源 + 不索取凭据);删除终端命令段 (该工具已隐藏)。
20
- - **新增 `idea-run-config` skill**:教模型在 `.run/*.run.xml` 里建/改/删 run configuration,并用 `get_run_configurations` 校验、`execute_run_configuration` 实跑 (IDE MCP 没有增删改能力)。仅 JetBrains 项目注册,与 `/open-in-idea` 无关。
21
- - **`/open-in-idea` 改为问注册表要连接状态**:活着只刷新,死了才换注册 (OpenCode 对未变更的 MCP 配置不会重连)。
22
- - **默认 MCP 端口收敛**:`DEFAULT_PORTS` 从 `[64342, 6420, 6421, 63342]` 改为 `[64342]`。
23
- - **修复发布脚本**:`assertCleanGit()` 原先排在版本递增之后,导致正式发布必然中途失败并留下已被改动的版本号;现在移到递增之前。
24
-
25
- ## 0.0.5
26
-
27
- - **冷启动等待 MCP 端点**:`/open-in-idea` 在 `open -a` 之后按 `mcpStartTimeoutMs`(默认 60s)轮询,直到 IDEA 自带的 MCP server 开始监听。冷启动时一次命令即可连上,不再像之前那样探测一次失败就报「未检测到 MCP 服务」。
28
- - **工具就绪判定**:连接后轮询 `ctx.tool.list()`,确认 `idea_read_file` / `idea_apply_patch` 已注册。未就绪时状态为 `tools-loading` 并提示稍后重试,不再在原生工具表尚未就绪时谎称「已连接」。
29
- - **重复执行刷新工具列表**:再次执行 `/open-in-idea` 会重建 MCP server 并依次 `ctx.mcp.reload()` + `ctx.tool.reload()`,让已经捕获过工具快照的会话立即看到最新工具,而不是停留在旧快照。
30
- - **IDE 掉线自动注销**:每次请求前复检端点,IDEA 关闭或某次 `idea_*` 工具调用失败时,立即移除 `idea_*` 工具并恢复原生工具,避免后续请求继续调用已失效的 IDE 工具;只有再次执行 `/open-in-idea` 才能重新注册。
31
- - **清理**:移除调试日志;删除过时的 `scripts/publish.sh`(旧包名 + bypass token 流程,已由 `scripts/release.mjs` 取代);`package.json` 的 `files` 移除早已删除的 `src/idea-tool-descriptions.js`。
32
-
33
- ## 0.0.4
34
-
35
- - **`/open-in-idea` 刷新工具列表**:在 `ctx.mcp.reload()` 之后显式调用 `ctx.tool.reload()`。之前只有 MCP 层重建目录,已经捕获过工具快照的会话仍然看不到新的 `idea_*` 原生工具;现在下一次模型请求即可用,无需重开会话。
36
-
37
- ## 0.0.3
38
-
39
- - **直接暴露 IDEA MCP 工具**:注册 MCP 服务器时设置 `codemode: false`,让 `idea_*` 工具直接出现在原生工具表(而非 Code Mode 的 `tools.idea.*`)。模型可以直接调用并看到完整参数 schema,不再需要先探索、也不会猜错参数名。
40
- - **引导补充**:明确要求「直接调用工具,不要用 `execute` 包裹」。
41
-
42
- ## 0.0.2
43
-
44
- - **路由引导重写**:system prompt 明确写出项目绝对路径,并要求路径内的检索 / 读文件 / 目录浏览 / 改文件 / 新建文件 / 校验都使用 `idea_*` 工具,逐条点名禁止对应的原生工具(`grep` / `glob` / `read` / `edit` / `write` / `ls` / `find`)。
45
- - **不再修改任何工具描述**:移除对 IDEA MCP 工具描述的前缀改写(`src/idea-tool-descriptions.js` 已删除),插件不再调用 `ctx.tool.transform`;IDEA 工具与原生工具的描述均保持原样。
46
- - **引导文案精简**:删除解释性内容和宽泛的「例外」条款,只保留要求与项目内 / 外边界。
47
- - **移除无用文件**:删除 `skills/`(setup skill)与 `UPGRADING.md`。
48
- - **安装文档更新**:README 的安装与配置示例改为 V2 的 `plugins` 对象写法。
49
-
50
- ## 0.0.1
51
-
52
- 首个版本(包名 `opencode-idea`,从 `opencode-jetbrains-mcp` 重命名而来)。
53
-
54
- **接入 IDE MCP**
55
-
56
- - **`/open-in-idea` 命令**:用 IntelliJ IDEA 打开当前项目(复用已运行实例),并即时加载 IDE MCP。命令可重入,重复触发共享同一次启动,不会重复 spawn。
57
- - **IDE 启动器** (`src/ide-launcher.js`):`open -a "IntelliJ IDEA" <dir>` 复用已运行实例(Toolbox CLI 的 `open -na` 会新开实例,故不使用)。
58
- - **启动保护 (launch guard)**:每目录记录 `lastSpawnAt` / `attempts`;冷却 `launchCooldownMs`(默认 120s)、上限 `launchMaxAttempts`(默认 5)。
59
- - **MCP 未开启时 fast-fail**:`/open-in-idea` 先短探测,未检测到 MCP 就立即返回并提示在 IDEA 中开启 MCP 服务和 Brave Mode,不轮询、不等待超时;用户开启后重试命令即可。
60
- - **Streamable HTTP 端点**:注册给 OpenCode 的 URL 使用 `/stream`(IntelliJ 2026.2+)。OpenCode V2 的远程 MCP 客户端只支持 Streamable HTTP,旧版 `/sse`(POST 返回 405)不可用;插件探测同样走 `/stream`。
61
- - **结果通知**(`feedback: "message"`,默认):命令结束后发一条标注清楚的通知,用户看到干净气泡(`metadata.displayText`),模型只看到"这是通知,请只回复『收到』";`false` 静默。
62
-
63
- **IDE 工具优先**
64
-
65
- - **系统提示直接调用引导** (`src/ide-guidance.js`):IDE 可用时,通过 `ctx.session.hook("context", …)` 往每次请求的 system 追加「项目内操作优先使用 IDEA MCP」引导 + 能力映射表,要求模型直接调用 `idea_*` 工具。`injectGuidance: false` 可关闭。
66
- - **IDEA 工具描述增强** (`src/idea-tool-descriptions.js`):通过 `ctx.tool.transform` 只更新 `idea_*` / `idea.*` 工具的 description,强调直接调用、按当前 schema 传参。原生 `edit` / `write` / `patch` / `shell` 的定义、描述和可用性保持不变。
67
- - **失败恢复指引**:IDEA MCP 工具缺失、连接被拒或超时时,提示用户执行 `/open-in-idea`,不反复探测或长时间等待。
68
-
69
- **IDE 环境注入**
70
-
71
- - **环境变量只来自 IDE 集成终端**:用 `execute_terminal_command printenv` 读取 IDE 实际运行环境(版本化 Node、goenv Go、SDKMAN Java、Maven 等),通过 V2 `shell` 的 `create.before` 钩子注入每个 shell;只补 SDK 变量并前置 PATH,不覆盖原有 PATH。需要 IDE MCP 可达 + Brave Mode。
72
- - **抽取值** (`src/ide-env.js` 的 `SDK_ENV_KEYS`):`JAVA_HOME` / `JRE_HOME` / `JDK_HOME` / `VIRTUAL_ENV` / `PYTHONPATH` / `PYTHONHOME` / `GOROOT` / `GOPATH` / `GOBIN` / `NODE_PATH` / `NVM_BIN` / `NVM_DIR` / `MAVEN_HOME` / `M2_HOME` / `GRADLE_HOME` / `SDKMAN_DIR` / `CONDA_PREFIX`。
73
-
74
- **其他**
75
-
76
- - **纯手动**:启动不探测、不连接 IDE MCP;IDE MCP 注册、环境重读、引导注入全部由 `/open-in-idea` 触发。
77
- - **根级 `index.js` 转发入口**:使仓库可作为 V2 本地目录插件直接加载(`plugins: [{ "package": "<repo>" }]`)。
78
- - **发布脚本** (`scripts/release.mjs`):`npm run release` 自动递增 patch、同步版本文件、跑测试并发布。
79
- - **配置项**:`ports` / `injectEnv` / `injectGuidance` / `openInIde` / `launchCooldownMs` / `launchMaxAttempts` / `mcpProbeTimeoutMs` / `feedback`。
80
- - 仅支持 **OpenCode V2**;非 JetBrains 项目完全不受影响。
@@ -1,61 +0,0 @@
1
- // The `idea-run-config` skill registered by the plugin.
2
- //
3
- // Run configurations are plain XML files under `.run/`. The IDE MCP server can
4
- // list and execute them (`get_run_configurations` / `execute_run_configuration`)
5
- // but has no create/update/delete. Hard-coding a template per configuration type
6
- // would be an open-ended maintenance hole (Application, JUnit, Gradle, npm,
7
- // Shell Script, Spring Boot, Docker, Compound, ...), so the plugin ships a skill
8
- // instead: it teaches the model where the files live, how to bootstrap a schema
9
- // from a real example, and how to verify a write.
10
- //
11
- // The text lives in `ide-run-config-skill.md` next to this module, so it is a
12
- // real skill document and the XML snippets it contains are not mistaken for
13
- // markup inside a string literal.
14
- //
15
- // The skill is registered at setup and does NOT depend on `/open-in-idea`.
16
-
17
- import { readFileSync } from 'node:fs';
18
- import { fileURLToPath } from 'node:url';
19
-
20
- /** Skill id used by the registry. */
21
- export const RUN_CONFIG_SKILL_ID = 'idea-run-config';
22
-
23
- /** Description shown to the model when picking a skill. */
24
- export const RUN_CONFIG_SKILL_DESCRIPTION = [
25
- '管理 JetBrains IDE 的 run configuration:在项目级 `.run/*.run.xml` 里创建、修改、删除运行配置。',
26
- '当用户要新建运行配置、修改或删除已有配置、把脚本或执行流程包成可运行的配置,',
27
- '或让 AI 执行用户手配的配置时使用。只操作项目级 `.run/` 文件,不碰 `.idea/workspace.xml`。',
28
- ].join('');
29
-
30
- const SKILL_FILE = new URL('./ide-run-config-skill.md', import.meta.url);
31
-
32
- /**
33
- * Read the skill document shipped next to this module.
34
- *
35
- * @returns {string}
36
- */
37
- export function readRunConfigSkillContent() {
38
- return readFileSync(SKILL_FILE, 'utf8').trimEnd();
39
- }
40
-
41
- /**
42
- * Build the skill definition registered through `ctx.skill.transform`.
43
- *
44
- * The schema (`Skill.Info` in `@opencode/schema/skill`) requires the field to be
45
- * named `path` and to hold an absolute path. Point it at the shipped `.md` — the
46
- * real skill document — rather than inventing a virtual filename.
47
- *
48
- * @returns {{ id: string, name: string, description: string, path: string, content: string }}
49
- */
50
- export function runConfigSkill() {
51
- return {
52
- id: RUN_CONFIG_SKILL_ID,
53
- name: 'idea-run-config',
54
- description: RUN_CONFIG_SKILL_DESCRIPTION,
55
- // Field names are schema-critical: `Skill.Info` requires `path`
56
- // (AbsolutePath). A wrong key fails validation and takes the whole plugin
57
- // down, not just the skill.
58
- path: fileURLToPath(SKILL_FILE),
59
- content: readRunConfigSkillContent(),
60
- };
61
- }
@@ -1,92 +0,0 @@
1
- # JetBrains Run Configuration 管理
2
-
3
- 本 skill 用于 **管理 JetBrains IDEA 的 run configuration (运行配置)**:创建、修改、删除、查看,并触发运行与调试。配置以 XML
4
- 文件形式存放在项目里,AI 通过读写这些文件完成管理,再用 IDE MCP 工具做校验和执行。
5
-
6
- ## 存放位置:只有 `.run/`
7
-
8
- 所有配置都写 **项目根 `.run/<name>.run.xml`**。这是 AI 唯一能可靠写入、且 IDEA 会 **即时加载**的位置。文件要不要提交到
9
- git,由用户自己决定,AI 不代劳、也不必追问。
10
-
11
- ### 为什么不用 `.idea/`
12
-
13
- - `.idea/workspace.xml` → `RunManager`:IDEA 的原生私有位置,但 **IDEA 是这份文件的主人** ——
14
- 工作区状态缓存在内存里、保存时整体重写,还有"工作区恢复"机制会覆盖或还原外部改动。AI 写进去不可靠。
15
- - `.idea/runConfigurations/*.xml`:这是 **2020.1 之前的共享位置**(不是私有位置),而且 `.idea` 常被 gitignore,反而更难共享。
16
-
17
- 用户已有的、存在 `.idea` 里的配置,AI 仍可 **读取和运行**(`idea_get_run_configurations` 能看到),只是不负责创建、修改或删除。
18
-
19
- ## 位置速查
20
-
21
- 这是 **事实参考**(IDEA 实际有三个位置),供识别用户已有配置用:
22
-
23
- | 位置 | 谁在用 | AI 能否写 |
24
- |--------------------------------------|--------------------------------------------|-----------------------------------------|
25
- | `.run/<name>.run.xml`(项目根) | 2020.1+ 的项目级位置 | 能写,IDEA 即时加载 |
26
- | `.idea/runConfigurations/*.xml` | 2020.1 **之前**的共享位置;现在仍兼容读取 | 一般不动,老项目可沿用 |
27
- | `.idea/workspace.xml` → `RunManager` | **默认**位置(不勾 "Store as project file") | **不写**(会被 IDEA 覆盖);但能读取和运行 |
28
-
29
- 新建配置时 `.run/` 的结构:
30
-
31
- ```xml
32
-
33
- <component name="ProjectRunConfigurationManager">
34
- <configuration default="false" name="<名字>" type="<类型 ID>">
35
- <option name="..." value="..."/>
36
- <envs/>
37
- <method v="2"/>
38
- </configuration>
39
- </component>
40
- ```
41
-
42
- ## 铁律
43
-
44
- 1. 不要凭空写 option 名。先找真实样本:
45
- - 用 `idea_search_file` 传 `q="**/*.run.xml"` 看项目里已有的配置。
46
- - 没有目标类型 → 请用户在 IDEA 里新建一个配置并勾选 "Store as project file",然后读生成的 XML 当模板。
47
- - 仍然没有 → 直接说明需要该类型的真实样本,不要猜 option 名。
48
- 2. 写完必须校验:
49
- - 在 `idea_get_run_configurations` 里能看到才算写对;看不到说明 `type` 写错了,改了重试。
50
- - 能看到不等于能跑:`idea_execute_run_configuration` 传 `configurationName` 实跑一次确认。
51
- - IDE MCP 不可用 → 提示用户执行 `/open-in-idea` 后再校验,不要跳过校验当成成功。
52
- 3. 改配置用定向修改:只用 `idea_apply_patch` 改需要的那几行 option,不要整文件重写。
53
- 4. 删除配置 = 删除对应的 `.run/<name>.run.xml`;不要试图从 `.idea/workspace.xml` 里删。
54
-
55
- ## 常见字段
56
-
57
- - `$PROJECT_DIR$`:项目根;`$MODULE_WORKING_DIR$`:模块目录。
58
- - 环境变量:
59
-
60
- ```xml
61
-
62
- <envs>
63
- <env name="KEY" value="VALUE"/>
64
- </envs>
65
- ```
66
-
67
- - Before launch 流程:`<method v="2">` 里加 `Make` 选项会先构建。
68
-
69
- ## 起步参考 (不是契约;动手前一律以真实样本为准)
70
-
71
- | 用途 | type | 关键 option |
72
- |------------|----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
73
- | Shell 脚本 | `ShConfigurationType` | 内联脚本:`SCRIPT_TEXT` + `EXECUTE_SCRIPT_FILE=false`;脚本文件:`SCRIPT_PATH` + `EXECUTE_SCRIPT_FILE=true`;`INTERPRETER_PATH`;`SCRIPT_WORKING_DIRECTORY` |
74
- | Java 应用 | `Application` | `MAIN_CLASS_NAME`;`WORKING_DIRECTORY`;`PROGRAM_PARAMETERS`;`VM_PARAMETERS` |
75
- | JUnit | `JUnit` | `TEST_OBJECT`;`MAIN_CLASS_NAME`;`WORKING_DIRECTORY` |
76
- | Gradle | `GradleRunConfiguration` | `ExternalProjectPath`;`TaskList` |
77
- | npm | `js.build_tools.npm` | `package-json`;`command`;`scripts` |
78
- | 串行流程 | `CompoundRunConfiguration` | `method` 里多个 `RunConfigurationTask`(带 `run_configuration_name` / `run_configuration_type`) |
79
-
80
- ## 命名
81
-
82
- - 把 `name` 转成文件名:去掉 `/ \ : * ? " < > |` 等非法字符,写成 `.run/<净化后的名字>.run.xml`。
83
- - 目标文件已存在时,先确认是要覆盖。
84
-
85
- ## 流程
86
-
87
- 1. `idea_search_file` 找 `**/*.run.xml` 样本。
88
- 2. 有同类样本 → 照它的结构改写;没有 → 请用户建一个。
89
- 3. `idea_create_new_file` 写 `.run/<name>.run.xml`。
90
- 4. `idea_get_run_configurations` 校验它出现。
91
- 5. `idea_execute_run_configuration` 实跑确认。
92
- 6. 修改用 `idea_apply_patch` 定向改 option;删除后确认它从列表里消失。