v2er-insight 1.0.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.
Files changed (205) hide show
  1. package/README.md +215 -0
  2. package/dist/cli/commands/ai.d.ts +13 -0
  3. package/dist/cli/commands/ai.js +153 -0
  4. package/dist/cli/commands/analyze.d.ts +13 -0
  5. package/dist/cli/commands/analyze.js +80 -0
  6. package/dist/cli/commands/config.d.ts +43 -0
  7. package/dist/cli/commands/config.js +267 -0
  8. package/dist/cli/commands/fetch.d.ts +13 -0
  9. package/dist/cli/commands/fetch.js +150 -0
  10. package/dist/cli/commands/index.d.ts +10 -0
  11. package/dist/cli/commands/index.js +22 -0
  12. package/dist/cli/commands/run.d.ts +23 -0
  13. package/dist/cli/commands/run.js +52 -0
  14. package/dist/cli/commands/show.d.ts +13 -0
  15. package/dist/cli/commands/show.js +154 -0
  16. package/dist/cli/index.d.ts +6 -0
  17. package/dist/cli/index.js +107 -0
  18. package/dist/cli/types.d.ts +58 -0
  19. package/dist/cli/types.js +6 -0
  20. package/dist/cli/utils/error.d.ts +6 -0
  21. package/dist/cli/utils/error.js +18 -0
  22. package/dist/cli/utils.d.ts +20 -0
  23. package/dist/cli/utils.js +48 -0
  24. package/dist/cli/workflow/orchestrator.d.ts +15 -0
  25. package/dist/cli/workflow/orchestrator.js +144 -0
  26. package/dist/cli/workflow/recovery.d.ts +10 -0
  27. package/dist/cli/workflow/recovery.js +134 -0
  28. package/dist/cli/workflow/state.d.ts +19 -0
  29. package/dist/cli/workflow/state.js +45 -0
  30. package/dist/cli/workflow/types.d.ts +60 -0
  31. package/dist/cli/workflow/types.js +3 -0
  32. package/dist/config/defaults.d.ts +48 -0
  33. package/dist/config/defaults.js +42 -0
  34. package/dist/config/index.d.ts +16 -0
  35. package/dist/config/index.js +21 -0
  36. package/dist/config/path.d.ts +11 -0
  37. package/dist/config/path.js +28 -0
  38. package/dist/config/proxy.d.ts +16 -0
  39. package/dist/config/proxy.js +39 -0
  40. package/dist/config/storage.d.ts +23 -0
  41. package/dist/config/storage.js +85 -0
  42. package/dist/config/types/ai.d.ts +31 -0
  43. package/dist/config/types/ai.js +13 -0
  44. package/dist/config/types/analyzer.d.ts +15 -0
  45. package/dist/config/types/analyzer.js +6 -0
  46. package/dist/config/types/data.d.ts +20 -0
  47. package/dist/config/types/data.js +6 -0
  48. package/dist/config/types/fetch.d.ts +9 -0
  49. package/dist/config/types/fetch.js +6 -0
  50. package/dist/config/types/index.d.ts +32 -0
  51. package/dist/config/types/index.js +11 -0
  52. package/dist/config/types/log.d.ts +11 -0
  53. package/dist/config/types/log.js +6 -0
  54. package/dist/core/ai/index.d.ts +11 -0
  55. package/dist/core/ai/index.js +18 -0
  56. package/dist/core/ai/parser/index.d.ts +12 -0
  57. package/dist/core/ai/parser/index.js +44 -0
  58. package/dist/core/ai/parser/validator.d.ts +18 -0
  59. package/dist/core/ai/parser/validator.js +179 -0
  60. package/dist/core/ai/prompt/index.d.ts +20 -0
  61. package/dist/core/ai/prompt/index.js +75 -0
  62. package/dist/core/ai/prompt/system-prompt.md +210 -0
  63. package/dist/core/ai/providers/gemini.d.ts +25 -0
  64. package/dist/core/ai/providers/gemini.js +74 -0
  65. package/dist/core/ai/providers/index.d.ts +6 -0
  66. package/dist/core/ai/providers/index.js +9 -0
  67. package/dist/core/ai/types/index.d.ts +7 -0
  68. package/dist/core/ai/types/index.js +6 -0
  69. package/dist/core/ai/types/options.d.ts +14 -0
  70. package/dist/core/ai/types/options.js +6 -0
  71. package/dist/core/ai/types/provider.d.ts +19 -0
  72. package/dist/core/ai/types/provider.js +6 -0
  73. package/dist/core/ai/types/result.d.ts +64 -0
  74. package/dist/core/ai/types/result.js +6 -0
  75. package/dist/core/ai/utils/api-key.d.ts +15 -0
  76. package/dist/core/ai/utils/api-key.js +36 -0
  77. package/dist/core/ai/utils/index.d.ts +6 -0
  78. package/dist/core/ai/utils/index.js +11 -0
  79. package/dist/core/ai/utils/retry.d.ts +15 -0
  80. package/dist/core/ai/utils/retry.js +37 -0
  81. package/dist/core/analyzer/builder.d.ts +23 -0
  82. package/dist/core/analyzer/builder.js +113 -0
  83. package/dist/core/analyzer/content/chunker.d.ts +18 -0
  84. package/dist/core/analyzer/content/chunker.js +74 -0
  85. package/dist/core/analyzer/content/index.d.ts +7 -0
  86. package/dist/core/analyzer/content/index.js +13 -0
  87. package/dist/core/analyzer/content/transformer.d.ts +19 -0
  88. package/dist/core/analyzer/content/transformer.js +33 -0
  89. package/dist/core/analyzer/index.d.ts +17 -0
  90. package/dist/core/analyzer/index.js +21 -0
  91. package/dist/core/analyzer/periods/detector.d.ts +17 -0
  92. package/dist/core/analyzer/periods/detector.js +36 -0
  93. package/dist/core/analyzer/periods/index.d.ts +6 -0
  94. package/dist/core/analyzer/periods/index.js +11 -0
  95. package/dist/core/analyzer/periods/splitter.d.ts +11 -0
  96. package/dist/core/analyzer/periods/splitter.js +35 -0
  97. package/dist/core/analyzer/stats/index.d.ts +7 -0
  98. package/dist/core/analyzer/stats/index.js +13 -0
  99. package/dist/core/analyzer/stats/reply-stats.d.ts +15 -0
  100. package/dist/core/analyzer/stats/reply-stats.js +45 -0
  101. package/dist/core/analyzer/stats/topic-stats.d.ts +16 -0
  102. package/dist/core/analyzer/stats/topic-stats.js +51 -0
  103. package/dist/core/analyzer/stats/user-overview.d.ts +9 -0
  104. package/dist/core/analyzer/stats/user-overview.js +52 -0
  105. package/dist/core/analyzer/types/index.d.ts +7 -0
  106. package/dist/core/analyzer/types/index.js +6 -0
  107. package/dist/core/analyzer/types/input.d.ts +13 -0
  108. package/dist/core/analyzer/types/input.js +6 -0
  109. package/dist/core/analyzer/types/internal.d.ts +28 -0
  110. package/dist/core/analyzer/types/internal.js +6 -0
  111. package/dist/core/analyzer/types/output.d.ts +68 -0
  112. package/dist/core/analyzer/types/output.js +6 -0
  113. package/dist/core/analyzer/utils/date-parser.d.ts +41 -0
  114. package/dist/core/analyzer/utils/date-parser.js +118 -0
  115. package/dist/core/analyzer/utils/index.d.ts +6 -0
  116. package/dist/core/analyzer/utils/index.js +18 -0
  117. package/dist/core/analyzer/utils/stats.d.ts +12 -0
  118. package/dist/core/analyzer/utils/stats.js +64 -0
  119. package/dist/core/v2ex/index.d.ts +10 -0
  120. package/dist/core/v2ex/index.js +27 -0
  121. package/dist/core/v2ex/parsers/index.d.ts +8 -0
  122. package/dist/core/v2ex/parsers/index.js +15 -0
  123. package/dist/core/v2ex/parsers/replies-page.d.ts +11 -0
  124. package/dist/core/v2ex/parsers/replies-page.js +114 -0
  125. package/dist/core/v2ex/parsers/selectors/index.d.ts +10 -0
  126. package/dist/core/v2ex/parsers/selectors/index.js +18 -0
  127. package/dist/core/v2ex/parsers/selectors/pagination.d.ts +11 -0
  128. package/dist/core/v2ex/parsers/selectors/pagination.js +14 -0
  129. package/dist/core/v2ex/parsers/selectors/replies-page.d.ts +21 -0
  130. package/dist/core/v2ex/parsers/selectors/replies-page.js +24 -0
  131. package/dist/core/v2ex/parsers/selectors/topic-detail.d.ts +19 -0
  132. package/dist/core/v2ex/parsers/selectors/topic-detail.js +22 -0
  133. package/dist/core/v2ex/parsers/selectors/topics-list-page.d.ts +11 -0
  134. package/dist/core/v2ex/parsers/selectors/topics-list-page.js +14 -0
  135. package/dist/core/v2ex/parsers/selectors/user-profile.d.ts +11 -0
  136. package/dist/core/v2ex/parsers/selectors/user-profile.js +14 -0
  137. package/dist/core/v2ex/parsers/topic-detail.d.ts +11 -0
  138. package/dist/core/v2ex/parsers/topic-detail.js +94 -0
  139. package/dist/core/v2ex/parsers/topics-list-page.d.ts +11 -0
  140. package/dist/core/v2ex/parsers/topics-list-page.js +90 -0
  141. package/dist/core/v2ex/parsers/user-profile.d.ts +11 -0
  142. package/dist/core/v2ex/parsers/user-profile.js +70 -0
  143. package/dist/core/v2ex/parsers/utils/index.d.ts +6 -0
  144. package/dist/core/v2ex/parsers/utils/index.js +9 -0
  145. package/dist/core/v2ex/parsers/utils/pagination.d.ts +19 -0
  146. package/dist/core/v2ex/parsers/utils/pagination.js +29 -0
  147. package/dist/core/v2ex/types/entities.d.ts +45 -0
  148. package/dist/core/v2ex/types/entities.js +7 -0
  149. package/dist/core/v2ex/types/index.d.ts +6 -0
  150. package/dist/core/v2ex/types/index.js +6 -0
  151. package/dist/core/v2ex/types/parse-result.d.ts +64 -0
  152. package/dist/core/v2ex/types/parse-result.js +7 -0
  153. package/dist/core/v2ex/urls/constants.d.ts +5 -0
  154. package/dist/core/v2ex/urls/constants.js +8 -0
  155. package/dist/core/v2ex/urls/index.d.ts +7 -0
  156. package/dist/core/v2ex/urls/index.js +16 -0
  157. package/dist/core/v2ex/urls/topic-urls.d.ts +19 -0
  158. package/dist/core/v2ex/urls/topic-urls.js +48 -0
  159. package/dist/core/v2ex/urls/user-urls.d.ts +24 -0
  160. package/dist/core/v2ex/urls/user-urls.js +36 -0
  161. package/dist/core/v2ex/use-cases/index.d.ts +8 -0
  162. package/dist/core/v2ex/use-cases/index.js +14 -0
  163. package/dist/core/v2ex/use-cases/types.d.ts +31 -0
  164. package/dist/core/v2ex/use-cases/types.js +7 -0
  165. package/dist/core/v2ex/use-cases/user/index.d.ts +10 -0
  166. package/dist/core/v2ex/use-cases/user/index.js +16 -0
  167. package/dist/core/v2ex/use-cases/user/profile.d.ts +14 -0
  168. package/dist/core/v2ex/use-cases/user/profile.js +51 -0
  169. package/dist/core/v2ex/use-cases/user/replies.d.ts +14 -0
  170. package/dist/core/v2ex/use-cases/user/replies.js +20 -0
  171. package/dist/core/v2ex/use-cases/user/topic-urls.d.ts +21 -0
  172. package/dist/core/v2ex/use-cases/user/topic-urls.js +29 -0
  173. package/dist/core/v2ex/use-cases/user/topics-detail.d.ts +30 -0
  174. package/dist/core/v2ex/use-cases/user/topics-detail.js +62 -0
  175. package/dist/core/v2ex/use-cases/utils/index.d.ts +6 -0
  176. package/dist/core/v2ex/use-cases/utils/index.js +9 -0
  177. package/dist/core/v2ex/use-cases/utils/page-orchestrator.d.ts +24 -0
  178. package/dist/core/v2ex/use-cases/utils/page-orchestrator.js +93 -0
  179. package/dist/infra/fetcher/agent.d.ts +10 -0
  180. package/dist/infra/fetcher/agent.js +17 -0
  181. package/dist/infra/fetcher/fetcher.d.ts +10 -0
  182. package/dist/infra/fetcher/fetcher.js +81 -0
  183. package/dist/infra/fetcher/index.d.ts +3 -0
  184. package/dist/infra/fetcher/index.js +19 -0
  185. package/dist/infra/fetcher/types.d.ts +29 -0
  186. package/dist/infra/fetcher/types.js +6 -0
  187. package/dist/infra/logger/colors.d.ts +15 -0
  188. package/dist/infra/logger/colors.js +18 -0
  189. package/dist/infra/logger/index.d.ts +16 -0
  190. package/dist/infra/logger/index.js +19 -0
  191. package/dist/infra/logger/logger.d.ts +34 -0
  192. package/dist/infra/logger/logger.js +101 -0
  193. package/dist/infra/storage/cleaner.d.ts +24 -0
  194. package/dist/infra/storage/cleaner.js +73 -0
  195. package/dist/infra/storage/index.d.ts +7 -0
  196. package/dist/infra/storage/index.js +15 -0
  197. package/dist/infra/storage/paths.d.ts +26 -0
  198. package/dist/infra/storage/paths.js +53 -0
  199. package/dist/infra/storage/reader.d.ts +15 -0
  200. package/dist/infra/storage/reader.js +34 -0
  201. package/dist/infra/storage/types.d.ts +21 -0
  202. package/dist/infra/storage/types.js +18 -0
  203. package/dist/infra/storage/writer.d.ts +16 -0
  204. package/dist/infra/storage/writer.js +31 -0
  205. package/package.json +89 -0
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRecoveryActions = getRecoveryActions;
4
+ /**
5
+ * 统一维护原因码到恢复动作的映射,避免恢复命令散落在各命令实现中。
6
+ */
7
+ const RECOVERY_MAP = {
8
+ FETCH_PROFILE_FAILED: [
9
+ {
10
+ type: 'command',
11
+ content: 'v2er fetch <username> --force',
12
+ description: '重新抓取 <username> 的用户资料并覆盖损坏缓存',
13
+ },
14
+ ],
15
+ FETCH_PARTIAL_FAILED: [
16
+ {
17
+ type: 'instruction',
18
+ content: '当前版本暂不支持仅重试失败页',
19
+ description: '建议先执行全量重抓,后续阶段会接入 --retry 能力',
20
+ },
21
+ {
22
+ type: 'command',
23
+ content: 'v2er fetch <username> --force',
24
+ description: '强制重新抓取,替换现有 raw 数据',
25
+ },
26
+ ],
27
+ ANALYZE_INPUT_MISSING: [
28
+ {
29
+ type: 'command',
30
+ content: 'v2er fetch <username>',
31
+ description: '先生成 raw.json,再执行 analyze',
32
+ },
33
+ ],
34
+ ANALYZE_FAILED: [
35
+ {
36
+ type: 'command',
37
+ content: 'v2er analyze <username>',
38
+ description: '修复数据问题后重试 analyze 步骤',
39
+ },
40
+ {
41
+ type: 'command',
42
+ content: 'v2er fetch <username> --force',
43
+ description: '若 raw 数据可能损坏,先强制重新抓取再分析',
44
+ },
45
+ ],
46
+ AI_INPUT_MISSING: [
47
+ {
48
+ type: 'command',
49
+ content: 'v2er analyze <username>',
50
+ description: '先生成 analyzed.json,再执行 AI 分析',
51
+ },
52
+ ],
53
+ AI_API_KEY_MISSING: [
54
+ {
55
+ type: 'instruction',
56
+ content: '先在环境变量或配置文件中设置 API Key',
57
+ description: '当前缺少 AI API Key,无法发起 AI 请求',
58
+ },
59
+ {
60
+ type: 'command',
61
+ content: 'v2er ai <username>',
62
+ description: '完成 API Key 配置后重试 AI 步骤',
63
+ },
64
+ ],
65
+ AI_INVALID_THINKING_LEVEL: [
66
+ {
67
+ type: 'instruction',
68
+ content: '将 thinking-level 调整为 minimal | low | medium | high 之一',
69
+ description: '当前传入的思考等级不合法,需使用受支持的枚举值',
70
+ },
71
+ {
72
+ type: 'command',
73
+ content: 'v2er ai <username> --thinking-level medium',
74
+ description: '使用合法思考等级重试 AI 步骤',
75
+ },
76
+ {
77
+ type: 'command',
78
+ content: 'v2er config set ai.thinkingLevel medium',
79
+ description: '修正全局默认 thinkingLevel,避免后续重复报错',
80
+ },
81
+ ],
82
+ AI_PROVIDER_FAILED: [
83
+ {
84
+ type: 'instruction',
85
+ content: '常见原因:网络或代理异常、请求限流(429)、模型不可用、响应格式异常',
86
+ description: '请先结合错误信息定位原因,再执行对应恢复动作',
87
+ },
88
+ {
89
+ type: 'command',
90
+ content: 'v2er config proxy <url>',
91
+ description: '网络受限时先配置代理后再重试',
92
+ },
93
+ {
94
+ type: 'command',
95
+ content: 'v2er ai <username>',
96
+ description: '在已存在 analyzed.json 时直接重试 AI 步骤',
97
+ },
98
+ {
99
+ type: 'command',
100
+ content: 'v2er ai <username> --model gemini-2.0-flash',
101
+ description: '若当前模型不稳定,可切换模型后重试',
102
+ },
103
+ ],
104
+ SHOW_RESULT_MISSING: [
105
+ {
106
+ type: 'command',
107
+ content: 'v2er ai <username>',
108
+ description: '先生成 result.json,再执行展示',
109
+ },
110
+ ],
111
+ UNKNOWN_ERROR: [],
112
+ };
113
+ /**
114
+ * 渲染恢复动作中的模板变量(如 <username>)。
115
+ */
116
+ function renderTemplate(content, context) {
117
+ if (!context.username)
118
+ return content;
119
+ return content.replace(/<username>/g, context.username);
120
+ }
121
+ /**
122
+ * 获取指定原因码对应的恢复动作列表,并按上下文渲染模板变量。
123
+ */
124
+ function getRecoveryActions(reasonCode, context = {}) {
125
+ if (!reasonCode)
126
+ return [];
127
+ const actions = RECOVERY_MAP[reasonCode] ?? [];
128
+ return actions.map((action) => ({
129
+ ...action,
130
+ content: renderTemplate(action.content, context),
131
+ description: renderTemplate(action.description, context),
132
+ }));
133
+ }
134
+ //# sourceMappingURL=recovery.js.map
@@ -0,0 +1,19 @@
1
+ import type { WorkflowState, WorkflowStep } from './types';
2
+ /**
3
+ * 检测用户本地工作流产物状态。
4
+ *
5
+ * 这里只做"文件是否存在"的轻量判断,不读取和解析 JSON 内容。
6
+ * 具体的数据缺失或结构错误由各步骤命令自行处理并返回 reasonCode。
7
+ */
8
+ export declare function detectWorkflowState(username: string): WorkflowState;
9
+ /**
10
+ * 根据当前状态推导入口步骤。
11
+ *
12
+ * 当 `force=true` 时,无条件从 `fetch` 开始执行全流程。
13
+ */
14
+ export declare function resolveEntryStep(state: WorkflowState, force?: boolean): WorkflowStep;
15
+ /**
16
+ * 根据入口步骤生成线性执行计划。
17
+ */
18
+ export declare function buildExecutionPlan(entryStep: WorkflowStep): WorkflowStep[];
19
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectWorkflowState = detectWorkflowState;
4
+ exports.resolveEntryStep = resolveEntryStep;
5
+ exports.buildExecutionPlan = buildExecutionPlan;
6
+ const fs_1 = require("fs");
7
+ const paths_1 = require("../../infra/storage/paths");
8
+ /**
9
+ * 检测用户本地工作流产物状态。
10
+ *
11
+ * 这里只做"文件是否存在"的轻量判断,不读取和解析 JSON 内容。
12
+ * 具体的数据缺失或结构错误由各步骤命令自行处理并返回 reasonCode。
13
+ */
14
+ function detectWorkflowState(username) {
15
+ const hasRaw = (0, fs_1.existsSync)((0, paths_1.getDataFilePath)(username, 'raw'));
16
+ const hasAnalyzed = (0, fs_1.existsSync)((0, paths_1.getDataFilePath)(username, 'analyzed'));
17
+ const hasResult = (0, fs_1.existsSync)((0, paths_1.getDataFilePath)(username, 'result'));
18
+ return { hasRaw, hasAnalyzed, hasResult };
19
+ }
20
+ /**
21
+ * 根据当前状态推导入口步骤。
22
+ *
23
+ * 当 `force=true` 时,无条件从 `fetch` 开始执行全流程。
24
+ */
25
+ function resolveEntryStep(state, force = false) {
26
+ if (force)
27
+ return 'fetch';
28
+ if (state.hasResult)
29
+ return 'show';
30
+ if (state.hasAnalyzed)
31
+ return 'ai';
32
+ if (state.hasRaw)
33
+ return 'analyze';
34
+ return 'fetch';
35
+ }
36
+ /** 固定步骤顺序,作为执行计划的唯一数据源 */
37
+ const STEP_ORDER = ['fetch', 'analyze', 'ai', 'show'];
38
+ /**
39
+ * 根据入口步骤生成线性执行计划。
40
+ */
41
+ function buildExecutionPlan(entryStep) {
42
+ const index = STEP_ORDER.indexOf(entryStep);
43
+ return index === -1 ? [...STEP_ORDER] : STEP_ORDER.slice(index);
44
+ }
45
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1,60 @@
1
+ import type { ThinkingLevel } from '../../config';
2
+ /**
3
+ * Workflow 层共享类型定义
4
+ */
5
+ /** 全流程固定步骤名称 */
6
+ export type WorkflowStep = 'fetch' | 'analyze' | 'ai' | 'show';
7
+ /** 单步骤执行状态 */
8
+ export type StepStatus = 'success' | 'partial' | 'failed' | 'skipped';
9
+ /** 统一错误/诊断原因码 */
10
+ export type ReasonCode = 'FETCH_PROFILE_FAILED' | 'FETCH_PARTIAL_FAILED' | 'ANALYZE_INPUT_MISSING' | 'ANALYZE_FAILED' | 'AI_INPUT_MISSING' | 'AI_API_KEY_MISSING' | 'AI_INVALID_THINKING_LEVEL' | 'AI_PROVIDER_FAILED' | 'SHOW_RESULT_MISSING' | 'UNKNOWN_ERROR';
11
+ /** 步骤失败或部分成功时可提供给用户的恢复动作 */
12
+ export interface RecoveryAction {
13
+ /** 动作类型:可执行命令或人工操作指引 */
14
+ type: 'command' | 'instruction';
15
+ /** 动作内容:命令文本或操作说明 */
16
+ content: string;
17
+ /** 动作用途说明 */
18
+ description: string;
19
+ }
20
+ /** 单个步骤的结构化执行结果 */
21
+ export interface StepRunResult {
22
+ /** 当前结果对应的步骤 */
23
+ step: WorkflowStep;
24
+ /** 步骤最终状态 */
25
+ status: StepStatus;
26
+ /** 非 success 状态下的原因码 */
27
+ reasonCode?: ReasonCode;
28
+ /** 面向用户的简短提示 */
29
+ message?: string;
30
+ /** 是否可通过恢复动作继续处理 */
31
+ recoverable?: boolean;
32
+ /** 恢复动作列表(按建议顺序) */
33
+ recoverActions?: RecoveryAction[];
34
+ /** 额外元数据,用于编排判断或后续重试 */
35
+ meta?: Record<string, unknown>;
36
+ }
37
+ /** 本地中间产物状态 */
38
+ export interface WorkflowState {
39
+ hasRaw: boolean;
40
+ hasAnalyzed: boolean;
41
+ hasResult: boolean;
42
+ }
43
+ /** 工作流最终聚合状态 */
44
+ export type WorkflowOverallStatus = 'success' | 'partial' | 'failed';
45
+ /** 一键工作流入口参数 */
46
+ export interface RunWorkflowOptions {
47
+ username: string;
48
+ force?: boolean;
49
+ model?: string;
50
+ thinkingLevel?: ThinkingLevel;
51
+ verbose?: boolean;
52
+ }
53
+ /** 一键工作流执行结果 */
54
+ export interface RunOutcome {
55
+ overallStatus: WorkflowOverallStatus;
56
+ exitCode: 0 | 1;
57
+ failedStep?: WorkflowStep;
58
+ results: StepRunResult[];
59
+ }
60
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * 配置默认值
3
+ *
4
+ * 定义所有配置项的默认值。
5
+ * getConfig() 会将用户设置覆盖到这些默认值上。
6
+ *
7
+ * 注意:
8
+ * - proxy、ai.apiKey 无默认值,必须由用户设置
9
+ * - 各模块内部的 config.ts 硬编码值应与此保持一致
10
+ */
11
+ import type { V2erConfig } from './types';
12
+ /**
13
+ * 合并默认值后的配置类型
14
+ * - 对象类型的字段(如 ai、fetch):所有子字段变为必填
15
+ * - 原始类型的字段(如 proxy):key 必须存在,但值仍可能为 undefined
16
+ */
17
+ export type ResolvedConfig = Required<{
18
+ [K in keyof V2erConfig]: V2erConfig[K] extends object | undefined ? Required<NonNullable<V2erConfig[K]>> : V2erConfig[K];
19
+ }>;
20
+ /** 全局默认配置 */
21
+ export declare const DEFAULT_CONFIG: {
22
+ readonly ai: {
23
+ readonly provider: "gemini";
24
+ readonly model: "gemini-3-pro-preview";
25
+ readonly thinkingLevel: "high";
26
+ readonly timeout: 60000;
27
+ readonly maxRetries: 3;
28
+ readonly baseDelay: 1000;
29
+ readonly maxDelay: 10000;
30
+ };
31
+ readonly fetch: {
32
+ readonly timeout: 30000;
33
+ };
34
+ readonly analyzer: {
35
+ readonly inactivityThreshold: 60;
36
+ readonly chunkMaxTopics: 20;
37
+ readonly chunkMaxReplies: 100;
38
+ readonly nodeDistributionTopN: 3;
39
+ };
40
+ readonly data: {
41
+ readonly keepRaw: false;
42
+ readonly rawRetention: 1;
43
+ };
44
+ readonly log: {
45
+ readonly level: "info";
46
+ };
47
+ };
48
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /**
3
+ * 配置默认值
4
+ *
5
+ * 定义所有配置项的默认值。
6
+ * getConfig() 会将用户设置覆盖到这些默认值上。
7
+ *
8
+ * 注意:
9
+ * - proxy、ai.apiKey 无默认值,必须由用户设置
10
+ * - 各模块内部的 config.ts 硬编码值应与此保持一致
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.DEFAULT_CONFIG = void 0;
14
+ /** 全局默认配置 */
15
+ exports.DEFAULT_CONFIG = {
16
+ ai: {
17
+ provider: 'gemini',
18
+ model: 'gemini-3-pro-preview',
19
+ thinkingLevel: 'high',
20
+ timeout: 60000,
21
+ maxRetries: 3,
22
+ baseDelay: 1000,
23
+ maxDelay: 10000,
24
+ },
25
+ fetch: {
26
+ timeout: 30000,
27
+ },
28
+ analyzer: {
29
+ inactivityThreshold: 60,
30
+ chunkMaxTopics: 20,
31
+ chunkMaxReplies: 100,
32
+ nodeDistributionTopN: 3,
33
+ },
34
+ data: {
35
+ keepRaw: false,
36
+ rawRetention: 1,
37
+ },
38
+ log: {
39
+ level: 'info',
40
+ },
41
+ };
42
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 配置模块公共导出
3
+ */
4
+ export type { V2erConfig } from './types';
5
+ export type { AIConfig, ThinkingLevel } from './types/ai';
6
+ export { THINKING_LEVELS } from './types/ai';
7
+ export type { FetchConfig } from './types/fetch';
8
+ export type { AnalyzerConfig } from './types/analyzer';
9
+ export type { DataConfig } from './types/data';
10
+ export type { LogConfig } from './types/log';
11
+ export type { LogLevel } from '../infra/logger';
12
+ export { getConfigDir, getConfigPath } from './path';
13
+ export { readConfig, writeConfig, getConfig } from './storage';
14
+ export { DEFAULT_CONFIG } from './defaults';
15
+ export { getProxyUrl, initFetchProxy } from './proxy';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * 配置模块公共导出
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initFetchProxy = exports.getProxyUrl = exports.DEFAULT_CONFIG = exports.getConfig = exports.writeConfig = exports.readConfig = exports.getConfigPath = exports.getConfigDir = exports.THINKING_LEVELS = void 0;
7
+ var ai_1 = require("./types/ai");
8
+ Object.defineProperty(exports, "THINKING_LEVELS", { enumerable: true, get: function () { return ai_1.THINKING_LEVELS; } });
9
+ var path_1 = require("./path");
10
+ Object.defineProperty(exports, "getConfigDir", { enumerable: true, get: function () { return path_1.getConfigDir; } });
11
+ Object.defineProperty(exports, "getConfigPath", { enumerable: true, get: function () { return path_1.getConfigPath; } });
12
+ var storage_1 = require("./storage");
13
+ Object.defineProperty(exports, "readConfig", { enumerable: true, get: function () { return storage_1.readConfig; } });
14
+ Object.defineProperty(exports, "writeConfig", { enumerable: true, get: function () { return storage_1.writeConfig; } });
15
+ Object.defineProperty(exports, "getConfig", { enumerable: true, get: function () { return storage_1.getConfig; } });
16
+ var defaults_1 = require("./defaults");
17
+ Object.defineProperty(exports, "DEFAULT_CONFIG", { enumerable: true, get: function () { return defaults_1.DEFAULT_CONFIG; } });
18
+ var proxy_1 = require("./proxy");
19
+ Object.defineProperty(exports, "getProxyUrl", { enumerable: true, get: function () { return proxy_1.getProxyUrl; } });
20
+ Object.defineProperty(exports, "initFetchProxy", { enumerable: true, get: function () { return proxy_1.initFetchProxy; } });
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 配置文件路径解析
3
+ *
4
+ * 配置目录:~/.v2er-insight/
5
+ * 配置文件:~/.v2er-insight/config.json
6
+ */
7
+ /** 返回配置目录路径 */
8
+ export declare function getConfigDir(): string;
9
+ /** 返回配置文件完整路径 */
10
+ export declare function getConfigPath(): string;
11
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ /**
3
+ * 配置文件路径解析
4
+ *
5
+ * 配置目录:~/.v2er-insight/
6
+ * 配置文件:~/.v2er-insight/config.json
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getConfigDir = getConfigDir;
13
+ exports.getConfigPath = getConfigPath;
14
+ const os_1 = __importDefault(require("os"));
15
+ const path_1 = __importDefault(require("path"));
16
+ /** 配置目录名 */
17
+ const CONFIG_DIR = '.v2er-insight';
18
+ /** 配置文件名 */
19
+ const CONFIG_FILE = 'config.json';
20
+ /** 返回配置目录路径 */
21
+ function getConfigDir() {
22
+ return path_1.default.join(os_1.default.homedir(), CONFIG_DIR);
23
+ }
24
+ /** 返回配置文件完整路径 */
25
+ function getConfigPath() {
26
+ return path_1.default.join(getConfigDir(), CONFIG_FILE);
27
+ }
28
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 获取代理 URL
3
+ * 优先级:配置文件 > HTTPS_PROXY > HTTP_PROXY
4
+ */
5
+ export declare function getProxyUrl(): string | undefined;
6
+ /**
7
+ * 为原生 fetch() 初始化代理
8
+ *
9
+ * 通过 undici 的 setGlobalDispatcher 设置全局代理,
10
+ * 使 @google/genai 等使用原生 fetch() 的库走配置的代理。
11
+ * 不影响 Axios 请求(Fetcher 模块仍使用自己的 httpsAgent)。
12
+ *
13
+ * 应在 CLI 入口处调用一次。
14
+ */
15
+ export declare function initFetchProxy(): void;
16
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getProxyUrl = getProxyUrl;
4
+ exports.initFetchProxy = initFetchProxy;
5
+ const undici_1 = require("undici");
6
+ const storage_1 = require("./storage");
7
+ const logger_1 = require("../infra/logger");
8
+ /**
9
+ * 获取代理 URL
10
+ * 优先级:配置文件 > HTTPS_PROXY > HTTP_PROXY
11
+ */
12
+ function getProxyUrl() {
13
+ const config = (0, storage_1.readConfig)();
14
+ return config.proxy || process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
15
+ }
16
+ /**
17
+ * 为原生 fetch() 初始化代理
18
+ *
19
+ * 通过 undici 的 setGlobalDispatcher 设置全局代理,
20
+ * 使 @google/genai 等使用原生 fetch() 的库走配置的代理。
21
+ * 不影响 Axios 请求(Fetcher 模块仍使用自己的 httpsAgent)。
22
+ *
23
+ * 应在 CLI 入口处调用一次。
24
+ */
25
+ function initFetchProxy() {
26
+ const proxyUrl = getProxyUrl();
27
+ if (!proxyUrl)
28
+ return;
29
+ try {
30
+ (0, undici_1.setGlobalDispatcher)(new undici_1.ProxyAgent(proxyUrl));
31
+ logger_1.logger.debug(`已为原生 fetch 设置代理: ${proxyUrl}`);
32
+ }
33
+ catch (error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ logger_1.logger.warn(`代理初始化失败 (${proxyUrl}): ${message}`);
36
+ logger_1.logger.warn('AI 请求将不使用代理,直接连接');
37
+ }
38
+ }
39
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 配置存储
3
+ *
4
+ * 提供读写配置文件和合并默认值的逻辑。
5
+ * getConfig() 是对外的主要入口,返回默认值与用户设置合并后的完整配置。
6
+ */
7
+ import type { V2erConfig } from './types';
8
+ /**
9
+ * 读取并解析用户配置文件
10
+ * 若文件不存在或解析失败,返回空对象
11
+ */
12
+ export declare function readConfig(): V2erConfig;
13
+ /**
14
+ * 将配置写入文件
15
+ * 自动创建配置目录,使用 0600 权限(Linux/Mac)
16
+ */
17
+ export declare function writeConfig(config: V2erConfig): void;
18
+ /**
19
+ * 获取合并后的完整配置(默认值 + 用户设置)
20
+ * 用户设置会覆盖默认值中的同名字段
21
+ */
22
+ export declare function getConfig(): V2erConfig;
23
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ /**
3
+ * 配置存储
4
+ *
5
+ * 提供读写配置文件和合并默认值的逻辑。
6
+ * getConfig() 是对外的主要入口,返回默认值与用户设置合并后的完整配置。
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.readConfig = readConfig;
13
+ exports.writeConfig = writeConfig;
14
+ exports.getConfig = getConfig;
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const path_1 = require("./path");
17
+ const defaults_1 = require("./defaults");
18
+ // -- 内部工具 ----------------------------------------------------------------
19
+ /**
20
+ * 深合并两个对象(仅处理普通对象,不处理数组)
21
+ * target 的值会被 source 中的非 undefined 值覆盖
22
+ */
23
+ function deepMerge(target, source) {
24
+ const result = { ...target };
25
+ for (const key of Object.keys(source)) {
26
+ const sourceVal = source[key];
27
+ const targetVal = target[key];
28
+ if (sourceVal === undefined)
29
+ continue;
30
+ if (typeof sourceVal === 'object' &&
31
+ sourceVal !== null &&
32
+ !Array.isArray(sourceVal) &&
33
+ typeof targetVal === 'object' &&
34
+ targetVal !== null &&
35
+ !Array.isArray(targetVal)) {
36
+ result[key] = deepMerge(targetVal, sourceVal);
37
+ }
38
+ else {
39
+ result[key] = sourceVal;
40
+ }
41
+ }
42
+ return result;
43
+ }
44
+ // -- 公共 API ----------------------------------------------------------------
45
+ /**
46
+ * 读取并解析用户配置文件
47
+ * 若文件不存在或解析失败,返回空对象
48
+ */
49
+ function readConfig() {
50
+ const configPath = (0, path_1.getConfigPath)();
51
+ if (!fs_1.default.existsSync(configPath)) {
52
+ return {};
53
+ }
54
+ try {
55
+ const content = fs_1.default.readFileSync(configPath, 'utf-8');
56
+ return JSON.parse(content);
57
+ }
58
+ catch {
59
+ return {};
60
+ }
61
+ }
62
+ /**
63
+ * 将配置写入文件
64
+ * 自动创建配置目录,使用 0600 权限(Linux/Mac)
65
+ */
66
+ function writeConfig(config) {
67
+ const configDir = (0, path_1.getConfigDir)();
68
+ const configPath = (0, path_1.getConfigPath)();
69
+ if (!fs_1.default.existsSync(configDir)) {
70
+ fs_1.default.mkdirSync(configDir, { recursive: true });
71
+ }
72
+ fs_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2), {
73
+ encoding: 'utf-8',
74
+ mode: 0o600,
75
+ });
76
+ }
77
+ /**
78
+ * 获取合并后的完整配置(默认值 + 用户设置)
79
+ * 用户设置会覆盖默认值中的同名字段
80
+ */
81
+ function getConfig() {
82
+ const userConfig = readConfig();
83
+ return deepMerge({ ...defaults_1.DEFAULT_CONFIG }, userConfig);
84
+ }
85
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1,31 @@
1
+ /**
2
+ * AI 模块配置类型
3
+ *
4
+ * ThinkingLevel 使用小写值,与 @google/genai SDK 内部类型一致。
5
+ * SDK 导出的枚举值(如 ThinkingLevel.HIGH = "HIGH")用于 API 调用,
6
+ * 但配置文件面向用户,使用小写更友好。
7
+ */
8
+ /** 合法的思考水平值(运行时校验用) */
9
+ export declare const THINKING_LEVELS: readonly ["minimal", "low", "medium", "high"];
10
+ /** 思考水平类型(从 THINKING_LEVELS 派生,保证类型与运行时一致) */
11
+ export type ThinkingLevel = (typeof THINKING_LEVELS)[number];
12
+ /** AI 模块配置 */
13
+ export interface AIConfig {
14
+ /** AI 提供商(目前仅支持 gemini) */
15
+ provider?: string;
16
+ /** API 密钥 */
17
+ apiKey?: string;
18
+ /** 模型名称 */
19
+ model?: string;
20
+ /** 思考水平 */
21
+ thinkingLevel?: ThinkingLevel;
22
+ /** AI 请求超时(毫秒) */
23
+ timeout?: number;
24
+ /** 最大重试次数 */
25
+ maxRetries?: number;
26
+ /** 重试基础延迟(毫秒) */
27
+ baseDelay?: number;
28
+ /** 重试最大延迟(毫秒) */
29
+ maxDelay?: number;
30
+ }
31
+ //# sourceMappingURL=ai.d.ts.map
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ /**
3
+ * AI 模块配置类型
4
+ *
5
+ * ThinkingLevel 使用小写值,与 @google/genai SDK 内部类型一致。
6
+ * SDK 导出的枚举值(如 ThinkingLevel.HIGH = "HIGH")用于 API 调用,
7
+ * 但配置文件面向用户,使用小写更友好。
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.THINKING_LEVELS = void 0;
11
+ /** 合法的思考水平值(运行时校验用) */
12
+ exports.THINKING_LEVELS = ['minimal', 'low', 'medium', 'high'];
13
+ //# sourceMappingURL=ai.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Analyzer 模块配置类型
3
+ */
4
+ /** Analyzer 模块配置 */
5
+ export interface AnalyzerConfig {
6
+ /** 暂停期检测阈值(天) */
7
+ inactivityThreshold?: number;
8
+ /** 单片最大帖子数 */
9
+ chunkMaxTopics?: number;
10
+ /** 单片最大回复数 */
11
+ chunkMaxReplies?: number;
12
+ /** 节点分布 Top N */
13
+ nodeDistributionTopN?: number;
14
+ }
15
+ //# sourceMappingURL=analyzer.d.ts.map
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Analyzer 模块配置类型
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=analyzer.js.map