markpdfdown 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +128 -0
  3. package/bin/cli.js +130 -0
  4. package/dist/main/AnthropicClient-CTbHYiqm.js +193 -0
  5. package/dist/main/GeminiClient-CrtYbwaF.js +196 -0
  6. package/dist/main/OllamaClient-DKJsnvIt.js +197 -0
  7. package/dist/main/OpenAIClient-gyy2nFkw.js +214 -0
  8. package/dist/main/OpenAIResponsesClient-DETYz2nL.js +297 -0
  9. package/dist/main/index.js +3523 -0
  10. package/dist/preload/index.js +102 -0
  11. package/dist/renderer/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  12. package/dist/renderer/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  13. package/dist/renderer/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  14. package/dist/renderer/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  15. package/dist/renderer/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  16. package/dist/renderer/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  17. package/dist/renderer/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  18. package/dist/renderer/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  19. package/dist/renderer/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  20. package/dist/renderer/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  21. package/dist/renderer/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  22. package/dist/renderer/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  23. package/dist/renderer/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  24. package/dist/renderer/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  25. package/dist/renderer/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  26. package/dist/renderer/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  27. package/dist/renderer/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  28. package/dist/renderer/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  29. package/dist/renderer/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  30. package/dist/renderer/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  31. package/dist/renderer/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  32. package/dist/renderer/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  33. package/dist/renderer/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  34. package/dist/renderer/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  35. package/dist/renderer/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  36. package/dist/renderer/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  37. package/dist/renderer/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  38. package/dist/renderer/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  39. package/dist/renderer/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  40. package/dist/renderer/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  41. package/dist/renderer/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  42. package/dist/renderer/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  43. package/dist/renderer/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  44. package/dist/renderer/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  45. package/dist/renderer/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  46. package/dist/renderer/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  47. package/dist/renderer/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  48. package/dist/renderer/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  49. package/dist/renderer/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  50. package/dist/renderer/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  51. package/dist/renderer/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  52. package/dist/renderer/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  53. package/dist/renderer/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  54. package/dist/renderer/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  55. package/dist/renderer/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  56. package/dist/renderer/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  57. package/dist/renderer/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  58. package/dist/renderer/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  59. package/dist/renderer/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  60. package/dist/renderer/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  61. package/dist/renderer/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  62. package/dist/renderer/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  63. package/dist/renderer/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  64. package/dist/renderer/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  65. package/dist/renderer/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  66. package/dist/renderer/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  67. package/dist/renderer/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  68. package/dist/renderer/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  69. package/dist/renderer/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  70. package/dist/renderer/assets/MarkPDFdown-C6Sb1T4M.png +0 -0
  71. package/dist/renderer/assets/index-CbMlWqbh.css +327 -0
  72. package/dist/renderer/assets/index-DeDe7lry.js +123956 -0
  73. package/dist/renderer/index.html +14 -0
  74. package/package.json +156 -0
  75. package/src/core/infrastructure/db/migrations/20250414154412_/migration.sql +24 -0
  76. package/src/core/infrastructure/db/migrations/20250419090345_/migration.sql +29 -0
  77. package/src/core/infrastructure/db/migrations/20250419104636_/migration.sql +47 -0
  78. package/src/core/infrastructure/db/migrations/20260121154536_add_worker_fields/migration.sql +50 -0
  79. package/src/core/infrastructure/db/migrations/20260124014806_/migration.sql +55 -0
  80. package/src/core/infrastructure/db/migrations/migration_lock.toml +3 -0
  81. package/src/core/infrastructure/db/schema.prisma +104 -0
@@ -0,0 +1,297 @@
1
+ import { L as LLMClient } from "./index.js";
2
+ class OpenAIResponsesClient extends LLMClient {
3
+ constructor(apiKey, baseUrl) {
4
+ super(apiKey, baseUrl || "https://api.openai.com/v1/responses");
5
+ }
6
+ /**
7
+ * 执行OpenAI Responses API补全
8
+ */
9
+ async completion(options) {
10
+ try {
11
+ const normalizedOptions = this.normalizeOptions(options);
12
+ const { input, instructions } = this.convertMessagesToResponsesFormat(normalizedOptions.messages);
13
+ const requestBody = {
14
+ model: normalizedOptions.model || "gpt-4o",
15
+ input,
16
+ temperature: normalizedOptions.temperature ?? 0.7,
17
+ max_tokens: normalizedOptions.maxTokens,
18
+ stream: normalizedOptions.stream || false
19
+ };
20
+ if (instructions) {
21
+ requestBody.instructions = instructions;
22
+ }
23
+ if (normalizedOptions.tools && normalizedOptions.tools.length > 0) {
24
+ requestBody.tools = normalizedOptions.tools;
25
+ if (normalizedOptions.tool_choice) {
26
+ requestBody.tool_choice = normalizedOptions.tool_choice;
27
+ }
28
+ }
29
+ if (normalizedOptions.response_format) {
30
+ requestBody.response_format = normalizedOptions.response_format;
31
+ }
32
+ const response = await fetch(`${this.baseUrl}`, {
33
+ method: "POST",
34
+ headers: {
35
+ "Content-Type": "application/json",
36
+ "Authorization": `Bearer ${normalizedOptions.apiKey || this.apiKey}`,
37
+ "X-Title": "MarkPDFdown",
38
+ "HTTP-Referer": "https://github.com/MarkPDFdown"
39
+ },
40
+ body: JSON.stringify(requestBody)
41
+ });
42
+ console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] POST ${this.baseUrl} (model: ${requestBody.model}) ${response.status} - ${response.statusText}`);
43
+ if (!response.ok) {
44
+ const error = await response.json();
45
+ throw new Error(`OpenAI Responses API错误: ${error.error?.message || response.statusText}`);
46
+ }
47
+ if (normalizedOptions.stream && response.body && normalizedOptions.onUpdate) {
48
+ return this.handleResponsesStreaming(response, normalizedOptions);
49
+ } else {
50
+ const data = await response.json();
51
+ return this.parseResponsesOutput(data, normalizedOptions);
52
+ }
53
+ } catch (error) {
54
+ const errorMessage = error instanceof Error ? error.message : String(error);
55
+ throw new Error(`OpenAI Responses API补全请求失败: ${errorMessage}`);
56
+ }
57
+ }
58
+ /**
59
+ * 将消息转换为Responses API格式
60
+ * 提取system消息作为instructions,其他消息放入input
61
+ */
62
+ convertMessagesToResponsesFormat(messages) {
63
+ const systemMessages = [];
64
+ const inputMessages = [];
65
+ for (const message of messages) {
66
+ if (message.role === "system") {
67
+ if (typeof message.content === "string") {
68
+ systemMessages.push(message.content);
69
+ } else if (Array.isArray(message.content)) {
70
+ for (const content of message.content) {
71
+ if (content.type === "text") {
72
+ systemMessages.push(content.text);
73
+ }
74
+ }
75
+ } else if (message.content.type === "text") {
76
+ systemMessages.push(message.content.text);
77
+ }
78
+ } else {
79
+ const inputMessage = {
80
+ role: message.role
81
+ };
82
+ if (message.name) {
83
+ inputMessage.name = message.name;
84
+ }
85
+ if (Array.isArray(message.content)) {
86
+ const allText = message.content.every((c) => c.type === "text");
87
+ if (allText) {
88
+ inputMessage.content = message.content.map((c) => c.text).join("");
89
+ } else {
90
+ inputMessage.content = message.content.map((content) => this.convertContentToResponsesAPIFormat(content));
91
+ }
92
+ } else {
93
+ if (typeof message.content === "string") {
94
+ inputMessage.content = message.content;
95
+ } else if (message.content.type === "text") {
96
+ inputMessage.content = message.content.text;
97
+ } else {
98
+ inputMessage.content = [this.convertContentToResponsesAPIFormat(message.content)];
99
+ }
100
+ }
101
+ inputMessages.push(inputMessage);
102
+ }
103
+ }
104
+ const result = {
105
+ input: inputMessages
106
+ };
107
+ if (systemMessages.length > 0) {
108
+ result.instructions = systemMessages.join("\n\n");
109
+ }
110
+ return result;
111
+ }
112
+ /**
113
+ * 将内容对象转换为Responses API格式(用于数组内容)
114
+ * Responses API有不同的内容类型命名
115
+ */
116
+ convertContentToResponsesAPIFormat(content) {
117
+ switch (content.type) {
118
+ case "text":
119
+ return {
120
+ type: "input_text",
121
+ text: content.text
122
+ };
123
+ case "image_url": {
124
+ const imageContent = content;
125
+ return {
126
+ type: "input_image",
127
+ // Responses API uses 'input_image' for user-provided images
128
+ image_url: imageContent.image_url.url
129
+ };
130
+ }
131
+ case "tool_call": {
132
+ const toolCallContent = content;
133
+ return {
134
+ type: "function_call",
135
+ // Responses API uses 'function_call'
136
+ call_id: toolCallContent.tool_call_id,
137
+ name: toolCallContent.function.name,
138
+ arguments: toolCallContent.function.arguments
139
+ };
140
+ }
141
+ case "tool_result": {
142
+ const toolResultContent = content;
143
+ return {
144
+ type: "function_call_output",
145
+ // Responses API uses 'function_call_output'
146
+ call_id: toolResultContent.tool_call_id,
147
+ output: toolResultContent.content
148
+ };
149
+ }
150
+ default:
151
+ throw new Error(`不支持的内容类型: ${content.type}`);
152
+ }
153
+ }
154
+ /**
155
+ * 解析Responses API的输出
156
+ */
157
+ parseResponsesOutput(data, options) {
158
+ let responseContent = "";
159
+ const toolCalls = [];
160
+ if (data.output && data.output.length > 0) {
161
+ const outputItem = data.output[0];
162
+ if (outputItem.content) {
163
+ if (typeof outputItem.content === "string") {
164
+ responseContent = outputItem.content;
165
+ } else if (Array.isArray(outputItem.content)) {
166
+ responseContent = outputItem.content.filter((c) => c.type === "text").map((c) => c.text).join("");
167
+ }
168
+ }
169
+ if (outputItem.tool_calls && outputItem.tool_calls.length > 0) {
170
+ for (const toolCall of outputItem.tool_calls) {
171
+ toolCalls.push({
172
+ id: toolCall.id,
173
+ type: toolCall.type,
174
+ function: {
175
+ name: toolCall.function.name,
176
+ arguments: toolCall.function.arguments
177
+ }
178
+ });
179
+ }
180
+ }
181
+ }
182
+ return {
183
+ content: responseContent,
184
+ model: data.model,
185
+ finishReason: data.output?.[0]?.finish_reason || "stop",
186
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
187
+ responseFormat: options.response_format?.type,
188
+ rawResponse: data
189
+ // 保留原始响应以便调试
190
+ };
191
+ }
192
+ /**
193
+ * 处理Responses API的流式响应
194
+ * 使用SSE格式: event: <type>\ndata: <json>\n\n
195
+ */
196
+ async handleResponsesStreaming(response, options) {
197
+ const reader = response.body.getReader();
198
+ const decoder = new TextDecoder("utf-8");
199
+ let content = "";
200
+ const toolCalls = [];
201
+ let finishReason;
202
+ let model = options.model || "gpt-4o";
203
+ let buffer = "";
204
+ const processStream = async () => {
205
+ const { done, value } = await reader.read();
206
+ if (done) {
207
+ return {
208
+ content,
209
+ model,
210
+ finishReason: finishReason || "stop",
211
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
212
+ responseFormat: options.response_format?.type
213
+ };
214
+ }
215
+ buffer += decoder.decode(value, { stream: true });
216
+ const lines = buffer.split("\n");
217
+ buffer = lines.pop() || "";
218
+ let currentEvent = null;
219
+ for (const line of lines) {
220
+ const trimmedLine = line.trim();
221
+ if (trimmedLine === "") {
222
+ currentEvent = null;
223
+ continue;
224
+ }
225
+ if (trimmedLine.startsWith("event:")) {
226
+ currentEvent = trimmedLine.substring(6).trim();
227
+ } else if (trimmedLine.startsWith("data:")) {
228
+ const dataStr = trimmedLine.substring(5).trim();
229
+ if (dataStr === "[DONE]") {
230
+ continue;
231
+ }
232
+ try {
233
+ const data = JSON.parse(dataStr);
234
+ if (currentEvent === "response.output_text.delta") {
235
+ if (data.delta) {
236
+ content += data.delta;
237
+ if (options.onUpdate) {
238
+ options.onUpdate(content);
239
+ }
240
+ }
241
+ } else if (currentEvent === "response.output_item.done") {
242
+ if (data.item) {
243
+ if (data.item.tool_calls && data.item.tool_calls.length > 0) {
244
+ for (const toolCall of data.item.tool_calls) {
245
+ toolCalls.push({
246
+ id: toolCall.id,
247
+ type: toolCall.type,
248
+ function: {
249
+ name: toolCall.function.name,
250
+ arguments: toolCall.function.arguments
251
+ }
252
+ });
253
+ }
254
+ }
255
+ }
256
+ } else if (currentEvent === "response.completed") {
257
+ if (data.response) {
258
+ model = data.response.model || model;
259
+ finishReason = data.response.output?.[0]?.finish_reason;
260
+ }
261
+ } else if (currentEvent === "response.tool_calls.delta") {
262
+ if (data.delta && data.index !== void 0) {
263
+ let toolCall = toolCalls[data.index];
264
+ if (!toolCall && data.delta.id) {
265
+ toolCall = {
266
+ id: data.delta.id,
267
+ type: "function",
268
+ function: {
269
+ name: "",
270
+ arguments: ""
271
+ }
272
+ };
273
+ toolCalls[data.index] = toolCall;
274
+ }
275
+ if (toolCall && data.delta.function) {
276
+ if (data.delta.function.name) {
277
+ toolCall.function.name = data.delta.function.name;
278
+ }
279
+ if (data.delta.function.arguments) {
280
+ toolCall.function.arguments += data.delta.function.arguments;
281
+ }
282
+ }
283
+ }
284
+ }
285
+ } catch (e) {
286
+ console.warn("Failed to parse SSE data:", dataStr, e);
287
+ }
288
+ }
289
+ }
290
+ return processStream();
291
+ };
292
+ return processStream();
293
+ }
294
+ }
295
+ export {
296
+ OpenAIResponsesClient
297
+ };