@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.
- package/agent/index.js +9 -7
- package/agent/index.js.map +1 -1
- package/agent-manager-SF4CAJJC.js +13 -0
- package/chat-Z7SFBEXS.js +28 -0
- package/{chunk-ANZF5NLB.js → chunk-26Q43CB2.js} +2 -2
- package/{chunk-IOPX7MWA.js → chunk-2DIW5EUT.js} +6 -6
- package/{chunk-ZRMLIQZL.js → chunk-3C3R5ZVX.js} +2 -2
- package/{chunk-I2EXJ2GI.js → chunk-3O54EIGT.js} +4 -4
- package/{chunk-KTRL6RDH.js → chunk-DTRZ5ZN7.js} +5 -5
- package/{chunk-3FSQ45SW.js → chunk-EUTW2S4P.js} +87 -16
- package/chunk-EUTW2S4P.js.map +1 -0
- package/{chunk-NVU7QNZO.js → chunk-MGKGIHT4.js} +2 -4
- package/{chunk-NVU7QNZO.js.map → chunk-MGKGIHT4.js.map} +1 -1
- package/{chunk-FYAKLTSY.js → chunk-PU6REPMY.js} +5 -5
- package/{chunk-FYAKLTSY.js.map → chunk-PU6REPMY.js.map} +1 -1
- package/{chunk-NKOG7375.js → chunk-QD2OVLK4.js} +2 -2
- package/{chunk-7O54TV2Y.js → chunk-QJSIN26R.js} +45 -38
- package/chunk-QJSIN26R.js.map +1 -0
- package/{chunk-3JIJSGQW.js → chunk-R4SKU6AO.js} +10 -12
- package/chunk-R4SKU6AO.js.map +1 -0
- package/{chunk-OCIKN4BK.js → chunk-RVZATF7R.js} +8 -8
- package/chunk-RVZATF7R.js.map +1 -0
- package/{chunk-YTO4O3UK.js → chunk-TBNCGMDM.js} +5 -5
- package/{companion-2YZZSKX5.js → companion-ZDEGNZ2G.js} +11 -9
- package/{desktop-installer-page-526XOYLO.js → desktop-installer-page-TBKSXVFD.js} +3 -3
- package/{desktop-launcher-WJPN6SPV.js → desktop-launcher-WBYP3KTF.js} +3 -3
- package/{environment-resolver-I6KF27QP.js → environment-resolver-R2GH6QOX.js} +6 -6
- package/{external-XHTD2IGX.js → external-UJ46WKBL.js} +3 -3
- package/index.js +15 -15
- package/index.js.map +1 -1
- package/{install-gate-VIJIEVF2.js → install-gate-TSCXUCYE.js} +2 -2
- package/mcp-server/external.js +7 -6
- package/mcp-server/external.js.map +1 -1
- package/mcp-server/index.js +7 -6
- package/mcp-server/index.js.map +1 -1
- package/package.json +1 -1
- package/{project-store-GONXVR2N.js → project-store-GBKM34QP.js} +7 -7
- package/settings-manager-VSOC3XGI.js +10 -0
- package/{src-QMPTXT7D.js → src-6WZKSNN7.js} +2 -2
- package/{src-ZDXFSJMJ.js → src-NWPED6TK.js} +33 -39
- package/src-NWPED6TK.js.map +1 -0
- package/{vault-resolver-MX7WFBJ5.js → vault-resolver-GGHULMG6.js} +3 -3
- package/web/assets/{AgentScalarChatInterface.vue-DXbf1TAm.js → AgentScalarChatInterface.vue-CEMnvqfq.js} +1 -1
- package/web/assets/{AgentTerminalPage-CgsW_pEb.js → AgentTerminalPage-qQ96vm5Y.js} +1 -1
- package/web/assets/{AiChatModals-DLTvqUBK.js → AiChatModals-BsfKdbEA.js} +1 -1
- package/web/assets/{AppLayout-BlhwflMq.css → AppLayout-Djk3-XbN.css} +1 -1
- package/web/assets/AppLayout-f0_BsXSc.js +1 -0
- package/web/assets/{AuditPage-HMNBcG9E.js → AuditPage-B-pCRqXH.js} +1 -1
- package/web/assets/CloudAccountPage-C7aV6M8U.js +1 -0
- package/web/assets/{CloudAccountPage-Ctf2gtpm.css → CloudAccountPage-CYcW_3tO.css} +1 -1
- package/web/assets/{CloudMessagingPage-Csbnn-Zm.js → CloudMessagingPage-BTc8xbjF.js} +1 -1
- package/web/assets/{DashboardPage-BeCmdPlp.js → DashboardPage-CF7GLFlx.js} +1 -1
- package/web/assets/{DirectoryPickerDialog-DpUZT_4M.js → DirectoryPickerDialog-bKqIFy8e.js} +1 -1
- package/web/assets/{EditorIcon-CcU8Z46_.js → EditorIcon-DksI79ZN.js} +1 -1
- package/web/assets/EnvironmentForm-BnTLokUw.css +1 -0
- package/web/assets/{EnvironmentForm-ypeBVGl-.js → EnvironmentForm-kOyM5xTa.js} +1 -1
- package/web/assets/{EnvironmentFormPage-B1gVyMWV.js → EnvironmentFormPage-DfNI6meL.js} +1 -1
- package/web/assets/{EnvironmentListPage-CdE-ksue.js → EnvironmentListPage-C1VLgeeP.js} +1 -1
- package/web/assets/{FlagChip-maG1f7pl.js → FlagChip-DjC14z4J.js} +1 -1
- package/web/assets/{KanbanBoardPage-_E6xalsS.js → KanbanBoardPage-Bl6UnQ6P.js} +3 -3
- package/web/assets/KanbanBoardPage-Cmu4Je4N.css +1 -0
- package/web/assets/{KanbanListPage-BigioApQ.css → KanbanListPage-DCK-N3nw.css} +1 -1
- package/web/assets/{KanbanListPage-DkjiefP8.js → KanbanListPage-Dly6XiRC.js} +1 -1
- package/web/assets/{LaunchProjectPage-C4kuqyMZ.js → LaunchProjectPage-DCrKSY8v.js} +1 -1
- package/web/assets/{LaunchServicesPage-s8HZF2aU.js → LaunchServicesPage-Bl1pjfYH.js} +1 -1
- package/web/assets/{LaunchShell-GWtn69Hh.js → LaunchShell-BcbfPDdc.js} +1 -1
- package/web/assets/{LogViewer-B0XUfzs3.js → LogViewer-C_XcH7Oe.js} +1 -1
- package/web/assets/{OrgKeyPrompt-Ch8jziJJ.js → OrgKeyPrompt-BK6gkvaO.js} +1 -1
- package/web/assets/{ProcessControls-bZbJJjkv.js → ProcessControls-BbRdiZsD.js} +1 -1
- package/web/assets/ProcessDetailPage-B7bD2jmj.css +1 -0
- package/web/assets/ProcessDetailPage-W7S7ogas.js +1 -0
- package/web/assets/{ProcessMetrics-D-rQkzqK.js → ProcessMetrics-C_7_boMv.js} +1 -1
- package/web/assets/{ProjectCreateDialog-KjvGUZnr.js → ProjectCreateDialog-q_39qiPd.js} +1 -1
- package/web/assets/{ProjectLocationGate-DFe2hgxM.js → ProjectLocationGate-BFvdSy-B.js} +1 -1
- package/web/assets/{ProjectPublishDialog-BgPH5gGM.js → ProjectPublishDialog-DAJAvDTT.js} +1 -1
- package/web/assets/{RandomJobTestPage-Bv3l2Trh.js → RandomJobTestPage-A-I7cImN.js} +1 -1
- package/web/assets/{ScenarioEditorPage-BtKSjE2X.css → ScenarioEditorPage-BwLBCVeS.css} +1 -1
- package/web/assets/ScenarioEditorPage-DXw4bCxb.js +14 -0
- package/web/assets/{SendToChatDialog-CkWcPSvZ.js → SendToChatDialog-CbhE2WYO.js} +1 -1
- package/web/assets/{ServiceControlsBar-VywLkYdH.js → ServiceControlsBar-CudCeQql.js} +1 -1
- package/web/assets/ServiceDetailPage-DQvL-VOx.js +2 -0
- package/web/assets/{ServiceDetailPage-CM5uzqpI.css → ServiceDetailPage-DuXvqXk4.css} +1 -1
- package/web/assets/{ServiceFormPage-v9c7DVdv.js → ServiceFormPage-0qXPeqrh.js} +1 -1
- package/web/assets/{SettingsPage-CetQ42p1.js → SettingsPage-Bjn4bKPP.js} +7 -7
- package/web/assets/{SettingsPage-B951NEBm.css → SettingsPage-NpFX7FAy.css} +1 -1
- package/web/assets/{UnlockPage-CZMvcAl1.js → UnlockPage-CtvaQt45.js} +1 -1
- package/web/assets/{VaultMigrationPage-CeX0mpxh.js → VaultMigrationPage-DtoAlng4.js} +1 -1
- package/web/assets/{VersionBadge-DDmZ4Dhc.js → VersionBadge-CiBz82BB.js} +1 -1
- package/web/assets/{WikiPage-3puq_dIL.js → WikiPage-cuKigw_5.js} +1 -1
- package/web/assets/{WikiView-J4U7er--.js → WikiView-BW-B83LB.js} +1 -1
- package/web/assets/{add-scalar-classes-B7027Ds2.js → add-scalar-classes-BPTxQDQd.js} +1 -1
- package/web/assets/{agent.store-CAhnz7FI.js → agent.store-DumNiX1X.js} +1 -1
- package/web/assets/{auth-DEwzvqNZ.js → auth-Qa1l14iV.js} +2 -2
- package/web/assets/{cloud-chat.store-Dw5IpDzc.js → cloud-chat.store-TYR1_27Z.js} +1 -1
- package/web/assets/{cloud-client-BmRvC15v.js → cloud-client-CdOqrdP_.js} +2 -2
- package/web/assets/{cloud-session-CxfJk0xr.js → cloud-session-Dd7b9wxV.js} +2 -2
- package/web/assets/dist-C9Qdh18x.js +1 -0
- package/web/assets/i18n-DipCGVKv.js +1 -0
- package/web/assets/{index-DSYMPMcP.js → index-BCU69ZHl.js} +7 -7
- package/web/assets/{index-CnXzQkLZ.css → index-Ck_3m_I9.css} +1 -1
- package/web/assets/{modal-CWJFP30c.js → modal-BgrgFhyC.js} +1 -1
- package/web/assets/notification.store-D2olEA0V.js +1 -0
- package/web/assets/{project-launch.store-_peuBwFo.js → project-launch.store-MX5LzgIm.js} +1 -1
- package/web/assets/{project.store-eANeFYaH.js → project.store-BFwiDQ1X.js} +1 -1
- package/web/assets/{scenario.store-C1Yj7c6l.js → scenario.store-C8kW-yTN.js} +1 -1
- package/web/assets/{service.store-Ck2_TmTB.js → service.store-B0Ass90H.js} +1 -1
- package/web/assets/{settings-scope-GiU9Nkh7.js → settings-scope-D0hzzuyq.js} +1 -1
- package/web/assets/settings.store-B9Kp0l1G.js +1 -0
- package/web/assets/{src-Bfb0PBSC.css → src-CfDz-9Q6.css} +1 -1
- package/web/assets/{src-DOcCcTQv.js → src-Ck_MutzB.js} +1 -1
- package/web/assets/{src-BsRUOIiC.js → src-DITmhvGS.js} +1 -1
- package/web/assets/src-DOziuDw8.css +1 -0
- package/web/assets/src-DnjsM9el.js +1960 -0
- package/web/assets/{trpc-Deb6EPHJ.js → trpc-BvrR5qP9.js} +3 -3
- package/web/assets/{useCloudOrg-7IK98BjW.js → useCloudOrg-2vv5fVV6.js} +1 -1
- package/web/assets/{useEnvVarAutocomplete-lfgStLwz.js → useEnvVarAutocomplete-VVX3MC62.js} +1 -1
- package/web/assets/{useEnvVarAutocomplete-B-LJ9dBm.css → useEnvVarAutocomplete-gV2loQYv.css} +1 -1
- package/web/assets/{useProjectCatalog-J40rgwRP.js → useProjectCatalog-DsVvtBzo.js} +1 -1
- package/web/assets/{useProjectCloudOrg-zePV-ihH.js → useProjectCloudOrg-wv-RfsmO.js} +1 -1
- package/web/assets/{useServiceUrlHost-BWtmwnoK.js → useServiceUrlHost-C4Evrede.js} +1 -1
- package/web/index.html +19 -19
- package/agent-manager-2KTEZXRO.js +0 -13
- package/chat-N2AYGN7I.js +0 -28
- package/chunk-3FSQ45SW.js.map +0 -1
- package/chunk-3JIJSGQW.js.map +0 -1
- package/chunk-7O54TV2Y.js.map +0 -1
- package/chunk-DA2DZBTL.js +0 -43
- package/chunk-DA2DZBTL.js.map +0 -1
- package/chunk-OCIKN4BK.js.map +0 -1
- package/mcp-ready-TAPBAOZY.js +0 -9
- package/settings-manager-QOLMKVP2.js +0 -10
- package/src-ZDXFSJMJ.js.map +0 -1
- package/vault-resolver-MX7WFBJ5.js.map +0 -1
- package/web/assets/AppLayout-BFCPOgV1.js +0 -1
- package/web/assets/CloudAccountPage-DXMDa3Zw.js +0 -1
- package/web/assets/EnvironmentForm-Do3i-fOk.css +0 -1
- package/web/assets/KanbanBoardPage-Bb_8xU-I.css +0 -1
- package/web/assets/ProcessDetailPage-CJcIxbLm.css +0 -1
- package/web/assets/ProcessDetailPage-Cy_9S9z8.js +0 -1
- package/web/assets/ScenarioEditorPage-DMZ_67kP.js +0 -14
- package/web/assets/ServiceDetailPage-C-RIYfjD.js +0 -2
- package/web/assets/dist-B6L3Jwj-.js +0 -1
- package/web/assets/i18n-BNITS3xi.js +0 -1
- package/web/assets/notification.store-C1JOcW8z.js +0 -1
- package/web/assets/settings.store-C6T1P_cU.js +0 -1
- package/web/assets/src-Dbg3CMY2.css +0 -1
- package/web/assets/src-Ip9ugq4e.js +0 -1960
- /package/{agent-manager-2KTEZXRO.js.map → agent-manager-SF4CAJJC.js.map} +0 -0
- /package/{chat-N2AYGN7I.js.map → chat-Z7SFBEXS.js.map} +0 -0
- /package/{chunk-ANZF5NLB.js.map → chunk-26Q43CB2.js.map} +0 -0
- /package/{chunk-IOPX7MWA.js.map → chunk-2DIW5EUT.js.map} +0 -0
- /package/{chunk-ZRMLIQZL.js.map → chunk-3C3R5ZVX.js.map} +0 -0
- /package/{chunk-I2EXJ2GI.js.map → chunk-3O54EIGT.js.map} +0 -0
- /package/{chunk-KTRL6RDH.js.map → chunk-DTRZ5ZN7.js.map} +0 -0
- /package/{chunk-NKOG7375.js.map → chunk-QD2OVLK4.js.map} +0 -0
- /package/{chunk-YTO4O3UK.js.map → chunk-TBNCGMDM.js.map} +0 -0
- /package/{companion-2YZZSKX5.js.map → companion-ZDEGNZ2G.js.map} +0 -0
- /package/{desktop-installer-page-526XOYLO.js.map → desktop-installer-page-TBKSXVFD.js.map} +0 -0
- /package/{desktop-launcher-WJPN6SPV.js.map → desktop-launcher-WBYP3KTF.js.map} +0 -0
- /package/{environment-resolver-I6KF27QP.js.map → environment-resolver-R2GH6QOX.js.map} +0 -0
- /package/{external-XHTD2IGX.js.map → external-UJ46WKBL.js.map} +0 -0
- /package/{install-gate-VIJIEVF2.js.map → install-gate-TSCXUCYE.js.map} +0 -0
- /package/{mcp-ready-TAPBAOZY.js.map → project-store-GBKM34QP.js.map} +0 -0
- /package/{project-store-GONXVR2N.js.map → settings-manager-VSOC3XGI.js.map} +0 -0
- /package/{settings-manager-QOLMKVP2.js.map → src-6WZKSNN7.js.map} +0 -0
- /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-
|
|
17
|
+
} from "./chunk-26Q43CB2.js";
|
|
18
18
|
import {
|
|
19
19
|
deriveLauncherIdentity,
|
|
20
20
|
launcherIdFromName,
|
|
21
21
|
slugifyLauncherName
|
|
22
|
-
} from "./chunk-
|
|
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-
|
|
43
|
+
//# sourceMappingURL=desktop-launcher-WBYP3KTF.js.map
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
describeVariables,
|
|
4
4
|
environmentResolver,
|
|
5
5
|
filterEnvForAi
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-TBNCGMDM.js";
|
|
7
|
+
import "./chunk-3O54EIGT.js";
|
|
8
8
|
import "./chunk-OZBSOSAS.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
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-
|
|
18
|
+
//# sourceMappingURL=environment-resolver-R2GH6QOX.js.map
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
callTrpc,
|
|
6
6
|
runCapability,
|
|
7
7
|
toRawParams
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
90
|
-
const { createGlobalInstaller } = await import("./install-gate-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
197
|
-
const { runExternalMcp } = await import("./external-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
60
|
+
//# sourceMappingURL=install-gate-TSCXUCYE.js.map
|
package/mcp-server/external.js
CHANGED
|
@@ -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
|
-
|
|
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
|
})),
|