hunter-mate 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.
- package/dist/cache/db.d.ts +7 -0
- package/dist/cache/db.js +105 -0
- package/dist/commands/addons.d.ts +4 -0
- package/dist/commands/addons.js +378 -0
- package/dist/commands/cache.d.ts +8 -0
- package/dist/commands/cache.js +58 -0
- package/dist/commands/config.d.ts +12 -0
- package/dist/commands/config.js +27 -0
- package/dist/commands/doctor.d.ts +21 -0
- package/dist/commands/doctor.js +332 -0
- package/dist/commands/extension.d.ts +5 -0
- package/dist/commands/extension.js +438 -0
- package/dist/commands/extras.d.ts +10 -0
- package/dist/commands/extras.js +111 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.js +87 -0
- package/dist/commands/install.d.ts +9 -0
- package/dist/commands/install.js +126 -0
- package/dist/commands/job.d.ts +9 -0
- package/dist/commands/job.js +114 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.js +51 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.js +16 -0
- package/dist/commands/native-check.d.ts +22 -0
- package/dist/commands/native-check.js +93 -0
- package/dist/commands/ops.d.ts +6 -0
- package/dist/commands/ops.js +330 -0
- package/dist/commands/record.d.ts +12 -0
- package/dist/commands/record.js +96 -0
- package/dist/commands/report.d.ts +7 -0
- package/dist/commands/report.js +54 -0
- package/dist/commands/search.d.ts +14 -0
- package/dist/commands/search.js +46 -0
- package/dist/commands/server.d.ts +23 -0
- package/dist/commands/server.js +232 -0
- package/dist/commands/status.d.ts +20 -0
- package/dist/commands/status.js +92 -0
- package/dist/commands/update.d.ts +8 -0
- package/dist/commands/update.js +161 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.js +65 -0
- package/dist/i18n/index.d.ts +7 -0
- package/dist/i18n/index.js +24 -0
- package/dist/i18n/locales/en-US.json +35 -0
- package/dist/i18n/locales/zh-CN.json +35 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +133 -0
- package/dist/keychain.d.ts +3 -0
- package/dist/keychain.js +117 -0
- package/dist/sentry.d.ts +3 -0
- package/dist/sentry.js +62 -0
- package/dist/updater.d.ts +23 -0
- package/dist/updater.js +161 -0
- package/dist/version.d.ts +16 -0
- package/dist/version.js +249 -0
- package/package.json +50 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cli.description": "HiredChina 猎头 Agent 数据助手",
|
|
3
|
+
"cli.langOption": "输出语言(zh-CN/en-US)",
|
|
4
|
+
"login.description": "使用 OAuth 设备码登录",
|
|
5
|
+
"login.start": "正在打开浏览器完成登录...",
|
|
6
|
+
"login.userCode": "用户码:",
|
|
7
|
+
"login.verifyUrl": "授权地址:",
|
|
8
|
+
"login.success": "登录成功",
|
|
9
|
+
"login.failed": "登录失败:",
|
|
10
|
+
"login.expired": "设备码已过期,请重试",
|
|
11
|
+
"logout.description": "退出登录并删除本地 token",
|
|
12
|
+
"logout.success": "已退出登录",
|
|
13
|
+
"status.description": "查看服务、登录、扩展状态",
|
|
14
|
+
"status.cli": "CLI 版本",
|
|
15
|
+
"status.loggedIn": "已登录",
|
|
16
|
+
"status.loggedOut": "未登录",
|
|
17
|
+
"status.server": "Server 状态",
|
|
18
|
+
"status.extension": "扩展状态",
|
|
19
|
+
"config.description": "配置 server 地址、监听文件夹、语言",
|
|
20
|
+
"config.saved": "配置已保存",
|
|
21
|
+
"search.description": "人才搜索",
|
|
22
|
+
"search.filter": "结构化过滤条件",
|
|
23
|
+
"search.source": "数据源,逗号分隔",
|
|
24
|
+
"search.top": "返回数量",
|
|
25
|
+
"job.description": "职位/案件管理",
|
|
26
|
+
"job.create": "从文件夹创建 JobCase",
|
|
27
|
+
"update.description": "检测并更新 CLI/Server/Extension/Rule",
|
|
28
|
+
"update.checking": "正在检查更新...",
|
|
29
|
+
"update.latest": "当前已是最新版本",
|
|
30
|
+
"extension.description": "浏览器扩展管理",
|
|
31
|
+
"extension.checkDescription": "检测扩展与本地 Server 的 WebSocket 连接",
|
|
32
|
+
"extension.connected": "WebSocket 连接正常",
|
|
33
|
+
"extension.timeout": "连接超时,请确认 server 是否启动",
|
|
34
|
+
"extension.error": "连接失败: {{message}}"
|
|
35
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
require("dotenv/config");
|
|
41
|
+
const commander_1 = require("commander");
|
|
42
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
+
const sentry_1 = require("./sentry");
|
|
44
|
+
const login_1 = require("./commands/login");
|
|
45
|
+
const logout_1 = require("./commands/logout");
|
|
46
|
+
const status_1 = require("./commands/status");
|
|
47
|
+
const config_1 = require("./commands/config");
|
|
48
|
+
const search_1 = require("./commands/search");
|
|
49
|
+
const job_1 = require("./commands/job");
|
|
50
|
+
const update_1 = require("./commands/update");
|
|
51
|
+
const extension_1 = require("./commands/extension");
|
|
52
|
+
const report_1 = require("./commands/report");
|
|
53
|
+
const record_1 = require("./commands/record");
|
|
54
|
+
const cache_1 = require("./commands/cache");
|
|
55
|
+
// 对应 ChromePilot 的新命令(环境管理 / 运维 / 扩展管理)
|
|
56
|
+
const init_1 = require("./commands/init");
|
|
57
|
+
const install_1 = require("./commands/install");
|
|
58
|
+
const server_1 = require("./commands/server");
|
|
59
|
+
const doctor_1 = require("./commands/doctor");
|
|
60
|
+
const extras_1 = require("./commands/extras");
|
|
61
|
+
const ops_1 = require("./commands/ops");
|
|
62
|
+
const addons_1 = require("./commands/addons");
|
|
63
|
+
const i18n_1 = require("./i18n");
|
|
64
|
+
(0, sentry_1.initSentry)();
|
|
65
|
+
const program = new commander_1.Command();
|
|
66
|
+
program
|
|
67
|
+
.name('hunter-mate')
|
|
68
|
+
.description(i18n_1.i18n.t('cli.description') + '(已对齐 ChromePilot: init/install/start/stop/status/recordings/control/adapter/run/memory/trace/autofix/external/plugin/skill/open-ext/doctor/reload)')
|
|
69
|
+
.version('0.1.0')
|
|
70
|
+
.option('--lang <lang>', i18n_1.i18n.t('cli.langOption'), 'zh-CN')
|
|
71
|
+
.hook('preAction', async (thisCommand) => {
|
|
72
|
+
const lang = thisCommand.opts().lang;
|
|
73
|
+
if (lang)
|
|
74
|
+
i18n_1.i18n.setLocale(lang);
|
|
75
|
+
// ADR-005 运行时一致性自动检测 + CLI 自更新(每次使用触发,版本判断):
|
|
76
|
+
// 1) CLI 自更新: 节流 1h 对比 npm registry,落后自动 npm install -g(下一条命令生效);
|
|
77
|
+
// dev 软链模式(wrapper 指向 hc-hw worktree dist)自动跳过。
|
|
78
|
+
// 2) server 在跑时对比磁盘版本 vs 运行版本,插件不一致 → reload,server 不一致 → 重启。
|
|
79
|
+
// HUNTER_MATE_NO_AUTOUPDATE=1 可禁用;update/start/stop 自行处理避免递归;
|
|
80
|
+
// server 未运行时一致性零成本跳过(本地 pid 探测,60s 节流)。
|
|
81
|
+
if (process.env.HUNTER_MATE_NO_AUTOUPDATE === '1')
|
|
82
|
+
return;
|
|
83
|
+
const name = thisCommand.name();
|
|
84
|
+
if (name === 'update' || name === 'start' || name === 'stop')
|
|
85
|
+
return;
|
|
86
|
+
try {
|
|
87
|
+
const { maybeCliSelfUpdate } = await Promise.resolve().then(() => __importStar(require('./updater')));
|
|
88
|
+
const upd = await maybeCliSelfUpdate();
|
|
89
|
+
for (const line of upd.logs)
|
|
90
|
+
console.log(chalk_1.default.gray(` [auto-update] ${line}`));
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
/* CLI 自更新检测永不阻塞主命令 */
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const { ensureRuntimeConsistency } = await Promise.resolve().then(() => __importStar(require('./version')));
|
|
97
|
+
const report = await ensureRuntimeConsistency({});
|
|
98
|
+
if (report.performed.length) {
|
|
99
|
+
for (const line of report.performed)
|
|
100
|
+
console.log(chalk_1.default.gray(` [auto-update] ${line}`));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
/* 一致性检测永不阻塞主命令 */
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
program.addCommand(init_1.initCommand);
|
|
108
|
+
program.addCommand(install_1.installCommand);
|
|
109
|
+
program.addCommand(server_1.startCommand);
|
|
110
|
+
program.addCommand(server_1.stopCommand);
|
|
111
|
+
program.addCommand(login_1.loginCommand);
|
|
112
|
+
program.addCommand(logout_1.logoutCommand);
|
|
113
|
+
program.addCommand(status_1.statusCommand);
|
|
114
|
+
program.addCommand(config_1.configCommand);
|
|
115
|
+
program.addCommand(search_1.searchCommand);
|
|
116
|
+
program.addCommand(job_1.jobCommand);
|
|
117
|
+
program.addCommand(update_1.updateCommand);
|
|
118
|
+
program.addCommand(extension_1.extensionCommand);
|
|
119
|
+
program.addCommand(ops_1.recordingsCommand);
|
|
120
|
+
program.addCommand(ops_1.adapterCommand);
|
|
121
|
+
program.addCommand(ops_1.memoryCommand);
|
|
122
|
+
program.addCommand(ops_1.traceCommand);
|
|
123
|
+
program.addCommand(ops_1.autofixCommand);
|
|
124
|
+
program.addCommand(addons_1.externalCommand);
|
|
125
|
+
program.addCommand(addons_1.pluginCommand);
|
|
126
|
+
program.addCommand(addons_1.skillCommand);
|
|
127
|
+
program.addCommand(extras_1.openExtCommand);
|
|
128
|
+
program.addCommand(doctor_1.doctorCommand);
|
|
129
|
+
program.addCommand(extras_1.reloadCommand);
|
|
130
|
+
program.addCommand(report_1.reportCommand);
|
|
131
|
+
program.addCommand(record_1.recordCommand);
|
|
132
|
+
program.addCommand(cache_1.cacheCommand);
|
|
133
|
+
program.parse();
|
package/dist/keychain.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.saveToken = saveToken;
|
|
37
|
+
exports.getToken = getToken;
|
|
38
|
+
exports.deleteToken = deleteToken;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const SERVICE = 'hunter-mate';
|
|
42
|
+
const ACCOUNT = 'user';
|
|
43
|
+
const HOME = process.env.HUNTER_MATE_HOME || process.env.HOME || process.env.USERPROFILE || '.';
|
|
44
|
+
const TOKEN_FILE = path.join(HOME, '.hunter-mate', 'token.json');
|
|
45
|
+
function fallbackSave(token) {
|
|
46
|
+
fs.mkdirSync(path.dirname(TOKEN_FILE), { recursive: true });
|
|
47
|
+
fs.writeFileSync(TOKEN_FILE, JSON.stringify({ token }), { mode: 0o600 });
|
|
48
|
+
}
|
|
49
|
+
function fallbackGet() {
|
|
50
|
+
if (!fs.existsSync(TOKEN_FILE))
|
|
51
|
+
return null;
|
|
52
|
+
try {
|
|
53
|
+
const data = JSON.parse(fs.readFileSync(TOKEN_FILE, 'utf-8'));
|
|
54
|
+
return data.token || null;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function fallbackDelete() {
|
|
61
|
+
if (fs.existsSync(TOKEN_FILE)) {
|
|
62
|
+
fs.unlinkSync(TOKEN_FILE);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function getKeytar() {
|
|
66
|
+
// Linux(尤其 headless/CI)上 keytar dlopen libsecret 会直接 SIGSEGV,
|
|
67
|
+
// try/catch 拦不住进程级段错误——一律文件降级(macOS Keychain / Windows 凭据管理器不受影响)
|
|
68
|
+
if (process.platform === 'linux')
|
|
69
|
+
return null;
|
|
70
|
+
try {
|
|
71
|
+
const mod = await Promise.resolve().then(() => __importStar(require('keytar')));
|
|
72
|
+
// ESM/CJS 混用:部分导出在 default 上
|
|
73
|
+
return mod.setPassword ? mod : mod.default || null;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async function saveToken(token) {
|
|
80
|
+
const keytar = await getKeytar();
|
|
81
|
+
if (keytar) {
|
|
82
|
+
try {
|
|
83
|
+
await keytar.setPassword(SERVICE, ACCOUNT, token);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// 降级到文件
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
fallbackSave(token);
|
|
91
|
+
}
|
|
92
|
+
async function getToken() {
|
|
93
|
+
const keytar = await getKeytar();
|
|
94
|
+
if (keytar) {
|
|
95
|
+
try {
|
|
96
|
+
const token = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
97
|
+
if (token)
|
|
98
|
+
return token;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// 降级
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return fallbackGet();
|
|
105
|
+
}
|
|
106
|
+
async function deleteToken() {
|
|
107
|
+
const keytar = await getKeytar();
|
|
108
|
+
if (keytar) {
|
|
109
|
+
try {
|
|
110
|
+
await keytar.deletePassword(SERVICE, ACCOUNT);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// 忽略 keychain 错误,继续清理本地文件
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
fallbackDelete();
|
|
117
|
+
}
|
package/dist/sentry.d.ts
ADDED
package/dist/sentry.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Sentry = void 0;
|
|
37
|
+
exports.initSentry = initSentry;
|
|
38
|
+
const Sentry = __importStar(require("@sentry/node"));
|
|
39
|
+
exports.Sentry = Sentry;
|
|
40
|
+
function initSentry() {
|
|
41
|
+
const dsn = process.env.HM_ERROR_TRACKING_DSN;
|
|
42
|
+
const enabled = process.env.HM_ERROR_TRACKING_ENABLED === 'true';
|
|
43
|
+
if (!enabled || !dsn)
|
|
44
|
+
return;
|
|
45
|
+
Sentry.init({
|
|
46
|
+
dsn,
|
|
47
|
+
release: process.env.HM_RELEASE,
|
|
48
|
+
environment: process.env.HM_ENVIRONMENT || 'development',
|
|
49
|
+
tracesSampleRate: 0,
|
|
50
|
+
sendClientReports: false,
|
|
51
|
+
beforeSend(event) {
|
|
52
|
+
if (event.request?.headers) {
|
|
53
|
+
const headers = event.request.headers;
|
|
54
|
+
if (headers.authorization)
|
|
55
|
+
headers.authorization = '***';
|
|
56
|
+
if (headers.cookie)
|
|
57
|
+
headers.cookie = '***';
|
|
58
|
+
}
|
|
59
|
+
return event;
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 判定是否开发软链模式(纯函数,便于单测):
|
|
3
|
+
* 包根路径含 /worktrees/ 段(hc-hw local worktree 布局)或 HUNTER_MATE_DEV=1。
|
|
4
|
+
* 注意:GitHub Release 二进制安装(~/.hunter-mate/bin)不属于 dev 模式。
|
|
5
|
+
*/
|
|
6
|
+
export declare function computeDevLinked(pkgRoot: string): boolean;
|
|
7
|
+
export declare function isDevLinked(): boolean;
|
|
8
|
+
/** npm registry 查询最新版本(spawnSync,不占用 axios mock 队列);失败返回 null */
|
|
9
|
+
export declare function npmLatestVersion(pkg?: string): string | null;
|
|
10
|
+
/** 自更新: npm install -g <pkg>@latest(运行中的进程无法替换,新命令生效) */
|
|
11
|
+
export declare function npmSelfUpdate(pkg?: string): {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
msg: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function updateCheckIntervalMs(): number;
|
|
16
|
+
export declare function shouldCheckUpdate(stateFile?: string, now?: number, intervalMs?: number): boolean;
|
|
17
|
+
export declare function markUpdateChecked(stateFile?: string): void;
|
|
18
|
+
export interface CliUpdateOutcome {
|
|
19
|
+
logs: string[];
|
|
20
|
+
devSkipped: boolean;
|
|
21
|
+
updated: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function maybeCliSelfUpdate(): Promise<CliUpdateOutcome>;
|
package/dist/updater.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.computeDevLinked = computeDevLinked;
|
|
37
|
+
exports.isDevLinked = isDevLinked;
|
|
38
|
+
exports.npmLatestVersion = npmLatestVersion;
|
|
39
|
+
exports.npmSelfUpdate = npmSelfUpdate;
|
|
40
|
+
exports.updateCheckIntervalMs = updateCheckIntervalMs;
|
|
41
|
+
exports.shouldCheckUpdate = shouldCheckUpdate;
|
|
42
|
+
exports.markUpdateChecked = markUpdateChecked;
|
|
43
|
+
exports.maybeCliSelfUpdate = maybeCliSelfUpdate;
|
|
44
|
+
/**
|
|
45
|
+
* CLI 自动更新(使用态)与开发模式识别(与 chromepilot updater 对齐)。
|
|
46
|
+
*
|
|
47
|
+
* 设计(ADR-005 延伸):
|
|
48
|
+
* - 每次命令使用时(preAction)节流(默认 1h)对比 npm registry 最新版本,落后则自动
|
|
49
|
+
* `npm install -g hunter-mate@latest`;运行中的进程无法替换自身,下一条命令起生效。
|
|
50
|
+
* - 开发软链模式(wrapper 指向 hc-hw local worktree dist)跳过 CLI 自更新,由开发者
|
|
51
|
+
* `pnpm build` 控制;server/插件/扩展的一致性 reload/restart 不受影响(version.ts)。
|
|
52
|
+
* - 逃生开关:
|
|
53
|
+
* - HUNTER_MATE_NO_AUTOUPDATE=1 关闭全部自动更新(CLI + 一致性,preAction 层)
|
|
54
|
+
* - HUNTER_MATE_UPDATE_CHECK_INTERVAL_MS 覆盖节流间隔(默认 3600000)
|
|
55
|
+
* - HUNTER_MATE_DEV=1 强制视为 dev 模式(测试用)
|
|
56
|
+
*/
|
|
57
|
+
const fs = __importStar(require("fs"));
|
|
58
|
+
const path = __importStar(require("path"));
|
|
59
|
+
const child_process_1 = require("child_process");
|
|
60
|
+
const version_1 = require("./version");
|
|
61
|
+
const HOME = () => process.env.HUNTER_MATE_HOME || process.env.HOME || process.env.USERPROFILE || '.';
|
|
62
|
+
const ROOT = () => path.join(HOME(), '.hunter-mate');
|
|
63
|
+
const LAST_CHECK_FILE = () => path.join(ROOT(), '.last-cli-update-check');
|
|
64
|
+
const NPM_PACKAGE = 'hunter-mate';
|
|
65
|
+
const DEFAULT_INTERVAL_MS = 60 * 60 * 1000;
|
|
66
|
+
/**
|
|
67
|
+
* 判定是否开发软链模式(纯函数,便于单测):
|
|
68
|
+
* 包根路径含 /worktrees/ 段(hc-hw local worktree 布局)或 HUNTER_MATE_DEV=1。
|
|
69
|
+
* 注意:GitHub Release 二进制安装(~/.hunter-mate/bin)不属于 dev 模式。
|
|
70
|
+
*/
|
|
71
|
+
function computeDevLinked(pkgRoot) {
|
|
72
|
+
if (process.env.HUNTER_MATE_DEV === '1')
|
|
73
|
+
return true;
|
|
74
|
+
return path.normalize(pkgRoot).includes(`${path.sep}worktrees${path.sep}`);
|
|
75
|
+
}
|
|
76
|
+
function isDevLinked() {
|
|
77
|
+
return computeDevLinked(path.join(__dirname, '..'));
|
|
78
|
+
}
|
|
79
|
+
/** npm registry 查询最新版本(spawnSync,不占用 axios mock 队列);失败返回 null */
|
|
80
|
+
function npmLatestVersion(pkg = NPM_PACKAGE) {
|
|
81
|
+
try {
|
|
82
|
+
const r = (0, child_process_1.spawnSync)('npm', ['view', pkg, 'version'], {
|
|
83
|
+
encoding: 'utf-8',
|
|
84
|
+
timeout: 15_000,
|
|
85
|
+
});
|
|
86
|
+
if (r.status === 0 && r.stdout)
|
|
87
|
+
return r.stdout.trim() || null;
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** 自更新: npm install -g <pkg>@latest(运行中的进程无法替换,新命令生效) */
|
|
95
|
+
function npmSelfUpdate(pkg = NPM_PACKAGE) {
|
|
96
|
+
const r = (0, child_process_1.spawnSync)('npm', ['install', '-g', `${pkg}@latest`], {
|
|
97
|
+
stdio: 'inherit',
|
|
98
|
+
timeout: 120_000,
|
|
99
|
+
});
|
|
100
|
+
if (r.status === 0) {
|
|
101
|
+
return { ok: true, msg: `npm install -g ${pkg}@latest 完成,下一条命令起使用新版本` };
|
|
102
|
+
}
|
|
103
|
+
return { ok: false, msg: `npm install -g ${pkg}@latest 失败 (exit=${r.status}),可手动执行` };
|
|
104
|
+
}
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// 节流
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
function updateCheckIntervalMs() {
|
|
109
|
+
const v = Number(process.env.HUNTER_MATE_UPDATE_CHECK_INTERVAL_MS);
|
|
110
|
+
return Number.isFinite(v) && v > 0 ? v : DEFAULT_INTERVAL_MS;
|
|
111
|
+
}
|
|
112
|
+
function shouldCheckUpdate(stateFile = LAST_CHECK_FILE(), now = Date.now(), intervalMs = updateCheckIntervalMs()) {
|
|
113
|
+
try {
|
|
114
|
+
const stat = fs.statSync(stateFile);
|
|
115
|
+
return now - stat.mtimeMs > intervalMs;
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function markUpdateChecked(stateFile = LAST_CHECK_FILE()) {
|
|
122
|
+
try {
|
|
123
|
+
fs.mkdirSync(path.dirname(stateFile), { recursive: true });
|
|
124
|
+
fs.writeFileSync(stateFile, String(Date.now()));
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
/* 尽力 */
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function maybeCliSelfUpdate() {
|
|
131
|
+
const logs = [];
|
|
132
|
+
const outcome = { logs, devSkipped: false, updated: false };
|
|
133
|
+
try {
|
|
134
|
+
if (isDevLinked()) {
|
|
135
|
+
outcome.devSkipped = true;
|
|
136
|
+
logs.push('dev 软链模式,跳过 CLI 自更新(改代码请 pnpm build;一致性 reload/restart 不受影响)');
|
|
137
|
+
return outcome;
|
|
138
|
+
}
|
|
139
|
+
if (!shouldCheckUpdate())
|
|
140
|
+
return outcome;
|
|
141
|
+
markUpdateChecked();
|
|
142
|
+
const installed = (0, version_1.readInstalledVersions)().cli;
|
|
143
|
+
if (!installed || installed === '0.0.0')
|
|
144
|
+
return outcome;
|
|
145
|
+
const latest = npmLatestVersion();
|
|
146
|
+
if (!latest) {
|
|
147
|
+
logs.push(`npm registry 查询 ${NPM_PACKAGE} 失败,本次跳过自更新`);
|
|
148
|
+
return outcome;
|
|
149
|
+
}
|
|
150
|
+
if (latest === installed)
|
|
151
|
+
return outcome;
|
|
152
|
+
logs.push(`CLI 自更新: ${installed} → ${latest}`);
|
|
153
|
+
const r = npmSelfUpdate();
|
|
154
|
+
logs.push(r.msg);
|
|
155
|
+
outcome.updated = r.ok;
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
logs.push(`自动更新检测异常(不影响命令执行): ${err instanceof Error ? err.message : String(err)}`);
|
|
159
|
+
}
|
|
160
|
+
return outcome;
|
|
161
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ConsistencyActions, InstalledVersions, SystemVersions } from '@hunter-mate/shared';
|
|
2
|
+
export declare function readInstalledVersions(): InstalledVersions;
|
|
3
|
+
export declare function readRuntimeStateFile(): any;
|
|
4
|
+
export declare function fetchLiveVersions(timeoutMs?: number): Promise<SystemVersions | null>;
|
|
5
|
+
export declare function decideConsistencyActions(installed: InstalledVersions, live: SystemVersions | null): ConsistencyActions;
|
|
6
|
+
export interface ConsistencyReport {
|
|
7
|
+
checked: boolean;
|
|
8
|
+
reason?: string;
|
|
9
|
+
actions: ConsistencyActions;
|
|
10
|
+
performed: string[];
|
|
11
|
+
}
|
|
12
|
+
export declare function ensureRuntimeConsistency(opts?: {
|
|
13
|
+
force?: boolean;
|
|
14
|
+
verbose?: boolean;
|
|
15
|
+
}): Promise<ConsistencyReport>;
|
|
16
|
+
export declare function shouldCheckNow(): boolean;
|