@covro/covro 0.6.1-dev.2 → 0.6.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 (126) hide show
  1. package/README.md +3 -3
  2. package/README.zh-CN.md +3 -3
  3. package/dist/cli/background.js +10 -7
  4. package/dist/cli/background.js.map +2 -2
  5. package/dist/cli/daemon.js +3 -1
  6. package/dist/cli/daemon.js.map +2 -2
  7. package/dist/cli/launch-environment.js +5 -2
  8. package/dist/cli/launch-environment.js.map +2 -2
  9. package/dist/cli/launchd.js +14 -8
  10. package/dist/cli/launchd.js.map +2 -2
  11. package/dist/cli/runtime-launch.js +108 -0
  12. package/dist/cli/runtime-launch.js.map +7 -0
  13. package/dist/cli/runtime.js +12 -0
  14. package/dist/cli/runtime.js.map +7 -0
  15. package/dist/cli/service.js +7 -4
  16. package/dist/cli/service.js.map +2 -2
  17. package/dist/codex/account-usage.js +132 -0
  18. package/dist/codex/account-usage.js.map +7 -0
  19. package/dist/codex/adapter.js +31 -2
  20. package/dist/codex/adapter.js.map +2 -2
  21. package/dist/server/http.js +4 -0
  22. package/dist/server/http.js.map +2 -2
  23. package/dist/server/service.js +11 -0
  24. package/dist/server/service.js.map +2 -2
  25. package/dist/shared/account-usage.js +1 -0
  26. package/dist/shared/account-usage.js.map +7 -0
  27. package/dist/shared/updates.js.map +2 -2
  28. package/dist/update-worker.cjs +1111 -754
  29. package/dist/updates/manager.js +89 -8
  30. package/dist/updates/manager.js.map +2 -2
  31. package/dist/updates/registry.js +7 -6
  32. package/dist/updates/registry.js.map +2 -2
  33. package/dist/updates/runtime.js +183 -0
  34. package/dist/updates/runtime.js.map +7 -0
  35. package/dist/updates/transaction.js +8 -4
  36. package/dist/updates/transaction.js.map +2 -2
  37. package/dist/updates/worker.js +177 -112
  38. package/dist/updates/worker.js.map +3 -3
  39. package/dist/web/assets/{abnfDiagram-WEYOIA3C-B0iAbIJD.js → abnfDiagram-WEYOIA3C--q3UKu-m.js} +1 -1
  40. package/dist/web/assets/{arc-_f1LafPd.js → arc-CsDLrA4o.js} +1 -1
  41. package/dist/web/assets/{architecture-WOLXFQ4H-BV5w3tVT.js → architecture-WOLXFQ4H-6TbwoUek.js} +1 -1
  42. package/dist/web/assets/{architectureDiagram-ZHVYKT53-DQYsHq3i.js → architectureDiagram-ZHVYKT53-GNeotXgT.js} +1 -1
  43. package/dist/web/assets/{blockDiagram-RJAE7QA3-D9T-XyZU.js → blockDiagram-RJAE7QA3-Ric8Njom.js} +1 -1
  44. package/dist/web/assets/{c4Diagram-XDPPPE54-DkRcrPuT.js → c4Diagram-XDPPPE54-CSFzq9_N.js} +1 -1
  45. package/dist/web/assets/channel-M3Agpi7p.js +1 -0
  46. package/dist/web/assets/{chunk-2E7WHVMD-js9pPyj7.js → chunk-2E7WHVMD-BwjaS8bo.js} +1 -1
  47. package/dist/web/assets/{chunk-4EMNKR2T-BPnIvGHL.js → chunk-4EMNKR2T-V38rR2JO.js} +1 -1
  48. package/dist/web/assets/{chunk-55XCU76K-DpLWtH9r.js → chunk-55XCU76K-DjF4oGX1.js} +1 -1
  49. package/dist/web/assets/{chunk-7S6XSTFO-jncPoxbX.js → chunk-7S6XSTFO-5YHKdb3u.js} +1 -1
  50. package/dist/web/assets/{chunk-AQDTSKZB-B_gC3lpG.js → chunk-AQDTSKZB-BGqebfJY.js} +1 -1
  51. package/dist/web/assets/{chunk-DSNLSHJZ-CPeooTRp.js → chunk-DSNLSHJZ-DoWMycRk.js} +1 -1
  52. package/dist/web/assets/{chunk-HAGFOTED-BdUSIss4.js → chunk-HAGFOTED-D23fXc2S.js} +1 -1
  53. package/dist/web/assets/{chunk-HNE4Q36P-C2eo7jyz.js → chunk-HNE4Q36P-BIJsRvPs.js} +1 -1
  54. package/dist/web/assets/{chunk-NQOKRVIF-Q6aWCxNr.js → chunk-NQOKRVIF-C54OjZSl.js} +1 -1
  55. package/dist/web/assets/{chunk-UHW7PFBP-BxE-7sbq.js → chunk-UHW7PFBP-C0X5au9W.js} +1 -1
  56. package/dist/web/assets/{chunk-VQ5W62QI-DRBDdftN.js → chunk-VQ5W62QI-C2vDy1Kl.js} +1 -1
  57. package/dist/web/assets/{chunk-WQQL4CDK-clrsIIlY.js → chunk-WQQL4CDK-CcesvmQO.js} +1 -1
  58. package/dist/web/assets/{chunk-XXDRQBXY-5PCgXvkc.js → chunk-XXDRQBXY-EiI0PYcn.js} +1 -1
  59. package/dist/web/assets/{chunk-YZO67HFG-6j9ve5_L.js → chunk-YZO67HFG-BqeaVf9n.js} +1 -1
  60. package/dist/web/assets/{chunk-ZAUX2LTX-CvFQwbwM.js → chunk-ZAUX2LTX-DW6sEeTI.js} +1 -1
  61. package/dist/web/assets/{chunk-ZCHMQSOR-CZOEs70I.js → chunk-ZCHMQSOR-BrlOBygH.js} +1 -1
  62. package/dist/web/assets/{classDiagram-v2-4MYWR3UA-BTkqkHXl.js → classDiagram-v2-4MYWR3UA-DFpCrr_A.js} +1 -1
  63. package/dist/web/assets/{cose-bilkent-JH36ORCC-BqWP1nzQ.js → cose-bilkent-JH36ORCC-CAWPSnN6.js} +1 -1
  64. package/dist/web/assets/{cynefin-EF2NZ3EQ-DsU4q5qS.js → cynefin-EF2NZ3EQ-DMeYqL7r.js} +1 -1
  65. package/dist/web/assets/{cynefinDiagram-WF24UDRP-COjozWKq.js → cynefinDiagram-WF24UDRP-DI-bFsxF.js} +1 -1
  66. package/dist/web/assets/{dagre-NK4GIZVX-BDHt1Ueh.js → dagre-NK4GIZVX-CdoitF7O.js} +1 -1
  67. package/dist/web/assets/{diagram-CBK3MWTC-D7aiLN-_.js → diagram-CBK3MWTC-DVTPnBLF.js} +1 -1
  68. package/dist/web/assets/{diagram-I5XIIV2D-0-EaMqOJ.js → diagram-I5XIIV2D-3eS1TE4r.js} +1 -1
  69. package/dist/web/assets/{diagram-ODIL2UCW-GSzs8w0Z.js → diagram-ODIL2UCW-cLU1ehlH.js} +1 -1
  70. package/dist/web/assets/{diagram-PFBEJUXE-D35fg8hx.js → diagram-PFBEJUXE-Bd1TAqaL.js} +1 -1
  71. package/dist/web/assets/{diagram-RJA3I4VV-DwwCuIEC.js → diagram-RJA3I4VV-CQqVlBOF.js} +1 -1
  72. package/dist/web/assets/{diagram-TYUNFSNR-DG6l9ew-.js → diagram-TYUNFSNR-CCGCiVOv.js} +1 -1
  73. package/dist/web/assets/{dist-zdlJtNPK.js → dist-BE4VEq-n.js} +1 -1
  74. package/dist/web/assets/{ebnfDiagram-V4P3TTPT-Bgfi_isK.js → ebnfDiagram-V4P3TTPT-BGOHdBAS.js} +1 -1
  75. package/dist/web/assets/{elk-QONTBCTQ-BAxMCFNL.js → elk-QONTBCTQ-D5OlAFYO.js} +1 -1
  76. package/dist/web/assets/{erDiagram-KYQIGQAA-D9YhFA2m.js → erDiagram-KYQIGQAA-DUtlMKNi.js} +1 -1
  77. package/dist/web/assets/{eventmodeling-K75KTNOO-8ocfEUPa.js → eventmodeling-K75KTNOO-DXK-D1Z0.js} +1 -1
  78. package/dist/web/assets/flowDiagram-IUGLLWBU-4EVBAMrs.js +1 -0
  79. package/dist/web/assets/{ganttDiagram-R7GPNTJY-BejsR9f5.js → ganttDiagram-R7GPNTJY-BVGsal-Q.js} +1 -1
  80. package/dist/web/assets/{gitGraph-VSP46ZUC-DlgbLMC2.js → gitGraph-VSP46ZUC-DV6-WqhO.js} +1 -1
  81. package/dist/web/assets/{gitGraphDiagram-PDYL7XHY-DpSqjPgo.js → gitGraphDiagram-PDYL7XHY-0QK_COI_.js} +1 -1
  82. package/dist/web/assets/index-BBPzwzxe.js +158 -0
  83. package/dist/web/assets/{index-qYBdGqKM.css → index-CSpioreu.css} +1 -1
  84. package/dist/web/assets/{info-OHQRW6UA-BUmj5tQa.js → info-OHQRW6UA-BZipuOqr.js} +1 -1
  85. package/dist/web/assets/{infoDiagram-MVDRKAX5-BEA3aavs.js → infoDiagram-MVDRKAX5-1db4SZ4k.js} +1 -1
  86. package/dist/web/assets/{ishikawaDiagram-HPEHV2GE-Dir67X2M.js → ishikawaDiagram-HPEHV2GE-DTrI4oTY.js} +1 -1
  87. package/dist/web/assets/{journeyDiagram-BOSHW7O7-BneoTNdl.js → journeyDiagram-BOSHW7O7-Bk5sPpaD.js} +1 -1
  88. package/dist/web/assets/{kanban-definition-FNSA4HC5-44JYQUer.js → kanban-definition-FNSA4HC5-smf99L9V.js} +1 -1
  89. package/dist/web/assets/{line-ByilfiTa.js → line-9F_GFNcI.js} +1 -1
  90. package/dist/web/assets/{linear-Db3eyjwk.js → linear-B80ozVj0.js} +1 -1
  91. package/dist/web/assets/{mermaid-parser.core-DQDrZAv8.js → mermaid-parser.core-DldmXGom.js} +3 -3
  92. package/dist/web/assets/{mermaid.core-DZ0it3bR.js → mermaid.core-DIZvVrdE.js} +4 -4
  93. package/dist/web/assets/{mindmap-definition-6OY57UG3-D1W6AEN6.js → mindmap-definition-6OY57UG3-CLhpt9eO.js} +1 -1
  94. package/dist/web/assets/{packet-JDAUHWVQ-UM3c__bC.js → packet-JDAUHWVQ-CL3Q6msP.js} +1 -1
  95. package/dist/web/assets/{pegDiagram-ECIUJNBX-CcCixVHf.js → pegDiagram-ECIUJNBX-BeBvMY1a.js} +1 -1
  96. package/dist/web/assets/{pie-XZMESJXO-CeA8Ssa1.js → pie-XZMESJXO-D_fdN7qT.js} +1 -1
  97. package/dist/web/assets/{pieDiagram-GNMPY74T-Bs2mtNl_.js → pieDiagram-GNMPY74T-DROrBz0o.js} +1 -1
  98. package/dist/web/assets/{quadrantDiagram-D57K4MC3-Ct6TbdVq.js → quadrantDiagram-D57K4MC3-C57SBgx7.js} +1 -1
  99. package/dist/web/assets/{radar-ABXABTNO-C9-VPFXC.js → radar-ABXABTNO-B0-FyoLn.js} +1 -1
  100. package/dist/web/assets/{railroad-I3PHUGI6-D73j4-mk.js → railroad-I3PHUGI6-_ocCyblF.js} +1 -1
  101. package/dist/web/assets/{railroad-abnf-LNEFI6M7-JUd56ILo.js → railroad-abnf-LNEFI6M7-Ct1oCv45.js} +1 -1
  102. package/dist/web/assets/{railroad-ebnf-DWYD2UWJ-BIHqXOMj.js → railroad-ebnf-DWYD2UWJ-Dz3MdcvL.js} +1 -1
  103. package/dist/web/assets/{railroad-peg-JR7BVNR7-BOucWj1Z.js → railroad-peg-JR7BVNR7-Ds4ONRXC.js} +1 -1
  104. package/dist/web/assets/{railroadDiagram-Y72NRBL7-CFhvojW0.js → railroadDiagram-Y72NRBL7-DqS1adHB.js} +1 -1
  105. package/dist/web/assets/{requirementDiagram-EQYSW5RA-B2CK3ZoL.js → requirementDiagram-EQYSW5RA-BReuC0TK.js} +1 -1
  106. package/dist/web/assets/{sankeyDiagram-SY24JHO5-eZRWWklW.js → sankeyDiagram-SY24JHO5-DDjUr4b9.js} +1 -1
  107. package/dist/web/assets/{sequenceDiagram-BLEHNHQU-Bhav5Cco.js → sequenceDiagram-BLEHNHQU-D71Uv16-.js} +1 -1
  108. package/dist/web/assets/{src-CLPfA06b.js → src-DiejhDC1.js} +1 -1
  109. package/dist/web/assets/{stateDiagram-v2-A6IESKWZ-BKBs6biU.js → stateDiagram-v2-A6IESKWZ-B8w400YH.js} +1 -1
  110. package/dist/web/assets/{swimlanes-B3ENRKFQ-D8lPXnY-.js → swimlanes-B3ENRKFQ-Cx8dbIra.js} +1 -1
  111. package/dist/web/assets/swimlanesDiagram-AYQRV4AK-DLuNBE0x.js +8 -0
  112. package/dist/web/assets/{timeline-definition-JXYKGLGB-PN8NzCdD.js → timeline-definition-JXYKGLGB-wEhTG9mn.js} +1 -1
  113. package/dist/web/assets/{treeView-D4JQ5SDB-CI7xCj5C.js → treeView-D4JQ5SDB-J1xTBv_o.js} +1 -1
  114. package/dist/web/assets/{treemap-SAJKECNS-CeE_hFs2.js → treemap-SAJKECNS-B-HfL4ut.js} +1 -1
  115. package/dist/web/assets/{usecaseDiagram-WPOLBNNX-VqjzJa5e.js → usecaseDiagram-WPOLBNNX-Bqvh0bcu.js} +1 -1
  116. package/dist/web/assets/{vennDiagram-Q3Y3IDCW-BkjF5KAf.js → vennDiagram-Q3Y3IDCW-B2TB6cEs.js} +1 -1
  117. package/dist/web/assets/{wardley-7MLQ67FV-C4QrbQ3q.js → wardley-7MLQ67FV-BF1eXS8d.js} +1 -1
  118. package/dist/web/assets/{wardleyDiagram-IVAIDKWA-DkVR8h8U.js → wardleyDiagram-IVAIDKWA-BZzFLzrU.js} +1 -1
  119. package/dist/web/assets/{xychartDiagram-4URNHDU4-B481vVlR.js → xychartDiagram-4URNHDU4-Dh0JpuLV.js} +1 -1
  120. package/dist/web/index.html +2 -2
  121. package/dist/web/notification-worker.js +33 -0
  122. package/package.json +3 -3
  123. package/dist/web/assets/channel-BUUh2AC8.js +0 -1
  124. package/dist/web/assets/flowDiagram-IUGLLWBU-BKDteYBU.js +0 -1
  125. package/dist/web/assets/index-KWYkfh4F.js +0 -156
  126. package/dist/web/assets/swimlanesDiagram-AYQRV4AK-BrP6D4C7.js +0 -8
@@ -7,8 +7,8 @@ import { stopAndWait } from "./control.js";
7
7
  import { saveJson } from "../updates/files.js";
8
8
  import { ensureConfig, packageRoot } from "./paths.js";
9
9
  import { macOSLoginService } from "./background.js";
10
+ import { launchRuntime, systemdQuote as unit } from "./runtime-launch.js";
10
11
  const exec = promisify(execFile);
11
- const unit = (value) => `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("%", "%%")}"`;
12
12
  async function service(location, install) {
13
13
  if (!["darwin", "linux"].includes(process.platform))
14
14
  throw new Error(
@@ -29,15 +29,18 @@ async function service(location, install) {
29
29
  const filename = join(directory, `${label}.service`);
30
30
  if (install) {
31
31
  await mkdir(directory, { recursive: true });
32
- if (/[\r\n]/.test([entry, location.config, location.home, process.env.PATH].join("")))
32
+ const runtime = await launchRuntime(location, entry);
33
+ if (/[\r\n]/.test(
34
+ [runtime.node, runtime.entry, location.config, location.home, runtime.path].join("")
35
+ ))
33
36
  throw new Error("\u670D\u52A1\u8DEF\u5F84\u548C PATH \u4E0D\u80FD\u5305\u542B\u6362\u884C");
34
37
  await writeFile(
35
38
  filename,
36
39
  `[Unit]
37
40
  Description=Covro
38
41
  [Service]
39
- ExecStart=${[process.execPath, entry, "run", "--config", location.config].map(unit).join(" ")}
40
- Environment=${unit(`COVRO_HOME=${location.home}`)} ${unit(`PATH=${process.env.PATH ?? "/usr/bin:/bin"}`)}
42
+ ExecStart=${[runtime.node, runtime.entry, "run", "--config", location.config].map(unit).join(" ")}
43
+ Environment=${unit(`COVRO_HOME=${location.home}`)} ${unit(`PATH=${runtime.path}`)}
41
44
  Restart=on-failure
42
45
  RestartSec=30
43
46
  [Install]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cli/service.ts"],
4
- "sourcesContent": ["import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { mkdir, rm, writeFile } from 'node:fs/promises';\nimport { stopAndWait } from './control.js';\nimport { saveJson } from '../updates/files.js';\nimport { ensureConfig, packageRoot, type CovroPaths } from './paths.js';\nimport { macOSLoginService } from './background.js';\n\nconst exec = promisify(execFile);\nconst unit = (value: string) =>\n `\"${value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"').replaceAll('%', '%%')}\"`;\n\nexport async function service(location: CovroPaths, install: boolean) {\n if (!['darwin', 'linux'].includes(process.platform))\n throw new Error(\n '\u767B\u5F55\u81EA\u542F\u76EE\u524D\u652F\u6301 macOS launchd \u548C Linux systemd --user\uFF1B\u53EF\u4F7F\u7528 covro start \u540E\u53F0\u8FD0\u884C\u3002',\n );\n const label = `dev.covro.${location.key}`;\n const entry = join(packageRoot, 'bin/covro.mjs');\n if (process.platform === 'darwin') {\n if (install) await ensureConfig(location);\n await macOSLoginService(location, entry, install);\n return;\n }\n if (install) {\n await stopAndWait(location);\n await mkdir(location.state, { recursive: true, mode: 0o700 });\n }\n const directory = join(homedir(), '.config/systemd/user');\n const filename = join(directory, `${label}.service`);\n if (install) {\n await mkdir(directory, { recursive: true });\n if (/[\\r\\n]/.test([entry, location.config, location.home, process.env.PATH].join('')))\n throw new Error('\u670D\u52A1\u8DEF\u5F84\u548C PATH \u4E0D\u80FD\u5305\u542B\u6362\u884C');\n await writeFile(\n filename,\n `[Unit]\\nDescription=Covro\\n[Service]\\nExecStart=${[process.execPath, entry, 'run', '--config', location.config].map(unit).join(' ')}\\nEnvironment=${unit(`COVRO_HOME=${location.home}`)} ${unit(`PATH=${process.env.PATH ?? '/usr/bin:/bin'}`)}\\nRestart=on-failure\\nRestartSec=30\\n[Install]\\nWantedBy=default.target\\n`,\n { mode: 0o600 },\n );\n await exec('systemctl', ['--user', 'daemon-reload']);\n await exec('systemctl', ['--user', 'enable', '--now', `${label}.service`]);\n await saveJson(join(location.state, 'service.json'), { platform: 'linux', label });\n } else {\n await exec('systemctl', ['--user', 'disable', '--now', `${label}.service`]);\n await rm(filename);\n await rm(join(location.state, 'service.json'), { force: true });\n await exec('systemctl', ['--user', 'daemon-reload']);\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,OAAO,IAAI,iBAAiB;AACrC,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB;AACzB,SAAS,cAAc,mBAAoC;AAC3D,SAAS,yBAAyB;AAElC,MAAM,OAAO,UAAU,QAAQ;AAC/B,MAAM,OAAO,CAAC,UACZ,IAAI,MAAM,WAAW,MAAM,MAAM,EAAE,WAAW,KAAK,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;AAEjF,eAAsB,QAAQ,UAAsB,SAAkB;AACpE,MAAI,CAAC,CAAC,UAAU,OAAO,EAAE,SAAS,QAAQ,QAAQ;AAChD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACF,QAAM,QAAQ,aAAa,SAAS,GAAG;AACvC,QAAM,QAAQ,KAAK,aAAa,eAAe;AAC/C,MAAI,QAAQ,aAAa,UAAU;AACjC,QAAI,QAAS,OAAM,aAAa,QAAQ;AACxC,UAAM,kBAAkB,UAAU,OAAO,OAAO;AAChD;AAAA,EACF;AACA,MAAI,SAAS;AACX,UAAM,YAAY,QAAQ;AAC1B,UAAM,MAAM,SAAS,OAAO,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAAA,EAC9D;AACA,QAAM,YAAY,KAAK,QAAQ,GAAG,sBAAsB;AACxD,QAAM,WAAW,KAAK,WAAW,GAAG,KAAK,UAAU;AACnD,MAAI,SAAS;AACX,UAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC1C,QAAI,SAAS,KAAK,CAAC,OAAO,SAAS,QAAQ,SAAS,MAAM,QAAQ,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;AAClF,YAAM,IAAI,MAAM,0EAAmB;AACrC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA;AAAA;AAAA,YAAmD,CAAC,QAAQ,UAAU,OAAO,OAAO,YAAY,SAAS,MAAM,EAAE,IAAI,IAAI,EAAE,KAAK,GAAG,CAAC;AAAA,cAAiB,KAAK,cAAc,SAAS,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,QAAQ,IAAI,QAAQ,eAAe,EAAE,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAC/O,EAAE,MAAM,IAAM;AAAA,IAChB;AACA,UAAM,KAAK,aAAa,CAAC,UAAU,eAAe,CAAC;AACnD,UAAM,KAAK,aAAa,CAAC,UAAU,UAAU,SAAS,GAAG,KAAK,UAAU,CAAC;AACzE,UAAM,SAAS,KAAK,SAAS,OAAO,cAAc,GAAG,EAAE,UAAU,SAAS,MAAM,CAAC;AAAA,EACnF,OAAO;AACL,UAAM,KAAK,aAAa,CAAC,UAAU,WAAW,SAAS,GAAG,KAAK,UAAU,CAAC;AAC1E,UAAM,GAAG,QAAQ;AACjB,UAAM,GAAG,KAAK,SAAS,OAAO,cAAc,GAAG,EAAE,OAAO,KAAK,CAAC;AAC9D,UAAM,KAAK,aAAa,CAAC,UAAU,eAAe,CAAC;AAAA,EACrD;AACF;",
4
+ "sourcesContent": ["import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { mkdir, rm, writeFile } from 'node:fs/promises';\nimport { stopAndWait } from './control.js';\nimport { saveJson } from '../updates/files.js';\nimport { ensureConfig, packageRoot, type CovroPaths } from './paths.js';\nimport { macOSLoginService } from './background.js';\nimport { launchRuntime, systemdQuote as unit } from './runtime-launch.js';\n\nconst exec = promisify(execFile);\n\nexport async function service(location: CovroPaths, install: boolean) {\n if (!['darwin', 'linux'].includes(process.platform))\n throw new Error(\n '\u767B\u5F55\u81EA\u542F\u76EE\u524D\u652F\u6301 macOS launchd \u548C Linux systemd --user\uFF1B\u53EF\u4F7F\u7528 covro start \u540E\u53F0\u8FD0\u884C\u3002',\n );\n const label = `dev.covro.${location.key}`;\n const entry = join(packageRoot, 'bin/covro.mjs');\n if (process.platform === 'darwin') {\n if (install) await ensureConfig(location);\n await macOSLoginService(location, entry, install);\n return;\n }\n if (install) {\n await stopAndWait(location);\n await mkdir(location.state, { recursive: true, mode: 0o700 });\n }\n const directory = join(homedir(), '.config/systemd/user');\n const filename = join(directory, `${label}.service`);\n if (install) {\n await mkdir(directory, { recursive: true });\n const runtime = await launchRuntime(location, entry);\n if (\n /[\\r\\n]/.test(\n [runtime.node, runtime.entry, location.config, location.home, runtime.path].join(''),\n )\n )\n throw new Error('\u670D\u52A1\u8DEF\u5F84\u548C PATH \u4E0D\u80FD\u5305\u542B\u6362\u884C');\n await writeFile(\n filename,\n `[Unit]\\nDescription=Covro\\n[Service]\\nExecStart=${[runtime.node, runtime.entry, 'run', '--config', location.config].map(unit).join(' ')}\\nEnvironment=${unit(`COVRO_HOME=${location.home}`)} ${unit(`PATH=${runtime.path}`)}\\nRestart=on-failure\\nRestartSec=30\\n[Install]\\nWantedBy=default.target\\n`,\n { mode: 0o600 },\n );\n await exec('systemctl', ['--user', 'daemon-reload']);\n await exec('systemctl', ['--user', 'enable', '--now', `${label}.service`]);\n await saveJson(join(location.state, 'service.json'), { platform: 'linux', label });\n } else {\n await exec('systemctl', ['--user', 'disable', '--now', `${label}.service`]);\n await rm(filename);\n await rm(join(location.state, 'service.json'), { force: true });\n await exec('systemctl', ['--user', 'daemon-reload']);\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,OAAO,IAAI,iBAAiB;AACrC,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB;AACzB,SAAS,cAAc,mBAAoC;AAC3D,SAAS,yBAAyB;AAClC,SAAS,eAAe,gBAAgB,YAAY;AAEpD,MAAM,OAAO,UAAU,QAAQ;AAE/B,eAAsB,QAAQ,UAAsB,SAAkB;AACpE,MAAI,CAAC,CAAC,UAAU,OAAO,EAAE,SAAS,QAAQ,QAAQ;AAChD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACF,QAAM,QAAQ,aAAa,SAAS,GAAG;AACvC,QAAM,QAAQ,KAAK,aAAa,eAAe;AAC/C,MAAI,QAAQ,aAAa,UAAU;AACjC,QAAI,QAAS,OAAM,aAAa,QAAQ;AACxC,UAAM,kBAAkB,UAAU,OAAO,OAAO;AAChD;AAAA,EACF;AACA,MAAI,SAAS;AACX,UAAM,YAAY,QAAQ;AAC1B,UAAM,MAAM,SAAS,OAAO,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAAA,EAC9D;AACA,QAAM,YAAY,KAAK,QAAQ,GAAG,sBAAsB;AACxD,QAAM,WAAW,KAAK,WAAW,GAAG,KAAK,UAAU;AACnD,MAAI,SAAS;AACX,UAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC1C,UAAM,UAAU,MAAM,cAAc,UAAU,KAAK;AACnD,QACE,SAAS;AAAA,MACP,CAAC,QAAQ,MAAM,QAAQ,OAAO,SAAS,QAAQ,SAAS,MAAM,QAAQ,IAAI,EAAE,KAAK,EAAE;AAAA,IACrF;AAEA,YAAM,IAAI,MAAM,0EAAmB;AACrC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA;AAAA;AAAA,YAAmD,CAAC,QAAQ,MAAM,QAAQ,OAAO,OAAO,YAAY,SAAS,MAAM,EAAE,IAAI,IAAI,EAAE,KAAK,GAAG,CAAC;AAAA,cAAiB,KAAK,cAAc,SAAS,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,QAAQ,IAAI,EAAE,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAC5N,EAAE,MAAM,IAAM;AAAA,IAChB;AACA,UAAM,KAAK,aAAa,CAAC,UAAU,eAAe,CAAC;AACnD,UAAM,KAAK,aAAa,CAAC,UAAU,UAAU,SAAS,GAAG,KAAK,UAAU,CAAC;AACzE,UAAM,SAAS,KAAK,SAAS,OAAO,cAAc,GAAG,EAAE,UAAU,SAAS,MAAM,CAAC;AAAA,EACnF,OAAO;AACL,UAAM,KAAK,aAAa,CAAC,UAAU,WAAW,SAAS,GAAG,KAAK,UAAU,CAAC;AAC1E,UAAM,GAAG,QAAQ;AACjB,UAAM,GAAG,KAAK,SAAS,OAAO,cAAc,GAAG,EAAE,OAAO,KAAK,CAAC;AAC9D,UAAM,KAAK,aAAa,CAAC,UAAU,eAAe,CAAC;AAAA,EACrD;AACF;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,132 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { z } from "zod";
3
+ import { CodexError, isRecord } from "./transport.js";
4
+ const nullable = (value) => value.nullish().transform((v) => v ?? null);
5
+ const text = nullable(z.string());
6
+ const number = nullable(z.number().finite());
7
+ const boolean = nullable(z.boolean());
8
+ const timestamp = nullable(z.number().finite().min(0).max(864e10));
9
+ const window = nullable(
10
+ z.object({
11
+ usedPercent: number,
12
+ windowDurationMins: nullable(z.number().finite().nonnegative()),
13
+ resetsAt: timestamp
14
+ })
15
+ );
16
+ const group = z.object({
17
+ limitId: text,
18
+ limitName: text,
19
+ normalModelSlug: text,
20
+ planType: text,
21
+ primary: window,
22
+ secondary: window,
23
+ credits: nullable(z.object({ hasCredits: boolean, unlimited: boolean, balance: text })),
24
+ individualLimit: nullable(
25
+ z.object({
26
+ limit: text,
27
+ used: text,
28
+ remainingPercent: number,
29
+ resetsAt: timestamp
30
+ })
31
+ ),
32
+ spendControlReached: boolean,
33
+ rateLimitReachedType: text
34
+ });
35
+ const response = z.object({
36
+ rateLimits: nullable(group),
37
+ rateLimitsByLimitId: nullable(z.record(z.string(), group)),
38
+ ordinaryUsageAllowed: boolean,
39
+ rateLimitResetCredits: nullable(
40
+ z.object({ availableCount: nullable(z.number().int().nonnegative()) })
41
+ )
42
+ });
43
+ function accountUsageValues(input) {
44
+ const value = response.parse(input);
45
+ const groups = Object.entries(value.rateLimitsByLimitId ?? {}).map(
46
+ ([id, entry]) => ({ ...entry, limitId: entry.limitId ?? id })
47
+ );
48
+ if (value.rateLimits && (!groups.length || value.rateLimits.limitId !== null && !groups.some((entry) => entry.limitId === value.rateLimits?.limitId))) {
49
+ groups.unshift(value.rateLimits);
50
+ }
51
+ return {
52
+ groups,
53
+ ordinaryUsageAllowed: value.ordinaryUsageAllowed,
54
+ resetCreditsAvailable: value.rateLimitResetCredits?.availableCount ?? null
55
+ };
56
+ }
57
+ class AccountUsageReader {
58
+ constructor(source) {
59
+ this.source = source;
60
+ }
61
+ source;
62
+ sequence = 0;
63
+ identity;
64
+ value = this.empty("offline");
65
+ snapshot() {
66
+ return structuredClone(this.value);
67
+ }
68
+ empty(status) {
69
+ return {
70
+ scope: randomUUID(),
71
+ status,
72
+ refreshing: false,
73
+ updatedAt: null,
74
+ groups: [],
75
+ ordinaryUsageAllowed: null,
76
+ resetCreditsAvailable: null
77
+ };
78
+ }
79
+ invalidate(status) {
80
+ this.sequence++;
81
+ this.identity = void 0;
82
+ this.value = this.empty(status);
83
+ this.source.changed();
84
+ }
85
+ async refresh() {
86
+ const sequence = ++this.sequence;
87
+ this.value = { ...this.value, refreshing: true };
88
+ this.source.changed();
89
+ try {
90
+ const result = await this.source.account();
91
+ if (sequence !== this.sequence) return this.snapshot();
92
+ if (!isRecord(result) || !Object.hasOwn(result, "account") || typeof result.requiresOpenaiAuth !== "boolean")
93
+ throw new Error("Invalid account response");
94
+ const identity = JSON.stringify(result.account);
95
+ if (this.identity !== void 0 && identity !== this.identity) {
96
+ this.value = this.empty("loading");
97
+ this.source.changed();
98
+ }
99
+ this.identity = identity;
100
+ this.source.authenticated(result.account !== null || !result.requiresOpenaiAuth);
101
+ if (!result.account) {
102
+ this.value = {
103
+ ...this.empty(result.requiresOpenaiAuth ? "signedOut" : "unsupported"),
104
+ scope: this.value.scope
105
+ };
106
+ } else if (result.account.type !== "chatgpt") {
107
+ this.value = { ...this.empty("unsupported"), scope: this.value.scope };
108
+ } else {
109
+ const values = accountUsageValues(await this.source.limits());
110
+ if (sequence !== this.sequence) return this.snapshot();
111
+ this.value = {
112
+ ...this.value,
113
+ ...values,
114
+ status: "ready",
115
+ refreshing: false,
116
+ updatedAt: Date.now()
117
+ };
118
+ }
119
+ } catch (error) {
120
+ if (sequence !== this.sequence) return this.snapshot();
121
+ const unsupported = error instanceof CodexError && (error.rpcCode === -32601 || error.code === "PROTOCOL_INCOMPATIBLE");
122
+ this.value = unsupported ? { ...this.empty("unsupported"), scope: this.value.scope } : { ...this.value, status: "error", refreshing: false };
123
+ }
124
+ if (sequence === this.sequence) this.source.changed();
125
+ return this.snapshot();
126
+ }
127
+ }
128
+ export {
129
+ AccountUsageReader,
130
+ accountUsageValues
131
+ };
132
+ //# sourceMappingURL=account-usage.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/codex/account-usage.ts"],
4
+ "sourcesContent": ["import { randomUUID } from 'node:crypto';\nimport { z } from 'zod';\nimport type { GetAccountResponse } from './generated/v2/GetAccountResponse.js';\nimport type { AccountUsage, UsageGroup } from '../shared/account-usage.js';\nimport { CodexError, isRecord } from './transport.js';\n\nconst nullable = <T extends z.ZodType>(value: T) => value.nullish().transform((v) => v ?? null);\nconst text = nullable(z.string());\nconst number = nullable(z.number().finite());\nconst boolean = nullable(z.boolean());\nconst timestamp = nullable(z.number().finite().min(0).max(8.64e12));\nconst window = nullable(\n z.object({\n usedPercent: number,\n windowDurationMins: nullable(z.number().finite().nonnegative()),\n resetsAt: timestamp,\n }),\n);\nconst group = z.object({\n limitId: text,\n limitName: text,\n normalModelSlug: text,\n planType: text,\n primary: window,\n secondary: window,\n credits: nullable(z.object({ hasCredits: boolean, unlimited: boolean, balance: text })),\n individualLimit: nullable(\n z.object({\n limit: text,\n used: text,\n remainingPercent: number,\n resetsAt: timestamp,\n }),\n ),\n spendControlReached: boolean,\n rateLimitReachedType: text,\n});\nconst response = z.object({\n rateLimits: nullable(group),\n rateLimitsByLimitId: nullable(z.record(z.string(), group)),\n ordinaryUsageAllowed: boolean,\n rateLimitResetCredits: nullable(\n z.object({ availableCount: nullable(z.number().int().nonnegative()) }),\n ),\n});\n\nexport function accountUsageValues(input: unknown) {\n const value = response.parse(input);\n const groups: UsageGroup[] = Object.entries(value.rateLimitsByLimitId ?? {}).map(\n ([id, entry]) => ({ ...entry, limitId: entry.limitId ?? id }),\n );\n // The legacy bucket mirrors a map entry. Keep it only when it adds a distinct bucket.\n if (\n value.rateLimits &&\n (!groups.length ||\n (value.rateLimits.limitId !== null &&\n !groups.some((entry) => entry.limitId === value.rateLimits?.limitId)))\n ) {\n groups.unshift(value.rateLimits);\n }\n return {\n groups,\n ordinaryUsageAllowed: value.ordinaryUsageAllowed,\n resetCreditsAvailable: value.rateLimitResetCredits?.availableCount ?? null,\n };\n}\n\n/** Owns freshness and identity boundaries. Sparse notifications trigger a full read. */\nexport class AccountUsageReader {\n private sequence = 0;\n private identity?: string;\n private value: AccountUsage = this.empty('offline');\n constructor(\n private readonly source: {\n account: () => Promise<GetAccountResponse>;\n limits: () => Promise<unknown>;\n changed: () => void;\n authenticated: (value: boolean) => void;\n },\n ) {}\n\n snapshot(): AccountUsage {\n return structuredClone(this.value);\n }\n\n private empty(status: AccountUsage['status']): AccountUsage {\n return {\n scope: randomUUID(),\n status,\n refreshing: false,\n updatedAt: null,\n groups: [],\n ordinaryUsageAllowed: null,\n resetCreditsAvailable: null,\n };\n }\n\n invalidate(status: 'offline' | 'loading'): void {\n this.sequence++;\n this.identity = undefined;\n this.value = this.empty(status);\n this.source.changed();\n }\n\n async refresh(): Promise<AccountUsage> {\n const sequence = ++this.sequence;\n this.value = { ...this.value, refreshing: true };\n this.source.changed();\n try {\n const result = await this.source.account();\n if (sequence !== this.sequence) return this.snapshot();\n if (\n !isRecord(result) ||\n !Object.hasOwn(result, 'account') ||\n typeof result.requiresOpenaiAuth !== 'boolean'\n )\n throw new Error('Invalid account response');\n const identity = JSON.stringify(result.account);\n if (this.identity !== undefined && identity !== this.identity) {\n this.value = this.empty('loading');\n this.source.changed();\n }\n this.identity = identity;\n this.source.authenticated(result.account !== null || !result.requiresOpenaiAuth);\n if (!result.account) {\n this.value = {\n ...this.empty(result.requiresOpenaiAuth ? 'signedOut' : 'unsupported'),\n scope: this.value.scope,\n };\n } else if (result.account.type !== 'chatgpt') {\n this.value = { ...this.empty('unsupported'), scope: this.value.scope };\n } else {\n const values = accountUsageValues(await this.source.limits());\n if (sequence !== this.sequence) return this.snapshot();\n this.value = {\n ...this.value,\n ...values,\n status: 'ready',\n refreshing: false,\n updatedAt: Date.now(),\n };\n }\n } catch (error) {\n if (sequence !== this.sequence) return this.snapshot();\n const unsupported =\n error instanceof CodexError &&\n (error.rpcCode === -32601 || error.code === 'PROTOCOL_INCOMPATIBLE');\n this.value = unsupported\n ? { ...this.empty('unsupported'), scope: this.value.scope }\n : { ...this.value, status: 'error', refreshing: false };\n }\n if (sequence === this.sequence) this.source.changed();\n return this.snapshot();\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,4 +1,5 @@
1
1
  import { CODEX_COMPATIBILITY } from "./compatibility.js";
2
+ import { AccountUsageReader } from "./account-usage.js";
2
3
  import { SHELL_TIMEOUT_MS, SHELL_OUTPUT_BYTES } from "../shared/shell.js";
3
4
  import { spawn, execFile } from "node:child_process";
4
5
  import { randomUUID } from "node:crypto";
@@ -71,7 +72,8 @@ const CAPABILITIES = [
71
72
  "config/batchWrite",
72
73
  "configRequirements/read",
73
74
  "experimentalFeature/list",
74
- "account/read"
75
+ "account/read",
76
+ "account/rateLimits/read"
75
77
  ];
76
78
  function permissionPathLabel(path) {
77
79
  if (path.type === "path") return path.path;
@@ -98,6 +100,21 @@ class CodexAdapter {
98
100
  this.options = options;
99
101
  }
100
102
  options;
103
+ accountUsage = new AccountUsageReader({
104
+ account: () => this.call("account/read", { refreshToken: false }),
105
+ limits: () => this.call("account/rateLimits/read", { excludeResetCreditDetails: true }),
106
+ changed: () => this.publishRuntime(),
107
+ authenticated: (value) => {
108
+ this.state.authenticated = value;
109
+ }
110
+ });
111
+ async refreshAccountUsage() {
112
+ if (!this.ready) {
113
+ this.accountUsage.invalidate("offline");
114
+ return this.accountUsage.snapshot();
115
+ }
116
+ return this.accountUsage.refresh();
117
+ }
101
118
  commandOutputs = /* @__PURE__ */ new Map();
102
119
  epoch = randomUUID();
103
120
  child;
@@ -137,7 +154,7 @@ class CodexAdapter {
137
154
  return this.state.ready;
138
155
  }
139
156
  diagnostics() {
140
- return structuredClone(this.state);
157
+ return { ...structuredClone(this.state), accountUsage: this.accountUsage.snapshot() };
141
158
  }
142
159
  onEvent(listener) {
143
160
  this.listeners.add(listener);
@@ -172,6 +189,7 @@ class CodexAdapter {
172
189
  error: void 0,
173
190
  capabilities: []
174
191
  };
192
+ this.accountUsage.invalidate("loading");
175
193
  this.publishRuntime();
176
194
  try {
177
195
  const env = {
@@ -235,6 +253,7 @@ class CodexAdapter {
235
253
  this.tokenUsage.clear();
236
254
  this.denials.clear();
237
255
  this.state.connection = "unavailable";
256
+ this.accountUsage.invalidate("offline");
238
257
  this.state.error = error.message;
239
258
  this.expireActions();
240
259
  this.publishRuntime();
@@ -319,6 +338,7 @@ class CodexAdapter {
319
338
  this.state.connection = "ready";
320
339
  this.state.capabilities = CAPABILITIES.filter((method) => !this.disabled.has(method));
321
340
  this.publishRuntime();
341
+ void this.refreshAccountUsage();
322
342
  } catch (error) {
323
343
  const failure = asCodexError(error);
324
344
  this.state.ready = false;
@@ -332,6 +352,7 @@ class CodexAdapter {
332
352
  }
333
353
  async stop() {
334
354
  this.stopped = true;
355
+ this.accountUsage.invalidate("offline");
335
356
  clearTimeout(this.restartTimer);
336
357
  this.restartTimer = void 0;
337
358
  await this.starting?.catch(() => {
@@ -959,6 +980,14 @@ class CodexAdapter {
959
980
  const event = message;
960
981
  const p = event.params;
961
982
  switch (event.method) {
983
+ case "account/updated":
984
+ this.state.authenticated = null;
985
+ this.accountUsage.invalidate("loading");
986
+ if (this.ready) void this.refreshAccountUsage();
987
+ break;
988
+ case "account/rateLimits/updated":
989
+ if (this.ready) void this.refreshAccountUsage();
990
+ break;
962
991
  case "command/exec/outputDelta": {
963
992
  const { processId, stream, deltaBase64, capReached } = event.params;
964
993
  this.commandOutputs.get(processId)?.(