@plolink/sdk 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -4
- package/dist/{chunk-LHNCGCWW.js → chunk-4H4RACSE.js} +3 -137
- package/dist/chunk-4H4RACSE.js.map +1 -0
- package/dist/{chunk-WFBN23AH.cjs → chunk-NS3DJP2O.cjs} +2 -141
- package/dist/chunk-NS3DJP2O.cjs.map +1 -0
- package/dist/chunk-PJAJFV7D.js +139 -0
- package/dist/chunk-PJAJFV7D.js.map +1 -0
- package/dist/chunk-V6NFRYO2.cjs +145 -0
- package/dist/chunk-V6NFRYO2.cjs.map +1 -0
- package/dist/client-CAjIQKPm.d.cts +193 -0
- package/dist/client-CwNikk7i.d.ts +193 -0
- package/dist/common/index.cjs +19 -18
- package/dist/common/index.d.cts +2 -126
- package/dist/common/index.d.ts +2 -126
- package/dist/common/index.js +2 -1
- package/dist/index.cjs +18 -751
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -410
- package/dist/index.d.ts +4 -410
- package/dist/index.js +4 -735
- package/dist/index.js.map +1 -1
- package/dist/modules/billing/index.cjs +1 -1
- package/dist/modules/billing/index.d.cts +1 -1
- package/dist/modules/billing/index.d.ts +1 -1
- package/dist/modules/billing/index.js +1 -1
- package/dist/modules/info-sync/index.cjs +275 -0
- package/dist/modules/info-sync/index.cjs.map +1 -0
- package/dist/modules/info-sync/index.d.cts +431 -0
- package/dist/modules/info-sync/index.d.ts +431 -0
- package/dist/modules/info-sync/index.js +269 -0
- package/dist/modules/info-sync/index.js.map +1 -0
- package/dist/modules/psychology-test/index.cjs +474 -0
- package/dist/modules/psychology-test/index.cjs.map +1 -0
- package/dist/{client-DXKAtLg1.d.ts → modules/psychology-test/index.d.cts} +34 -200
- package/dist/{client-l6cekf09.d.cts → modules/psychology-test/index.d.ts} +34 -200
- package/dist/modules/psychology-test/index.js +472 -0
- package/dist/modules/psychology-test/index.js.map +1 -0
- package/dist/modules/rbac/index.d.cts +1 -1
- package/dist/modules/rbac/index.d.ts +1 -1
- package/dist/modules/report-writer/index.cjs +282 -0
- package/dist/modules/report-writer/index.cjs.map +1 -0
- package/dist/modules/report-writer/index.d.cts +476 -0
- package/dist/modules/report-writer/index.d.ts +476 -0
- package/dist/modules/report-writer/index.js +280 -0
- package/dist/modules/report-writer/index.js.map +1 -0
- package/dist/modules/team/index.d.cts +1 -1
- package/dist/modules/team/index.d.ts +1 -1
- package/dist/modules/video-psych-analysis/index.cjs +1 -1
- package/dist/modules/video-psych-analysis/index.d.cts +1 -1
- package/dist/modules/video-psych-analysis/index.d.ts +1 -1
- package/dist/modules/video-psych-analysis/index.js +1 -1
- package/dist/modules/virtual-account/index.d.cts +1 -1
- package/dist/modules/virtual-account/index.d.ts +1 -1
- package/dist/signature-B5LL3Zij.d.cts +126 -0
- package/dist/signature-B5LL3Zij.d.ts +126 -0
- package/package.json +17 -1
- package/dist/chunk-LHNCGCWW.js.map +0 -1
- package/dist/chunk-WFBN23AH.cjs.map +0 -1
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { PlolinkError } from '../../chunk-MD4O7FWT.js';
|
|
2
|
+
|
|
3
|
+
// src/modules/report-writer/index.ts
|
|
4
|
+
var ReportWriter = class {
|
|
5
|
+
constructor(client) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* 创建报告
|
|
10
|
+
*
|
|
11
|
+
* @description
|
|
12
|
+
* 创建一个新的报告任务,系统会自动加入队列进行处理。
|
|
13
|
+
* 报告生成过程是异步的,需要通过 getDetail() 方法轮询检查状态。
|
|
14
|
+
*
|
|
15
|
+
* @param params - 创建报告参数
|
|
16
|
+
* @param params.name - 报告名称
|
|
17
|
+
* @param params.instruction - 写作指令,描述要生成的文章内容
|
|
18
|
+
* @param params.businessCode - 业务代号,用于后续处理策略分发
|
|
19
|
+
* @param params.externalId - 外部ID,关联外部业务系统
|
|
20
|
+
* @param params.materials - 参考材料数组(可选)
|
|
21
|
+
* @param params.articleLevel - 文章层级,1-3,默认 3(可选)
|
|
22
|
+
*
|
|
23
|
+
* @returns 创建结果,包含报告ID
|
|
24
|
+
*
|
|
25
|
+
* @throws {PlolinkError} 参数验证失败或 API 调用失败
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const result = await client.reportWriter.create({
|
|
30
|
+
* name: '2024年度总结报告',
|
|
31
|
+
* instruction: '请根据提供的材料,撰写一份年度工作总结报告',
|
|
32
|
+
* businessCode: 'annual-report',
|
|
33
|
+
* externalId: '2024-001',
|
|
34
|
+
* articleLevel: 3,
|
|
35
|
+
* materials: [
|
|
36
|
+
* {
|
|
37
|
+
* type: 'text',
|
|
38
|
+
* content: '2024年完成了10个项目,总营收增长30%...'
|
|
39
|
+
* }
|
|
40
|
+
* ]
|
|
41
|
+
* });
|
|
42
|
+
* console.log(`报告ID: ${result.id}`);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
async create(params) {
|
|
46
|
+
this.client.logger.debug("Creating report", { params });
|
|
47
|
+
if (!params.name?.trim()) {
|
|
48
|
+
throw new PlolinkError("Parameter validation failed: name is required", "VALIDATION_ERROR");
|
|
49
|
+
}
|
|
50
|
+
if (!params.instruction?.trim()) {
|
|
51
|
+
throw new PlolinkError("Parameter validation failed: instruction is required", "VALIDATION_ERROR");
|
|
52
|
+
}
|
|
53
|
+
if (!params.businessCode?.trim()) {
|
|
54
|
+
throw new PlolinkError("Parameter validation failed: businessCode is required", "VALIDATION_ERROR");
|
|
55
|
+
}
|
|
56
|
+
if (!params.externalId?.trim()) {
|
|
57
|
+
throw new PlolinkError("Parameter validation failed: externalId is required", "VALIDATION_ERROR");
|
|
58
|
+
}
|
|
59
|
+
if (params.articleLevel !== void 0 && (params.articleLevel < 1 || params.articleLevel > 3)) {
|
|
60
|
+
throw new PlolinkError("Parameter validation failed: articleLevel must be between 1 and 3", "VALIDATION_ERROR");
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const response = await this.client.axiosInstance.post(
|
|
64
|
+
"/api/v1/report-writer/reports",
|
|
65
|
+
params
|
|
66
|
+
);
|
|
67
|
+
this.client.logger.info("Report created successfully", { reportId: response.id });
|
|
68
|
+
return response;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
this.client.logger.error("Failed to create report", { error, params });
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 获取报告列表
|
|
76
|
+
*
|
|
77
|
+
* @description
|
|
78
|
+
* 分页获取报告列表,支持按状态、业务代号、关键词筛选。
|
|
79
|
+
*
|
|
80
|
+
* @param params - 查询参数(可选)
|
|
81
|
+
* @param params.page - 页码,默认 1(可选)
|
|
82
|
+
* @param params.pageSize - 每页数量,默认 20(可选)
|
|
83
|
+
* @param params.keyword - 搜索关键词(报告名称、业务代号)(可选)
|
|
84
|
+
* @param params.status - 状态筛选(可选)
|
|
85
|
+
* @param params.businessCode - 业务代号筛选(可选)
|
|
86
|
+
*
|
|
87
|
+
* @returns 分页列表结果
|
|
88
|
+
*
|
|
89
|
+
* @throws {PlolinkError} API 调用失败
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* // 获取所有报告
|
|
94
|
+
* const allReports = await client.reportWriter.list();
|
|
95
|
+
*
|
|
96
|
+
* // 分页查询
|
|
97
|
+
* const page2 = await client.reportWriter.list({
|
|
98
|
+
* page: 2,
|
|
99
|
+
* pageSize: 10
|
|
100
|
+
* });
|
|
101
|
+
*
|
|
102
|
+
* // 按状态筛选
|
|
103
|
+
* const completedReports = await client.reportWriter.list({
|
|
104
|
+
* status: 'COMPLETED'
|
|
105
|
+
* });
|
|
106
|
+
*
|
|
107
|
+
* // 按业务代号和关键词筛选
|
|
108
|
+
* const filtered = await client.reportWriter.list({
|
|
109
|
+
* businessCode: 'annual-report',
|
|
110
|
+
* keyword: '2024'
|
|
111
|
+
* });
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
async list(params) {
|
|
115
|
+
this.client.logger.debug("Listing reports", { params });
|
|
116
|
+
try {
|
|
117
|
+
const queryParams = {};
|
|
118
|
+
if (params?.page !== void 0) {
|
|
119
|
+
queryParams.page = params.page.toString();
|
|
120
|
+
}
|
|
121
|
+
if (params?.pageSize !== void 0) {
|
|
122
|
+
queryParams.pageSize = params.pageSize.toString();
|
|
123
|
+
}
|
|
124
|
+
if (params?.keyword) {
|
|
125
|
+
queryParams.keyword = params.keyword;
|
|
126
|
+
}
|
|
127
|
+
if (params?.status) {
|
|
128
|
+
queryParams.status = params.status;
|
|
129
|
+
}
|
|
130
|
+
if (params?.businessCode) {
|
|
131
|
+
queryParams.businessCode = params.businessCode;
|
|
132
|
+
}
|
|
133
|
+
const response = await this.client.axiosInstance.get(
|
|
134
|
+
"/api/v1/report-writer/reports",
|
|
135
|
+
{ params: queryParams }
|
|
136
|
+
);
|
|
137
|
+
this.client.logger.info("Reports listed successfully", {
|
|
138
|
+
total: response.total,
|
|
139
|
+
page: response.page,
|
|
140
|
+
pageSize: response.pageSize
|
|
141
|
+
});
|
|
142
|
+
return response;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
this.client.logger.error("Failed to list reports", { error, params });
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 获取报告详情
|
|
150
|
+
*
|
|
151
|
+
* @description
|
|
152
|
+
* 获取单个报告的完整详情,包括文章风格、结构化内容和生成状态。
|
|
153
|
+
* 可用于轮询检查报告生成进度。
|
|
154
|
+
*
|
|
155
|
+
* @param id - 报告ID
|
|
156
|
+
*
|
|
157
|
+
* @returns 报告详情
|
|
158
|
+
*
|
|
159
|
+
* @throws {PlolinkError} 报告不存在或 API 调用失败
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* // 获取报告详情
|
|
164
|
+
* const detail = await client.reportWriter.getDetail('report-123');
|
|
165
|
+
* console.log(`状态: ${detail.status}`);
|
|
166
|
+
*
|
|
167
|
+
* // 轮询检查状态
|
|
168
|
+
* let report = await client.reportWriter.getDetail('report-123');
|
|
169
|
+
* while (report.status !== 'COMPLETED' && report.status !== 'FAILED') {
|
|
170
|
+
* await new Promise(resolve => setTimeout(resolve, 5000)); // 等待5秒
|
|
171
|
+
* report = await client.reportWriter.getDetail('report-123');
|
|
172
|
+
* console.log(`当前状态: ${report.status}`);
|
|
173
|
+
* }
|
|
174
|
+
*
|
|
175
|
+
* if (report.status === 'COMPLETED') {
|
|
176
|
+
* console.log('报告生成完成');
|
|
177
|
+
* } else {
|
|
178
|
+
* console.error('报告生成失败:', report.errorMessage);
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
async getDetail(id) {
|
|
183
|
+
this.client.logger.debug("Getting report detail", { id });
|
|
184
|
+
if (!id?.trim()) {
|
|
185
|
+
throw new PlolinkError("Parameter validation failed: id is required", "VALIDATION_ERROR");
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
const response = await this.client.axiosInstance.get(
|
|
189
|
+
`/api/v1/report-writer/reports/${id}`
|
|
190
|
+
);
|
|
191
|
+
this.client.logger.info("Report detail retrieved", {
|
|
192
|
+
id: response.id,
|
|
193
|
+
status: response.status
|
|
194
|
+
});
|
|
195
|
+
return response;
|
|
196
|
+
} catch (error) {
|
|
197
|
+
this.client.logger.error("Failed to get report detail", { error, id });
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* 删除报告
|
|
203
|
+
*
|
|
204
|
+
* @description
|
|
205
|
+
* 软删除指定报告。已删除的报告无法恢复。
|
|
206
|
+
*
|
|
207
|
+
* @param id - 报告ID
|
|
208
|
+
*
|
|
209
|
+
* @returns Promise<void>
|
|
210
|
+
*
|
|
211
|
+
* @throws {PlolinkError} 报告不存在或 API 调用失败
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* await client.reportWriter.delete('report-123');
|
|
216
|
+
* console.log('报告已删除');
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
async delete(id) {
|
|
220
|
+
this.client.logger.debug("Deleting report", { id });
|
|
221
|
+
if (!id?.trim()) {
|
|
222
|
+
throw new PlolinkError("Parameter validation failed: id is required", "VALIDATION_ERROR");
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
await this.client.axiosInstance.delete(
|
|
226
|
+
`/api/v1/report-writer/reports/${id}`
|
|
227
|
+
);
|
|
228
|
+
this.client.logger.info("Report deleted successfully", { id });
|
|
229
|
+
} catch (error) {
|
|
230
|
+
this.client.logger.error("Failed to delete report", { error, id });
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* 获取 Markdown 格式
|
|
236
|
+
*
|
|
237
|
+
* @description
|
|
238
|
+
* 将报告内容渲染为 Markdown 格式。
|
|
239
|
+
* 只有状态为 COMPLETED 的报告才能导出 Markdown。
|
|
240
|
+
*
|
|
241
|
+
* @param id - 报告ID
|
|
242
|
+
*
|
|
243
|
+
* @returns Markdown 内容
|
|
244
|
+
*
|
|
245
|
+
* @throws {PlolinkError} 报告不存在、未完成或 API 调用失败
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```typescript
|
|
249
|
+
* const result = await client.reportWriter.getMarkdown('report-123');
|
|
250
|
+
* console.log(result.markdown);
|
|
251
|
+
*
|
|
252
|
+
* // 保存为文件
|
|
253
|
+
* const fs = require('fs');
|
|
254
|
+
* fs.writeFileSync('report.md', result.markdown, 'utf-8');
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
async getMarkdown(id) {
|
|
258
|
+
this.client.logger.debug("Getting report markdown", { id });
|
|
259
|
+
if (!id?.trim()) {
|
|
260
|
+
throw new PlolinkError("Parameter validation failed: id is required", "VALIDATION_ERROR");
|
|
261
|
+
}
|
|
262
|
+
try {
|
|
263
|
+
const response = await this.client.axiosInstance.get(
|
|
264
|
+
`/api/v1/report-writer/reports/${id}/markdown`
|
|
265
|
+
);
|
|
266
|
+
this.client.logger.info("Report markdown retrieved", {
|
|
267
|
+
id,
|
|
268
|
+
markdownLength: response.markdown.length
|
|
269
|
+
});
|
|
270
|
+
return response;
|
|
271
|
+
} catch (error) {
|
|
272
|
+
this.client.logger.error("Failed to get report markdown", { error, id });
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
export { ReportWriter };
|
|
279
|
+
//# sourceMappingURL=index.js.map
|
|
280
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/modules/report-writer/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Report Writer 模块\n * \n * @description\n * 提供 AI 自动报告写作功能,支持:\n * - 创建报告任务\n * - 查询报告列表和详情\n * - 删除报告\n * - 导出 Markdown 格式\n * \n * @example\n * ```typescript\n * import { PlolinkClient } from '@plolink/sdk';\n * \n * const client = new PlolinkClient({\n * token: 'sk-your-api-key'\n * });\n * \n * // 创建报告\n * const createResult = await client.reportWriter.create({\n * name: '2024年度总结报告',\n * instruction: '请根据提供的材料,撰写一份年度工作总结报告',\n * businessCode: 'annual-report',\n * externalId: '2024-001',\n * articleLevel: 3,\n * materials: [\n * {\n * type: 'text',\n * content: '2024年完成了10个项目,总营收增长30%...'\n * }\n * ]\n * });\n * console.log(`报告创建成功: ${createResult.id}`);\n * \n * // 查询报告详情(轮询检查状态)\n * let detail = await client.reportWriter.getDetail(createResult.id);\n * while (detail.status !== 'COMPLETED' && detail.status !== 'FAILED') {\n * await new Promise(resolve => setTimeout(resolve, 5000));\n * detail = await client.reportWriter.getDetail(createResult.id);\n * console.log(`当前状态: ${detail.status}`);\n * }\n * \n * // 获取 Markdown 格式\n * if (detail.status === 'COMPLETED') {\n * const markdown = await client.reportWriter.getMarkdown(createResult.id);\n * console.log('报告内容:', markdown.markdown);\n * }\n * ```\n * \n * @module report-writer\n */\n\nimport { PlolinkClient } from '../../core/client';\nimport { PlolinkError } from '../../core/error';\nimport type {\n CreateReportParams,\n CreateReportResponse,\n ListReportsParams,\n ListReportsResponse,\n ReportDetail,\n GetMarkdownResponse,\n} from '../../types/report-writer';\n\nexport type {\n ReportStatus,\n MaterialType,\n MaterialItem,\n MaterialsSummary,\n ArticleStyle,\n ReviewSuggestion,\n ArticleNode,\n CreateReportParams,\n CreateReportResponse,\n ListReportsParams,\n ReportSummary,\n ListReportsResponse,\n ReportDetail,\n GetMarkdownResponse,\n ReportWebhookData,\n} from '../../types/report-writer';\n\n/**\n * Report Writer 模块类\n * \n * @description\n * 提供 AI 报告写作相关功能的封装,包括创建报告、查询状态、导出结果等。\n * \n * 报告生成流程:\n * 1. 调用 create() 创建报告,返回 reportId\n * 2. 后端异步处理,经历多个阶段(STYLE_GENERATING → ... → COMPLETED)\n * 3. 使用 getDetail() 轮询检查状态\n * 4. 完成后调用 getMarkdown() 获取最终结果\n * \n * Webhook 通知:\n * - REPORT_COMPLETED - 报告生成完成\n * - REPORT_FAILED - 报告生成失败\n */\nexport class ReportWriter {\n private client: PlolinkClient;\n\n constructor(client: PlolinkClient) {\n this.client = client;\n }\n\n /**\n * 创建报告\n * \n * @description\n * 创建一个新的报告任务,系统会自动加入队列进行处理。\n * 报告生成过程是异步的,需要通过 getDetail() 方法轮询检查状态。\n * \n * @param params - 创建报告参数\n * @param params.name - 报告名称\n * @param params.instruction - 写作指令,描述要生成的文章内容\n * @param params.businessCode - 业务代号,用于后续处理策略分发\n * @param params.externalId - 外部ID,关联外部业务系统\n * @param params.materials - 参考材料数组(可选)\n * @param params.articleLevel - 文章层级,1-3,默认 3(可选)\n * \n * @returns 创建结果,包含报告ID\n * \n * @throws {PlolinkError} 参数验证失败或 API 调用失败\n * \n * @example\n * ```typescript\n * const result = await client.reportWriter.create({\n * name: '2024年度总结报告',\n * instruction: '请根据提供的材料,撰写一份年度工作总结报告',\n * businessCode: 'annual-report',\n * externalId: '2024-001',\n * articleLevel: 3,\n * materials: [\n * {\n * type: 'text',\n * content: '2024年完成了10个项目,总营收增长30%...'\n * }\n * ]\n * });\n * console.log(`报告ID: ${result.id}`);\n * ```\n */\n public async create(params: CreateReportParams): Promise<CreateReportResponse> {\n this.client.logger.debug('Creating report', { params });\n\n // 参数验证\n if (!params.name?.trim()) {\n throw new PlolinkError('Parameter validation failed: name is required', 'VALIDATION_ERROR');\n }\n if (!params.instruction?.trim()) {\n throw new PlolinkError('Parameter validation failed: instruction is required', 'VALIDATION_ERROR');\n }\n if (!params.businessCode?.trim()) {\n throw new PlolinkError('Parameter validation failed: businessCode is required', 'VALIDATION_ERROR');\n }\n if (!params.externalId?.trim()) {\n throw new PlolinkError('Parameter validation failed: externalId is required', 'VALIDATION_ERROR');\n }\n if (params.articleLevel !== undefined && (params.articleLevel < 1 || params.articleLevel > 3)) {\n throw new PlolinkError('Parameter validation failed: articleLevel must be between 1 and 3', 'VALIDATION_ERROR');\n }\n\n try {\n const response = await this.client.axiosInstance.post<CreateReportResponse>(\n '/api/v1/report-writer/reports',\n params\n );\n\n this.client.logger.info('Report created successfully', { reportId: response.id });\n return response;\n } catch (error) {\n this.client.logger.error('Failed to create report', { error, params });\n throw error;\n }\n }\n\n /**\n * 获取报告列表\n * \n * @description\n * 分页获取报告列表,支持按状态、业务代号、关键词筛选。\n * \n * @param params - 查询参数(可选)\n * @param params.page - 页码,默认 1(可选)\n * @param params.pageSize - 每页数量,默认 20(可选)\n * @param params.keyword - 搜索关键词(报告名称、业务代号)(可选)\n * @param params.status - 状态筛选(可选)\n * @param params.businessCode - 业务代号筛选(可选)\n * \n * @returns 分页列表结果\n * \n * @throws {PlolinkError} API 调用失败\n * \n * @example\n * ```typescript\n * // 获取所有报告\n * const allReports = await client.reportWriter.list();\n * \n * // 分页查询\n * const page2 = await client.reportWriter.list({\n * page: 2,\n * pageSize: 10\n * });\n * \n * // 按状态筛选\n * const completedReports = await client.reportWriter.list({\n * status: 'COMPLETED'\n * });\n * \n * // 按业务代号和关键词筛选\n * const filtered = await client.reportWriter.list({\n * businessCode: 'annual-report',\n * keyword: '2024'\n * });\n * ```\n */\n public async list(params?: ListReportsParams): Promise<ListReportsResponse> {\n this.client.logger.debug('Listing reports', { params });\n\n try {\n const queryParams: Record<string, string> = {};\n \n if (params?.page !== undefined) {\n queryParams.page = params.page.toString();\n }\n if (params?.pageSize !== undefined) {\n queryParams.pageSize = params.pageSize.toString();\n }\n if (params?.keyword) {\n queryParams.keyword = params.keyword;\n }\n if (params?.status) {\n queryParams.status = params.status;\n }\n if (params?.businessCode) {\n queryParams.businessCode = params.businessCode;\n }\n\n const response = await this.client.axiosInstance.get<ListReportsResponse>(\n '/api/v1/report-writer/reports',\n { params: queryParams }\n );\n\n this.client.logger.info('Reports listed successfully', { \n total: response.total,\n page: response.page,\n pageSize: response.pageSize\n });\n return response;\n } catch (error) {\n this.client.logger.error('Failed to list reports', { error, params });\n throw error;\n }\n }\n\n /**\n * 获取报告详情\n * \n * @description\n * 获取单个报告的完整详情,包括文章风格、结构化内容和生成状态。\n * 可用于轮询检查报告生成进度。\n * \n * @param id - 报告ID\n * \n * @returns 报告详情\n * \n * @throws {PlolinkError} 报告不存在或 API 调用失败\n * \n * @example\n * ```typescript\n * // 获取报告详情\n * const detail = await client.reportWriter.getDetail('report-123');\n * console.log(`状态: ${detail.status}`);\n * \n * // 轮询检查状态\n * let report = await client.reportWriter.getDetail('report-123');\n * while (report.status !== 'COMPLETED' && report.status !== 'FAILED') {\n * await new Promise(resolve => setTimeout(resolve, 5000)); // 等待5秒\n * report = await client.reportWriter.getDetail('report-123');\n * console.log(`当前状态: ${report.status}`);\n * }\n * \n * if (report.status === 'COMPLETED') {\n * console.log('报告生成完成');\n * } else {\n * console.error('报告生成失败:', report.errorMessage);\n * }\n * ```\n */\n public async getDetail(id: string): Promise<ReportDetail> {\n this.client.logger.debug('Getting report detail', { id });\n\n if (!id?.trim()) {\n throw new PlolinkError('Parameter validation failed: id is required', 'VALIDATION_ERROR');\n }\n\n try {\n const response = await this.client.axiosInstance.get<ReportDetail>(\n `/api/v1/report-writer/reports/${id}`\n );\n\n this.client.logger.info('Report detail retrieved', { \n id: response.id,\n status: response.status\n });\n return response;\n } catch (error) {\n this.client.logger.error('Failed to get report detail', { error, id });\n throw error;\n }\n }\n\n /**\n * 删除报告\n * \n * @description\n * 软删除指定报告。已删除的报告无法恢复。\n * \n * @param id - 报告ID\n * \n * @returns Promise<void>\n * \n * @throws {PlolinkError} 报告不存在或 API 调用失败\n * \n * @example\n * ```typescript\n * await client.reportWriter.delete('report-123');\n * console.log('报告已删除');\n * ```\n */\n public async delete(id: string): Promise<void> {\n this.client.logger.debug('Deleting report', { id });\n\n if (!id?.trim()) {\n throw new PlolinkError('Parameter validation failed: id is required', 'VALIDATION_ERROR');\n }\n\n try {\n await this.client.axiosInstance.delete<{ message: string }>(\n `/api/v1/report-writer/reports/${id}`\n );\n\n this.client.logger.info('Report deleted successfully', { id });\n } catch (error) {\n this.client.logger.error('Failed to delete report', { error, id });\n throw error;\n }\n }\n\n /**\n * 获取 Markdown 格式\n * \n * @description\n * 将报告内容渲染为 Markdown 格式。\n * 只有状态为 COMPLETED 的报告才能导出 Markdown。\n * \n * @param id - 报告ID\n * \n * @returns Markdown 内容\n * \n * @throws {PlolinkError} 报告不存在、未完成或 API 调用失败\n * \n * @example\n * ```typescript\n * const result = await client.reportWriter.getMarkdown('report-123');\n * console.log(result.markdown);\n * \n * // 保存为文件\n * const fs = require('fs');\n * fs.writeFileSync('report.md', result.markdown, 'utf-8');\n * ```\n */\n public async getMarkdown(id: string): Promise<GetMarkdownResponse> {\n this.client.logger.debug('Getting report markdown', { id });\n\n if (!id?.trim()) {\n throw new PlolinkError('Parameter validation failed: id is required', 'VALIDATION_ERROR');\n }\n\n try {\n const response = await this.client.axiosInstance.get<GetMarkdownResponse>(\n `/api/v1/report-writer/reports/${id}/markdown`\n );\n\n this.client.logger.info('Report markdown retrieved', { \n id,\n markdownLength: response.markdown.length\n });\n return response;\n } catch (error) {\n this.client.logger.error('Failed to get report markdown', { error, id });\n throw error;\n }\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var chunkY3UJVC2L_cjs = require('../../chunk-Y3UJVC2L.cjs');
|
|
4
3
|
var chunkJR4HYYQI_cjs = require('../../chunk-JR4HYYQI.cjs');
|
|
4
|
+
var chunkY3UJVC2L_cjs = require('../../chunk-Y3UJVC2L.cjs');
|
|
5
5
|
|
|
6
6
|
// src/modules/video-psych-analysis/index.ts
|
|
7
7
|
var VideoPsychAnalysis = class {
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 信息同步签名工具
|
|
3
|
+
*
|
|
4
|
+
* 用于生成和验证 Webhook 请求的 HMAC-SHA256 签名
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* // 验证 Webhook 签名
|
|
9
|
+
* const timestamp = parseInt(req.headers['x-sync-timestamp']);
|
|
10
|
+
* const signature = req.headers['x-sync-signature'];
|
|
11
|
+
* const payload = JSON.stringify(req.body);
|
|
12
|
+
*
|
|
13
|
+
* const isValid = InfoSyncSignature.verifySignature(
|
|
14
|
+
* secretKey,
|
|
15
|
+
* timestamp,
|
|
16
|
+
* payload,
|
|
17
|
+
* signature
|
|
18
|
+
* );
|
|
19
|
+
*
|
|
20
|
+
* if (!isValid) {
|
|
21
|
+
* return res.status(401).json({ error: 'Invalid signature' });
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare class InfoSyncSignature {
|
|
26
|
+
/**
|
|
27
|
+
* 生成 HMAC-SHA256 签名
|
|
28
|
+
*
|
|
29
|
+
* 签名算法:
|
|
30
|
+
* - message = `${timestamp}.${payload}`
|
|
31
|
+
* - signature = HMAC-SHA256(secretKey, message)
|
|
32
|
+
*
|
|
33
|
+
* @param secretKey - 密钥(从创建 Webhook 配置时获得)
|
|
34
|
+
* @param timestamp - 时间戳(毫秒)
|
|
35
|
+
* @param payload - 负载字符串(通常是 JSON.stringify 后的请求体)
|
|
36
|
+
* @returns 签名(hex 格式)
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const timestamp = Date.now();
|
|
41
|
+
* const payload = JSON.stringify({ foo: 'bar' });
|
|
42
|
+
* const signature = InfoSyncSignature.generateSignature(
|
|
43
|
+
* 'your-secret-key',
|
|
44
|
+
* timestamp,
|
|
45
|
+
* payload
|
|
46
|
+
* );
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
static generateSignature(secretKey: string, timestamp: number, payload: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* 验证 HMAC-SHA256 签名
|
|
52
|
+
*
|
|
53
|
+
* @param secretKey - 密钥
|
|
54
|
+
* @param timestamp - 时间戳(毫秒)
|
|
55
|
+
* @param payload - 负载字符串
|
|
56
|
+
* @param signature - 待验证的签名
|
|
57
|
+
* @returns 签名是否有效
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const isValid = InfoSyncSignature.verifySignature(
|
|
62
|
+
* secretKey,
|
|
63
|
+
* timestamp,
|
|
64
|
+
* payload,
|
|
65
|
+
* signature
|
|
66
|
+
* );
|
|
67
|
+
*
|
|
68
|
+
* if (!isValid) {
|
|
69
|
+
* throw new Error('Invalid signature');
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
static verifySignature(secretKey: string, timestamp: number, payload: string, signature: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* 验证时间戳是否在有效期内
|
|
76
|
+
*
|
|
77
|
+
* 用于防止重放攻击,确保请求是最近发送的
|
|
78
|
+
*
|
|
79
|
+
* @param timestamp - 时间戳(毫秒)
|
|
80
|
+
* @param maxAge - 最大有效期(毫秒),默认 5 分钟
|
|
81
|
+
* @returns 时间戳是否有效
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const timestamp = parseInt(req.headers['x-sync-timestamp']);
|
|
86
|
+
*
|
|
87
|
+
* // 验证时间戳是否在 5 分钟内
|
|
88
|
+
* if (!InfoSyncSignature.verifyTimestamp(timestamp, 5 * 60 * 1000)) {
|
|
89
|
+
* return res.status(401).json({ error: 'Timestamp expired' });
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
static verifyTimestamp(timestamp: number, maxAge?: number): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* 完整的 Webhook 请求验证
|
|
96
|
+
*
|
|
97
|
+
* 同时验证签名和时间戳,是推荐的验证方式
|
|
98
|
+
*
|
|
99
|
+
* @param secretKey - 密钥
|
|
100
|
+
* @param timestamp - 时间戳(毫秒)
|
|
101
|
+
* @param payload - 负载字符串
|
|
102
|
+
* @param signature - 待验证的签名
|
|
103
|
+
* @param maxAge - 最大有效期(毫秒),默认 5 分钟
|
|
104
|
+
* @returns 验证结果
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const result = InfoSyncSignature.verifyWebhookRequest(
|
|
109
|
+
* secretKey,
|
|
110
|
+
* timestamp,
|
|
111
|
+
* payload,
|
|
112
|
+
* signature
|
|
113
|
+
* );
|
|
114
|
+
*
|
|
115
|
+
* if (!result.valid) {
|
|
116
|
+
* return res.status(401).json({ error: result.error });
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
static verifyWebhookRequest(secretKey: string, timestamp: number, payload: string, signature: string, maxAge?: number): {
|
|
121
|
+
valid: boolean;
|
|
122
|
+
error?: string;
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export { InfoSyncSignature as I };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 信息同步签名工具
|
|
3
|
+
*
|
|
4
|
+
* 用于生成和验证 Webhook 请求的 HMAC-SHA256 签名
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* // 验证 Webhook 签名
|
|
9
|
+
* const timestamp = parseInt(req.headers['x-sync-timestamp']);
|
|
10
|
+
* const signature = req.headers['x-sync-signature'];
|
|
11
|
+
* const payload = JSON.stringify(req.body);
|
|
12
|
+
*
|
|
13
|
+
* const isValid = InfoSyncSignature.verifySignature(
|
|
14
|
+
* secretKey,
|
|
15
|
+
* timestamp,
|
|
16
|
+
* payload,
|
|
17
|
+
* signature
|
|
18
|
+
* );
|
|
19
|
+
*
|
|
20
|
+
* if (!isValid) {
|
|
21
|
+
* return res.status(401).json({ error: 'Invalid signature' });
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare class InfoSyncSignature {
|
|
26
|
+
/**
|
|
27
|
+
* 生成 HMAC-SHA256 签名
|
|
28
|
+
*
|
|
29
|
+
* 签名算法:
|
|
30
|
+
* - message = `${timestamp}.${payload}`
|
|
31
|
+
* - signature = HMAC-SHA256(secretKey, message)
|
|
32
|
+
*
|
|
33
|
+
* @param secretKey - 密钥(从创建 Webhook 配置时获得)
|
|
34
|
+
* @param timestamp - 时间戳(毫秒)
|
|
35
|
+
* @param payload - 负载字符串(通常是 JSON.stringify 后的请求体)
|
|
36
|
+
* @returns 签名(hex 格式)
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const timestamp = Date.now();
|
|
41
|
+
* const payload = JSON.stringify({ foo: 'bar' });
|
|
42
|
+
* const signature = InfoSyncSignature.generateSignature(
|
|
43
|
+
* 'your-secret-key',
|
|
44
|
+
* timestamp,
|
|
45
|
+
* payload
|
|
46
|
+
* );
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
static generateSignature(secretKey: string, timestamp: number, payload: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* 验证 HMAC-SHA256 签名
|
|
52
|
+
*
|
|
53
|
+
* @param secretKey - 密钥
|
|
54
|
+
* @param timestamp - 时间戳(毫秒)
|
|
55
|
+
* @param payload - 负载字符串
|
|
56
|
+
* @param signature - 待验证的签名
|
|
57
|
+
* @returns 签名是否有效
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const isValid = InfoSyncSignature.verifySignature(
|
|
62
|
+
* secretKey,
|
|
63
|
+
* timestamp,
|
|
64
|
+
* payload,
|
|
65
|
+
* signature
|
|
66
|
+
* );
|
|
67
|
+
*
|
|
68
|
+
* if (!isValid) {
|
|
69
|
+
* throw new Error('Invalid signature');
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
static verifySignature(secretKey: string, timestamp: number, payload: string, signature: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* 验证时间戳是否在有效期内
|
|
76
|
+
*
|
|
77
|
+
* 用于防止重放攻击,确保请求是最近发送的
|
|
78
|
+
*
|
|
79
|
+
* @param timestamp - 时间戳(毫秒)
|
|
80
|
+
* @param maxAge - 最大有效期(毫秒),默认 5 分钟
|
|
81
|
+
* @returns 时间戳是否有效
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const timestamp = parseInt(req.headers['x-sync-timestamp']);
|
|
86
|
+
*
|
|
87
|
+
* // 验证时间戳是否在 5 分钟内
|
|
88
|
+
* if (!InfoSyncSignature.verifyTimestamp(timestamp, 5 * 60 * 1000)) {
|
|
89
|
+
* return res.status(401).json({ error: 'Timestamp expired' });
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
static verifyTimestamp(timestamp: number, maxAge?: number): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* 完整的 Webhook 请求验证
|
|
96
|
+
*
|
|
97
|
+
* 同时验证签名和时间戳,是推荐的验证方式
|
|
98
|
+
*
|
|
99
|
+
* @param secretKey - 密钥
|
|
100
|
+
* @param timestamp - 时间戳(毫秒)
|
|
101
|
+
* @param payload - 负载字符串
|
|
102
|
+
* @param signature - 待验证的签名
|
|
103
|
+
* @param maxAge - 最大有效期(毫秒),默认 5 分钟
|
|
104
|
+
* @returns 验证结果
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const result = InfoSyncSignature.verifyWebhookRequest(
|
|
109
|
+
* secretKey,
|
|
110
|
+
* timestamp,
|
|
111
|
+
* payload,
|
|
112
|
+
* signature
|
|
113
|
+
* );
|
|
114
|
+
*
|
|
115
|
+
* if (!result.valid) {
|
|
116
|
+
* return res.status(401).json({ error: result.error });
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
static verifyWebhookRequest(secretKey: string, timestamp: number, payload: string, signature: string, maxAge?: number): {
|
|
121
|
+
valid: boolean;
|
|
122
|
+
error?: string;
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export { InfoSyncSignature as I };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plolink/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "Plolink 开放平台官方 SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -41,6 +41,21 @@
|
|
|
41
41
|
"import": "./dist/modules/video-psych-analysis/index.js",
|
|
42
42
|
"require": "./dist/modules/video-psych-analysis/index.cjs"
|
|
43
43
|
},
|
|
44
|
+
"./info-sync": {
|
|
45
|
+
"types": "./dist/modules/info-sync/index.d.ts",
|
|
46
|
+
"import": "./dist/modules/info-sync/index.js",
|
|
47
|
+
"require": "./dist/modules/info-sync/index.cjs"
|
|
48
|
+
},
|
|
49
|
+
"./psychology-test": {
|
|
50
|
+
"types": "./dist/modules/psychology-test/index.d.ts",
|
|
51
|
+
"import": "./dist/modules/psychology-test/index.js",
|
|
52
|
+
"require": "./dist/modules/psychology-test/index.cjs"
|
|
53
|
+
},
|
|
54
|
+
"./report-writer": {
|
|
55
|
+
"types": "./dist/modules/report-writer/index.d.ts",
|
|
56
|
+
"import": "./dist/modules/report-writer/index.js",
|
|
57
|
+
"require": "./dist/modules/report-writer/index.cjs"
|
|
58
|
+
},
|
|
44
59
|
"./common": {
|
|
45
60
|
"types": "./dist/common/index.d.ts",
|
|
46
61
|
"import": "./dist/common/index.js",
|
|
@@ -79,6 +94,7 @@
|
|
|
79
94
|
"ts-jest": "^29.1.2",
|
|
80
95
|
"tslib": "^2.8.1",
|
|
81
96
|
"tsup": "^8.0.2",
|
|
97
|
+
"tsx": "^4.21.0",
|
|
82
98
|
"typedoc": "^0.25.8",
|
|
83
99
|
"typedoc-plugin-markdown": "^3.17.1",
|
|
84
100
|
"typescript": "^5.3.3"
|