hunter-mate 0.1.12 → 0.1.14
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/assets/extension/background/service-worker.js +7 -0
- package/dist/assets/extension/build-info.json +1 -1
- package/dist/assets/extension/content/index.js +4 -3
- package/dist/assets/extension/manifest.json +1 -1
- package/dist/assets/extension/sidepanel/index.css +1 -1
- package/dist/assets/extension/sidepanel/index.js +30 -8
- package/dist/assets/server/app.module.js +4 -1
- package/dist/assets/server/app.module.js.map +1 -1
- package/dist/assets/server/auth/auth.controller.d.ts +14 -0
- package/dist/assets/server/auth/auth.controller.js +19 -0
- package/dist/assets/server/auth/auth.controller.js.map +1 -1
- package/dist/assets/server/auth/auth.module.js +4 -1
- package/dist/assets/server/auth/auth.module.js.map +1 -1
- package/dist/assets/server/auth/auth.service.d.ts +18 -1
- package/dist/assets/server/auth/auth.service.js +65 -2
- package/dist/assets/server/auth/auth.service.js.map +1 -1
- package/dist/assets/server/auth/saas-token.entity.d.ts +7 -0
- package/dist/assets/server/auth/saas-token.entity.js +46 -0
- package/dist/assets/server/auth/saas-token.entity.js.map +1 -0
- package/dist/assets/server/build-info.json +1 -1
- package/dist/assets/server/datasync/datasync.module.d.ts +2 -0
- package/dist/assets/server/datasync/datasync.module.js +26 -0
- package/dist/assets/server/datasync/datasync.module.js.map +1 -0
- package/dist/assets/server/datasync/datasync.service.d.ts +50 -0
- package/dist/assets/server/datasync/datasync.service.js +389 -0
- package/dist/assets/server/datasync/datasync.service.js.map +1 -0
- package/dist/assets/server/datasync/entities/sync-conflict.entity.d.ts +10 -0
- package/dist/assets/server/datasync/entities/sync-conflict.entity.js +61 -0
- package/dist/assets/server/datasync/entities/sync-conflict.entity.js.map +1 -0
- package/dist/assets/server/datasync/entities/sync-cursor.entity.d.ts +9 -0
- package/dist/assets/server/datasync/entities/sync-cursor.entity.js +56 -0
- package/dist/assets/server/datasync/entities/sync-cursor.entity.js.map +1 -0
- package/dist/assets/server/datasync/registry.d.ts +8 -0
- package/dist/assets/server/datasync/registry.js +55 -0
- package/dist/assets/server/datasync/registry.js.map +1 -0
- package/dist/assets/server/db/sqlite.module.js +6 -0
- package/dist/assets/server/db/sqlite.module.js.map +1 -1
- package/dist/assets/server/package.json +1 -0
- package/dist/commands/doctor.js +46 -0
- package/dist/commands/ops.js +45 -8
- package/dist/commands/update.js +5 -5
- package/dist/index.js +5 -1
- package/dist/updater.d.ts +95 -2
- package/dist/updater.js +372 -32
- package/dist/web/dist/404.html +1 -1
- package/dist/web/dist/_next/static/chunks/{539-5d0e8c5c238c56f8.js → 539-cd9d7c0ee78f8874.js} +1 -1
- package/dist/web/dist/_next/static/chunks/app/auth/verify/page-f13c66b48f7cf13e.js +1 -0
- package/dist/web/dist/_next/static/chunks/app/matching/jobs/[id]/talents/{page-f57f4b7529823601.js → page-cdf1ed0971999f35.js} +1 -1
- package/dist/web/dist/_next/static/chunks/app/matching/portraits/[id]/jobs/page-87f04f1d61b94cb2.js +1 -0
- package/dist/web/dist/_next/static/chunks/app/page-affa1ffde089f1dd.js +1 -0
- package/dist/web/dist/_next/static/chunks/app/parselog/{page-58d3acece95b4089.js → page-31d3630d611649f7.js} +1 -1
- package/dist/web/dist/_next/static/chunks/app/recordings/{page-e2e2e3c3a64083fb.js → page-9cdefceb2bff613f.js} +1 -1
- package/dist/web/dist/_next/static/chunks/app/snapshots/[id]/agent-prompt/page-6996f7f221b1a7eb.js +1 -0
- package/dist/web/dist/_next/static/chunks/{main-app-0af848156a5b13fc.js → main-app-cb4554c86eba200c.js} +1 -1
- package/dist/web/dist/_next/static/chunks/pages/{_app-3d844792ec91e4d1.js → _app-834b8a94a4a3c493.js} +2 -2
- package/dist/web/dist/_next/static/css/{db881c5b3072b88a.css → b7097b50a6497650.css} +1 -1
- package/dist/web/dist/auth/verify.html +1 -1
- package/dist/web/dist/auth/verify.txt +2 -2
- package/dist/web/dist/companies.html +1 -1
- package/dist/web/dist/companies.txt +2 -2
- package/dist/web/dist/entity.html +1 -1
- package/dist/web/dist/entity.txt +1 -1
- package/dist/web/dist/index.html +1 -1
- package/dist/web/dist/index.txt +2 -2
- package/dist/web/dist/jobs.html +1 -1
- package/dist/web/dist/jobs.txt +2 -2
- package/dist/web/dist/logs.html +1 -1
- package/dist/web/dist/logs.txt +1 -1
- package/dist/web/dist/matching/jobs/placeholder/talents.html +1 -1
- package/dist/web/dist/matching/jobs/placeholder/talents.txt +2 -2
- package/dist/web/dist/matching/portraits/placeholder/jobs.html +1 -1
- package/dist/web/dist/matching/portraits/placeholder/jobs.txt +2 -2
- package/dist/web/dist/parselog.html +1 -1
- package/dist/web/dist/parselog.txt +2 -2
- package/dist/web/dist/recordings.html +1 -1
- package/dist/web/dist/recordings.txt +2 -2
- package/dist/web/dist/snapshots/placeholder/agent-prompt.html +1 -1
- package/dist/web/dist/snapshots/placeholder/agent-prompt.txt +2 -2
- package/dist/web/dist/talents.html +1 -1
- package/dist/web/dist/talents.txt +2 -2
- package/package.json +3 -2
- package/dist/web/dist/_next/static/chunks/app/auth/verify/page-8e5cff53d6f7d8e1.js +0 -1
- package/dist/web/dist/_next/static/chunks/app/matching/portraits/[id]/jobs/page-614d1e62d7b9d215.js +0 -1
- package/dist/web/dist/_next/static/chunks/app/page-e3392de08ae81fba.js +0 -1
- package/dist/web/dist/_next/static/chunks/app/snapshots/[id]/agent-prompt/page-fd3b7d7373b8f8b7.js +0 -1
- /package/dist/web/dist/_next/static/{RSIT2tCOW5--9YD-rmuF7 → ZJtEh3uyN_mQhaXvrDYzJ}/_buildManifest.js +0 -0
- /package/dist/web/dist/_next/static/{RSIT2tCOW5--9YD-rmuF7 → ZJtEh3uyN_mQhaXvrDYzJ}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.module.js","sourceRoot":"","sources":["../../src/db/sqlite.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,2CAA6D;AAC7D,yBAAyB;AACzB,6BAA6B;AAC7B,2DAAgE;AAChE,yFAA8E;AAC9E,8DAAoD;AACpD,iFAAsE;AACtE,8FAAmF;AACnF,yEAA8D;AAC9D,gFAAqE;AACrE,sFAA2E;AAC3E,+FAAoF;AACpF,yFAA6E;AAC7E,2DAAiD;AACjD,oFAAwE;AACxE,gFAAqE;AACrE,8EAAmE;AACnE,wFAA6E;AAC7E,kFAAuE;AACvE,0FAA+E;AAC/E,+FAAoF;AACpF,oFAAyE;AACzE,mEAAwD;AACxD,yEAAoE;AACpE,iEAAuD;AACvD,uEAA6D;AAC7D,2EAAgE;AAEhE,MAAM,IAAI,GAAG,GAAG,EAAE,CAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC;AAM9E,MAAM,OAAO,GAAG,GAAG,EAAE,CAC1B,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;AADlD,QAAA,OAAO,WAC2C;
|
|
1
|
+
{"version":3,"file":"sqlite.module.js","sourceRoot":"","sources":["../../src/db/sqlite.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,2CAA6D;AAC7D,yBAAyB;AACzB,6BAA6B;AAC7B,2DAAgE;AAChE,yFAA8E;AAC9E,8DAAoD;AACpD,iFAAsE;AACtE,8FAAmF;AACnF,yEAA8D;AAC9D,gFAAqE;AACrE,sFAA2E;AAC3E,+FAAoF;AACpF,yFAA6E;AAC7E,2DAAiD;AACjD,oFAAwE;AACxE,gFAAqE;AACrE,8EAAmE;AACnE,wFAA6E;AAC7E,kFAAuE;AACvE,0FAA+E;AAC/E,+FAAoF;AACpF,oFAAyE;AACzE,mEAAwD;AACxD,yEAAoE;AACpE,iEAAsD;AACtD,gFAAqE;AACrE,oFAAyE;AACzE,iEAAuD;AACvD,uEAA6D;AAC7D,2EAAgE;AAEhE,MAAM,IAAI,GAAG,GAAG,EAAE,CAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC;AAM9E,MAAM,OAAO,GAAG,GAAG,EAAE,CAC1B,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;AADlD,QAAA,OAAO,WAC2C;AAkExD,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IAvDxB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,uBAAa,CAAC,YAAY,CAAC;gBACzB,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,MAAM,EAAE,CAAC,sBAAa,CAAC;gBACvB,UAAU,EAAE,CAAC,MAAqB,EAAE,EAAE;oBACpC,MAAM,MAAM,GACV,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;wBACzB,IAAI,CAAC,IAAI,CAAC,IAAA,eAAO,GAAE,EAAE,gBAAgB,CAAC,CAAC;oBACzC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;oBACxD,OAAO;wBACL,IAAI,EAAE,gBAAyB;wBAC/B,QAAQ,EAAE,MAAM;wBAChB,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,KAAK,OAAO;wBACjE,QAAQ,EAAE;4BACR,uCAAc;4BACd,wBAAO;4BACP,uCAAc;4BACd,iDAAmB;4BACnB,iCAAW;4BACX,mCAAY;4BACZ,uCAAc;4BACd,6CAAiB;4BACjB,wCAAc;4BACd,sBAAM;4BACN,4CAAgB;4BAChB,mCAAY;4BACZ,2BAAQ;4BACR,qCAAa;4BACb,+BAAU;4BACV,uCAAc;4BACd,6CAAiB;4BACjB,iCAAW;4BACX,qCAAa;4BACb,0BAAQ;4BACR,8BAAU;4BAEV,iCAAW;4BAIX,uBAAc;4BAEd,6BAAS;4BACT,+BAAU;4BACV,mCAAY;yBACb;qBACF,CAAC;gBACJ,CAAC;aACF,CAAC;YACF,uBAAa,CAAC,UAAU,CAAC,CAAC,qCAAa,CAAC,CAAC;SAC1C;QACD,SAAS,EAAE,CAAC,iDAAsB,CAAC;QACnC,OAAO,EAAE,CAAC,iDAAsB,CAAC;KAClC,CAAC;GACW,YAAY,CAAG"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -88,6 +88,52 @@ export async function runDoctor(opts) {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
catch { /* 检测失败不阻断 doctor */ }
|
|
91
|
+
// ── 0.6) 孤儿 CLI 安装清理(断点 2 现场:运行中的 CLI 是 npm -g 全局安装,
|
|
92
|
+
// ~/.hunter-mate/cli 里却残留一份完整安装——自更新每小时往这个孤儿目录
|
|
93
|
+
// 重复装新版,用户永远跑旧版。检测:运行包根不在 cliPrefix 内 +
|
|
94
|
+
// cliPrefix/node_modules/hunter-mate/package.json 存在) ──
|
|
95
|
+
try {
|
|
96
|
+
const { detectOrphanPrefixInstall } = await import('../updater.js');
|
|
97
|
+
const { resolveDataDir } = await import('../config.js');
|
|
98
|
+
const orphan = detectOrphanPrefixInstall();
|
|
99
|
+
if (orphan.orphan) {
|
|
100
|
+
const cliPrefix = path.join(resolveDataDir(), 'cli');
|
|
101
|
+
const orphanVer = (() => {
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(fs.readFileSync(path.join(cliPrefix, 'node_modules', 'hunter-mate', 'package.json'), 'utf-8')).version ?? '?';
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return '?';
|
|
107
|
+
}
|
|
108
|
+
})();
|
|
109
|
+
checks.push({
|
|
110
|
+
key: 'orphan_cli_install',
|
|
111
|
+
status: 'warn',
|
|
112
|
+
detail: `运行中的 CLI 装在 ${orphan.runPkgRoot},但 ${cliPrefix} 残留一份 ${orphanVer} 完整安装(孤儿)。自动更新会错误地装进该目录而非运行入口,建议清理`,
|
|
113
|
+
});
|
|
114
|
+
// 删除目录是有损操作:只随显式 --fix 执行,不随 autoHeal 默认开启
|
|
115
|
+
if (fix) {
|
|
116
|
+
const { moveEntry } = await import('./migrate.js');
|
|
117
|
+
const trashDir = path.join(resolveDataDir(), 'trash', `cli-${Date.now()}`);
|
|
118
|
+
try {
|
|
119
|
+
moveEntry(cliPrefix, trashDir);
|
|
120
|
+
checks.push({ key: 'orphan_cli_cleanup', status: 'ok', detail: `已移入 ${trashDir}(可手动回滚,确认无用后可删除)` });
|
|
121
|
+
healed.push('cleanup_orphan_cli');
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
// Windows 上若孤儿目录内文件被占用(npm/node 进程),rename 会 EPERM
|
|
125
|
+
checks.push({ key: 'orphan_cli_cleanup', status: 'warn', detail: `清理失败: ${e.message}(请关闭可能占用该目录的进程后重试 hunter-mate doctor --fix)` });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
hints.push('运行 hunter-mate doctor --fix 清理孤儿 CLI 安装(移入 trash 目录,可回滚)');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
checks.push({ key: 'orphan_cli_install', status: 'ok', detail: `无孤儿 CLI 安装(运行入口: ${orphan.runPkgRoot})` });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch { /* 检测失败不阻断 doctor */ }
|
|
91
137
|
// ── 1) 目录 & token ──
|
|
92
138
|
let initResult = null;
|
|
93
139
|
try {
|
package/dist/commands/ops.js
CHANGED
|
@@ -36,38 +36,75 @@ const printResult = (data, format) => {
|
|
|
36
36
|
export const recordingsCommand = new Command('recordings').description('管理录制会话(rrweb/network/console 事件流)');
|
|
37
37
|
recordingsCommand
|
|
38
38
|
.command('start')
|
|
39
|
-
.description('开始录制: 生成新 sessionId
|
|
39
|
+
.description('开始录制: 生成新 sessionId,注册会话;带 --tab 时经 server 广播通知该 tab 的扩展开始上报事件')
|
|
40
40
|
.requiredOption('--title <text>', '录制标题,例如 LinkedIn 寻访 2026-08-15')
|
|
41
41
|
.option('--tags <csv>', '标签,逗号分隔')
|
|
42
|
+
.option('--tab <pageId>', '目标 tab id(chromepilot page id);通知该 tab 的扩展立即开录,事件即以本 sessionId 上报')
|
|
42
43
|
.action(async (opts) => {
|
|
43
|
-
// MVP: 直接调用 server 的 recordings POST 端点(若存在)或返回本地 sessionId 交给扩展
|
|
44
44
|
const sessionId = 'sess_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
45
|
+
// 注册会话(server REST 未就绪时忽略,扩展事件到达时会自动建)
|
|
45
46
|
try {
|
|
46
47
|
await http().post(`/api/recordings/${sessionId}/events`, []);
|
|
47
48
|
}
|
|
48
49
|
catch {
|
|
49
50
|
/* 忽略: server REST 未就绪也允许本地启动 */
|
|
50
51
|
}
|
|
52
|
+
// CLI → server 广播 → 扩展:让目标 tab 的 content script 以本 sessionId 开录
|
|
53
|
+
let relay = null;
|
|
54
|
+
if (opts.tab) {
|
|
55
|
+
try {
|
|
56
|
+
const r = await http().post('/system/broadcast-extension', {
|
|
57
|
+
payload: { type: 'start-recording', sessionId, tabId: Number(opts.tab) },
|
|
58
|
+
});
|
|
59
|
+
relay = { broadcast: r.data?.broadcast ?? 0, queued: !!r.data?.queued, errors: r.data?.errors };
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
relay = { broadcast: 0, queued: false, errors: [{ extensionId: '-', error: e?.message ?? String(e) }] };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
51
65
|
console.log(JSON.stringify({
|
|
52
66
|
sessionId,
|
|
53
67
|
title: opts.title,
|
|
54
68
|
tags: opts.tags ? opts.tags.split(',').map((s) => s.trim()) : [],
|
|
69
|
+
tab: opts.tab ? Number(opts.tab) : null,
|
|
70
|
+
relay,
|
|
55
71
|
startedAt: new Date().toISOString(),
|
|
56
|
-
next:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
72
|
+
next: opts.tab
|
|
73
|
+
? [
|
|
74
|
+
`扩展已被通知开录(tab ${opts.tab});操作页面后 \`hunter-mate recordings stop ${sessionId} --tab ${opts.tab}\` 停止,`,
|
|
75
|
+
`再 \`hunter-mate recordings show ${sessionId} --parse\` 解析。`,
|
|
76
|
+
].join('')
|
|
77
|
+
: [
|
|
78
|
+
'未指定 --tab:扩展未收到开录通知,本 sessionId 不会有事件上报。',
|
|
79
|
+
'两种补救:① 重跑带 --tab <pageId>;② 在 sidepanel 手动点开始录制(扩展自生成 sessionId,',
|
|
80
|
+
'用 recordings list 查到后再 show <那个sid> --parse)。',
|
|
81
|
+
].join(''),
|
|
60
82
|
}, null, 2));
|
|
61
83
|
});
|
|
62
84
|
recordingsCommand
|
|
63
85
|
.command('stop')
|
|
64
86
|
.argument('<sessionId>', '会话 ID')
|
|
87
|
+
.option('--tab <pageId>', '目标 tab id;通知该 tab 的扩展停止上报(软标记之外的实际停录)')
|
|
65
88
|
.description('停止录制(软标记,不再接受新事件)')
|
|
66
|
-
.action(async (sessionId) => {
|
|
89
|
+
.action(async (sessionId, opts) => {
|
|
90
|
+
let relay = null;
|
|
91
|
+
if (opts.tab) {
|
|
92
|
+
try {
|
|
93
|
+
const r = await http().post('/system/broadcast-extension', {
|
|
94
|
+
payload: { type: 'stop-recording', sessionId, tabId: Number(opts.tab) },
|
|
95
|
+
});
|
|
96
|
+
relay = { broadcast: r.data?.broadcast ?? 0, queued: !!r.data?.queued, errors: r.data?.errors };
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
relay = { broadcast: 0, queued: false, errors: [{ extensionId: '-', error: e?.message ?? String(e) }] };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
67
102
|
console.log(JSON.stringify({
|
|
68
103
|
sessionId,
|
|
104
|
+
tab: opts.tab ? Number(opts.tab) : null,
|
|
105
|
+
relay,
|
|
69
106
|
stoppedAt: new Date().toISOString(),
|
|
70
|
-
detail: 'stop
|
|
107
|
+
detail: 'stop 是软标记 + 可选扩展停录通知。可通过 POST /api/recordings/:sessionId/parse 触发后端解析。',
|
|
71
108
|
}, null, 2));
|
|
72
109
|
});
|
|
73
110
|
withFormat(recordingsCommand.command('list').description('列出录制会话(从 /api/recordings 端点)'))
|
package/dist/commands/update.js
CHANGED
|
@@ -8,7 +8,7 @@ import { i18n } from '../i18n/index.js';
|
|
|
8
8
|
import { getCliLogger } from '../logger.js';
|
|
9
9
|
import chalk from 'chalk';
|
|
10
10
|
import { readInstalledVersions, ensureRuntimeConsistency } from '../version.js';
|
|
11
|
-
import { isDevLinked,
|
|
11
|
+
import { isDevLinked, npmLatestVersionRobust, npmSelfUpdate } from '../updater.js';
|
|
12
12
|
const RULES_DIR = () => path.join(resolveDataDir(), 'rules');
|
|
13
13
|
const VERSION_FILE = () => path.join(RULES_DIR(), 'version.json');
|
|
14
14
|
function loadLocalVersion() {
|
|
@@ -95,17 +95,17 @@ export const updateCommand = new Command('update')
|
|
|
95
95
|
console.log(chalk.gray(`dev 软链模式,跳过 CLI 自更新(改代码请 pnpm build);继续执行一致性修复`));
|
|
96
96
|
}
|
|
97
97
|
else if (channel === 'npm') {
|
|
98
|
-
const latest =
|
|
98
|
+
const { version: latest, detail } = await npmLatestVersionRobust(npmPackage);
|
|
99
99
|
if (!latest) {
|
|
100
|
-
console.log(chalk.yellow(`npm registry 查询 ${npmPackage}
|
|
100
|
+
console.log(chalk.yellow(`npm registry 查询 ${npmPackage} 失败(${detail}),跳过自更新`));
|
|
101
101
|
}
|
|
102
102
|
else if (latest === installed.cli) {
|
|
103
103
|
console.log(chalk.gray(`CLI 已是最新: ${installed.cli}`));
|
|
104
104
|
}
|
|
105
105
|
else {
|
|
106
106
|
console.log(chalk.cyan(`CLI 自更新: ${installed.cli} → ${latest}`));
|
|
107
|
-
const r = await npmSelfUpdate(npmPackage);
|
|
108
|
-
console.log(r.ok ? chalk.green(r.msg) : chalk.yellow(r.msg));
|
|
107
|
+
const r = await npmSelfUpdate(npmPackage, latest);
|
|
108
|
+
console.log(r.ok && r.verified !== false ? chalk.green(r.msg) : chalk.yellow(r.msg));
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
// ---- server / 插件 / 扩展 一致性修复(插件 reload / server 重启 / 扩展广播 reload) ----
|
package/dist/index.js
CHANGED
|
@@ -107,9 +107,11 @@ program
|
|
|
107
107
|
else
|
|
108
108
|
console.log(text);
|
|
109
109
|
};
|
|
110
|
+
let cliUpdated = false;
|
|
110
111
|
try {
|
|
111
112
|
const { maybeCliSelfUpdate } = await import('./updater.js');
|
|
112
113
|
const upd = await maybeCliSelfUpdate();
|
|
114
|
+
cliUpdated = upd.updated === true;
|
|
113
115
|
for (const line of upd.logs)
|
|
114
116
|
notify(line);
|
|
115
117
|
}
|
|
@@ -118,7 +120,9 @@ program
|
|
|
118
120
|
}
|
|
119
121
|
try {
|
|
120
122
|
const { ensureRuntimeConsistency } = await import('./version.js');
|
|
121
|
-
|
|
123
|
+
// 刚完成 CLI 自更新:force+verbose 跑一次,让扩展 reload / server 重启 / 插件 reload
|
|
124
|
+
// 立即生效并逐行可见;未更新时维持 60s 节流轻量检查,不放大每条命令的副作用
|
|
125
|
+
const report = await ensureRuntimeConsistency(cliUpdated ? { force: true, verbose: true } : {});
|
|
122
126
|
if (report.performed.length) {
|
|
123
127
|
for (const line of report.performed)
|
|
124
128
|
notify(line);
|
package/dist/updater.d.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 七牛 CDN 发布镜像(hcweb-temp-file bucket,hunter-mate-releases/ 前缀)。
|
|
3
|
+
* 工厂 pnpm-release 发布后上传 tgz + latest.json,并只保留最近 5 个版本;
|
|
4
|
+
* npm registry 不可达时(国内网络/Windows 现场)CLI 回退到这里查版本与下载。
|
|
5
|
+
* 覆盖方式:HUNTER_MATE_CDN_BASE(测试/内网镜像用)。
|
|
6
|
+
*/
|
|
7
|
+
export declare const CDN_RELEASES_BASE: string;
|
|
8
|
+
export interface CdnReleaseManifest {
|
|
9
|
+
version: string;
|
|
10
|
+
tgz: string;
|
|
11
|
+
publishedAt?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 从 CDN 读 latest.json 发布清单(10s 超时,proxy:false 绕开死代理)。
|
|
15
|
+
* 工厂上传脚本负责维护该文件;不存在/解析失败返回 null。
|
|
16
|
+
*/
|
|
17
|
+
export declare function fetchCdnLatestManifest(): Promise<CdnReleaseManifest | null>;
|
|
1
18
|
/**
|
|
2
19
|
* 判定是否开发软链模式(纯函数,便于单测):
|
|
3
20
|
* 包根路径含 /worktrees/ 段(hc-hw local worktree 布局)或 HUNTER_MATE_DEV=1。
|
|
@@ -5,15 +22,91 @@
|
|
|
5
22
|
*/
|
|
6
23
|
export declare function computeDevLinked(pkgRoot: string): boolean;
|
|
7
24
|
export declare function isDevLinked(): boolean;
|
|
8
|
-
export declare const npmLatestVersion: (pkg?: string) => string | null;
|
|
9
25
|
export declare const updateCheckIntervalMs: () => number;
|
|
10
26
|
export declare const shouldCheckUpdate: (stateFile?: string, now?: number, intervalMs?: number) => boolean;
|
|
11
27
|
export declare const markUpdateChecked: (stateFile?: string) => void;
|
|
28
|
+
/**
|
|
29
|
+
* 解析 npm 可执行命令(纯函数,便于单测)。
|
|
30
|
+
* - HUNTER_MATE_NPM_BIN 显式指定时优先(沙盒内局部 npm)
|
|
31
|
+
* - win32 下 spawn 不解析 PATHEXT,直接 spawn 'npm' 会 ENOENT;必须走 npm.cmd + shell
|
|
32
|
+
* - 其余平台原生 npm,无需 shell
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveNpmCommand(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): {
|
|
35
|
+
cmd: string;
|
|
36
|
+
shell: boolean;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* 构造剔除死代理的子进程 env(复用 utils/proxy-detect)。
|
|
40
|
+
* 返回 env 与给用户的提示语;检测失败不阻断(沿用 npmSelfUpdate 原有语义)。
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildSanitizedNpmEnv(): Promise<{
|
|
43
|
+
env: NodeJS.ProcessEnv;
|
|
44
|
+
proxyNote: string;
|
|
45
|
+
}>;
|
|
46
|
+
export interface NpmLatestVersionResult {
|
|
47
|
+
version: string | null;
|
|
48
|
+
/** 失败原因细分,便于现场定位(ENOENT/timeout/exit) */
|
|
49
|
+
detail: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 健壮版最新版本查询:npm registry 优先,失败回退七牛 CDN latest.json。
|
|
53
|
+
* (kit 版 15s 裸 spawn 在 Windows/代理环境必失败,见文件头 TODO)
|
|
54
|
+
*/
|
|
55
|
+
export declare function npmLatestVersionRobust(pkg?: string): Promise<NpmLatestVersionResult>;
|
|
56
|
+
/** 当前运行 CLI 的包根(dist 的上一级),realpath 归一 */
|
|
57
|
+
export declare function getCliPkgRoot(): string;
|
|
58
|
+
export type CliInstallLayout = {
|
|
59
|
+
mode: 'prefix';
|
|
60
|
+
prefix: string;
|
|
61
|
+
reason: string;
|
|
62
|
+
} | {
|
|
63
|
+
mode: 'global';
|
|
64
|
+
reason: string;
|
|
65
|
+
} | {
|
|
66
|
+
mode: 'custom-prefix';
|
|
67
|
+
prefix: string;
|
|
68
|
+
reason: string;
|
|
69
|
+
} | {
|
|
70
|
+
mode: 'skip';
|
|
71
|
+
reason: string;
|
|
72
|
+
} | {
|
|
73
|
+
mode: 'fallback';
|
|
74
|
+
prefix: string;
|
|
75
|
+
reason: string;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* 判定当前运行 CLI 的安装形态(纯函数;global 判定依赖调用方预解析的 globalPrefix,
|
|
79
|
+
* globalPrefix===undefined 表示尚未解析,有 node_modules 祖先时返回 fallback 提示调用方先解析)。
|
|
80
|
+
*
|
|
81
|
+
* 优先级:
|
|
82
|
+
* 1. pkgRoot 在 cliPrefix(~/.hunter-mate/cli)下 → prefix(设计形态,现有行为)
|
|
83
|
+
* 2. pkgRoot 在 ROOT 内但不在 cliPrefix(Release 二进制/daemon 布局)→ skip,npm 自更新不适用
|
|
84
|
+
* 3. 有 node_modules 祖先:
|
|
85
|
+
* - globalPrefix 已知且 pkgRoot 在其下 → global(npm install -g,不带 --prefix)
|
|
86
|
+
* - globalPrefix 已知但不在其下 → custom-prefix(prefix = node_modules 父目录,装回原处)
|
|
87
|
+
* - globalPrefix 未知 → fallback(调用方通常应先 spawn `npm prefix -g` 解析)
|
|
88
|
+
* 4. 无 node_modules 祖先且不在 ROOT 下 → fallback(未识别形态,沿用原 --prefix 行为)
|
|
89
|
+
*/
|
|
90
|
+
export declare function detectCliInstallLayout(pkgRootIn: string, cliPrefixIn: string, globalPrefixIn?: string | null): CliInstallLayout;
|
|
91
|
+
/** spawn `npm prefix -g` 解析全局前缀(10s 封顶,失败返回 null,不阻断) */
|
|
92
|
+
export declare function resolveGlobalNpmPrefix(): Promise<string | null>;
|
|
93
|
+
/** 孤儿 ~/.hunter-mate/cli 安装检测(doctor orphan_cli_install 检查项;纯函数) */
|
|
94
|
+
export declare function detectOrphanPrefixInstall(pkgRootIn?: string, cliPrefixIn?: string): {
|
|
95
|
+
orphan: boolean;
|
|
96
|
+
orphanPkgDir?: string;
|
|
97
|
+
runPkgRoot: string;
|
|
98
|
+
};
|
|
12
99
|
export interface NpmSelfUpdateResult {
|
|
13
100
|
ok: boolean;
|
|
14
101
|
msg: string;
|
|
102
|
+
/** 装后验证:目标位置版本是否等于期望版本(null=未验证) */
|
|
103
|
+
verified?: boolean;
|
|
15
104
|
}
|
|
16
|
-
export declare function npmSelfUpdate(pkg?: string
|
|
105
|
+
export declare function npmSelfUpdate(pkg?: string, expectedVersion?: string,
|
|
106
|
+
/** 测试注入:覆盖"当前运行 CLI 包根"的判定 */
|
|
107
|
+
opts?: {
|
|
108
|
+
pkgRoot?: string;
|
|
109
|
+
}): Promise<NpmSelfUpdateResult>;
|
|
17
110
|
export interface CliUpdateOutcome {
|
|
18
111
|
logs: string[];
|
|
19
112
|
devSkipped: boolean;
|