@viyzhu/boss-cli-fork 0.6.8
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/AGENTS.md +30 -0
- package/LICENSE +674 -0
- package/README.md +223 -0
- package/dist/browser/browser_session.d.ts +27 -0
- package/dist/browser/browser_session.d.ts.map +1 -0
- package/dist/browser/browser_session.js +246 -0
- package/dist/browser/browser_session.js.map +1 -0
- package/dist/browser/cdp_browser.d.ts +50 -0
- package/dist/browser/cdp_browser.d.ts.map +1 -0
- package/dist/browser/cdp_browser.js +315 -0
- package/dist/browser/cdp_browser.js.map +1 -0
- package/dist/browser/human_delay.d.ts +117 -0
- package/dist/browser/human_delay.d.ts.map +1 -0
- package/dist/browser/human_delay.js +71 -0
- package/dist/browser/human_delay.js.map +1 -0
- package/dist/browser/index.d.ts +9 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +9 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/timing.d.ts +7 -0
- package/dist/browser/timing.d.ts.map +1 -0
- package/dist/browser/timing.js +34 -0
- package/dist/browser/timing.js.map +1 -0
- package/dist/browser/viewport_temp.d.ts +15 -0
- package/dist/browser/viewport_temp.d.ts.map +1 -0
- package/dist/browser/viewport_temp.js +78 -0
- package/dist/browser/viewport_temp.js.map +1 -0
- package/dist/cli/banner.d.ts +2 -0
- package/dist/cli/banner.d.ts.map +1 -0
- package/dist/cli/banner.js +69 -0
- package/dist/cli/banner.js.map +1 -0
- package/dist/cli/cliRouter.d.ts +9 -0
- package/dist/cli/cliRouter.d.ts.map +1 -0
- package/dist/cli/cliRouter.js +604 -0
- package/dist/cli/cliRouter.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +34 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/version.d.ts +29 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +180 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/common/auth.d.ts +44 -0
- package/dist/common/auth.d.ts.map +1 -0
- package/dist/common/auth.js +168 -0
- package/dist/common/auth.js.map +1 -0
- package/dist/common/baidu_user_env.d.ts +7 -0
- package/dist/common/baidu_user_env.d.ts.map +1 -0
- package/dist/common/baidu_user_env.js +56 -0
- package/dist/common/baidu_user_env.js.map +1 -0
- package/dist/common/boss_availability.d.ts +5 -0
- package/dist/common/boss_availability.d.ts.map +1 -0
- package/dist/common/boss_availability.js +245 -0
- package/dist/common/boss_availability.js.map +1 -0
- package/dist/common/boss_modal.d.ts +14 -0
- package/dist/common/boss_modal.d.ts.map +1 -0
- package/dist/common/boss_modal.js +81 -0
- package/dist/common/boss_modal.js.map +1 -0
- package/dist/common/boss_page_guards.d.ts +14 -0
- package/dist/common/boss_page_guards.d.ts.map +1 -0
- package/dist/common/boss_page_guards.js +596 -0
- package/dist/common/boss_page_guards.js.map +1 -0
- package/dist/common/boss_paywall_popup.d.ts +28 -0
- package/dist/common/boss_paywall_popup.d.ts.map +1 -0
- package/dist/common/boss_paywall_popup.js +158 -0
- package/dist/common/boss_paywall_popup.js.map +1 -0
- package/dist/common/boss_session_lock.d.ts +2 -0
- package/dist/common/boss_session_lock.d.ts.map +1 -0
- package/dist/common/boss_session_lock.js +127 -0
- package/dist/common/boss_session_lock.js.map +1 -0
- package/dist/common/boss_session_page.d.ts +27 -0
- package/dist/common/boss_session_page.d.ts.map +1 -0
- package/dist/common/boss_session_page.js +173 -0
- package/dist/common/boss_session_page.js.map +1 -0
- package/dist/common/boss_sidebar_nav.d.ts +7 -0
- package/dist/common/boss_sidebar_nav.d.ts.map +1 -0
- package/dist/common/boss_sidebar_nav.js +53 -0
- package/dist/common/boss_sidebar_nav.js.map +1 -0
- package/dist/common/c_resume_capture.d.ts +19 -0
- package/dist/common/c_resume_capture.d.ts.map +1 -0
- package/dist/common/c_resume_capture.js +185 -0
- package/dist/common/c_resume_capture.js.map +1 -0
- package/dist/common/ensure_page.d.ts +9 -0
- package/dist/common/ensure_page.d.ts.map +1 -0
- package/dist/common/ensure_page.js +14 -0
- package/dist/common/ensure_page.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +57 -0
- package/dist/config.js.map +1 -0
- package/dist/ocr/baidu_ocr.d.ts +13 -0
- package/dist/ocr/baidu_ocr.d.ts.map +1 -0
- package/dist/ocr/baidu_ocr.js +80 -0
- package/dist/ocr/baidu_ocr.js.map +1 -0
- package/dist/ocr/index.d.ts +3 -0
- package/dist/ocr/index.d.ts.map +1 -0
- package/dist/ocr/index.js +3 -0
- package/dist/ocr/index.js.map +1 -0
- package/dist/ocr/resume_ocr.d.ts +13 -0
- package/dist/ocr/resume_ocr.d.ts.map +1 -0
- package/dist/ocr/resume_ocr.js +38 -0
- package/dist/ocr/resume_ocr.js.map +1 -0
- package/dist/toolset/action.d.ts +12 -0
- package/dist/toolset/action.d.ts.map +1 -0
- package/dist/toolset/action.js +521 -0
- package/dist/toolset/action.js.map +1 -0
- package/dist/toolset/baidu_credentials.d.ts +5 -0
- package/dist/toolset/baidu_credentials.d.ts.map +1 -0
- package/dist/toolset/baidu_credentials.js +24 -0
- package/dist/toolset/baidu_credentials.js.map +1 -0
- package/dist/toolset/chat.d.ts +10 -0
- package/dist/toolset/chat.d.ts.map +1 -0
- package/dist/toolset/chat.js +763 -0
- package/dist/toolset/chat.js.map +1 -0
- package/dist/toolset/deep-search.d.ts +35 -0
- package/dist/toolset/deep-search.d.ts.map +1 -0
- package/dist/toolset/deep-search.js +1505 -0
- package/dist/toolset/deep-search.js.map +1 -0
- package/dist/toolset/greet.d.ts +6 -0
- package/dist/toolset/greet.d.ts.map +1 -0
- package/dist/toolset/greet.js +81 -0
- package/dist/toolset/greet.js.map +1 -0
- package/dist/toolset/index.d.ts +48 -0
- package/dist/toolset/index.d.ts.map +1 -0
- package/dist/toolset/index.js +71 -0
- package/dist/toolset/index.js.map +1 -0
- package/dist/toolset/jd.d.ts +10 -0
- package/dist/toolset/jd.d.ts.map +1 -0
- package/dist/toolset/jd.js +406 -0
- package/dist/toolset/jd.js.map +1 -0
- package/dist/toolset/list.d.ts +6 -0
- package/dist/toolset/list.d.ts.map +1 -0
- package/dist/toolset/list.js +146 -0
- package/dist/toolset/list.js.map +1 -0
- package/dist/toolset/login.d.ts +6 -0
- package/dist/toolset/login.d.ts.map +1 -0
- package/dist/toolset/login.js +76 -0
- package/dist/toolset/login.js.map +1 -0
- package/dist/toolset/normal-search.d.ts +12 -0
- package/dist/toolset/normal-search.d.ts.map +1 -0
- package/dist/toolset/normal-search.js +301 -0
- package/dist/toolset/normal-search.js.map +1 -0
- package/dist/toolset/preview.d.ts +5 -0
- package/dist/toolset/preview.d.ts.map +1 -0
- package/dist/toolset/preview.js +100 -0
- package/dist/toolset/preview.js.map +1 -0
- package/dist/toolset/recommend.d.ts +36 -0
- package/dist/toolset/recommend.d.ts.map +1 -0
- package/dist/toolset/recommend.js +428 -0
- package/dist/toolset/recommend.js.map +1 -0
- package/dist/toolset/send.d.ts +7 -0
- package/dist/toolset/send.d.ts.map +1 -0
- package/dist/toolset/send.js +52 -0
- package/dist/toolset/send.js.map +1 -0
- package/package.json +69 -0
- package/skills/boss-frontend-analysis/SKILL.md +58 -0
- package/skills/boss-frontend-analysis/agents/openai.yaml +4 -0
- package/skills/boss-frontend-analysis/scripts/capture_boss_frontend.mjs +604 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { sleepRandom } from '../browser/timing.js';
|
|
2
|
+
import { resumeHeight, setTempHeight } from '../browser/viewport_temp.js';
|
|
3
|
+
/** 在线简历 iframe:`src` 常为相对路径 `/web/frame/c-resume/...`,故用子串匹配 */
|
|
4
|
+
export const C_RESUME_IFRAME_SELECTOR = 'iframe[src*="c-resume"], iframe[src*="frame/c-resume"]';
|
|
5
|
+
const CLOSE_C_RESUME_PANEL_SCRIPT = `(() => {
|
|
6
|
+
const sel = ${JSON.stringify(C_RESUME_IFRAME_SELECTOR)};
|
|
7
|
+
function hasCResumeIframe(root) {
|
|
8
|
+
return Array.from(root.querySelectorAll('iframe')).some((iframe) => {
|
|
9
|
+
const src = iframe.getAttribute('src') || '';
|
|
10
|
+
return src.includes('c-resume') || src.includes('frame/c-resume');
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
const wraps = Array.from(document.querySelectorAll('.dialog-lib-resume, .boss-popup__wrapper, .boss-dialog__wrapper, .dialog-container'));
|
|
14
|
+
for (var wi = 0; wi < wraps.length; wi++) {
|
|
15
|
+
var w = wraps[wi];
|
|
16
|
+
if (hasCResumeIframe(w)) {
|
|
17
|
+
var c =
|
|
18
|
+
w.querySelector('.close-btn') ||
|
|
19
|
+
w.querySelector('.boss-popup__close') ||
|
|
20
|
+
w.querySelector('.boss-dialog__close') ||
|
|
21
|
+
w.querySelector('.drawer-close') ||
|
|
22
|
+
w.querySelector('.icon-close') ||
|
|
23
|
+
w.querySelector('.btn-quxiao');
|
|
24
|
+
if (c) {
|
|
25
|
+
c.click();
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
var iframe = document.querySelector(sel);
|
|
31
|
+
var node = iframe ? iframe.parentElement : null;
|
|
32
|
+
for (var i = 0; i < 12 && node; i++) {
|
|
33
|
+
var closeBtn = node.querySelector(
|
|
34
|
+
'.close-btn, .boss-popup__close, .boss-dialog__close, .drawer-close, .icon-close, .btn-quxiao',
|
|
35
|
+
);
|
|
36
|
+
if (closeBtn) {
|
|
37
|
+
closeBtn.click();
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
node = node.parentElement;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
})()`;
|
|
44
|
+
const C_RESUME_CLOSE_AFTER_CAPTURE_DELAY_MS = 3_000;
|
|
45
|
+
const VISIBLE_C_RESUME_IN_FRAME_SCRIPT = `(() => {
|
|
46
|
+
var iframe = document.querySelector(${JSON.stringify(C_RESUME_IFRAME_SELECTOR)});
|
|
47
|
+
if (!(iframe instanceof HTMLElement)) return false;
|
|
48
|
+
var r = iframe.getBoundingClientRect();
|
|
49
|
+
return r.width > 8 && r.height > 8;
|
|
50
|
+
})()`;
|
|
51
|
+
export async function frameHasVisibleCResumeIframe(frame) {
|
|
52
|
+
try {
|
|
53
|
+
return (await frame.evaluate(VISIBLE_C_RESUME_IN_FRAME_SCRIPT));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** 截图文件名安全段(在线简历 / 推荐预览共用) */
|
|
60
|
+
export function safeResumeScreenshotFileBase(name) {
|
|
61
|
+
const t = name.replace(/[/\\?%*:|"<>]/g, '_').trim().slice(0, 64);
|
|
62
|
+
return t.length > 0 ? t : 'candidate';
|
|
63
|
+
}
|
|
64
|
+
/** 关闭含 `c-resume` iframe 的弹层(聊天「在线简历」与推荐「预览」共用)。含 `.boss-popup__close`、`.btn-quxiao`(取消)等。会在主文档与各子 frame 中尝试。 */
|
|
65
|
+
export async function closeCResumePanel(page) {
|
|
66
|
+
try {
|
|
67
|
+
for (let round = 0; round < 5; round++) {
|
|
68
|
+
let closedAny = false;
|
|
69
|
+
for (const frame of page.frames()) {
|
|
70
|
+
try {
|
|
71
|
+
const closed = (await frame.evaluate(CLOSE_C_RESUME_PANEL_SCRIPT));
|
|
72
|
+
closedAny = closedAny || closed;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
/* detached / 无权限 */
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (!closedAny) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
await sleepRandom(200, 450);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
/* ignore */
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 在任意 frame(含主 frame、`recommendFrame` 等)中查找已挂载且尺寸可见的 c-resume iframe。
|
|
90
|
+
*/
|
|
91
|
+
export async function findVisibleCResumeIframeHandle(page) {
|
|
92
|
+
for (const frame of page.frames()) {
|
|
93
|
+
try {
|
|
94
|
+
if (!(await frameHasVisibleCResumeIframe(frame))) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const h = await frame.$(C_RESUME_IFRAME_SELECTOR);
|
|
98
|
+
if (h) {
|
|
99
|
+
return h;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
/* detached */
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
export async function waitForVisibleCResumeIframeReady(page, timeoutMs = 6_000) {
|
|
109
|
+
const deadline = Date.now() + timeoutMs;
|
|
110
|
+
while (Date.now() < deadline) {
|
|
111
|
+
const iframe = await findVisibleCResumeIframeHandle(page);
|
|
112
|
+
if (!iframe) {
|
|
113
|
+
await sleepRandom(100, 180);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const box = await iframe.boundingBox();
|
|
118
|
+
const contentFrame = await iframe.contentFrame();
|
|
119
|
+
if (box && box.width > 8 && box.height > 8) {
|
|
120
|
+
if (!contentFrame) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const ready = (await contentFrame.evaluate(`(() => {
|
|
125
|
+
const body = document.body;
|
|
126
|
+
const doc = document.documentElement;
|
|
127
|
+
const readyStateOk = document.readyState === "complete" || document.readyState === "interactive";
|
|
128
|
+
const contentHeight = Math.max(body?.scrollHeight || 0, doc?.scrollHeight || 0);
|
|
129
|
+
return readyStateOk && contentHeight > 100;
|
|
130
|
+
})()`));
|
|
131
|
+
if (ready) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
await iframe.dispose();
|
|
142
|
+
}
|
|
143
|
+
await sleepRandom(100, 180);
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* 在已出现 `c-resume` iframe 的页面上,对 iframe 整框截图并关闭弹层。
|
|
149
|
+
* `preOpenViewport` 为打开弹层前的视口快照,请用 `snapshotBossPageViewport(page)`(`page.viewport()` 常为 null 时勿直接用默认尺寸)。
|
|
150
|
+
*/
|
|
151
|
+
export async function captureCResumeIframeToFile(page, preOpenViewport, absPath) {
|
|
152
|
+
try {
|
|
153
|
+
await setTempHeight(page, preOpenViewport);
|
|
154
|
+
await waitForVisibleCResumeIframeReady(page, 2_000);
|
|
155
|
+
const iframe = await findVisibleCResumeIframeHandle(page);
|
|
156
|
+
if (!iframe) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
await iframe.evaluate(`((el) => {
|
|
160
|
+
el.scrollIntoView({ block: "start", inline: "nearest" });
|
|
161
|
+
})`);
|
|
162
|
+
const box = await iframe.boundingBox();
|
|
163
|
+
if (!box) {
|
|
164
|
+
await iframe.dispose();
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
await iframe.screenshot({
|
|
169
|
+
path: absPath,
|
|
170
|
+
type: 'png',
|
|
171
|
+
captureBeyondViewport: true,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
await iframe.dispose();
|
|
176
|
+
}
|
|
177
|
+
await sleepRandom(C_RESUME_CLOSE_AFTER_CAPTURE_DELAY_MS, C_RESUME_CLOSE_AFTER_CAPTURE_DELAY_MS);
|
|
178
|
+
await closeCResumePanel(page);
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
await resumeHeight(page, preOpenViewport);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=c_resume_capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"c_resume_capture.js","sourceRoot":"","sources":["../../src/common/c_resume_capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Page } from 'puppeteer-core';
|
|
2
|
+
export type EnsurePageOptions = {
|
|
3
|
+
name: string;
|
|
4
|
+
targetUrl: string;
|
|
5
|
+
matches: (url: string) => boolean;
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function ensurePage(page: Page, opts: EnsurePageOptions): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=ensure_page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure_page.d.ts","sourceRoot":"","sources":["../../src/common/ensure_page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAenF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export async function ensurePage(page, opts) {
|
|
2
|
+
const startUrl = page.url();
|
|
3
|
+
if (!opts.matches(startUrl)) {
|
|
4
|
+
await page.goto(opts.targetUrl, {
|
|
5
|
+
waitUntil: 'load',
|
|
6
|
+
timeout: opts.timeoutMs ?? 60_000,
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
const currentUrl = page.url();
|
|
10
|
+
if (!opts.matches(currentUrl)) {
|
|
11
|
+
throw new Error(`进入${opts.name}失败。起始页面:${startUrl || 'unknown'};当前页面:${currentUrl || 'unknown'};目标页面:${opts.targetUrl}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=ensure_page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure_page.js","sourceRoot":"","sources":["../../src/common/ensure_page.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAU,EAAE,IAAuB;IAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAC9B,SAAS,EAAE,MAAM;YACjB,OAAO,EAAE,IAAI,CAAC,SAAS,IAAI,MAAM;SAClC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,KAAK,IAAI,CAAC,IAAI,WAAW,QAAQ,IAAI,SAAS,SAAS,UAAU,IAAI,SAAS,SAAS,IAAI,CAAC,SAAS,EAAE,CACxG,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 多数 Agent 客户端约定的 skills 根目录(如 `~/.agents/skills`)。
|
|
3
|
+
* 可用 `BOSS_AGENT_SKILLS_DIR` 设为绝对路径以覆盖。
|
|
4
|
+
*/
|
|
5
|
+
export declare function getAgentSkillsDir(): string;
|
|
6
|
+
/** 应用主目录(业务数据在 .cache 下) */
|
|
7
|
+
export declare const APP_HOME: string;
|
|
8
|
+
/** 存放岗位 JD 的目录(每个岗位一个 .md 文件) */
|
|
9
|
+
export declare const JD_DIR: string;
|
|
10
|
+
/**
|
|
11
|
+
* 应用缓存与生成数据根目录(浏览器配置等)
|
|
12
|
+
*/
|
|
13
|
+
export declare const CACHE_DIR: string;
|
|
14
|
+
/** Puppeteer 用户数据目录(与 CDP 启动默认目录一致) */
|
|
15
|
+
export declare const BROWSER_USER_DATA_DIR: string;
|
|
16
|
+
/** `chat` 抓取在线简历时对 iframe 区域截图保存目录 */
|
|
17
|
+
export declare const RESUME_SCREENSHOTS_DIR: string;
|
|
18
|
+
/** 在线简历截图经 OCR 后的纯文本保存目录(与截图同名 `.txt`) */
|
|
19
|
+
export declare const RESUME_OCR_DIR: string;
|
|
20
|
+
/** 确保 `~/.boss-cli/.cache` 目录存在(幂等) */
|
|
21
|
+
export declare function ensureAppDataLayout(): void;
|
|
22
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAM1C;AAED,4BAA4B;AAC5B,eAAO,MAAM,QAAQ,QAA+B,CAAC;AAErD,iCAAiC;AACjC,eAAO,MAAM,MAAM,QAAuB,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,SAAS,QAA2B,CAAC;AAElD,uCAAuC;AACvC,eAAO,MAAM,qBAAqB,QAAkC,CAAC;AAErE,sCAAsC;AACtC,eAAO,MAAM,sBAAsB,QAAwC,CAAC;AAE5E,0CAA0C;AAC1C,eAAO,MAAM,cAAc,QAAyB,CAAC;AAIrD,uCAAuC;AACvC,wBAAgB,mBAAmB,IAAI,IAAI,CAwB1C"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// 配置文件 — 应用数据位于 ~/.boss-cli/.cache/
|
|
2
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
/**
|
|
6
|
+
* 多数 Agent 客户端约定的 skills 根目录(如 `~/.agents/skills`)。
|
|
7
|
+
* 可用 `BOSS_AGENT_SKILLS_DIR` 设为绝对路径以覆盖。
|
|
8
|
+
*/
|
|
9
|
+
export function getAgentSkillsDir() {
|
|
10
|
+
const raw = process.env.BOSS_AGENT_SKILLS_DIR?.trim();
|
|
11
|
+
if (raw && raw.length > 0) {
|
|
12
|
+
return raw;
|
|
13
|
+
}
|
|
14
|
+
return join(homedir(), '.agents', 'skills');
|
|
15
|
+
}
|
|
16
|
+
/** 应用主目录(业务数据在 .cache 下) */
|
|
17
|
+
export const APP_HOME = join(homedir(), '.boss-cli');
|
|
18
|
+
/** 存放岗位 JD 的目录(每个岗位一个 .md 文件) */
|
|
19
|
+
export const JD_DIR = join(APP_HOME, 'jd');
|
|
20
|
+
/**
|
|
21
|
+
* 应用缓存与生成数据根目录(浏览器配置等)
|
|
22
|
+
*/
|
|
23
|
+
export const CACHE_DIR = join(APP_HOME, '.cache');
|
|
24
|
+
/** Puppeteer 用户数据目录(与 CDP 启动默认目录一致) */
|
|
25
|
+
export const BROWSER_USER_DATA_DIR = join(CACHE_DIR, 'browser-data');
|
|
26
|
+
/** `chat` 抓取在线简历时对 iframe 区域截图保存目录 */
|
|
27
|
+
export const RESUME_SCREENSHOTS_DIR = join(CACHE_DIR, 'resume-screenshots');
|
|
28
|
+
/** 在线简历截图经 OCR 后的纯文本保存目录(与截图同名 `.txt`) */
|
|
29
|
+
export const RESUME_OCR_DIR = join(CACHE_DIR, 'ocr');
|
|
30
|
+
let appDataLayoutReady = false;
|
|
31
|
+
/** 确保 `~/.boss-cli/.cache` 目录存在(幂等) */
|
|
32
|
+
export function ensureAppDataLayout() {
|
|
33
|
+
if (appDataLayoutReady) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
appDataLayoutReady = true;
|
|
37
|
+
if (!existsSync(CACHE_DIR)) {
|
|
38
|
+
mkdirSync(CACHE_DIR, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
if (!existsSync(BROWSER_USER_DATA_DIR)) {
|
|
41
|
+
mkdirSync(BROWSER_USER_DATA_DIR, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
if (!existsSync(JD_DIR)) {
|
|
44
|
+
mkdirSync(JD_DIR, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
if (!existsSync(RESUME_SCREENSHOTS_DIR)) {
|
|
47
|
+
mkdirSync(RESUME_SCREENSHOTS_DIR, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
if (!existsSync(RESUME_OCR_DIR)) {
|
|
50
|
+
mkdirSync(RESUME_OCR_DIR, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
const agentSkills = getAgentSkillsDir();
|
|
53
|
+
if (!existsSync(agentSkills)) {
|
|
54
|
+
mkdirSync(agentSkills, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,oCAAoC;AAEpC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,EAAE,CAAC;IACtD,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC9C,CAAC;AAED,4BAA4B;AAC5B,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAErD,iCAAiC;AACjC,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAElD,uCAAuC;AACvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAErE,sCAAsC;AACtC,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAE5E,0CAA0C;AAC1C,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AAErD,IAAI,kBAAkB,GAAG,KAAK,CAAC;AAE/B,uCAAuC;AACvC,MAAM,UAAU,mBAAmB;IACjC,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IACD,kBAAkB,GAAG,IAAI,CAAC;IAC1B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACvC,SAAS,CAAC,qBAAqB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;QACxC,SAAS,CAAC,sBAAsB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAC;IACxC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 百度 AI 开放平台:OAuth + 通用文字识别(高精度含位置版 accurate_basic)。
|
|
3
|
+
* 需在环境变量中配置 `API_KEY`、`SECRET_KEY`(与百度控制台一致)。
|
|
4
|
+
* @see https://ai.baidu.com/ai-doc/OCR/zk3h7xz52
|
|
5
|
+
*/
|
|
6
|
+
export declare function isBaiduOcrConfigured(): boolean;
|
|
7
|
+
/** 更换密钥后应调用,避免沿用旧 access_token。 */
|
|
8
|
+
export declare function clearBaiduTokenCache(): void;
|
|
9
|
+
/** 获取 access_token(带简单内存缓存,过期前 1 分钟刷新)。 */
|
|
10
|
+
export declare function getBaiduAccessToken(): Promise<string>;
|
|
11
|
+
/** 对整张 PNG/JPG 做高精度识别,返回合并文本(按行拼接)。 */
|
|
12
|
+
export declare function baiduOcrImageBase64(imageBase64: string): Promise<string>;
|
|
13
|
+
//# sourceMappingURL=baidu_ocr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baidu_ocr.d.ts","sourceRoot":"","sources":["../../src/ocr/baidu_ocr.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAID,mCAAmC;AACnC,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED,2CAA2C;AAC3C,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CA4C3D;AAID,uCAAuC;AACvC,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgC9E"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 百度 AI 开放平台:OAuth + 通用文字识别(高精度含位置版 accurate_basic)。
|
|
3
|
+
* 需在环境变量中配置 `API_KEY`、`SECRET_KEY`(与百度控制台一致)。
|
|
4
|
+
* @see https://ai.baidu.com/ai-doc/OCR/zk3h7xz52
|
|
5
|
+
*/
|
|
6
|
+
const BAIDU_TOKEN_URL = 'https://aip.baidubce.com/oauth/2.0/token';
|
|
7
|
+
const BAIDU_OCR_ACCURATE_BASIC = 'https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic';
|
|
8
|
+
function apiKey() {
|
|
9
|
+
return process.env.API_KEY?.trim() || process.env.BOSS_BAIDU_API_KEY?.trim();
|
|
10
|
+
}
|
|
11
|
+
function secretKey() {
|
|
12
|
+
return process.env.SECRET_KEY?.trim() || process.env.BOSS_BAIDU_SECRET_KEY?.trim();
|
|
13
|
+
}
|
|
14
|
+
export function isBaiduOcrConfigured() {
|
|
15
|
+
return !!(apiKey() && secretKey());
|
|
16
|
+
}
|
|
17
|
+
let cachedToken = null;
|
|
18
|
+
/** 更换密钥后应调用,避免沿用旧 access_token。 */
|
|
19
|
+
export function clearBaiduTokenCache() {
|
|
20
|
+
cachedToken = null;
|
|
21
|
+
}
|
|
22
|
+
/** 获取 access_token(带简单内存缓存,过期前 1 分钟刷新)。 */
|
|
23
|
+
export async function getBaiduAccessToken() {
|
|
24
|
+
const client_id = apiKey();
|
|
25
|
+
const client_secret = secretKey();
|
|
26
|
+
if (!client_id || !client_secret) {
|
|
27
|
+
throw new Error('缺少百度 OCR 凭证:请设置 API_KEY 与 SECRET_KEY(或 BOSS_BAIDU_API_KEY / BOSS_BAIDU_SECRET_KEY)');
|
|
28
|
+
}
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
if (cachedToken && now < cachedToken.expiresAtMs - 60_000) {
|
|
31
|
+
return cachedToken.token;
|
|
32
|
+
}
|
|
33
|
+
const u = new URL(BAIDU_TOKEN_URL);
|
|
34
|
+
u.searchParams.set('grant_type', 'client_credentials');
|
|
35
|
+
u.searchParams.set('client_id', client_id);
|
|
36
|
+
u.searchParams.set('client_secret', client_secret);
|
|
37
|
+
const res = await fetch(u.toString(), {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: {
|
|
40
|
+
'Content-Type': 'application/json',
|
|
41
|
+
Accept: 'application/json',
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
const data = (await res.json());
|
|
45
|
+
if (!res.ok || !data.access_token) {
|
|
46
|
+
throw new Error(`百度 OAuth 失败: ${res.status} ${data.error ?? ''} ${data.error_description ?? JSON.stringify(data)}`);
|
|
47
|
+
}
|
|
48
|
+
const expiresInSec = typeof data.expires_in === 'number' ? data.expires_in : 2592000;
|
|
49
|
+
cachedToken = {
|
|
50
|
+
token: data.access_token,
|
|
51
|
+
expiresAtMs: now + expiresInSec * 1000,
|
|
52
|
+
};
|
|
53
|
+
return data.access_token;
|
|
54
|
+
}
|
|
55
|
+
/** 对整张 PNG/JPG 做高精度识别,返回合并文本(按行拼接)。 */
|
|
56
|
+
export async function baiduOcrImageBase64(imageBase64) {
|
|
57
|
+
const token = await getBaiduAccessToken();
|
|
58
|
+
const url = new URL(BAIDU_OCR_ACCURATE_BASIC);
|
|
59
|
+
url.searchParams.set('access_token', token);
|
|
60
|
+
const body = new URLSearchParams();
|
|
61
|
+
body.set('image', imageBase64);
|
|
62
|
+
body.set('language_type', 'CHN_ENG');
|
|
63
|
+
const res = await fetch(url.toString(), {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
67
|
+
Accept: 'application/json',
|
|
68
|
+
},
|
|
69
|
+
body: body.toString(),
|
|
70
|
+
});
|
|
71
|
+
const data = (await res.json());
|
|
72
|
+
if (!res.ok || (data.error_code !== undefined && data.error_code !== 0)) {
|
|
73
|
+
throw new Error(`百度 OCR 失败: ${res.status} ${data.error_msg ?? JSON.stringify(data)}`);
|
|
74
|
+
}
|
|
75
|
+
const lines = (data.words_result ?? [])
|
|
76
|
+
.map((r) => (r.words ?? '').trim())
|
|
77
|
+
.filter((s) => s.length > 0);
|
|
78
|
+
return lines.join('\n').trim();
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=baidu_ocr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baidu_ocr.js","sourceRoot":"","sources":["../../src/ocr/baidu_ocr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ocr/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ocr/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 是否对在线简历截图做 OCR。关闭:`BOSS_RESUME_OCR=0`。
|
|
3
|
+
* 开启时需配置百度 `API_KEY` + `SECRET_KEY`(在线识别,无本地引擎)。
|
|
4
|
+
*/
|
|
5
|
+
export declare function isResumeOcrEnabled(): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* 对简历区域 PNG 调用百度 OCR,将结果写入 `~/.boss-cli/.cache/ocr/`(与截图同名 `.txt`)。
|
|
8
|
+
*/
|
|
9
|
+
export declare function ocrResumePngToTextFile(pngAbsPath: string): Promise<{
|
|
10
|
+
textPath: string;
|
|
11
|
+
text: string;
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=resume_ocr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume_ocr.d.ts","sourceRoot":"","sources":["../../src/ocr/resume_ocr.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAG5C;AAKD;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAwB5G"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { basename, join } from 'node:path';
|
|
2
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { ensureAppDataLayout, RESUME_OCR_DIR } from '../config.js';
|
|
4
|
+
import { baiduOcrImageBase64, isBaiduOcrConfigured } from './baidu_ocr.js';
|
|
5
|
+
/**
|
|
6
|
+
* 是否对在线简历截图做 OCR。关闭:`BOSS_RESUME_OCR=0`。
|
|
7
|
+
* 开启时需配置百度 `API_KEY` + `SECRET_KEY`(在线识别,无本地引擎)。
|
|
8
|
+
*/
|
|
9
|
+
export function isResumeOcrEnabled() {
|
|
10
|
+
const v = process.env.BOSS_RESUME_OCR?.trim().toLowerCase();
|
|
11
|
+
return v !== '0' && v !== 'false' && v !== 'no';
|
|
12
|
+
}
|
|
13
|
+
/** 串行执行 OCR,避免并发请求交错 */
|
|
14
|
+
let ocrChain = Promise.resolve();
|
|
15
|
+
/**
|
|
16
|
+
* 对简历区域 PNG 调用百度 OCR,将结果写入 `~/.boss-cli/.cache/ocr/`(与截图同名 `.txt`)。
|
|
17
|
+
*/
|
|
18
|
+
export async function ocrResumePngToTextFile(pngAbsPath) {
|
|
19
|
+
ensureAppDataLayout();
|
|
20
|
+
if (!isBaiduOcrConfigured()) {
|
|
21
|
+
throw new Error('已开启简历 OCR(BOSS_RESUME_OCR),但未配置百度密钥:请设置 API_KEY 与 SECRET_KEY(或 BOSS_BAIDU_API_KEY / BOSS_BAIDU_SECRET_KEY)。');
|
|
22
|
+
}
|
|
23
|
+
const base = basename(pngAbsPath).replace(/\.png$/i, '.txt');
|
|
24
|
+
const textPath = join(RESUME_OCR_DIR, base);
|
|
25
|
+
const run = async () => {
|
|
26
|
+
const buf = await readFile(pngAbsPath);
|
|
27
|
+
const text = await baiduOcrImageBase64(buf.toString('base64'));
|
|
28
|
+
await writeFile(textPath, text.endsWith('\n') ? text : `${text}\n`, 'utf8');
|
|
29
|
+
return { textPath, text };
|
|
30
|
+
};
|
|
31
|
+
const p = ocrChain.then(run);
|
|
32
|
+
ocrChain = p.catch((err) => {
|
|
33
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
34
|
+
console.error('[boss-cli] resume OCR chain reset after failure:', msg);
|
|
35
|
+
});
|
|
36
|
+
return p;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=resume_ocr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume_ocr.js","sourceRoot":"","sources":["../../src/ocr/resume_ocr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3E;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5D,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,IAAI,CAAC;AAClD,CAAC;AAED,wBAAwB;AACxB,IAAI,QAAQ,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;AAEnD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,UAAkB;IAC7D,mBAAmB,EAAE,CAAC;IACtB,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,6GAA6G,CAC9G,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAE5C,MAAM,GAAG,GAAG,KAAK,IAAiD,EAAE;QAClE,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/D,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5E,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACzB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,CAAC,KAAK,CAAC,kDAAkD,EAAE,GAAG,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Page } from 'puppeteer-core';
|
|
2
|
+
/**
|
|
3
|
+
* 在聊天页左侧工具栏点击「求简历」,并在确认弹窗中点「确定」。
|
|
4
|
+
* 平台规则:双方需各至少发送一条消息后该入口才可点;否则按钮为禁用态。
|
|
5
|
+
*/
|
|
6
|
+
export declare function runRequestAttachmentResume(page: Page): Promise<string>;
|
|
7
|
+
export type ChatPageAction = 'resume' | 'not-fit' | 'remark' | 'agree-resume' | 'request-attachment-resume' | 'history' | 'exchange-wechat';
|
|
8
|
+
export declare function runChatActionOnCurrentConversation(page: Page, options: {
|
|
9
|
+
action: ChatPageAction;
|
|
10
|
+
remark?: string;
|
|
11
|
+
}): Promise<string>;
|
|
12
|
+
//# sourceMappingURL=action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../src/toolset/action.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAmM3C;;;GAGG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAiG5E;AA8PD,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,cAAc,GACd,2BAA2B,GAC3B,SAAS,GACT,iBAAiB,CAAC;AAEtB,wBAAsB,kCAAkC,CACtD,IAAI,EAAE,IAAI,EACV,OAAO,EAAE;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAAC,MAAM,CAAC,CAsCjB"}
|