@wu529778790/open-im 1.10.7-beta.0 → 1.10.7-beta.1
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 +4 -0
- package/README.zh-CN.md +4 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.js +5 -0
- package/dist/git-hook.d.ts +5 -0
- package/dist/git-hook.js +86 -0
- package/dist/index.js +3 -0
- package/dist/shared/git-coauthor.d.ts +16 -0
- package/dist/shared/git-coauthor.js +47 -0
- package/package.json +2 -1
- package/scripts/git-hooks/prepare-commit-msg +18 -0
package/README.md
CHANGED
|
@@ -38,6 +38,10 @@ Config: **`~/.open-im/config.json`**
|
|
|
38
38
|
|
|
39
39
|
After `start`, the CLI prints the dashboard URL (default **`http://127.0.0.1:39282`**).
|
|
40
40
|
|
|
41
|
+
## Git co-authors
|
|
42
|
+
|
|
43
|
+
`Co-authored-by` is appended by default on AI-driven commits. **Disable:** set **`OPEN_IM_GIT_COAUTHOR=0`** in the environment and restart the bridge.
|
|
44
|
+
|
|
41
45
|
## Web dashboard
|
|
42
46
|
|
|
43
47
|
`open-im start` and `open-im dashboard` serve the built-in SPA and **`/api/*`** on **`OPEN_IM_WEB_PORT`** (default **39282**). Open **`http://127.0.0.1:39282`** in a browser (same origin as the API). Override the displayed URL with **`OPEN_IM_PUBLIC_WEB_URL`** if behind a proxy.
|
package/README.zh-CN.md
CHANGED
|
@@ -38,6 +38,10 @@ npx @wu529778790/open-im start
|
|
|
38
38
|
|
|
39
39
|
`start` 后会提示控制台地址(默认 **`http://127.0.0.1:39282`**)。
|
|
40
40
|
|
|
41
|
+
## Git 共同作者
|
|
42
|
+
|
|
43
|
+
默认在 AI 发起的提交里追加 `Co-authored-by`。**关闭**:设置环境变量 **`OPEN_IM_GIT_COAUTHOR=0`** 并重启桥接。
|
|
44
|
+
|
|
41
45
|
## Web 控制台
|
|
42
46
|
|
|
43
47
|
`open-im start` / `open-im dashboard` 在 **`OPEN_IM_WEB_PORT`**(默认 **39282**)提供内置页面与 **`/api/*`**。浏览器打开 **`http://127.0.0.1:39282`** 即可(与 API 同源)。反向代理时可设 **`OPEN_IM_PUBLIC_WEB_URL`**。
|
package/dist/constants.d.ts
CHANGED
|
@@ -17,6 +17,11 @@ export declare const WEB_CONFIG_PORT = 39282;
|
|
|
17
17
|
export declare function getDefaultLocalDashboardUrl(): string;
|
|
18
18
|
export declare function getPublicWebDashboardUrl(): string;
|
|
19
19
|
export declare const IMAGE_DIR: string;
|
|
20
|
+
/**
|
|
21
|
+
* Co-authored-by 使用的固定提交者地址(开箱即用,形如 GitHub noreply)。
|
|
22
|
+
* 若希望贡献图关联到具体用户,请将该地址加入对应 GitHub 账号的已验证联系方式,或 fork 后自行修改常量。
|
|
23
|
+
*/
|
|
24
|
+
export declare const DEFAULT_OPEN_IM_COAUTHOR_ADDR = "529778790@qq.com";
|
|
20
25
|
export declare const TERMINAL_ONLY_COMMANDS: Set<string>;
|
|
21
26
|
/** CardKit 流式更新节流:80ms(约 12 次/秒,cardElement.content 专为打字机设计,支持更高频率) */
|
|
22
27
|
export declare const CARDKIT_THROTTLE_MS = 80;
|
package/dist/constants.js
CHANGED
|
@@ -29,6 +29,11 @@ export function getPublicWebDashboardUrl() {
|
|
|
29
29
|
return raw.replace(/\/$/, "");
|
|
30
30
|
}
|
|
31
31
|
export const IMAGE_DIR = join(tmpdir(), "open-im-images");
|
|
32
|
+
/**
|
|
33
|
+
* Co-authored-by 使用的固定提交者地址(开箱即用,形如 GitHub noreply)。
|
|
34
|
+
* 若希望贡献图关联到具体用户,请将该地址加入对应 GitHub 账号的已验证联系方式,或 fork 后自行修改常量。
|
|
35
|
+
*/
|
|
36
|
+
export const DEFAULT_OPEN_IM_COAUTHOR_ADDR = "529778790@qq.com";
|
|
32
37
|
export const TERMINAL_ONLY_COMMANDS = new Set([
|
|
33
38
|
"/context",
|
|
34
39
|
"/rewind",
|
package/dist/git-hook.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { chmodSync, copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join, resolve as pathResolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { execFileSync } from "node:child_process";
|
|
6
|
+
import { APP_HOME } from "./constants.js";
|
|
7
|
+
import { createLogger } from "./logger.js";
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const log = createLogger("GitHook");
|
|
10
|
+
/** 避免每次启动在满足「已占用 hooksPath」时重复打 WARN */
|
|
11
|
+
let warnedForeignHooksPath = false;
|
|
12
|
+
function packageRoot() {
|
|
13
|
+
return join(__dirname, "..");
|
|
14
|
+
}
|
|
15
|
+
function bundledPrepareCommitMsg() {
|
|
16
|
+
return join(packageRoot(), "scripts", "git-hooks", "prepare-commit-msg");
|
|
17
|
+
}
|
|
18
|
+
function targetHooksDir() {
|
|
19
|
+
return join(APP_HOME, "git-hooks");
|
|
20
|
+
}
|
|
21
|
+
function targetPrepareCommitMsg() {
|
|
22
|
+
return join(targetHooksDir(), "prepare-commit-msg");
|
|
23
|
+
}
|
|
24
|
+
function gitTry(args) {
|
|
25
|
+
try {
|
|
26
|
+
return execFileSync("git", args, { encoding: "utf-8" }).trim();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** 将包内钩子复制到 ~/.open-im/git-hooks(失败则返回 false) */
|
|
33
|
+
function materializeOpenImHookScript() {
|
|
34
|
+
const src = bundledPrepareCommitMsg();
|
|
35
|
+
if (!existsSync(src)) {
|
|
36
|
+
log.debug(`Bundled prepare-commit-msg not found at ${src}, skip`);
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
mkdirSync(targetHooksDir(), { recursive: true });
|
|
41
|
+
copyFileSync(src, targetPrepareCommitMsg());
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
log.warn(`Could not copy prepare-commit-msg: ${err instanceof Error ? err.message : String(err)}`);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (process.platform !== "win32") {
|
|
48
|
+
try {
|
|
49
|
+
chmodSync(targetPrepareCommitMsg(), 0o755);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
/* ignore */
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 桥接启动时调用:在未占用 global core.hooksPath 时自动指向 ~/.open-im/git-hooks。
|
|
59
|
+
* 若用户已设置其它 hooksPath,仅打日志,不覆盖。
|
|
60
|
+
*/
|
|
61
|
+
export function ensureOpenImGlobalPrepareCommitHook() {
|
|
62
|
+
if (!materializeOpenImHookScript())
|
|
63
|
+
return;
|
|
64
|
+
const hooksPath = targetHooksDir();
|
|
65
|
+
const existing = gitTry(["config", "--global", "--get", "core.hooksPath"]);
|
|
66
|
+
if (!existing) {
|
|
67
|
+
try {
|
|
68
|
+
execFileSync("git", ["config", "--global", "core.hooksPath", hooksPath]);
|
|
69
|
+
log.info(`Auto-set git config --global core.hooksPath → ${hooksPath}`);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
log.warn(`Could not set global core.hooksPath (is git installed?): ${err instanceof Error ? err.message : String(err)}`);
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const a = pathResolve(existing.replace(/^~(?=$|[/\\])/, homedir()));
|
|
77
|
+
const b = pathResolve(hooksPath);
|
|
78
|
+
if (a === b)
|
|
79
|
+
return;
|
|
80
|
+
if (!warnedForeignHooksPath) {
|
|
81
|
+
warnedForeignHooksPath = true;
|
|
82
|
+
log.warn(`Global core.hooksPath is "${existing}" (not open-im's dir); skipping auto wire. ` +
|
|
83
|
+
`Merge scripts/git-hooks/prepare-commit-msg into that hooks directory, ` +
|
|
84
|
+
`or set OPEN_IM_GIT_COAUTHOR_NO_AUTO_HOOK=1 to silence this warning.`);
|
|
85
|
+
}
|
|
86
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ import { initLogger, createLogger, closeLogger, emitStructuredEvent, shutdownLog
|
|
|
31
31
|
import { APP_HOME, SHUTDOWN_PORT } from "./constants.js";
|
|
32
32
|
import { createRequire } from "node:module";
|
|
33
33
|
import { escapePathForMarkdown } from "./shared/utils.js";
|
|
34
|
+
import { applyOpenImGitCoauthorToProcessEnv } from "./shared/git-coauthor.js";
|
|
34
35
|
const require = createRequire(import.meta.url);
|
|
35
36
|
const { version: APP_VERSION } = require("../package.json");
|
|
36
37
|
const log = createLogger("Main");
|
|
@@ -157,6 +158,7 @@ export async function main() {
|
|
|
157
158
|
logLevel: config.logLevel,
|
|
158
159
|
telemetry: config.telemetry,
|
|
159
160
|
});
|
|
161
|
+
applyOpenImGitCoauthorToProcessEnv();
|
|
160
162
|
}
|
|
161
163
|
catch (err) {
|
|
162
164
|
if (err instanceof Error &&
|
|
@@ -172,6 +174,7 @@ export async function main() {
|
|
|
172
174
|
logLevel: config.logLevel,
|
|
173
175
|
telemetry: config.telemetry,
|
|
174
176
|
});
|
|
177
|
+
applyOpenImGitCoauthorToProcessEnv();
|
|
175
178
|
}
|
|
176
179
|
else {
|
|
177
180
|
throw err;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub 会识别 commit message 中的 Co-authored-by 并在提交页展示共同作者。
|
|
3
|
+
*
|
|
4
|
+
* **默认开启**:无需也不应手动设置 `OPEN_IM_GIT_COAUTHOR_LINE`,桥接启动时会自动写入该变量;
|
|
5
|
+
* 仅当 `OPEN_IM_GIT_COAUTHOR=0|false|no` 时才会清空。地址来自 {@link DEFAULT_OPEN_IM_COAUTHOR_ADDR}。
|
|
6
|
+
*
|
|
7
|
+
* - OPEN_IM_GIT_COAUTHOR=0|false|no — 关闭共同作者(不写 OPEN_IM_GIT_COAUTHOR_LINE)
|
|
8
|
+
* - OPEN_IM_GIT_COAUTHOR_NAME — 显示名,默认 open-im
|
|
9
|
+
* - OPEN_IM_GIT_COAUTHOR_NO_AUTO_HOOK=1 — 不自动改 git global core.hooksPath(需自行装钩子)
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveOpenImGitCoauthorLine(): string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* 默认开启:设置 `process.env.OPEN_IM_GIT_COAUTHOR_LINE` 供子进程与 git 钩子使用;
|
|
14
|
+
* AI 发起的 commit 会由 prepare-commit-msg 追加该行(除非已显式关闭共同作者)。
|
|
15
|
+
*/
|
|
16
|
+
export declare function applyOpenImGitCoauthorToProcessEnv(): void;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { DEFAULT_OPEN_IM_COAUTHOR_ADDR } from "../constants.js";
|
|
2
|
+
import { createLogger } from "../logger.js";
|
|
3
|
+
import { ensureOpenImGlobalPrepareCommitHook } from "../git-hook.js";
|
|
4
|
+
const log = createLogger("GitCoauthor");
|
|
5
|
+
const DISABLE_VALUES = new Set(["0", "false", "no"]);
|
|
6
|
+
/**
|
|
7
|
+
* GitHub 会识别 commit message 中的 Co-authored-by 并在提交页展示共同作者。
|
|
8
|
+
*
|
|
9
|
+
* **默认开启**:无需也不应手动设置 `OPEN_IM_GIT_COAUTHOR_LINE`,桥接启动时会自动写入该变量;
|
|
10
|
+
* 仅当 `OPEN_IM_GIT_COAUTHOR=0|false|no` 时才会清空。地址来自 {@link DEFAULT_OPEN_IM_COAUTHOR_ADDR}。
|
|
11
|
+
*
|
|
12
|
+
* - OPEN_IM_GIT_COAUTHOR=0|false|no — 关闭共同作者(不写 OPEN_IM_GIT_COAUTHOR_LINE)
|
|
13
|
+
* - OPEN_IM_GIT_COAUTHOR_NAME — 显示名,默认 open-im
|
|
14
|
+
* - OPEN_IM_GIT_COAUTHOR_NO_AUTO_HOOK=1 — 不自动改 git global core.hooksPath(需自行装钩子)
|
|
15
|
+
*/
|
|
16
|
+
export function resolveOpenImGitCoauthorLine() {
|
|
17
|
+
const flag = process.env.OPEN_IM_GIT_COAUTHOR?.trim().toLowerCase();
|
|
18
|
+
if (flag && DISABLE_VALUES.has(flag))
|
|
19
|
+
return undefined;
|
|
20
|
+
const addr = DEFAULT_OPEN_IM_COAUTHOR_ADDR;
|
|
21
|
+
if (!addr.trim())
|
|
22
|
+
return undefined;
|
|
23
|
+
const rawName = process.env.OPEN_IM_GIT_COAUTHOR_NAME?.trim() || "open-im";
|
|
24
|
+
const name = rawName.replace(/[<>]/g, "").trim() || "open-im";
|
|
25
|
+
return `Co-authored-by: ${name} <${addr}>`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 默认开启:设置 `process.env.OPEN_IM_GIT_COAUTHOR_LINE` 供子进程与 git 钩子使用;
|
|
29
|
+
* AI 发起的 commit 会由 prepare-commit-msg 追加该行(除非已显式关闭共同作者)。
|
|
30
|
+
*/
|
|
31
|
+
export function applyOpenImGitCoauthorToProcessEnv() {
|
|
32
|
+
const line = resolveOpenImGitCoauthorLine();
|
|
33
|
+
if (line) {
|
|
34
|
+
process.env.OPEN_IM_GIT_COAUTHOR_LINE = line;
|
|
35
|
+
if (!isTruthyEnv(process.env.OPEN_IM_GIT_COAUTHOR_NO_AUTO_HOOK)) {
|
|
36
|
+
ensureOpenImGlobalPrepareCommitHook();
|
|
37
|
+
}
|
|
38
|
+
log.info("Git co-author enabled; AI git commits will append OPEN_IM_GIT_COAUTHOR_LINE when the hook runs.");
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
delete process.env.OPEN_IM_GIT_COAUTHOR_LINE;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isTruthyEnv(v) {
|
|
45
|
+
const t = v?.trim().toLowerCase();
|
|
46
|
+
return t === "1" || t === "true" || t === "yes";
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wu529778790/open-im",
|
|
3
|
-
"version": "1.10.7-beta.
|
|
3
|
+
"version": "1.10.7-beta.1",
|
|
4
4
|
"description": "Multi-platform IM bridge for AI CLI tools (Claude, Codex, CodeBuddy)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
12
|
"web/dist",
|
|
13
|
+
"scripts/git-hooks",
|
|
13
14
|
"README.md",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# open-im: 在 git commit 时追加 Co-authored-by。
|
|
3
|
+
# OPEN_IM_GIT_COAUTHOR_LINE:由桥接进程默认注入(共同作者默认开启),无需在 shell 里手动 export。
|
|
4
|
+
# 若为空则跳过(例如未启动桥接、或已设 OPEN_IM_GIT_COAUTHOR=0 后重启)。
|
|
5
|
+
# 安装:由桥接启动时自动复制并配置 core.hooksPath(若尚未占用)
|
|
6
|
+
|
|
7
|
+
COMMIT_MSG_FILE=$1
|
|
8
|
+
|
|
9
|
+
if [ -z "$OPEN_IM_GIT_COAUTHOR_LINE" ] || [ -z "$COMMIT_MSG_FILE" ] || [ ! -f "$COMMIT_MSG_FILE" ]; then
|
|
10
|
+
exit 0
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
if grep -qF "$OPEN_IM_GIT_COAUTHOR_LINE" "$COMMIT_MSG_FILE" 2>/dev/null; then
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
printf '\n%s\n' "$OPEN_IM_GIT_COAUTHOR_LINE" >>"$COMMIT_MSG_FILE"
|
|
18
|
+
exit 0
|