@aiti-ai/aiti-devtools-webpack 0.0.0-stage → 0.1.0

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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -2
  3. package/package.json +30 -4
  4. package/src/index.js +113 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 aiti-ai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,39 @@
1
- # Temporary Holding Version
1
+ # @aiti-ai/aiti-devtools-webpack
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > webpack-dev-server 载体插件:setupMiddlewares 挂桥 + html-webpack-plugin 注入;Rspack 同格式零改动直接复用。
4
+
5
+ ## 来源 · Origin
6
+
7
+ 本包是 **aiti** 生态的组成部分——以 [pi](https://pi.dev) 为引擎的个人 AI 开发工作台与本地调试注入生态:**aiti-agent**(自托管 Web 工作台,基于开源项目 [pi-web](https://github.com/aiti-ai/pi-web) 构建,浏览器为主操作面)+ 各开发工具内的调试注入(aiti-devtools)+ 丰富的扩展体系。
8
+
9
+ This package is part of the **aiti** ecosystem — a personal AI development workbench powered by [pi](https://pi.dev): **aiti-agent** (a self-hosted web workbench built on the open-source [pi-web](https://github.com/aiti-ai/pi-web)) plus debug injection into mainstream dev tools (aiti-devtools) and a rich extension system.
10
+
11
+ - 工作台 / workbench: <https://github.com/aiti-ai/pi-web>
12
+ - 生态仓库 / monorepo: <https://github.com/aiti-ai/aiti-ai>
13
+ - 官网 / site: <https://aiti.pw>
14
+
15
+ ## 功能定位(中文)
16
+
17
+ webpack-dev-server 载体插件:setupMiddlewares 挂桥 + html-webpack-plugin 注入;Rspack 同格式零改动直接复用。
18
+
19
+ ## Positioning (English)
20
+
21
+ webpack-dev-server carrier plugin: bridge via setupMiddlewares + html-webpack-plugin injection; Rspack reuses it unchanged.
22
+
23
+ ## 安装 / 部署
24
+
25
+ ```bash
26
+ npm install -D @aiti-ai/aiti-devtools-webpack
27
+ ```
28
+
29
+ 不同载体的接线方式见文档(多数一行接入)。
30
+
31
+ ## 文档 · Documentation
32
+
33
+ - 中文完整文档(aiti-docs): <https://aiti.pw/devtools/integrations/webpack-rspack.html>
34
+ - English docs: <https://aiti.pw/en/devtools/integrations/webpack-rspack.html>
35
+ - 扩展注册表 / registry: <https://aiti.pw/extensions.html> · machine-readable <https://aiti.pw/extensions.json>
36
+
37
+ ## License
38
+
39
+ MIT
package/package.json CHANGED
@@ -1,6 +1,32 @@
1
1
  {
2
2
  "name": "@aiti-ai/aiti-devtools-webpack",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "aiti-devtools webpack-dev-server 插件(载体 2):dev server 内置 MCP(launcher 注入 + 桥 + MCP 端点 + 操作台,同源 /aiti/),启动自动注册到常见 agent 工具。复用 aiti-devtools-core 全部公共能力",
5
+ "type": "module",
6
+ "main": "src/index.js",
7
+ "exports": {
8
+ ".": "./src/index.js"
9
+ },
10
+ "files": [
11
+ "src"
12
+ ],
13
+ "dependencies": {
14
+ "@aiti-ai/aiti-devtools-core": "^0.3.5"
15
+ },
16
+ "peerDependencies": {
17
+ "webpack": "^5.0.0",
18
+ "webpack-dev-server": "^4.0.0 || ^5.0.0",
19
+ "html-webpack-plugin": "^5.0.0"
20
+ },
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/aiti-ai/aiti-ai.git",
25
+ "directory": "packages/aiti-devtools-webpack"
26
+ },
27
+ "homepage": "https://github.com/aiti-ai/aiti-ai#readme",
28
+ "bugs": {
29
+ "url": "https://github.com/aiti-ai/aiti-ai/issues"
30
+ },
31
+ "contentHash": "d1f622a04ca1e4ad"
32
+ }
package/src/index.js ADDED
@@ -0,0 +1,113 @@
1
+ /**
2
+ * aiti-devtools-webpack —— webpack-dev-server 插件(载体 2)
3
+ *
4
+ * 与 aiti-devtools-vite 同能力、薄载体层:
5
+ * - devServer.setupMiddlewares 挂 connectBridge(复用 core 的 connect 中间件适配,webpack-dev-server 中间件格式兼容)
6
+ * - html-webpack-plugin 注入 <script src="/aiti/aiti-launcher.js" data-ai-url data-bridge-url>
7
+ * - 端口就绪后解析端点 + 自动注册 MCP + 打印启动输出
8
+ *
9
+ * 资产/桥/注册/协商全部来自 @aiti-ai/aiti-devtools-core(loadAssets / createBridge / registerMcp / resolveEndpoints)。
10
+ */
11
+ import { createRequire } from 'node:module';
12
+ import { join, resolve } from 'node:path';
13
+ import { homedir } from 'node:os';
14
+ import { createBridge, connectBridge, resolveEndpoints, registerMcp, loadAssets } from '@aiti-ai/aiti-devtools-core';
15
+
16
+ const require = createRequire(import.meta.url);
17
+
18
+ export class AitiDevtoolsWebpackPlugin {
19
+ constructor(opts = {}) {
20
+ this.opts = opts;
21
+ this.prefix = (opts.prefix || '/aiti').replace(/\/+$/, '') || '/aiti';
22
+ this.name = opts.name || 'aiti-devtools';
23
+ this.log = opts.log || ((l) => console.log(l));
24
+ this.staticFiles = loadAssets(opts.assetsDir);
25
+ this.bridge = createBridge(opts.dataDir || join(homedir(), '.pi', 'aiti-bridge'), { name: this.name });
26
+ }
27
+
28
+ apply(compiler) {
29
+ const opts = this.opts;
30
+
31
+ // ---- 1. dev server 中间件 + 端口就绪后注册 MCP ----
32
+ compiler.options.devServer = compiler.options.devServer || {};
33
+ const origSetup = compiler.options.devServer.setupMiddlewares;
34
+ compiler.options.devServer.setupMiddlewares = (middlewares, devServer) => {
35
+ middlewares.unshift(connectBridge(this.bridge, { prefix: this.prefix, staticFiles: this.staticFiles }));
36
+ const server = devServer && devServer.server;
37
+ const registerOnce = () => {
38
+ try {
39
+ const addr = server.address && server.address();
40
+ const port = (addr && typeof addr === 'object' && addr.port) || devServer.options?.port || 8080;
41
+ const host = (devServer.options?.host && devServer.options.host !== '0.0.0.0' && devServer.options.host) || 'localhost';
42
+ const e = resolveEndpoints({ bridgeUrl: opts.bridgeUrl, aiUrl: opts.aiUrl, serverUrl: `http://${host}:${port}`, prefix: this.prefix });
43
+ this.printBanner(e, host, port);
44
+ this.doRegisterMcp(e, compiler.context || process.cwd());
45
+ } catch (err) {
46
+ this.log(`[${this.name}] ⚠ 启动后处理失败:${err.message}`);
47
+ }
48
+ };
49
+ if (server && typeof server.once === 'function') server.once('listening', registerOnce);
50
+ else registerOnce();
51
+ return origSetup ? origSetup(middlewares, devServer) : middlewares;
52
+ };
53
+
54
+ // ---- 2. HTML 注入(html-webpack-plugin)——仅 dev(webpack build 生产产物不注入)----
55
+ if (opts.inject === false) return;
56
+ const isDev = !!compiler.options.devServer && compiler.options.mode !== 'production';
57
+ if (!isDev) return;
58
+ // html-webpack-plugin 装在使用方项目:从 compiler.context 解析(插件源码位置解析不到)
59
+ const userRequire = createRequire(join(compiler.context || process.cwd(), 'package.json'));
60
+ compiler.hooks.compilation.tap('@aiti-ai/aiti-devtools-webpack', (compilation) => {
61
+ let HtmlWebpackPlugin = null;
62
+ try { HtmlWebpackPlugin = userRequire('html-webpack-plugin'); } catch {}
63
+ if (!HtmlWebpackPlugin || !HtmlWebpackPlugin.getHooks) return;
64
+ const hooks = HtmlWebpackPlugin.getHooks(compilation);
65
+ hooks.alterAssetTagGroups.tapAsync('@aiti-ai/aiti-devtools-webpack', (data, cb) => {
66
+ // dev 模式端口未知 → 相对路径(同源 /aiti/);bridge/aiUrl 同源相对,用户自定义则绝对
67
+ const bridgeBase = opts.bridgeUrl ? resolveEndpoints({ bridgeUrl: opts.bridgeUrl, aiUrl: '', serverUrl: 'http://localhost', prefix: this.prefix }).bridgeBase : this.prefix;
68
+ const aiUrl = opts.aiUrl || `${this.prefix}/cockpit.html`;
69
+ data.headTags.unshift({
70
+ tagName: 'script',
71
+ closeTag: true,
72
+ attributes: {
73
+ src: `${this.prefix}/aiti-launcher.js`,
74
+ 'data-ai-url': aiUrl,
75
+ 'data-bridge-url': bridgeBase,
76
+ 'data-name': this.name,
77
+ },
78
+ });
79
+ cb(null, data);
80
+ });
81
+ });
82
+ }
83
+
84
+ printBanner(e, host, port) {
85
+ const kindLabel = e.kind === 'same-origin' ? '同源模式' : '外部桥模式';
86
+ this.log('');
87
+ this.log(`[${this.name}] 🧰 ${this.name}-webpack 已启动(${kindLabel} · name=${this.name} · ${host}:${port})`);
88
+ this.log(` launcher: ${e.launcherUrl}`);
89
+ this.log(` 操作台: ${e.cockpitUrl}`);
90
+ this.log(` MCP: ${e.mcpUrl} ← agent 的 mcp 配置 url 指这里`);
91
+ this.log(` bridge: ${e.bridgeBase}`);
92
+ this.log(` AI 窗: ${e.aiUrl}${this.opts.aiUrl ? '(aiti-agent)' : '(同源 cockpit,可用 aiUrl 指定 aiti-agent)'}`);
93
+ for (const n of e.notes) this.log(` · ${n}`);
94
+ }
95
+
96
+ doRegisterMcp(e, projectDir) {
97
+ const m = this.opts.mcp || {};
98
+ if (m.register === false || m.targets === false) return;
99
+ const r = registerMcp({
100
+ url: e.mcpUrl,
101
+ serverName: this.name,
102
+ targets: m.targets === false ? undefined : (m.targets || 'auto'),
103
+ configPaths: m.configPaths || [],
104
+ projectDir,
105
+ dryRun: !!m.dryRun,
106
+ log: this.log,
107
+ });
108
+ this.log(`[${this.name}] MCP 注册:${r.summary}`);
109
+ if (r.ok && !r.changed) this.log(`[${this.name}] (全部已是最新,未写盘)`);
110
+ }
111
+ }
112
+
113
+ export default AitiDevtoolsWebpackPlugin;