ppxc-leads-mcp 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/README.md +115 -0
- package/dist/backend/config.js +13 -0
- package/dist/backend/ppxc-client.js +156 -0
- package/dist/backend/ppxc-login-window.js +168 -0
- package/dist/backend/token-store.js +65 -0
- package/dist/browser/comments.js +9 -0
- package/dist/browser/douyin-runner.js +15 -0
- package/dist/browser/kernel/electron-profile.js +32 -0
- package/dist/browser/kernel/logger.js +57 -0
- package/dist/browser/kernel/page-scripts/index.js +1422 -0
- package/dist/browser/kernel/runner-page-manager.js +145 -0
- package/dist/browser/kernel/runner-page-session.js +1465 -0
- package/dist/browser/kernel/runner-page-session.search-parser.js +187 -0
- package/dist/browser/kernel/runner-page-session.user-agent.js +32 -0
- package/dist/browser/platform-runner.js +312 -0
- package/dist/browser/platforms/detect-platform.js +33 -0
- package/dist/browser/platforms/douyin/adapter.js +162 -0
- package/dist/browser/platforms/douyin/comments.js +130 -0
- package/dist/browser/platforms/kuaishou/adapter.js +178 -0
- package/dist/browser/platforms/kuaishou/comments.js +170 -0
- package/dist/browser/platforms/registry.js +23 -0
- package/dist/browser/platforms/shared/cdp-json-waiter.js +75 -0
- package/dist/browser/platforms/types.js +3 -0
- package/dist/browser/platforms/xiaohongshu/adapter.js +233 -0
- package/dist/browser/platforms/xiaohongshu/comments.js +184 -0
- package/dist/browser/usage-throttle.js +72 -0
- package/dist/main.js +64 -0
- package/dist/mcp/battle-report.js +325 -0
- package/dist/mcp/content-insights.js +66 -0
- package/dist/mcp/diagnostics.js +79 -0
- package/dist/mcp/server.js +829 -0
- package/dist/version.js +19 -0
- package/package.json +43 -0
- package/scripts/launch-mcp.cjs +96 -0
- package/skills/ppxc-find-customers/SKILL.md +110 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RunnerPageManager = void 0;
|
|
4
|
+
const logger_1 = require("./logger");
|
|
5
|
+
const runner_page_session_1 = require("./runner-page-session");
|
|
6
|
+
const log = logger_1.logger.scope("page-manager");
|
|
7
|
+
class RunnerPageManager {
|
|
8
|
+
constructor(opts = {}) {
|
|
9
|
+
this._sessions = new Map();
|
|
10
|
+
this._windowCreateIndexes = new Map();
|
|
11
|
+
this._lastRecycleReasons = new Map();
|
|
12
|
+
this._opts = {
|
|
13
|
+
maxConcurrent: opts.maxConcurrent ?? 2,
|
|
14
|
+
defaultVisible: opts.defaultVisible ?? false,
|
|
15
|
+
navigationTimeoutMs: opts.navigationTimeoutMs ?? 25000,
|
|
16
|
+
collectMaxWaitMs: opts.collectMaxWaitMs ?? 12000,
|
|
17
|
+
collectMaxItems: opts.collectMaxItems ?? 30,
|
|
18
|
+
sessionDefaults: opts.sessionDefaults ?? {},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
acquire(slotId, override) {
|
|
22
|
+
const existing = this._sessions.get(slotId);
|
|
23
|
+
if (existing && existing.isAlive()) {
|
|
24
|
+
if (existing.shouldRecycleOnRelease()) {
|
|
25
|
+
const reason = existing.lastRecycleReason ?? "recycle_after_session_marked_unusable";
|
|
26
|
+
this._lastRecycleReasons.set(slotId, reason);
|
|
27
|
+
log.warn(`slot ${slotId} previous session marked for recycle, will create fresh`, {
|
|
28
|
+
reason,
|
|
29
|
+
sessionId: existing.sessionId,
|
|
30
|
+
windowCreateIndex: existing.windowCreateIndex,
|
|
31
|
+
});
|
|
32
|
+
void existing.close();
|
|
33
|
+
this._sessions.delete(slotId);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
if (override?.visible === true) {
|
|
37
|
+
existing.reveal();
|
|
38
|
+
}
|
|
39
|
+
log.info(`slot ${slotId} session reused`, {
|
|
40
|
+
total: this._sessions.size,
|
|
41
|
+
warmed: existing.isWarmed(),
|
|
42
|
+
sessionId: existing.sessionId,
|
|
43
|
+
windowCreateIndex: existing.windowCreateIndex,
|
|
44
|
+
});
|
|
45
|
+
return existing;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (existing && !existing.isAlive()) {
|
|
49
|
+
log.warn(`slot ${slotId} previous session dead, will create fresh`);
|
|
50
|
+
void existing.close();
|
|
51
|
+
this._sessions.delete(slotId);
|
|
52
|
+
}
|
|
53
|
+
if (this._sessions.size >= this._opts.maxConcurrent) {
|
|
54
|
+
throw new Error(`RunnerPageManager: max concurrent sessions reached (${this._opts.maxConcurrent})`);
|
|
55
|
+
}
|
|
56
|
+
const windowCreateIndex = (this._windowCreateIndexes.get(slotId) ?? 0) + 1;
|
|
57
|
+
this._windowCreateIndexes.set(slotId, windowCreateIndex);
|
|
58
|
+
const session = new runner_page_session_1.RunnerPageSession({
|
|
59
|
+
slotId,
|
|
60
|
+
windowCreateIndex,
|
|
61
|
+
lastRecycleReason: this._lastRecycleReasons.get(slotId) ?? null,
|
|
62
|
+
visible: override?.visible ?? this._opts.defaultVisible,
|
|
63
|
+
navigationTimeoutMs: override?.navigationTimeoutMs ?? this._opts.navigationTimeoutMs,
|
|
64
|
+
collectMaxWaitMs: override?.collectMaxWaitMs ?? this._opts.collectMaxWaitMs,
|
|
65
|
+
collectMaxItems: override?.collectMaxItems ?? this._opts.collectMaxItems,
|
|
66
|
+
...this._opts.sessionDefaults,
|
|
67
|
+
...override,
|
|
68
|
+
});
|
|
69
|
+
this._sessions.set(slotId, session);
|
|
70
|
+
log.info(`slot ${slotId} session created`, {
|
|
71
|
+
total: this._sessions.size,
|
|
72
|
+
maxConcurrent: this._opts.maxConcurrent,
|
|
73
|
+
sessionId: session.sessionId,
|
|
74
|
+
windowCreateIndex,
|
|
75
|
+
lastRecycleReason: session.lastRecycleReason,
|
|
76
|
+
});
|
|
77
|
+
return session;
|
|
78
|
+
}
|
|
79
|
+
async release(slotId) {
|
|
80
|
+
const session = this._sessions.get(slotId);
|
|
81
|
+
if (!session)
|
|
82
|
+
return;
|
|
83
|
+
this._sessions.delete(slotId);
|
|
84
|
+
if (session.lastRecycleReason) {
|
|
85
|
+
this._lastRecycleReasons.set(slotId, session.lastRecycleReason);
|
|
86
|
+
}
|
|
87
|
+
await session.close();
|
|
88
|
+
log.info(`slot ${slotId} session released`, { total: this._sessions.size });
|
|
89
|
+
}
|
|
90
|
+
async invalidate(slotId, opts = {}) {
|
|
91
|
+
const session = this._sessions.get(slotId);
|
|
92
|
+
if (!session)
|
|
93
|
+
return;
|
|
94
|
+
const reason = opts.reason ?? "unknown";
|
|
95
|
+
session.invalidateWarmed();
|
|
96
|
+
session.markForRecycle(reason);
|
|
97
|
+
this._lastRecycleReasons.set(slotId, reason);
|
|
98
|
+
log.warn(`slot ${slotId} session invalidated`, {
|
|
99
|
+
reason,
|
|
100
|
+
release: opts.release === true,
|
|
101
|
+
total: this._sessions.size,
|
|
102
|
+
sessionId: session.sessionId,
|
|
103
|
+
windowCreateIndex: session.windowCreateIndex,
|
|
104
|
+
});
|
|
105
|
+
if (opts.release === true) {
|
|
106
|
+
await this.release(slotId);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
reveal(slotId) {
|
|
110
|
+
return this._sessions.get(slotId)?.reveal() === true;
|
|
111
|
+
}
|
|
112
|
+
revealStatus(slotId) {
|
|
113
|
+
const session = this._sessions.get(slotId);
|
|
114
|
+
if (!session) {
|
|
115
|
+
return {
|
|
116
|
+
alive: false,
|
|
117
|
+
visible: false,
|
|
118
|
+
focused: false,
|
|
119
|
+
minimized: false,
|
|
120
|
+
bounds: null,
|
|
121
|
+
platform: process.platform,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return session.revealStatus();
|
|
125
|
+
}
|
|
126
|
+
getSession(slotId) {
|
|
127
|
+
return this._sessions.get(slotId) ?? null;
|
|
128
|
+
}
|
|
129
|
+
hideAll() {
|
|
130
|
+
for (const s of this._sessions.values()) {
|
|
131
|
+
s.hide();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async destroyAll() {
|
|
135
|
+
const all = Array.from(this._sessions.values());
|
|
136
|
+
this._sessions.clear();
|
|
137
|
+
await Promise.all(all.map((s) => s.close().catch(() => undefined)));
|
|
138
|
+
log.info(`destroyed all sessions`, { count: all.length });
|
|
139
|
+
}
|
|
140
|
+
get activeSlotIds() {
|
|
141
|
+
return Array.from(this._sessions.keys());
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
exports.RunnerPageManager = RunnerPageManager;
|
|
145
|
+
//# sourceMappingURL=runner-page-manager.js.map
|