@runeya/runeya 2.0.151 → 2.0.153

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 (166) hide show
  1. package/agent/index.js +9 -7
  2. package/agent/index.js.map +1 -1
  3. package/agent-manager-SF4CAJJC.js +13 -0
  4. package/chat-Z7SFBEXS.js +28 -0
  5. package/{chunk-ANZF5NLB.js → chunk-26Q43CB2.js} +2 -2
  6. package/{chunk-IOPX7MWA.js → chunk-2DIW5EUT.js} +6 -6
  7. package/{chunk-ZRMLIQZL.js → chunk-3C3R5ZVX.js} +2 -2
  8. package/{chunk-I2EXJ2GI.js → chunk-3O54EIGT.js} +4 -4
  9. package/{chunk-KTRL6RDH.js → chunk-DTRZ5ZN7.js} +5 -5
  10. package/{chunk-3FSQ45SW.js → chunk-EUTW2S4P.js} +87 -16
  11. package/chunk-EUTW2S4P.js.map +1 -0
  12. package/{chunk-NVU7QNZO.js → chunk-MGKGIHT4.js} +2 -4
  13. package/{chunk-NVU7QNZO.js.map → chunk-MGKGIHT4.js.map} +1 -1
  14. package/{chunk-FYAKLTSY.js → chunk-PU6REPMY.js} +5 -5
  15. package/{chunk-FYAKLTSY.js.map → chunk-PU6REPMY.js.map} +1 -1
  16. package/{chunk-NKOG7375.js → chunk-QD2OVLK4.js} +2 -2
  17. package/{chunk-7O54TV2Y.js → chunk-QJSIN26R.js} +45 -38
  18. package/chunk-QJSIN26R.js.map +1 -0
  19. package/{chunk-3JIJSGQW.js → chunk-R4SKU6AO.js} +10 -12
  20. package/chunk-R4SKU6AO.js.map +1 -0
  21. package/{chunk-OCIKN4BK.js → chunk-RVZATF7R.js} +8 -8
  22. package/chunk-RVZATF7R.js.map +1 -0
  23. package/{chunk-YTO4O3UK.js → chunk-TBNCGMDM.js} +5 -5
  24. package/{companion-2YZZSKX5.js → companion-ZDEGNZ2G.js} +11 -9
  25. package/{desktop-installer-page-526XOYLO.js → desktop-installer-page-TBKSXVFD.js} +3 -3
  26. package/{desktop-launcher-WJPN6SPV.js → desktop-launcher-WBYP3KTF.js} +3 -3
  27. package/{environment-resolver-I6KF27QP.js → environment-resolver-R2GH6QOX.js} +6 -6
  28. package/{external-XHTD2IGX.js → external-UJ46WKBL.js} +3 -3
  29. package/index.js +15 -15
  30. package/index.js.map +1 -1
  31. package/{install-gate-VIJIEVF2.js → install-gate-TSCXUCYE.js} +2 -2
  32. package/mcp-server/external.js +7 -6
  33. package/mcp-server/external.js.map +1 -1
  34. package/mcp-server/index.js +7 -6
  35. package/mcp-server/index.js.map +1 -1
  36. package/package.json +1 -1
  37. package/{project-store-GONXVR2N.js → project-store-GBKM34QP.js} +7 -7
  38. package/settings-manager-VSOC3XGI.js +10 -0
  39. package/{src-QMPTXT7D.js → src-6WZKSNN7.js} +2 -2
  40. package/{src-ZDXFSJMJ.js → src-NWPED6TK.js} +33 -39
  41. package/src-NWPED6TK.js.map +1 -0
  42. package/{vault-resolver-MX7WFBJ5.js → vault-resolver-GGHULMG6.js} +3 -3
  43. package/web/assets/{AgentScalarChatInterface.vue-DXbf1TAm.js → AgentScalarChatInterface.vue-CEMnvqfq.js} +1 -1
  44. package/web/assets/{AgentTerminalPage-CgsW_pEb.js → AgentTerminalPage-qQ96vm5Y.js} +1 -1
  45. package/web/assets/{AiChatModals-DLTvqUBK.js → AiChatModals-BsfKdbEA.js} +1 -1
  46. package/web/assets/{AppLayout-BlhwflMq.css → AppLayout-Djk3-XbN.css} +1 -1
  47. package/web/assets/AppLayout-f0_BsXSc.js +1 -0
  48. package/web/assets/{AuditPage-HMNBcG9E.js → AuditPage-B-pCRqXH.js} +1 -1
  49. package/web/assets/CloudAccountPage-C7aV6M8U.js +1 -0
  50. package/web/assets/{CloudAccountPage-Ctf2gtpm.css → CloudAccountPage-CYcW_3tO.css} +1 -1
  51. package/web/assets/{CloudMessagingPage-Csbnn-Zm.js → CloudMessagingPage-BTc8xbjF.js} +1 -1
  52. package/web/assets/{DashboardPage-BeCmdPlp.js → DashboardPage-CF7GLFlx.js} +1 -1
  53. package/web/assets/{DirectoryPickerDialog-DpUZT_4M.js → DirectoryPickerDialog-bKqIFy8e.js} +1 -1
  54. package/web/assets/{EditorIcon-CcU8Z46_.js → EditorIcon-DksI79ZN.js} +1 -1
  55. package/web/assets/EnvironmentForm-BnTLokUw.css +1 -0
  56. package/web/assets/{EnvironmentForm-ypeBVGl-.js → EnvironmentForm-kOyM5xTa.js} +1 -1
  57. package/web/assets/{EnvironmentFormPage-B1gVyMWV.js → EnvironmentFormPage-DfNI6meL.js} +1 -1
  58. package/web/assets/{EnvironmentListPage-CdE-ksue.js → EnvironmentListPage-C1VLgeeP.js} +1 -1
  59. package/web/assets/{FlagChip-maG1f7pl.js → FlagChip-DjC14z4J.js} +1 -1
  60. package/web/assets/{KanbanBoardPage-_E6xalsS.js → KanbanBoardPage-Bl6UnQ6P.js} +3 -3
  61. package/web/assets/KanbanBoardPage-Cmu4Je4N.css +1 -0
  62. package/web/assets/{KanbanListPage-BigioApQ.css → KanbanListPage-DCK-N3nw.css} +1 -1
  63. package/web/assets/{KanbanListPage-DkjiefP8.js → KanbanListPage-Dly6XiRC.js} +1 -1
  64. package/web/assets/{LaunchProjectPage-C4kuqyMZ.js → LaunchProjectPage-DCrKSY8v.js} +1 -1
  65. package/web/assets/{LaunchServicesPage-s8HZF2aU.js → LaunchServicesPage-Bl1pjfYH.js} +1 -1
  66. package/web/assets/{LaunchShell-GWtn69Hh.js → LaunchShell-BcbfPDdc.js} +1 -1
  67. package/web/assets/{LogViewer-B0XUfzs3.js → LogViewer-C_XcH7Oe.js} +1 -1
  68. package/web/assets/{OrgKeyPrompt-Ch8jziJJ.js → OrgKeyPrompt-BK6gkvaO.js} +1 -1
  69. package/web/assets/{ProcessControls-bZbJJjkv.js → ProcessControls-BbRdiZsD.js} +1 -1
  70. package/web/assets/ProcessDetailPage-B7bD2jmj.css +1 -0
  71. package/web/assets/ProcessDetailPage-W7S7ogas.js +1 -0
  72. package/web/assets/{ProcessMetrics-D-rQkzqK.js → ProcessMetrics-C_7_boMv.js} +1 -1
  73. package/web/assets/{ProjectCreateDialog-KjvGUZnr.js → ProjectCreateDialog-q_39qiPd.js} +1 -1
  74. package/web/assets/{ProjectLocationGate-DFe2hgxM.js → ProjectLocationGate-BFvdSy-B.js} +1 -1
  75. package/web/assets/{ProjectPublishDialog-BgPH5gGM.js → ProjectPublishDialog-DAJAvDTT.js} +1 -1
  76. package/web/assets/{RandomJobTestPage-Bv3l2Trh.js → RandomJobTestPage-A-I7cImN.js} +1 -1
  77. package/web/assets/{ScenarioEditorPage-BtKSjE2X.css → ScenarioEditorPage-BwLBCVeS.css} +1 -1
  78. package/web/assets/ScenarioEditorPage-DXw4bCxb.js +14 -0
  79. package/web/assets/{SendToChatDialog-CkWcPSvZ.js → SendToChatDialog-CbhE2WYO.js} +1 -1
  80. package/web/assets/{ServiceControlsBar-VywLkYdH.js → ServiceControlsBar-CudCeQql.js} +1 -1
  81. package/web/assets/ServiceDetailPage-DQvL-VOx.js +2 -0
  82. package/web/assets/{ServiceDetailPage-CM5uzqpI.css → ServiceDetailPage-DuXvqXk4.css} +1 -1
  83. package/web/assets/{ServiceFormPage-v9c7DVdv.js → ServiceFormPage-0qXPeqrh.js} +1 -1
  84. package/web/assets/{SettingsPage-CetQ42p1.js → SettingsPage-Bjn4bKPP.js} +7 -7
  85. package/web/assets/{SettingsPage-B951NEBm.css → SettingsPage-NpFX7FAy.css} +1 -1
  86. package/web/assets/{UnlockPage-CZMvcAl1.js → UnlockPage-CtvaQt45.js} +1 -1
  87. package/web/assets/{VaultMigrationPage-CeX0mpxh.js → VaultMigrationPage-DtoAlng4.js} +1 -1
  88. package/web/assets/{VersionBadge-DDmZ4Dhc.js → VersionBadge-CiBz82BB.js} +1 -1
  89. package/web/assets/{WikiPage-3puq_dIL.js → WikiPage-cuKigw_5.js} +1 -1
  90. package/web/assets/{WikiView-J4U7er--.js → WikiView-BW-B83LB.js} +1 -1
  91. package/web/assets/{add-scalar-classes-B7027Ds2.js → add-scalar-classes-BPTxQDQd.js} +1 -1
  92. package/web/assets/{agent.store-CAhnz7FI.js → agent.store-DumNiX1X.js} +1 -1
  93. package/web/assets/{auth-DEwzvqNZ.js → auth-Qa1l14iV.js} +2 -2
  94. package/web/assets/{cloud-chat.store-Dw5IpDzc.js → cloud-chat.store-TYR1_27Z.js} +1 -1
  95. package/web/assets/{cloud-client-BmRvC15v.js → cloud-client-CdOqrdP_.js} +2 -2
  96. package/web/assets/{cloud-session-CxfJk0xr.js → cloud-session-Dd7b9wxV.js} +2 -2
  97. package/web/assets/dist-C9Qdh18x.js +1 -0
  98. package/web/assets/i18n-DipCGVKv.js +1 -0
  99. package/web/assets/{index-DSYMPMcP.js → index-BCU69ZHl.js} +7 -7
  100. package/web/assets/{index-CnXzQkLZ.css → index-Ck_3m_I9.css} +1 -1
  101. package/web/assets/{modal-CWJFP30c.js → modal-BgrgFhyC.js} +1 -1
  102. package/web/assets/notification.store-D2olEA0V.js +1 -0
  103. package/web/assets/{project-launch.store-_peuBwFo.js → project-launch.store-MX5LzgIm.js} +1 -1
  104. package/web/assets/{project.store-eANeFYaH.js → project.store-BFwiDQ1X.js} +1 -1
  105. package/web/assets/{scenario.store-C1Yj7c6l.js → scenario.store-C8kW-yTN.js} +1 -1
  106. package/web/assets/{service.store-Ck2_TmTB.js → service.store-B0Ass90H.js} +1 -1
  107. package/web/assets/{settings-scope-GiU9Nkh7.js → settings-scope-D0hzzuyq.js} +1 -1
  108. package/web/assets/settings.store-B9Kp0l1G.js +1 -0
  109. package/web/assets/{src-Bfb0PBSC.css → src-CfDz-9Q6.css} +1 -1
  110. package/web/assets/{src-DOcCcTQv.js → src-Ck_MutzB.js} +1 -1
  111. package/web/assets/{src-BsRUOIiC.js → src-DITmhvGS.js} +1 -1
  112. package/web/assets/src-DOziuDw8.css +1 -0
  113. package/web/assets/src-DnjsM9el.js +1960 -0
  114. package/web/assets/{trpc-Deb6EPHJ.js → trpc-BvrR5qP9.js} +3 -3
  115. package/web/assets/{useCloudOrg-7IK98BjW.js → useCloudOrg-2vv5fVV6.js} +1 -1
  116. package/web/assets/{useEnvVarAutocomplete-lfgStLwz.js → useEnvVarAutocomplete-VVX3MC62.js} +1 -1
  117. package/web/assets/{useEnvVarAutocomplete-B-LJ9dBm.css → useEnvVarAutocomplete-gV2loQYv.css} +1 -1
  118. package/web/assets/{useProjectCatalog-J40rgwRP.js → useProjectCatalog-DsVvtBzo.js} +1 -1
  119. package/web/assets/{useProjectCloudOrg-zePV-ihH.js → useProjectCloudOrg-wv-RfsmO.js} +1 -1
  120. package/web/assets/{useServiceUrlHost-BWtmwnoK.js → useServiceUrlHost-C4Evrede.js} +1 -1
  121. package/web/index.html +19 -19
  122. package/agent-manager-2KTEZXRO.js +0 -13
  123. package/chat-N2AYGN7I.js +0 -28
  124. package/chunk-3FSQ45SW.js.map +0 -1
  125. package/chunk-3JIJSGQW.js.map +0 -1
  126. package/chunk-7O54TV2Y.js.map +0 -1
  127. package/chunk-DA2DZBTL.js +0 -43
  128. package/chunk-DA2DZBTL.js.map +0 -1
  129. package/chunk-OCIKN4BK.js.map +0 -1
  130. package/mcp-ready-TAPBAOZY.js +0 -9
  131. package/settings-manager-QOLMKVP2.js +0 -10
  132. package/src-ZDXFSJMJ.js.map +0 -1
  133. package/vault-resolver-MX7WFBJ5.js.map +0 -1
  134. package/web/assets/AppLayout-BFCPOgV1.js +0 -1
  135. package/web/assets/CloudAccountPage-DXMDa3Zw.js +0 -1
  136. package/web/assets/EnvironmentForm-Do3i-fOk.css +0 -1
  137. package/web/assets/KanbanBoardPage-Bb_8xU-I.css +0 -1
  138. package/web/assets/ProcessDetailPage-CJcIxbLm.css +0 -1
  139. package/web/assets/ProcessDetailPage-Cy_9S9z8.js +0 -1
  140. package/web/assets/ScenarioEditorPage-DMZ_67kP.js +0 -14
  141. package/web/assets/ServiceDetailPage-C-RIYfjD.js +0 -2
  142. package/web/assets/dist-B6L3Jwj-.js +0 -1
  143. package/web/assets/i18n-BNITS3xi.js +0 -1
  144. package/web/assets/notification.store-C1JOcW8z.js +0 -1
  145. package/web/assets/settings.store-C6T1P_cU.js +0 -1
  146. package/web/assets/src-Dbg3CMY2.css +0 -1
  147. package/web/assets/src-Ip9ugq4e.js +0 -1960
  148. /package/{agent-manager-2KTEZXRO.js.map → agent-manager-SF4CAJJC.js.map} +0 -0
  149. /package/{chat-N2AYGN7I.js.map → chat-Z7SFBEXS.js.map} +0 -0
  150. /package/{chunk-ANZF5NLB.js.map → chunk-26Q43CB2.js.map} +0 -0
  151. /package/{chunk-IOPX7MWA.js.map → chunk-2DIW5EUT.js.map} +0 -0
  152. /package/{chunk-ZRMLIQZL.js.map → chunk-3C3R5ZVX.js.map} +0 -0
  153. /package/{chunk-I2EXJ2GI.js.map → chunk-3O54EIGT.js.map} +0 -0
  154. /package/{chunk-KTRL6RDH.js.map → chunk-DTRZ5ZN7.js.map} +0 -0
  155. /package/{chunk-NKOG7375.js.map → chunk-QD2OVLK4.js.map} +0 -0
  156. /package/{chunk-YTO4O3UK.js.map → chunk-TBNCGMDM.js.map} +0 -0
  157. /package/{companion-2YZZSKX5.js.map → companion-ZDEGNZ2G.js.map} +0 -0
  158. /package/{desktop-installer-page-526XOYLO.js.map → desktop-installer-page-TBKSXVFD.js.map} +0 -0
  159. /package/{desktop-launcher-WJPN6SPV.js.map → desktop-launcher-WBYP3KTF.js.map} +0 -0
  160. /package/{environment-resolver-I6KF27QP.js.map → environment-resolver-R2GH6QOX.js.map} +0 -0
  161. /package/{external-XHTD2IGX.js.map → external-UJ46WKBL.js.map} +0 -0
  162. /package/{install-gate-VIJIEVF2.js.map → install-gate-TSCXUCYE.js.map} +0 -0
  163. /package/{mcp-ready-TAPBAOZY.js.map → project-store-GBKM34QP.js.map} +0 -0
  164. /package/{project-store-GONXVR2N.js.map → settings-manager-VSOC3XGI.js.map} +0 -0
  165. /package/{settings-manager-QOLMKVP2.js.map → src-6WZKSNN7.js.map} +0 -0
  166. /package/{src-QMPTXT7D.js.map → vault-resolver-GGHULMG6.js.map} +0 -0
@@ -14,12 +14,12 @@ import {
14
14
  uninstallDesktopLauncher,
15
15
  vbsQuote,
16
16
  windowsVbsScript
17
- } from "./chunk-ANZF5NLB.js";
17
+ } from "./chunk-26Q43CB2.js";
18
18
  import {
19
19
  deriveLauncherIdentity,
20
20
  launcherIdFromName,
21
21
  slugifyLauncherName
22
- } from "./chunk-OCIKN4BK.js";
22
+ } from "./chunk-RVZATF7R.js";
23
23
  export {
24
24
  deriveLauncherIdentity as deriveIdentity,
25
25
  desktopExecQuote,
@@ -40,4 +40,4 @@ export {
40
40
  vbsQuote,
41
41
  windowsVbsScript
42
42
  };
43
- //# sourceMappingURL=desktop-launcher-WJPN6SPV.js.map
43
+ //# sourceMappingURL=desktop-launcher-WBYP3KTF.js.map
@@ -3,16 +3,16 @@ import {
3
3
  describeVariables,
4
4
  environmentResolver,
5
5
  filterEnvForAi
6
- } from "./chunk-YTO4O3UK.js";
7
- import "./chunk-I2EXJ2GI.js";
6
+ } from "./chunk-TBNCGMDM.js";
7
+ import "./chunk-3O54EIGT.js";
8
8
  import "./chunk-OZBSOSAS.js";
9
- import "./chunk-ZRMLIQZL.js";
10
- import "./chunk-NVU7QNZO.js";
11
- import "./chunk-OCIKN4BK.js";
9
+ import "./chunk-3C3R5ZVX.js";
10
+ import "./chunk-MGKGIHT4.js";
11
+ import "./chunk-RVZATF7R.js";
12
12
  export {
13
13
  HIDDEN_VALUES_NOTICE,
14
14
  describeVariables,
15
15
  environmentResolver,
16
16
  filterEnvForAi
17
17
  };
18
- //# sourceMappingURL=environment-resolver-I6KF27QP.js.map
18
+ //# sourceMappingURL=environment-resolver-R2GH6QOX.js.map
@@ -5,8 +5,8 @@ import {
5
5
  callTrpc,
6
6
  runCapability,
7
7
  toRawParams
8
- } from "./chunk-NKOG7375.js";
9
- import "./chunk-OCIKN4BK.js";
8
+ } from "./chunk-QD2OVLK4.js";
9
+ import "./chunk-RVZATF7R.js";
10
10
 
11
11
  // ../../packages/mcp-server/src/external.ts
12
12
  import { homedir } from "os";
@@ -384,4 +384,4 @@ async function runExternalMcp(opts) {
384
384
  export {
385
385
  runExternalMcp
386
386
  };
387
- //# sourceMappingURL=external-XHTD2IGX.js.map
387
+ //# sourceMappingURL=external-UJ46WKBL.js.map
package/index.js CHANGED
@@ -62,7 +62,6 @@ var ENV_FLAGS = [
62
62
  { flag: "--agent-host", env: "RUNEYA_AGENT_HOST" },
63
63
  { flag: "--agent-binary-path", env: "RUNEYA_AGENT_BINARY_PATH" },
64
64
  { flag: "--data-dir", env: "RUNEYA_DATA_DIR" },
65
- { flag: "--mode", env: "RUNEYA_MODE" },
66
65
  { flag: "--cloud-url", env: "RUNEYA_CLOUD_URL" },
67
66
  { flag: "--cloud-app-url", env: "RUNEYA_CLOUD_APP_URL" },
68
67
  { flag: "--cors-origin", env: "RUNEYA_CORS_ORIGIN" },
@@ -76,6 +75,9 @@ var flagsWithValues = /* @__PURE__ */ new Set([
76
75
  "--environment",
77
76
  "-s",
78
77
  "--service",
78
+ // Retiré, mais encore accepté et ignoré : sans cela, un ancien script lancé
79
+ // avec `--mode local-simple` prendrait `local-simple` pour le dossier cible.
80
+ "--mode",
79
81
  ...ENV_FLAGS.map((f) => f.flag)
80
82
  ]);
81
83
  for (const { flag, env: key } of ENV_FLAGS) {
@@ -84,10 +86,10 @@ for (const { flag, env: key } of ENV_FLAGS) {
84
86
  }
85
87
  if (args.includes("--debug")) process.env["RUNEYA_DEBUG"] = "1";
86
88
  async function runDesktopInstaller(required) {
87
- const { installDesktopLauncher, listDesktopLaunchers, uninstallDesktopLauncher, deriveIdentity } = await import("./desktop-launcher-WJPN6SPV.js");
89
+ const { installDesktopLauncher, listDesktopLaunchers, uninstallDesktopLauncher, deriveIdentity } = await import("./desktop-launcher-WBYP3KTF.js");
88
90
  const { printInstallReport } = await import("./desktop-wizard-XIDDAG7L.js");
89
- const { runInstallerPage } = await import("./desktop-installer-page-526XOYLO.js");
90
- const { createGlobalInstaller } = await import("./install-gate-VIJIEVF2.js");
91
+ const { runInstallerPage } = await import("./desktop-installer-page-TBKSXVFD.js");
92
+ const { createGlobalInstaller } = await import("./install-gate-TSCXUCYE.js");
91
93
  const current = { nodePath: process.execPath, cliEntry: fileURLToPath(import.meta.url) };
92
94
  const outcome = await runInstallerPage({
93
95
  openUrl: (url) => open(url),
@@ -110,7 +112,7 @@ async function runDesktopInstaller(required) {
110
112
  }
111
113
  var subCommand = args[0];
112
114
  if (subCommand === "install-desktop" || subCommand === "uninstall-desktop") {
113
- const { installDesktopLauncher, uninstallDesktopLauncher, deriveIdentity } = await import("./desktop-launcher-WJPN6SPV.js");
115
+ const { installDesktopLauncher, uninstallDesktopLauncher, deriveIdentity } = await import("./desktop-launcher-WBYP3KTF.js");
114
116
  const { shouldOpenInstallPage, printInstallReport, printUninstallReport } = await import("./desktop-wizard-XIDDAG7L.js");
115
117
  const { parsePort } = await import("./free-port-5UNHDWGE.js");
116
118
  const rest = args.slice(1);
@@ -129,7 +131,7 @@ if (subCommand === "install-desktop" || subCommand === "uninstall-desktop") {
129
131
  const agentPort = parsePort(agentPortFlagRaw);
130
132
  const projectId = getFlagValue(["--project"]) ?? null;
131
133
  if (projectId !== null) {
132
- const { isLauncherProjectId } = await import("./src-QMPTXT7D.js");
134
+ const { isLauncherProjectId } = await import("./src-6WZKSNN7.js");
133
135
  if (!isLauncherProjectId(projectId)) {
134
136
  console.error(`Erreur : --project attend un id de projet (re\xE7u ${JSON.stringify(projectId)}).`);
135
137
  process.exit(1);
@@ -143,7 +145,7 @@ if (subCommand === "install-desktop" || subCommand === "uninstall-desktop") {
143
145
  }
144
146
  const { name, id } = deriveIdentity(displayName, workingDir);
145
147
  if (subCommand === "install-desktop") {
146
- const { createGlobalInstaller, SKIP_INSTALL_CHECK_ENV } = await import("./install-gate-VIJIEVF2.js");
148
+ const { createGlobalInstaller, SKIP_INSTALL_CHECK_ENV } = await import("./install-gate-TSCXUCYE.js");
147
149
  if (process.env[SKIP_INSTALL_CHECK_ENV] !== "1") {
148
150
  const target = { cliEntry: launcherBase.cliEntry };
149
151
  const global = await (await createGlobalInstaller(target, version)).state();
@@ -178,7 +180,7 @@ if (subCommand === "install-desktop" || subCommand === "uninstall-desktop") {
178
180
  }
179
181
  }
180
182
  if (subCommand === "instances") {
181
- const { listInstances, killInstance, restartInstance } = await import("./src-ZDXFSJMJ.js");
183
+ const { listInstances, killInstance, restartInstance } = await import("./src-NWPED6TK.js");
182
184
  const { runInstancesCommand } = await import("./instances-command-KZ5UGXOR.js");
183
185
  process.exit(await runInstancesCommand(args.slice(1), {
184
186
  listInstances,
@@ -193,8 +195,8 @@ if (subCommand === "instances") {
193
195
  }));
194
196
  }
195
197
  if (subCommand === "mcp") {
196
- const { listInstances } = await import("./src-ZDXFSJMJ.js");
197
- const { runExternalMcp } = await import("./external-XHTD2IGX.js");
198
+ const { listInstances } = await import("./src-NWPED6TK.js");
199
+ const { runExternalMcp } = await import("./external-UJ46WKBL.js");
198
200
  await runExternalMcp({ listInstances });
199
201
  await new Promise(() => {
200
202
  });
@@ -260,8 +262,6 @@ Configuration:
260
262
  --agent-host <address> RUNEYA_AGENT_HOST 127.0.0.1
261
263
  --agent-binary-path <path> RUNEYA_AGENT_BINARY_PATH bundled with the CLI
262
264
  --data-dir <path> RUNEYA_DATA_DIR <cwd>/.runeya
263
- --mode <mode> RUNEYA_MODE local-simple
264
- 'local-simple' | 'cloud'
265
265
  --cloud-url <url> RUNEYA_CLOUD_URL \u2014
266
266
  --cloud-app-url <url> RUNEYA_CLOUD_APP_URL \u2014
267
267
  --cors-origin <origin> RUNEYA_CORS_ORIGIN \u2014
@@ -354,7 +354,7 @@ function listenWithRetry(server, port, host, wss, maxRetries = 20, delay = 500)
354
354
  });
355
355
  }
356
356
  async function main() {
357
- const { mustOpenInstaller, hasDesktop, SKIP_INSTALL_CHECK_ENV } = await import("./install-gate-VIJIEVF2.js");
357
+ const { mustOpenInstaller, hasDesktop, SKIP_INSTALL_CHECK_ENV } = await import("./install-gate-TSCXUCYE.js");
358
358
  if (mustOpenInstaller({
359
359
  isFromDesktop,
360
360
  isRestartHandoff: process.env.RUNEYA_RESTART_HANDOFF === "1",
@@ -386,7 +386,7 @@ async function main() {
386
386
  console.warn(`[cli] Journal sur disque indisponible : ${err.message}`);
387
387
  }
388
388
  }
389
- const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import("./src-ZDXFSJMJ.js");
389
+ const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import("./src-NWPED6TK.js");
390
390
  registerCliLocation({ execPath: process.execPath, cliEntry: fileURLToPath(import.meta.url) });
391
391
  if (isPullEnv) {
392
392
  if (!serviceArg) {
@@ -495,7 +495,7 @@ async function main() {
495
495
  networkInfo,
496
496
  setLanMode,
497
497
  resolveTrayIcon
498
- } = await import("./src-ZDXFSJMJ.js");
498
+ } = await import("./src-NWPED6TK.js");
499
499
  tray = await startInstanceTray({
500
500
  info: { cwd: process.cwd(), port, version, url: appUrl },
501
501
  assetsDir: join(__dirname, "assets"),
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/port-resolution.ts"],"sourcesContent":["#!/usr/bin/env node\nimport type { Server } from 'node:http';\nimport type { WebSocketServer } from 'ws';\nimport type { Request, Response } from 'express';\nimport { fileURLToPath, URL as NodeURL } from 'node:url';\nimport { dirname, join, resolve } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport express from 'express';\nimport dotenv from 'dotenv'\nimport open from 'open';\nimport { resolvePort } from './port-resolution.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst { version } = JSON.parse(\n readFileSync(new NodeURL('./package.json', import.meta.url), 'utf8'),\n) as { version: string };\n\nfunction printStartupTable(port: number, appUrl: string): void {\n const rows: [string, string][] = [\n ['Version', version],\n ['Port', String(port)],\n ['Url', appUrl],\n ];\n\n const col0 = Math.max(...rows.map(([k]) => k.length));\n const col1 = Math.max(...rows.map(([, v]) => v.length));\n\n const pad = (s: string, n: number) => s.padEnd(n);\n const hr = (l: string, m: string, r: string, f: string) =>\n l + f.repeat(col0 + 2) + m + f.repeat(col1 + 2) + r;\n\n console.log('');\n console.log(hr('┌', '┬', '┐', '─'));\n for (const [key, value] of rows) {\n console.log(`│ ${pad(key, col0)} │ ${pad(value, col1)} │`);\n }\n console.log(hr('└', '┴', '┘', '─'));\n console.log('');\n}\n\n// Parse CLI flags\nconst args = process.argv.slice(2);\n\n/**\n * Set by the desktop launcher. It means nobody is watching a terminal, so a\n * startup failure has to be reported through a window of its own.\n */\nconst isFromDesktop = args.includes('--from-desktop');\n\n// Capture must start before anything logs, hence this early import.\nconst startupFailure = isFromDesktop ? await import('./startup-failure.js') : null;\nstartupFailure?.captureOutput();\n\nfunction getFlagValue(flags: string[]): string | undefined {\n for (const flag of flags) {\n const idx = args.indexOf(flag);\n if (idx !== -1 && idx + 1 < args.length) return args[idx + 1];\n }\n return undefined;\n}\n\n/**\n * Flags that mirror a RUNEYA_* environment variable. The flag always wins over\n * the variable, and both are equivalent otherwise.\n *\n * Secrets (RUNEYA_ENCRYPTION_KEY, RUNEYA_MASTER_PASSWORD) deliberately have no\n * flag: process arguments are world-readable through `ps` on most systems.\n */\nconst ENV_FLAGS: { flag: string; env: string }[] = [\n { flag: '--host', env: 'RUNEYA_HOST' },\n { flag: '--agent-port', env: 'RUNEYA_AGENT_PORT' },\n { flag: '--agent-host', env: 'RUNEYA_AGENT_HOST' },\n { flag: '--agent-binary-path', env: 'RUNEYA_AGENT_BINARY_PATH' },\n { flag: '--data-dir', env: 'RUNEYA_DATA_DIR' },\n { flag: '--mode', env: 'RUNEYA_MODE' },\n { flag: '--cloud-url', env: 'RUNEYA_CLOUD_URL' },\n { flag: '--cloud-app-url', env: 'RUNEYA_CLOUD_APP_URL' },\n { flag: '--cors-origin', env: 'RUNEYA_CORS_ORIGIN' },\n { flag: '--claude-pty', env: 'RUNEYA_CLAUDE_PTY' },\n { flag: '--project', env: 'RUNEYA_PROJECT_ID' },\n];\n\n// Flags taking a value — needed so their value is not mistaken for the target directory\nconst flagsWithValues = new Set([\n '--port',\n '--name',\n '-e', '--environment',\n '-s', '--service',\n ...ENV_FLAGS.map((f) => f.flag),\n]);\n\n// Apply value flags to their env var (flag wins over an already-set variable).\n// Done before dotenv so a .env file can never override an explicit flag.\nfor (const { flag, env: key } of ENV_FLAGS) {\n const value = getFlagValue([flag]);\n if (value !== undefined) process.env[key] = value;\n}\n// --debug is a boolean shortcut for RUNEYA_DEBUG=1\nif (args.includes('--debug')) process.env['RUNEYA_DEBUG'] = '1';\n\n/**\n * La page d'installation du raccourci. Rend quand on la quitte : le code de\n * sortie du process.\n *\n * `required` : ouverte par un `runeya` lancé hors raccourci (voir\n * `install-gate.ts`), et non par `runeya install-desktop`.\n */\nasync function runDesktopInstaller(required: boolean): Promise<number> {\n const { installDesktopLauncher, listDesktopLaunchers, uninstallDesktopLauncher, deriveIdentity } =\n await import('./desktop-launcher.js');\n const { printInstallReport } = await import('./desktop-wizard.js');\n const { runInstallerPage } = await import('./desktop-installer-page.js');\n const { createGlobalInstaller } = await import('./install-gate.js');\n\n // Ce que viseront les raccourcis : ce CLI, puis la copie globale une fois installée.\n const current = { nodePath: process.execPath, cliEntry: fileURLToPath(import.meta.url) };\n const outcome = await runInstallerPage({\n openUrl: (url) => open(url),\n install: (answers) => installDesktopLauncher({\n ...current,\n distDir: dirname(current.cliEntry),\n ...answers,\n ...deriveIdentity(answers.name, answers.workingDir),\n }),\n list: listDesktopLaunchers,\n uninstall: (launcher) => uninstallDesktopLauncher(launcher.name, launcher.id),\n current,\n global: await createGlobalInstaller(current, version),\n required,\n });\n if (!outcome) return 130; // annulé depuis la page ou par Ctrl+C\n const { answers, result } = outcome;\n printInstallReport({ ...answers, nodePath: process.execPath, result });\n return 0;\n}\n\n/**\n * `install-desktop` / `uninstall-desktop` — handled before anything else so the\n * sub-command name is never mistaken for a target directory, and so the current\n * working directory is still the user's when we capture it.\n *\n * Bare on a TTY, `install-desktop` opens a dedicated installer page served by a\n * short-lived local server — Runeya itself is not started. Any flag that\n * pre-answers a question installs directly so scripts stay unattended.\n */\nconst subCommand = args[0];\nif (subCommand === 'install-desktop' || subCommand === 'uninstall-desktop') {\n const { installDesktopLauncher, uninstallDesktopLauncher, deriveIdentity } =\n await import('./desktop-launcher.js');\n const { shouldOpenInstallPage, printInstallReport, printUninstallReport } =\n await import('./desktop-wizard.js');\n\n const { parsePort } = await import('./free-port.js');\n\n const rest = args.slice(1);\n // Every flag of this sub-command that takes a value: without this, the value\n // itself (a port number, a name) is mistaken for the target directory.\n const subFlagsWithValues = new Set(['--name', '--port', '--agent-port', '--project']);\n const positional = rest.find((a, i) => !a.startsWith('-') && !subFlagsWithValues.has(rest[i - 1] ?? ''));\n const nameFlag = getFlagValue(['--name']);\n\n // Ports baked into the shortcut. Null means \"follow Runeya's default\", so a\n // launcher created without them keeps tracking the default if it changes.\n const portFlagRaw = getFlagValue(['--port']);\n const agentPortFlagRaw = getFlagValue(['--agent-port']);\n for (const [flag, raw] of [['--port', portFlagRaw], ['--agent-port', agentPortFlagRaw]] as const) {\n if (raw !== undefined && parsePort(raw) === null) {\n console.error(`Erreur : ${flag} attend un entier entre 1 et 65535 (reçu ${JSON.stringify(raw)}).`);\n process.exit(1);\n }\n }\n const port = parsePort(portFlagRaw);\n const agentPort = parsePort(agentPortFlagRaw);\n\n // Le projet que le raccourci ouvre directement, sans passer par la liste.\n const projectId = getFlagValue(['--project']) ?? null;\n if (projectId !== null) {\n const { isLauncherProjectId } = await import('@runeya/packages-shared');\n if (!isLauncherProjectId(projectId)) {\n console.error(`Erreur : --project attend un id de projet (reçu ${JSON.stringify(projectId)}).`);\n process.exit(1);\n }\n }\n\n // The data directory is resolved from the working directory, so a launcher\n // that does not pin one would start Runeya in the desktop's cwd (usually the\n // home directory) and create a stray .runeya there. Pin the cwd by default.\n const workingDir = rest.includes('--no-cwd') ? null : resolve(positional ?? process.cwd());\n const displayName = nameFlag;\n\n const launcherBase = { nodePath: process.execPath, cliEntry: fileURLToPath(import.meta.url), distDir: __dirname };\n\n if (subCommand === 'install-desktop' && shouldOpenInstallPage(rest, positional !== undefined)) {\n process.exit(await runDesktopInstaller(false));\n }\n\n const { name, id } = deriveIdentity(displayName, workingDir);\n\n // Même règle que la page : un raccourci vers une copie npx ou un clone cesserait\n // de marcher le jour où elle disparaît. Un clone de développement passe par\n // RUNEYA_SKIP_INSTALL_CHECK=1, comme pour démarrer Runeya.\n if (subCommand === 'install-desktop') {\n const { createGlobalInstaller, SKIP_INSTALL_CHECK_ENV } = await import('./install-gate.js');\n if (process.env[SKIP_INSTALL_CHECK_ENV] !== '1') {\n // Une copie globale à jour déjà présente est retenue : le raccourci la vise.\n const target = { cliEntry: launcherBase.cliEntry };\n const global = await (await createGlobalInstaller(target, version)).state();\n launcherBase.cliEntry = target.cliEntry;\n launcherBase.distDir = dirname(target.cliEntry);\n if (!global.installed) {\n console.error('Erreur : ce Runeya n’est pas installé globalement, le raccourci ne marcherait plus une fois cette copie supprimée.');\n console.error('Lancez « runeya install-desktop » sans option pour l’installer depuis la page, ou « npm install -g @runeya/runeya ».');\n process.exit(1);\n }\n }\n }\n\n try {\n if (subCommand === 'install-desktop') {\n const result = await installDesktopLauncher({\n ...launcherBase,\n workingDir,\n name,\n id,\n port,\n agentPort,\n projectId,\n });\n printInstallReport({ name, workingDir, nodePath: process.execPath, port, agentPort, result });\n } else {\n printUninstallReport(name, await uninstallDesktopLauncher(name, id));\n }\n process.exit(0);\n } catch (err) {\n console.error(`Erreur : ${(err as Error).message}`);\n process.exit(1);\n }\n}\n\n/**\n * `runeya instances` — voir et piloter les Runeya de cette machine depuis un\n * terminal. Traité ici, avec les autres sous-commandes, pour que le mot\n * « instances » ne soit jamais pris pour un répertoire cible.\n *\n * Le pendant de l'icône de barre système, qui ne montre qu'une instance — la\n * sienne — et n'existe pas partout. Celle-ci les montre toutes, partout.\n *\n * Aucun serveur n'est démarré : le registre machine est un dossier de fichiers,\n * et le lire ne demande rien d'autre que de le lire.\n */\nif (subCommand === 'instances') {\n // Importé ici et pas en tête de fichier : charger `@runeya/apps-server` a un\n // coût, et un `runeya` ordinaire n'a pas à le payer pour une sous-commande\n // qu'il n'utilise pas.\n const { listInstances, killInstance, restartInstance } = await import('@runeya/apps-server');\n const { runInstancesCommand } = await import('./instances-command.js');\n\n process.exit(await runInstancesCommand(args.slice(1), {\n listInstances,\n stopInstance: killInstance,\n restartInstance: async (pid: number) => {\n const { pid: newPid, portReleased } = await restartInstance(pid);\n return { pid: newPid, portReleased };\n },\n openUrl: (url: string) => open(url),\n log: (message: string) => console.log(message),\n warn: (message: string) => console.error(message),\n }));\n}\n\n/**\n * `runeya mcp` — le serveur MCP de Runeya pour un client lancé hors de Runeya\n * (Claude Code, Codex, Cursor…). La config du client appelle cette commande et\n * non un chemin de fichier : le MCP suit ainsi les mises à jour du CLI.\n *\n * Stdout porte le protocole MCP : rien d'autre ne doit y écrire.\n */\nif (subCommand === 'mcp') {\n const { listInstances } = await import('@runeya/apps-server');\n const { runExternalMcp } = await import('@runeya/packages-mcp-server/external');\n await runExternalMcp({ listInstances });\n // Le reste de ce fichier démarre un serveur : ne jamais l'atteindre. Une\n // promesse en attente ne retient pas le process, qui s'arrête quand le\n // client ferme stdin.\n await new Promise(() => {});\n}\n\n// Resolve target directory (first positional arg, skipping flag values)\nconst targetDir = args.find((a, i) => !a.startsWith('-') && !flagsWithValues.has(args[i - 1] ?? ''));\nif (targetDir) {\n const resolved = resolve(targetDir);\n process.chdir(resolved);\n console.log(`[cli] Working directory: ${resolved}`);\n} else if (process.env['RUNEYA_DATA_DIR']) {\n const resolved = resolve(process.env['RUNEYA_DATA_DIR'], '..');\n process.chdir(resolved);\n console.log(`[cli] Working directory: ${resolved} (from RUNEYA_DATA_DIR)`);\n} else if (process.cwd() === '/') {\n /**\n * On n'écrit jamais à la racine.\n *\n * Un lanceur global — installé sans dossier épinglé — démarre avec le cwd que\n * lui donne le système, et le Finder comme les services systemd donnent `/`.\n * `DATA_DIR` y vaudrait `/.runeya` : sous macOS la racine est le volume\n * système signé, monté en lecture seule, et la première écriture locale\n * échouerait en EROFS — que même root ne peut pas lever sans\n * `/etc/synthetic.conf` et un redémarrage. Sous Linux elle demanderait les\n * droits du superutilisateur pour un dossier qui n'a rien à faire là.\n *\n * Le repli vaut aussi pour les lanceurs DÉJÀ installés, que corriger le stub\n * ne rattraperait pas.\n */\n const home = homedir();\n process.chdir(home);\n console.log(`[cli] Working directory: ${home} (lanceur sans dossier épinglé)`);\n}\n\ndotenv.config({ quiet: true });\n\nif (args.includes('--help') || args.includes('-h')) {\n console.log(`Usage: runeya [path-to-your-stack] [options]\n\nCommands:\n install-desktop [path] Create a desktop/menu launcher for this machine\n Bare on a terminal, this opens a dedicated installer page.\n uninstall-desktop Remove a launcher created by install-desktop\n --name <label> Launcher name (default: \"Runeya — <folder>\")\n --no-cwd Global launcher — do not pin a working directory\n --port <n> Port baked into the launcher (default: Runeya's own)\n --agent-port <n> Agent port baked in (default: launcher port + 1)\n --project <id> Open this project directly (no project list)\n -y, --yes Skip the wizard and take the defaults\n instances [open|stop|restart <pid>]\n List the Runeya running on this machine, and act on\n one. --json for the raw records.\n mcp Runeya MCP server on stdio, for Claude Code, Codex,\n Cursor… Asks for access in the Runeya app on first use.\n --from-desktop Set by desktop launchers: report startup failures\n in a browser window instead of a silent exit\n\nOptions:\n --version Show version number\n --pe, --pull-env Print env vars for a service to stdout (requires -e and -s)\n -e, --environment <n> Environment name or id\n -s, --service <name> Service name or id\n --lan Expose server on the local network (shortcut for --host 0.0.0.0)\n --no-open Do not open browser on startup\n --no-tray Do not put this instance in the system tray\n --agent Run as agent only (no server, no UI) — for remote machines\n -h, --help Show this help message\n\nConfiguration:\n Each setting has a flag and an equivalent RUNEYA_ environment variable; the\n flag wins. Variables are prefixed so they cannot collide with those of the\n services you manage. A .env file in the working directory is loaded\n automatically, but never overrides a flag.\n\n Flag Environment variable Default\n --port <n> RUNEYA_HTTP_PORT 4000\n (binds the agent instead when --agent is used)\n --host <address> RUNEYA_HOST 127.0.0.1\n --agent-port <n> RUNEYA_AGENT_PORT server port + 1\n --agent-host <address> RUNEYA_AGENT_HOST 127.0.0.1\n --agent-binary-path <path> RUNEYA_AGENT_BINARY_PATH bundled with the CLI\n --data-dir <path> RUNEYA_DATA_DIR <cwd>/.runeya\n --mode <mode> RUNEYA_MODE local-simple\n 'local-simple' | 'cloud'\n --cloud-url <url> RUNEYA_CLOUD_URL —\n --cloud-app-url <url> RUNEYA_CLOUD_APP_URL —\n --cors-origin <origin> RUNEYA_CORS_ORIGIN —\n --lan RUNEYA_LAN_PROXY false\n --debug RUNEYA_DEBUG false\n --claude-pty <0|1> RUNEYA_CLAUDE_PTY 1\n --project <id> RUNEYA_PROJECT_ID —\n Open this project only: no project list, no switching\n PTY mode for the Claude Code runner\n\n Secrets have no flag — process arguments are readable by other users via 'ps':\n RUNEYA_ENCRYPTION_KEY 64-char hex key for CI/CD — unlocks secrets without a\n master password AND disables tRPC authentication.\n Never set this on a machine reachable by others.\n RUNEYA_MASTER_PASSWORD Master password used by --pull-env instead of prompting\n\n Started from a terminal, 'runeya' opens the desktop shortcut installer instead\n of Runeya itself. RUNEYA_SKIP_INSTALL_CHECK=1 starts Runeya anyway (servers,\n containers, CI).\n\n Standard variables Runeya also honours: NODE_ENV, CI (skips opening the browser).\n`);\n process.exit(0);\n}\n\nif (args.includes('--version')) {\n console.log(version);\n process.exit(0);\n}\n\n/**\n * L'icône de barre système, sauf `--no-tray`.\n *\n * Chaque Runeya pose la sienne au démarrage et la retire en s'arrêtant : une\n * icône par instance en cours. Là où la barre système n'existe pas (serveur\n * sans bureau, arm64, paquet optionnel absent), il n'y a rien à désactiver —\n * l'icône ne se pose pas, et Runeya démarre pareil.\n */\nconst noTray = args.includes('--no-tray');\n\nconst noOpen =\n args.includes('--no-open') ||\n !!process.env['VITEST'] ||\n !!process.env['CI'] ||\n process.env['NODE_ENV'] === 'test';\n\n// --pull-env flag — detect early so we can silence stdout before any log\nconst isPullEnv = args.includes('--pull-env') || args.includes('--pe');\n\n// In pull-env mode, redirect console.log/info to stderr so only KEY=VALUE goes to stdout\nif (isPullEnv) {\n const toStderr = (...a: unknown[]) => process.stderr.write(a.join(' ') + '\\n');\n console.log = toStderr;\n console.info = toStderr;\n}\n\nconst serviceArg = getFlagValue(['-s', '--service']);\nconst environmentArg = getFlagValue(['-e', '--environment']);\n\n// Configure environment BEFORE importing server (env is parsed at module load)\n// --agent mode: run as standalone agent only (no server, no UI)\nconst isAgentOnly = args.includes('--agent');\n\n// --port targets the server, except in agent mode where it binds the agent\nconst portFlag = getFlagValue(['--port']);\nif (portFlag) {\n process.env[isAgentOnly ? 'RUNEYA_AGENT_PORT' : 'RUNEYA_HTTP_PORT'] = portFlag;\n}\n\n// --lan binds to 0.0.0.0. As an explicit flag it outranks RUNEYA_HOST; coming\n// from RUNEYA_LAN_PROXY it only fills in a host nobody else set.\nconst hostFlag = getFlagValue(['--host']);\nconst isLan = args.includes('--lan');\nconst isLanProxy = isLan || process.env.RUNEYA_LAN_PROXY === 'true' || process.env.RUNEYA_LAN_PROXY === '1';\nif (isLanProxy) {\n process.env.RUNEYA_LAN_PROXY = 'true';\n if (!hostFlag && isLan) process.env.RUNEYA_HOST = '0.0.0.0';\n else process.env.RUNEYA_HOST ??= '0.0.0.0';\n}\n\n// In agent mode --host binds the agent rather than the server\nif (isAgentOnly) {\n if (hostFlag) {\n process.env.RUNEYA_AGENT_HOST = hostFlag;\n } else if (isLan) {\n process.env.RUNEYA_AGENT_HOST = '0.0.0.0';\n } else if (isLanProxy) {\n process.env.RUNEYA_AGENT_HOST ??= '0.0.0.0';\n }\n}\n\n// Agent binary shipped inside the CLI dist — overridable via --agent-binary-path\nprocess.env.RUNEYA_AGENT_BINARY_PATH ??= join(__dirname, 'agent/index.js');\n// Expose CLI version to server\nprocess.env.RUNEYA_VERSION = version;\n// Tell the server it was launched from a shortcut, so the UI can say so\nif (isFromDesktop) process.env.RUNEYA_FROM_DESKTOP = '1';\n// Data directory defaults to CWD/.runeya (server env.ts default)\n// so Runeya data lives alongside the target project.\n\n/**\n * Listen with retry for EADDRINUSE — handles the race condition when the CLI\n * restarts the server before the old process has fully released the port.\n *\n * The `wss` parameter is needed because the `ws` library re-emits HTTP server\n * errors on the WebSocketServer — without a handler the error becomes unhandled.\n */\nfunction listenWithRetry(\n server: Server,\n port: number,\n host: string,\n wss?: WebSocketServer,\n maxRetries = 20,\n delay = 500,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n\n // Absorb EADDRINUSE errors re-emitted by the ws library on the WSS\n // during the retry window. Without this, Node.js crashes on unhandled error.\n const wssErrorHandler = () => { /* absorbed — handled via server 'error' */ };\n wss?.on('error', wssErrorHandler);\n\n const tryListen = () => {\n const onError = (err: NodeJS.ErrnoException) => {\n // Clean up the 'listening' callback that server.listen() registered\n server.removeAllListeners('listening');\n\n if (err.code === 'EADDRINUSE' && attempts < maxRetries) {\n attempts++;\n console.log(`[cli] Port ${port} in use, retrying in ${delay}ms (${attempts}/${maxRetries})...`);\n setTimeout(tryListen, delay);\n } else {\n wss?.removeListener('error', wssErrorHandler);\n reject(err);\n }\n };\n\n server.once('error', onError);\n server.listen(port, host, () => {\n server.removeListener('error', onError);\n wss?.removeListener('error', wssErrorHandler);\n resolve();\n });\n };\n\n tryListen();\n });\n}\n\nasync function main() {\n // Hors raccourci, `runeya` mène à la page d'installation (voir install-gate.ts).\n const { mustOpenInstaller, hasDesktop, SKIP_INSTALL_CHECK_ENV } = await import('./install-gate.js');\n if (mustOpenInstaller({\n isFromDesktop,\n isRestartHandoff: process.env.RUNEYA_RESTART_HANDOFF === '1',\n startsServer: !isPullEnv && !isAgentOnly,\n env: process.env,\n })) {\n const { shouldOpenInstallPage } = await import('./desktop-wizard.js');\n if (!hasDesktop(process.platform, process.env)) {\n // Serveur, SSH : ni page à montrer, ni menu où poser un raccourci.\n console.error('Aucun bureau sur cette session (SSH ou serveur sans affichage) : pas de raccourci à créer ici.');\n console.error(`Pour démarrer Runeya directement : ${SKIP_INSTALL_CHECK_ENV}=1 runeya`);\n process.exit(1);\n }\n if (!shouldOpenInstallPage([], false)) {\n // Sans terminal (script, CI), personne ne verrait la page.\n console.error('Runeya se lance depuis un raccourci de bureau : lancez « runeya » dans un terminal pour le créer.');\n console.error(`Pour démarrer Runeya sans raccourci (serveur, CI) : ${SKIP_INSTALL_CHECK_ENV}=1 runeya`);\n process.exit(1);\n }\n process.exit(await runDesktopInstaller(true));\n }\n\n // Avant tout : ce que ce process hérite ici, le serveur, l'agent local et\n // chaque service lancé ensuite en héritent à leur tour. Un raccourci de bureau\n // reçoit le PATH de la session graphique, où ni les gestionnaires de version\n // ni les binaires installés par l'utilisateur (claude, codex) ne figurent.\n const { ensureNodeBinOnPath, ensureUserBinsOnPath, stampConsole } = await import('@runeya/packages-shared/node');\n ensureNodeBinOnPath();\n await ensureUserBinsOnPath();\n\n // Journaux datés du temps écoulé depuis le démarrage. Jamais en --pull-env :\n // sa sortie est lue par un script, pas par un humain.\n if (!isPullEnv) {\n stampConsole();\n // Sortie et crash recopiés sur disque : une instance relancée en\n // `stdio: 'ignore'` (bureau, mise à jour) n'a sinon aucune trace.\n try {\n const { installLogFile } = await import('./log-file.js');\n console.log(`[cli] Journal : ${installLogFile().logPath}`);\n } catch (err) {\n console.warn(`[cli] Journal sur disque indisponible : ${(err as Error).message}`);\n }\n }\n\n // Dynamic import ensures env is parsed AFTER we configure it\n const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import('@runeya/apps-server');\n\n // D'où ce CLI a été lancé, pour que l'interface puisse proposer `install-desktop`\n // sans que le serveur ait à deviner un exécutable.\n registerCliLocation({ execPath: process.execPath, cliEntry: fileURLToPath(import.meta.url) });\n\n // Handle --pull-env mode: resolve env vars and print, then exit\n if (isPullEnv) {\n if (!serviceArg) {\n console.error('Error: --service (-s) is required with --pull-env');\n process.exit(1);\n }\n if (!environmentArg) {\n console.error('Error: --environment (-e) is required with --pull-env');\n process.exit(1);\n }\n try {\n const output = await pullEnv({ service: serviceArg, environment: environmentArg });\n if (output) process.stdout.write(output + '\\n');\n process.exit(0);\n } catch (err: unknown) {\n if (err instanceof PullEnvError) {\n console.error(`Error: ${err.message}`);\n process.exit(err.exitCode);\n }\n throw err;\n }\n }\n\n // --agent mode: standalone agent, no server, no UI\n if (isAgentOnly) {\n const { spawn } = await import('node:child_process');\n const agentBin = join(__dirname, 'agent/index.js');\n const child = spawn(process.execPath, [agentBin], { stdio: 'inherit', windowsHide: true });\n child.on('exit', (code) => process.exit(code ?? 0));\n // SIGINT is already delivered to the child by the terminal (same process group).\n // Intercept it here only to suppress Node's default exit so we stay alive\n // until the child finishes its graceful shutdown.\n process.on('SIGINT', () => { /* wait for child to exit */ });\n process.on('SIGTERM', () => child.kill('SIGTERM'));\n return;\n }\n\n /**\n * Un relais de redémarrage (`appUpdate.restart`) est l'exception au garde-fou\n * ci-dessous : l'instance qui répond encore sur le port est précisément celle\n * qu'on remplace. On la laisse s'éteindre, `listenWithRetry` absorbe\n * l'EADDRINUSE du chevauchement. La marque est consommée ici pour ne pas se\n * propager aux services lancés ensuite, qui héritent de cet environnement.\n */\n const isRestartHandoff = process.env.RUNEYA_RESTART_HANDOFF === '1';\n delete process.env.RUNEYA_RESTART_HANDOFF;\n\n /**\n * A shortcut clicked twice must not fail.\n *\n * Starting a second instance on a port a Runeya already holds ends in\n * EADDRINUSE after ten seconds of retries — and from a launcher there is no\n * terminal to read that in. So the port is asked first: if Runeya answers,\n * the right move is to bring up the window that already exists.\n *\n * Only for launcher starts. From a terminal, `runeya` twice on one port is a\n * mistake worth reporting, not one worth papering over.\n */\n if (isFromDesktop && !isRestartHandoff) {\n const port = resolvePort();\n const { probeRuneya } = await import('./free-port.js');\n const existing = await probeRuneya(port);\n if (existing) {\n const url = `http://localhost:${port}`;\n console.log(`[cli] Runeya v${existing.version} déjà en cours sur le port ${port} — ouverture de ${url}`);\n if (!noOpen) await open(url);\n return;\n }\n }\n\n console.log('[cli] Starting Runeya...');\n\n // Create server (automatically spawns local agent)\n const { app, server, wss, shutdown } = await createLocalServer();\n\n // Serve static files from web frontend (embedded in CLI dist during build)\n const webDistPath = join(__dirname, 'web');\n\n /**\n * Les fichiers d'`assets/` portent un hash de leur contenu dans leur nom : une\n * mise à jour produit un NOUVEAU nom, jamais un contenu différent sous le même\n * nom. Ils peuvent donc être gardés indéfiniment, et `immutable` dit au\n * navigateur de ne même pas revalider.\n *\n * Sans cela, `express.static` répond `max-age=0` : chaque rechargement\n * redemande les 295 fichiers pour s'entendre répondre 304. Ce sont des\n * requêtes vides, mais elles occupent les six connexions qu'un navigateur\n * accorde par hôte — pour tous ses onglets à la fois. Avec plusieurs onglets\n * rechargés ensemble, l'ouverture du WebSocket attendait derrière cette file.\n */\n app.use('/assets', express.static(join(webDistPath, 'assets'), {\n immutable: true,\n maxAge: '1y',\n fallthrough: false,\n }));\n\n // Tout le reste (favicon…) : revalidation à chaque fois, ces noms ne changent\n // pas d'une version à l'autre.\n app.use(express.static(webDistPath, {\n index: false,\n setHeaders: (res) => res.setHeader('Cache-Control', 'no-cache'),\n }));\n\n // Fallback to index.html for client-side routing (Vue Router)\n // Express 5 requires explicit path patterns (not '*')\n //\n // JAMAIS mis en cache : c'est lui qui nomme les assets de la version courante.\n // Un index.html périmé rappellerait les fichiers de l'ancienne version — qui,\n // eux, ne sont plus là.\n //\n // `root` + nom relatif, jamais un chemin absolu : `sendFile` refuse tout\n // segment commençant par un point (`dotfiles: 'ignore'` par défaut) et\n // répond 404. Or l'installation la plus courante — `npx @runeya/runeya` —\n // vit sous `~/.npm/_npx/…`. Avec un chemin absolu, la page d'accueil était\n // donc introuvable sur toute machine lancée par npx (ou depuis `~/.nvm`),\n // alors que `/index.html` répondait : `express.static` ne teste, lui, que la\n // partie relative à sa racine.\n app.use((_req: Request, res: Response) => {\n res.setHeader('Cache-Control', 'no-cache');\n res.sendFile('index.html', { root: webDistPath });\n });\n\n const port = resolvePort();\n const host = process.env.RUNEYA_HOST ?? '127.0.0.1';\n\n await listenWithRetry(server, port, host, wss);\n\n // Announce this instance now that the port is really ours, so the settings\n // panel of any Runeya on this machine can list it.\n await registerInstance();\n\n /**\n * L'adresse d'écoute n'est pas une adresse de visite.\n *\n * `0.0.0.0` (et son équivalent IPv6 `::`) dit « toutes les interfaces » à\n * bind ; ce n'est pas une destination. Sous Linux une connexion vers elle\n * retombe sur la boucle locale, ce qui a longtemps masqué le problème — sous\n * Windows elle n'est pas routable du tout, et les navigateurs la bloquent\n * désormais ailleurs aussi. On écoute donc partout, mais on ouvre localhost.\n */\n const browseHost = host === '0.0.0.0' || host === '::' ? 'localhost' : host;\n const appUrl = `http://${browseHost}:${port}`;\n\n if (!noOpen) {\n await open(appUrl);\n }\n\n console.log('\\n🚀 Runeya is running!');\n if (isLanProxy) {\n console.log('🌐 LAN mode: server and service ports exposed on local network');\n }\n printStartupTable(port, appUrl);\n console.log('[cli] Press Ctrl+C to stop');\n\n // Assignée plus bas : l'arrêt doit pouvoir la retirer, et la poser demande\n // de savoir arrêter — les deux se référencent.\n let tray: { stop: () => Promise<void> } | null = null;\n\n let shuttingDown = false;\n const gracefulShutdown = async (signal: string) => {\n if (shuttingDown) {\n console.log(`[cli] Forced exit (second ${signal})`);\n process.exit(1);\n }\n shuttingDown = true;\n console.log(`\\n[cli] Received ${signal}, shutting down gracefully...`);\n\n // L'icône part en premier : elle annonce une instance vivante, et la\n // laisser pendant l'extinction inviterait à cliquer dans le vide.\n await tray?.stop();\n\n // In dev, exit immediately — ports are freed on process death,\n // and the 'exit' handler in agent-spawner SIGKILLs the agent.\n if (process.env.NODE_ENV === 'development') {\n process.exit(0);\n }\n\n await shutdown();\n console.log('[cli] Shutdown complete');\n process.exit(0);\n };\n\n process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n process.on('SIGINT', () => gracefulShutdown('SIGINT'));\n\n if (!noTray) {\n const { startInstanceTray } = await import('./tray.js');\n const {\n scheduleSelfRestart,\n listTrayServices,\n onTrayServicesChanged,\n startProcess,\n stopProcess,\n restartProcess,\n networkInfo,\n setLanMode,\n resolveTrayIcon,\n } = await import('@runeya/apps-server');\n\n tray = await startInstanceTray({\n info: { cwd: process.cwd(), port, version, url: appUrl },\n assetsDir: join(__dirname, 'assets'),\n openUrl: (target) => open(target),\n restart: () => scheduleSelfRestart(),\n stop: () => void gracefulShutdown('tray'),\n\n listServices: listTrayServices,\n startService: (id) => startProcess(id),\n // L'arrêt exige l'agent qui le fait tourner : il est dans la vue, et\n // seul un service en cours propose ce geste.\n stopService: async (id) => {\n const service = (await listTrayServices()).find((s) => s.id === id);\n if (!service?.agentId) throw new Error(`Aucun agent pour ${id}`);\n return stopProcess(id, service.agentId);\n },\n restartService: (id) => restartProcess(id),\n onServicesChanged: onTrayServicesChanged,\n // Le logo de l'organisation du projet ouvert, quand il y en a un : c'est ce\n // qui distingue deux Runeya dans la barre système.\n projectIcon: () => resolveTrayIcon(),\n\n lan: {\n read: () => {\n const info = networkInfo();\n // `lanUrls` est déjà ce qu'on voudrait lire au survol : des adresses\n // joignables, pas des IP brutes. Vide hors mode réseau local.\n return { enabled: info.lanEnabled, addresses: info.lanUrls };\n },\n toggle: (enabled) => setLanMode(enabled),\n },\n\n warn: (message) => console.log(message),\n });\n }\n}\n\nmain().catch(async (err) => {\n console.error('[cli] Fatal error:', err);\n\n // With a terminal, the message above is the report. Without one, it goes\n // nowhere: serve it as a page and open it in the browser instead.\n if (startupFailure) {\n try {\n const { diagnose, renderFailurePage, capturedLines, showStartupFailure } = startupFailure;\n const html = renderFailurePage(\n diagnose(err, resolvePort()),\n capturedLines(),\n {\n 'Version': version,\n 'Dossier de travail': process.cwd(),\n 'Node': process.execPath,\n 'Runeya': fileURLToPath(import.meta.url),\n },\n );\n await showStartupFailure(html);\n } catch (reportErr) {\n console.error('[cli] Impossible d\\'afficher le rapport d\\'erreur:', reportErr);\n }\n }\n\n process.exit(1);\n});\n","/**\n * Resolve the HTTP port Runeya should listen on.\n *\n * Only RUNEYA_HTTP_PORT is read (default 4000) — the generic PORT variable is\n * intentionally ignored so it can stay reserved for the user's own services.\n *\n * Throws if the resolved value is not an integer in [1, 65535].\n */\nexport function resolvePort(): number {\n const raw = process.env.RUNEYA_HTTP_PORT;\n if (raw === undefined) return 4000;\n\n const port = Number(raw);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(\n `Invalid port: ${JSON.stringify(raw)}. Must be an integer between 1 and 65535.`,\n );\n }\n return port;\n}\n"],"mappings":"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","names":["answers","resolve","port"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/port-resolution.ts"],"sourcesContent":["#!/usr/bin/env node\nimport type { Server } from 'node:http';\nimport type { WebSocketServer } from 'ws';\nimport type { Request, Response } from 'express';\nimport { fileURLToPath, URL as NodeURL } from 'node:url';\nimport { dirname, join, resolve } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport express from 'express';\nimport dotenv from 'dotenv'\nimport open from 'open';\nimport { resolvePort } from './port-resolution.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst { version } = JSON.parse(\n readFileSync(new NodeURL('./package.json', import.meta.url), 'utf8'),\n) as { version: string };\n\nfunction printStartupTable(port: number, appUrl: string): void {\n const rows: [string, string][] = [\n ['Version', version],\n ['Port', String(port)],\n ['Url', appUrl],\n ];\n\n const col0 = Math.max(...rows.map(([k]) => k.length));\n const col1 = Math.max(...rows.map(([, v]) => v.length));\n\n const pad = (s: string, n: number) => s.padEnd(n);\n const hr = (l: string, m: string, r: string, f: string) =>\n l + f.repeat(col0 + 2) + m + f.repeat(col1 + 2) + r;\n\n console.log('');\n console.log(hr('┌', '┬', '┐', '─'));\n for (const [key, value] of rows) {\n console.log(`│ ${pad(key, col0)} │ ${pad(value, col1)} │`);\n }\n console.log(hr('└', '┴', '┘', '─'));\n console.log('');\n}\n\n// Parse CLI flags\nconst args = process.argv.slice(2);\n\n/**\n * Set by the desktop launcher. It means nobody is watching a terminal, so a\n * startup failure has to be reported through a window of its own.\n */\nconst isFromDesktop = args.includes('--from-desktop');\n\n// Capture must start before anything logs, hence this early import.\nconst startupFailure = isFromDesktop ? await import('./startup-failure.js') : null;\nstartupFailure?.captureOutput();\n\nfunction getFlagValue(flags: string[]): string | undefined {\n for (const flag of flags) {\n const idx = args.indexOf(flag);\n if (idx !== -1 && idx + 1 < args.length) return args[idx + 1];\n }\n return undefined;\n}\n\n/**\n * Flags that mirror a RUNEYA_* environment variable. The flag always wins over\n * the variable, and both are equivalent otherwise.\n *\n * Secrets (RUNEYA_ENCRYPTION_KEY, RUNEYA_MASTER_PASSWORD) deliberately have no\n * flag: process arguments are world-readable through `ps` on most systems.\n */\nconst ENV_FLAGS: { flag: string; env: string }[] = [\n { flag: '--host', env: 'RUNEYA_HOST' },\n { flag: '--agent-port', env: 'RUNEYA_AGENT_PORT' },\n { flag: '--agent-host', env: 'RUNEYA_AGENT_HOST' },\n { flag: '--agent-binary-path', env: 'RUNEYA_AGENT_BINARY_PATH' },\n { flag: '--data-dir', env: 'RUNEYA_DATA_DIR' },\n { flag: '--cloud-url', env: 'RUNEYA_CLOUD_URL' },\n { flag: '--cloud-app-url', env: 'RUNEYA_CLOUD_APP_URL' },\n { flag: '--cors-origin', env: 'RUNEYA_CORS_ORIGIN' },\n { flag: '--claude-pty', env: 'RUNEYA_CLAUDE_PTY' },\n { flag: '--project', env: 'RUNEYA_PROJECT_ID' },\n];\n\n// Flags taking a value — needed so their value is not mistaken for the target directory\nconst flagsWithValues = new Set([\n '--port',\n '--name',\n '-e', '--environment',\n '-s', '--service',\n // Retiré, mais encore accepté et ignoré : sans cela, un ancien script lancé\n // avec `--mode local-simple` prendrait `local-simple` pour le dossier cible.\n '--mode',\n ...ENV_FLAGS.map((f) => f.flag),\n]);\n\n// Apply value flags to their env var (flag wins over an already-set variable).\n// Done before dotenv so a .env file can never override an explicit flag.\nfor (const { flag, env: key } of ENV_FLAGS) {\n const value = getFlagValue([flag]);\n if (value !== undefined) process.env[key] = value;\n}\n// --debug is a boolean shortcut for RUNEYA_DEBUG=1\nif (args.includes('--debug')) process.env['RUNEYA_DEBUG'] = '1';\n\n/**\n * La page d'installation du raccourci. Rend quand on la quitte : le code de\n * sortie du process.\n *\n * `required` : ouverte par un `runeya` lancé hors raccourci (voir\n * `install-gate.ts`), et non par `runeya install-desktop`.\n */\nasync function runDesktopInstaller(required: boolean): Promise<number> {\n const { installDesktopLauncher, listDesktopLaunchers, uninstallDesktopLauncher, deriveIdentity } =\n await import('./desktop-launcher.js');\n const { printInstallReport } = await import('./desktop-wizard.js');\n const { runInstallerPage } = await import('./desktop-installer-page.js');\n const { createGlobalInstaller } = await import('./install-gate.js');\n\n // Ce que viseront les raccourcis : ce CLI, puis la copie globale une fois installée.\n const current = { nodePath: process.execPath, cliEntry: fileURLToPath(import.meta.url) };\n const outcome = await runInstallerPage({\n openUrl: (url) => open(url),\n install: (answers) => installDesktopLauncher({\n ...current,\n distDir: dirname(current.cliEntry),\n ...answers,\n ...deriveIdentity(answers.name, answers.workingDir),\n }),\n list: listDesktopLaunchers,\n uninstall: (launcher) => uninstallDesktopLauncher(launcher.name, launcher.id),\n current,\n global: await createGlobalInstaller(current, version),\n required,\n });\n if (!outcome) return 130; // annulé depuis la page ou par Ctrl+C\n const { answers, result } = outcome;\n printInstallReport({ ...answers, nodePath: process.execPath, result });\n return 0;\n}\n\n/**\n * `install-desktop` / `uninstall-desktop` — handled before anything else so the\n * sub-command name is never mistaken for a target directory, and so the current\n * working directory is still the user's when we capture it.\n *\n * Bare on a TTY, `install-desktop` opens a dedicated installer page served by a\n * short-lived local server — Runeya itself is not started. Any flag that\n * pre-answers a question installs directly so scripts stay unattended.\n */\nconst subCommand = args[0];\nif (subCommand === 'install-desktop' || subCommand === 'uninstall-desktop') {\n const { installDesktopLauncher, uninstallDesktopLauncher, deriveIdentity } =\n await import('./desktop-launcher.js');\n const { shouldOpenInstallPage, printInstallReport, printUninstallReport } =\n await import('./desktop-wizard.js');\n\n const { parsePort } = await import('./free-port.js');\n\n const rest = args.slice(1);\n // Every flag of this sub-command that takes a value: without this, the value\n // itself (a port number, a name) is mistaken for the target directory.\n const subFlagsWithValues = new Set(['--name', '--port', '--agent-port', '--project']);\n const positional = rest.find((a, i) => !a.startsWith('-') && !subFlagsWithValues.has(rest[i - 1] ?? ''));\n const nameFlag = getFlagValue(['--name']);\n\n // Ports baked into the shortcut. Null means \"follow Runeya's default\", so a\n // launcher created without them keeps tracking the default if it changes.\n const portFlagRaw = getFlagValue(['--port']);\n const agentPortFlagRaw = getFlagValue(['--agent-port']);\n for (const [flag, raw] of [['--port', portFlagRaw], ['--agent-port', agentPortFlagRaw]] as const) {\n if (raw !== undefined && parsePort(raw) === null) {\n console.error(`Erreur : ${flag} attend un entier entre 1 et 65535 (reçu ${JSON.stringify(raw)}).`);\n process.exit(1);\n }\n }\n const port = parsePort(portFlagRaw);\n const agentPort = parsePort(agentPortFlagRaw);\n\n // Le projet que le raccourci ouvre directement, sans passer par la liste.\n const projectId = getFlagValue(['--project']) ?? null;\n if (projectId !== null) {\n const { isLauncherProjectId } = await import('@runeya/packages-shared');\n if (!isLauncherProjectId(projectId)) {\n console.error(`Erreur : --project attend un id de projet (reçu ${JSON.stringify(projectId)}).`);\n process.exit(1);\n }\n }\n\n // The data directory is resolved from the working directory, so a launcher\n // that does not pin one would start Runeya in the desktop's cwd (usually the\n // home directory) and create a stray .runeya there. Pin the cwd by default.\n const workingDir = rest.includes('--no-cwd') ? null : resolve(positional ?? process.cwd());\n const displayName = nameFlag;\n\n const launcherBase = { nodePath: process.execPath, cliEntry: fileURLToPath(import.meta.url), distDir: __dirname };\n\n if (subCommand === 'install-desktop' && shouldOpenInstallPage(rest, positional !== undefined)) {\n process.exit(await runDesktopInstaller(false));\n }\n\n const { name, id } = deriveIdentity(displayName, workingDir);\n\n // Même règle que la page : un raccourci vers une copie npx ou un clone cesserait\n // de marcher le jour où elle disparaît. Un clone de développement passe par\n // RUNEYA_SKIP_INSTALL_CHECK=1, comme pour démarrer Runeya.\n if (subCommand === 'install-desktop') {\n const { createGlobalInstaller, SKIP_INSTALL_CHECK_ENV } = await import('./install-gate.js');\n if (process.env[SKIP_INSTALL_CHECK_ENV] !== '1') {\n // Une copie globale à jour déjà présente est retenue : le raccourci la vise.\n const target = { cliEntry: launcherBase.cliEntry };\n const global = await (await createGlobalInstaller(target, version)).state();\n launcherBase.cliEntry = target.cliEntry;\n launcherBase.distDir = dirname(target.cliEntry);\n if (!global.installed) {\n console.error('Erreur : ce Runeya n’est pas installé globalement, le raccourci ne marcherait plus une fois cette copie supprimée.');\n console.error('Lancez « runeya install-desktop » sans option pour l’installer depuis la page, ou « npm install -g @runeya/runeya ».');\n process.exit(1);\n }\n }\n }\n\n try {\n if (subCommand === 'install-desktop') {\n const result = await installDesktopLauncher({\n ...launcherBase,\n workingDir,\n name,\n id,\n port,\n agentPort,\n projectId,\n });\n printInstallReport({ name, workingDir, nodePath: process.execPath, port, agentPort, result });\n } else {\n printUninstallReport(name, await uninstallDesktopLauncher(name, id));\n }\n process.exit(0);\n } catch (err) {\n console.error(`Erreur : ${(err as Error).message}`);\n process.exit(1);\n }\n}\n\n/**\n * `runeya instances` — voir et piloter les Runeya de cette machine depuis un\n * terminal. Traité ici, avec les autres sous-commandes, pour que le mot\n * « instances » ne soit jamais pris pour un répertoire cible.\n *\n * Le pendant de l'icône de barre système, qui ne montre qu'une instance — la\n * sienne — et n'existe pas partout. Celle-ci les montre toutes, partout.\n *\n * Aucun serveur n'est démarré : le registre machine est un dossier de fichiers,\n * et le lire ne demande rien d'autre que de le lire.\n */\nif (subCommand === 'instances') {\n // Importé ici et pas en tête de fichier : charger `@runeya/apps-server` a un\n // coût, et un `runeya` ordinaire n'a pas à le payer pour une sous-commande\n // qu'il n'utilise pas.\n const { listInstances, killInstance, restartInstance } = await import('@runeya/apps-server');\n const { runInstancesCommand } = await import('./instances-command.js');\n\n process.exit(await runInstancesCommand(args.slice(1), {\n listInstances,\n stopInstance: killInstance,\n restartInstance: async (pid: number) => {\n const { pid: newPid, portReleased } = await restartInstance(pid);\n return { pid: newPid, portReleased };\n },\n openUrl: (url: string) => open(url),\n log: (message: string) => console.log(message),\n warn: (message: string) => console.error(message),\n }));\n}\n\n/**\n * `runeya mcp` — le serveur MCP de Runeya pour un client lancé hors de Runeya\n * (Claude Code, Codex, Cursor…). La config du client appelle cette commande et\n * non un chemin de fichier : le MCP suit ainsi les mises à jour du CLI.\n *\n * Stdout porte le protocole MCP : rien d'autre ne doit y écrire.\n */\nif (subCommand === 'mcp') {\n const { listInstances } = await import('@runeya/apps-server');\n const { runExternalMcp } = await import('@runeya/packages-mcp-server/external');\n await runExternalMcp({ listInstances });\n // Le reste de ce fichier démarre un serveur : ne jamais l'atteindre. Une\n // promesse en attente ne retient pas le process, qui s'arrête quand le\n // client ferme stdin.\n await new Promise(() => {});\n}\n\n// Resolve target directory (first positional arg, skipping flag values)\nconst targetDir = args.find((a, i) => !a.startsWith('-') && !flagsWithValues.has(args[i - 1] ?? ''));\nif (targetDir) {\n const resolved = resolve(targetDir);\n process.chdir(resolved);\n console.log(`[cli] Working directory: ${resolved}`);\n} else if (process.env['RUNEYA_DATA_DIR']) {\n const resolved = resolve(process.env['RUNEYA_DATA_DIR'], '..');\n process.chdir(resolved);\n console.log(`[cli] Working directory: ${resolved} (from RUNEYA_DATA_DIR)`);\n} else if (process.cwd() === '/') {\n /**\n * On n'écrit jamais à la racine.\n *\n * Un lanceur global — installé sans dossier épinglé — démarre avec le cwd que\n * lui donne le système, et le Finder comme les services systemd donnent `/`.\n * `DATA_DIR` y vaudrait `/.runeya` : sous macOS la racine est le volume\n * système signé, monté en lecture seule, et la première écriture locale\n * échouerait en EROFS — que même root ne peut pas lever sans\n * `/etc/synthetic.conf` et un redémarrage. Sous Linux elle demanderait les\n * droits du superutilisateur pour un dossier qui n'a rien à faire là.\n *\n * Le repli vaut aussi pour les lanceurs DÉJÀ installés, que corriger le stub\n * ne rattraperait pas.\n */\n const home = homedir();\n process.chdir(home);\n console.log(`[cli] Working directory: ${home} (lanceur sans dossier épinglé)`);\n}\n\ndotenv.config({ quiet: true });\n\nif (args.includes('--help') || args.includes('-h')) {\n console.log(`Usage: runeya [path-to-your-stack] [options]\n\nCommands:\n install-desktop [path] Create a desktop/menu launcher for this machine\n Bare on a terminal, this opens a dedicated installer page.\n uninstall-desktop Remove a launcher created by install-desktop\n --name <label> Launcher name (default: \"Runeya — <folder>\")\n --no-cwd Global launcher — do not pin a working directory\n --port <n> Port baked into the launcher (default: Runeya's own)\n --agent-port <n> Agent port baked in (default: launcher port + 1)\n --project <id> Open this project directly (no project list)\n -y, --yes Skip the wizard and take the defaults\n instances [open|stop|restart <pid>]\n List the Runeya running on this machine, and act on\n one. --json for the raw records.\n mcp Runeya MCP server on stdio, for Claude Code, Codex,\n Cursor… Asks for access in the Runeya app on first use.\n --from-desktop Set by desktop launchers: report startup failures\n in a browser window instead of a silent exit\n\nOptions:\n --version Show version number\n --pe, --pull-env Print env vars for a service to stdout (requires -e and -s)\n -e, --environment <n> Environment name or id\n -s, --service <name> Service name or id\n --lan Expose server on the local network (shortcut for --host 0.0.0.0)\n --no-open Do not open browser on startup\n --no-tray Do not put this instance in the system tray\n --agent Run as agent only (no server, no UI) — for remote machines\n -h, --help Show this help message\n\nConfiguration:\n Each setting has a flag and an equivalent RUNEYA_ environment variable; the\n flag wins. Variables are prefixed so they cannot collide with those of the\n services you manage. A .env file in the working directory is loaded\n automatically, but never overrides a flag.\n\n Flag Environment variable Default\n --port <n> RUNEYA_HTTP_PORT 4000\n (binds the agent instead when --agent is used)\n --host <address> RUNEYA_HOST 127.0.0.1\n --agent-port <n> RUNEYA_AGENT_PORT server port + 1\n --agent-host <address> RUNEYA_AGENT_HOST 127.0.0.1\n --agent-binary-path <path> RUNEYA_AGENT_BINARY_PATH bundled with the CLI\n --data-dir <path> RUNEYA_DATA_DIR <cwd>/.runeya\n --cloud-url <url> RUNEYA_CLOUD_URL —\n --cloud-app-url <url> RUNEYA_CLOUD_APP_URL —\n --cors-origin <origin> RUNEYA_CORS_ORIGIN —\n --lan RUNEYA_LAN_PROXY false\n --debug RUNEYA_DEBUG false\n --claude-pty <0|1> RUNEYA_CLAUDE_PTY 1\n --project <id> RUNEYA_PROJECT_ID —\n Open this project only: no project list, no switching\n PTY mode for the Claude Code runner\n\n Secrets have no flag — process arguments are readable by other users via 'ps':\n RUNEYA_ENCRYPTION_KEY 64-char hex key for CI/CD — unlocks secrets without a\n master password AND disables tRPC authentication.\n Never set this on a machine reachable by others.\n RUNEYA_MASTER_PASSWORD Master password used by --pull-env instead of prompting\n\n Started from a terminal, 'runeya' opens the desktop shortcut installer instead\n of Runeya itself. RUNEYA_SKIP_INSTALL_CHECK=1 starts Runeya anyway (servers,\n containers, CI).\n\n Standard variables Runeya also honours: NODE_ENV, CI (skips opening the browser).\n`);\n process.exit(0);\n}\n\nif (args.includes('--version')) {\n console.log(version);\n process.exit(0);\n}\n\n/**\n * L'icône de barre système, sauf `--no-tray`.\n *\n * Chaque Runeya pose la sienne au démarrage et la retire en s'arrêtant : une\n * icône par instance en cours. Là où la barre système n'existe pas (serveur\n * sans bureau, arm64, paquet optionnel absent), il n'y a rien à désactiver —\n * l'icône ne se pose pas, et Runeya démarre pareil.\n */\nconst noTray = args.includes('--no-tray');\n\nconst noOpen =\n args.includes('--no-open') ||\n !!process.env['VITEST'] ||\n !!process.env['CI'] ||\n process.env['NODE_ENV'] === 'test';\n\n// --pull-env flag — detect early so we can silence stdout before any log\nconst isPullEnv = args.includes('--pull-env') || args.includes('--pe');\n\n// In pull-env mode, redirect console.log/info to stderr so only KEY=VALUE goes to stdout\nif (isPullEnv) {\n const toStderr = (...a: unknown[]) => process.stderr.write(a.join(' ') + '\\n');\n console.log = toStderr;\n console.info = toStderr;\n}\n\nconst serviceArg = getFlagValue(['-s', '--service']);\nconst environmentArg = getFlagValue(['-e', '--environment']);\n\n// Configure environment BEFORE importing server (env is parsed at module load)\n// --agent mode: run as standalone agent only (no server, no UI)\nconst isAgentOnly = args.includes('--agent');\n\n// --port targets the server, except in agent mode where it binds the agent\nconst portFlag = getFlagValue(['--port']);\nif (portFlag) {\n process.env[isAgentOnly ? 'RUNEYA_AGENT_PORT' : 'RUNEYA_HTTP_PORT'] = portFlag;\n}\n\n// --lan binds to 0.0.0.0. As an explicit flag it outranks RUNEYA_HOST; coming\n// from RUNEYA_LAN_PROXY it only fills in a host nobody else set.\nconst hostFlag = getFlagValue(['--host']);\nconst isLan = args.includes('--lan');\nconst isLanProxy = isLan || process.env.RUNEYA_LAN_PROXY === 'true' || process.env.RUNEYA_LAN_PROXY === '1';\nif (isLanProxy) {\n process.env.RUNEYA_LAN_PROXY = 'true';\n if (!hostFlag && isLan) process.env.RUNEYA_HOST = '0.0.0.0';\n else process.env.RUNEYA_HOST ??= '0.0.0.0';\n}\n\n// In agent mode --host binds the agent rather than the server\nif (isAgentOnly) {\n if (hostFlag) {\n process.env.RUNEYA_AGENT_HOST = hostFlag;\n } else if (isLan) {\n process.env.RUNEYA_AGENT_HOST = '0.0.0.0';\n } else if (isLanProxy) {\n process.env.RUNEYA_AGENT_HOST ??= '0.0.0.0';\n }\n}\n\n// Agent binary shipped inside the CLI dist — overridable via --agent-binary-path\nprocess.env.RUNEYA_AGENT_BINARY_PATH ??= join(__dirname, 'agent/index.js');\n// Expose CLI version to server\nprocess.env.RUNEYA_VERSION = version;\n// Tell the server it was launched from a shortcut, so the UI can say so\nif (isFromDesktop) process.env.RUNEYA_FROM_DESKTOP = '1';\n// Data directory defaults to CWD/.runeya (server env.ts default)\n// so Runeya data lives alongside the target project.\n\n/**\n * Listen with retry for EADDRINUSE — handles the race condition when the CLI\n * restarts the server before the old process has fully released the port.\n *\n * The `wss` parameter is needed because the `ws` library re-emits HTTP server\n * errors on the WebSocketServer — without a handler the error becomes unhandled.\n */\nfunction listenWithRetry(\n server: Server,\n port: number,\n host: string,\n wss?: WebSocketServer,\n maxRetries = 20,\n delay = 500,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n\n // Absorb EADDRINUSE errors re-emitted by the ws library on the WSS\n // during the retry window. Without this, Node.js crashes on unhandled error.\n const wssErrorHandler = () => { /* absorbed — handled via server 'error' */ };\n wss?.on('error', wssErrorHandler);\n\n const tryListen = () => {\n const onError = (err: NodeJS.ErrnoException) => {\n // Clean up the 'listening' callback that server.listen() registered\n server.removeAllListeners('listening');\n\n if (err.code === 'EADDRINUSE' && attempts < maxRetries) {\n attempts++;\n console.log(`[cli] Port ${port} in use, retrying in ${delay}ms (${attempts}/${maxRetries})...`);\n setTimeout(tryListen, delay);\n } else {\n wss?.removeListener('error', wssErrorHandler);\n reject(err);\n }\n };\n\n server.once('error', onError);\n server.listen(port, host, () => {\n server.removeListener('error', onError);\n wss?.removeListener('error', wssErrorHandler);\n resolve();\n });\n };\n\n tryListen();\n });\n}\n\nasync function main() {\n // Hors raccourci, `runeya` mène à la page d'installation (voir install-gate.ts).\n const { mustOpenInstaller, hasDesktop, SKIP_INSTALL_CHECK_ENV } = await import('./install-gate.js');\n if (mustOpenInstaller({\n isFromDesktop,\n isRestartHandoff: process.env.RUNEYA_RESTART_HANDOFF === '1',\n startsServer: !isPullEnv && !isAgentOnly,\n env: process.env,\n })) {\n const { shouldOpenInstallPage } = await import('./desktop-wizard.js');\n if (!hasDesktop(process.platform, process.env)) {\n // Serveur, SSH : ni page à montrer, ni menu où poser un raccourci.\n console.error('Aucun bureau sur cette session (SSH ou serveur sans affichage) : pas de raccourci à créer ici.');\n console.error(`Pour démarrer Runeya directement : ${SKIP_INSTALL_CHECK_ENV}=1 runeya`);\n process.exit(1);\n }\n if (!shouldOpenInstallPage([], false)) {\n // Sans terminal (script, CI), personne ne verrait la page.\n console.error('Runeya se lance depuis un raccourci de bureau : lancez « runeya » dans un terminal pour le créer.');\n console.error(`Pour démarrer Runeya sans raccourci (serveur, CI) : ${SKIP_INSTALL_CHECK_ENV}=1 runeya`);\n process.exit(1);\n }\n process.exit(await runDesktopInstaller(true));\n }\n\n // Avant tout : ce que ce process hérite ici, le serveur, l'agent local et\n // chaque service lancé ensuite en héritent à leur tour. Un raccourci de bureau\n // reçoit le PATH de la session graphique, où ni les gestionnaires de version\n // ni les binaires installés par l'utilisateur (claude, codex) ne figurent.\n const { ensureNodeBinOnPath, ensureUserBinsOnPath, stampConsole } = await import('@runeya/packages-shared/node');\n ensureNodeBinOnPath();\n await ensureUserBinsOnPath();\n\n // Journaux datés du temps écoulé depuis le démarrage. Jamais en --pull-env :\n // sa sortie est lue par un script, pas par un humain.\n if (!isPullEnv) {\n stampConsole();\n // Sortie et crash recopiés sur disque : une instance relancée en\n // `stdio: 'ignore'` (bureau, mise à jour) n'a sinon aucune trace.\n try {\n const { installLogFile } = await import('./log-file.js');\n console.log(`[cli] Journal : ${installLogFile().logPath}`);\n } catch (err) {\n console.warn(`[cli] Journal sur disque indisponible : ${(err as Error).message}`);\n }\n }\n\n // Dynamic import ensures env is parsed AFTER we configure it\n const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import('@runeya/apps-server');\n\n // D'où ce CLI a été lancé, pour que l'interface puisse proposer `install-desktop`\n // sans que le serveur ait à deviner un exécutable.\n registerCliLocation({ execPath: process.execPath, cliEntry: fileURLToPath(import.meta.url) });\n\n // Handle --pull-env mode: resolve env vars and print, then exit\n if (isPullEnv) {\n if (!serviceArg) {\n console.error('Error: --service (-s) is required with --pull-env');\n process.exit(1);\n }\n if (!environmentArg) {\n console.error('Error: --environment (-e) is required with --pull-env');\n process.exit(1);\n }\n try {\n const output = await pullEnv({ service: serviceArg, environment: environmentArg });\n if (output) process.stdout.write(output + '\\n');\n process.exit(0);\n } catch (err: unknown) {\n if (err instanceof PullEnvError) {\n console.error(`Error: ${err.message}`);\n process.exit(err.exitCode);\n }\n throw err;\n }\n }\n\n // --agent mode: standalone agent, no server, no UI\n if (isAgentOnly) {\n const { spawn } = await import('node:child_process');\n const agentBin = join(__dirname, 'agent/index.js');\n const child = spawn(process.execPath, [agentBin], { stdio: 'inherit', windowsHide: true });\n child.on('exit', (code) => process.exit(code ?? 0));\n // SIGINT is already delivered to the child by the terminal (same process group).\n // Intercept it here only to suppress Node's default exit so we stay alive\n // until the child finishes its graceful shutdown.\n process.on('SIGINT', () => { /* wait for child to exit */ });\n process.on('SIGTERM', () => child.kill('SIGTERM'));\n return;\n }\n\n /**\n * Un relais de redémarrage (`appUpdate.restart`) est l'exception au garde-fou\n * ci-dessous : l'instance qui répond encore sur le port est précisément celle\n * qu'on remplace. On la laisse s'éteindre, `listenWithRetry` absorbe\n * l'EADDRINUSE du chevauchement. La marque est consommée ici pour ne pas se\n * propager aux services lancés ensuite, qui héritent de cet environnement.\n */\n const isRestartHandoff = process.env.RUNEYA_RESTART_HANDOFF === '1';\n delete process.env.RUNEYA_RESTART_HANDOFF;\n\n /**\n * A shortcut clicked twice must not fail.\n *\n * Starting a second instance on a port a Runeya already holds ends in\n * EADDRINUSE after ten seconds of retries — and from a launcher there is no\n * terminal to read that in. So the port is asked first: if Runeya answers,\n * the right move is to bring up the window that already exists.\n *\n * Only for launcher starts. From a terminal, `runeya` twice on one port is a\n * mistake worth reporting, not one worth papering over.\n */\n if (isFromDesktop && !isRestartHandoff) {\n const port = resolvePort();\n const { probeRuneya } = await import('./free-port.js');\n const existing = await probeRuneya(port);\n if (existing) {\n const url = `http://localhost:${port}`;\n console.log(`[cli] Runeya v${existing.version} déjà en cours sur le port ${port} — ouverture de ${url}`);\n if (!noOpen) await open(url);\n return;\n }\n }\n\n console.log('[cli] Starting Runeya...');\n\n // Create server (automatically spawns local agent)\n const { app, server, wss, shutdown } = await createLocalServer();\n\n // Serve static files from web frontend (embedded in CLI dist during build)\n const webDistPath = join(__dirname, 'web');\n\n /**\n * Les fichiers d'`assets/` portent un hash de leur contenu dans leur nom : une\n * mise à jour produit un NOUVEAU nom, jamais un contenu différent sous le même\n * nom. Ils peuvent donc être gardés indéfiniment, et `immutable` dit au\n * navigateur de ne même pas revalider.\n *\n * Sans cela, `express.static` répond `max-age=0` : chaque rechargement\n * redemande les 295 fichiers pour s'entendre répondre 304. Ce sont des\n * requêtes vides, mais elles occupent les six connexions qu'un navigateur\n * accorde par hôte — pour tous ses onglets à la fois. Avec plusieurs onglets\n * rechargés ensemble, l'ouverture du WebSocket attendait derrière cette file.\n */\n app.use('/assets', express.static(join(webDistPath, 'assets'), {\n immutable: true,\n maxAge: '1y',\n fallthrough: false,\n }));\n\n // Tout le reste (favicon…) : revalidation à chaque fois, ces noms ne changent\n // pas d'une version à l'autre.\n app.use(express.static(webDistPath, {\n index: false,\n setHeaders: (res) => res.setHeader('Cache-Control', 'no-cache'),\n }));\n\n // Fallback to index.html for client-side routing (Vue Router)\n // Express 5 requires explicit path patterns (not '*')\n //\n // JAMAIS mis en cache : c'est lui qui nomme les assets de la version courante.\n // Un index.html périmé rappellerait les fichiers de l'ancienne version — qui,\n // eux, ne sont plus là.\n //\n // `root` + nom relatif, jamais un chemin absolu : `sendFile` refuse tout\n // segment commençant par un point (`dotfiles: 'ignore'` par défaut) et\n // répond 404. Or l'installation la plus courante — `npx @runeya/runeya` —\n // vit sous `~/.npm/_npx/…`. Avec un chemin absolu, la page d'accueil était\n // donc introuvable sur toute machine lancée par npx (ou depuis `~/.nvm`),\n // alors que `/index.html` répondait : `express.static` ne teste, lui, que la\n // partie relative à sa racine.\n app.use((_req: Request, res: Response) => {\n res.setHeader('Cache-Control', 'no-cache');\n res.sendFile('index.html', { root: webDistPath });\n });\n\n const port = resolvePort();\n const host = process.env.RUNEYA_HOST ?? '127.0.0.1';\n\n await listenWithRetry(server, port, host, wss);\n\n // Announce this instance now that the port is really ours, so the settings\n // panel of any Runeya on this machine can list it.\n await registerInstance();\n\n /**\n * L'adresse d'écoute n'est pas une adresse de visite.\n *\n * `0.0.0.0` (et son équivalent IPv6 `::`) dit « toutes les interfaces » à\n * bind ; ce n'est pas une destination. Sous Linux une connexion vers elle\n * retombe sur la boucle locale, ce qui a longtemps masqué le problème — sous\n * Windows elle n'est pas routable du tout, et les navigateurs la bloquent\n * désormais ailleurs aussi. On écoute donc partout, mais on ouvre localhost.\n */\n const browseHost = host === '0.0.0.0' || host === '::' ? 'localhost' : host;\n const appUrl = `http://${browseHost}:${port}`;\n\n if (!noOpen) {\n await open(appUrl);\n }\n\n console.log('\\n🚀 Runeya is running!');\n if (isLanProxy) {\n console.log('🌐 LAN mode: server and service ports exposed on local network');\n }\n printStartupTable(port, appUrl);\n console.log('[cli] Press Ctrl+C to stop');\n\n // Assignée plus bas : l'arrêt doit pouvoir la retirer, et la poser demande\n // de savoir arrêter — les deux se référencent.\n let tray: { stop: () => Promise<void> } | null = null;\n\n let shuttingDown = false;\n const gracefulShutdown = async (signal: string) => {\n if (shuttingDown) {\n console.log(`[cli] Forced exit (second ${signal})`);\n process.exit(1);\n }\n shuttingDown = true;\n console.log(`\\n[cli] Received ${signal}, shutting down gracefully...`);\n\n // L'icône part en premier : elle annonce une instance vivante, et la\n // laisser pendant l'extinction inviterait à cliquer dans le vide.\n await tray?.stop();\n\n // In dev, exit immediately — ports are freed on process death,\n // and the 'exit' handler in agent-spawner SIGKILLs the agent.\n if (process.env.NODE_ENV === 'development') {\n process.exit(0);\n }\n\n await shutdown();\n console.log('[cli] Shutdown complete');\n process.exit(0);\n };\n\n process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n process.on('SIGINT', () => gracefulShutdown('SIGINT'));\n\n if (!noTray) {\n const { startInstanceTray } = await import('./tray.js');\n const {\n scheduleSelfRestart,\n listTrayServices,\n onTrayServicesChanged,\n startProcess,\n stopProcess,\n restartProcess,\n networkInfo,\n setLanMode,\n resolveTrayIcon,\n } = await import('@runeya/apps-server');\n\n tray = await startInstanceTray({\n info: { cwd: process.cwd(), port, version, url: appUrl },\n assetsDir: join(__dirname, 'assets'),\n openUrl: (target) => open(target),\n restart: () => scheduleSelfRestart(),\n stop: () => void gracefulShutdown('tray'),\n\n listServices: listTrayServices,\n startService: (id) => startProcess(id),\n // L'arrêt exige l'agent qui le fait tourner : il est dans la vue, et\n // seul un service en cours propose ce geste.\n stopService: async (id) => {\n const service = (await listTrayServices()).find((s) => s.id === id);\n if (!service?.agentId) throw new Error(`Aucun agent pour ${id}`);\n return stopProcess(id, service.agentId);\n },\n restartService: (id) => restartProcess(id),\n onServicesChanged: onTrayServicesChanged,\n // Le logo de l'organisation du projet ouvert, quand il y en a un : c'est ce\n // qui distingue deux Runeya dans la barre système.\n projectIcon: () => resolveTrayIcon(),\n\n lan: {\n read: () => {\n const info = networkInfo();\n // `lanUrls` est déjà ce qu'on voudrait lire au survol : des adresses\n // joignables, pas des IP brutes. Vide hors mode réseau local.\n return { enabled: info.lanEnabled, addresses: info.lanUrls };\n },\n toggle: (enabled) => setLanMode(enabled),\n },\n\n warn: (message) => console.log(message),\n });\n }\n}\n\nmain().catch(async (err) => {\n console.error('[cli] Fatal error:', err);\n\n // With a terminal, the message above is the report. Without one, it goes\n // nowhere: serve it as a page and open it in the browser instead.\n if (startupFailure) {\n try {\n const { diagnose, renderFailurePage, capturedLines, showStartupFailure } = startupFailure;\n const html = renderFailurePage(\n diagnose(err, resolvePort()),\n capturedLines(),\n {\n 'Version': version,\n 'Dossier de travail': process.cwd(),\n 'Node': process.execPath,\n 'Runeya': fileURLToPath(import.meta.url),\n },\n );\n await showStartupFailure(html);\n } catch (reportErr) {\n console.error('[cli] Impossible d\\'afficher le rapport d\\'erreur:', reportErr);\n }\n }\n\n process.exit(1);\n});\n","/**\n * Resolve the HTTP port Runeya should listen on.\n *\n * Only RUNEYA_HTTP_PORT is read (default 4000) — the generic PORT variable is\n * intentionally ignored so it can stay reserved for the user's own services.\n *\n * Throws if the resolved value is not an integer in [1, 65535].\n */\nexport function resolvePort(): number {\n const raw = process.env.RUNEYA_HTTP_PORT;\n if (raw === undefined) return 4000;\n\n const port = Number(raw);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(\n `Invalid port: ${JSON.stringify(raw)}. Must be an integer between 1 and 65535.`,\n );\n }\n return port;\n}\n"],"mappings":"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","names":["answers","resolve","port"]}
@@ -19,7 +19,7 @@ function samePath(a, b, platform = process.platform) {
19
19
  }
20
20
  }
21
21
  async function createGlobalInstaller(current, runningVersion) {
22
- const { resolveNpm, probeVersion, installRuneyaGlobally, installedRuneya, compareSemver, installPrefix, userPrefix } = await import("./src-ZDXFSJMJ.js");
22
+ const { resolveNpm, probeVersion, installRuneyaGlobally, installedRuneya, compareSemver, installPrefix, userPrefix } = await import("./src-NWPED6TK.js");
23
23
  const npm = resolveNpm();
24
24
  async function prefixes() {
25
25
  const global = await probeVersion(npm, ["prefix", "-g"]);
@@ -57,4 +57,4 @@ export {
57
57
  hasDesktop,
58
58
  mustOpenInstaller
59
59
  };
60
- //# sourceMappingURL=install-gate-VIJIEVF2.js.map
60
+ //# sourceMappingURL=install-gate-TSCXUCYE.js.map
@@ -212,11 +212,8 @@ var NotificationPreferencesSchema = z5.object({
212
212
  scenario_waiting_input: z5.boolean().default(true),
213
213
  ai_conversation_complete: z5.boolean().default(true),
214
214
  ai_conversation_error: z5.boolean().default(true),
215
- service_error_log: z5.boolean().default(true),
216
215
  service_status_changed: z5.boolean().default(true),
217
216
  service_health_changed: z5.boolean().default(true),
218
- /** Service IDs excluded from error-log notifications */
219
- service_error_log_excluded: z5.array(z5.string().max(100)).max(500).default([]),
220
217
  /** Service IDs excluded from status-change notifications */
221
218
  service_status_changed_excluded: z5.array(z5.string().max(100)).max(500).default([]),
222
219
  /** Service IDs excluded from health-change notifications */
@@ -244,7 +241,13 @@ var CompanionSettingsSchema = z5.object({
244
241
  effort: z5.enum(["low", "normal", "high"]).optional()
245
242
  });
246
243
  var SettingsSchema = z5.object({
247
- mode: z5.enum(["local-simple", "cloud"]),
244
+ /**
245
+ * Reste de l'ancien choix de mode, que plus rien ne lit. Toujours écrit : la
246
+ * racine machine est partagée par toutes les instances du poste, et une
247
+ * version plus ancienne qui ne le trouverait pas réécrirait ces réglages
248
+ * avec leurs valeurs par défaut.
249
+ */
250
+ mode: z5.enum(["local-simple", "cloud"]).default("local-simple"),
248
251
  cloudUrl: z5.string().url().max(2048).nullable().optional(),
249
252
  logParsers: z5.array(JSLogParserSchema).max(100).default([]),
250
253
  scenarios: z5.array(ScenarioSchema).max(100).default([]),
@@ -276,10 +279,8 @@ var SettingsPrivateSchema = z5.object({
276
279
  scenario_waiting_input: true,
277
280
  ai_conversation_complete: true,
278
281
  ai_conversation_error: true,
279
- service_error_log: true,
280
282
  service_status_changed: true,
281
283
  service_health_changed: true,
282
- service_error_log_excluded: [],
283
284
  service_status_changed_excluded: [],
284
285
  service_health_changed_excluded: []
285
286
  })),