@covro/covro 0.2.1-dev.6 → 0.2.1-dev.8

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 (129) hide show
  1. package/README.md +8 -1
  2. package/README.zh-CN.md +8 -1
  3. package/dist/backups/factory.js +22 -0
  4. package/dist/backups/factory.js.map +7 -0
  5. package/dist/backups/lock.js +22 -0
  6. package/dist/backups/lock.js.map +7 -0
  7. package/dist/backups/manager.js +170 -0
  8. package/dist/backups/manager.js.map +7 -0
  9. package/dist/backups/restore.js +188 -0
  10. package/dist/backups/restore.js.map +7 -0
  11. package/dist/backups/store.js +274 -0
  12. package/dist/backups/store.js.map +7 -0
  13. package/dist/cli/backup.js +84 -0
  14. package/dist/cli/backup.js.map +7 -0
  15. package/dist/cli/daemon.js +7 -0
  16. package/dist/cli/daemon.js.map +2 -2
  17. package/dist/cli/main.js +35 -5
  18. package/dist/cli/main.js.map +2 -2
  19. package/dist/cli/paths.js.map +2 -2
  20. package/dist/server/db/history.js +60 -0
  21. package/dist/server/db/history.js.map +7 -0
  22. package/dist/server/db/index.js +11 -1
  23. package/dist/server/db/index.js.map +2 -2
  24. package/dist/server/db/migrate.js +8 -18
  25. package/dist/server/db/migrate.js.map +2 -2
  26. package/dist/server/http.js +21 -3
  27. package/dist/server/http.js.map +2 -2
  28. package/dist/server/main.js +14 -3
  29. package/dist/server/main.js.map +2 -2
  30. package/dist/server/service.js +9 -5
  31. package/dist/server/service.js.map +2 -2
  32. package/dist/shared/backups.js +55 -0
  33. package/dist/shared/backups.js.map +7 -0
  34. package/dist/shared/database.js +15 -0
  35. package/dist/shared/database.js.map +7 -0
  36. package/dist/update-worker.cjs +934 -388
  37. package/dist/updates/files.js +2 -1
  38. package/dist/updates/files.js.map +2 -2
  39. package/dist/updates/transaction.js +3 -24
  40. package/dist/updates/transaction.js.map +2 -2
  41. package/dist/updates/worker.js +69 -19
  42. package/dist/updates/worker.js.map +2 -2
  43. package/dist/web/assets/{abnfDiagram-WEYOIA3C-BkC1EVBk.js → abnfDiagram-WEYOIA3C-B8zG_C_F.js} +1 -1
  44. package/dist/web/assets/{arc-CYGT9huc.js → arc-BXL9OpmU.js} +1 -1
  45. package/dist/web/assets/{architecture-WOLXFQ4H-DCsF3gVg.js → architecture-WOLXFQ4H-BTKK_aYo.js} +1 -1
  46. package/dist/web/assets/{architectureDiagram-ZHVYKT53-Cn6kovuz.js → architectureDiagram-ZHVYKT53-DBCaGxvE.js} +1 -1
  47. package/dist/web/assets/{blockDiagram-RJAE7QA3-CNk2zXm9.js → blockDiagram-RJAE7QA3-5nSpgG2R.js} +1 -1
  48. package/dist/web/assets/{c4Diagram-XDPPPE54-CTuI_1XJ.js → c4Diagram-XDPPPE54-ZFSa_lAc.js} +1 -1
  49. package/dist/web/assets/channel-C_xSZVUz.js +1 -0
  50. package/dist/web/assets/{chunk-2E7WHVMD-TrYs0qV3.js → chunk-2E7WHVMD-m7Z4-p6b.js} +1 -1
  51. package/dist/web/assets/{chunk-4EMNKR2T-QL4-PZ4r.js → chunk-4EMNKR2T-Dd3Du5Wp.js} +1 -1
  52. package/dist/web/assets/{chunk-55XCU76K-yynn-EEr.js → chunk-55XCU76K-B4Cym3GJ.js} +1 -1
  53. package/dist/web/assets/{chunk-7S6XSTFO-dzrEn-_W.js → chunk-7S6XSTFO-CDr8VPut.js} +1 -1
  54. package/dist/web/assets/{chunk-AQDTSKZB-DaNZMEGO.js → chunk-AQDTSKZB-DN_lahgB.js} +1 -1
  55. package/dist/web/assets/{chunk-DSNLSHJZ-BnMtx8Ho.js → chunk-DSNLSHJZ-DtN5l5Ar.js} +1 -1
  56. package/dist/web/assets/{chunk-HAGFOTED-fg-JyiA5.js → chunk-HAGFOTED-aPHy1aHo.js} +1 -1
  57. package/dist/web/assets/{chunk-HNE4Q36P-CCsfPbcn.js → chunk-HNE4Q36P-LHoOBckL.js} +1 -1
  58. package/dist/web/assets/{chunk-NQOKRVIF-DLlOpcWZ.js → chunk-NQOKRVIF-CgVqPObB.js} +1 -1
  59. package/dist/web/assets/{chunk-UHW7PFBP-B-sPKpeS.js → chunk-UHW7PFBP-D7IOS7fZ.js} +1 -1
  60. package/dist/web/assets/{chunk-VQ5W62QI-BVqGMzey.js → chunk-VQ5W62QI-L-rpgVHW.js} +1 -1
  61. package/dist/web/assets/{chunk-WQQL4CDK-DcwJXNuh.js → chunk-WQQL4CDK-BwxlS7IY.js} +1 -1
  62. package/dist/web/assets/{chunk-XXDRQBXY-DRwLkqyU.js → chunk-XXDRQBXY-DeafdT4i.js} +1 -1
  63. package/dist/web/assets/{chunk-YZO67HFG-BrrgBnrQ.js → chunk-YZO67HFG-DXfUlNkI.js} +1 -1
  64. package/dist/web/assets/{chunk-ZAUX2LTX-C7qvwkRr.js → chunk-ZAUX2LTX-Do69fykC.js} +1 -1
  65. package/dist/web/assets/{chunk-ZCHMQSOR-DdBd3Cvs.js → chunk-ZCHMQSOR-CjoJalzt.js} +1 -1
  66. package/dist/web/assets/{classDiagram-v2-4MYWR3UA-Dn2RZb3v.js → classDiagram-v2-4MYWR3UA-CigIdZ7U.js} +1 -1
  67. package/dist/web/assets/{cose-bilkent-JH36ORCC-BlXvtfgE.js → cose-bilkent-JH36ORCC-CS7jqO5R.js} +1 -1
  68. package/dist/web/assets/{cynefin-EF2NZ3EQ-odDgTxc-.js → cynefin-EF2NZ3EQ-DclsepTa.js} +1 -1
  69. package/dist/web/assets/{cynefinDiagram-WF24UDRP-BySEoCW8.js → cynefinDiagram-WF24UDRP-BwggxvVt.js} +1 -1
  70. package/dist/web/assets/{dagre-NK4GIZVX-ihxmhB4X.js → dagre-NK4GIZVX-CDegqij1.js} +1 -1
  71. package/dist/web/assets/{diagram-CBK3MWTC-Ckr5P3IM.js → diagram-CBK3MWTC-CtYiu41o.js} +1 -1
  72. package/dist/web/assets/{diagram-I5XIIV2D-D5BZIval.js → diagram-I5XIIV2D-B_EdvEQ0.js} +1 -1
  73. package/dist/web/assets/{diagram-ODIL2UCW-BC5jjqqY.js → diagram-ODIL2UCW-DIAhaYWV.js} +1 -1
  74. package/dist/web/assets/{diagram-PFBEJUXE-D_IdYKqC.js → diagram-PFBEJUXE-h-2MVJLS.js} +1 -1
  75. package/dist/web/assets/{diagram-RJA3I4VV-DlPNsPqP.js → diagram-RJA3I4VV-L6CtV-wX.js} +1 -1
  76. package/dist/web/assets/{diagram-TYUNFSNR-Ca2ANhGM.js → diagram-TYUNFSNR-CRK7uDlw.js} +1 -1
  77. package/dist/web/assets/{dist-BSWkYZRr.js → dist-BJ7e_WRa.js} +1 -1
  78. package/dist/web/assets/{ebnfDiagram-V4P3TTPT-BrqvmeiB.js → ebnfDiagram-V4P3TTPT-DiMUSVcw.js} +1 -1
  79. package/dist/web/assets/{elk-QONTBCTQ-BfXeOE2E.js → elk-QONTBCTQ-zMe0e0lf.js} +1 -1
  80. package/dist/web/assets/{erDiagram-KYQIGQAA-CMuYoCVJ.js → erDiagram-KYQIGQAA-BurDHKVW.js} +1 -1
  81. package/dist/web/assets/{eventmodeling-K75KTNOO-9s4vQqv1.js → eventmodeling-K75KTNOO-CCdDU1Vn.js} +1 -1
  82. package/dist/web/assets/flowDiagram-IUGLLWBU-kvOthkRX.js +1 -0
  83. package/dist/web/assets/{ganttDiagram-R7GPNTJY-B-Xmfmm2.js → ganttDiagram-R7GPNTJY-B3p12HzE.js} +1 -1
  84. package/dist/web/assets/{gitGraph-VSP46ZUC-ZSbSQ7jf.js → gitGraph-VSP46ZUC-DwfEEe29.js} +1 -1
  85. package/dist/web/assets/{gitGraphDiagram-PDYL7XHY-BhxijLaZ.js → gitGraphDiagram-PDYL7XHY-C-4TICdU.js} +1 -1
  86. package/dist/web/assets/{index-mkDvqMQ3.css → index-COSho7m2.css} +1 -1
  87. package/dist/web/assets/index-_PgEAg27.js +147 -0
  88. package/dist/web/assets/{info-OHQRW6UA-CTSCkjt3.js → info-OHQRW6UA-9VU-Tuww.js} +1 -1
  89. package/dist/web/assets/{infoDiagram-MVDRKAX5-D46MTesD.js → infoDiagram-MVDRKAX5-Dl9CbN5F.js} +1 -1
  90. package/dist/web/assets/{ishikawaDiagram-HPEHV2GE-Bafu9NOk.js → ishikawaDiagram-HPEHV2GE-SDN10Ajd.js} +1 -1
  91. package/dist/web/assets/{journeyDiagram-BOSHW7O7-CRsIi1Ry.js → journeyDiagram-BOSHW7O7-BLB0N0xW.js} +1 -1
  92. package/dist/web/assets/{kanban-definition-FNSA4HC5-DjIT_uLs.js → kanban-definition-FNSA4HC5-DXwfxq7I.js} +1 -1
  93. package/dist/web/assets/{line-B5MDdgVs.js → line-46gZz5LW.js} +1 -1
  94. package/dist/web/assets/{linear-wm7JWxlT.js → linear-BAxP-UN2.js} +1 -1
  95. package/dist/web/assets/{mermaid-parser.core-C7jTW4sZ.js → mermaid-parser.core-do5rGU42.js} +3 -3
  96. package/dist/web/assets/{mermaid.core-DcWRGjP5.js → mermaid.core-DH3b37vl.js} +4 -4
  97. package/dist/web/assets/{mindmap-definition-6OY57UG3-qY6vV0UI.js → mindmap-definition-6OY57UG3-DMxeUKAv.js} +1 -1
  98. package/dist/web/assets/{packet-JDAUHWVQ-9B7vLYK0.js → packet-JDAUHWVQ-D3a0MMF_.js} +1 -1
  99. package/dist/web/assets/{pegDiagram-ECIUJNBX-B7gLZ_Fs.js → pegDiagram-ECIUJNBX-DTwfTBgO.js} +1 -1
  100. package/dist/web/assets/{pie-XZMESJXO-MfazZSiE.js → pie-XZMESJXO-e46xxIb_.js} +1 -1
  101. package/dist/web/assets/{pieDiagram-GNMPY74T-1ahagzzC.js → pieDiagram-GNMPY74T-PVAAsxhT.js} +1 -1
  102. package/dist/web/assets/{quadrantDiagram-D57K4MC3-C-GkwjOp.js → quadrantDiagram-D57K4MC3-B9amPs7h.js} +1 -1
  103. package/dist/web/assets/{radar-ABXABTNO-CgutvWTi.js → radar-ABXABTNO-D6ZOHa6D.js} +1 -1
  104. package/dist/web/assets/{railroad-I3PHUGI6-Bl9LJINm.js → railroad-I3PHUGI6-BKBsMC0B.js} +1 -1
  105. package/dist/web/assets/{railroad-abnf-LNEFI6M7-CGRpAnuU.js → railroad-abnf-LNEFI6M7-BxJ-MDoO.js} +1 -1
  106. package/dist/web/assets/{railroad-ebnf-DWYD2UWJ-D6A47xZS.js → railroad-ebnf-DWYD2UWJ-aG0mC8vs.js} +1 -1
  107. package/dist/web/assets/{railroad-peg-JR7BVNR7-DxGphrFO.js → railroad-peg-JR7BVNR7-DGhAES9a.js} +1 -1
  108. package/dist/web/assets/{railroadDiagram-Y72NRBL7-D8P17OV4.js → railroadDiagram-Y72NRBL7-8Bj0VxcB.js} +1 -1
  109. package/dist/web/assets/{requirementDiagram-EQYSW5RA-c93_xAaQ.js → requirementDiagram-EQYSW5RA-CiTdnYqt.js} +1 -1
  110. package/dist/web/assets/{sankeyDiagram-SY24JHO5-FankqwcZ.js → sankeyDiagram-SY24JHO5-JOgC0a7X.js} +1 -1
  111. package/dist/web/assets/{sequenceDiagram-BLEHNHQU-CWH5SeL1.js → sequenceDiagram-BLEHNHQU-BH4lajeV.js} +1 -1
  112. package/dist/web/assets/{src-BXQOmVZv.js → src-BWVVEoim.js} +1 -1
  113. package/dist/web/assets/{stateDiagram-v2-A6IESKWZ-DLfcw0e7.js → stateDiagram-v2-A6IESKWZ-BbiuK5Zz.js} +1 -1
  114. package/dist/web/assets/{swimlanes-B3ENRKFQ-DZ-yBiap.js → swimlanes-B3ENRKFQ-Dscu-_Yz.js} +1 -1
  115. package/dist/web/assets/swimlanesDiagram-AYQRV4AK-DSGMlqJQ.js +8 -0
  116. package/dist/web/assets/{timeline-definition-JXYKGLGB-B7XvxDHY.js → timeline-definition-JXYKGLGB-Br42w2T8.js} +1 -1
  117. package/dist/web/assets/{treeView-D4JQ5SDB-DrB6wXJ0.js → treeView-D4JQ5SDB-DSb5v9pO.js} +1 -1
  118. package/dist/web/assets/{treemap-SAJKECNS-BynFjsvx.js → treemap-SAJKECNS-C7iN5GFB.js} +1 -1
  119. package/dist/web/assets/{usecaseDiagram-WPOLBNNX-BISzHOHN.js → usecaseDiagram-WPOLBNNX-CTSO8vjh.js} +1 -1
  120. package/dist/web/assets/{vennDiagram-Q3Y3IDCW-BZwjTIST.js → vennDiagram-Q3Y3IDCW-BMAynpAa.js} +1 -1
  121. package/dist/web/assets/{wardley-7MLQ67FV-2bM0pMhO.js → wardley-7MLQ67FV-C0mrVGIB.js} +1 -1
  122. package/dist/web/assets/{wardleyDiagram-IVAIDKWA-CflkU8us.js → wardleyDiagram-IVAIDKWA-Cn5Ctwjf.js} +1 -1
  123. package/dist/web/assets/{xychartDiagram-4URNHDU4-DRspOlD3.js → xychartDiagram-4URNHDU4-7HTAaZFv.js} +1 -1
  124. package/dist/web/index.html +2 -2
  125. package/package.json +8 -3
  126. package/dist/web/assets/channel-BDxsxdm-.js +0 -1
  127. package/dist/web/assets/flowDiagram-IUGLLWBU-BHwP7Ha7.js +0 -1
  128. package/dist/web/assets/index-BrvtlTwN.js +0 -147
  129. package/dist/web/assets/swimlanesDiagram-AYQRV4AK-BlmdUBbW.js +0 -8
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cli/paths.ts"],
4
- "sourcesContent": ["import { createHash, randomUUID } from 'node:crypto';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { readFileSync } from 'node:fs';\nimport { chmod, mkdir, readFile, rename, writeFile } from 'node:fs/promises';\n\nexport const packageRoot = fileURLToPath(new URL('../../', import.meta.url));\nexport const packageInfo = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8')) as {\n name: string;\n version: string;\n engines: { node: string };\n covroCodex?: unknown;\n covroCommit?: string;\n covroChannel?: 'stable' | 'beta' | 'dev';\n};\nexport function paths(configPath?: string) {\n const home = resolve(process.env.COVRO_HOME ?? join(homedir(), '.covro'));\n const config = resolve(configPath ?? join(home, 'config.json'));\n const key = createHash('sha256').update(config).digest('hex').slice(0, 16);\n const state = join(home, 'instances', key);\n const socket =\n process.platform === 'win32' ? `\\\\\\\\.\\\\pipe\\\\covro-${key}` : join(home, `c-${key}.sock`);\n return { home, config, key, state, socket, log: join(state, 'covro.log') };\n}\nexport type CovroPaths = ReturnType<typeof paths>;\nexport async function writeJson(filename: string, value: unknown) {\n await mkdir(dirname(filename), { recursive: true, mode: 0o700 });\n const temporary = `${filename}.${randomUUID()}.tmp`;\n await writeFile(temporary, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n await rename(temporary, filename);\n}\nexport async function ensureConfig(location: CovroPaths) {\n await mkdir(location.home, { recursive: true, mode: 0o700 });\n await chmod(location.home, 0o700);\n await mkdir(dirname(location.config), { recursive: true, mode: 0o700 });\n try {\n await readFile(location.config);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n await writeFile(\n location.config,\n `${JSON.stringify(\n {\n host: '127.0.0.1',\n port: 8787,\n publicOrigin: ['http://127.0.0.1:8787', 'http://localhost:8787'],\n dataDir: './data',\n codex: { binary: process.env.COVRO_CODEX_BINARY ?? 'codex' },\n projects: [],\n },\n null,\n 2,\n )}\\n`,\n { flag: 'wx', mode: 0o600 },\n ).catch((failure: NodeJS.ErrnoException) => {\n if (failure.code !== 'EEXIST') throw failure;\n });\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,YAAY,kBAAkB;AACvC,SAAS,eAAe;AACxB,SAAS,SAAS,MAAM,eAAe;AACvC,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,OAAO,OAAO,UAAU,QAAQ,iBAAiB;AAEnD,MAAM,cAAc,cAAc,IAAI,IAAI,UAAU,YAAY,GAAG,CAAC;AACpE,MAAM,cAAc,KAAK,MAAM,aAAa,KAAK,aAAa,cAAc,GAAG,MAAM,CAAC;AAQtF,SAAS,MAAM,YAAqB;AACzC,QAAM,OAAO,QAAQ,QAAQ,IAAI,cAAc,KAAK,QAAQ,GAAG,QAAQ,CAAC;AACxE,QAAM,SAAS,QAAQ,cAAc,KAAK,MAAM,aAAa,CAAC;AAC9D,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AACzE,QAAM,QAAQ,KAAK,MAAM,aAAa,GAAG;AACzC,QAAM,SACJ,QAAQ,aAAa,UAAU,sBAAsB,GAAG,KAAK,KAAK,MAAM,KAAK,GAAG,OAAO;AACzF,SAAO,EAAE,MAAM,QAAQ,KAAK,OAAO,QAAQ,KAAK,KAAK,OAAO,WAAW,EAAE;AAC3E;AAEA,eAAsB,UAAU,UAAkB,OAAgB;AAChE,QAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC/D,QAAM,YAAY,GAAG,QAAQ,IAAI,WAAW,CAAC;AAC7C,QAAM,UAAU,WAAW,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AACjF,QAAM,OAAO,WAAW,QAAQ;AAClC;AACA,eAAsB,aAAa,UAAsB;AACvD,QAAM,MAAM,SAAS,MAAM,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC3D,QAAM,MAAM,SAAS,MAAM,GAAK;AAChC,QAAM,MAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACtE,MAAI;AACF,UAAM,SAAS,SAAS,MAAM;AAAA,EAChC,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU,OAAM;AAC9D,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,GAAG,KAAK;AAAA,QACN;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,cAAc,CAAC,yBAAyB,uBAAuB;AAAA,UAC/D,SAAS;AAAA,UACT,OAAO,EAAE,QAAQ,QAAQ,IAAI,sBAAsB,QAAQ;AAAA,UAC3D,UAAU,CAAC;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA;AAAA,MACD,EAAE,MAAM,MAAM,MAAM,IAAM;AAAA,IAC5B,EAAE,MAAM,CAAC,YAAmC;AAC1C,UAAI,QAAQ,SAAS,SAAU,OAAM;AAAA,IACvC,CAAC;AAAA,EACH;AACF;",
4
+ "sourcesContent": ["import { createHash, randomUUID } from 'node:crypto';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { readFileSync } from 'node:fs';\nimport { chmod, mkdir, readFile, rename, writeFile } from 'node:fs/promises';\n\nexport const packageRoot = fileURLToPath(new URL('../../', import.meta.url));\nexport const packageInfo = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8')) as {\n name: string;\n version: string;\n engines: { node: string };\n covroCodex?: unknown;\n covroDatabase?: unknown;\n covroCommit?: string;\n covroChannel?: 'stable' | 'beta' | 'dev';\n};\nexport function paths(configPath?: string) {\n const home = resolve(process.env.COVRO_HOME ?? join(homedir(), '.covro'));\n const config = resolve(configPath ?? join(home, 'config.json'));\n const key = createHash('sha256').update(config).digest('hex').slice(0, 16);\n const state = join(home, 'instances', key);\n const socket =\n process.platform === 'win32' ? `\\\\\\\\.\\\\pipe\\\\covro-${key}` : join(home, `c-${key}.sock`);\n return { home, config, key, state, socket, log: join(state, 'covro.log') };\n}\nexport type CovroPaths = ReturnType<typeof paths>;\nexport async function writeJson(filename: string, value: unknown) {\n await mkdir(dirname(filename), { recursive: true, mode: 0o700 });\n const temporary = `${filename}.${randomUUID()}.tmp`;\n await writeFile(temporary, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n await rename(temporary, filename);\n}\nexport async function ensureConfig(location: CovroPaths) {\n await mkdir(location.home, { recursive: true, mode: 0o700 });\n await chmod(location.home, 0o700);\n await mkdir(dirname(location.config), { recursive: true, mode: 0o700 });\n try {\n await readFile(location.config);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n await writeFile(\n location.config,\n `${JSON.stringify(\n {\n host: '127.0.0.1',\n port: 8787,\n publicOrigin: ['http://127.0.0.1:8787', 'http://localhost:8787'],\n dataDir: './data',\n codex: { binary: process.env.COVRO_CODEX_BINARY ?? 'codex' },\n projects: [],\n },\n null,\n 2,\n )}\\n`,\n { flag: 'wx', mode: 0o600 },\n ).catch((failure: NodeJS.ErrnoException) => {\n if (failure.code !== 'EEXIST') throw failure;\n });\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,YAAY,kBAAkB;AACvC,SAAS,eAAe;AACxB,SAAS,SAAS,MAAM,eAAe;AACvC,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,OAAO,OAAO,UAAU,QAAQ,iBAAiB;AAEnD,MAAM,cAAc,cAAc,IAAI,IAAI,UAAU,YAAY,GAAG,CAAC;AACpE,MAAM,cAAc,KAAK,MAAM,aAAa,KAAK,aAAa,cAAc,GAAG,MAAM,CAAC;AAStF,SAAS,MAAM,YAAqB;AACzC,QAAM,OAAO,QAAQ,QAAQ,IAAI,cAAc,KAAK,QAAQ,GAAG,QAAQ,CAAC;AACxE,QAAM,SAAS,QAAQ,cAAc,KAAK,MAAM,aAAa,CAAC;AAC9D,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AACzE,QAAM,QAAQ,KAAK,MAAM,aAAa,GAAG;AACzC,QAAM,SACJ,QAAQ,aAAa,UAAU,sBAAsB,GAAG,KAAK,KAAK,MAAM,KAAK,GAAG,OAAO;AACzF,SAAO,EAAE,MAAM,QAAQ,KAAK,OAAO,QAAQ,KAAK,KAAK,OAAO,WAAW,EAAE;AAC3E;AAEA,eAAsB,UAAU,UAAkB,OAAgB;AAChE,QAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC/D,QAAM,YAAY,GAAG,QAAQ,IAAI,WAAW,CAAC;AAC7C,QAAM,UAAU,WAAW,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AACjF,QAAM,OAAO,WAAW,QAAQ;AAClC;AACA,eAAsB,aAAa,UAAsB;AACvD,QAAM,MAAM,SAAS,MAAM,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC3D,QAAM,MAAM,SAAS,MAAM,GAAK;AAChC,QAAM,MAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACtE,MAAI;AACF,UAAM,SAAS,SAAS,MAAM;AAAA,EAChC,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU,OAAM;AAC9D,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,GAAG,KAAK;AAAA,QACN;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,cAAc,CAAC,yBAAyB,uBAAuB;AAAA,UAC/D,SAAS;AAAA,UACT,OAAO,EAAE,QAAQ,QAAQ,IAAI,sBAAsB,QAAQ;AAAA,UAC3D,UAAU,CAAC;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA;AAAA,MACD,EAAE,MAAM,MAAM,MAAM,IAAM;AAAA,IAC5B,EAAE,MAAM,CAAC,YAAmC;AAC1C,UAAI,QAAQ,SAAS,SAAU,OAAM;AAAA,IACvC,CAAC;AAAA,EACH;AACF;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,60 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ function readMigrations(folder) {
5
+ const journal = JSON.parse(readFileSync(join(folder, "meta/_journal.json"), "utf8"));
6
+ let last = 0;
7
+ return journal.entries.map((entry, index) => {
8
+ if (!/^[a-zA-Z0-9_-]+$/.test(entry.tag) || entry.idx !== index || entry.when <= last)
9
+ throw new Error("Invalid database migration journal");
10
+ last = entry.when;
11
+ const source = readFileSync(join(folder, `${entry.tag}.sql`), "utf8");
12
+ return {
13
+ hash: createHash("sha256").update(source).digest("hex"),
14
+ createdAt: entry.when,
15
+ sql: source.split("--> statement-breakpoint")
16
+ };
17
+ });
18
+ }
19
+ function inspectDatabase(sqlite, migrations) {
20
+ const recorded = sqlite.pragma("user_version", { simple: true });
21
+ const tables = sqlite.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'").all();
22
+ const applied = tables.some((table) => table.name === "__drizzle_migrations") ? sqlite.prepare("SELECT hash, created_at FROM __drizzle_migrations ORDER BY created_at").all() : [];
23
+ if (!applied.length && tables.some((table) => table.name !== "__drizzle_migrations") || applied.some(
24
+ (entry, index) => entry.hash !== migrations[index]?.hash || entry.created_at !== migrations[index]?.createdAt
25
+ ) || recorded !== 0 && recorded !== applied.length)
26
+ throw new Error(
27
+ "\u6570\u636E\u5E93 Schema \u6216\u8FC1\u79FB\u5386\u53F2\u4E0D\u517C\u5BB9\uFF1B\u8BF7\u4F7F\u7528\u517C\u5BB9\u7248\u672C\u6216\u6062\u590D\u5347\u7EA7\u524D\u5907\u4EFD\uFF0C\u4E0D\u4F1A\u6539\u5199\u6216\u91CD\u5EFA\u6570\u636E\u5E93\u3002"
28
+ );
29
+ return {
30
+ schemaVersion: applied.length,
31
+ legacy: recorded === 0,
32
+ migrationHashes: applied.map((entry) => entry.hash)
33
+ };
34
+ }
35
+ function requireRestorable(version, contract) {
36
+ if (version < contract.minRestorableSchemaVersion || version > contract.schemaVersion)
37
+ throw new Error(
38
+ `\u5907\u4EFD Schema ${version} \u4E0D\u517C\u5BB9\u76EE\u6807\u7248\u672C\uFF08\u652F\u6301 ${contract.minRestorableSchemaVersion}\u2013${contract.schemaVersion}\uFF09\u3002`
39
+ );
40
+ }
41
+ function migrateSqlite(sqlite, migrations) {
42
+ const before = inspectDatabase(sqlite, migrations);
43
+ sqlite.transaction(() => {
44
+ sqlite.exec(
45
+ "CREATE TABLE IF NOT EXISTS __drizzle_migrations (id SERIAL PRIMARY KEY, hash text NOT NULL, created_at numeric)"
46
+ );
47
+ for (const migration of migrations.slice(before.schemaVersion)) {
48
+ for (const statement of migration.sql) sqlite.exec(statement);
49
+ sqlite.prepare("INSERT INTO __drizzle_migrations (hash, created_at) VALUES (?, ?)").run(migration.hash, migration.createdAt);
50
+ }
51
+ sqlite.pragma(`user_version = ${migrations.length}`);
52
+ })();
53
+ }
54
+ export {
55
+ inspectDatabase,
56
+ migrateSqlite,
57
+ readMigrations,
58
+ requireRestorable
59
+ };
60
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/server/db/history.ts"],
4
+ "sourcesContent": ["import { createHash } from 'node:crypto';\nimport { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type Database from 'better-sqlite3';\nimport type { DatabaseCompatibility } from '../../shared/database.js';\n\nexport interface Migration {\n hash: string;\n createdAt: number;\n sql: string[];\n}\n\nexport function readMigrations(folder: string): Migration[] {\n const journal = JSON.parse(readFileSync(join(folder, 'meta/_journal.json'), 'utf8')) as {\n entries: { idx: number; tag: string; when: number }[];\n };\n let last = 0;\n return journal.entries.map((entry, index) => {\n if (!/^[a-zA-Z0-9_-]+$/.test(entry.tag) || entry.idx !== index || entry.when <= last)\n throw new Error('Invalid database migration journal');\n last = entry.when;\n const source = readFileSync(join(folder, `${entry.tag}.sql`), 'utf8');\n return {\n hash: createHash('sha256').update(source).digest('hex'),\n createdAt: entry.when,\n sql: source.split('--> statement-breakpoint'),\n };\n });\n}\n\n/** A public ordinal never replaces validation of the immutable migration chain. */\nexport function inspectDatabase(sqlite: Database.Database, migrations: Migration[]) {\n const recorded = sqlite.pragma('user_version', { simple: true }) as number;\n const tables = sqlite\n .prepare(\"SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'\")\n .all() as { name: string }[];\n const applied = tables.some((table) => table.name === '__drizzle_migrations')\n ? (sqlite\n .prepare('SELECT hash, created_at FROM __drizzle_migrations ORDER BY created_at')\n .all() as { hash: string; created_at: number }[])\n : [];\n if (\n (!applied.length && tables.some((table) => table.name !== '__drizzle_migrations')) ||\n applied.some(\n (entry, index) =>\n entry.hash !== migrations[index]?.hash || entry.created_at !== migrations[index]?.createdAt,\n ) ||\n (recorded !== 0 && recorded !== applied.length)\n )\n throw new Error(\n '\u6570\u636E\u5E93 Schema \u6216\u8FC1\u79FB\u5386\u53F2\u4E0D\u517C\u5BB9\uFF1B\u8BF7\u4F7F\u7528\u517C\u5BB9\u7248\u672C\u6216\u6062\u590D\u5347\u7EA7\u524D\u5907\u4EFD\uFF0C\u4E0D\u4F1A\u6539\u5199\u6216\u91CD\u5EFA\u6570\u636E\u5E93\u3002',\n );\n return {\n schemaVersion: applied.length,\n legacy: recorded === 0,\n migrationHashes: applied.map((entry) => entry.hash),\n };\n}\n\nexport function requireRestorable(version: number, contract: DatabaseCompatibility) {\n if (version < contract.minRestorableSchemaVersion || version > contract.schemaVersion)\n throw new Error(\n `\u5907\u4EFD Schema ${version} \u4E0D\u517C\u5BB9\u76EE\u6807\u7248\u672C\uFF08\u652F\u6301 ${contract.minRestorableSchemaVersion}\u2013${contract.schemaVersion}\uFF09\u3002`,\n );\n}\n\n/** SQL, Drizzle's existing journal and the public version commit together. */\nexport function migrateSqlite(sqlite: Database.Database, migrations: Migration[]) {\n const before = inspectDatabase(sqlite, migrations);\n sqlite.transaction(() => {\n sqlite.exec(\n 'CREATE TABLE IF NOT EXISTS __drizzle_migrations (id SERIAL PRIMARY KEY, hash text NOT NULL, created_at numeric)',\n );\n for (const migration of migrations.slice(before.schemaVersion)) {\n for (const statement of migration.sql) sqlite.exec(statement);\n sqlite\n .prepare('INSERT INTO __drizzle_migrations (hash, created_at) VALUES (?, ?)')\n .run(migration.hash, migration.createdAt);\n }\n sqlite.pragma(`user_version = ${migrations.length}`);\n })();\n}\n"],
5
+ "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,YAAY;AAUd,SAAS,eAAe,QAA6B;AAC1D,QAAM,UAAU,KAAK,MAAM,aAAa,KAAK,QAAQ,oBAAoB,GAAG,MAAM,CAAC;AAGnF,MAAI,OAAO;AACX,SAAO,QAAQ,QAAQ,IAAI,CAAC,OAAO,UAAU;AAC3C,QAAI,CAAC,mBAAmB,KAAK,MAAM,GAAG,KAAK,MAAM,QAAQ,SAAS,MAAM,QAAQ;AAC9E,YAAM,IAAI,MAAM,oCAAoC;AACtD,WAAO,MAAM;AACb,UAAM,SAAS,aAAa,KAAK,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM;AACpE,WAAO;AAAA,MACL,MAAM,WAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK;AAAA,MACtD,WAAW,MAAM;AAAA,MACjB,KAAK,OAAO,MAAM,0BAA0B;AAAA,IAC9C;AAAA,EACF,CAAC;AACH;AAGO,SAAS,gBAAgB,QAA2B,YAAyB;AAClF,QAAM,WAAW,OAAO,OAAO,gBAAgB,EAAE,QAAQ,KAAK,CAAC;AAC/D,QAAM,SAAS,OACZ,QAAQ,kFAAkF,EAC1F,IAAI;AACP,QAAM,UAAU,OAAO,KAAK,CAAC,UAAU,MAAM,SAAS,sBAAsB,IACvE,OACE,QAAQ,uEAAuE,EAC/E,IAAI,IACP,CAAC;AACL,MACG,CAAC,QAAQ,UAAU,OAAO,KAAK,CAAC,UAAU,MAAM,SAAS,sBAAsB,KAChF,QAAQ;AAAA,IACN,CAAC,OAAO,UACN,MAAM,SAAS,WAAW,KAAK,GAAG,QAAQ,MAAM,eAAe,WAAW,KAAK,GAAG;AAAA,EACtF,KACC,aAAa,KAAK,aAAa,QAAQ;AAExC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACF,SAAO;AAAA,IACL,eAAe,QAAQ;AAAA,IACvB,QAAQ,aAAa;AAAA,IACrB,iBAAiB,QAAQ,IAAI,CAAC,UAAU,MAAM,IAAI;AAAA,EACpD;AACF;AAEO,SAAS,kBAAkB,SAAiB,UAAiC;AAClF,MAAI,UAAU,SAAS,8BAA8B,UAAU,SAAS;AACtE,UAAM,IAAI;AAAA,MACR,uBAAa,OAAO,iEAAe,SAAS,0BAA0B,SAAI,SAAS,aAAa;AAAA,IAClG;AACJ;AAGO,SAAS,cAAc,QAA2B,YAAyB;AAChF,QAAM,SAAS,gBAAgB,QAAQ,UAAU;AACjD,SAAO,YAAY,MAAM;AACvB,WAAO;AAAA,MACL;AAAA,IACF;AACA,eAAW,aAAa,WAAW,MAAM,OAAO,aAAa,GAAG;AAC9D,iBAAW,aAAa,UAAU,IAAK,QAAO,KAAK,SAAS;AAC5D,aACG,QAAQ,mEAAmE,EAC3E,IAAI,UAAU,MAAM,UAAU,SAAS;AAAA,IAC5C;AACA,WAAO,OAAO,kBAAkB,WAAW,MAAM,EAAE;AAAA,EACrD,CAAC,EAAE;AACL;",
6
+ "names": []
7
+ }
@@ -1,9 +1,19 @@
1
- import { chmodSync, mkdirSync } from "node:fs";
1
+ import { inspectDatabase, readMigrations } from "./history.js";
2
+ import { runtimeMigrationsFolder } from "./migrate.js";
3
+ import { chmodSync, mkdirSync, existsSync } from "node:fs";
2
4
  import { dirname } from "node:path";
3
5
  import Database from "better-sqlite3";
4
6
  import { drizzle } from "drizzle-orm/better-sqlite3";
5
7
  import * as schema from "./schema.js";
6
8
  function openDatabase(filename) {
9
+ if (filename !== ":memory:" && existsSync(filename)) {
10
+ const preflight = new Database(filename, { readonly: true, fileMustExist: true });
11
+ try {
12
+ inspectDatabase(preflight, readMigrations(runtimeMigrationsFolder));
13
+ } finally {
14
+ preflight.close();
15
+ }
16
+ }
7
17
  if (filename !== ":memory:") {
8
18
  mkdirSync(dirname(filename), { recursive: true, mode: 448 });
9
19
  chmodSync(dirname(filename), 448);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/server/db/index.ts"],
4
- "sourcesContent": ["import { chmodSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport Database from 'better-sqlite3';\nimport { drizzle, type BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';\nimport * as schema from './schema.js';\n\nexport type AppDatabase = BetterSQLite3Database<typeof schema>;\n\n/** The caller must hold the data directory instance lock before opening/migrating. */\nexport function openDatabase(filename: string): { database: AppDatabase; close: () => void } {\n if (filename !== ':memory:') {\n mkdirSync(dirname(filename), { recursive: true, mode: 0o700 });\n chmodSync(dirname(filename), 0o700);\n }\n const sqlite = new Database(filename);\n sqlite.pragma('foreign_keys = ON');\n sqlite.pragma('journal_mode = WAL');\n sqlite.pragma('busy_timeout = 5000');\n if (filename !== ':memory:') chmodSync(filename, 0o600);\n return { database: drizzle(sqlite, { schema }), close: () => sqlite.close() };\n}\n"],
5
- "mappings": "AAAA,SAAS,WAAW,iBAAiB;AACrC,SAAS,eAAe;AACxB,OAAO,cAAc;AACrB,SAAS,eAA2C;AACpD,YAAY,YAAY;AAKjB,SAAS,aAAa,UAAgE;AAC3F,MAAI,aAAa,YAAY;AAC3B,cAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC7D,cAAU,QAAQ,QAAQ,GAAG,GAAK;AAAA,EACpC;AACA,QAAM,SAAS,IAAI,SAAS,QAAQ;AACpC,SAAO,OAAO,mBAAmB;AACjC,SAAO,OAAO,oBAAoB;AAClC,SAAO,OAAO,qBAAqB;AACnC,MAAI,aAAa,WAAY,WAAU,UAAU,GAAK;AACtD,SAAO,EAAE,UAAU,QAAQ,QAAQ,EAAE,OAAO,CAAC,GAAG,OAAO,MAAM,OAAO,MAAM,EAAE;AAC9E;",
4
+ "sourcesContent": ["import { inspectDatabase, readMigrations } from './history.js';\nimport { runtimeMigrationsFolder } from './migrate.js';\nimport { chmodSync, mkdirSync, existsSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport Database from 'better-sqlite3';\nimport { drizzle, type BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';\nimport * as schema from './schema.js';\n\nexport type AppDatabase = BetterSQLite3Database<typeof schema> & { $client: Database.Database };\n\n/** The caller must hold the data directory instance lock before opening/migrating. */\nexport function openDatabase(filename: string): { database: AppDatabase; close: () => void } {\n if (filename !== ':memory:' && existsSync(filename)) {\n const preflight = new Database(filename, { readonly: true, fileMustExist: true });\n try {\n inspectDatabase(preflight, readMigrations(runtimeMigrationsFolder));\n } finally {\n preflight.close();\n }\n }\n if (filename !== ':memory:') {\n mkdirSync(dirname(filename), { recursive: true, mode: 0o700 });\n chmodSync(dirname(filename), 0o700);\n }\n const sqlite = new Database(filename);\n sqlite.pragma('foreign_keys = ON');\n sqlite.pragma('journal_mode = WAL');\n sqlite.pragma('busy_timeout = 5000');\n if (filename !== ':memory:') chmodSync(filename, 0o600);\n return { database: drizzle(sqlite, { schema }), close: () => sqlite.close() };\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB,sBAAsB;AAChD,SAAS,+BAA+B;AACxC,SAAS,WAAW,WAAW,kBAAkB;AACjD,SAAS,eAAe;AACxB,OAAO,cAAc;AACrB,SAAS,eAA2C;AACpD,YAAY,YAAY;AAKjB,SAAS,aAAa,UAAgE;AAC3F,MAAI,aAAa,cAAc,WAAW,QAAQ,GAAG;AACnD,UAAM,YAAY,IAAI,SAAS,UAAU,EAAE,UAAU,MAAM,eAAe,KAAK,CAAC;AAChF,QAAI;AACF,sBAAgB,WAAW,eAAe,uBAAuB,CAAC;AAAA,IACpE,UAAE;AACA,gBAAU,MAAM;AAAA,IAClB;AAAA,EACF;AACA,MAAI,aAAa,YAAY;AAC3B,cAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC7D,cAAU,QAAQ,QAAQ,GAAG,GAAK;AAAA,EACpC;AACA,QAAM,SAAS,IAAI,SAAS,QAAQ;AACpC,SAAO,OAAO,mBAAmB;AACjC,SAAO,OAAO,oBAAoB;AAClC,SAAO,OAAO,qBAAqB;AACnC,MAAI,aAAa,WAAY,WAAU,UAAU,GAAK;AACtD,SAAO,EAAE,UAAU,QAAQ,QAAQ,EAAE,OAAO,CAAC,GAAG,OAAO,MAAM,OAAO,MAAM,EAAE;AAC9E;",
6
6
  "names": []
7
7
  }
@@ -1,26 +1,16 @@
1
1
  import { fileURLToPath } from "node:url";
2
- import { migrate } from "drizzle-orm/better-sqlite3/migrator";
3
- import { readMigrationFiles } from "drizzle-orm/migrator";
4
- import { sql } from "drizzle-orm";
2
+ import { existsSync } from "node:fs";
3
+ import { migrateSqlite, readMigrations } from "./history.js";
5
4
  const defaultMigrationsFolder = fileURLToPath(new URL("../../../drizzle", import.meta.url));
5
+ const runtimeMigrationsFolder = existsSync(
6
+ fileURLToPath(new URL("../../drizzle", import.meta.url))
7
+ ) ? fileURLToPath(new URL("../../drizzle", import.meta.url)) : defaultMigrationsFolder;
6
8
  function migrateDatabase(database, migrationsFolder = defaultMigrationsFolder) {
7
- const table = database.get(
8
- sql`SELECT name FROM sqlite_master WHERE name = '__drizzle_migrations'`
9
- );
10
- if (table) {
11
- const applied = database.all(
12
- sql`SELECT hash FROM __drizzle_migrations ORDER BY created_at`
13
- );
14
- const migrations = readMigrationFiles({ migrationsFolder });
15
- if (applied.some((entry, i) => entry.hash !== migrations[i]?.hash))
16
- throw new Error(
17
- "\u5F53\u524D\u5B89\u88C5\u4E0D\u517C\u5BB9\u6570\u636E\u5E93\u8FC1\u79FB\u5386\u53F2\uFF1B\u8BF7\u4F7F\u7528\u517C\u5BB9\u7248\u672C\u6216\u5347\u7EA7\u524D\u5907\u4EFD\uFF0C\u4E0D\u4F1A\u6539\u5199\u6216\u91CD\u5EFA\u6570\u636E\u5E93\u3002"
18
- );
19
- }
20
- migrate(database, { migrationsFolder });
9
+ migrateSqlite(database.$client, readMigrations(migrationsFolder));
21
10
  }
22
11
  export {
23
12
  defaultMigrationsFolder,
24
- migrateDatabase
13
+ migrateDatabase,
14
+ runtimeMigrationsFolder
25
15
  };
26
16
  //# sourceMappingURL=migrate.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/server/db/migrate.ts"],
4
- "sourcesContent": ["import { fileURLToPath } from 'node:url';\nimport { migrate } from 'drizzle-orm/better-sqlite3/migrator';\nimport { readMigrationFiles } from 'drizzle-orm/migrator';\nimport { sql } from 'drizzle-orm';\nimport type { AppDatabase } from './index.js';\n\n/** Source and unbundled dist/server/db resolve to repository/dist drizzle respectively. */\nexport const defaultMigrationsFolder = fileURLToPath(new URL('../../../drizzle', import.meta.url));\n\nexport function migrateDatabase(\n database: AppDatabase,\n migrationsFolder = defaultMigrationsFolder,\n): void {\n const table = database.get(\n sql`SELECT name FROM sqlite_master WHERE name = '__drizzle_migrations'`,\n );\n if (table) {\n const applied = database.all<{ hash: string }>(\n sql`SELECT hash FROM __drizzle_migrations ORDER BY created_at`,\n );\n const migrations = readMigrationFiles({ migrationsFolder });\n if (applied.some((entry, i) => entry.hash !== migrations[i]?.hash))\n throw new Error(\n '\u5F53\u524D\u5B89\u88C5\u4E0D\u517C\u5BB9\u6570\u636E\u5E93\u8FC1\u79FB\u5386\u53F2\uFF1B\u8BF7\u4F7F\u7528\u517C\u5BB9\u7248\u672C\u6216\u5347\u7EA7\u524D\u5907\u4EFD\uFF0C\u4E0D\u4F1A\u6539\u5199\u6216\u91CD\u5EFA\u6570\u636E\u5E93\u3002',\n );\n }\n migrate(database, { migrationsFolder });\n}\n"],
5
- "mappings": "AAAA,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AACxB,SAAS,0BAA0B;AACnC,SAAS,WAAW;AAIb,MAAM,0BAA0B,cAAc,IAAI,IAAI,oBAAoB,YAAY,GAAG,CAAC;AAE1F,SAAS,gBACd,UACA,mBAAmB,yBACb;AACN,QAAM,QAAQ,SAAS;AAAA,IACrB;AAAA,EACF;AACA,MAAI,OAAO;AACT,UAAM,UAAU,SAAS;AAAA,MACvB;AAAA,IACF;AACA,UAAM,aAAa,mBAAmB,EAAE,iBAAiB,CAAC;AAC1D,QAAI,QAAQ,KAAK,CAAC,OAAO,MAAM,MAAM,SAAS,WAAW,CAAC,GAAG,IAAI;AAC/D,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,EACJ;AACA,UAAQ,UAAU,EAAE,iBAAiB,CAAC;AACxC;",
4
+ "sourcesContent": ["import { fileURLToPath } from 'node:url';\nimport { existsSync } from 'node:fs';\nimport type { AppDatabase } from './index.js';\nimport { migrateSqlite, readMigrations } from './history.js';\n\n/** Source and unbundled dist/server/db resolve to repository/dist drizzle respectively. */\nexport const defaultMigrationsFolder = fileURLToPath(new URL('../../../drizzle', import.meta.url));\nexport const runtimeMigrationsFolder = existsSync(\n fileURLToPath(new URL('../../drizzle', import.meta.url)),\n)\n ? fileURLToPath(new URL('../../drizzle', import.meta.url))\n : defaultMigrationsFolder;\n\nexport function migrateDatabase(\n database: AppDatabase,\n migrationsFolder = defaultMigrationsFolder,\n): void {\n migrateSqlite(database.$client, readMigrations(migrationsFolder));\n}\n"],
5
+ "mappings": "AAAA,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAE3B,SAAS,eAAe,sBAAsB;AAGvC,MAAM,0BAA0B,cAAc,IAAI,IAAI,oBAAoB,YAAY,GAAG,CAAC;AAC1F,MAAM,0BAA0B;AAAA,EACrC,cAAc,IAAI,IAAI,iBAAiB,YAAY,GAAG,CAAC;AACzD,IACI,cAAc,IAAI,IAAI,iBAAiB,YAAY,GAAG,CAAC,IACvD;AAEG,SAAS,gBACd,UACA,mBAAmB,yBACb;AACN,gBAAc,SAAS,SAAS,eAAe,gBAAgB,CAAC;AAClE;",
6
6
  "names": []
7
7
  }
@@ -1,3 +1,5 @@
1
+ import { backupIdSchema } from "../shared/backups.js";
2
+ import { backupRequestSchema } from "../backups/manager.js";
1
3
  import { createHash } from "node:crypto";
2
4
  import { Hono } from "hono";
3
5
  import { bodyLimit } from "hono/body-limit";
@@ -19,7 +21,8 @@ function createApp({
19
21
  service,
20
22
  staticDir,
21
23
  authenticate = createAuthenticator(config),
22
- updates
24
+ updates,
25
+ backups
23
26
  }) {
24
27
  const app = new Hono();
25
28
  app.onError((error, c) => {
@@ -42,10 +45,25 @@ function createApp({
42
45
  );
43
46
  app.use("/api/*", async (c, next) => {
44
47
  c.header("Cache-Control", "no-store");
45
- if (service.isInMaintenance() && !["GET", "HEAD", "OPTIONS"].includes(c.req.method) && !c.req.path.startsWith("/api/updates"))
46
- throw new AppError("UPDATE_MAINTENANCE", "\u6B63\u5728\u5347\u7EA7\uFF0C\u8BF7\u7B49\u5F85\u670D\u52A1\u91CD\u65B0\u8FDE\u63A5", 503);
48
+ if (service.isInMaintenance() && !["GET", "HEAD", "OPTIONS"].includes(c.req.method) && !c.req.path.startsWith("/api/updates") && !c.req.path.startsWith("/api/backups"))
49
+ throw service.maintenanceError();
47
50
  await next();
48
51
  });
52
+ if (backups) {
53
+ app.get("/api/backups", async (c) => c.json(await backups.status()));
54
+ app.post(
55
+ "/api/backups",
56
+ async (c) => c.json(await backups.start(backupRequestSchema.parse(await c.req.json())), 202)
57
+ );
58
+ app.post(
59
+ "/api/backups/:id/cancel",
60
+ async (c) => c.json(await backups.cancel(backupIdSchema.parse(c.req.param("id"))))
61
+ );
62
+ app.post(
63
+ "/api/backups/:id/verify",
64
+ async (c) => c.json(await backups.verify(backupIdSchema.parse(c.req.param("id"))))
65
+ );
66
+ }
49
67
  if (updates) {
50
68
  app.get("/api/updates", async (c) => c.json(await updates.status()));
51
69
  app.post("/api/updates/check", async (c) => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/server/http.ts"],
4
- "sourcesContent": ["import { createHash } from 'node:crypto';\nimport { Hono } from 'hono';\nimport { bodyLimit } from 'hono/body-limit';\nimport { serveStatic } from '@hono/node-server/serve-static';\nimport { upgradeWebSocket, type HttpBindings } from '@hono/node-server';\nimport type { ZodType } from 'zod';\nimport { ZodError } from 'zod';\nimport { AppError } from '../shared/errors.js';\nimport { IMAGE_REQUEST_BYTES } from '../shared/images.js';\nimport * as schemas from '../shared/validation.js';\nimport type { Operation } from '../shared/types.js';\nimport type { AppConfig } from './config.js';\nimport { ConfigStore } from './config-store.js';\nimport { createAuthenticator, type Authenticator, type Identity } from './auth.js';\nimport type { GatewayService } from './service.js';\nimport { socketHandlers } from './websocket.js';\nimport { z } from 'zod';\nimport { releaseChannels, type UpdateController } from '../shared/updates.js';\nimport { settingsSchema, updateRequestSchema } from '../updates/manager.js';\nimport { startShellSchema } from '../shared/shell.js';\nexport interface HttpDependencies {\n config: AppConfig;\n service: GatewayService;\n staticDir: string;\n authenticate?: Authenticator;\n updates?: UpdateController;\n}\nexport function createApp({\n config,\n service,\n staticDir,\n authenticate = createAuthenticator(config),\n updates,\n}: HttpDependencies) {\n const app = new Hono<{\n Bindings: HttpBindings;\n Variables: { identity: Identity; operationId?: string };\n }>();\n app.onError((error, c) => {\n const failure =\n error instanceof AppError\n ? error\n : error instanceof ZodError || error instanceof SyntaxError\n ? new AppError('VALIDATION_FAILED', 'Invalid request data', 400)\n : new AppError('INTERNAL_ERROR', 'An internal error occurred', 500);\n return c.json({ error: failure.toJSON(c.get('operationId')) }, failure.status as 400);\n });\n app.get('/api/health', (c) => c.json({ ok: true }));\n app.use('*', async (c, next) => {\n c.set('identity', await authenticate(c.req.raw, c.req.path === '/ws'));\n await next();\n });\n app.use('/api/*', (c, next) =>\n bodyLimit({\n maxSize: /^\\/api\\/threads\\/[^/]+\\/(turns|steer)$/.test(c.req.path)\n ? IMAGE_REQUEST_BYTES\n : 512 * 1024,\n onError: () => {\n throw new AppError('BODY_TOO_LARGE', 'Request body exceeds limit', 413);\n },\n })(c, next),\n );\n app.use('/api/*', async (c, next) => {\n c.header('Cache-Control', 'no-store');\n if (\n service.isInMaintenance() &&\n !['GET', 'HEAD', 'OPTIONS'].includes(c.req.method) &&\n !c.req.path.startsWith('/api/updates')\n )\n throw new AppError('UPDATE_MAINTENANCE', '\u6B63\u5728\u5347\u7EA7\uFF0C\u8BF7\u7B49\u5F85\u670D\u52A1\u91CD\u65B0\u8FDE\u63A5', 503);\n await next();\n });\n if (updates) {\n app.get('/api/updates', async (c) => c.json(await updates.status()));\n app.post('/api/updates/check', async (c) => {\n const input = z\n .object({ channel: z.enum(releaseChannels).optional() })\n .strict()\n .parse(await c.req.json());\n return c.json(await updates.check(input.channel));\n });\n app.post('/api/updates/settings', async (c) =>\n c.json(await updates.configure(settingsSchema.parse(await c.req.json()))),\n );\n app.post('/api/updates/run', async (c) =>\n c.json(await updates.start(updateRequestSchema.parse(await c.req.json())), 202),\n );\n }\n const id = (value: string) => schemas.idSchema.parse(value);\n const parse = async <T>(\n c: { req: { json: () => Promise<unknown> }; set: (key: 'operationId', value: string) => void },\n schema: ZodType<T>,\n ): Promise<T> => {\n const value: unknown = await c.req.json();\n if (\n value &&\n typeof value === 'object' &&\n 'clientOperationId' in value &&\n typeof value.clientOperationId === 'string'\n )\n c.set('operationId', value.clientOperationId);\n return schema.parse(value);\n };\n const status = (op: Operation) =>\n op.status === 'dispatching' || op.status === 'accepted' ? (202 as const) : (200 as const);\n const configuration = new ConfigStore(config);\n app.use('/api/config*', async (c, next) => {\n c.header('Cache-Control', 'no-store');\n await next();\n });\n app.get('/api/config', async (c) => c.json(await configuration.snapshot()));\n app.post('/api/config', async (c) => c.json(await configuration.save(await c.req.json())));\n app.post('/api/config/import', async (c) =>\n c.json(await configuration.previewImport(await c.req.json())),\n );\n app.get('/api/config/export', async (c) => {\n c.header('Content-Disposition', 'attachment; filename=\"codex-web-config.json\"');\n return c.json(await configuration.export());\n });\n app.get('/api/history-cache-context', async (c) => {\n const identity = c.get('identity');\n if (config.auth.mode !== 'local' && !identity.subject)\n throw new AppError('UNAUTHENTICATED', '\u65E0\u6CD5\u786E\u8BA4\u7F13\u5B58\u6240\u5C5E\u7528\u6237', 401);\n const projects = await service.listProjects();\n // A restart, user change or project/permission change creates a new namespace.\n // The subject is hashed on the server and is never exposed to browser storage.\n const scope = createHash('sha256')\n .update(\n JSON.stringify([\n service.events.serverEpoch,\n service.getSystem().codexEpoch,\n config.auth.mode,\n identity.subject ?? 'local',\n projects.map((project) => [project.id, project.rootPath, project.available]),\n ]),\n )\n .digest('hex');\n return c.json({ scope });\n });\n app.get('/api/system', (c) => c.json(service.getSystem()));\n app.get('/api/shell', (c) =>\n c.json(\n service.shell.snapshot(\n c.req.query('epoch'),\n z.coerce\n .number()\n .int()\n .min(0)\n .max(Number.MAX_SAFE_INTEGER)\n .default(0)\n .parse(c.req.query('after')),\n ),\n ),\n );\n app.post('/api/projects/:projectId/shell', async (c) => {\n const op = await service.startShell(\n id(c.req.param('projectId')),\n await parse(c, startShellSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/shell/:commandId/interrupt', async (c) => {\n const op = await service.interruptShell(\n id(c.req.param('commandId')),\n await parse(c, schemas.operationSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/system/compatibility/confirm', async (c) => {\n const op = await service.confirmCompatibility(\n await parse(c, schemas.confirmCompatibilitySchema),\n );\n return c.json(op, status(op));\n });\n app.get('/api/projects', async (c) => c.json({ data: await service.listProjects() }));\n app.get('/api/unassigned/runtime-settings', async (c) =>\n c.json(await service.readRuntimeSettings(null)),\n );\n app.post('/api/unassigned/model-defaults', async (c) => {\n const op = await service.saveModelDefaults(\n null,\n await parse(c, schemas.saveModelDefaultsSchema),\n );\n return c.json(op, status(op));\n });\n app.get('/api/unassigned/threads', async (c) =>\n c.json(\n await service.listThreadSummaries(\n null,\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.post('/api/unassigned/threads', async (c) => {\n const op = await service.createThread(null, await parse(c, schemas.createThreadSchema));\n return c.json(op, status(op));\n });\n app.post('/api/project-clones', async (c) =>\n c.json(service.cloneProject(await parse(c, schemas.cloneProjectSchema)), 202),\n );\n app.get('/api/project-clones/:cloneId', (c) =>\n c.json(service.projectClones.get(id(c.req.param('cloneId')))),\n );\n app.post('/api/project-clones/:cloneId/cancel', async (c) => {\n await parse(c, schemas.removeProjectSchema);\n return c.json(service.projectClones.cancel(id(c.req.param('cloneId'))));\n });\n app.post('/api/project-clones/:cloneId/register', async (c) => {\n await parse(c, schemas.removeProjectSchema);\n return c.json(service.projectClones.retryRegistration(id(c.req.param('cloneId'))));\n });\n app.get('/api/projects/:projectId/runtime-settings', async (c) =>\n c.json(await service.readRuntimeSettings(id(c.req.param('projectId')))),\n );\n app.post('/api/projects/:projectId/model-defaults', async (c) => {\n const op = await service.saveModelDefaults(\n id(c.req.param('projectId')),\n await parse(c, schemas.saveModelDefaultsSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/projects', async (c) =>\n c.json(service.addProject(await parse(c, schemas.createProjectSchema))),\n );\n app.post('/api/projects/:projectId/rename', async (c) =>\n c.json(\n service.renameProject(\n id(c.req.param('projectId')),\n await parse(c, schemas.renameProjectSchema),\n ),\n ),\n );\n app.post('/api/projects/:projectId/remove', async (c) => {\n await parse(c, schemas.removeProjectSchema);\n return c.json(service.removeProject(id(c.req.param('projectId'))));\n });\n app.get('/api/projects/:projectId/threads', async (c) =>\n c.json(\n await service.listThreadSummaries(\n id(c.req.param('projectId')),\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.get('/api/threads', async (c) =>\n c.json(\n await service.listThreads(\n id(c.req.query('projectId') ?? ''),\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.post('/api/threads/:threadId/archive', async (c) => {\n return c.json(\n await service.setThreadArchived(\n id(c.req.param('threadId')),\n await parse(c, schemas.archiveThreadSchema),\n ),\n );\n });\n app.get('/api/threads/:threadId', async (c) =>\n c.json(await service.getThread(id(c.req.param('threadId')))),\n );\n app.get('/api/threads/:threadId/history', async (c) =>\n c.json(await service.getThreadHistory(id(c.req.param('threadId')), c.req.query('cursor'))),\n );\n app.get('/api/threads/:threadId/metadata', async (c) =>\n c.json(await service.getThreadMetadata(id(c.req.param('threadId')))),\n );\n app.get('/api/threads/:threadId/export', async (c) => {\n const exported = await service.exportThread(id(c.req.param('threadId')));\n c.header('Content-Type', 'text/markdown; charset=utf-8');\n c.header('Content-Disposition', `attachment; filename=\"${exported.filename}\"`);\n c.header('Cache-Control', 'no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('X-Export-Completeness', exported.partial ? 'partial' : 'saved-history');\n return c.body(exported.markdown);\n });\n app.get('/api/threads/:threadId/images', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n c.header('Content-Security-Policy', \"default-src 'none'; sandbox\");\n const image = await service.getThreadImage(id(c.req.param('threadId')), c.req.query('path'));\n return c.body(image.bytes, 200, {\n 'Content-Type': image.contentType,\n 'Content-Length': String(image.bytes.length),\n });\n });\n app.get('/api/threads/:threadId/markdown', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n return c.json(\n await service.getThreadMarkdown(id(c.req.param('threadId')), c.req.query('path')),\n );\n });\n app.get('/api/threads/:threadId/json', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n return c.json(await service.getThreadJson(id(c.req.param('threadId')), c.req.query('path')));\n });\n app.get('/api/operations/:operationId', (c) =>\n c.json(service.getOperation(id(c.req.param('operationId')))),\n );\n app.post('/api/projects/:projectId/threads', async (c) => {\n const op = await service.createThread(\n id(c.req.param('projectId')),\n await parse(c, schemas.createThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/resume', async (c) => {\n const op = await service.resumeThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.resumeThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/fork', async (c) => {\n const op = await service.forkThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.forkThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/rename', async (c) => {\n const op = await service.renameThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.renameThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/turns', async (c) => {\n const op = await service.startTurn(\n id(c.req.param('threadId')),\n await parse(c, schemas.startTurnSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/review', async (c) => {\n const op = await service.startReview(\n id(c.req.param('threadId')),\n await parse(c, schemas.startReviewSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/steer', async (c) => {\n const op = await service.steer(\n id(c.req.param('threadId')),\n await parse(c, schemas.steerSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/compact', async (c) => {\n const op = await service.compactThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.operationSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/interrupt', async (c) => {\n const op = await service.interrupt(\n id(c.req.param('threadId')),\n await parse(c, schemas.interruptSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/actions/:actionId/resolve', async (c) => {\n const op = await service.resolveAction(\n id(c.req.param('actionId')),\n await parse(c, schemas.resolveActionSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/operations/:operationId/reconcile', async (c) => {\n const op = await service.reconcileOperation(\n id(c.req.param('operationId')),\n await parse(c, schemas.reconcileSchema),\n );\n return c.json(op, status(op));\n });\n app.get(\n '/ws',\n upgradeWebSocket((c) =>\n socketHandlers(service, config, c.get('identity'), c.req.query('overview') === '1'),\n ),\n );\n app.all('/api/*', () => {\n throw new AppError('NOT_FOUND', 'API route not found', 404);\n });\n app.all('/api', () => {\n throw new AppError('NOT_FOUND', 'API route not found', 404);\n });\n app.all('/ws/*', () => {\n throw new AppError('NOT_FOUND', 'WebSocket route not found', 404);\n });\n app.use('*', async (c, next) => {\n if (!c.req.path.startsWith('/assets/')) c.header('Cache-Control', 'no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Referrer-Policy', 'same-origin');\n c.header(\n 'Content-Security-Policy',\n // Remote Markdown images load directly in the browser, including HTTPS redirects.\n // Keep scripts, connections and all other resource policies restricted as before.\n \"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; connect-src 'self'; frame-ancestors 'none'; base-uri 'none'\",\n );\n await next();\n });\n app.get('*', serveStatic({ root: staticDir }));\n app.get('*', async (c, next) => {\n if (!c.req.header('accept')?.includes('text/html') || /\\.[^/]+$/.test(c.req.path))\n return c.json({ error: { code: 'NOT_FOUND', message: 'Resource not found' } }, 404);\n return serveStatic({ path: `${staticDir}/index.html` })(c, next);\n });\n app.notFound((c) => c.json({ error: { code: 'NOT_FOUND', message: 'Resource not found' } }, 404));\n return app;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { BackupController } from '../shared/backups.js';\nimport { backupIdSchema } from '../shared/backups.js';\nimport { backupRequestSchema } from '../backups/manager.js';\nimport { createHash } from 'node:crypto';\nimport { Hono } from 'hono';\nimport { bodyLimit } from 'hono/body-limit';\nimport { serveStatic } from '@hono/node-server/serve-static';\nimport { upgradeWebSocket, type HttpBindings } from '@hono/node-server';\nimport type { ZodType } from 'zod';\nimport { ZodError } from 'zod';\nimport { AppError } from '../shared/errors.js';\nimport { IMAGE_REQUEST_BYTES } from '../shared/images.js';\nimport * as schemas from '../shared/validation.js';\nimport type { Operation } from '../shared/types.js';\nimport type { AppConfig } from './config.js';\nimport { ConfigStore } from './config-store.js';\nimport { createAuthenticator, type Authenticator, type Identity } from './auth.js';\nimport type { GatewayService } from './service.js';\nimport { socketHandlers } from './websocket.js';\nimport { z } from 'zod';\nimport { releaseChannels, type UpdateController } from '../shared/updates.js';\nimport { settingsSchema, updateRequestSchema } from '../updates/manager.js';\nimport { startShellSchema } from '../shared/shell.js';\nexport interface HttpDependencies {\n config: AppConfig;\n service: GatewayService;\n staticDir: string;\n authenticate?: Authenticator;\n updates?: UpdateController;\n backups?: BackupController;\n}\nexport function createApp({\n config,\n service,\n staticDir,\n authenticate = createAuthenticator(config),\n updates,\n backups,\n}: HttpDependencies) {\n const app = new Hono<{\n Bindings: HttpBindings;\n Variables: { identity: Identity; operationId?: string };\n }>();\n app.onError((error, c) => {\n const failure =\n error instanceof AppError\n ? error\n : error instanceof ZodError || error instanceof SyntaxError\n ? new AppError('VALIDATION_FAILED', 'Invalid request data', 400)\n : new AppError('INTERNAL_ERROR', 'An internal error occurred', 500);\n return c.json({ error: failure.toJSON(c.get('operationId')) }, failure.status as 400);\n });\n app.get('/api/health', (c) => c.json({ ok: true }));\n app.use('*', async (c, next) => {\n c.set('identity', await authenticate(c.req.raw, c.req.path === '/ws'));\n await next();\n });\n app.use('/api/*', (c, next) =>\n bodyLimit({\n maxSize: /^\\/api\\/threads\\/[^/]+\\/(turns|steer)$/.test(c.req.path)\n ? IMAGE_REQUEST_BYTES\n : 512 * 1024,\n onError: () => {\n throw new AppError('BODY_TOO_LARGE', 'Request body exceeds limit', 413);\n },\n })(c, next),\n );\n app.use('/api/*', async (c, next) => {\n c.header('Cache-Control', 'no-store');\n if (\n service.isInMaintenance() &&\n !['GET', 'HEAD', 'OPTIONS'].includes(c.req.method) &&\n !c.req.path.startsWith('/api/updates') &&\n !c.req.path.startsWith('/api/backups')\n )\n throw service.maintenanceError();\n await next();\n });\n if (backups) {\n app.get('/api/backups', async (c) => c.json(await backups.status()));\n app.post('/api/backups', async (c) =>\n c.json(await backups.start(backupRequestSchema.parse(await c.req.json())), 202),\n );\n app.post('/api/backups/:id/cancel', async (c) =>\n c.json(await backups.cancel(backupIdSchema.parse(c.req.param('id')))),\n );\n app.post('/api/backups/:id/verify', async (c) =>\n c.json(await backups.verify(backupIdSchema.parse(c.req.param('id')))),\n );\n }\n if (updates) {\n app.get('/api/updates', async (c) => c.json(await updates.status()));\n app.post('/api/updates/check', async (c) => {\n const input = z\n .object({ channel: z.enum(releaseChannels).optional() })\n .strict()\n .parse(await c.req.json());\n return c.json(await updates.check(input.channel));\n });\n app.post('/api/updates/settings', async (c) =>\n c.json(await updates.configure(settingsSchema.parse(await c.req.json()))),\n );\n app.post('/api/updates/run', async (c) =>\n c.json(await updates.start(updateRequestSchema.parse(await c.req.json())), 202),\n );\n }\n const id = (value: string) => schemas.idSchema.parse(value);\n const parse = async <T>(\n c: { req: { json: () => Promise<unknown> }; set: (key: 'operationId', value: string) => void },\n schema: ZodType<T>,\n ): Promise<T> => {\n const value: unknown = await c.req.json();\n if (\n value &&\n typeof value === 'object' &&\n 'clientOperationId' in value &&\n typeof value.clientOperationId === 'string'\n )\n c.set('operationId', value.clientOperationId);\n return schema.parse(value);\n };\n const status = (op: Operation) =>\n op.status === 'dispatching' || op.status === 'accepted' ? (202 as const) : (200 as const);\n const configuration = new ConfigStore(config);\n app.use('/api/config*', async (c, next) => {\n c.header('Cache-Control', 'no-store');\n await next();\n });\n app.get('/api/config', async (c) => c.json(await configuration.snapshot()));\n app.post('/api/config', async (c) => c.json(await configuration.save(await c.req.json())));\n app.post('/api/config/import', async (c) =>\n c.json(await configuration.previewImport(await c.req.json())),\n );\n app.get('/api/config/export', async (c) => {\n c.header('Content-Disposition', 'attachment; filename=\"codex-web-config.json\"');\n return c.json(await configuration.export());\n });\n app.get('/api/history-cache-context', async (c) => {\n const identity = c.get('identity');\n if (config.auth.mode !== 'local' && !identity.subject)\n throw new AppError('UNAUTHENTICATED', '\u65E0\u6CD5\u786E\u8BA4\u7F13\u5B58\u6240\u5C5E\u7528\u6237', 401);\n const projects = await service.listProjects();\n // A restart, user change or project/permission change creates a new namespace.\n // The subject is hashed on the server and is never exposed to browser storage.\n const scope = createHash('sha256')\n .update(\n JSON.stringify([\n service.events.serverEpoch,\n service.getSystem().codexEpoch,\n config.auth.mode,\n identity.subject ?? 'local',\n projects.map((project) => [project.id, project.rootPath, project.available]),\n ]),\n )\n .digest('hex');\n return c.json({ scope });\n });\n app.get('/api/system', (c) => c.json(service.getSystem()));\n app.get('/api/shell', (c) =>\n c.json(\n service.shell.snapshot(\n c.req.query('epoch'),\n z.coerce\n .number()\n .int()\n .min(0)\n .max(Number.MAX_SAFE_INTEGER)\n .default(0)\n .parse(c.req.query('after')),\n ),\n ),\n );\n app.post('/api/projects/:projectId/shell', async (c) => {\n const op = await service.startShell(\n id(c.req.param('projectId')),\n await parse(c, startShellSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/shell/:commandId/interrupt', async (c) => {\n const op = await service.interruptShell(\n id(c.req.param('commandId')),\n await parse(c, schemas.operationSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/system/compatibility/confirm', async (c) => {\n const op = await service.confirmCompatibility(\n await parse(c, schemas.confirmCompatibilitySchema),\n );\n return c.json(op, status(op));\n });\n app.get('/api/projects', async (c) => c.json({ data: await service.listProjects() }));\n app.get('/api/unassigned/runtime-settings', async (c) =>\n c.json(await service.readRuntimeSettings(null)),\n );\n app.post('/api/unassigned/model-defaults', async (c) => {\n const op = await service.saveModelDefaults(\n null,\n await parse(c, schemas.saveModelDefaultsSchema),\n );\n return c.json(op, status(op));\n });\n app.get('/api/unassigned/threads', async (c) =>\n c.json(\n await service.listThreadSummaries(\n null,\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.post('/api/unassigned/threads', async (c) => {\n const op = await service.createThread(null, await parse(c, schemas.createThreadSchema));\n return c.json(op, status(op));\n });\n app.post('/api/project-clones', async (c) =>\n c.json(service.cloneProject(await parse(c, schemas.cloneProjectSchema)), 202),\n );\n app.get('/api/project-clones/:cloneId', (c) =>\n c.json(service.projectClones.get(id(c.req.param('cloneId')))),\n );\n app.post('/api/project-clones/:cloneId/cancel', async (c) => {\n await parse(c, schemas.removeProjectSchema);\n return c.json(service.projectClones.cancel(id(c.req.param('cloneId'))));\n });\n app.post('/api/project-clones/:cloneId/register', async (c) => {\n await parse(c, schemas.removeProjectSchema);\n return c.json(service.projectClones.retryRegistration(id(c.req.param('cloneId'))));\n });\n app.get('/api/projects/:projectId/runtime-settings', async (c) =>\n c.json(await service.readRuntimeSettings(id(c.req.param('projectId')))),\n );\n app.post('/api/projects/:projectId/model-defaults', async (c) => {\n const op = await service.saveModelDefaults(\n id(c.req.param('projectId')),\n await parse(c, schemas.saveModelDefaultsSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/projects', async (c) =>\n c.json(service.addProject(await parse(c, schemas.createProjectSchema))),\n );\n app.post('/api/projects/:projectId/rename', async (c) =>\n c.json(\n service.renameProject(\n id(c.req.param('projectId')),\n await parse(c, schemas.renameProjectSchema),\n ),\n ),\n );\n app.post('/api/projects/:projectId/remove', async (c) => {\n await parse(c, schemas.removeProjectSchema);\n return c.json(service.removeProject(id(c.req.param('projectId'))));\n });\n app.get('/api/projects/:projectId/threads', async (c) =>\n c.json(\n await service.listThreadSummaries(\n id(c.req.param('projectId')),\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.get('/api/threads', async (c) =>\n c.json(\n await service.listThreads(\n id(c.req.query('projectId') ?? ''),\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.post('/api/threads/:threadId/archive', async (c) => {\n return c.json(\n await service.setThreadArchived(\n id(c.req.param('threadId')),\n await parse(c, schemas.archiveThreadSchema),\n ),\n );\n });\n app.get('/api/threads/:threadId', async (c) =>\n c.json(await service.getThread(id(c.req.param('threadId')))),\n );\n app.get('/api/threads/:threadId/history', async (c) =>\n c.json(await service.getThreadHistory(id(c.req.param('threadId')), c.req.query('cursor'))),\n );\n app.get('/api/threads/:threadId/metadata', async (c) =>\n c.json(await service.getThreadMetadata(id(c.req.param('threadId')))),\n );\n app.get('/api/threads/:threadId/export', async (c) => {\n const exported = await service.exportThread(id(c.req.param('threadId')));\n c.header('Content-Type', 'text/markdown; charset=utf-8');\n c.header('Content-Disposition', `attachment; filename=\"${exported.filename}\"`);\n c.header('Cache-Control', 'no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('X-Export-Completeness', exported.partial ? 'partial' : 'saved-history');\n return c.body(exported.markdown);\n });\n app.get('/api/threads/:threadId/images', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n c.header('Content-Security-Policy', \"default-src 'none'; sandbox\");\n const image = await service.getThreadImage(id(c.req.param('threadId')), c.req.query('path'));\n return c.body(image.bytes, 200, {\n 'Content-Type': image.contentType,\n 'Content-Length': String(image.bytes.length),\n });\n });\n app.get('/api/threads/:threadId/markdown', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n return c.json(\n await service.getThreadMarkdown(id(c.req.param('threadId')), c.req.query('path')),\n );\n });\n app.get('/api/threads/:threadId/json', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n return c.json(await service.getThreadJson(id(c.req.param('threadId')), c.req.query('path')));\n });\n app.get('/api/operations/:operationId', (c) =>\n c.json(service.getOperation(id(c.req.param('operationId')))),\n );\n app.post('/api/projects/:projectId/threads', async (c) => {\n const op = await service.createThread(\n id(c.req.param('projectId')),\n await parse(c, schemas.createThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/resume', async (c) => {\n const op = await service.resumeThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.resumeThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/fork', async (c) => {\n const op = await service.forkThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.forkThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/rename', async (c) => {\n const op = await service.renameThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.renameThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/turns', async (c) => {\n const op = await service.startTurn(\n id(c.req.param('threadId')),\n await parse(c, schemas.startTurnSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/review', async (c) => {\n const op = await service.startReview(\n id(c.req.param('threadId')),\n await parse(c, schemas.startReviewSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/steer', async (c) => {\n const op = await service.steer(\n id(c.req.param('threadId')),\n await parse(c, schemas.steerSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/compact', async (c) => {\n const op = await service.compactThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.operationSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/interrupt', async (c) => {\n const op = await service.interrupt(\n id(c.req.param('threadId')),\n await parse(c, schemas.interruptSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/actions/:actionId/resolve', async (c) => {\n const op = await service.resolveAction(\n id(c.req.param('actionId')),\n await parse(c, schemas.resolveActionSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/operations/:operationId/reconcile', async (c) => {\n const op = await service.reconcileOperation(\n id(c.req.param('operationId')),\n await parse(c, schemas.reconcileSchema),\n );\n return c.json(op, status(op));\n });\n app.get(\n '/ws',\n upgradeWebSocket((c) =>\n socketHandlers(service, config, c.get('identity'), c.req.query('overview') === '1'),\n ),\n );\n app.all('/api/*', () => {\n throw new AppError('NOT_FOUND', 'API route not found', 404);\n });\n app.all('/api', () => {\n throw new AppError('NOT_FOUND', 'API route not found', 404);\n });\n app.all('/ws/*', () => {\n throw new AppError('NOT_FOUND', 'WebSocket route not found', 404);\n });\n app.use('*', async (c, next) => {\n if (!c.req.path.startsWith('/assets/')) c.header('Cache-Control', 'no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Referrer-Policy', 'same-origin');\n c.header(\n 'Content-Security-Policy',\n // Remote Markdown images load directly in the browser, including HTTPS redirects.\n // Keep scripts, connections and all other resource policies restricted as before.\n \"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; connect-src 'self'; frame-ancestors 'none'; base-uri 'none'\",\n );\n await next();\n });\n app.get('*', serveStatic({ root: staticDir }));\n app.get('*', async (c, next) => {\n if (!c.req.header('accept')?.includes('text/html') || /\\.[^/]+$/.test(c.req.path))\n return c.json({ error: { code: 'NOT_FOUND', message: 'Resource not found' } }, 404);\n return serveStatic({ path: `${staticDir}/index.html` })(c, next);\n });\n app.notFound((c) => c.json({ error: { code: 'NOT_FOUND', message: 'Resource not found' } }, 404));\n return app;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,10 +1,13 @@
1
+ import { BackupManager } from "../backups/manager.js";
2
+ import { createBackupStore } from "../backups/factory.js";
3
+ import { assertNoPendingRestore } from "../backups/restore.js";
1
4
  import { fileURLToPath } from "node:url";
2
5
  import { join } from "node:path";
3
6
  import { existsSync, realpathSync } from "node:fs";
4
7
  import { serve } from "@hono/node-server";
5
8
  import { WebSocketServer } from "ws";
6
9
  import { CodexAdapter } from "../codex/adapter.js";
7
- import { loadConfig } from "./config.js";
10
+ import { loadConfig, configSource } from "./config.js";
8
11
  import { acquireInstanceLock } from "./instance-lock.js";
9
12
  import { openDatabase } from "./db/index.js";
10
13
  import { migrateDatabase } from "./db/migrate.js";
@@ -18,8 +21,12 @@ async function startGateway(config, overrides = {}) {
18
21
  const release = await acquireInstanceLock(config.dataDir);
19
22
  let closeDatabase;
20
23
  let codex;
24
+ let backups = overrides.backups;
21
25
  const updates = overrides.updates ?? new UpdateManager(void 0, void 0, () => codex?.diagnostics().codexVersion ?? null);
22
26
  try {
27
+ const source = configSource(config);
28
+ const backupStore = source ? createBackupStore(source.path, config.dataDir, overrides.migrationsDir) : void 0;
29
+ if (backupStore) await assertNoPendingRestore(backupStore.options.directory);
23
30
  const db = openDatabase(join(config.dataDir, "app.sqlite"));
24
31
  closeDatabase = db.close;
25
32
  const packagedMigrations = fileURLToPath(new URL("../drizzle", import.meta.url));
@@ -38,6 +45,7 @@ async function startGateway(config, overrides = {}) {
38
45
  demo: config.demo
39
46
  });
40
47
  service.setMaintenance(overrides.maintenance ?? false);
48
+ backups ??= backupStore ? new BackupManager(backupStore, service) : void 0;
41
49
  try {
42
50
  await codex.start();
43
51
  } catch {
@@ -47,7 +55,8 @@ async function startGateway(config, overrides = {}) {
47
55
  config,
48
56
  service,
49
57
  staticDir: overrides.staticDir ?? fileURLToPath(new URL("../web", import.meta.url)),
50
- updates
58
+ updates,
59
+ backups
51
60
  });
52
61
  const server = serve({
53
62
  fetch: app.fetch,
@@ -71,6 +80,7 @@ async function startGateway(config, overrides = {}) {
71
80
  }
72
81
  wss.close();
73
82
  try {
83
+ await backups?.close();
74
84
  await service.shutdown();
75
85
  } finally {
76
86
  if ("closeAllConnections" in server) server.closeAllConnections();
@@ -82,9 +92,10 @@ async function startGateway(config, overrides = {}) {
82
92
  }
83
93
  }
84
94
  })();
85
- return { app, server, service, codex, close, updates };
95
+ return { app, server, service, codex, close, updates, backups };
86
96
  } catch (error) {
87
97
  updates.close();
98
+ await backups?.close();
88
99
  try {
89
100
  await codex?.stop();
90
101
  } finally {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/server/main.ts"],
4
- "sourcesContent": ["import { fileURLToPath } from 'node:url';\nimport { join } from 'node:path';\nimport { existsSync, realpathSync } from 'node:fs';\nimport { serve } from '@hono/node-server';\nimport { WebSocketServer } from 'ws';\nimport { CodexAdapter } from '../codex/adapter.js';\nimport type { CodexClient } from '../codex/types.js';\nimport { loadConfig, type AppConfig } from './config.js';\nimport { acquireInstanceLock } from './instance-lock.js';\nimport { openDatabase } from './db/index.js';\nimport { migrateDatabase } from './db/migrate.js';\nimport { OperationStore } from './db/operations.js';\nimport { ProjectRegistry } from './projects.js';\nimport { GatewayService } from './service.js';\nimport { createApp } from './http.js';\nimport { startHeartbeat } from './websocket.js';\nimport { UpdateManager } from '../updates/manager.js';\nimport type { UpdateController } from '../shared/updates.js';\nexport async function startGateway(\n config: AppConfig,\n overrides: {\n codex?: CodexClient;\n staticDir?: string;\n migrationsDir?: string;\n updates?: UpdateController;\n maintenance?: boolean;\n } = {},\n) {\n const release = await acquireInstanceLock(config.dataDir);\n let closeDatabase: (() => void) | undefined;\n let codex: CodexClient | undefined;\n const updates =\n overrides.updates ??\n new UpdateManager(undefined, undefined, () => codex?.diagnostics().codexVersion ?? null);\n try {\n const db = openDatabase(join(config.dataDir, 'app.sqlite'));\n closeDatabase = db.close;\n const packagedMigrations = fileURLToPath(new URL('../drizzle', import.meta.url));\n migrateDatabase(\n db.database,\n overrides.migrationsDir ?? (existsSync(packagedMigrations) ? packagedMigrations : undefined),\n );\n codex = overrides.codex ?? new CodexAdapter(config.codex);\n const service = new GatewayService({\n store: new OperationStore(db.database),\n projects: new ProjectRegistry(config.projects, db.database),\n codex,\n workspacesRoot: join(config.dataDir, 'workspaces'),\n limits: config.limits,\n authMode: config.auth.mode,\n demo: config.demo,\n });\n service.setMaintenance(overrides.maintenance ?? false);\n try {\n await codex.start();\n } catch {\n /* Diagnostics remain available; never substitute a fixture. */\n }\n const wss = new WebSocketServer({ noServer: true, maxPayload: 8192 });\n const app = createApp({\n config,\n service,\n staticDir: overrides.staticDir ?? fileURLToPath(new URL('../web', import.meta.url)),\n updates,\n });\n const server = serve({\n fetch: app.fetch,\n hostname: config.host,\n port: config.port,\n websocket: { server: wss },\n });\n await new Promise<void>((resolveListening, reject) => {\n server.once('listening', resolveListening);\n server.once('error', reject);\n });\n const stopHeartbeat = startHeartbeat(wss);\n let closing: Promise<void> | undefined;\n const close = (): Promise<void> =>\n (closing ??= (async () => {\n stopHeartbeat();\n updates.close();\n const closed = new Promise<void>((resolveClosed) => server.close(() => resolveClosed()));\n for (const ws of wss.clients) {\n ws.close(1001, 'Gateway stopping');\n ws.terminate();\n }\n wss.close();\n try {\n await service.shutdown();\n } finally {\n if ('closeAllConnections' in server) server.closeAllConnections();\n await closed;\n try {\n db.close();\n } finally {\n await release();\n }\n }\n })());\n return { app, server, service, codex, close, updates };\n } catch (error) {\n updates.close();\n try {\n await codex?.stop();\n } finally {\n try {\n closeDatabase?.();\n } finally {\n await release();\n }\n }\n throw error;\n }\n}\nif (process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {\n try {\n const config = await loadConfig();\n const runtime = await startGateway(config);\n console.log(`Codex Web UI listening on ${config.host}:${config.port}`);\n console.log(`Allowed origins: ${config.publicOrigin.join(', ')}`);\n const stop = () => {\n void runtime.close().then(\n () => {\n process.exitCode = 0;\n },\n () => {\n process.exitCode = 1;\n },\n );\n };\n process.once('SIGINT', stop);\n process.once('SIGTERM', stop);\n } catch (error) {\n console.error(error instanceof Error ? error.message : 'Startup failed');\n process.exitCode = 1;\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { BackupManager } from '../backups/manager.js';\nimport { createBackupStore } from '../backups/factory.js';\nimport { assertNoPendingRestore } from '../backups/restore.js';\nimport type { BackupController } from '../shared/backups.js';\nimport { fileURLToPath } from 'node:url';\nimport { join } from 'node:path';\nimport { existsSync, realpathSync } from 'node:fs';\nimport { serve } from '@hono/node-server';\nimport { WebSocketServer } from 'ws';\nimport { CodexAdapter } from '../codex/adapter.js';\nimport type { CodexClient } from '../codex/types.js';\nimport { loadConfig, configSource, type AppConfig } from './config.js';\nimport { acquireInstanceLock } from './instance-lock.js';\nimport { openDatabase } from './db/index.js';\nimport { migrateDatabase } from './db/migrate.js';\nimport { OperationStore } from './db/operations.js';\nimport { ProjectRegistry } from './projects.js';\nimport { GatewayService } from './service.js';\nimport { createApp } from './http.js';\nimport { startHeartbeat } from './websocket.js';\nimport { UpdateManager } from '../updates/manager.js';\nimport type { UpdateController } from '../shared/updates.js';\nexport async function startGateway(\n config: AppConfig,\n overrides: {\n codex?: CodexClient;\n staticDir?: string;\n migrationsDir?: string;\n updates?: UpdateController;\n backups?: BackupController;\n maintenance?: boolean;\n } = {},\n) {\n const release = await acquireInstanceLock(config.dataDir);\n let closeDatabase: (() => void) | undefined;\n let codex: CodexClient | undefined;\n let backups: BackupController | undefined = overrides.backups;\n const updates =\n overrides.updates ??\n new UpdateManager(undefined, undefined, () => codex?.diagnostics().codexVersion ?? null);\n try {\n const source = configSource(config);\n const backupStore = source\n ? createBackupStore(source.path, config.dataDir, overrides.migrationsDir)\n : undefined;\n if (backupStore) await assertNoPendingRestore(backupStore.options.directory);\n const db = openDatabase(join(config.dataDir, 'app.sqlite'));\n closeDatabase = db.close;\n const packagedMigrations = fileURLToPath(new URL('../drizzle', import.meta.url));\n migrateDatabase(\n db.database,\n overrides.migrationsDir ?? (existsSync(packagedMigrations) ? packagedMigrations : undefined),\n );\n codex = overrides.codex ?? new CodexAdapter(config.codex);\n const service = new GatewayService({\n store: new OperationStore(db.database),\n projects: new ProjectRegistry(config.projects, db.database),\n codex,\n workspacesRoot: join(config.dataDir, 'workspaces'),\n limits: config.limits,\n authMode: config.auth.mode,\n demo: config.demo,\n });\n service.setMaintenance(overrides.maintenance ?? false);\n backups ??= backupStore ? new BackupManager(backupStore, service) : undefined;\n try {\n await codex.start();\n } catch {\n /* Diagnostics remain available; never substitute a fixture. */\n }\n const wss = new WebSocketServer({ noServer: true, maxPayload: 8192 });\n const app = createApp({\n config,\n service,\n staticDir: overrides.staticDir ?? fileURLToPath(new URL('../web', import.meta.url)),\n updates,\n backups,\n });\n const server = serve({\n fetch: app.fetch,\n hostname: config.host,\n port: config.port,\n websocket: { server: wss },\n });\n await new Promise<void>((resolveListening, reject) => {\n server.once('listening', resolveListening);\n server.once('error', reject);\n });\n const stopHeartbeat = startHeartbeat(wss);\n let closing: Promise<void> | undefined;\n const close = (): Promise<void> =>\n (closing ??= (async () => {\n stopHeartbeat();\n updates.close();\n const closed = new Promise<void>((resolveClosed) => server.close(() => resolveClosed()));\n for (const ws of wss.clients) {\n ws.close(1001, 'Gateway stopping');\n ws.terminate();\n }\n wss.close();\n try {\n await backups?.close();\n await service.shutdown();\n } finally {\n if ('closeAllConnections' in server) server.closeAllConnections();\n await closed;\n try {\n db.close();\n } finally {\n await release();\n }\n }\n })());\n return { app, server, service, codex, close, updates, backups };\n } catch (error) {\n updates.close();\n await backups?.close();\n try {\n await codex?.stop();\n } finally {\n try {\n closeDatabase?.();\n } finally {\n await release();\n }\n }\n throw error;\n }\n}\nif (process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {\n try {\n const config = await loadConfig();\n const runtime = await startGateway(config);\n console.log(`Codex Web UI listening on ${config.host}:${config.port}`);\n console.log(`Allowed origins: ${config.publicOrigin.join(', ')}`);\n const stop = () => {\n void runtime.close().then(\n () => {\n process.exitCode = 0;\n },\n () => {\n process.exitCode = 1;\n },\n );\n };\n process.once('SIGINT', stop);\n process.once('SIGTERM', stop);\n } catch (error) {\n console.error(error instanceof Error ? error.message : 'Startup failed');\n process.exitCode = 1;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -64,6 +64,7 @@ class GatewayService {
64
64
  fileTemporaryRoots = temporaryFileRoots();
65
65
  accepting = true;
66
66
  maintenance = false;
67
+ maintenanceReason = "update";
67
68
  currentEpoch;
68
69
  confirmedCompatibility;
69
70
  archiveChanges = /* @__PURE__ */ new Set();
@@ -103,10 +104,14 @@ class GatewayService {
103
104
  isInMaintenance() {
104
105
  return this.maintenance;
105
106
  }
106
- setMaintenance(value) {
107
+ setMaintenance(value, reason = "update") {
107
108
  this.maintenance = value;
109
+ this.maintenanceReason = reason;
108
110
  }
109
- prepareUpdate() {
111
+ maintenanceError() {
112
+ return this.maintenanceReason === "backup" ? new AppError("BACKUP_MAINTENANCE", "\u6B63\u5728\u5907\u4EFD\uFF0C\u8BF7\u5B8C\u6210\u540E\u91CD\u8BD5\u3002", 503) : new AppError("UPDATE_MAINTENANCE", "\u6B63\u5728\u5347\u7EA7\uFF0C\u8BF7\u7B49\u5F85\u670D\u52A1\u91CD\u65B0\u8FDE\u63A5", 503);
113
+ }
114
+ prepareUpdate(reason = "update") {
110
115
  if (this.projectClones.hasActive) return { ready: false, reason: "\u7B49\u5F85\u9879\u76EE\u514B\u9686\u5B8C\u6210\u6216\u53D6\u6D88" };
111
116
  if (this.shell.active()) return { ready: false, reason: "\u7B49\u5F85 Shell \u547D\u4EE4\u7ED3\u675F" };
112
117
  if (this.inFlightOperations.size || this.resumes.size || this.pendingThreadCreations.size)
@@ -117,7 +122,7 @@ class GatewayService {
117
122
  (action) => ["pending", "responding"].includes(action.status)
118
123
  ))
119
124
  return { ready: false, reason: "\u7B49\u5F85\u6267\u884C\u4E2D\u7684\u4EFB\u52A1\u3001\u5BA1\u6279\u6216\u8F93\u5165\u7ED3\u675F" };
120
- this.maintenance = true;
125
+ this.setMaintenance(true, reason);
121
126
  return { ready: true };
122
127
  }
123
128
  addProject(input) {
@@ -882,8 +887,7 @@ class GatewayService {
882
887
  }
883
888
  async perform(kind, target, input, work) {
884
889
  if (!this.accepting) throw new AppError("CODEX_UNAVAILABLE", "\u670D\u52A1\u6B63\u5728\u5173\u95ED", 503);
885
- if (this.maintenance)
886
- throw new AppError("UPDATE_MAINTENANCE", "\u6B63\u5728\u5347\u7EA7\uFF0C\u8BF7\u7B49\u5F85\u670D\u52A1\u91CD\u65B0\u8FDE\u63A5", 503);
890
+ if (this.maintenance) throw this.maintenanceError();
887
891
  let accepted;
888
892
  try {
889
893
  accepted = this.store.accept(input.clientOperationId, kind, target, input);