@covro/covro 0.2.1-dev.3 → 0.2.1-dev.4

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 (111) hide show
  1. package/README.md +6 -1
  2. package/README.zh-CN.md +6 -1
  3. package/dist/codex/adapter.js +8 -1
  4. package/dist/codex/adapter.js.map +2 -2
  5. package/dist/drizzle/0005_session_workspaces.sql +24 -0
  6. package/dist/drizzle/meta/0005_snapshot.json +480 -0
  7. package/dist/drizzle/meta/_journal.json +7 -0
  8. package/dist/server/db/operations.js +14 -1
  9. package/dist/server/db/operations.js.map +2 -2
  10. package/dist/server/db/schema.js +9 -1
  11. package/dist/server/db/schema.js.map +2 -2
  12. package/dist/server/http.js +25 -0
  13. package/dist/server/http.js.map +2 -2
  14. package/dist/server/local-files.js +2 -2
  15. package/dist/server/local-files.js.map +2 -2
  16. package/dist/server/main.js +1 -0
  17. package/dist/server/main.js.map +2 -2
  18. package/dist/server/service.js +96 -51
  19. package/dist/server/service.js.map +2 -2
  20. package/dist/server/workspaces.js +138 -0
  21. package/dist/server/workspaces.js.map +7 -0
  22. package/dist/shared/workspace-scope.js +9 -0
  23. package/dist/shared/workspace-scope.js.map +7 -0
  24. package/dist/web/assets/{abnfDiagram-WEYOIA3C-6n1mVJ0V.js → abnfDiagram-WEYOIA3C-DTTcFQGL.js} +1 -1
  25. package/dist/web/assets/{arc-DFIzIYgQ.js → arc-K2pKIwfu.js} +1 -1
  26. package/dist/web/assets/{architecture-WOLXFQ4H-CoZpoP0F.js → architecture-WOLXFQ4H-DrxN_1CG.js} +1 -1
  27. package/dist/web/assets/{architectureDiagram-ZHVYKT53-LcqVhgRh.js → architectureDiagram-ZHVYKT53-CyyCrVAb.js} +1 -1
  28. package/dist/web/assets/{blockDiagram-RJAE7QA3-CnVQsmM8.js → blockDiagram-RJAE7QA3-C8vl8QXS.js} +1 -1
  29. package/dist/web/assets/{c4Diagram-XDPPPE54-C38UO-rV.js → c4Diagram-XDPPPE54-BtnIITFN.js} +1 -1
  30. package/dist/web/assets/channel-CDExoPVe.js +1 -0
  31. package/dist/web/assets/{chunk-2E7WHVMD-SlpXCVVC.js → chunk-2E7WHVMD-BssauSch.js} +1 -1
  32. package/dist/web/assets/{chunk-4EMNKR2T-BPJa0lfJ.js → chunk-4EMNKR2T-BZOo1RWg.js} +1 -1
  33. package/dist/web/assets/{chunk-55XCU76K-CkP_cE5N.js → chunk-55XCU76K-D8ZWazMQ.js} +1 -1
  34. package/dist/web/assets/{chunk-7S6XSTFO-BnrWU32l.js → chunk-7S6XSTFO-C8WqPzUl.js} +1 -1
  35. package/dist/web/assets/{chunk-AQDTSKZB-J2M9tBY-.js → chunk-AQDTSKZB-Coo6Axpg.js} +1 -1
  36. package/dist/web/assets/{chunk-DSNLSHJZ-ClfNpgVO.js → chunk-DSNLSHJZ-5TwmEPWR.js} +1 -1
  37. package/dist/web/assets/{chunk-HAGFOTED-k7XcZqWB.js → chunk-HAGFOTED-Dgtj-Fc_.js} +1 -1
  38. package/dist/web/assets/{chunk-HNE4Q36P-DHHenyG4.js → chunk-HNE4Q36P-COoS4UPL.js} +1 -1
  39. package/dist/web/assets/{chunk-NQOKRVIF-CkA3TLYc.js → chunk-NQOKRVIF-tPhNkBBj.js} +1 -1
  40. package/dist/web/assets/{chunk-UHW7PFBP-DSLKZJoJ.js → chunk-UHW7PFBP-BLk_BkCl.js} +1 -1
  41. package/dist/web/assets/{chunk-VQ5W62QI-BBkSWILl.js → chunk-VQ5W62QI-HBeSVTU0.js} +1 -1
  42. package/dist/web/assets/{chunk-WQQL4CDK-BeKgda0U.js → chunk-WQQL4CDK-LmZUm8If.js} +1 -1
  43. package/dist/web/assets/{chunk-XXDRQBXY-BC-ozzjn.js → chunk-XXDRQBXY-49rKU8Nk.js} +1 -1
  44. package/dist/web/assets/{chunk-YZO67HFG-C19e3AP5.js → chunk-YZO67HFG-B_TgpaEG.js} +1 -1
  45. package/dist/web/assets/{chunk-ZAUX2LTX-C03NsQfr.js → chunk-ZAUX2LTX-f7-DSOrY.js} +1 -1
  46. package/dist/web/assets/{chunk-ZCHMQSOR-CrXzPEWh.js → chunk-ZCHMQSOR-QhJOh7x0.js} +1 -1
  47. package/dist/web/assets/{classDiagram-v2-4MYWR3UA-DCbxTUm6.js → classDiagram-v2-4MYWR3UA-CwF2HuoZ.js} +1 -1
  48. package/dist/web/assets/{cose-bilkent-JH36ORCC-CQZjK1BR.js → cose-bilkent-JH36ORCC-CLvKOlx5.js} +1 -1
  49. package/dist/web/assets/{cynefin-EF2NZ3EQ-i1jWxeqI.js → cynefin-EF2NZ3EQ-BNRVavZN.js} +1 -1
  50. package/dist/web/assets/{cynefinDiagram-WF24UDRP-DfVYiPE9.js → cynefinDiagram-WF24UDRP-DEd83kgI.js} +1 -1
  51. package/dist/web/assets/{dagre-NK4GIZVX-OhkyZBvK.js → dagre-NK4GIZVX-C340UEI3.js} +1 -1
  52. package/dist/web/assets/{diagram-CBK3MWTC-CXdVEIne.js → diagram-CBK3MWTC-CuN7ncUm.js} +1 -1
  53. package/dist/web/assets/{diagram-I5XIIV2D-BjrxVPW0.js → diagram-I5XIIV2D-D9mGAfA7.js} +1 -1
  54. package/dist/web/assets/{diagram-ODIL2UCW-C5BpAqPG.js → diagram-ODIL2UCW-CXtBv4bI.js} +1 -1
  55. package/dist/web/assets/{diagram-PFBEJUXE-3yWOE5ZP.js → diagram-PFBEJUXE-B8qP5nGT.js} +1 -1
  56. package/dist/web/assets/{diagram-RJA3I4VV-DdRZojn9.js → diagram-RJA3I4VV-BVrzsw2b.js} +1 -1
  57. package/dist/web/assets/{diagram-TYUNFSNR-m_gnI0-3.js → diagram-TYUNFSNR-Djfine3D.js} +1 -1
  58. package/dist/web/assets/{dist-DMGebNoK.js → dist-D8kDnYqD.js} +1 -1
  59. package/dist/web/assets/{ebnfDiagram-V4P3TTPT-CVwc9K-O.js → ebnfDiagram-V4P3TTPT-C69Oiekp.js} +1 -1
  60. package/dist/web/assets/{elk-QONTBCTQ-BDC-J8E3.js → elk-QONTBCTQ-Bd3BP1h1.js} +1 -1
  61. package/dist/web/assets/{erDiagram-KYQIGQAA-D-dqUb0a.js → erDiagram-KYQIGQAA-Dxcl5jVl.js} +1 -1
  62. package/dist/web/assets/{eventmodeling-K75KTNOO-ByZ_MfSZ.js → eventmodeling-K75KTNOO-Do8p535i.js} +1 -1
  63. package/dist/web/assets/flowDiagram-IUGLLWBU-X85uzgrG.js +1 -0
  64. package/dist/web/assets/{ganttDiagram-R7GPNTJY-BHzyPnqV.js → ganttDiagram-R7GPNTJY-MBGUZbVy.js} +1 -1
  65. package/dist/web/assets/{gitGraph-VSP46ZUC-DQhxrj3o.js → gitGraph-VSP46ZUC-CHxRIbkg.js} +1 -1
  66. package/dist/web/assets/{gitGraphDiagram-PDYL7XHY-8M2oNXTx.js → gitGraphDiagram-PDYL7XHY-DbW0GeW4.js} +1 -1
  67. package/dist/web/assets/index-Cz3AOJOw.js +142 -0
  68. package/dist/web/assets/index-DaMLk_sl.css +1 -0
  69. package/dist/web/assets/{info-OHQRW6UA-717A6Kfa.js → info-OHQRW6UA-K8BF1xZb.js} +1 -1
  70. package/dist/web/assets/{infoDiagram-MVDRKAX5-D-fxOvE-.js → infoDiagram-MVDRKAX5-QaWV5-SY.js} +1 -1
  71. package/dist/web/assets/{ishikawaDiagram-HPEHV2GE-CKrXOGrR.js → ishikawaDiagram-HPEHV2GE-DpVz_sC0.js} +1 -1
  72. package/dist/web/assets/{journeyDiagram-BOSHW7O7-BLD4lmI6.js → journeyDiagram-BOSHW7O7-S9MzozV7.js} +1 -1
  73. package/dist/web/assets/{kanban-definition-FNSA4HC5-Mj1GI5Fb.js → kanban-definition-FNSA4HC5-BiU8Ibw-.js} +1 -1
  74. package/dist/web/assets/{line-DotNyRbu.js → line-B1KaX5ms.js} +1 -1
  75. package/dist/web/assets/{linear-DQ0Uvp2K.js → linear-Cg1dwAtU.js} +1 -1
  76. package/dist/web/assets/{mermaid-parser.core-BtFC_UVn.js → mermaid-parser.core-hzYHYxfI.js} +3 -3
  77. package/dist/web/assets/{mermaid.core-DHL14mKq.js → mermaid.core-N8xYYvXy.js} +4 -4
  78. package/dist/web/assets/{mindmap-definition-6OY57UG3-CMCguBhk.js → mindmap-definition-6OY57UG3-BmIQCrEd.js} +1 -1
  79. package/dist/web/assets/{packet-JDAUHWVQ-CGyEqUmo.js → packet-JDAUHWVQ-DhOTX9De.js} +1 -1
  80. package/dist/web/assets/{pegDiagram-ECIUJNBX-DPgLxTHJ.js → pegDiagram-ECIUJNBX-CVfE6yUu.js} +1 -1
  81. package/dist/web/assets/{pie-XZMESJXO-Ddsl6geS.js → pie-XZMESJXO-BayfKVL8.js} +1 -1
  82. package/dist/web/assets/{pieDiagram-GNMPY74T-BJdkqrU_.js → pieDiagram-GNMPY74T-ClbMRve3.js} +1 -1
  83. package/dist/web/assets/{quadrantDiagram-D57K4MC3-47l23gov.js → quadrantDiagram-D57K4MC3-DFp-P_EZ.js} +1 -1
  84. package/dist/web/assets/{radar-ABXABTNO-DAyB1li0.js → radar-ABXABTNO-Bt1EAsxC.js} +1 -1
  85. package/dist/web/assets/{railroad-I3PHUGI6-BZYuBfPR.js → railroad-I3PHUGI6-CSos2Rm9.js} +1 -1
  86. package/dist/web/assets/{railroad-abnf-LNEFI6M7-PBkoxIWP.js → railroad-abnf-LNEFI6M7-CebY-3Kh.js} +1 -1
  87. package/dist/web/assets/{railroad-ebnf-DWYD2UWJ-Bl_rTgpR.js → railroad-ebnf-DWYD2UWJ-DpA6-TBs.js} +1 -1
  88. package/dist/web/assets/{railroad-peg-JR7BVNR7-U9kj7aP3.js → railroad-peg-JR7BVNR7-Bg3QPvi5.js} +1 -1
  89. package/dist/web/assets/{railroadDiagram-Y72NRBL7-Dpq4us5_.js → railroadDiagram-Y72NRBL7-BM4RAgqS.js} +1 -1
  90. package/dist/web/assets/{requirementDiagram-EQYSW5RA-CCqQbcTz.js → requirementDiagram-EQYSW5RA-CqP9bCS_.js} +1 -1
  91. package/dist/web/assets/{sankeyDiagram-SY24JHO5-DDwytZM3.js → sankeyDiagram-SY24JHO5-BhS8f6-k.js} +1 -1
  92. package/dist/web/assets/{sequenceDiagram-BLEHNHQU-C-z57Y06.js → sequenceDiagram-BLEHNHQU-p3C1DgeC.js} +1 -1
  93. package/dist/web/assets/{src-CK51kAyQ.js → src-9XJAFibc.js} +1 -1
  94. package/dist/web/assets/{stateDiagram-v2-A6IESKWZ-DgTp0O6g.js → stateDiagram-v2-A6IESKWZ-DVVy8chY.js} +1 -1
  95. package/dist/web/assets/{swimlanes-B3ENRKFQ-BiyS7wH3.js → swimlanes-B3ENRKFQ-CtMPO6Gw.js} +1 -1
  96. package/dist/web/assets/swimlanesDiagram-AYQRV4AK-BRXJWgnO.js +8 -0
  97. package/dist/web/assets/{timeline-definition-JXYKGLGB-D_PAPA8Z.js → timeline-definition-JXYKGLGB-DuTqpjLQ.js} +1 -1
  98. package/dist/web/assets/{treeView-D4JQ5SDB-m1fbOydD.js → treeView-D4JQ5SDB-qpOZEphu.js} +1 -1
  99. package/dist/web/assets/{treemap-SAJKECNS-Bxt7Udu9.js → treemap-SAJKECNS-Dm6e3TpG.js} +1 -1
  100. package/dist/web/assets/{usecaseDiagram-WPOLBNNX-BTrMcoPL.js → usecaseDiagram-WPOLBNNX-DoCSdm5y.js} +1 -1
  101. package/dist/web/assets/{vennDiagram-Q3Y3IDCW-C_kOOxPJ.js → vennDiagram-Q3Y3IDCW-qzd4yvh5.js} +1 -1
  102. package/dist/web/assets/{wardley-7MLQ67FV-C33rdYbB.js → wardley-7MLQ67FV-CkcgIQgQ.js} +1 -1
  103. package/dist/web/assets/{wardleyDiagram-IVAIDKWA-DpG2rl09.js → wardleyDiagram-IVAIDKWA-CE6OR9hA.js} +1 -1
  104. package/dist/web/assets/{xychartDiagram-4URNHDU4-5a7LnsSZ.js → xychartDiagram-4URNHDU4-OrFXHVc6.js} +1 -1
  105. package/dist/web/index.html +2 -2
  106. package/package.json +3 -3
  107. package/dist/web/assets/channel-CV6Myu73.js +0 -1
  108. package/dist/web/assets/flowDiagram-IUGLLWBU-CiUTloqN.js +0 -1
  109. package/dist/web/assets/index-DYwdlB-_.js +0 -142
  110. package/dist/web/assets/index-TP24ydrn.css +0 -1
  111. package/dist/web/assets/swimlanesDiagram-AYQRV4AK-DJ90Jhqq.js +0 -8
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/server/db/schema.ts"],
4
- "sourcesContent": ["import { sql } from 'drizzle-orm';\nimport {\n check,\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n uniqueIndex,\n} from 'drizzle-orm/sqlite-core';\nimport type { ApiError } from '../../shared/types.js';\n\nexport const operations = sqliteTable(\n 'operations',\n {\n clientOperationId: text('client_operation_id').primaryKey(),\n kind: text('kind').notNull(),\n target: text('target').notNull(),\n projectId: text('project_id'),\n requestDigest: text('request_digest').notNull(),\n state: text('state', {\n enum: ['accepted', 'dispatching', 'acknowledged', 'failed', 'unknown'],\n }).notNull(),\n result: text('result', { mode: 'json' }).$type<unknown>(),\n error: text('error', { mode: 'json' }).$type<ApiError>(),\n createdAt: integer('created_at').notNull(),\n updatedAt: integer('updated_at').notNull(),\n reconciledAt: integer('reconciled_at'),\n reconciliationDecision: text('reconciliation_decision'),\n },\n (table) => [\n check(\n 'operations_state_check',\n sql`${table.state} in ('accepted', 'dispatching', 'acknowledged', 'failed', 'unknown')`,\n ),\n index('operations_state_idx').on(table.state),\n ],\n);\n\nexport const executionMarkers = sqliteTable(\n 'execution_markers',\n {\n operationId: text('operation_id')\n .primaryKey()\n .references(() => operations.clientOperationId),\n threadId: text('thread_id').notNull(),\n turnId: text('turn_id'),\n workspaceKey: text('workspace_key').notNull(),\n codexEpoch: text('codex_epoch').notNull(),\n state: text('state', { enum: ['active', 'unknown', 'terminal', 'reconciled'] }).notNull(),\n createdAt: integer('created_at').notNull(),\n endedAt: integer('ended_at'),\n reconciledAt: integer('reconciled_at'),\n reconciliationOperationId: text('reconciliation_operation_id').references(\n () => operations.clientOperationId,\n ),\n },\n (table) => [\n check(\n 'execution_markers_state_check',\n sql`${table.state} in ('active', 'unknown', 'terminal', 'reconciled')`,\n ),\n uniqueIndex('execution_markers_active_thread')\n .on(table.threadId)\n .where(sql`${table.endedAt} is null`),\n ],\n);\n\nexport const threadLinks = sqliteTable('thread_links', {\n threadId: text('thread_id').primaryKey(),\n projectId: text('project_id').notNull(),\n cwd: text('cwd').notNull(),\n source: text('source').notNull(),\n managedEpoch: text('managed_epoch'),\n updatedAt: integer('updated_at').notNull(),\n});\n\nexport const preferences = sqliteTable('preferences', {\n key: text('key').primaryKey(),\n value: text('value', { mode: 'json' }).$type<unknown>().notNull(),\n});\n\n/** Locally observed turn totals; upstream turn history does not include token usage. */\nexport const turnUsage = sqliteTable(\n 'turn_usage',\n {\n threadId: text('thread_id').notNull(),\n turnId: text('turn_id').notNull(),\n outputTokens: integer('output_tokens').notNull(),\n },\n (table) => [primaryKey({ columns: [table.threadId, table.turnId] })],\n);\n\n/** Removing a registration retains its identity and all existing thread links. */\nexport const projectRegistrations = sqliteTable('project_registrations', {\n id: text('id').primaryKey(),\n name: text('name').notNull(),\n path: text('path').notNull(),\n canonicalRoot: text('canonical_root'),\n removedAt: integer('removed_at'),\n createdAt: integer('created_at').notNull(),\n updatedAt: integer('updated_at').notNull(),\n});\n"],
5
- "mappings": "AAAA,SAAS,WAAW;AACpB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGA,MAAM,aAAa;AAAA,EACxB;AAAA,EACA;AAAA,IACE,mBAAmB,KAAK,qBAAqB,EAAE,WAAW;AAAA,IAC1D,MAAM,KAAK,MAAM,EAAE,QAAQ;AAAA,IAC3B,QAAQ,KAAK,QAAQ,EAAE,QAAQ;AAAA,IAC/B,WAAW,KAAK,YAAY;AAAA,IAC5B,eAAe,KAAK,gBAAgB,EAAE,QAAQ;AAAA,IAC9C,OAAO,KAAK,SAAS;AAAA,MACnB,MAAM,CAAC,YAAY,eAAe,gBAAgB,UAAU,SAAS;AAAA,IACvE,CAAC,EAAE,QAAQ;AAAA,IACX,QAAQ,KAAK,UAAU,EAAE,MAAM,OAAO,CAAC,EAAE,MAAe;AAAA,IACxD,OAAO,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC,EAAE,MAAgB;AAAA,IACvD,WAAW,QAAQ,YAAY,EAAE,QAAQ;AAAA,IACzC,WAAW,QAAQ,YAAY,EAAE,QAAQ;AAAA,IACzC,cAAc,QAAQ,eAAe;AAAA,IACrC,wBAAwB,KAAK,yBAAyB;AAAA,EACxD;AAAA,EACA,CAAC,UAAU;AAAA,IACT;AAAA,MACE;AAAA,MACA,MAAM,MAAM,KAAK;AAAA,IACnB;AAAA,IACA,MAAM,sBAAsB,EAAE,GAAG,MAAM,KAAK;AAAA,EAC9C;AACF;AAEO,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,IACE,aAAa,KAAK,cAAc,EAC7B,WAAW,EACX,WAAW,MAAM,WAAW,iBAAiB;AAAA,IAChD,UAAU,KAAK,WAAW,EAAE,QAAQ;AAAA,IACpC,QAAQ,KAAK,SAAS;AAAA,IACtB,cAAc,KAAK,eAAe,EAAE,QAAQ;AAAA,IAC5C,YAAY,KAAK,aAAa,EAAE,QAAQ;AAAA,IACxC,OAAO,KAAK,SAAS,EAAE,MAAM,CAAC,UAAU,WAAW,YAAY,YAAY,EAAE,CAAC,EAAE,QAAQ;AAAA,IACxF,WAAW,QAAQ,YAAY,EAAE,QAAQ;AAAA,IACzC,SAAS,QAAQ,UAAU;AAAA,IAC3B,cAAc,QAAQ,eAAe;AAAA,IACrC,2BAA2B,KAAK,6BAA6B,EAAE;AAAA,MAC7D,MAAM,WAAW;AAAA,IACnB;AAAA,EACF;AAAA,EACA,CAAC,UAAU;AAAA,IACT;AAAA,MACE;AAAA,MACA,MAAM,MAAM,KAAK;AAAA,IACnB;AAAA,IACA,YAAY,iCAAiC,EAC1C,GAAG,MAAM,QAAQ,EACjB,MAAM,MAAM,MAAM,OAAO,UAAU;AAAA,EACxC;AACF;AAEO,MAAM,cAAc,YAAY,gBAAgB;AAAA,EACrD,UAAU,KAAK,WAAW,EAAE,WAAW;AAAA,EACvC,WAAW,KAAK,YAAY,EAAE,QAAQ;AAAA,EACtC,KAAK,KAAK,KAAK,EAAE,QAAQ;AAAA,EACzB,QAAQ,KAAK,QAAQ,EAAE,QAAQ;AAAA,EAC/B,cAAc,KAAK,eAAe;AAAA,EAClC,WAAW,QAAQ,YAAY,EAAE,QAAQ;AAC3C,CAAC;AAEM,MAAM,cAAc,YAAY,eAAe;AAAA,EACpD,KAAK,KAAK,KAAK,EAAE,WAAW;AAAA,EAC5B,OAAO,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC,EAAE,MAAe,EAAE,QAAQ;AAClE,CAAC;AAGM,MAAM,YAAY;AAAA,EACvB;AAAA,EACA;AAAA,IACE,UAAU,KAAK,WAAW,EAAE,QAAQ;AAAA,IACpC,QAAQ,KAAK,SAAS,EAAE,QAAQ;AAAA,IAChC,cAAc,QAAQ,eAAe,EAAE,QAAQ;AAAA,EACjD;AAAA,EACA,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,CAAC,MAAM,UAAU,MAAM,MAAM,EAAE,CAAC,CAAC;AACrE;AAGO,MAAM,uBAAuB,YAAY,yBAAyB;AAAA,EACvE,IAAI,KAAK,IAAI,EAAE,WAAW;AAAA,EAC1B,MAAM,KAAK,MAAM,EAAE,QAAQ;AAAA,EAC3B,MAAM,KAAK,MAAM,EAAE,QAAQ;AAAA,EAC3B,eAAe,KAAK,gBAAgB;AAAA,EACpC,WAAW,QAAQ,YAAY;AAAA,EAC/B,WAAW,QAAQ,YAAY,EAAE,QAAQ;AAAA,EACzC,WAAW,QAAQ,YAAY,EAAE,QAAQ;AAC3C,CAAC;",
4
+ "sourcesContent": ["import { sql } from 'drizzle-orm';\nimport {\n check,\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n uniqueIndex,\n} from 'drizzle-orm/sqlite-core';\nimport type { ApiError } from '../../shared/types.js';\n\nexport const operations = sqliteTable(\n 'operations',\n {\n clientOperationId: text('client_operation_id').primaryKey(),\n kind: text('kind').notNull(),\n target: text('target').notNull(),\n projectId: text('project_id'),\n requestDigest: text('request_digest').notNull(),\n state: text('state', {\n enum: ['accepted', 'dispatching', 'acknowledged', 'failed', 'unknown'],\n }).notNull(),\n result: text('result', { mode: 'json' }).$type<unknown>(),\n error: text('error', { mode: 'json' }).$type<ApiError>(),\n createdAt: integer('created_at').notNull(),\n updatedAt: integer('updated_at').notNull(),\n reconciledAt: integer('reconciled_at'),\n reconciliationDecision: text('reconciliation_decision'),\n },\n (table) => [\n check(\n 'operations_state_check',\n sql`${table.state} in ('accepted', 'dispatching', 'acknowledged', 'failed', 'unknown')`,\n ),\n index('operations_state_idx').on(table.state),\n ],\n);\n\nexport const executionMarkers = sqliteTable(\n 'execution_markers',\n {\n operationId: text('operation_id')\n .primaryKey()\n .references(() => operations.clientOperationId),\n threadId: text('thread_id').notNull(),\n turnId: text('turn_id'),\n workspaceKey: text('workspace_key').notNull(),\n codexEpoch: text('codex_epoch').notNull(),\n state: text('state', { enum: ['active', 'unknown', 'terminal', 'reconciled'] }).notNull(),\n createdAt: integer('created_at').notNull(),\n endedAt: integer('ended_at'),\n reconciledAt: integer('reconciled_at'),\n reconciliationOperationId: text('reconciliation_operation_id').references(\n () => operations.clientOperationId,\n ),\n },\n (table) => [\n check(\n 'execution_markers_state_check',\n sql`${table.state} in ('active', 'unknown', 'terminal', 'reconciled')`,\n ),\n uniqueIndex('execution_markers_active_thread')\n .on(table.threadId)\n .where(sql`${table.endedAt} is null`),\n ],\n);\n\nexport const threadLinks = sqliteTable('thread_links', {\n threadId: text('thread_id').primaryKey(),\n projectId: text('project_id'),\n cwd: text('cwd').notNull(),\n source: text('source').notNull(),\n managedEpoch: text('managed_epoch'),\n updatedAt: integer('updated_at').notNull(),\n});\n\n/** Allocations survive failed/unknown RPCs; names and archive state remain in Codex. */\nexport const sessionWorkspaces = sqliteTable('session_workspaces', {\n operationId: text('operation_id').primaryKey(),\n threadId: text('thread_id').unique(),\n rootPath: text('root_path').notNull(),\n canonicalRoot: text('canonical_root').notNull().unique(),\n createdAt: integer('created_at').notNull(),\n});\n\nexport const preferences = sqliteTable('preferences', {\n key: text('key').primaryKey(),\n value: text('value', { mode: 'json' }).$type<unknown>().notNull(),\n});\n\n/** Locally observed turn totals; upstream turn history does not include token usage. */\nexport const turnUsage = sqliteTable(\n 'turn_usage',\n {\n threadId: text('thread_id').notNull(),\n turnId: text('turn_id').notNull(),\n outputTokens: integer('output_tokens').notNull(),\n },\n (table) => [primaryKey({ columns: [table.threadId, table.turnId] })],\n);\n\n/** Removing a registration retains its identity and all existing thread links. */\nexport const projectRegistrations = sqliteTable('project_registrations', {\n id: text('id').primaryKey(),\n name: text('name').notNull(),\n path: text('path').notNull(),\n canonicalRoot: text('canonical_root'),\n removedAt: integer('removed_at'),\n createdAt: integer('created_at').notNull(),\n updatedAt: integer('updated_at').notNull(),\n});\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -131,6 +131,31 @@ function createApp({
131
131
  return c.json(op, status(op));
132
132
  });
133
133
  app.get("/api/projects", async (c) => c.json({ data: await service.listProjects() }));
134
+ app.get(
135
+ "/api/unassigned/runtime-settings",
136
+ async (c) => c.json(await service.readRuntimeSettings(null))
137
+ );
138
+ app.post("/api/unassigned/model-defaults", async (c) => {
139
+ const op = await service.saveModelDefaults(
140
+ null,
141
+ await parse(c, schemas.saveModelDefaultsSchema)
142
+ );
143
+ return c.json(op, status(op));
144
+ });
145
+ app.get(
146
+ "/api/unassigned/threads",
147
+ async (c) => c.json(
148
+ await service.listThreadSummaries(
149
+ null,
150
+ c.req.query("cursor") === void 0 ? void 0 : schemas.cursorSchema.parse(c.req.query("cursor")),
151
+ schemas.archivedQuerySchema.parse(c.req.query("archived"))
152
+ )
153
+ )
154
+ );
155
+ app.post("/api/unassigned/threads", async (c) => {
156
+ const op = await service.createThread(null, await parse(c, schemas.createThreadSchema));
157
+ return c.json(op, status(op));
158
+ });
134
159
  app.get(
135
160
  "/api/projects/:projectId/runtime-settings",
136
161
  async (c) => c.json(await service.readRuntimeSettings(id(c.req.param("projectId"))))
@@ -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/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 { 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.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
  }
@@ -25,7 +25,7 @@ function temporaryFileRoots() {
25
25
  function outsideProject(policy) {
26
26
  return new AppError(
27
27
  `${policy.code}_OUTSIDE_PROJECT`,
28
- `\u53EA\u80FD\u9884\u89C8\u5F53\u524D\u4F1A\u8BDD\u6240\u5C5E\u9879\u76EE\u6216\u670D\u52A1\u5668\u4E34\u65F6\u76EE\u5F55\u5185\u7684${policy.label}`,
28
+ `\u53EA\u80FD\u9884\u89C8\u5F53\u524D\u4F1A\u8BDD\u5DE5\u4F5C\u533A\u6216\u5141\u8BB8\u7684\u670D\u52A1\u5668\u4E34\u65F6\u76EE\u5F55\u5185\u7684${policy.label}`,
29
29
  403
30
30
  );
31
31
  }
@@ -42,7 +42,7 @@ async function readLocalFile(path, scope, policy) {
42
42
  (root) => containsPath(root.canonicalRoot, candidate) || root.aliases.some((alias) => containsPath(alias, candidate))
43
43
  ))
44
44
  throw outsideProject(policy);
45
- const isAllowed = (path2) => scope.roots.some((root) => containsPath(root.canonicalRoot, path2));
45
+ const isAllowed = (path2) => !scope.excludedRoots?.some((root) => containsPath(root, path2)) && scope.roots.some((root) => containsPath(root.canonicalRoot, path2));
46
46
  policy.validatePath(candidate);
47
47
  try {
48
48
  const canonical = await realpath(candidate);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/server/local-files.ts"],
4
- "sourcesContent": ["import { constants, realpathSync, statSync } from 'node:fs';\nimport { open, realpath, stat } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { isAbsolute, parse, resolve } from 'node:path';\nimport { AppError } from '../shared/errors.js';\nimport { containsPath } from './projects.js';\n\nexport interface FileRoot {\n canonicalRoot: string;\n aliases: string[];\n}\n\nexport interface FileScope {\n cwd: string;\n roots: readonly FileRoot[];\n}\n\n/** Capture server-owned roots once; clients cannot nominate a temporary directory. */\nexport function temporaryFileRoots(): FileRoot[] {\n const roots = new Map<string, FileRoot>();\n for (const directory of [tmpdir(), ...(process.platform === 'win32' ? [] : ['/tmp'])]) {\n if (!isAbsolute(directory)) continue;\n const alias = resolve(directory);\n if (alias === parse(alias).root) continue;\n try {\n const canonicalRoot = realpathSync(alias);\n if (canonicalRoot === parse(canonicalRoot).root || !statSync(canonicalRoot).isDirectory())\n continue;\n const root = roots.get(canonicalRoot) ?? { canonicalRoot, aliases: [] };\n if (!root.aliases.includes(alias)) root.aliases.push(alias);\n roots.set(canonicalRoot, root);\n } catch {\n // Unavailable temp locations do not prevent previews in the remaining roots.\n }\n }\n return [...roots.values()];\n}\n\ninterface FilePolicy {\n code: 'IMAGE' | 'MARKDOWN' | 'JSON';\n label: string;\n maxBytes: number;\n sizeError: string;\n validatePath: (path: string) => void;\n}\n\nfunction outsideProject(policy: FilePolicy): AppError {\n return new AppError(\n `${policy.code}_OUTSIDE_PROJECT`,\n `\u53EA\u80FD\u9884\u89C8\u5F53\u524D\u4F1A\u8BDD\u6240\u5C5E\u9879\u76EE\u6216\u670D\u52A1\u5668\u4E34\u65F6\u76EE\u5F55\u5185\u7684${policy.label}`,\n 403,\n );\n}\n\nfunction changedFile(policy: FilePolicy): AppError {\n return new AppError(`${policy.code}_CHANGED`, `${policy.label}\u6587\u4EF6\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u9884\u89C8`, 409);\n}\n\n/** Shared project/temp authorization and bounded, verified file reads for previews. */\nexport async function readLocalFile(\n path: string | undefined,\n scope: FileScope,\n policy: FilePolicy,\n) {\n if (\n !path ||\n path.length > 4096 ||\n [...path].some(\n (character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127,\n ) ||\n /^[a-z][a-z\\d+.-]*:/i.test(path) ||\n path.startsWith('//') ||\n path.startsWith('\\\\\\\\')\n )\n throw new AppError(`INVALID_${policy.code}_PATH`, `${policy.label}\u8DEF\u5F84\u65E0\u6548`, 400);\n\n const candidate = resolve(scope.cwd, path);\n // Both spellings matter on systems where /tmp or the registered directory is an alias.\n if (\n !scope.roots.some(\n (root) =>\n containsPath(root.canonicalRoot, candidate) ||\n root.aliases.some((alias) => containsPath(alias, candidate)),\n )\n )\n throw outsideProject(policy);\n const isAllowed = (path: string) =>\n scope.roots.some((root) => containsPath(root.canonicalRoot, path));\n policy.validatePath(candidate);\n\n try {\n const canonical = await realpath(candidate);\n if (!isAllowed(canonical)) throw outsideProject(policy);\n // NOFOLLOW rejects a last-component symlink swapped in after realpath. NONBLOCK\n // ensures opening a substituted FIFO cannot leave the request waiting forever.\n const file = await open(\n canonical,\n constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,\n );\n try {\n const before = await file.stat();\n if (!before.isFile())\n throw new AppError(`${policy.code}_NOT_FILE`, `${policy.label}\u8DEF\u5F84\u4E0D\u662F\u666E\u901A\u6587\u4EF6`, 415);\n if (before.size > policy.maxBytes)\n throw new AppError(`${policy.code}_TOO_LARGE`, policy.sizeError, 413);\n\n // Recheck the path and opened inode to detect ordinary concurrent replacements.\n // Node's portable file API cannot make parent-directory traversal race-free.\n const verifyPath = async () => {\n const current = await realpath(candidate);\n if (!isAllowed(current)) throw outsideProject(policy);\n if (current !== canonical) throw changedFile(policy);\n const currentStat = await stat(current);\n if (currentStat.dev !== before.dev || currentStat.ino !== before.ino)\n throw changedFile(policy);\n };\n await verifyPath();\n // One extra byte detects growth without letting readFile allocate unbounded data.\n const data = Buffer.alloc(before.size + 1);\n let length = 0;\n while (length < data.length) {\n const { bytesRead } = await file.read(data, length, data.length - length, length);\n if (!bytesRead) break;\n length += bytesRead;\n }\n if (length > policy.maxBytes)\n throw new AppError(`${policy.code}_TOO_LARGE`, policy.sizeError, 413);\n const after = await file.stat();\n if (length !== before.size || after.size !== before.size || after.mtimeMs !== before.mtimeMs)\n throw changedFile(policy);\n await verifyPath();\n const bytes = data.subarray(0, length);\n return { bytes, path: canonical };\n } finally {\n await file.close();\n }\n } catch (error) {\n if (error instanceof AppError) throw error;\n const code = (error as NodeJS.ErrnoException).code;\n if (code === 'ENOENT' || code === 'ENOTDIR')\n throw new AppError(`${policy.code}_NOT_FOUND`, `${policy.label}\u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664`, 404);\n if (code === 'ELOOP') throw outsideProject(policy);\n throw new AppError(`${policy.code}_UNREADABLE`, `${policy.label}\u6587\u4EF6\u4E0D\u53EF\u8BFB\u53D6`, 403);\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { constants, realpathSync, statSync } from 'node:fs';\nimport { open, realpath, stat } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { isAbsolute, parse, resolve } from 'node:path';\nimport { AppError } from '../shared/errors.js';\nimport { containsPath } from './projects.js';\n\nexport interface FileRoot {\n canonicalRoot: string;\n aliases: string[];\n}\n\nexport interface FileScope {\n cwd: string;\n roots: readonly FileRoot[];\n excludedRoots?: readonly string[];\n}\n\n/** Capture server-owned roots once; clients cannot nominate a temporary directory. */\nexport function temporaryFileRoots(): FileRoot[] {\n const roots = new Map<string, FileRoot>();\n for (const directory of [tmpdir(), ...(process.platform === 'win32' ? [] : ['/tmp'])]) {\n if (!isAbsolute(directory)) continue;\n const alias = resolve(directory);\n if (alias === parse(alias).root) continue;\n try {\n const canonicalRoot = realpathSync(alias);\n if (canonicalRoot === parse(canonicalRoot).root || !statSync(canonicalRoot).isDirectory())\n continue;\n const root = roots.get(canonicalRoot) ?? { canonicalRoot, aliases: [] };\n if (!root.aliases.includes(alias)) root.aliases.push(alias);\n roots.set(canonicalRoot, root);\n } catch {\n // Unavailable temp locations do not prevent previews in the remaining roots.\n }\n }\n return [...roots.values()];\n}\n\ninterface FilePolicy {\n code: 'IMAGE' | 'MARKDOWN' | 'JSON';\n label: string;\n maxBytes: number;\n sizeError: string;\n validatePath: (path: string) => void;\n}\n\nfunction outsideProject(policy: FilePolicy): AppError {\n return new AppError(\n `${policy.code}_OUTSIDE_PROJECT`,\n `\u53EA\u80FD\u9884\u89C8\u5F53\u524D\u4F1A\u8BDD\u5DE5\u4F5C\u533A\u6216\u5141\u8BB8\u7684\u670D\u52A1\u5668\u4E34\u65F6\u76EE\u5F55\u5185\u7684${policy.label}`,\n 403,\n );\n}\n\nfunction changedFile(policy: FilePolicy): AppError {\n return new AppError(`${policy.code}_CHANGED`, `${policy.label}\u6587\u4EF6\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u9884\u89C8`, 409);\n}\n\n/** Shared project/temp authorization and bounded, verified file reads for previews. */\nexport async function readLocalFile(\n path: string | undefined,\n scope: FileScope,\n policy: FilePolicy,\n) {\n if (\n !path ||\n path.length > 4096 ||\n [...path].some(\n (character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127,\n ) ||\n /^[a-z][a-z\\d+.-]*:/i.test(path) ||\n path.startsWith('//') ||\n path.startsWith('\\\\\\\\')\n )\n throw new AppError(`INVALID_${policy.code}_PATH`, `${policy.label}\u8DEF\u5F84\u65E0\u6548`, 400);\n\n const candidate = resolve(scope.cwd, path);\n // Both spellings matter on systems where /tmp or the registered directory is an alias.\n if (\n !scope.roots.some(\n (root) =>\n containsPath(root.canonicalRoot, candidate) ||\n root.aliases.some((alias) => containsPath(alias, candidate)),\n )\n )\n throw outsideProject(policy);\n const isAllowed = (path: string) =>\n !scope.excludedRoots?.some((root) => containsPath(root, path)) &&\n scope.roots.some((root) => containsPath(root.canonicalRoot, path));\n policy.validatePath(candidate);\n\n try {\n const canonical = await realpath(candidate);\n if (!isAllowed(canonical)) throw outsideProject(policy);\n // NOFOLLOW rejects a last-component symlink swapped in after realpath. NONBLOCK\n // ensures opening a substituted FIFO cannot leave the request waiting forever.\n const file = await open(\n canonical,\n constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,\n );\n try {\n const before = await file.stat();\n if (!before.isFile())\n throw new AppError(`${policy.code}_NOT_FILE`, `${policy.label}\u8DEF\u5F84\u4E0D\u662F\u666E\u901A\u6587\u4EF6`, 415);\n if (before.size > policy.maxBytes)\n throw new AppError(`${policy.code}_TOO_LARGE`, policy.sizeError, 413);\n\n // Recheck the path and opened inode to detect ordinary concurrent replacements.\n // Node's portable file API cannot make parent-directory traversal race-free.\n const verifyPath = async () => {\n const current = await realpath(candidate);\n if (!isAllowed(current)) throw outsideProject(policy);\n if (current !== canonical) throw changedFile(policy);\n const currentStat = await stat(current);\n if (currentStat.dev !== before.dev || currentStat.ino !== before.ino)\n throw changedFile(policy);\n };\n await verifyPath();\n // One extra byte detects growth without letting readFile allocate unbounded data.\n const data = Buffer.alloc(before.size + 1);\n let length = 0;\n while (length < data.length) {\n const { bytesRead } = await file.read(data, length, data.length - length, length);\n if (!bytesRead) break;\n length += bytesRead;\n }\n if (length > policy.maxBytes)\n throw new AppError(`${policy.code}_TOO_LARGE`, policy.sizeError, 413);\n const after = await file.stat();\n if (length !== before.size || after.size !== before.size || after.mtimeMs !== before.mtimeMs)\n throw changedFile(policy);\n await verifyPath();\n const bytes = data.subarray(0, length);\n return { bytes, path: canonical };\n } finally {\n await file.close();\n }\n } catch (error) {\n if (error instanceof AppError) throw error;\n const code = (error as NodeJS.ErrnoException).code;\n if (code === 'ENOENT' || code === 'ENOTDIR')\n throw new AppError(`${policy.code}_NOT_FOUND`, `${policy.label}\u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664`, 404);\n if (code === 'ELOOP') throw outsideProject(policy);\n throw new AppError(`${policy.code}_UNREADABLE`, `${policy.label}\u6587\u4EF6\u4E0D\u53EF\u8BFB\u53D6`, 403);\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["path"]
7
7
  }
@@ -32,6 +32,7 @@ async function startGateway(config, overrides = {}) {
32
32
  store: new OperationStore(db.database),
33
33
  projects: new ProjectRegistry(config.projects, db.database),
34
34
  codex,
35
+ workspacesRoot: join(config.dataDir, "workspaces"),
35
36
  limits: config.limits,
36
37
  authMode: config.auth.mode,
37
38
  demo: config.demo
@@ -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 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 { 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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",
6
6
  "names": []
7
7
  }