@joohw/boss-cli 0.1.1

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.
Files changed (68) hide show
  1. package/AGENTS.md +25 -0
  2. package/LICENSE +674 -0
  3. package/README.md +81 -0
  4. package/dist/browser/auth.d.ts +34 -0
  5. package/dist/browser/auth.d.ts.map +1 -0
  6. package/dist/browser/auth.js +153 -0
  7. package/dist/browser/auth.js.map +1 -0
  8. package/dist/browser/browser_session.d.ts +17 -0
  9. package/dist/browser/browser_session.d.ts.map +1 -0
  10. package/dist/browser/browser_session.js +156 -0
  11. package/dist/browser/browser_session.js.map +1 -0
  12. package/dist/browser/cdp_browser.d.ts +34 -0
  13. package/dist/browser/cdp_browser.d.ts.map +1 -0
  14. package/dist/browser/cdp_browser.js +95 -0
  15. package/dist/browser/cdp_browser.js.map +1 -0
  16. package/dist/browser/chat.d.ts +7 -0
  17. package/dist/browser/chat.d.ts.map +1 -0
  18. package/dist/browser/chat.js +63 -0
  19. package/dist/browser/chat.js.map +1 -0
  20. package/dist/browser/index.d.ts +9 -0
  21. package/dist/browser/index.d.ts.map +1 -0
  22. package/dist/browser/index.js +9 -0
  23. package/dist/browser/index.js.map +1 -0
  24. package/dist/browser/withLoggedInPage.d.ts +7 -0
  25. package/dist/browser/withLoggedInPage.d.ts.map +1 -0
  26. package/dist/browser/withLoggedInPage.js +19 -0
  27. package/dist/browser/withLoggedInPage.js.map +1 -0
  28. package/dist/cli/banner.d.ts +2 -0
  29. package/dist/cli/banner.d.ts.map +1 -0
  30. package/dist/cli/banner.js +27 -0
  31. package/dist/cli/banner.js.map +1 -0
  32. package/dist/cli/cliRouter.d.ts +9 -0
  33. package/dist/cli/cliRouter.d.ts.map +1 -0
  34. package/dist/cli/cliRouter.js +254 -0
  35. package/dist/cli/cliRouter.js.map +1 -0
  36. package/dist/cli/index.d.ts +3 -0
  37. package/dist/cli/index.d.ts.map +1 -0
  38. package/dist/cli/index.js +21 -0
  39. package/dist/cli/index.js.map +1 -0
  40. package/dist/config.d.ts +11 -0
  41. package/dist/config.d.ts.map +1 -0
  42. package/dist/config.js +27 -0
  43. package/dist/config.js.map +1 -0
  44. package/dist/toolset/index.d.ts +7 -0
  45. package/dist/toolset/index.d.ts.map +1 -0
  46. package/dist/toolset/index.js +26 -0
  47. package/dist/toolset/index.js.map +1 -0
  48. package/dist/toolset/list_candidates.d.ts +4 -0
  49. package/dist/toolset/list_candidates.d.ts.map +1 -0
  50. package/dist/toolset/list_candidates.js +127 -0
  51. package/dist/toolset/list_candidates.js.map +1 -0
  52. package/dist/toolset/list_positions.d.ts +9 -0
  53. package/dist/toolset/list_positions.d.ts.map +1 -0
  54. package/dist/toolset/list_positions.js +41 -0
  55. package/dist/toolset/list_positions.js.map +1 -0
  56. package/dist/toolset/login.d.ts +11 -0
  57. package/dist/toolset/login.d.ts.map +1 -0
  58. package/dist/toolset/login.js +91 -0
  59. package/dist/toolset/login.js.map +1 -0
  60. package/dist/toolset/open_chat.d.ts +3 -0
  61. package/dist/toolset/open_chat.d.ts.map +1 -0
  62. package/dist/toolset/open_chat.js +181 -0
  63. package/dist/toolset/open_chat.js.map +1 -0
  64. package/dist/toolset/send_message.d.ts +2 -0
  65. package/dist/toolset/send_message.d.ts.map +1 -0
  66. package/dist/toolset/send_message.js +115 -0
  67. package/dist/toolset/send_message.js.map +1 -0
  68. package/package.json +30 -0
@@ -0,0 +1,63 @@
1
+ import { ensureBrowserSession, getBrowserRef, getPageRef, setSessionPage } from './browser_session.js';
2
+ import { BOSS_CHAT_INDEX_URL, isBossChatIndexUrl, sleep } from './auth.js';
3
+ const SHOULD_DISABLE_JS = process.env.BOSS_BROWSER_DISABLE_JS === 'true' || process.env.BOSS_BROWSER_DISABLE_JS === '1';
4
+ async function pickExistingPage(browser) {
5
+ const pages = (await browser.pages()).filter((p) => !p.isClosed());
6
+ if (pages.length === 0)
7
+ return null;
8
+ const urls = await Promise.all(pages.map((p) => {
9
+ try {
10
+ return p.url();
11
+ }
12
+ catch {
13
+ return '';
14
+ }
15
+ }));
16
+ const zhipin = pages.find((p, i) => {
17
+ const u = urls[i] ?? '';
18
+ return u.length > 0 && u !== 'about:blank' && u.includes('zhipin.com');
19
+ });
20
+ if (zhipin)
21
+ return zhipin;
22
+ const nonBlank = pages.find((p, i) => {
23
+ const u = urls[i] ?? '';
24
+ return u.length > 0 && u !== 'about:blank';
25
+ });
26
+ return nonBlank ?? null;
27
+ }
28
+ /**
29
+ * 获取 chat page 来执行回调:确保已启动浏览器并导航到 Boss 沟通列表页(/web/chat/index)。
30
+ * 仅负责“浏览器状态/导航”,不在这里做登录成功与否的业务判断。
31
+ */
32
+ export async function withChatPage(callback) {
33
+ await ensureBrowserSession();
34
+ const browser = getBrowserRef();
35
+ if (!browser) {
36
+ throw new Error('无法获取浏览器实例。');
37
+ }
38
+ let page = getPageRef();
39
+ if (!page || page.isClosed()) {
40
+ page = (await pickExistingPage(browser)) ?? (await browser.newPage());
41
+ }
42
+ setSessionPage(page);
43
+ await page.bringToFront();
44
+ if (SHOULD_DISABLE_JS) {
45
+ await page.setJavaScriptEnabled(false);
46
+ }
47
+ // 如果当前已在沟通列表页,则不刷新页面,避免打断用户状态(滚动位置/选中会话等)。
48
+ const currentUrl = (() => {
49
+ try {
50
+ return page.url();
51
+ }
52
+ catch {
53
+ return '';
54
+ }
55
+ })();
56
+ if (!isBossChatIndexUrl(currentUrl)) {
57
+ await page.goto(BOSS_CHAT_INDEX_URL, { waitUntil: 'load', timeout: 60_000 });
58
+ // 等待页面渲染稳定(SPA/异步接口),避免紧接着查询元素时拿不到
59
+ await sleep(2_000);
60
+ }
61
+ return callback(page);
62
+ }
63
+ //# sourceMappingURL=chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/browser/chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 浏览器:CDP 连接与会话(统一出口)。
3
+ */
4
+ export { connectBrowser, createPageCDPSession, LAUNCH_ARGS_ALLOW_ALL_CORS, LAUNCH_ARGS_LESS_AUTOMATION, type ConnectBrowserOptions, } from './cdp_browser.js';
5
+ export { disconnectBrowserSession, ensureAndGetBrowser, ensureBrowserSession, getBrowserRef, getPageRef, setSessionPage, } from './browser_session.js';
6
+ export * from './auth.js';
7
+ export { withLoggedInPage } from './withLoggedInPage.js';
8
+ export { withChatPage } from './chat.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,0BAA0B,EAC1B,2BAA2B,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,UAAU,EACV,cAAc,GACf,MAAM,sBAAsB,CAAC;AAE9B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 浏览器:CDP 连接与会话(统一出口)。
3
+ */
4
+ export { connectBrowser, createPageCDPSession, LAUNCH_ARGS_ALLOW_ALL_CORS, LAUNCH_ARGS_LESS_AUTOMATION, } from './cdp_browser.js';
5
+ export { disconnectBrowserSession, ensureAndGetBrowser, ensureBrowserSession, getBrowserRef, getPageRef, setSessionPage, } from './browser_session.js';
6
+ export * from './auth.js';
7
+ export { withLoggedInPage } from './withLoggedInPage.js';
8
+ export { withChatPage } from './chat.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,0BAA0B,EAC1B,2BAA2B,GAE5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,UAAU,EACV,cAAc,GACf,MAAM,sBAAsB,CAAC;AAE9B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Page } from 'puppeteer-core';
2
+ /**
3
+ * 获取一个“已登录”页面来执行回调;未登录则抛错提示先运行 `boss login`。
4
+ * 说明:boss-cli 采用长期会话(CDP 连接)而非每次启动/关闭浏览器。
5
+ */
6
+ export declare function withLoggedInPage<T>(callback: (page: Page) => Promise<T>): Promise<T>;
7
+ //# sourceMappingURL=withLoggedInPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withLoggedInPage.d.ts","sourceRoot":"","sources":["../../src/browser/withLoggedInPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAI3C;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAW1F"}
@@ -0,0 +1,19 @@
1
+ import { ensureBrowserSession, getPageRef } from './browser_session.js';
2
+ import { probeLoggedInFromPage } from './auth.js';
3
+ /**
4
+ * 获取一个“已登录”页面来执行回调;未登录则抛错提示先运行 `boss login`。
5
+ * 说明:boss-cli 采用长期会话(CDP 连接)而非每次启动/关闭浏览器。
6
+ */
7
+ export async function withLoggedInPage(callback) {
8
+ await ensureBrowserSession();
9
+ const page = getPageRef();
10
+ if (!page) {
11
+ throw new Error('浏览器会话尚未初始化,请先运行 boss login。');
12
+ }
13
+ const { loggedIn } = await probeLoggedInFromPage(page);
14
+ if (!loggedIn) {
15
+ throw new Error('未检测到登录状态,请先运行 boss login 并在浏览器中完成登录。');
16
+ }
17
+ return callback(page);
18
+ }
19
+ //# sourceMappingURL=withLoggedInPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withLoggedInPage.js","sourceRoot":"","sources":["../../src/browser/withLoggedInPage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAI,QAAoC;IAC5E,MAAM,oBAAoB,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function printBossInteractiveBanner(): void;
2
+ //# sourceMappingURL=banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/cli/banner.ts"],"names":[],"mappings":"AASA,wBAAgB,0BAA0B,IAAI,IAAI,CAmBjD"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 进入交互模式(无参 `boss`)时在终端打印品牌条(红底白字)与作者信息。
3
+ * 无 NO_COLOR 且 stderr 为 TTY 时使用 ANSI;否则纯文本仍输出,避免「看不到」。
4
+ */
5
+ import process from 'node:process';
6
+ /** 主标题 + 作者(两行均着色,保证在交互入口足够显眼) */
7
+ const BANNER_LINES = [' boss-cli · by @joo '];
8
+ export function printBossInteractiveBanner() {
9
+ const useAnsi = !process.env.NO_COLOR && process.env.TERM !== 'dumb' && (process.stderr.isTTY ?? false);
10
+ console.error('');
11
+ if (useAnsi) {
12
+ const R = '\x1b[41m';
13
+ const W = '\x1b[97m';
14
+ const B = '\x1b[1m';
15
+ const Z = '\x1b[0m';
16
+ for (const line of BANNER_LINES) {
17
+ console.error(`${R}${W}${B}${line}${Z}`);
18
+ }
19
+ }
20
+ else {
21
+ for (const line of BANNER_LINES) {
22
+ console.error(line);
23
+ }
24
+ }
25
+ console.error('');
26
+ }
27
+ //# sourceMappingURL=banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/cli/banner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,kCAAkC;AAClC,MAAM,YAAY,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAEjD,MAAM,UAAU,0BAA0B;IACxC,MAAM,OAAO,GACX,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;IAE1F,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClB,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,GAAG,UAAU,CAAC;QACrB,MAAM,CAAC,GAAG,UAAU,CAAC;QACrB,MAAM,CAAC,GAAG,SAAS,CAAC;QACpB,MAAM,CAAC,GAAG,SAAS,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** `readline.question` 在 Ctrl+C 时会抛出 AbortError,视为正常结束而非业务错误 */
2
+ export declare function isReadlineAbortError(e: unknown): boolean;
3
+ /**
4
+ * 执行一条子命令并返回结果(与传入 `process.argv` 切片语义一致,不含 `boss` 本身)。
5
+ */
6
+ export declare function executeCommand(argv: string[]): Promise<string>;
7
+ export declare function runOneCommand(argv: string[]): Promise<void>;
8
+ export declare function runCli(argv: string[]): Promise<void>;
9
+ //# sourceMappingURL=cliRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cliRouter.d.ts","sourceRoot":"","sources":["../../src/cli/cliRouter.ts"],"names":[],"mappings":"AA6BA,gEAAgE;AAChE,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAMxD;AAuHD;;GAEG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDpE;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAWjE;AA0CD,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB1D"}
@@ -0,0 +1,254 @@
1
+ /**
2
+ * CLI:子命令直接调用 toolset 中的 impl*。
3
+ * 无参数时进入交互模式,逐行解析与 `boss <argv...>` 相同的命令。
4
+ */
5
+ import { createInterface } from 'node:readline/promises';
6
+ import { stdin as input, stdout as output } from 'node:process';
7
+ import { disconnectBrowserSession } from '../browser/index.js';
8
+ import { CACHE_DIR } from '../config.js';
9
+ import { implLogin, implListCandidates, implListUnreadCandidates, implListPositions, implOpenChat, implSendMessage, } from '../toolset/index.js';
10
+ import { printBossInteractiveBanner } from './banner.js';
11
+ class CliError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = 'CliError';
15
+ }
16
+ }
17
+ function die(msg) {
18
+ throw new CliError(msg);
19
+ }
20
+ /** `readline.question` 在 Ctrl+C 时会抛出 AbortError,视为正常结束而非业务错误 */
21
+ export function isReadlineAbortError(e) {
22
+ if (e === null || typeof e !== 'object') {
23
+ return false;
24
+ }
25
+ const err = e;
26
+ return err.name === 'AbortError' || err.code === 'ABORT_ERR';
27
+ }
28
+ /** 类 shell 分词:支持双引号、单引号包裹含空格的参数 */
29
+ function splitShellLine(line) {
30
+ const out = [];
31
+ let cur = '';
32
+ let quote = null;
33
+ for (let i = 0; i < line.length; i++) {
34
+ const c = line[i];
35
+ if (quote) {
36
+ if (c === quote) {
37
+ quote = null;
38
+ }
39
+ else {
40
+ cur += c;
41
+ }
42
+ continue;
43
+ }
44
+ if (c === '"' || c === "'") {
45
+ quote = c;
46
+ continue;
47
+ }
48
+ if (/\s/.test(c)) {
49
+ if (cur.length > 0) {
50
+ out.push(cur);
51
+ cur = '';
52
+ }
53
+ continue;
54
+ }
55
+ cur += c;
56
+ }
57
+ if (cur.length > 0) {
58
+ out.push(cur);
59
+ }
60
+ return out;
61
+ }
62
+ function printHelp() {
63
+ console.error(`boss-cli — Boss 直聘浏览器自动化(纯 CLI,无 Agent 运行时)
64
+
65
+ 用法与说明:
66
+ boss
67
+ 进入交互模式;提示符 boss> ,exit / quit 退出;Ctrl+C 正常结束
68
+ boss help
69
+ 显示本帮助
70
+ boss login
71
+ 打开登录页并等待你在浏览器中完成登录
72
+ boss list-candidates
73
+ 读取「全部」聊天列表候选人
74
+ --unread 仅显示未读(角标>0)
75
+ boss open-chat <姓名> [--fuzzy]
76
+ 打开指定联系人会话;默认精确匹配,--fuzzy 为包含匹配
77
+ boss send-message --text <内容> [--also-request-resume]
78
+ 在聊天输入框发送消息;-t 同 --text
79
+ boss list-positions
80
+ 读取本地 jd/ 目录下的岗位 Markdown
81
+
82
+ 成功时 stdout 为纯文本;业务失败时进程退出码为 1。
83
+
84
+ 数据目录默认:${CACHE_DIR}(浏览器用户数据见环境变量 BOSS_BROWSER_USER_DATA_DIR,未设置时使用其下 browser-data)。
85
+ `);
86
+ }
87
+ /** 解析 `--key value` / `--key=value` / 布尔 `--flag` */
88
+ function parseOpts(argv) {
89
+ const rest = [];
90
+ const flags = new Set();
91
+ const opts = {};
92
+ for (let i = 0; i < argv.length; i++) {
93
+ const a = argv[i];
94
+ if (a === '--') {
95
+ rest.push(...argv.slice(i + 1));
96
+ break;
97
+ }
98
+ if (a.startsWith('--')) {
99
+ const eq = a.indexOf('=');
100
+ if (eq !== -1) {
101
+ const k = a.slice(2, eq);
102
+ opts[k] = a.slice(eq + 1);
103
+ continue;
104
+ }
105
+ const key = a.slice(2);
106
+ const next = argv[i + 1];
107
+ if (next !== undefined && !next.startsWith('-')) {
108
+ opts[key] = next;
109
+ i += 1;
110
+ }
111
+ else {
112
+ flags.add(key);
113
+ }
114
+ continue;
115
+ }
116
+ if (a.startsWith('-') && a.length > 1 && !a.startsWith('--')) {
117
+ const short = a.slice(1);
118
+ const next = argv[i + 1];
119
+ if (short === 't' && next !== undefined && !next.startsWith('-')) {
120
+ opts.t = next;
121
+ i += 1;
122
+ continue;
123
+ }
124
+ if (!/^\d/.test(short)) {
125
+ flags.add(short);
126
+ continue;
127
+ }
128
+ }
129
+ rest.push(a);
130
+ }
131
+ return { rest, flags, opts };
132
+ }
133
+ function printStdout(text) {
134
+ const t = text.trimEnd();
135
+ if (t.length > 0) {
136
+ console.log(t);
137
+ }
138
+ }
139
+ /**
140
+ * 执行一条子命令并返回结果(与传入 `process.argv` 切片语义一致,不含 `boss` 本身)。
141
+ */
142
+ export async function executeCommand(argv) {
143
+ if (argv.length === 0) {
144
+ die('❌ 空命令');
145
+ }
146
+ const cmd = argv[0];
147
+ const tail = argv.slice(1);
148
+ if (cmd === 'login') {
149
+ return implLogin();
150
+ }
151
+ if (cmd === 'list-candidates') {
152
+ const { flags } = parseOpts(tail);
153
+ if (flags.has('unread')) {
154
+ return implListUnreadCandidates();
155
+ }
156
+ return implListCandidates();
157
+ }
158
+ if (cmd === 'open-chat') {
159
+ const { rest, flags } = parseOpts(tail);
160
+ const nameArg = rest[0]?.trim();
161
+ if (!nameArg) {
162
+ die('❌ 用法: open-chat <姓名> [--fuzzy]');
163
+ }
164
+ const exact = !flags.has('fuzzy');
165
+ return implOpenChat(nameArg, exact);
166
+ }
167
+ if (cmd === 'send-message') {
168
+ const { opts, flags } = parseOpts(tail);
169
+ const text = opts.text?.trim() || opts.t?.trim() || '';
170
+ const alsoRequestResume = flags.has('also-request-resume') ||
171
+ opts['also-request-resume'] === 'true' ||
172
+ opts.alsoRequestResume === 'true';
173
+ if (!text) {
174
+ die('❌ 用法: send-message --text <消息内容> [--also-request-resume]');
175
+ }
176
+ return implSendMessage(text, alsoRequestResume);
177
+ }
178
+ if (cmd === 'list-positions') {
179
+ return implListPositions();
180
+ }
181
+ die(`❌ 未知命令 “${cmd}”。输入 help 查看用法。`);
182
+ }
183
+ export async function runOneCommand(argv) {
184
+ if (argv.length === 0) {
185
+ return;
186
+ }
187
+ try {
188
+ const text = await executeCommand(argv);
189
+ printStdout(text);
190
+ }
191
+ catch (e) {
192
+ console.error(e instanceof Error ? e.message : String(e));
193
+ process.exitCode = 1;
194
+ }
195
+ }
196
+ async function runInteractiveLoop() {
197
+ const rl = createInterface({ input, output, terminal: true });
198
+ printBossInteractiveBanner();
199
+ console.error('欢迎使用 boss-cli。输入 help 查看可用命令,exit / quit 退出。\n');
200
+ try {
201
+ for (;;) {
202
+ let line;
203
+ try {
204
+ line = await rl.question('boss> ');
205
+ }
206
+ catch (e) {
207
+ if (isReadlineAbortError(e)) {
208
+ break;
209
+ }
210
+ throw e;
211
+ }
212
+ const trimmed = line.trim();
213
+ if (!trimmed) {
214
+ continue;
215
+ }
216
+ if (/^(exit|quit)$/i.test(trimmed)) {
217
+ break;
218
+ }
219
+ if (/^help$/i.test(trimmed)) {
220
+ printHelp();
221
+ continue;
222
+ }
223
+ const argv = splitShellLine(trimmed);
224
+ try {
225
+ const text = await executeCommand(argv);
226
+ printStdout(text);
227
+ }
228
+ catch (e) {
229
+ console.error(e instanceof Error ? e.message : e);
230
+ }
231
+ }
232
+ }
233
+ finally {
234
+ rl.close();
235
+ await disconnectBrowserSession().catch(() => { });
236
+ }
237
+ }
238
+ export async function runCli(argv) {
239
+ if (argv.length === 0) {
240
+ await runInteractiveLoop();
241
+ return;
242
+ }
243
+ if (argv[0] === 'help' || argv[0] === '--help' || argv[0] === '-h') {
244
+ printHelp();
245
+ return;
246
+ }
247
+ try {
248
+ await runOneCommand(argv);
249
+ }
250
+ finally {
251
+ await disconnectBrowserSession().catch(() => { });
252
+ }
253
+ }
254
+ //# sourceMappingURL=cliRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cliRouter.js","sourceRoot":"","sources":["../../src/cli/cliRouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ // boss-cli 入口:子命令见 cliRouter;业务能力见 toolset(impl*)
3
+ import { runCli, isReadlineAbortError } from './cliRouter.js';
4
+ async function main() {
5
+ const args = process.argv.slice(2);
6
+ try {
7
+ await runCli(args);
8
+ }
9
+ catch (error) {
10
+ if (isReadlineAbortError(error)) {
11
+ process.exit(0);
12
+ }
13
+ console.error('❌ 执行出错:', error);
14
+ if (error instanceof Error) {
15
+ console.error('错误信息:', error.message);
16
+ }
17
+ process.exit(1);
18
+ }
19
+ }
20
+ main();
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,kDAAkD;AAElD,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAChC,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ /** 应用主目录(业务数据在 .cache 下) */
2
+ export declare const APP_HOME: string;
3
+ /**
4
+ * 应用缓存与生成数据根目录(浏览器配置等)
5
+ */
6
+ export declare const CACHE_DIR: string;
7
+ /** Puppeteer 用户数据目录(与 CDP 启动默认目录一致) */
8
+ export declare const BROWSER_USER_DATA_DIR: string;
9
+ /** 确保 `~/.boss-cli/.cache` 目录存在(幂等) */
10
+ export declare function ensureAppDataLayout(): void;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,4BAA4B;AAC5B,eAAO,MAAM,QAAQ,QAA+B,CAAC;AAErD;;GAEG;AACH,eAAO,MAAM,SAAS,QAA2B,CAAC;AAElD,uCAAuC;AACvC,eAAO,MAAM,qBAAqB,QAAkC,CAAC;AAIrE,uCAAuC;AACvC,wBAAgB,mBAAmB,IAAI,IAAI,CAW1C"}
package/dist/config.js ADDED
@@ -0,0 +1,27 @@
1
+ // 配置文件 — 应用数据位于 ~/.boss-cli/.cache/
2
+ import { existsSync, mkdirSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+ /** 应用主目录(业务数据在 .cache 下) */
6
+ export const APP_HOME = join(homedir(), '.boss-cli');
7
+ /**
8
+ * 应用缓存与生成数据根目录(浏览器配置等)
9
+ */
10
+ export const CACHE_DIR = join(APP_HOME, '.cache');
11
+ /** Puppeteer 用户数据目录(与 CDP 启动默认目录一致) */
12
+ export const BROWSER_USER_DATA_DIR = join(CACHE_DIR, 'browser-data');
13
+ let appDataLayoutReady = false;
14
+ /** 确保 `~/.boss-cli/.cache` 目录存在(幂等) */
15
+ export function ensureAppDataLayout() {
16
+ if (appDataLayoutReady) {
17
+ return;
18
+ }
19
+ appDataLayoutReady = true;
20
+ if (!existsSync(CACHE_DIR)) {
21
+ mkdirSync(CACHE_DIR, { recursive: true });
22
+ }
23
+ if (!existsSync(BROWSER_USER_DATA_DIR)) {
24
+ mkdirSync(BROWSER_USER_DATA_DIR, { recursive: true });
25
+ }
26
+ }
27
+ //# 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,4BAA4B;AAC5B,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAErD;;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,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;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare function implLogin(): Promise<string>;
2
+ export declare function implListCandidates(): Promise<string>;
3
+ export declare function implListUnreadCandidates(): Promise<string>;
4
+ export declare function implOpenChat(candidateName: string, exact: boolean): Promise<string>;
5
+ export declare function implSendMessage(text: string, alsoRequestResume: boolean): Promise<string>;
6
+ export declare function implListPositions(): Promise<string>;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/toolset/index.ts"],"names":[],"mappings":"AAQA,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAEjD;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAE1D;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEhE;AAED,wBAAsB,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAEzF;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,OAAO,GACzB,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEzD"}
@@ -0,0 +1,26 @@
1
+ /** 业务实现聚合出口:impl* 供 CLI 与其它模块调用 */
2
+ import { runLogin } from './login.js';
3
+ import { runGetCandidateList } from './list_candidates.js';
4
+ import { runListOpenPositions } from './list_positions.js';
5
+ import { runOpenCandidateChat } from './open_chat.js';
6
+ import { runSendChatMessage } from './send_message.js';
7
+ import { withChatPage } from '../browser/index.js';
8
+ export async function implLogin() {
9
+ return runLogin();
10
+ }
11
+ export async function implListCandidates() {
12
+ return runGetCandidateList();
13
+ }
14
+ export async function implListUnreadCandidates() {
15
+ return runGetCandidateList({ unreadOnly: true });
16
+ }
17
+ export async function implOpenChat(candidateName, exact) {
18
+ return withChatPage(async (page) => runOpenCandidateChat(page, candidateName, exact));
19
+ }
20
+ export async function implSendMessage(text, alsoRequestResume) {
21
+ return runSendChatMessage(text, alsoRequestResume);
22
+ }
23
+ export async function implListPositions() {
24
+ return runListOpenPositions();
25
+ }
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/toolset/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,OAAO,QAAQ,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,OAAO,mBAAmB,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,OAAO,mBAAmB,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,aAAqB,EAAE,KAAc;IACtE,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY,EACZ,iBAA0B;IAE1B,OAAO,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,OAAO,oBAAoB,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function runGetCandidateList(opts?: {
2
+ unreadOnly?: boolean;
3
+ }): Promise<string>;
4
+ //# sourceMappingURL=list_candidates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_candidates.d.ts","sourceRoot":"","sources":["../../src/toolset/list_candidates.ts"],"names":[],"mappings":"AA2DA,wBAAsB,mBAAmB,CACvC,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC,MAAM,CAAC,CAgGjB"}