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,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>MarkPDFdown</title>
8
+ <script type="module" crossorigin src="./assets/index-DeDe7lry.js"></script>
9
+ <link rel="stylesheet" crossorigin href="./assets/index-CbMlWqbh.css">
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ </body>
14
+ </html>
package/package.json ADDED
@@ -0,0 +1,156 @@
1
+ {
2
+ "name": "markpdfdown",
3
+ "version": "0.1.0",
4
+ "description": "A high-quality PDF to Markdown tool based on large language model visual recognition.",
5
+ "author": "MarkPDFdown",
6
+ "main": "dist/main/index.js",
7
+ "bin": {
8
+ "markpdfdown": "./bin/cli.js"
9
+ },
10
+ "type": "module",
11
+ "engines": {
12
+ "node": ">=18.0.0"
13
+ },
14
+ "homepage": "https://github.com/markpdfdown/markpdfdown-desktop",
15
+ "files": [
16
+ "bin/",
17
+ "dist/",
18
+ "src/core/infrastructure/db/migrations/",
19
+ "src/core/infrastructure/db/schema.prisma"
20
+ ],
21
+ "scripts": {
22
+ "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
23
+ "dev": "npm run generate && electron-vite dev",
24
+ "build": "npm run generate && electron-vite build",
25
+ "start": "npm run generate && electron-vite preview",
26
+ "build:mac": "npm run build && electron-builder --mac --x64 --arm64",
27
+ "build:win": "npm run build && electron-builder --win --x64 --arm64",
28
+ "build:linux": "npm run build && electron-builder --linux --x64 --arm64",
29
+ "migrate:dev": "prisma migrate dev --schema=./src/core/infrastructure/db/schema.prisma",
30
+ "migrate:reset": "prisma migrate reset --schema=./src/core/infrastructure/db/schema.prisma",
31
+ "generate": "prisma generate --schema=./src/core/infrastructure/db/schema.prisma",
32
+ "logo": "electron-icon-builder --input=./src/renderer/assets/logo.png --output=./public",
33
+ "test": "vitest",
34
+ "test:unit": "vitest run --config vitest.config.ts",
35
+ "test:renderer": "vitest run --config vitest.config.renderer.ts",
36
+ "test:watch": "vitest watch",
37
+ "test:coverage": "vitest run --coverage",
38
+ "prepare": "husky"
39
+ },
40
+ "build": {
41
+ "appId": "com.markpdfdown.desktop",
42
+ "productName": "MarkPDFdown",
43
+ "files": [
44
+ "dist/**/*",
45
+ "!**/*.db",
46
+ "!**/*.d.ts",
47
+ "!**/*.min.*.map",
48
+ "!**/{.DS_Store,Thumbs.db}"
49
+ ],
50
+ "extraResources": [
51
+ "node_modules/.prisma/**/*",
52
+ "node_modules/@prisma/client/**/*",
53
+ {
54
+ "from": "src/core/infrastructure/db/migrations",
55
+ "to": "migrations",
56
+ "filter": [
57
+ "**/*.sql"
58
+ ]
59
+ }
60
+ ],
61
+ "asarUnpack": [
62
+ "**/*.{node,dll,metal,exp,lib}"
63
+ ],
64
+ "directories": {
65
+ "buildResources": "assets",
66
+ "output": "release"
67
+ },
68
+ "mac": {
69
+ "category": "public.app-category.productivity",
70
+ "artifactName": "${productName}-${version}-${arch}.${ext}",
71
+ "icon": "public/icons/mac/icon.icns"
72
+ },
73
+ "win": {
74
+ "target": "nsis",
75
+ "artifactName": "${productName}-${version}-${arch}.${ext}",
76
+ "icon": "public/icons/win/icon.ico"
77
+ },
78
+ "nsis": {
79
+ "artifactName": "${productName}-${version}-${arch}.${ext}",
80
+ "shortcutName": "${productName}",
81
+ "uninstallDisplayName": "${productName}",
82
+ "createDesktopShortcut": true,
83
+ "allowToChangeInstallationDirectory": true,
84
+ "oneClick": false
85
+ },
86
+ "linux": {
87
+ "target": "AppImage",
88
+ "artifactName": "${productName}-${version}-${arch}.${ext}",
89
+ "icon": "public/icons/png"
90
+ },
91
+ "electronDownload": {
92
+ "mirror": "https://github.com/electron/electron/releases/download/"
93
+ },
94
+ "asar": true
95
+ },
96
+ "lint-staged": {
97
+ "*.{js,jsx,cjs,mjs,ts,tsx,cts,mts}": [
98
+ "eslint --fix",
99
+ "prettier --write"
100
+ ],
101
+ "*.{json,css,md}": [
102
+ "prettier --write"
103
+ ]
104
+ },
105
+ "dependencies": {
106
+ "@ant-design/icons": "^5.6.1",
107
+ "@prisma/client": "^6.5.0",
108
+ "@types/sharp": "^0.31.1",
109
+ "antd": "^5.24.4",
110
+ "electron-is-dev": "^3.0.1",
111
+ "katex": "^0.16.21",
112
+ "pdf-lib": "^1.17.1",
113
+ "pdf-to-png-converter": "^3.11.0",
114
+ "prismjs": "^1.30.0",
115
+ "react": "^18.2.0",
116
+ "react-dom": "^18.2.0",
117
+ "react-i18next": "^16.5.3",
118
+ "react-markdown": "^10.1.0",
119
+ "react-router-dom": "^7.3.0",
120
+ "rehype-katex": "^7.0.1",
121
+ "rehype-prism-plus": "^2.0.0",
122
+ "remark-gfm": "^4.0.1",
123
+ "remark-math": "^6.0.0",
124
+ "sharp": "^0.34.1",
125
+ "uuid": "^11.1.0"
126
+ },
127
+ "devDependencies": {
128
+ "@eslint/js": "^9.21.0",
129
+ "@testing-library/jest-dom": "^6.1.5",
130
+ "@testing-library/react": "^14.0.0",
131
+ "@testing-library/user-event": "^14.5.1",
132
+ "@types/react": "^18.2.67",
133
+ "@types/react-dom": "^18.2.22",
134
+ "@vitejs/plugin-react": "^4.3.4",
135
+ "@vitest/coverage-v8": "^2.1.8",
136
+ "concurrently": "^9.1.2",
137
+ "electron": "^35.0.2",
138
+ "electron-builder": "^25.1.8",
139
+ "electron-icon-builder": "^2.0.1",
140
+ "electron-vite": "^3.1.0",
141
+ "eslint": "^9.21.0",
142
+ "eslint-plugin-react-hooks": "^5.1.0",
143
+ "eslint-plugin-react-refresh": "^0.4.19",
144
+ "globals": "^15.15.0",
145
+ "husky": "^9.1.7",
146
+ "jsdom": "^25.0.1",
147
+ "nodemon": "^3.1.9",
148
+ "prisma": "^6.5.0",
149
+ "typescript": "~5.7.2",
150
+ "typescript-eslint": "^8.24.1",
151
+ "vite": "^6.2.0",
152
+ "vitest": "^2.1.8",
153
+ "vitest-mock-extended": "^2.0.2",
154
+ "wait-on": "^8.0.3"
155
+ }
156
+ }
@@ -0,0 +1,24 @@
1
+ -- CreateTable
2
+ CREATE TABLE "Provider" (
3
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
4
+ "name" TEXT NOT NULL,
5
+ "type" TEXT NOT NULL,
6
+ "api_key" TEXT,
7
+ "base_url" TEXT,
8
+ "suffix" TEXT,
9
+ "status" INTEGER NOT NULL DEFAULT 0,
10
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
11
+ "updatedAt" DATETIME NOT NULL
12
+ );
13
+
14
+ -- CreateTable
15
+ CREATE TABLE "Model" (
16
+ "id" TEXT NOT NULL,
17
+ "provider" INTEGER NOT NULL,
18
+ "name" TEXT NOT NULL,
19
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
20
+ "updatedAt" DATETIME NOT NULL
21
+ );
22
+
23
+ -- CreateIndex
24
+ CREATE UNIQUE INDEX "Model_id_provider_key" ON "Model"("id", "provider");
@@ -0,0 +1,29 @@
1
+ -- CreateTable
2
+ CREATE TABLE "Task" (
3
+ "id" TEXT NOT NULL,
4
+ "filename" TEXT NOT NULL,
5
+ "type" TEXT NOT NULL,
6
+ "pages" TEXT NOT NULL,
7
+ "provider" INTEGER NOT NULL,
8
+ "model" TEXT NOT NULL,
9
+ "model_name" TEXT NOT NULL,
10
+ "progress" INTEGER NOT NULL DEFAULT 0,
11
+ "status" INTEGER NOT NULL DEFAULT 0,
12
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
13
+ "updatedAt" DATETIME NOT NULL
14
+ );
15
+
16
+ -- CreateTable
17
+ CREATE TABLE "TaskDetail" (
18
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
19
+ "task" TEXT NOT NULL,
20
+ "page" INTEGER NOT NULL,
21
+ "status" INTEGER NOT NULL DEFAULT 0,
22
+ "provider" INTEGER NOT NULL,
23
+ "model" TEXT NOT NULL,
24
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
25
+ "updatedAt" DATETIME NOT NULL
26
+ );
27
+
28
+ -- CreateIndex
29
+ CREATE UNIQUE INDEX "Task_id_key" ON "Task"("id");
@@ -0,0 +1,47 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - You are about to alter the column `pages` on the `Task` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`.
5
+ - Added the required column `page_range` to the `Task` table without a default value. This is not possible if the table is not empty.
6
+ - Added the required column `content` to the `TaskDetail` table without a default value. This is not possible if the table is not empty.
7
+ - Added the required column `page_source` to the `TaskDetail` table without a default value. This is not possible if the table is not empty.
8
+
9
+ */
10
+ -- RedefineTables
11
+ PRAGMA defer_foreign_keys=ON;
12
+ PRAGMA foreign_keys=OFF;
13
+ CREATE TABLE "new_Task" (
14
+ "id" TEXT NOT NULL,
15
+ "filename" TEXT NOT NULL,
16
+ "type" TEXT NOT NULL,
17
+ "page_range" TEXT NOT NULL,
18
+ "pages" INTEGER NOT NULL,
19
+ "provider" INTEGER NOT NULL,
20
+ "model" TEXT NOT NULL,
21
+ "model_name" TEXT NOT NULL,
22
+ "progress" INTEGER NOT NULL DEFAULT 0,
23
+ "status" INTEGER NOT NULL DEFAULT 0,
24
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
25
+ "updatedAt" DATETIME NOT NULL
26
+ );
27
+ INSERT INTO "new_Task" ("createdAt", "filename", "id", "model", "model_name", "pages", "progress", "provider", "status", "type", "updatedAt") SELECT "createdAt", "filename", "id", "model", "model_name", "pages", "progress", "provider", "status", "type", "updatedAt" FROM "Task";
28
+ DROP TABLE "Task";
29
+ ALTER TABLE "new_Task" RENAME TO "Task";
30
+ CREATE UNIQUE INDEX "Task_id_key" ON "Task"("id");
31
+ CREATE TABLE "new_TaskDetail" (
32
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
33
+ "task" TEXT NOT NULL,
34
+ "page" INTEGER NOT NULL,
35
+ "page_source" INTEGER NOT NULL,
36
+ "status" INTEGER NOT NULL DEFAULT 0,
37
+ "provider" INTEGER NOT NULL,
38
+ "model" TEXT NOT NULL,
39
+ "content" TEXT NOT NULL,
40
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
41
+ "updatedAt" DATETIME NOT NULL
42
+ );
43
+ INSERT INTO "new_TaskDetail" ("createdAt", "id", "model", "page", "provider", "status", "task", "updatedAt") SELECT "createdAt", "id", "model", "page", "provider", "status", "task", "updatedAt" FROM "TaskDetail";
44
+ DROP TABLE "TaskDetail";
45
+ ALTER TABLE "new_TaskDetail" RENAME TO "TaskDetail";
46
+ PRAGMA foreign_keys=ON;
47
+ PRAGMA defer_foreign_keys=OFF;
@@ -0,0 +1,50 @@
1
+ -- RedefineTables
2
+ PRAGMA defer_foreign_keys=ON;
3
+ PRAGMA foreign_keys=OFF;
4
+ CREATE TABLE "new_Task" (
5
+ "id" TEXT NOT NULL,
6
+ "filename" TEXT NOT NULL,
7
+ "type" TEXT NOT NULL,
8
+ "page_range" TEXT NOT NULL,
9
+ "pages" INTEGER NOT NULL DEFAULT 0,
10
+ "provider" INTEGER NOT NULL,
11
+ "model" TEXT NOT NULL,
12
+ "model_name" TEXT NOT NULL,
13
+ "progress" INTEGER NOT NULL DEFAULT 0,
14
+ "status" INTEGER NOT NULL DEFAULT 1,
15
+ "completed_count" INTEGER NOT NULL DEFAULT 0,
16
+ "failed_count" INTEGER NOT NULL DEFAULT 0,
17
+ "worker_id" TEXT,
18
+ "merged_path" TEXT,
19
+ "error" TEXT,
20
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
21
+ "updatedAt" DATETIME NOT NULL
22
+ );
23
+ INSERT INTO "new_Task" ("createdAt", "filename", "id", "model", "model_name", "page_range", "pages", "progress", "provider", "status", "type", "updatedAt") SELECT "createdAt", "filename", "id", "model", "model_name", "page_range", "pages", "progress", "provider", "status", "type", "updatedAt" FROM "Task";
24
+ DROP TABLE "Task";
25
+ ALTER TABLE "new_Task" RENAME TO "Task";
26
+ CREATE UNIQUE INDEX "Task_id_key" ON "Task"("id");
27
+ CREATE INDEX "Task_status_idx" ON "Task"("status");
28
+ CREATE INDEX "Task_status_updatedAt_idx" ON "Task"("status", "updatedAt");
29
+ CREATE TABLE "new_TaskDetail" (
30
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
31
+ "task" TEXT NOT NULL,
32
+ "page" INTEGER NOT NULL,
33
+ "page_source" INTEGER NOT NULL,
34
+ "status" INTEGER NOT NULL DEFAULT 0,
35
+ "worker_id" TEXT,
36
+ "provider" INTEGER NOT NULL,
37
+ "model" TEXT NOT NULL,
38
+ "content" TEXT NOT NULL DEFAULT '',
39
+ "error" TEXT,
40
+ "retry_count" INTEGER NOT NULL DEFAULT 0,
41
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
42
+ "updatedAt" DATETIME NOT NULL
43
+ );
44
+ INSERT INTO "new_TaskDetail" ("content", "createdAt", "id", "model", "page", "page_source", "provider", "status", "task", "updatedAt") SELECT "content", "createdAt", "id", "model", "page", "page_source", "provider", "status", "task", "updatedAt" FROM "TaskDetail";
45
+ DROP TABLE "TaskDetail";
46
+ ALTER TABLE "new_TaskDetail" RENAME TO "TaskDetail";
47
+ CREATE INDEX "TaskDetail_task_status_idx" ON "TaskDetail"("task", "status");
48
+ CREATE INDEX "TaskDetail_task_page_idx" ON "TaskDetail"("task", "page");
49
+ PRAGMA foreign_keys=ON;
50
+ PRAGMA defer_foreign_keys=OFF;
@@ -0,0 +1,55 @@
1
+ -- RedefineTables
2
+ PRAGMA defer_foreign_keys=ON;
3
+ PRAGMA foreign_keys=OFF;
4
+ CREATE TABLE "new_Task" (
5
+ "id" TEXT NOT NULL,
6
+ "filename" TEXT NOT NULL,
7
+ "type" TEXT NOT NULL,
8
+ "page_range" TEXT NOT NULL,
9
+ "pages" INTEGER NOT NULL DEFAULT 0,
10
+ "provider" INTEGER NOT NULL,
11
+ "model" TEXT NOT NULL,
12
+ "model_name" TEXT NOT NULL,
13
+ "progress" INTEGER NOT NULL DEFAULT 0,
14
+ "status" INTEGER NOT NULL DEFAULT -1,
15
+ "completed_count" INTEGER NOT NULL DEFAULT 0,
16
+ "failed_count" INTEGER NOT NULL DEFAULT 0,
17
+ "worker_id" TEXT,
18
+ "merged_path" TEXT,
19
+ "error" TEXT,
20
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
21
+ "updatedAt" DATETIME NOT NULL
22
+ );
23
+ INSERT INTO "new_Task" ("completed_count", "createdAt", "error", "failed_count", "filename", "id", "merged_path", "model", "model_name", "page_range", "pages", "progress", "provider", "status", "type", "updatedAt", "worker_id") SELECT "completed_count", "createdAt", "error", "failed_count", "filename", "id", "merged_path", "model", "model_name", "page_range", "pages", "progress", "provider", "status", "type", "updatedAt", "worker_id" FROM "Task";
24
+ DROP TABLE "Task";
25
+ ALTER TABLE "new_Task" RENAME TO "Task";
26
+ CREATE UNIQUE INDEX "Task_id_key" ON "Task"("id");
27
+ CREATE INDEX "Task_status_idx" ON "Task"("status");
28
+ CREATE INDEX "Task_status_updatedAt_idx" ON "Task"("status", "updatedAt");
29
+ CREATE TABLE "new_TaskDetail" (
30
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
31
+ "task" TEXT NOT NULL,
32
+ "page" INTEGER NOT NULL,
33
+ "page_source" INTEGER NOT NULL,
34
+ "status" INTEGER NOT NULL DEFAULT 0,
35
+ "worker_id" TEXT,
36
+ "provider" INTEGER NOT NULL,
37
+ "model" TEXT NOT NULL,
38
+ "content" TEXT NOT NULL DEFAULT '',
39
+ "error" TEXT,
40
+ "retry_count" INTEGER NOT NULL DEFAULT 0,
41
+ "input_tokens" INTEGER NOT NULL DEFAULT 0,
42
+ "output_tokens" INTEGER NOT NULL DEFAULT 0,
43
+ "conversion_time" INTEGER NOT NULL DEFAULT 0,
44
+ "started_at" DATETIME,
45
+ "completed_at" DATETIME,
46
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
47
+ "updatedAt" DATETIME NOT NULL
48
+ );
49
+ INSERT INTO "new_TaskDetail" ("content", "createdAt", "error", "id", "model", "page", "page_source", "provider", "retry_count", "status", "task", "updatedAt", "worker_id") SELECT "content", "createdAt", "error", "id", "model", "page", "page_source", "provider", "retry_count", "status", "task", "updatedAt", "worker_id" FROM "TaskDetail";
50
+ DROP TABLE "TaskDetail";
51
+ ALTER TABLE "new_TaskDetail" RENAME TO "TaskDetail";
52
+ CREATE INDEX "TaskDetail_task_status_idx" ON "TaskDetail"("task", "status");
53
+ CREATE INDEX "TaskDetail_task_page_idx" ON "TaskDetail"("task", "page");
54
+ PRAGMA foreign_keys=ON;
55
+ PRAGMA defer_foreign_keys=OFF;
@@ -0,0 +1,3 @@
1
+ # Please do not edit this file manually
2
+ # It should be added in your version-control system (e.g., Git)
3
+ provider = "sqlite"
@@ -0,0 +1,104 @@
1
+ // This is your Prisma schema file,
2
+ // learn more about it in the docs: https://pris.ly/d/prisma-schema
3
+
4
+ // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
5
+ // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
6
+
7
+ generator client {
8
+ provider = "prisma-client-js"
9
+ }
10
+
11
+ datasource db {
12
+ provider = "sqlite"
13
+ url = env("DATABASE_URL")
14
+ }
15
+
16
+ model Provider {
17
+ id Int @id @default(autoincrement())
18
+ name String
19
+ type String
20
+ api_key String?
21
+ base_url String?
22
+ suffix String?
23
+ status Int @default(0)
24
+ createdAt DateTime @default(now())
25
+ updatedAt DateTime @updatedAt
26
+ }
27
+
28
+ model Model {
29
+ id String
30
+ provider Int
31
+ name String
32
+ createdAt DateTime @default(now())
33
+ updatedAt DateTime @updatedAt
34
+
35
+ @@unique([id, provider])
36
+ }
37
+
38
+ model Task {
39
+ id String @unique
40
+ filename String
41
+ type String
42
+ page_range String
43
+ pages Int @default(0)
44
+ provider Int
45
+ model String
46
+ model_name String
47
+
48
+ // 进度和状态
49
+ progress Int @default(0) // 0-100
50
+ status Int @default(-1) // TaskStatus (CREATED)
51
+ completed_count Int @default(0) // 已完成页面数
52
+ failed_count Int @default(0) // 失败页面数
53
+
54
+ // Worker 追踪
55
+ worker_id String? // 当前处理的 worker ID
56
+
57
+ // 结果和错误
58
+ merged_path String? // 合并后的文件路径
59
+ error String? // 错误信息
60
+
61
+ createdAt DateTime @default(now())
62
+ updatedAt DateTime @updatedAt
63
+
64
+ @@index([status])
65
+ @@index([status, updatedAt])
66
+ }
67
+
68
+ model TaskDetail {
69
+ id Int @id @default(autoincrement())
70
+ task String // 关联 Task.id
71
+ page Int // 当前页码 (1-based)
72
+ page_source Int // 原始 PDF 页码
73
+
74
+ // 状态和处理
75
+ status Int @default(0) // PageStatus
76
+ worker_id String? // 当前处理的 worker ID
77
+
78
+ // LLM 配置
79
+ provider Int
80
+ model String
81
+
82
+ // 结果和错误
83
+ content String @default("") // 转换后的 Markdown
84
+ error String? // 错误信息
85
+ retry_count Int @default(0) // 重试次数
86
+
87
+ // 成本追踪
88
+ input_tokens Int @default(0)
89
+ output_tokens Int @default(0)
90
+
91
+ // 性能指标
92
+ conversion_time Int @default(0)
93
+ started_at DateTime?
94
+ completed_at DateTime?
95
+
96
+ // 注意:不存储 image_path,图片路径通过 ImagePathUtil.getPath(task, page) 动态计算
97
+ // 格式:{tempDir}/{taskId}/page-{page}.png
98
+
99
+ createdAt DateTime @default(now())
100
+ updatedAt DateTime @updatedAt
101
+
102
+ @@index([task, status])
103
+ @@index([task, page])
104
+ }