@wu529778790/open-im 1.10.2-beta.4 → 1.10.2-beta.5

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/README.md CHANGED
@@ -58,13 +58,13 @@ The published npm package includes **`web/dist`**. `open-im start` or `open-im d
58
58
  - Default dashboard URL: **`http://127.0.0.1:39282`** (respects **`OPEN_IM_WEB_PORT`**)
59
59
  - Override the URL shown/opened by the CLI with **`OPEN_IM_PUBLIC_WEB_URL`** (e.g. behind a reverse proxy)
60
60
 
61
- If you install from source without running `npm run web:build`, `web/dist` may be missing and **`GET /`** falls back to a minimal landing page only.
61
+ If you install from source without running **`npm run build`** (which runs `web:build` + `tsc`), `web/dist` may be missing and **`GET /`** returns **503** until you build. Use **`npm run build:ts`** for TypeScript-only iteration (skips the web bundle).
62
62
 
63
63
  ### Local HTTP service
64
64
 
65
65
  The running process listens on **`OPEN_IM_WEB_PORT`** (default **39282**):
66
66
 
67
- - **`GET /`** — built-in dashboard when `web/dist` is present; otherwise a minimal landing page
67
+ - **`GET /`** — built-in dashboard when `web/dist` is present; otherwise **503** with a short plain-text hint
68
68
  - **`/assets/*`** — static assets for the bundled SPA (when present)
69
69
  - **`/api/*`** — JSON API used by the dashboard
70
70
 
@@ -88,7 +88,9 @@ In the repository:
88
88
 
89
89
  ```bash
90
90
  npm run web:dev # Vite dev server; proxies /api to 127.0.0.1:39282
91
- npm run web:build # Production build web/dist (included in `npm publish` via `files`)
91
+ npm run build # web:build + tsc (use before running the compiled CLI with dashboard)
92
+ npm run build:ts # tsc only (no web/dist refresh)
93
+ npm run web:build # web/dist only
92
94
  ```
93
95
 
94
96
  More detail: [CLAUDE.md](./CLAUDE.md), [AGENTS.md](./AGENTS.md).
package/README.zh-CN.md CHANGED
@@ -58,13 +58,13 @@ open-im start
58
58
  - 默认控制台地址:本机 **`http://127.0.0.1:39282`**(随 **`OPEN_IM_WEB_PORT`** 变化)
59
59
  - 若需自定义打开的链接(例如反向代理后的地址),可设置 **`OPEN_IM_PUBLIC_WEB_URL`**
60
60
 
61
- 若从源码安装且未执行 `npm run web:build`,可能没有 `web/dist`,此时 **`GET /`** 仅为极简落地页。
61
+ 若从源码安装且未执行 **`npm run build`**(内含 `web:build`),可能没有 `web/dist`,此时 **`GET /`** 会返回 **503** 直至构建完成。仅改 TypeScript 时可使用 **`npm run build:ts`** 跳过前端构建。
62
62
 
63
63
  ### 本机 HTTP 服务
64
64
 
65
65
  进程监听 **`OPEN_IM_WEB_PORT`**(默认 **39282**):
66
66
 
67
- - **`GET /`** — 有 `web/dist` 时返回内置仪表盘;否则为极简落地页
67
+ - **`GET /`** — 有 `web/dist` 时返回内置仪表盘;否则 **503** 纯文本提示
68
68
  - **`/assets/*`** — 内置前端静态资源(有构建产物时)
69
69
  - **`/api/*`** — JSON API
70
70
 
@@ -86,7 +86,9 @@ export OPEN_IM_WEB_HOST=0.0.0.0
86
86
 
87
87
  ```bash
88
88
  npm run web:dev # Vite;将 /api 代理到 127.0.0.1:39282
89
- npm run web:build # 构建到 web/dist(`npm publish` 时会随包打入)
89
+ npm run build # web:build + tsc;发布前与日常请用此命令
90
+ npm run build:ts # 仅 tsc(不更新 web/dist)
91
+ npm run web:build # 仅构建 web/dist
90
92
  ```
91
93
 
92
94
  更多开发说明见 [CLAUDE.md](./CLAUDE.md)、[AGENTS.md](./AGENTS.md)。
package/dist/cli.js CHANGED
@@ -142,7 +142,7 @@ async function cmdDashboard() {
142
142
  const publicUrl = getPublicWebDashboardUrl();
143
143
  console.log(`\nWeb dashboard: ${publicUrl}`);
144
144
  if (!getWebDistDir()) {
145
- console.log("Note: web/dist not found — only minimal landing page at GET /. Run npm run web:build or use the published npm package.");
145
+ console.log("Note: web/dist not found — GET / returns 503 until you run npm run build (or npm run web:build), or use the published npm package.");
146
146
  }
147
147
  if (server.loginUrl) {
148
148
  console.log(`Remote login: ${server.loginUrl}`);
@@ -1,6 +1,6 @@
1
1
  import type { IncomingMessage, ServerResponse } from "node:http";
2
2
  import type { OutgoingHttpHeaders } from "node:http";
3
- /** npm 包内 `web/dist`(与 dist/*.js 相对路径固定) */
3
+ /** npm 包内 `web/dist`(相对本文件 `../web/dist`;开发时亦可匹配 `process.cwd()/web/dist`) */
4
4
  export declare function getWebDistDir(): string | null;
5
5
  /**
6
6
  * 若存在内置 `web/dist`,则对 GET 返回对应静态文件(含 `/` → index.html)。
@@ -12,12 +12,15 @@ const MIME = {
12
12
  ".woff2": "font/woff2",
13
13
  ".map": "application/json",
14
14
  };
15
- /** npm 包内 `web/dist`(与 dist/*.js 相对路径固定) */
15
+ /** npm 包内 `web/dist`(相对本文件 `../web/dist`;开发时亦可匹配 `process.cwd()/web/dist`) */
16
16
  export function getWebDistDir() {
17
17
  const here = dirname(fileURLToPath(import.meta.url));
18
- const candidate = join(here, "..", "web", "dist");
19
- if (existsSync(join(candidate, "index.html")))
20
- return candidate;
18
+ const fromPackage = join(here, "..", "web", "dist");
19
+ if (existsSync(join(fromPackage, "index.html")))
20
+ return fromPackage;
21
+ const fromCwd = join(process.cwd(), "web", "dist");
22
+ if (resolve(fromCwd) !== resolve(fromPackage) && existsSync(join(fromCwd, "index.html")))
23
+ return fromCwd;
21
24
  return null;
22
25
  }
23
26
  function resolveUnderRoot(root, pathname) {
@@ -8,7 +8,6 @@ import { DWClient } from "dingtalk-stream";
8
8
  import { WEB_CONFIG_PORT, getPublicWebDashboardUrl } from "./constants.js";
9
9
  import { CONFIG_PATH, getClaudeConfigHome, loadClaudeSettingsEnv, saveClaudeSettingsEnv, loadConfig, loadFileConfig, saveFileConfig } from "./config.js";
10
10
  import { getWebDistDir, tryServeDashboardStatic } from "./config-web-static.js";
11
- import { getConfigWebLandingHtml } from "./config-web-page.js";
12
11
  import { getServiceStatus, startBackgroundService, stopBackgroundService } from "./service-control.js";
13
12
  import { initWeWork, stopWeWork } from "./wework/client.js";
14
13
  import { createLogger } from "./logger.js";
@@ -806,8 +805,8 @@ export async function startWebConfigServer(options) {
806
805
  if (request.method === "GET" && requestUrl.pathname === "/") {
807
806
  if (tryServeDashboardStatic(requestUrl, request, response, mergeCors))
808
807
  return;
809
- response.writeHead(200, mergeCors(request, { "content-type": "text/html; charset=utf-8" }));
810
- response.end(getConfigWebLandingHtml());
808
+ response.writeHead(503, mergeCors(request, { "content-type": "text/plain; charset=utf-8" }));
809
+ response.end("open-im: web/dist is missing. Run npm run build in the repository root, then restart.\n");
811
810
  return;
812
811
  }
813
812
  if (request.method === "GET" && requestUrl.pathname === "/api/config") {
@@ -1067,7 +1066,7 @@ export async function runWebConfigFlow(options) {
1067
1066
  log.info("Full dashboard UI is bundled (same origin as API).");
1068
1067
  }
1069
1068
  else {
1070
- log.info(`API base: ${apiUrl} — install has no web/dist; minimal landing page only.`);
1069
+ log.info(`API base: ${apiUrl} — install has no web/dist; GET / returns 503 until you run npm run build.`);
1071
1070
  }
1072
1071
  if (started.loginUrl) {
1073
1072
  log.info(`Remote login (first visit): ${started.loginUrl}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.10.2-beta.4",
3
+ "version": "1.10.2-beta.5",
4
4
  "description": "Multi-platform IM bridge for AI CLI tools (Claude, Codex, CodeBuddy)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,7 +14,8 @@
14
14
  "LICENSE"
15
15
  ],
16
16
  "scripts": {
17
- "build": "tsc",
17
+ "build": "npm run web:build && tsc",
18
+ "build:ts": "tsc",
18
19
  "dev": "tsx src/index.ts",
19
20
  "init": "tsx src/cli.ts init",
20
21
  "start": "node dist/cli.js start",
@@ -26,7 +27,7 @@
26
27
  "lint": "eslint src",
27
28
  "web:build": "npm --prefix web run build",
28
29
  "web:dev": "npm --prefix web run dev",
29
- "prepublishOnly": "npm run web:build && npm run build"
30
+ "prepublishOnly": "npm run build"
30
31
  },
31
32
  "keywords": [
32
33
  "dingtalk",
@@ -1,5 +0,0 @@
1
- /**
2
- * 无内置 `web/dist` 时的极简落地页(例如从源码运行且未执行 web:build)。
3
- * 发布到 npm 的包通常包含构建产物,由 config-web-static 直接提供 SPA。
4
- */
5
- export declare function getConfigWebLandingHtml(): string;
@@ -1,32 +0,0 @@
1
- import { getPublicWebDashboardUrl } from "./constants.js";
2
- function escapeHtml(s) {
3
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
4
- }
5
- /**
6
- * 无内置 `web/dist` 时的极简落地页(例如从源码运行且未执行 web:build)。
7
- * 发布到 npm 的包通常包含构建产物,由 config-web-static 直接提供 SPA。
8
- */
9
- export function getConfigWebLandingHtml() {
10
- const web = escapeHtml(getPublicWebDashboardUrl());
11
- return `<!doctype html>
12
- <html lang="en">
13
- <head>
14
- <meta charset="utf-8" />
15
- <meta name="viewport" content="width=device-width, initial-scale=1" />
16
- <title>open-im</title>
17
- <style>
18
- body { font-family: system-ui, -apple-system, Segoe UI, sans-serif; max-width: 40rem; margin: 2rem auto; padding: 0 1rem; line-height: 1.55; color: #111827; background: #f9fafb; }
19
- a { color: #2563eb; }
20
- code { font-size: 0.9em; background: #e5e7eb; padding: 0.15em 0.4em; border-radius: 4px; word-break: break-all; }
21
- h1 { font-size: 1.25rem; }
22
- </style>
23
- </head>
24
- <body>
25
- <h1>open-im</h1>
26
- <p>No bundled dashboard (<code>web/dist</code> missing). Run <code>npm run web:build</code> in the repo, or install the published npm package.</p>
27
- <p>Console URL when bundled: <a href="${web}">${web}</a></p>
28
- <p>API base: <code id="api"></code></p>
29
- <script>document.getElementById("api").textContent = location.origin;</script>
30
- </body>
31
- </html>`;
32
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,26 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { getConfigWebLandingHtml } from "./config-web-page.js";
3
- import { getDefaultLocalDashboardUrl, getPublicWebDashboardUrl } from "./constants.js";
4
- describe("config web landing page", () => {
5
- it("does not embed legacy full-dashboard markers", () => {
6
- const html = getConfigWebLandingHtml();
7
- expect(html).not.toContain("__PAGE_TEXTS__");
8
- expect(html).not.toContain("heroBodyFull");
9
- expect(html).not.toContain("Local AI bridge");
10
- });
11
- it("links to the dashboard URL and explains missing bundle", () => {
12
- const url = getPublicWebDashboardUrl();
13
- const html = getConfigWebLandingHtml();
14
- expect(html).toContain(url);
15
- expect(html).toContain("web/dist");
16
- });
17
- it("includes API origin script hook", () => {
18
- const html = getConfigWebLandingHtml();
19
- expect(html).toContain('id="api"');
20
- expect(html).toContain("location.origin");
21
- });
22
- it("defaults public dashboard to local http", () => {
23
- expect(getDefaultLocalDashboardUrl()).toMatch(/^http:\/\/127\.0\.0\.1:\d+$/);
24
- expect(getPublicWebDashboardUrl()).toMatch(/^http:\/\/127\.0\.0\.1:\d+$/);
25
- });
26
- });