hunter-mate 0.1.7 → 0.1.11
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 +808 -153
- package/dist/assets/extension/build-info.json +1 -0
- package/dist/assets/extension/content/index.js +23 -5
- package/dist/assets/extension/manifest.json +5 -4
- package/dist/assets/extension/offscreen/offscreen.html +8 -0
- package/dist/assets/extension/offscreen/offscreen.js +149 -0
- package/dist/assets/extension/package.json +8 -1
- package/dist/assets/extension/sidepanel/index.css +2 -0
- package/dist/assets/extension/sidepanel/index.html +7 -394
- package/dist/assets/extension/sidepanel/index.js +53 -923
- package/dist/assets/server/app.module.js +11 -1
- package/dist/assets/server/app.module.js.map +1 -1
- package/dist/assets/server/auth/auth.middleware.js +9 -1
- package/dist/assets/server/auth/auth.middleware.js.map +1 -1
- package/dist/assets/server/build-info.json +1 -1
- package/dist/assets/server/customer/customer.controller.d.ts +18 -0
- package/dist/assets/server/customer/customer.controller.js +81 -0
- package/dist/assets/server/customer/customer.controller.js.map +1 -0
- package/dist/assets/server/customer/customer.entity.d.ts +17 -0
- package/dist/assets/server/customer/customer.entity.js +82 -0
- package/dist/assets/server/customer/customer.entity.js.map +1 -0
- package/dist/assets/server/customer/customer.module.d.ts +2 -0
- package/dist/assets/server/customer/customer.module.js +28 -0
- package/dist/assets/server/customer/customer.module.js.map +1 -0
- package/dist/assets/server/customer/customer.service.d.ts +36 -0
- package/dist/assets/server/customer/customer.service.js +200 -0
- package/dist/assets/server/customer/customer.service.js.map +1 -0
- package/dist/assets/server/db/schema-validator.service.d.ts +2 -0
- package/dist/assets/server/db/schema-validator.service.js +32 -1
- package/dist/assets/server/db/schema-validator.service.js.map +1 -1
- package/dist/assets/server/db/sqlite.module.d.ts +1 -0
- package/dist/assets/server/db/sqlite.module.js +12 -2
- package/dist/assets/server/db/sqlite.module.js.map +1 -1
- package/dist/assets/server/devops/devops-sink-init.d.ts +1 -14
- package/dist/assets/server/devops/devops-sink-init.js +3 -8
- package/dist/assets/server/devops/devops-sink-init.js.map +1 -1
- package/dist/assets/server/extension/extension-control.controller.d.ts +17 -1
- package/dist/assets/server/extension/extension-control.controller.js +68 -12
- package/dist/assets/server/extension/extension-control.controller.js.map +1 -1
- package/dist/assets/server/extension/extension-control.service.d.ts +6 -1
- package/dist/assets/server/extension/extension-control.service.js +27 -1
- package/dist/assets/server/extension/extension-control.service.js.map +1 -1
- package/dist/assets/server/extension/extension.module.js +2 -1
- package/dist/assets/server/extension/extension.module.js.map +1 -1
- package/dist/assets/server/extraction/adapter.service.d.ts +3 -0
- package/dist/assets/server/extraction/adapter.service.js +127 -6
- package/dist/assets/server/extraction/adapter.service.js.map +1 -1
- package/dist/assets/server/extraction/anomaly-report.service.js +1 -1
- package/dist/assets/server/extraction/anomaly-report.service.js.map +1 -1
- package/dist/assets/server/extraction/entities/adapter-rule.entity.d.ts +2 -0
- package/dist/assets/server/extraction/entities/adapter-rule.entity.js +10 -0
- package/dist/assets/server/extraction/entities/adapter-rule.entity.js.map +1 -1
- package/dist/assets/server/extraction/extraction-entity.controller.d.ts +21 -3
- package/dist/assets/server/extraction/extraction-entity.controller.js +44 -9
- package/dist/assets/server/extraction/extraction-entity.controller.js.map +1 -1
- package/dist/assets/server/extraction/extraction.module.js +13 -3
- package/dist/assets/server/extraction/extraction.module.js.map +1 -1
- package/dist/assets/server/extraction/extraction.service.d.ts +4 -1
- package/dist/assets/server/extraction/extraction.service.js +71 -13
- package/dist/assets/server/extraction/extraction.service.js.map +1 -1
- package/dist/assets/server/extraction/harness-overlay.service.d.ts +41 -0
- package/dist/assets/server/extraction/harness-overlay.service.js +319 -0
- package/dist/assets/server/extraction/harness-overlay.service.js.map +1 -0
- package/dist/assets/server/extraction/liepin-extractor.d.ts +1 -0
- package/dist/assets/server/extraction/liepin-extractor.js +172 -0
- package/dist/assets/server/extraction/liepin-extractor.js.map +1 -0
- package/dist/assets/server/extraction/script-rule.js +14 -2
- package/dist/assets/server/extraction/script-rule.js.map +1 -1
- package/dist/assets/server/governance/action-audit.entity.d.ts +12 -0
- package/dist/assets/server/governance/action-audit.entity.js +66 -0
- package/dist/assets/server/governance/action-audit.entity.js.map +1 -0
- package/dist/assets/server/governance/governance.command-recorder.d.ts +17 -0
- package/dist/assets/server/governance/governance.command-recorder.js +98 -0
- package/dist/assets/server/governance/governance.command-recorder.js.map +1 -0
- package/dist/assets/server/governance/governance.controller.d.ts +14 -0
- package/dist/assets/server/governance/governance.controller.js +77 -0
- package/dist/assets/server/governance/governance.controller.js.map +1 -0
- package/dist/assets/server/governance/governance.ingester.d.ts +21 -0
- package/dist/assets/server/governance/governance.ingester.js +117 -0
- package/dist/assets/server/governance/governance.ingester.js.map +1 -0
- package/dist/assets/server/governance/governance.module.d.ts +2 -0
- package/dist/assets/server/governance/governance.module.js +27 -0
- package/dist/assets/server/governance/governance.module.js.map +1 -0
- package/dist/assets/server/governance/governance.service.d.ts +122 -0
- package/dist/assets/server/governance/governance.service.js +398 -0
- package/dist/assets/server/governance/governance.service.js.map +1 -0
- package/dist/assets/server/jobcase/jobcase.controller.d.ts +1 -0
- package/dist/assets/server/jobcase/jobcase.entity.d.ts +1 -0
- package/dist/assets/server/jobcase/jobcase.entity.js +6 -0
- package/dist/assets/server/jobcase/jobcase.entity.js.map +1 -1
- package/dist/assets/server/jobcase/jobcase.service.d.ts +2 -0
- package/dist/assets/server/jobcase/jobcase.service.js +2 -1
- package/dist/assets/server/jobcase/jobcase.service.js.map +1 -1
- package/dist/assets/server/main.js +1 -0
- package/dist/assets/server/main.js.map +1 -1
- package/dist/assets/server/package.json +1 -1
- package/dist/assets/server/preference/preference.controller.d.ts +14 -0
- package/dist/assets/server/preference/preference.controller.js +66 -0
- package/dist/assets/server/preference/preference.controller.js.map +1 -0
- package/dist/assets/server/preference/preference.entity.d.ts +13 -0
- package/dist/assets/server/preference/preference.entity.js +77 -0
- package/dist/assets/server/preference/preference.entity.js.map +1 -0
- package/dist/assets/server/preference/preference.module.d.ts +2 -0
- package/dist/assets/server/preference/preference.module.js +26 -0
- package/dist/assets/server/preference/preference.module.js.map +1 -0
- package/dist/assets/server/preference/preference.service.d.ts +33 -0
- package/dist/assets/server/preference/preference.service.js +122 -0
- package/dist/assets/server/preference/preference.service.js.map +1 -0
- package/dist/assets/server/recording/recording-event-queue.service.js +1 -1
- package/dist/assets/server/recording/recording-event-queue.service.js.map +1 -1
- package/dist/assets/server/recording/recording-retention.service.d.ts +19 -2
- package/dist/assets/server/recording/recording-retention.service.js +95 -6
- package/dist/assets/server/recording/recording-retention.service.js.map +1 -1
- package/dist/assets/server/recording/recording-snapshot.service.d.ts +1 -0
- package/dist/assets/server/recording/recording-snapshot.service.js +4 -0
- package/dist/assets/server/recording/recording-snapshot.service.js.map +1 -1
- package/dist/assets/server/recording/recording.controller.d.ts +10 -0
- package/dist/assets/server/recording/recording.controller.js +19 -0
- package/dist/assets/server/recording/recording.controller.js.map +1 -1
- package/dist/assets/server/recording/recording.gateway.js +15 -0
- package/dist/assets/server/recording/recording.gateway.js.map +1 -1
- package/dist/assets/server/recording/recording.module.js +6 -1
- package/dist/assets/server/recording/recording.module.js.map +1 -1
- package/dist/assets/server/recording/recording.service.d.ts +5 -0
- package/dist/assets/server/recording/recording.service.js +10 -0
- package/dist/assets/server/recording/recording.service.js.map +1 -1
- package/dist/assets/server/remark/remark.controller.d.ts +1 -1
- package/dist/assets/server/remark/remark.controller.js +1 -10
- package/dist/assets/server/remark/remark.controller.js.map +1 -1
- package/dist/assets/server/remark/remark.entity.d.ts +1 -1
- package/dist/assets/server/remark/remark.entity.js.map +1 -1
- package/dist/assets/server/site/entities/site-registry.entity.d.ts +1 -1
- package/dist/assets/server/site/entities/site-registry.entity.js +1 -1
- package/dist/assets/server/site/entities/site-registry.entity.js.map +1 -1
- package/dist/assets/server/site/site.controller.d.ts +1 -1
- package/dist/assets/server/site/site.service.d.ts +5 -1
- package/dist/assets/server/site/site.service.js +13 -0
- package/dist/assets/server/site/site.service.js.map +1 -1
- package/dist/assets/server/system/system.controller.d.ts +1 -0
- package/dist/assets/server/system/system.controller.js +1 -1
- package/dist/assets/server/system/system.controller.js.map +1 -1
- package/dist/assets/server/system/system.service.d.ts +1 -0
- package/dist/assets/server/system/system.service.js +3 -2
- package/dist/assets/server/system/system.service.js.map +1 -1
- package/dist/cache/db.js +6 -6
- package/dist/commands/addons.js +2 -1
- package/dist/commands/cache.js +1 -1
- package/dist/commands/case.d.ts +67 -0
- package/dist/commands/case.js +101 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.js +8 -1
- package/dist/commands/customer.d.ts +25 -0
- package/dist/commands/customer.js +137 -0
- package/dist/commands/doctor.js +33 -9
- package/dist/commands/extension.js +21 -16
- package/dist/commands/extras.d.ts +18 -3
- package/dist/commands/extras.js +162 -5
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +3 -4
- package/dist/commands/install.d.ts +5 -0
- package/dist/commands/install.js +22 -42
- package/dist/commands/issue-env.d.ts +23 -0
- package/dist/commands/issue-env.js +101 -0
- package/dist/commands/job.d.ts +2 -1
- package/dist/commands/job.js +25 -5
- package/dist/commands/login.d.ts +4 -0
- package/dist/commands/login.js +57 -4
- package/dist/commands/migrate.d.ts +32 -0
- package/dist/commands/migrate.js +116 -0
- package/dist/commands/note.d.ts +3 -0
- package/dist/commands/note.js +75 -0
- package/dist/commands/ops.js +64 -13
- package/dist/commands/preference.d.ts +6 -0
- package/dist/commands/preference.js +80 -0
- package/dist/commands/record.js +1 -1
- package/dist/commands/report.js +1 -1
- package/dist/commands/search.js +1 -1
- package/dist/commands/server.d.ts +12 -0
- package/dist/commands/server.js +182 -18
- package/dist/commands/status.d.ts +4 -0
- package/dist/commands/status.js +16 -6
- package/dist/commands/update.js +7 -8
- package/dist/config.d.ts +21 -0
- package/dist/config.js +27 -0
- package/dist/extension-sync.d.ts +35 -0
- package/dist/extension-sync.js +159 -0
- package/dist/i18n/locales/en-US.json +17 -1
- package/dist/i18n/locales/zh-CN.json +17 -1
- package/dist/index.js +17 -0
- package/dist/keychain.d.ts +16 -1
- package/dist/keychain.js +43 -16
- package/dist/logger.js +2 -2
- package/dist/postinstall.d.ts +1 -0
- package/dist/postinstall.js +31 -0
- package/dist/updater.js +2 -2
- package/dist/utils/artifact-checksum.d.ts +4 -0
- package/dist/utils/artifact-checksum.js +40 -0
- package/dist/utils/command-error.d.ts +4 -2
- package/dist/utils/command-error.js +19 -3
- package/dist/utils/link.d.ts +18 -0
- package/dist/utils/link.js +83 -0
- package/dist/utils/local-http.d.ts +7 -0
- package/dist/utils/local-http.js +30 -0
- package/dist/version.js +86 -49
- package/dist/watchdog.d.ts +8 -0
- package/dist/watchdog.js +49 -9
- package/dist/web/dist/404.html +1 -1
- package/dist/web/dist/_next/static/chunks/app/logs/page-d478031d49f7ba00.js +1 -0
- package/dist/web/dist/_next/static/chunks/{main-app-80b038a312917d90.js → main-app-0af848156a5b13fc.js} +1 -1
- package/dist/web/dist/_next/static/chunks/pages/{_app-da7d628f49271ece.js → _app-3d844792ec91e4d1.js} +2 -2
- package/dist/web/dist/auth/verify.html +1 -1
- package/dist/web/dist/auth/verify.txt +1 -1
- package/dist/web/dist/companies.html +1 -1
- package/dist/web/dist/companies.txt +1 -1
- 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 +1 -1
- package/dist/web/dist/jobs.html +1 -1
- package/dist/web/dist/jobs.txt +1 -1
- package/dist/web/dist/logs.html +1 -1
- package/dist/web/dist/logs.txt +2 -2
- package/dist/web/dist/matching/jobs/placeholder/talents.html +1 -1
- package/dist/web/dist/matching/jobs/placeholder/talents.txt +1 -1
- package/dist/web/dist/matching/portraits/placeholder/jobs.html +1 -1
- package/dist/web/dist/matching/portraits/placeholder/jobs.txt +1 -1
- package/dist/web/dist/parselog.html +1 -1
- package/dist/web/dist/parselog.txt +1 -1
- package/dist/web/dist/recordings.html +1 -1
- package/dist/web/dist/recordings.txt +1 -1
- package/dist/web/dist/snapshots/placeholder/agent-prompt.html +1 -1
- package/dist/web/dist/snapshots/placeholder/agent-prompt.txt +1 -1
- package/dist/web/dist/talents.html +1 -1
- package/dist/web/dist/talents.txt +1 -1
- package/package.json +6 -4
- package/scripts/postinstall-run.mjs +14 -0
- package/dist/web/dist/_next/static/chunks/app/logs/page-9f41d44fa1add723.js +0 -1
- /package/dist/web/dist/_next/static/{hqJ-7vr4X71DNfzZugHJ- → 3bVkK4pAgbbmp5r0ThyBL}/_buildManifest.js +0 -0
- /package/dist/web/dist/_next/static/{hqJ-7vr4X71DNfzZugHJ- → 3bVkK4pAgbbmp5r0ThyBL}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// utils/local-http.ts — 本地 server 探测的代理绕过(Issue #24 P1)
|
|
2
|
+
//
|
|
3
|
+
// 事故:用户 shell 带 http_proxy=http://127.0.0.1:1087 时,CLI 探测
|
|
4
|
+
// localhost:34570 被代理拦截(500)→ 误判 "server not running" → 自动启动
|
|
5
|
+
// 与 start 的 "already running" 形成死循环。Node/axios 默认读 http_proxy 环境变量,
|
|
6
|
+
// 只对 localhost/127.0.0.1/[::1] 禁用代理;远程 serverUrl(如 SaaS)保留代理行为。
|
|
7
|
+
import axios from 'axios';
|
|
8
|
+
const LOCAL_HOST_RE = /^(?:https?:)?\/\/(?:localhost|127\.0\.0\.1|\[::1\]|0\.0\.0\.0)(?::|\/|$)/i;
|
|
9
|
+
export function isLocalServerUrl(url) {
|
|
10
|
+
if (!url)
|
|
11
|
+
return false;
|
|
12
|
+
return LOCAL_HOST_RE.test(url);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 全局 axios 请求拦截器:调用方未显式指定 proxy 且目标是本地地址时强制 proxy:false。
|
|
16
|
+
* 在 CLI 入口(index.ts)注册一次,覆盖 status/doctor/extension 等所有探测路径;
|
|
17
|
+
* 显式传了 proxy(含已有的 proxy:false)的请求不覆盖,尊重调用方意图。
|
|
18
|
+
*/
|
|
19
|
+
export function installLocalProxyBypass() {
|
|
20
|
+
axios.interceptors.request.use((config) => {
|
|
21
|
+
if (config.proxy === undefined) {
|
|
22
|
+
const url = config.baseURL
|
|
23
|
+
? new URL(config.url ?? '', config.baseURL).toString()
|
|
24
|
+
: (config.url ?? '');
|
|
25
|
+
if (isLocalServerUrl(url))
|
|
26
|
+
config.proxy = false;
|
|
27
|
+
}
|
|
28
|
+
return config;
|
|
29
|
+
});
|
|
30
|
+
}
|
package/dist/version.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { createHash } from 'crypto';
|
|
5
4
|
import axios from 'axios';
|
|
6
5
|
import chalk from 'chalk';
|
|
7
|
-
import { loadConfig } from './config.js';
|
|
8
|
-
import { runStop, runStart, tryReadPid, findServerRoot } from './commands/server.js';
|
|
6
|
+
import { loadConfig, resolveDataDir } from './config.js';
|
|
7
|
+
import { runStop, runStart, tryReadPid, findServerRoot, probeServerHealth } from './commands/server.js';
|
|
9
8
|
import { runReload } from './commands/extras.js';
|
|
9
|
+
import { dirChecksum } from './utils/artifact-checksum.js';
|
|
10
|
+
import { compareExtensionArtifacts, syncExtensionArtifacts } from './extension-sync.js';
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
12
|
const __dirname = path.dirname(__filename);
|
|
12
|
-
const
|
|
13
|
-
const ROOT = () => path.join(HOME(), '.hunter-mate');
|
|
13
|
+
const ROOT = resolveDataDir;
|
|
14
14
|
const PLUGINS_DIR = () => path.join(ROOT(), 'plugins');
|
|
15
15
|
const EXTENSION_MANIFEST = () => path.join(ROOT(), 'extension', 'manifest.json');
|
|
16
16
|
const EXTENSION_DIR = () => path.join(ROOT(), 'extension');
|
|
17
17
|
const RUNTIME_FILE = () => path.join(ROOT(), 'runtime.json');
|
|
18
18
|
const LAST_CHECK_FILE = () => path.join(ROOT(), '.last-consistency-check');
|
|
19
|
+
// D5(R3 定案):extension reload 广播边沿触发 —— 同一 checksum 只广播一次。
|
|
20
|
+
// 原逻辑只要 disk≠bootSnapshot 每次 CLI 调用都广播,dev 频繁构建态下
|
|
21
|
+
// 每个命令都杀死在途长命令(linkedin search 分钟级编排反复横死)。
|
|
22
|
+
const LAST_EXT_RELOAD_BROADCAST_FILE = () => path.join(ROOT(), '.last-ext-reload-broadcast');
|
|
19
23
|
const CHECK_THROTTLE_MS = 60_000;
|
|
20
24
|
// ---------------------------------------------------------------------------
|
|
21
25
|
// 三层指纹工具(version + checksum + mtime/linked)— 与 chromepilot version-manager / server SystemService 算法完全等价
|
|
@@ -29,40 +33,6 @@ function readJson(file) {
|
|
|
29
33
|
}
|
|
30
34
|
}
|
|
31
35
|
/** 递归目录 SHA-1(文件名+内容)+ 最新 mtime — 与 server SystemService.dirChecksum 字节等价 */
|
|
32
|
-
function dirChecksum(dir) {
|
|
33
|
-
const hash = createHash('sha1');
|
|
34
|
-
let latest = 0;
|
|
35
|
-
function walk(d, rel = '') {
|
|
36
|
-
try {
|
|
37
|
-
const entries = fs.readdirSync(d, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
38
|
-
for (const entry of entries) {
|
|
39
|
-
const relPath = path.join(rel, entry.name);
|
|
40
|
-
const full = path.join(d, entry.name);
|
|
41
|
-
if (entry.isDirectory()) {
|
|
42
|
-
walk(full, relPath);
|
|
43
|
-
}
|
|
44
|
-
else if (entry.isFile() || entry.isSymbolicLink()) {
|
|
45
|
-
try {
|
|
46
|
-
const stat = fs.statSync(full);
|
|
47
|
-
if (stat.mtimeMs > latest)
|
|
48
|
-
latest = stat.mtimeMs;
|
|
49
|
-
hash.update(relPath + '\0');
|
|
50
|
-
const buf = fs.readFileSync(full);
|
|
51
|
-
hash.update(buf);
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
/* ignore unreadable */
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
/* dir missing → empty */
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
walk(dir);
|
|
64
|
-
return { checksum: hash.digest('hex'), latestMtimeMs: latest };
|
|
65
|
-
}
|
|
66
36
|
function inspectArtifact(dir, versionSource) {
|
|
67
37
|
if (!fs.existsSync(dir))
|
|
68
38
|
return null;
|
|
@@ -286,6 +256,31 @@ export async function ensureRuntimeConsistency(opts = {}) {
|
|
|
286
256
|
}
|
|
287
257
|
const installed = readInstalledVersions();
|
|
288
258
|
const actions = decideConsistencyActions(installed, live);
|
|
259
|
+
// Issue #23:npm 升级 CLI 后 ~/.hunter-mate/extension 还是旧构建——
|
|
260
|
+
// 上面的三层指纹比对的是"运行中扩展 vs ~/.hunter-mate 磁盘",二者同为旧版
|
|
261
|
+
// 所以误判一致。这里以 CLI 包内置产物(dist/assets/extension)为上游 SSOT
|
|
262
|
+
// 按 checksum 比对,不一致先同步产物,再按需补 reload 广播。
|
|
263
|
+
const bundledCmp = compareExtensionArtifacts();
|
|
264
|
+
if (bundledCmp.stale) {
|
|
265
|
+
const sync = syncExtensionArtifacts();
|
|
266
|
+
if (sync.synced) {
|
|
267
|
+
performed.push(`extension artifacts synced: ${sync.fromVersion ?? '?'} → ${sync.toVersion ?? '?'}`
|
|
268
|
+
+ ` (copied=${sync.copied}, removed=${sync.removed}, reason=bundled_mismatch)`);
|
|
269
|
+
// 磁盘刚被刷新,重新计算 installed 指纹,供下面 broadcast 的边沿触发判据用
|
|
270
|
+
installed.artifacts = computeLocalArtifacts({
|
|
271
|
+
server: installed.server,
|
|
272
|
+
extension: sync.toVersion ?? installed.extension,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
performed.push(`extension artifacts sync SKIPPED: ${sync.reason}`);
|
|
277
|
+
}
|
|
278
|
+
if (live.extensions.length > 0 && !actions.extensionReload) {
|
|
279
|
+
actions.extensionReload = true;
|
|
280
|
+
actions.extensionReason = `CLI 内置扩展产物与 ~/.hunter-mate/extension 不一致`
|
|
281
|
+
+ `(bundled ${bundledCmp.sourceVersion} vs installed ${bundledCmp.targetVersion}),已先同步产物(bundled_mismatch)`;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
289
284
|
// 1) 插件热重载
|
|
290
285
|
if (actions.pluginsReload.length) {
|
|
291
286
|
try {
|
|
@@ -301,24 +296,66 @@ export async function ensureRuntimeConsistency(opts = {}) {
|
|
|
301
296
|
// 2) server 重启(stop + start)
|
|
302
297
|
if (actions.serverRestart) {
|
|
303
298
|
try {
|
|
304
|
-
await runStop();
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
299
|
+
const stopped = await runStop();
|
|
300
|
+
// FID-093:runStop 在 /health 探活失败时走 red-line 不杀(进程可能还活着,
|
|
301
|
+
// 只是探活被机器抖动打断)。此时绝不能盲启新实例——双 server 抢端口会
|
|
302
|
+
// EADDRINUSE 崩溃循环(2026-09-10 23:13 实机复现)。停后复核:进程仍存活
|
|
303
|
+
// 且 /health 恢复 → 视为重启完成(跳过 start);真死了才拉新。
|
|
304
|
+
let stillUp = false;
|
|
305
|
+
if (!stopped.stopped && stopped.pid) {
|
|
306
|
+
const deadline = Date.now() + 10_000;
|
|
307
|
+
while (Date.now() < deadline) {
|
|
308
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
309
|
+
if (await probeServerHealth(`${config.serverUrl}`)) {
|
|
310
|
+
stillUp = true;
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (stillUp) {
|
|
316
|
+
performed.push(`server restart skipped (${actions.serverReason}): runStop 因健康探活失败未杀旧进程,red-line 保护生效;复核期内 /health 已恢复,旧 server 仍在服务,拉起新实例会造成双实例`);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
const r = await runStart({});
|
|
320
|
+
performed.push(r.started
|
|
321
|
+
? `server restarted (${actions.serverReason}) — new pid=${r.pid}`
|
|
322
|
+
: `server restart FAILED: ${r.msg}`);
|
|
323
|
+
}
|
|
309
324
|
}
|
|
310
325
|
catch (err) {
|
|
311
326
|
performed.push(`server restart FAILED: ${err.message}`);
|
|
312
327
|
}
|
|
313
328
|
}
|
|
314
|
-
// 3) 浏览器扩展 reload 广播
|
|
329
|
+
// 3) 浏览器扩展 reload 广播(D5: checksum 边沿触发,同值不重播)
|
|
315
330
|
if (actions.extensionReload) {
|
|
331
|
+
const currentChecksum = installed.artifacts?.extension?.checksum ?? '';
|
|
332
|
+
let lastBroadcast = '';
|
|
316
333
|
try {
|
|
317
|
-
|
|
318
|
-
|
|
334
|
+
lastBroadcast = fs.readFileSync(LAST_EXT_RELOAD_BROADCAST_FILE(), 'utf8').trim();
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
/* 首次 */
|
|
319
338
|
}
|
|
320
|
-
|
|
321
|
-
performed.push(`extension reload
|
|
339
|
+
if (currentChecksum && lastBroadcast === currentChecksum) {
|
|
340
|
+
performed.push(`extension reload skipped (checksum 已广播过, D5 边沿去重): ${actions.extensionReason}`);
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
try {
|
|
344
|
+
const r = await runReload(3000);
|
|
345
|
+
performed.push(`extension reload broadcast: ${actions.extensionReason ?? 'version mismatch'} — broadcast=${r.broadcast}, msg=${r.msg}`);
|
|
346
|
+
if (currentChecksum) {
|
|
347
|
+
try {
|
|
348
|
+
fs.mkdirSync(ROOT(), { recursive: true });
|
|
349
|
+
fs.writeFileSync(LAST_EXT_RELOAD_BROADCAST_FILE(), currentChecksum);
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
/* 尽力 */
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
catch (e) {
|
|
357
|
+
performed.push(`extension reload FAILED: ${e.message}. Tip: chrome://extensions → 点 HunterMate 卡片的刷新图标`);
|
|
358
|
+
}
|
|
322
359
|
}
|
|
323
360
|
}
|
|
324
361
|
markChecked();
|
package/dist/watchdog.d.ts
CHANGED
|
@@ -21,3 +21,11 @@ export declare class LivenessProbe {
|
|
|
21
21
|
start(): void;
|
|
22
22
|
stop(): void;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* 原子占用 watchdog 单例锁(O_CREAT|O_EXCL,跨平台同语义)。
|
|
26
|
+
* 背景:旧实现 tryReadPid + writePid 分两步(check-then-write 竞态),并发 auto-start
|
|
27
|
+
* 曾产生 5+ 个常驻 watchdog,各自拉起 server 子进程抢同一端口/SQLite →
|
|
28
|
+
* database is locked → 全体 exit(1) → 指数退避重启风暴(server-crash.log 8.5 万行)。
|
|
29
|
+
* 持有者崩溃残留锁时按 mtime 判 stale 抢占(崩溃的 watchdog 不会自己清锁)。
|
|
30
|
+
*/
|
|
31
|
+
export declare function acquireWatchdogLock(file: string, staleMs?: number): boolean;
|
package/dist/watchdog.js
CHANGED
|
@@ -2,9 +2,9 @@ import { spawn } from 'child_process';
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import * as http from 'http';
|
|
5
|
-
import { isMainModule } from './utils/script-path';
|
|
6
|
-
|
|
7
|
-
const ROOT =
|
|
5
|
+
import { isMainModule } from './utils/script-path.js';
|
|
6
|
+
import { resolveDataDir } from './config.js';
|
|
7
|
+
const ROOT = resolveDataDir;
|
|
8
8
|
const SERVER_PID_FILE = () => path.join(ROOT(), 'server.pid');
|
|
9
9
|
const WATCHDOG_PID_FILE = () => path.join(ROOT(), 'watchdog.pid');
|
|
10
10
|
const CRASH_LOG_FILE = () => path.join(ROOT(), 'server-crash.log');
|
|
@@ -77,6 +77,40 @@ function writePid(file, pid) {
|
|
|
77
77
|
}
|
|
78
78
|
catch { /* ignore */ }
|
|
79
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* 原子占用 watchdog 单例锁(O_CREAT|O_EXCL,跨平台同语义)。
|
|
82
|
+
* 背景:旧实现 tryReadPid + writePid 分两步(check-then-write 竞态),并发 auto-start
|
|
83
|
+
* 曾产生 5+ 个常驻 watchdog,各自拉起 server 子进程抢同一端口/SQLite →
|
|
84
|
+
* database is locked → 全体 exit(1) → 指数退避重启风暴(server-crash.log 8.5 万行)。
|
|
85
|
+
* 持有者崩溃残留锁时按 mtime 判 stale 抢占(崩溃的 watchdog 不会自己清锁)。
|
|
86
|
+
*/
|
|
87
|
+
export function acquireWatchdogLock(file, staleMs = 60_000) {
|
|
88
|
+
const write = () => {
|
|
89
|
+
try {
|
|
90
|
+
const fd = fs.openSync(file, 'wx'); // 原子:已存在则失败
|
|
91
|
+
try {
|
|
92
|
+
fs.writeFileSync(fd, String(process.pid));
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
fs.closeSync(fd);
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
if (write())
|
|
104
|
+
return true;
|
|
105
|
+
try {
|
|
106
|
+
if (Date.now() - fs.statSync(file).mtimeMs > staleMs) {
|
|
107
|
+
fs.unlinkSync(file);
|
|
108
|
+
return write();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch { /* 竞态:其他进程同时清理/占用,让出 */ }
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
80
114
|
function tryReadPid(file) {
|
|
81
115
|
try {
|
|
82
116
|
const raw = fs.readFileSync(file, 'utf-8').trim();
|
|
@@ -121,12 +155,15 @@ function runWatchdog() {
|
|
|
121
155
|
}
|
|
122
156
|
// 清理残留 pid
|
|
123
157
|
cleanPid(SERVER_PID_FILE());
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
158
|
+
// FID-093:原子单例锁,替代旧的 tryReadPid+writePid 两步检查(并发 auto-start
|
|
159
|
+
// 竞态会产生多常驻 watchdog → 多 server 抢端口/SQLite → 重启风暴)。
|
|
160
|
+
// 未抢到锁的进程必须不碰 pid 文件——它是胜者注册的,输者清理会把活锁删掉。
|
|
161
|
+
if (!acquireWatchdogLock(WATCHDOG_PID_FILE())) {
|
|
162
|
+
const existing = tryReadPid(WATCHDOG_PID_FILE());
|
|
163
|
+
console.error(`[HunterMate watchdog] another watchdog already running (pid=${existing ?? 'unknown'}), exiting`);
|
|
127
164
|
process.exit(1);
|
|
128
165
|
}
|
|
129
|
-
|
|
166
|
+
const ownsLock = true;
|
|
130
167
|
let child = null;
|
|
131
168
|
let restartCount = 0;
|
|
132
169
|
let restartTimer = null;
|
|
@@ -202,12 +239,15 @@ function runWatchdog() {
|
|
|
202
239
|
if (child && !child.killed) {
|
|
203
240
|
child.kill('SIGTERM');
|
|
204
241
|
}
|
|
205
|
-
|
|
242
|
+
if (ownsLock)
|
|
243
|
+
cleanPid(WATCHDOG_PID_FILE());
|
|
206
244
|
}
|
|
207
245
|
process.on('SIGTERM', stop);
|
|
208
246
|
process.on('SIGINT', stop);
|
|
209
247
|
process.on('exit', () => {
|
|
210
|
-
|
|
248
|
+
// 只有锁所有者才能清:抢锁失败的进程也走这个 handler,清掉会删掉胜者的活锁
|
|
249
|
+
if (ownsLock)
|
|
250
|
+
cleanPid(WATCHDOG_PID_FILE());
|
|
211
251
|
});
|
|
212
252
|
startChild();
|
|
213
253
|
}
|
package/dist/web/dist/404.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="zh-CN"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/db881c5b3072b88a.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-1784baecc6fdcf0b.js"/><script src="/_next/static/chunks/a7067448-96dd4b8457c447e8.js" async=""></script><script src="/_next/static/chunks/935-99f57b7d4151d9e7.js" async=""></script><script src="/_next/static/chunks/main-app-
|
|
1
|
+
<!DOCTYPE html><html lang="zh-CN"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/db881c5b3072b88a.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-1784baecc6fdcf0b.js"/><script src="/_next/static/chunks/a7067448-96dd4b8457c447e8.js" async=""></script><script src="/_next/static/chunks/935-99f57b7d4151d9e7.js" async=""></script><script src="/_next/static/chunks/main-app-0af848156a5b13fc.js" async=""></script><script src="/_next/static/chunks/589-d632233641f35681.js" async=""></script><script src="/_next/static/chunks/app/layout-83e623e973c1693f.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>HunterMate 采集仪表盘</title><meta name="description" content="HunterMate 采集/解析/入库仪表盘"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="flex h-screen overflow-hidden bg-gray-50 text-gray-900"><aside class="flex h-screen w-56 flex-col border-r border-gray-200 bg-white"><div class="flex items-center gap-2 border-b border-gray-200 px-4 py-3"><span class="text-xl">🤝</span><span class="font-semibold text-gray-900">HunterMate</span></div><nav class="flex-1 overflow-auto py-3"><a class="mx-2 flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors text-gray-600 hover:bg-gray-50 hover:text-gray-900" href="/"><span class="text-base">📊</span>仪表盘</a><a class="mx-2 flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors text-gray-600 hover:bg-gray-50 hover:text-gray-900" href="/talents"><span class="text-base">👤</span>人才</a><a class="mx-2 flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors text-gray-600 hover:bg-gray-50 hover:text-gray-900" href="/jobs"><span class="text-base">💼</span>职位</a><a class="mx-2 flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors text-gray-600 hover:bg-gray-50 hover:text-gray-900" href="/companies"><span class="text-base">🏢</span>公司</a><a class="mx-2 flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors text-gray-600 hover:bg-gray-50 hover:text-gray-900" href="/parselog"><span class="text-base">📋</span>解析日志</a><a class="mx-2 flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors text-gray-600 hover:bg-gray-50 hover:text-gray-900" href="/recordings"><span class="text-base">🔴</span>录制</a></nav></aside><main class="flex-1 overflow-hidden"><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div></main><script src="/_next/static/chunks/webpack-1784baecc6fdcf0b.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/_next/static/css/db881c5b3072b88a.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"2:I[6939,[],\"\"]\n4:I[4268,[],\"\"]\n5:I[1050,[],\"\"]\n6:I[4798,[\"589\",\"static/chunks/589-d632233641f35681.js\",\"185\",\"static/chunks/app/layout-83e623e973c1693f.js\"],\"SystemSidebar\"]\nc:I[2319,[],\"\"]\n7:{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"}\n8:{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"}\n9:{\"display\":\"inline-block\"}\na:{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0}\nd:[]\n"])</script><script>self.__next_f.push([1,"0:[\"$\",\"$L2\",null,{\"buildId\":\"3bVkK4pAgbbmp5r0ThyBL\",\"assetPrefix\":\"\",\"urlParts\":[\"\",\"_not-found\"],\"initialTree\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},[[\"$L3\",[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null],null],null]},[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\",\"/_not-found\",\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"notFoundStyles\":\"$undefined\"}]],null]},[[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/db881c5b3072b88a.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"zh-CN\",\"children\":[\"$\",\"body\",null,{\"className\":\"flex h-screen overflow-hidden bg-gray-50 text-gray-900\",\"children\":[[\"$\",\"$L6\",null,{}],[\"$\",\"main\",null,{\"className\":\"flex-1 overflow-hidden\",\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$7\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$8\",\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":\"$9\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$a\",\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[]}]}]]}]}]],null],null],\"couldBeIntercepted\":false,\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$Lb\"],\"globalErrorComponent\":\"$c\",\"missingSlots\":\"$Wd\"}]\n"])</script><script>self.__next_f.push([1,"b:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"HunterMate 采集仪表盘\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"HunterMate 采集/解析/入库仪表盘\"}]]\n3:null\n"])</script></body></html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},t=(new e.Error).stack;t&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[t]="3670dc30-7b94-42ec-8ee2-03949c228709",e._sentryDebugIdIdentifier="sentry-dbid-3670dc30-7b94-42ec-8ee2-03949c228709")}catch(e){}}(),(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[745],{6452:function(e,t,s){Promise.resolve().then(s.bind(s,1266))},1266:function(e,t,s){"use strict";s.r(t),s.d(t,{default:function(){return n}});var r=s(2835),l=s(635);function a(e){let{apiUrl:t,pollIntervalMs:s}=e,{logs:a,loading:n,error:c,paused:d,filters:i,setFilters:o,pause:u,resume:x,refresh:m}=function(e){let{apiUrl:t,pollIntervalMs:s=2500}=e,[r,a]=(0,l.useState)([]),[n,c]=(0,l.useState)(!1),[d,i]=(0,l.useState)(null),[o,u]=(0,l.useState)(!1),[x,m]=(0,l.useState)({}),h=(0,l.useRef)(void 0),p=t.replace(/\/$/,""),f=(0,l.useCallback)(async(e=!0)=>{if(!o||!e){c(!0);try{let t=new URLSearchParams;x.sessionId&&t.set("sessionId",x.sessionId),x.context&&t.set("context",x.context),x.level&&t.set("level",x.level),e&&h.current&&t.set("lastId",String(h.current)),t.set("limit","200");let s=await fetch(`${p}/logs?${t.toString()}`);if(!s.ok)throw Error(`HTTP ${s.status}`);let r=(await s.json()).items||[];e&&r.length?a(e=>{let t=new Set(e.map(e=>e.id));return[...r.filter(e=>!t.has(e.id)),...e].slice(0,1e3)}):a(r),r.length&&(h.current=Math.max(...r.map(e=>e.id||0))),i(null)}catch(e){i(e.message||String(e))}finally{c(!1)}}},[p,x,o]);return(0,l.useEffect)(()=>{h.current=void 0,a([]),f(!1)},[x.sessionId,x.context,x.level]),(0,l.useEffect)(()=>{if(o)return;let e=setInterval(()=>f(!0),s);return()=>clearInterval(e)},[f,o,s]),{logs:r,loading:n,error:d,paused:o,filters:x,setFilters:m,pause:()=>u(!0),resume:()=>u(!1),refresh:()=>f(!1)}}({apiUrl:t,pollIntervalMs:s}),h=(0,l.useRef)(null);return(0,l.useEffect)(()=>{!d&&h.current&&h.current.scrollIntoView({behavior:"smooth"})},[a,d]),(0,r.jsx)("div",{className:"min-h-screen bg-gray-50 p-4 text-sm",children:(0,r.jsxs)("div",{className:"mx-auto max-w-7xl",children:[(0,r.jsxs)("div",{className:"mb-4 flex flex-wrap items-center gap-3 rounded-lg bg-white p-3 shadow",children:[(0,r.jsx)("input",{type:"text",placeholder:"sessionId",value:i.sessionId||"",onChange:e=>o({...i,sessionId:e.target.value}),className:"rounded border border-gray-300 px-2 py-1"}),(0,r.jsx)("select",{value:i.context||"",onChange:e=>o({...i,context:e.target.value}),className:"rounded border border-gray-300 px-2 py-1",children:["","cli","server","content","background","sidepanel"].map(e=>(0,r.jsx)("option",{value:e,children:e||"all contexts"},e))}),(0,r.jsx)("select",{value:i.level||"",onChange:e=>o({...i,level:e.target.value}),className:"rounded border border-gray-300 px-2 py-1",children:["","debug","info","warn","error"].map(e=>(0,r.jsx)("option",{value:e,children:e||"all levels"},e))}),(0,r.jsx)("button",{onClick:()=>d?x():u(),className:`rounded px-3 py-1 font-medium ${d?"bg-green-600 text-white":"bg-yellow-500 text-white"}`,children:d?"Resume":"Pause"}),(0,r.jsx)("button",{onClick:m,className:"rounded bg-blue-600 px-3 py-1 font-medium text-white",children:"Refresh"}),n&&(0,r.jsx)("span",{className:"text-gray-500",children:"Loading..."}),c&&(0,r.jsxs)("span",{className:"text-red-600",children:["Error: ",c]})]}),(0,r.jsx)("div",{className:"rounded-lg bg-white shadow",children:(0,r.jsxs)("div",{className:"max-h-[70vh] overflow-auto",children:[(0,r.jsxs)("table",{className:"w-full table-auto border-collapse",children:[(0,r.jsx)("thead",{className:"sticky top-0 bg-gray-100",children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("th",{className:"px-3 py-2 text-left font-semibold text-gray-700",children:"Time"}),(0,r.jsx)("th",{className:"px-3 py-2 text-left font-semibold text-gray-700",children:"Context"}),(0,r.jsx)("th",{className:"px-3 py-2 text-left font-semibold text-gray-700",children:"Level"}),(0,r.jsx)("th",{className:"px-3 py-2 text-left font-semibold text-gray-700",children:"Message"}),(0,r.jsx)("th",{className:"px-3 py-2 text-left font-semibold text-gray-700",children:"Meta"})]})}),(0,r.jsx)("tbody",{children:a.map(e=>(0,r.jsxs)("tr",{className:"border-b border-gray-100 hover:bg-gray-50",children:[(0,r.jsx)("td",{className:"px-3 py-2 whitespace-nowrap text-gray-500",children:new Date(e.timestamp).toLocaleTimeString()}),(0,r.jsx)("td",{className:"px-3 py-2",children:e.context}),(0,r.jsx)("td",{className:"px-3 py-2",children:(0,r.jsx)("span",{className:function(e){let t="rounded px-2 py-0.5 text-xs font-medium ";switch(e){case"error":return t+"bg-red-100 text-red-700";case"warn":return t+"bg-yellow-100 text-yellow-700";case"info":return t+"bg-blue-100 text-blue-700";default:return t+"bg-gray-100 text-gray-600"}}(e.level),children:e.level})}),(0,r.jsx)("td",{className:"px-3 py-2 max-w-md truncate",title:e.message,children:e.message}),(0,r.jsx)("td",{className:"px-3 py-2",children:e.meta?(0,r.jsxs)("details",{children:[(0,r.jsx)("summary",{className:"cursor-pointer text-blue-600",children:"meta"}),(0,r.jsx)("pre",{className:"mt-1 max-w-xs overflow-auto rounded bg-gray-100 p-1 text-xs",children:JSON.stringify(e.meta,null,2)})]}):"-"})]},e.id))})]}),(0,r.jsx)("div",{ref:h})]})})]})})}function n(){return(0,r.jsx)(a,{apiUrl:"",pollIntervalMs:2500})}}},function(e){e.O(0,[400,935,744],function(){return e(e.s=6452)}),_N_E=e.O()}]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
1
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b5a0b51e-c12c-4e5b-a564-a33a8fe86d58",e._sentryDebugIdIdentifier="sentry-dbid-b5a0b51e-c12c-4e5b-a564-a33a8fe86d58")}catch(e){}}(),(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{5746:function(){},7539:function(e,n,t){Promise.resolve().then(t.t.bind(t,6939,23)),Promise.resolve().then(t.t.bind(t,7360,23)),Promise.resolve().then(t.t.bind(t,2319,23)),Promise.resolve().then(t.t.bind(t,4268,23)),Promise.resolve().then(t.t.bind(t,742,23)),Promise.resolve().then(t.t.bind(t,1050,23))},9531:function(e,n,t){"use strict";var r=t(258),i=t(529);globalThis._sentryRewritesTunnelPath=void 0,globalThis.SENTRY_RELEASE={id:"a678db1e3d9efb345ab829dd6fb95a5b5cc724e6"},globalThis._sentryBasePath=void 0,globalThis._sentryRewriteFramesAssetPrefixPath="";let s=i.env.NEXT_PUBLIC_HM_ERROR_TRACKING_DSN;"true"===i.env.NEXT_PUBLIC_HM_ERROR_TRACKING_ENABLED&&s&&r.S1({dsn:s,release:i.env.NEXT_PUBLIC_HM_RELEASE,environment:i.env.NEXT_PUBLIC_HM_ENVIRONMENT||"development",tracesSampleRate:0,sendClientReports:!1,beforeSend(e){var n;if(null===(n=e.request)||void 0===n?void 0:n.headers){let n=e.request.headers;n.authorization&&(n.authorization="***"),n.cookie&&(n.cookie="***")}return e}})}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[400,935],function(){return n(9531),n(8063),n(7539)}),_N_E=e.O()}]);
|