@agimon-ai/doompi-runner 0.0.1-alpha.0
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/LICENSE +21 -0
- package/README.md +47 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs +1 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs +1 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.cjs +1 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.mjs +1 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.cjs +1 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.mjs +1 -0
- package/dist/_virtual/_rolldown/runtime.cjs +1 -0
- package/dist/bin/cli.cjs +5 -0
- package/dist/bin/cli.cjs.map +1 -0
- package/dist/bin/cli.d.cts +5 -0
- package/dist/bin/cli.d.cts.map +1 -0
- package/dist/bin/cli.d.mts +5 -0
- package/dist/bin/cli.d.mts.map +1 -0
- package/dist/bin/cli.mjs +5 -0
- package/dist/bin/cli.mjs.map +1 -0
- package/dist/bin/logSink.cjs +2 -0
- package/dist/bin/logSink.cjs.map +1 -0
- package/dist/bin/logSink.d.cts +5 -0
- package/dist/bin/logSink.d.cts.map +1 -0
- package/dist/bin/logSink.d.mts +5 -0
- package/dist/bin/logSink.d.mts.map +1 -0
- package/dist/bin/logSink.mjs +2 -0
- package/dist/bin/logSink.mjs.map +1 -0
- package/dist/bin/runnerHost.cjs +2 -0
- package/dist/bin/runnerHost.cjs.map +1 -0
- package/dist/bin/runnerHost.d.cts +5 -0
- package/dist/bin/runnerHost.d.cts.map +1 -0
- package/dist/bin/runnerHost.d.mts +5 -0
- package/dist/bin/runnerHost.d.mts.map +1 -0
- package/dist/bin/runnerHost.mjs +2 -0
- package/dist/bin/runnerHost.mjs.map +1 -0
- package/dist/cli/cliApp.cjs +6 -0
- package/dist/cli/cliApp.cjs.map +1 -0
- package/dist/cli/cliApp.d.cts +23 -0
- package/dist/cli/cliApp.d.cts.map +1 -0
- package/dist/cli/cliApp.d.mts +23 -0
- package/dist/cli/cliApp.d.mts.map +1 -0
- package/dist/cli/cliApp.mjs +6 -0
- package/dist/cli/cliApp.mjs.map +1 -0
- package/dist/compaction.cjs +4 -0
- package/dist/compaction.cjs.map +1 -0
- package/dist/compaction.d.cts +14 -0
- package/dist/compaction.d.cts.map +1 -0
- package/dist/compaction.d.mts +14 -0
- package/dist/compaction.d.mts.map +1 -0
- package/dist/compaction.mjs +4 -0
- package/dist/compaction.mjs.map +1 -0
- package/dist/config.cjs +2 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +32 -0
- package/dist/config.d.cts.map +1 -0
- package/dist/config.d.mts +32 -0
- package/dist/config.d.mts.map +1 -0
- package/dist/config.mjs +2 -0
- package/dist/config.mjs.map +1 -0
- package/dist/container/index.cjs +2 -0
- package/dist/container/index.cjs.map +1 -0
- package/dist/container/index.d.cts +14 -0
- package/dist/container/index.d.cts.map +1 -0
- package/dist/container/index.d.mts +14 -0
- package/dist/container/index.d.mts.map +1 -0
- package/dist/container/index.mjs +2 -0
- package/dist/container/index.mjs.map +1 -0
- package/dist/extension.cjs +3 -0
- package/dist/extension.cjs.map +1 -0
- package/dist/extension.d.cts +10 -0
- package/dist/extension.d.cts.map +1 -0
- package/dist/extension.d.mts +10 -0
- package/dist/extension.d.mts.map +1 -0
- package/dist/extension.mjs +3 -0
- package/dist/extension.mjs.map +1 -0
- package/dist/extensions/pi.cjs +2 -0
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.cts +2 -0
- package/dist/extensions/pi.d.mts +2 -0
- package/dist/extensions/pi.mjs +2 -0
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +1 -0
- package/dist/ptyProvider.cjs +2 -0
- package/dist/ptyProvider.cjs.map +1 -0
- package/dist/ptyProvider.d.cts +13 -0
- package/dist/ptyProvider.d.cts.map +1 -0
- package/dist/ptyProvider.d.mts +13 -0
- package/dist/ptyProvider.d.mts.map +1 -0
- package/dist/ptyProvider.mjs +2 -0
- package/dist/ptyProvider.mjs.map +1 -0
- package/dist/reconcile.cjs +2 -0
- package/dist/reconcile.cjs.map +1 -0
- package/dist/reconcile.d.cts +37 -0
- package/dist/reconcile.d.cts.map +1 -0
- package/dist/reconcile.d.mts +37 -0
- package/dist/reconcile.d.mts.map +1 -0
- package/dist/reconcile.mjs +2 -0
- package/dist/reconcile.mjs.map +1 -0
- package/dist/runnerSpec.cjs +2 -0
- package/dist/runnerSpec.cjs.map +1 -0
- package/dist/runnerSpec.d.cts +50 -0
- package/dist/runnerSpec.d.cts.map +1 -0
- package/dist/runnerSpec.d.mts +50 -0
- package/dist/runnerSpec.d.mts.map +1 -0
- package/dist/runnerSpec.mjs +2 -0
- package/dist/runnerSpec.mjs.map +1 -0
- package/dist/services/AnsiScrub/ansiScrub.cjs +5 -0
- package/dist/services/AnsiScrub/ansiScrub.cjs.map +1 -0
- package/dist/services/AnsiScrub/ansiScrub.d.cts +34 -0
- package/dist/services/AnsiScrub/ansiScrub.d.cts.map +1 -0
- package/dist/services/AnsiScrub/ansiScrub.d.mts +34 -0
- package/dist/services/AnsiScrub/ansiScrub.d.mts.map +1 -0
- package/dist/services/AnsiScrub/ansiScrub.mjs +5 -0
- package/dist/services/AnsiScrub/ansiScrub.mjs.map +1 -0
- package/dist/services/AnsiScrub/index.cjs +1 -0
- package/dist/services/AnsiScrub/index.d.cts +2 -0
- package/dist/services/AnsiScrub/index.d.mts +2 -0
- package/dist/services/AnsiScrub/index.mjs +1 -0
- package/dist/services/BashRunService/BashRunService.cjs +2 -0
- package/dist/services/BashRunService/BashRunService.cjs.map +1 -0
- package/dist/services/BashRunService/BashRunService.d.cts +38 -0
- package/dist/services/BashRunService/BashRunService.d.cts.map +1 -0
- package/dist/services/BashRunService/BashRunService.d.mts +38 -0
- package/dist/services/BashRunService/BashRunService.d.mts.map +1 -0
- package/dist/services/BashRunService/BashRunService.mjs +2 -0
- package/dist/services/BashRunService/BashRunService.mjs.map +1 -0
- package/dist/services/BashRunService/index.cjs +1 -0
- package/dist/services/BashRunService/index.d.cts +3 -0
- package/dist/services/BashRunService/index.d.mts +3 -0
- package/dist/services/BashRunService/index.mjs +1 -0
- package/dist/services/BashRunService/types.d.cts +62 -0
- package/dist/services/BashRunService/types.d.cts.map +1 -0
- package/dist/services/BashRunService/types.d.mts +62 -0
- package/dist/services/BashRunService/types.d.mts.map +1 -0
- package/dist/services/Clock/SystemClock.cjs +2 -0
- package/dist/services/Clock/SystemClock.cjs.map +1 -0
- package/dist/services/Clock/SystemClock.d.cts +11 -0
- package/dist/services/Clock/SystemClock.d.cts.map +1 -0
- package/dist/services/Clock/SystemClock.d.mts +11 -0
- package/dist/services/Clock/SystemClock.d.mts.map +1 -0
- package/dist/services/Clock/SystemClock.mjs +2 -0
- package/dist/services/Clock/SystemClock.mjs.map +1 -0
- package/dist/services/Clock/index.cjs +1 -0
- package/dist/services/Clock/index.d.cts +3 -0
- package/dist/services/Clock/index.d.mts +3 -0
- package/dist/services/Clock/index.mjs +1 -0
- package/dist/services/Clock/types.d.cts +11 -0
- package/dist/services/Clock/types.d.cts.map +1 -0
- package/dist/services/Clock/types.d.mts +11 -0
- package/dist/services/Clock/types.d.mts.map +1 -0
- package/dist/services/Launcher/Launcher.cjs +2 -0
- package/dist/services/Launcher/Launcher.cjs.map +1 -0
- package/dist/services/Launcher/Launcher.d.cts +27 -0
- package/dist/services/Launcher/Launcher.d.cts.map +1 -0
- package/dist/services/Launcher/Launcher.d.mts +27 -0
- package/dist/services/Launcher/Launcher.d.mts.map +1 -0
- package/dist/services/Launcher/Launcher.mjs +2 -0
- package/dist/services/Launcher/Launcher.mjs.map +1 -0
- package/dist/services/Launcher/index.cjs +1 -0
- package/dist/services/Launcher/index.d.cts +3 -0
- package/dist/services/Launcher/index.d.mts +3 -0
- package/dist/services/Launcher/index.mjs +1 -0
- package/dist/services/Launcher/types.d.cts +40 -0
- package/dist/services/Launcher/types.d.cts.map +1 -0
- package/dist/services/Launcher/types.d.mts +40 -0
- package/dist/services/Launcher/types.d.mts.map +1 -0
- package/dist/services/Lifeline/NodeLifeline.cjs +2 -0
- package/dist/services/Lifeline/NodeLifeline.cjs.map +1 -0
- package/dist/services/Lifeline/NodeLifeline.d.cts +21 -0
- package/dist/services/Lifeline/NodeLifeline.d.cts.map +1 -0
- package/dist/services/Lifeline/NodeLifeline.d.mts +21 -0
- package/dist/services/Lifeline/NodeLifeline.d.mts.map +1 -0
- package/dist/services/Lifeline/NodeLifeline.mjs +2 -0
- package/dist/services/Lifeline/NodeLifeline.mjs.map +1 -0
- package/dist/services/Lifeline/client.cjs +2 -0
- package/dist/services/Lifeline/client.cjs.map +1 -0
- package/dist/services/Lifeline/client.d.cts +23 -0
- package/dist/services/Lifeline/client.d.cts.map +1 -0
- package/dist/services/Lifeline/client.d.mts +23 -0
- package/dist/services/Lifeline/client.d.mts.map +1 -0
- package/dist/services/Lifeline/client.mjs +2 -0
- package/dist/services/Lifeline/client.mjs.map +1 -0
- package/dist/services/Lifeline/index.cjs +1 -0
- package/dist/services/Lifeline/index.d.cts +4 -0
- package/dist/services/Lifeline/index.d.mts +4 -0
- package/dist/services/Lifeline/index.mjs +1 -0
- package/dist/services/Lifeline/types.d.cts +19 -0
- package/dist/services/Lifeline/types.d.cts.map +1 -0
- package/dist/services/Lifeline/types.d.mts +19 -0
- package/dist/services/Lifeline/types.d.mts.map +1 -0
- package/dist/services/LogFile/LogFile.cjs +2 -0
- package/dist/services/LogFile/LogFile.cjs.map +1 -0
- package/dist/services/LogFile/LogFile.d.cts +13 -0
- package/dist/services/LogFile/LogFile.d.cts.map +1 -0
- package/dist/services/LogFile/LogFile.d.mts +13 -0
- package/dist/services/LogFile/LogFile.d.mts.map +1 -0
- package/dist/services/LogFile/LogFile.mjs +2 -0
- package/dist/services/LogFile/LogFile.mjs.map +1 -0
- package/dist/services/LogFile/index.cjs +1 -0
- package/dist/services/LogFile/index.d.cts +3 -0
- package/dist/services/LogFile/index.d.mts +3 -0
- package/dist/services/LogFile/index.mjs +1 -0
- package/dist/services/LogFile/types.d.cts +16 -0
- package/dist/services/LogFile/types.d.cts.map +1 -0
- package/dist/services/LogFile/types.d.mts +16 -0
- package/dist/services/LogFile/types.d.mts.map +1 -0
- package/dist/services/LogReader/LogReader.cjs +10 -0
- package/dist/services/LogReader/LogReader.cjs.map +1 -0
- package/dist/services/LogReader/LogReader.d.cts +14 -0
- package/dist/services/LogReader/LogReader.d.cts.map +1 -0
- package/dist/services/LogReader/LogReader.d.mts +14 -0
- package/dist/services/LogReader/LogReader.d.mts.map +1 -0
- package/dist/services/LogReader/LogReader.mjs +10 -0
- package/dist/services/LogReader/LogReader.mjs.map +1 -0
- package/dist/services/LogReader/index.cjs +1 -0
- package/dist/services/LogReader/index.d.cts +3 -0
- package/dist/services/LogReader/index.d.mts +3 -0
- package/dist/services/LogReader/index.mjs +1 -0
- package/dist/services/LogReader/types.d.cts +27 -0
- package/dist/services/LogReader/types.d.cts.map +1 -0
- package/dist/services/LogReader/types.d.mts +27 -0
- package/dist/services/LogReader/types.d.mts.map +1 -0
- package/dist/services/ProcessControl/NodeProcessControl.cjs +2 -0
- package/dist/services/ProcessControl/NodeProcessControl.cjs.map +1 -0
- package/dist/services/ProcessControl/NodeProcessControl.d.cts +11 -0
- package/dist/services/ProcessControl/NodeProcessControl.d.cts.map +1 -0
- package/dist/services/ProcessControl/NodeProcessControl.d.mts +11 -0
- package/dist/services/ProcessControl/NodeProcessControl.d.mts.map +1 -0
- package/dist/services/ProcessControl/NodeProcessControl.mjs +2 -0
- package/dist/services/ProcessControl/NodeProcessControl.mjs.map +1 -0
- package/dist/services/ProcessControl/index.cjs +1 -0
- package/dist/services/ProcessControl/index.d.cts +3 -0
- package/dist/services/ProcessControl/index.d.mts +3 -0
- package/dist/services/ProcessControl/index.mjs +1 -0
- package/dist/services/ProcessControl/types.d.cts +14 -0
- package/dist/services/ProcessControl/types.d.cts.map +1 -0
- package/dist/services/ProcessControl/types.d.mts +14 -0
- package/dist/services/ProcessControl/types.d.mts.map +1 -0
- package/dist/services/PtyHost/PtyHost.cjs +5 -0
- package/dist/services/PtyHost/PtyHost.cjs.map +1 -0
- package/dist/services/PtyHost/PtyHost.d.cts +28 -0
- package/dist/services/PtyHost/PtyHost.d.cts.map +1 -0
- package/dist/services/PtyHost/PtyHost.d.mts +28 -0
- package/dist/services/PtyHost/PtyHost.d.mts.map +1 -0
- package/dist/services/PtyHost/PtyHost.mjs +5 -0
- package/dist/services/PtyHost/PtyHost.mjs.map +1 -0
- package/dist/services/PtyHost/index.cjs +1 -0
- package/dist/services/PtyHost/index.d.cts +3 -0
- package/dist/services/PtyHost/index.d.mts +3 -0
- package/dist/services/PtyHost/index.mjs +1 -0
- package/dist/services/PtyHost/types.d.cts +39 -0
- package/dist/services/PtyHost/types.d.cts.map +1 -0
- package/dist/services/PtyHost/types.d.mts +39 -0
- package/dist/services/PtyHost/types.d.mts.map +1 -0
- package/dist/services/PtySpawner/NodePtySpawner.cjs +2 -0
- package/dist/services/PtySpawner/NodePtySpawner.cjs.map +1 -0
- package/dist/services/PtySpawner/NodePtySpawner.d.cts +18 -0
- package/dist/services/PtySpawner/NodePtySpawner.d.cts.map +1 -0
- package/dist/services/PtySpawner/NodePtySpawner.d.mts +18 -0
- package/dist/services/PtySpawner/NodePtySpawner.d.mts.map +1 -0
- package/dist/services/PtySpawner/NodePtySpawner.mjs +2 -0
- package/dist/services/PtySpawner/NodePtySpawner.mjs.map +1 -0
- package/dist/services/PtySpawner/index.cjs +1 -0
- package/dist/services/PtySpawner/index.d.cts +3 -0
- package/dist/services/PtySpawner/index.d.mts +3 -0
- package/dist/services/PtySpawner/index.mjs +1 -0
- package/dist/services/PtySpawner/types.d.cts +28 -0
- package/dist/services/PtySpawner/types.d.cts.map +1 -0
- package/dist/services/PtySpawner/types.d.mts +28 -0
- package/dist/services/PtySpawner/types.d.mts.map +1 -0
- package/dist/services/RmuxBackend/RmuxBackend.cjs +2 -0
- package/dist/services/RmuxBackend/RmuxBackend.cjs.map +1 -0
- package/dist/services/RmuxBackend/RmuxBackend.d.cts +36 -0
- package/dist/services/RmuxBackend/RmuxBackend.d.cts.map +1 -0
- package/dist/services/RmuxBackend/RmuxBackend.d.mts +36 -0
- package/dist/services/RmuxBackend/RmuxBackend.d.mts.map +1 -0
- package/dist/services/RmuxBackend/RmuxBackend.mjs +2 -0
- package/dist/services/RmuxBackend/RmuxBackend.mjs.map +1 -0
- package/dist/services/RmuxBackend/index.cjs +1 -0
- package/dist/services/RmuxBackend/index.d.cts +3 -0
- package/dist/services/RmuxBackend/index.d.mts +3 -0
- package/dist/services/RmuxBackend/index.mjs +1 -0
- package/dist/services/RmuxBackend/types.d.cts +29 -0
- package/dist/services/RmuxBackend/types.d.cts.map +1 -0
- package/dist/services/RmuxBackend/types.d.mts +29 -0
- package/dist/services/RmuxBackend/types.d.mts.map +1 -0
- package/dist/services/RunnerNamer/RunnerNamer.cjs +2 -0
- package/dist/services/RunnerNamer/RunnerNamer.cjs.map +1 -0
- package/dist/services/RunnerNamer/RunnerNamer.d.cts +13 -0
- package/dist/services/RunnerNamer/RunnerNamer.d.cts.map +1 -0
- package/dist/services/RunnerNamer/RunnerNamer.d.mts +13 -0
- package/dist/services/RunnerNamer/RunnerNamer.d.mts.map +1 -0
- package/dist/services/RunnerNamer/RunnerNamer.mjs +2 -0
- package/dist/services/RunnerNamer/RunnerNamer.mjs.map +1 -0
- package/dist/services/RunnerNamer/index.cjs +1 -0
- package/dist/services/RunnerNamer/index.d.cts +3 -0
- package/dist/services/RunnerNamer/index.d.mts +3 -0
- package/dist/services/RunnerNamer/index.mjs +1 -0
- package/dist/services/RunnerNamer/types.d.cts +12 -0
- package/dist/services/RunnerNamer/types.d.cts.map +1 -0
- package/dist/services/RunnerNamer/types.d.mts +12 -0
- package/dist/services/RunnerNamer/types.d.mts.map +1 -0
- package/dist/services/RunnerPaths/RunnerPaths.cjs +2 -0
- package/dist/services/RunnerPaths/RunnerPaths.cjs.map +1 -0
- package/dist/services/RunnerPaths/RunnerPaths.d.cts +31 -0
- package/dist/services/RunnerPaths/RunnerPaths.d.cts.map +1 -0
- package/dist/services/RunnerPaths/RunnerPaths.d.mts +31 -0
- package/dist/services/RunnerPaths/RunnerPaths.d.mts.map +1 -0
- package/dist/services/RunnerPaths/RunnerPaths.mjs +2 -0
- package/dist/services/RunnerPaths/RunnerPaths.mjs.map +1 -0
- package/dist/services/RunnerPaths/index.cjs +1 -0
- package/dist/services/RunnerPaths/index.d.cts +3 -0
- package/dist/services/RunnerPaths/index.d.mts +3 -0
- package/dist/services/RunnerPaths/index.mjs +1 -0
- package/dist/services/RunnerPaths/types.d.cts +33 -0
- package/dist/services/RunnerPaths/types.d.cts.map +1 -0
- package/dist/services/RunnerPaths/types.d.mts +33 -0
- package/dist/services/RunnerPaths/types.d.mts.map +1 -0
- package/dist/services/RunnerRegistry/RunnerRegistry.cjs +2 -0
- package/dist/services/RunnerRegistry/RunnerRegistry.cjs.map +1 -0
- package/dist/services/RunnerRegistry/RunnerRegistry.d.cts +40 -0
- package/dist/services/RunnerRegistry/RunnerRegistry.d.cts.map +1 -0
- package/dist/services/RunnerRegistry/RunnerRegistry.d.mts +40 -0
- package/dist/services/RunnerRegistry/RunnerRegistry.d.mts.map +1 -0
- package/dist/services/RunnerRegistry/RunnerRegistry.mjs +2 -0
- package/dist/services/RunnerRegistry/RunnerRegistry.mjs.map +1 -0
- package/dist/services/RunnerRegistry/index.cjs +1 -0
- package/dist/services/RunnerRegistry/index.d.cts +3 -0
- package/dist/services/RunnerRegistry/index.d.mts +3 -0
- package/dist/services/RunnerRegistry/index.mjs +1 -0
- package/dist/services/RunnerRegistry/types.d.cts +98 -0
- package/dist/services/RunnerRegistry/types.d.cts.map +1 -0
- package/dist/services/RunnerRegistry/types.d.mts +98 -0
- package/dist/services/RunnerRegistry/types.d.mts.map +1 -0
- package/dist/services/Spawner/NodeSpawner.cjs +2 -0
- package/dist/services/Spawner/NodeSpawner.cjs.map +1 -0
- package/dist/services/Spawner/NodeSpawner.d.cts +10 -0
- package/dist/services/Spawner/NodeSpawner.d.cts.map +1 -0
- package/dist/services/Spawner/NodeSpawner.d.mts +10 -0
- package/dist/services/Spawner/NodeSpawner.d.mts.map +1 -0
- package/dist/services/Spawner/NodeSpawner.mjs +2 -0
- package/dist/services/Spawner/NodeSpawner.mjs.map +1 -0
- package/dist/services/Spawner/index.cjs +1 -0
- package/dist/services/Spawner/index.d.cts +3 -0
- package/dist/services/Spawner/index.d.mts +3 -0
- package/dist/services/Spawner/index.mjs +1 -0
- package/dist/services/Spawner/types.d.cts +31 -0
- package/dist/services/Spawner/types.d.cts.map +1 -0
- package/dist/services/Spawner/types.d.mts +31 -0
- package/dist/services/Spawner/types.d.mts.map +1 -0
- package/dist/session.cjs +2 -0
- package/dist/session.cjs.map +1 -0
- package/dist/session.d.cts +10 -0
- package/dist/session.d.cts.map +1 -0
- package/dist/session.d.mts +10 -0
- package/dist/session.d.mts.map +1 -0
- package/dist/session.mjs +2 -0
- package/dist/session.mjs.map +1 -0
- package/dist/tool/bashTool.cjs +7 -0
- package/dist/tool/bashTool.cjs.map +1 -0
- package/dist/tool/bashTool.d.cts +25 -0
- package/dist/tool/bashTool.d.cts.map +1 -0
- package/dist/tool/bashTool.d.mts +25 -0
- package/dist/tool/bashTool.d.mts.map +1 -0
- package/dist/tool/bashTool.mjs +7 -0
- package/dist/tool/bashTool.mjs.map +1 -0
- package/dist/tool/responseEnvelope.cjs +10 -0
- package/dist/tool/responseEnvelope.cjs.map +1 -0
- package/dist/tool/responseEnvelope.d.cts +45 -0
- package/dist/tool/responseEnvelope.d.cts.map +1 -0
- package/dist/tool/responseEnvelope.d.mts +45 -0
- package/dist/tool/responseEnvelope.d.mts.map +1 -0
- package/dist/tool/responseEnvelope.mjs +10 -0
- package/dist/tool/responseEnvelope.mjs.map +1 -0
- package/dist/tool/schema.cjs +2 -0
- package/dist/tool/schema.cjs.map +1 -0
- package/dist/tool/schema.d.cts +25 -0
- package/dist/tool/schema.d.cts.map +1 -0
- package/dist/tool/schema.d.mts +25 -0
- package/dist/tool/schema.d.mts.map +1 -0
- package/dist/tool/schema.mjs +2 -0
- package/dist/tool/schema.mjs.map +1 -0
- package/dist/tui/bashRender.cjs +8 -0
- package/dist/tui/bashRender.cjs.map +1 -0
- package/dist/tui/bashRender.d.cts +51 -0
- package/dist/tui/bashRender.d.cts.map +1 -0
- package/dist/tui/bashRender.d.mts +51 -0
- package/dist/tui/bashRender.d.mts.map +1 -0
- package/dist/tui/bashRender.mjs +8 -0
- package/dist/tui/bashRender.mjs.map +1 -0
- package/dist/tui/format.cjs +2 -0
- package/dist/tui/format.cjs.map +1 -0
- package/dist/tui/format.d.cts +25 -0
- package/dist/tui/format.d.cts.map +1 -0
- package/dist/tui/format.d.mts +25 -0
- package/dist/tui/format.d.mts.map +1 -0
- package/dist/tui/format.mjs +2 -0
- package/dist/tui/format.mjs.map +1 -0
- package/dist/tui/runnerSpace.cjs +6 -0
- package/dist/tui/runnerSpace.cjs.map +1 -0
- package/dist/tui/runnerSpace.d.cts +52 -0
- package/dist/tui/runnerSpace.d.cts.map +1 -0
- package/dist/tui/runnerSpace.d.mts +52 -0
- package/dist/tui/runnerSpace.d.mts.map +1 -0
- package/dist/tui/runnerSpace.mjs +6 -0
- package/dist/tui/runnerSpace.mjs.map +1 -0
- package/dist/types.cjs +2 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +28 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +28 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +335 -0
- package/skills/doom-runner/SKILL.md +69 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//#region src/services/BashRunService/types.d.ts
|
|
2
|
+
interface BashRunRequest {
|
|
3
|
+
command: string;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Stops the command outright once it has run this long. Only meaningful
|
|
7
|
+
* below the background threshold: past that the command is promoted instead.
|
|
8
|
+
*/
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
/** Runs in the background immediately, skipping the wait entirely. */
|
|
11
|
+
background?: boolean;
|
|
12
|
+
/** Runs under a pseudo terminal so the command can prompt for input. */
|
|
13
|
+
interactive?: boolean;
|
|
14
|
+
/** Preferred runner name. A colliding name gets a numbered variant. */
|
|
15
|
+
name?: string;
|
|
16
|
+
/** Receives bounded output snapshots while the command remains in the foreground. */
|
|
17
|
+
onOutput?: (output: string) => void;
|
|
18
|
+
/** Session that owns the runner, so shutdown can stop what it started. */
|
|
19
|
+
sessionId: string;
|
|
20
|
+
}
|
|
21
|
+
/** The command finished inside the foreground window. */
|
|
22
|
+
interface CompletedRun {
|
|
23
|
+
kind: 'completed';
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
output: string;
|
|
27
|
+
exitCode: number | null;
|
|
28
|
+
signal: NodeJS.Signals | null;
|
|
29
|
+
logPath: string;
|
|
30
|
+
backend: 'rmux' | 'tmux' | 'native';
|
|
31
|
+
/** True when the run was stopped by the caller's timeout rather than finishing. */
|
|
32
|
+
timedOut?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** The command is still running and is now a supervised background runner. */
|
|
35
|
+
interface PromotedRun {
|
|
36
|
+
kind: 'promoted';
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
pid: number;
|
|
40
|
+
logPath: string;
|
|
41
|
+
backend: 'rmux' | 'tmux' | 'native';
|
|
42
|
+
/**
|
|
43
|
+
* `requested` when the caller asked for it, `threshold` when it outlived the
|
|
44
|
+
* foreground window, `interactive` when it was hosted on a terminal.
|
|
45
|
+
*/
|
|
46
|
+
reason: 'requested' | 'threshold' | 'interactive';
|
|
47
|
+
}
|
|
48
|
+
/** The process could not be started at all. */
|
|
49
|
+
interface FailedRun {
|
|
50
|
+
kind: 'failed';
|
|
51
|
+
id: string;
|
|
52
|
+
name: string;
|
|
53
|
+
error: string;
|
|
54
|
+
}
|
|
55
|
+
type BashRunResult = CompletedRun | PromotedRun | FailedRun;
|
|
56
|
+
/** Runs one bash command, promoting it to a background runner when it outlives the threshold. */
|
|
57
|
+
interface IBashRunService {
|
|
58
|
+
run(request: BashRunRequest): Promise<BashRunResult>;
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
export { BashRunRequest, BashRunResult, CompletedRun, FailedRun, IBashRunService, PromotedRun };
|
|
62
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../../../src/services/BashRunService/types.ts"],"mappings":";UAAiB;EACf;EACA;;;;;EAKA;;EAEA;;EAEA;;EAEA;;EAEA,YAAY;;EAEZ;;;UAIe;EACf;EACA;EACA;EACA;EACA;EACA,QAAQ,OAAO;EACf;EACA;;EAEA;;;UAIe;EACf;EACA;EACA;EACA;EACA;EACA;;;;;EAKA;;;UAIe;EACf;EACA;EACA;EACA;;KAGU,gBAAgB,eAAe,cAAc;;UAGxC;EACf,IAAI,SAAS,iBAAiB,QAAQ"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//#region src/services/BashRunService/types.d.ts
|
|
2
|
+
interface BashRunRequest {
|
|
3
|
+
command: string;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Stops the command outright once it has run this long. Only meaningful
|
|
7
|
+
* below the background threshold: past that the command is promoted instead.
|
|
8
|
+
*/
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
/** Runs in the background immediately, skipping the wait entirely. */
|
|
11
|
+
background?: boolean;
|
|
12
|
+
/** Runs under a pseudo terminal so the command can prompt for input. */
|
|
13
|
+
interactive?: boolean;
|
|
14
|
+
/** Preferred runner name. A colliding name gets a numbered variant. */
|
|
15
|
+
name?: string;
|
|
16
|
+
/** Receives bounded output snapshots while the command remains in the foreground. */
|
|
17
|
+
onOutput?: (output: string) => void;
|
|
18
|
+
/** Session that owns the runner, so shutdown can stop what it started. */
|
|
19
|
+
sessionId: string;
|
|
20
|
+
}
|
|
21
|
+
/** The command finished inside the foreground window. */
|
|
22
|
+
interface CompletedRun {
|
|
23
|
+
kind: 'completed';
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
output: string;
|
|
27
|
+
exitCode: number | null;
|
|
28
|
+
signal: NodeJS.Signals | null;
|
|
29
|
+
logPath: string;
|
|
30
|
+
backend: 'rmux' | 'tmux' | 'native';
|
|
31
|
+
/** True when the run was stopped by the caller's timeout rather than finishing. */
|
|
32
|
+
timedOut?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** The command is still running and is now a supervised background runner. */
|
|
35
|
+
interface PromotedRun {
|
|
36
|
+
kind: 'promoted';
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
pid: number;
|
|
40
|
+
logPath: string;
|
|
41
|
+
backend: 'rmux' | 'tmux' | 'native';
|
|
42
|
+
/**
|
|
43
|
+
* `requested` when the caller asked for it, `threshold` when it outlived the
|
|
44
|
+
* foreground window, `interactive` when it was hosted on a terminal.
|
|
45
|
+
*/
|
|
46
|
+
reason: 'requested' | 'threshold' | 'interactive';
|
|
47
|
+
}
|
|
48
|
+
/** The process could not be started at all. */
|
|
49
|
+
interface FailedRun {
|
|
50
|
+
kind: 'failed';
|
|
51
|
+
id: string;
|
|
52
|
+
name: string;
|
|
53
|
+
error: string;
|
|
54
|
+
}
|
|
55
|
+
type BashRunResult = CompletedRun | PromotedRun | FailedRun;
|
|
56
|
+
/** Runs one bash command, promoting it to a background runner when it outlives the threshold. */
|
|
57
|
+
interface IBashRunService {
|
|
58
|
+
run(request: BashRunRequest): Promise<BashRunResult>;
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
export { BashRunRequest, BashRunResult, CompletedRun, FailedRun, IBashRunService, PromotedRun };
|
|
62
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/services/BashRunService/types.ts"],"mappings":";UAAiB;EACf;EACA;;;;;EAKA;;EAEA;;EAEA;;EAEA;;EAEA,YAAY;;EAEZ;;;UAIe;EACf;EACA;EACA;EACA;EACA;EACA,QAAQ,OAAO;EACf;EACA;;EAEA;;;UAIe;EACf;EACA;EACA;EACA;EACA;EACA;;;;;EAKA;;;UAIe;EACf;EACA;EACA;EACA;;KAGU,gBAAgB,eAAe,cAAc;;UAGxC;EACf,IAAI,SAAS,iBAAiB,QAAQ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs");let t=require("inversify");require("reflect-metadata/lite");let n=class{now(){return Date.now()}after(e,t){let n=setTimeout(t,e);return n.unref?.(),()=>clearTimeout(n)}};n=e.default([(0,t.injectable)()],n),Object.defineProperty(exports,"SystemClock",{enumerable:!0,get:function(){return n}});
|
|
2
|
+
//# sourceMappingURL=SystemClock.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SystemClock.cjs","names":["injectable"],"sources":["../../../src/services/Clock/SystemClock.ts"],"sourcesContent":["import { injectable } from 'inversify';\nimport 'reflect-metadata/lite';\nimport type { IClock } from './types.ts';\n\n/** Real wall clock and timers. */\n@injectable()\nexport class SystemClock implements IClock {\n now(): number {\n return Date.now();\n }\n\n after(ms: number, handler: () => void): () => void {\n const timer = setTimeout(handler, ms);\n // The timer must never be the reason the host process stays alive.\n timer.unref?.();\n return () => clearTimeout(timer);\n }\n}\n"],"mappings":"wNAMO,IAAM,EAAN,KAAoC,CACzC,KAAc,CACZ,OAAO,KAAK,IAAI,CAClB,CAEA,MAAM,EAAY,EAAiC,CACjD,IAAM,EAAQ,WAAW,EAAS,CAAE,EAGpC,OADA,EAAM,QAAQ,MACD,aAAa,CAAK,CACjC,CACF,EAZCA,EAAAA,EAAAA,QAAAA,EAAAA,EAAAA,EAAAA,WAAAA,CAAW,CAAA,EAAA,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IClock } from "./types.cjs";
|
|
2
|
+
import "reflect-metadata/lite";
|
|
3
|
+
//#region src/services/Clock/SystemClock.d.ts
|
|
4
|
+
/** Real wall clock and timers. */
|
|
5
|
+
declare class SystemClock implements IClock {
|
|
6
|
+
now(): number;
|
|
7
|
+
after(ms: number, handler: () => void): () => void;
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { SystemClock };
|
|
11
|
+
//# sourceMappingURL=SystemClock.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SystemClock.d.cts","names":[],"sources":["../../../src/services/Clock/SystemClock.ts"],"mappings":";;;;cAMa,uBAAuB;EAClC;EAIA,MAAM,YAAY"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IClock } from "./types.mjs";
|
|
2
|
+
import "reflect-metadata/lite";
|
|
3
|
+
//#region src/services/Clock/SystemClock.d.ts
|
|
4
|
+
/** Real wall clock and timers. */
|
|
5
|
+
declare class SystemClock implements IClock {
|
|
6
|
+
now(): number;
|
|
7
|
+
after(ms: number, handler: () => void): () => void;
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { SystemClock };
|
|
11
|
+
//# sourceMappingURL=SystemClock.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SystemClock.d.mts","names":[],"sources":["../../../src/services/Clock/SystemClock.ts"],"mappings":";;;;cAMa,uBAAuB;EAClC;EAIA,MAAM,YAAY"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{injectable as t}from"inversify";import"reflect-metadata/lite";let n=class{now(){return Date.now()}after(e,t){let n=setTimeout(t,e);return n.unref?.(),()=>clearTimeout(n)}};n=e([t()],n);export{n as SystemClock};
|
|
2
|
+
//# sourceMappingURL=SystemClock.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SystemClock.mjs","names":[],"sources":["../../../src/services/Clock/SystemClock.ts"],"sourcesContent":["import { injectable } from 'inversify';\nimport 'reflect-metadata/lite';\nimport type { IClock } from './types.ts';\n\n/** Real wall clock and timers. */\n@injectable()\nexport class SystemClock implements IClock {\n now(): number {\n return Date.now();\n }\n\n after(ms: number, handler: () => void): () => void {\n const timer = setTimeout(handler, ms);\n // The timer must never be the reason the host process stays alive.\n timer.unref?.();\n return () => clearTimeout(timer);\n }\n}\n"],"mappings":"0JAMO,IAAM,EAAN,KAAoC,CACzC,KAAc,CACZ,OAAO,KAAK,IAAI,CAClB,CAEA,MAAM,EAAY,EAAiC,CACjD,IAAM,EAAQ,WAAW,EAAS,CAAE,EAGpC,OADA,EAAM,QAAQ,MACD,aAAa,CAAK,CACjC,CACF,EAZC,EAAA,EAAA,CAAA,EAAW,CAAA,EAAA,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./SystemClock.cjs");Object.defineProperty(exports,"SystemClock",{enumerable:!0,get:function(){return e.SystemClock}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{SystemClock as e}from"./SystemClock.mjs";export{e as SystemClock};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/services/Clock/types.d.ts
|
|
2
|
+
/** Time and timers as a port, so the background threshold is testable. */
|
|
3
|
+
interface IClock {
|
|
4
|
+
/** Milliseconds since the epoch. */
|
|
5
|
+
now(): number;
|
|
6
|
+
/** Schedules `handler` after `ms` and returns a cancel function. */
|
|
7
|
+
after(ms: number, handler: () => void): () => void;
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { IClock };
|
|
11
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../../../src/services/Clock/types.ts"],"mappings":";;UACiB;;EAEf;;EAEA,MAAM,YAAY"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/services/Clock/types.d.ts
|
|
2
|
+
/** Time and timers as a port, so the background threshold is testable. */
|
|
3
|
+
interface IClock {
|
|
4
|
+
/** Milliseconds since the epoch. */
|
|
5
|
+
now(): number;
|
|
6
|
+
/** Schedules `handler` after `ms` and returns a cancel function. */
|
|
7
|
+
after(ms: number, handler: () => void): () => void;
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { IClock };
|
|
11
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/services/Clock/types.ts"],"mappings":";;UACiB;;EAEf;;EAEA,MAAM,YAAY"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../config.cjs"),n=require("../../types.cjs"),r=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.cjs"),i=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.cjs"),a=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs"),o=require("../../runnerSpec.cjs"),s=require("../../session.cjs");let c=require("inversify");require("reflect-metadata/lite");let l=require("node:fs");l=e.__toESM(l,1);const u={FORCE_COLOR:`1`,CI:`1`};let d=class{spawner;processControl;logFile;clock;paths;constructor(e,t,n,r,i){this.spawner=e,this.processControl=t,this.logFile=n,this.clock=r,this.paths=i}launch(e){let n=this.logFile.open(e.id),r=t.getResultMaxBytes()*2,i=``,a=!0,c=!1,d=()=>void 0,p=()=>void 0,m=new Promise((e,t)=>{d=e,p=t});this.paths.ensureDirectories(e.sessionId);let h=o.supervisorPaths(this.paths.stateDirectory(e.sessionId),e.id),g={...process.env,...u,...o.NO_TERMINAL_INPUT_ENV,[s.PI_SESSION_ID_ENV]:e.sessionId};o.cleanupSupervisorFiles(h),o.writeCommandSpec(h.spec,{command:e.command,cwd:e.cwd,env:f(g)}),l.default.writeFileSync(h.gate,``,{mode:384});let _=this.spawner.spawn({command:o.supervisorCommand(h),cwd:e.cwd,env:g,detached:!0});return _.onOutput(e=>{n.append(e),a&&(i+=e,i.length>r&&(i=i.slice(-r)))}),_.onError(e=>{c||(c=!0,n.close(),o.cleanupSupervisorFiles(h),p(e))}),_.onExit(e=>{if(c)return;c=!0,n.close();let t=o.readExitMetadata(h.exit)??e;o.cleanupSupervisorFiles(h),d(t)}),_.unref(),{id:e.id,name:e.name,pid:_.pid,logPath:n.path,backend:`native`,output:()=>i,completion:()=>m,detach:()=>{a=!1,i=``},stop:async()=>_.pid!==void 0&&this.stop(_.pid)}}async stop(e){if(!this.processControl.isAlive(e))return!1;this.processControl.signalGroup(e,`SIGTERM`);let t=this.clock.now()+2e3;for(;this.clock.now()<t;){if(!this.processControl.isAlive(e))return!0;await this.sleep(100)}return this.processControl.signalGroup(e,`SIGKILL`),!0}sleep(e){return new Promise(t=>{this.clock.after(e,t)})}};d=a.default([(0,c.injectable)(),i.default(0,(0,c.inject)(n.TYPES.Spawner)),i.default(1,(0,c.inject)(n.TYPES.ProcessControl)),i.default(2,(0,c.inject)(n.TYPES.LogFile)),i.default(3,(0,c.inject)(n.TYPES.Clock)),i.default(4,(0,c.inject)(n.TYPES.RunnerPaths)),r.default(`design:paramtypes`,[Object,Object,Object,Object,Object])],d);function f(e){return Object.fromEntries(Object.entries(e).filter(e=>e[1]!==void 0))}Object.defineProperty(exports,"Launcher",{enumerable:!0,get:function(){return d}});
|
|
2
|
+
//# sourceMappingURL=Launcher.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Launcher.cjs","names":["getResultMaxBytes","supervisorPaths","NO_TERMINAL_INPUT_ENV","PI_SESSION_ID_ENV","supervisorCommand","readExitMetadata","injectable","inject","TYPES"],"sources":["../../../src/services/Launcher/Launcher.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { inject, injectable } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { getResultMaxBytes } from '../../config.ts';\nimport {\n NO_TERMINAL_INPUT_ENV,\n cleanupSupervisorFiles,\n readExitMetadata,\n supervisorCommand,\n supervisorPaths,\n writeCommandSpec,\n} from '../../runnerSpec.ts';\nimport { TYPES } from '../../types.ts';\nimport type { IClock } from '../Clock/index.ts';\nimport type { ILogFile } from '../LogFile/index.ts';\nimport type { IProcessControl } from '../ProcessControl/index.ts';\nimport type { IRunnerPaths } from '../RunnerPaths/index.ts';\nimport type { ExitResult, ISpawner } from '../Spawner/index.ts';\nimport type { ILauncher, LaunchRequest, RunHandle } from './types.ts';\nimport { PI_SESSION_ID_ENV } from '../../session.ts';\n\n/**\n * Prompts belong on a screen, not in a log file, so `CI` stays set.\n *\n * Colour is kept: the log is replayed into the transcript, and the scrub keeps\n * SGR while still removing the cursor moves that made raw output unreadable.\n */\nconst NON_INTERACTIVE_ENV = { FORCE_COLOR: '1', CI: '1' };\nconst TERM_GRACE_MS = 2_000;\nconst LIVENESS_POLL_MS = 100;\n/** In-memory output is a multiple of the result ceiling; the log holds the rest. */\nconst MEMORY_BUFFER_FACTOR = 2;\nconst GATE_MODE = 0o600;\n\n@injectable()\nexport class Launcher implements ILauncher {\n constructor(\n @inject(TYPES.Spawner) private readonly spawner: ISpawner,\n @inject(TYPES.ProcessControl) private readonly processControl: IProcessControl,\n @inject(TYPES.LogFile) private readonly logFile: ILogFile,\n @inject(TYPES.Clock) private readonly clock: IClock,\n @inject(TYPES.RunnerPaths) private readonly paths: IRunnerPaths,\n ) {}\n\n launch(request: LaunchRequest): RunHandle {\n const writer = this.logFile.open(request.id);\n const memoryLimit = getResultMaxBytes() * MEMORY_BUFFER_FACTOR;\n\n let buffer = '';\n let buffering = true;\n let settled = false;\n let resolveCompletion: (result: ExitResult) => void = () => undefined;\n let rejectCompletion: (error: Error) => void = () => undefined;\n const completion = new Promise<ExitResult>((resolve, reject) => {\n resolveCompletion = resolve;\n rejectCompletion = reject;\n });\n\n this.paths.ensureDirectories(request.sessionId);\n const supervisor = supervisorPaths(this.paths.stateDirectory(request.sessionId), request.id);\n const env = {\n ...process.env,\n ...NON_INTERACTIVE_ENV,\n ...NO_TERMINAL_INPUT_ENV,\n [PI_SESSION_ID_ENV]: request.sessionId,\n };\n cleanupSupervisorFiles(supervisor);\n writeCommandSpec(supervisor.spec, { command: request.command, cwd: request.cwd, env: defined(env) });\n // Nothing has to be attached before this runner starts, so its gate opens at once.\n fs.writeFileSync(supervisor.gate, '', { mode: GATE_MODE });\n\n const child = this.spawner.spawn({\n // runnerHost supervises the command: it forwards signals and, if the owning\n // pi dies without running its shutdown handler, kills the group itself.\n command: supervisorCommand(supervisor),\n cwd: request.cwd,\n env,\n // Its own process group, so stopping a runner takes the whole tree with it.\n detached: true,\n });\n\n child.onOutput((chunk) => {\n writer.append(chunk);\n if (!buffering) return;\n buffer += chunk;\n if (buffer.length > memoryLimit) buffer = buffer.slice(-memoryLimit);\n });\n\n child.onError((error) => {\n if (settled) return;\n settled = true;\n writer.close();\n cleanupSupervisorFiles(supervisor);\n rejectCompletion(error);\n });\n\n child.onExit((result) => {\n if (settled) return;\n settled = true;\n writer.close();\n // The supervisor collapses a signalled command into an exit code, so its\n // own sidecar is the only place the original signal survives.\n const outcome = readExitMetadata(supervisor.exit) ?? result;\n cleanupSupervisorFiles(supervisor);\n resolveCompletion(outcome);\n });\n\n // The launcher must never hold the pi process open on a runner's behalf.\n child.unref();\n\n const stop = async (): Promise<boolean> => (child.pid === undefined ? false : this.stop(child.pid));\n\n return {\n id: request.id,\n name: request.name,\n pid: child.pid,\n logPath: writer.path,\n backend: 'native',\n output: () => buffer,\n completion: () => completion,\n detach: () => {\n buffering = false;\n buffer = '';\n },\n stop,\n };\n }\n\n async stop(pid: number): Promise<boolean> {\n if (!this.processControl.isAlive(pid)) return false;\n\n this.processControl.signalGroup(pid, 'SIGTERM');\n const deadline = this.clock.now() + TERM_GRACE_MS;\n while (this.clock.now() < deadline) {\n if (!this.processControl.isAlive(pid)) return true;\n await this.sleep(LIVENESS_POLL_MS);\n }\n\n this.processControl.signalGroup(pid, 'SIGKILL');\n return true;\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n this.clock.after(ms, resolve);\n });\n }\n}\n\n/** The spec is JSON, which has no way to carry an unset variable. */\nfunction defined(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(Object.entries(env).filter((entry): entry is [string, string] => entry[1] !== undefined));\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { IClock } from "../Clock/types.cjs";
|
|
2
|
+
import "../Clock/index.cjs";
|
|
3
|
+
import { IRunnerPaths } from "../RunnerPaths/types.cjs";
|
|
4
|
+
import "../RunnerPaths/index.cjs";
|
|
5
|
+
import { ILogFile } from "../LogFile/types.cjs";
|
|
6
|
+
import "../LogFile/index.cjs";
|
|
7
|
+
import { IProcessControl } from "../ProcessControl/types.cjs";
|
|
8
|
+
import "../ProcessControl/index.cjs";
|
|
9
|
+
import { ISpawner } from "../Spawner/types.cjs";
|
|
10
|
+
import "../Spawner/index.cjs";
|
|
11
|
+
import { ILauncher, LaunchRequest, RunHandle } from "./types.cjs";
|
|
12
|
+
import "reflect-metadata/lite";
|
|
13
|
+
//#region src/services/Launcher/Launcher.d.ts
|
|
14
|
+
declare class Launcher implements ILauncher {
|
|
15
|
+
private readonly spawner;
|
|
16
|
+
private readonly processControl;
|
|
17
|
+
private readonly logFile;
|
|
18
|
+
private readonly clock;
|
|
19
|
+
private readonly paths;
|
|
20
|
+
constructor(spawner: ISpawner, processControl: IProcessControl, logFile: ILogFile, clock: IClock, paths: IRunnerPaths);
|
|
21
|
+
launch(request: LaunchRequest): RunHandle;
|
|
22
|
+
stop(pid: number): Promise<boolean>;
|
|
23
|
+
private sleep;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { Launcher };
|
|
27
|
+
//# sourceMappingURL=Launcher.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Launcher.d.cts","names":[],"sources":["../../../src/services/Launcher/Launcher.ts"],"mappings":";;;;;;;;;;;;;cAmCa,oBAAoB;mBAEW;mBACO;mBACP;mBACF;mBACM;EAJJ,YAAA,SAAS,UACF,gBAAgB,iBACvB,SAAS,UACX,OAAO,QACD,OAAO;EAGrD,OAAO,SAAS,gBAAgB;EAoF1B,KAAK,cAAc;UAcjB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { IClock } from "../Clock/types.mjs";
|
|
2
|
+
import "../Clock/index.mjs";
|
|
3
|
+
import { IRunnerPaths } from "../RunnerPaths/types.mjs";
|
|
4
|
+
import "../RunnerPaths/index.mjs";
|
|
5
|
+
import { ILogFile } from "../LogFile/types.mjs";
|
|
6
|
+
import "../LogFile/index.mjs";
|
|
7
|
+
import { IProcessControl } from "../ProcessControl/types.mjs";
|
|
8
|
+
import "../ProcessControl/index.mjs";
|
|
9
|
+
import { ISpawner } from "../Spawner/types.mjs";
|
|
10
|
+
import "../Spawner/index.mjs";
|
|
11
|
+
import { ILauncher, LaunchRequest, RunHandle } from "./types.mjs";
|
|
12
|
+
import "reflect-metadata/lite";
|
|
13
|
+
//#region src/services/Launcher/Launcher.d.ts
|
|
14
|
+
declare class Launcher implements ILauncher {
|
|
15
|
+
private readonly spawner;
|
|
16
|
+
private readonly processControl;
|
|
17
|
+
private readonly logFile;
|
|
18
|
+
private readonly clock;
|
|
19
|
+
private readonly paths;
|
|
20
|
+
constructor(spawner: ISpawner, processControl: IProcessControl, logFile: ILogFile, clock: IClock, paths: IRunnerPaths);
|
|
21
|
+
launch(request: LaunchRequest): RunHandle;
|
|
22
|
+
stop(pid: number): Promise<boolean>;
|
|
23
|
+
private sleep;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { Launcher };
|
|
27
|
+
//# sourceMappingURL=Launcher.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Launcher.d.mts","names":[],"sources":["../../../src/services/Launcher/Launcher.ts"],"mappings":";;;;;;;;;;;;;cAmCa,oBAAoB;mBAEW;mBACO;mBACP;mBACF;mBACM;EAJJ,YAAA,SAAS,UACF,gBAAgB,iBACvB,SAAS,UACX,OAAO,QACD,OAAO;EAGrD,OAAO,SAAS,gBAAgB;EAoF1B,KAAK,cAAc;UAcjB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{getResultMaxBytes as e}from"../../config.mjs";import{TYPES as t}from"../../types.mjs";import n from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.mjs";import r from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.mjs";import i from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{NO_TERMINAL_INPUT_ENV as a,cleanupSupervisorFiles as o,readExitMetadata as s,supervisorCommand as c,supervisorPaths as l,writeCommandSpec as u}from"../../runnerSpec.mjs";import{PI_SESSION_ID_ENV as d}from"../../session.mjs";import{inject as f,injectable as p}from"inversify";import"reflect-metadata/lite";import m from"node:fs";const h={FORCE_COLOR:`1`,CI:`1`};let g=class{spawner;processControl;logFile;clock;paths;constructor(e,t,n,r,i){this.spawner=e,this.processControl=t,this.logFile=n,this.clock=r,this.paths=i}launch(t){let n=this.logFile.open(t.id),r=e()*2,i=``,f=!0,p=!1,g=()=>void 0,v=()=>void 0,y=new Promise((e,t)=>{g=e,v=t});this.paths.ensureDirectories(t.sessionId);let b=l(this.paths.stateDirectory(t.sessionId),t.id),x={...process.env,...h,...a,[d]:t.sessionId};o(b),u(b.spec,{command:t.command,cwd:t.cwd,env:_(x)}),m.writeFileSync(b.gate,``,{mode:384});let S=this.spawner.spawn({command:c(b),cwd:t.cwd,env:x,detached:!0});return S.onOutput(e=>{n.append(e),f&&(i+=e,i.length>r&&(i=i.slice(-r)))}),S.onError(e=>{p||(p=!0,n.close(),o(b),v(e))}),S.onExit(e=>{if(p)return;p=!0,n.close();let t=s(b.exit)??e;o(b),g(t)}),S.unref(),{id:t.id,name:t.name,pid:S.pid,logPath:n.path,backend:`native`,output:()=>i,completion:()=>y,detach:()=>{f=!1,i=``},stop:async()=>S.pid!==void 0&&this.stop(S.pid)}}async stop(e){if(!this.processControl.isAlive(e))return!1;this.processControl.signalGroup(e,`SIGTERM`);let t=this.clock.now()+2e3;for(;this.clock.now()<t;){if(!this.processControl.isAlive(e))return!0;await this.sleep(100)}return this.processControl.signalGroup(e,`SIGKILL`),!0}sleep(e){return new Promise(t=>{this.clock.after(e,t)})}};g=i([p(),r(0,f(t.Spawner)),r(1,f(t.ProcessControl)),r(2,f(t.LogFile)),r(3,f(t.Clock)),r(4,f(t.RunnerPaths)),n(`design:paramtypes`,[Object,Object,Object,Object,Object])],g);function _(e){return Object.fromEntries(Object.entries(e).filter(e=>e[1]!==void 0))}export{g as Launcher};
|
|
2
|
+
//# sourceMappingURL=Launcher.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Launcher.mjs","names":[],"sources":["../../../src/services/Launcher/Launcher.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { inject, injectable } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { getResultMaxBytes } from '../../config.ts';\nimport {\n NO_TERMINAL_INPUT_ENV,\n cleanupSupervisorFiles,\n readExitMetadata,\n supervisorCommand,\n supervisorPaths,\n writeCommandSpec,\n} from '../../runnerSpec.ts';\nimport { TYPES } from '../../types.ts';\nimport type { IClock } from '../Clock/index.ts';\nimport type { ILogFile } from '../LogFile/index.ts';\nimport type { IProcessControl } from '../ProcessControl/index.ts';\nimport type { IRunnerPaths } from '../RunnerPaths/index.ts';\nimport type { ExitResult, ISpawner } from '../Spawner/index.ts';\nimport type { ILauncher, LaunchRequest, RunHandle } from './types.ts';\nimport { PI_SESSION_ID_ENV } from '../../session.ts';\n\n/**\n * Prompts belong on a screen, not in a log file, so `CI` stays set.\n *\n * Colour is kept: the log is replayed into the transcript, and the scrub keeps\n * SGR while still removing the cursor moves that made raw output unreadable.\n */\nconst NON_INTERACTIVE_ENV = { FORCE_COLOR: '1', CI: '1' };\nconst TERM_GRACE_MS = 2_000;\nconst LIVENESS_POLL_MS = 100;\n/** In-memory output is a multiple of the result ceiling; the log holds the rest. */\nconst MEMORY_BUFFER_FACTOR = 2;\nconst GATE_MODE = 0o600;\n\n@injectable()\nexport class Launcher implements ILauncher {\n constructor(\n @inject(TYPES.Spawner) private readonly spawner: ISpawner,\n @inject(TYPES.ProcessControl) private readonly processControl: IProcessControl,\n @inject(TYPES.LogFile) private readonly logFile: ILogFile,\n @inject(TYPES.Clock) private readonly clock: IClock,\n @inject(TYPES.RunnerPaths) private readonly paths: IRunnerPaths,\n ) {}\n\n launch(request: LaunchRequest): RunHandle {\n const writer = this.logFile.open(request.id);\n const memoryLimit = getResultMaxBytes() * MEMORY_BUFFER_FACTOR;\n\n let buffer = '';\n let buffering = true;\n let settled = false;\n let resolveCompletion: (result: ExitResult) => void = () => undefined;\n let rejectCompletion: (error: Error) => void = () => undefined;\n const completion = new Promise<ExitResult>((resolve, reject) => {\n resolveCompletion = resolve;\n rejectCompletion = reject;\n });\n\n this.paths.ensureDirectories(request.sessionId);\n const supervisor = supervisorPaths(this.paths.stateDirectory(request.sessionId), request.id);\n const env = {\n ...process.env,\n ...NON_INTERACTIVE_ENV,\n ...NO_TERMINAL_INPUT_ENV,\n [PI_SESSION_ID_ENV]: request.sessionId,\n };\n cleanupSupervisorFiles(supervisor);\n writeCommandSpec(supervisor.spec, { command: request.command, cwd: request.cwd, env: defined(env) });\n // Nothing has to be attached before this runner starts, so its gate opens at once.\n fs.writeFileSync(supervisor.gate, '', { mode: GATE_MODE });\n\n const child = this.spawner.spawn({\n // runnerHost supervises the command: it forwards signals and, if the owning\n // pi dies without running its shutdown handler, kills the group itself.\n command: supervisorCommand(supervisor),\n cwd: request.cwd,\n env,\n // Its own process group, so stopping a runner takes the whole tree with it.\n detached: true,\n });\n\n child.onOutput((chunk) => {\n writer.append(chunk);\n if (!buffering) return;\n buffer += chunk;\n if (buffer.length > memoryLimit) buffer = buffer.slice(-memoryLimit);\n });\n\n child.onError((error) => {\n if (settled) return;\n settled = true;\n writer.close();\n cleanupSupervisorFiles(supervisor);\n rejectCompletion(error);\n });\n\n child.onExit((result) => {\n if (settled) return;\n settled = true;\n writer.close();\n // The supervisor collapses a signalled command into an exit code, so its\n // own sidecar is the only place the original signal survives.\n const outcome = readExitMetadata(supervisor.exit) ?? result;\n cleanupSupervisorFiles(supervisor);\n resolveCompletion(outcome);\n });\n\n // The launcher must never hold the pi process open on a runner's behalf.\n child.unref();\n\n const stop = async (): Promise<boolean> => (child.pid === undefined ? false : this.stop(child.pid));\n\n return {\n id: request.id,\n name: request.name,\n pid: child.pid,\n logPath: writer.path,\n backend: 'native',\n output: () => buffer,\n completion: () => completion,\n detach: () => {\n buffering = false;\n buffer = '';\n },\n stop,\n };\n }\n\n async stop(pid: number): Promise<boolean> {\n if (!this.processControl.isAlive(pid)) return false;\n\n this.processControl.signalGroup(pid, 'SIGTERM');\n const deadline = this.clock.now() + TERM_GRACE_MS;\n while (this.clock.now() < deadline) {\n if (!this.processControl.isAlive(pid)) return true;\n await this.sleep(LIVENESS_POLL_MS);\n }\n\n this.processControl.signalGroup(pid, 'SIGKILL');\n return true;\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n this.clock.after(ms, resolve);\n });\n }\n}\n\n/** The spec is JSON, which has no way to carry an unset variable. */\nfunction defined(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(Object.entries(env).filter((entry): entry is [string, string] => entry[1] !== undefined));\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./Launcher.cjs");Object.defineProperty(exports,"Launcher",{enumerable:!0,get:function(){return e.Launcher}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Launcher as e}from"./Launcher.mjs";export{e as Launcher};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ExitResult } from "../Spawner/types.cjs";
|
|
2
|
+
import "../Spawner/index.cjs";
|
|
3
|
+
//#region src/services/Launcher/types.d.ts
|
|
4
|
+
interface LaunchRequest {
|
|
5
|
+
id: string;
|
|
6
|
+
/** Runner name, already allocated and free of collisions. */
|
|
7
|
+
name: string;
|
|
8
|
+
command: string;
|
|
9
|
+
cwd: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
}
|
|
12
|
+
interface RunHandle {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly pid: number | undefined;
|
|
16
|
+
readonly logPath: string;
|
|
17
|
+
readonly backend: 'rmux' | 'tmux' | 'native';
|
|
18
|
+
readonly backendTarget?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Output captured so far, tail-capped. The log file always holds everything.
|
|
21
|
+
*/
|
|
22
|
+
output(): string;
|
|
23
|
+
/** Resolves when the process exits, or rejects if it never started. */
|
|
24
|
+
completion(): Promise<ExitResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Stops buffering output in memory and lets the process outlive this handle.
|
|
27
|
+
* Called when a run is promoted to a background runner.
|
|
28
|
+
*/
|
|
29
|
+
detach(): void;
|
|
30
|
+
/** Signals the process group and waits for it to go away. */
|
|
31
|
+
stop(): Promise<boolean>;
|
|
32
|
+
}
|
|
33
|
+
interface ILauncher {
|
|
34
|
+
launch(request: LaunchRequest): RunHandle;
|
|
35
|
+
/** SIGTERM the group led by `pid`, then SIGKILL if it outlasts the grace period. */
|
|
36
|
+
stop(pid: number): Promise<boolean>;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { ILauncher, LaunchRequest, RunHandle };
|
|
40
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../../../src/services/Launcher/types.ts"],"mappings":";;;UAEiB;EACf;;EAEA;EACA;EACA;EACA;;UAGe;WACN;WACA;WACA;WACA;WACA;WACA;;;;EAIT;;EAEA,cAAc,QAAQ;;;;;EAKtB;;EAEA,QAAQ;;UAGO;EACf,OAAO,SAAS,gBAAgB;;EAEhC,KAAK,cAAc"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ExitResult } from "../Spawner/types.mjs";
|
|
2
|
+
import "../Spawner/index.mjs";
|
|
3
|
+
//#region src/services/Launcher/types.d.ts
|
|
4
|
+
interface LaunchRequest {
|
|
5
|
+
id: string;
|
|
6
|
+
/** Runner name, already allocated and free of collisions. */
|
|
7
|
+
name: string;
|
|
8
|
+
command: string;
|
|
9
|
+
cwd: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
}
|
|
12
|
+
interface RunHandle {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly pid: number | undefined;
|
|
16
|
+
readonly logPath: string;
|
|
17
|
+
readonly backend: 'rmux' | 'tmux' | 'native';
|
|
18
|
+
readonly backendTarget?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Output captured so far, tail-capped. The log file always holds everything.
|
|
21
|
+
*/
|
|
22
|
+
output(): string;
|
|
23
|
+
/** Resolves when the process exits, or rejects if it never started. */
|
|
24
|
+
completion(): Promise<ExitResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Stops buffering output in memory and lets the process outlive this handle.
|
|
27
|
+
* Called when a run is promoted to a background runner.
|
|
28
|
+
*/
|
|
29
|
+
detach(): void;
|
|
30
|
+
/** Signals the process group and waits for it to go away. */
|
|
31
|
+
stop(): Promise<boolean>;
|
|
32
|
+
}
|
|
33
|
+
interface ILauncher {
|
|
34
|
+
launch(request: LaunchRequest): RunHandle;
|
|
35
|
+
/** SIGTERM the group led by `pid`, then SIGKILL if it outlasts the grace period. */
|
|
36
|
+
stop(pid: number): Promise<boolean>;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { ILauncher, LaunchRequest, RunHandle };
|
|
40
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/services/Launcher/types.ts"],"mappings":";;;UAEiB;EACf;;EAEA;EACA;EACA;EACA;;UAGe;WACN;WACA;WACA;WACA;WACA;WACA;;;;EAIT;;EAEA,cAAc,QAAQ;;;;;EAKtB;;EAEA,QAAQ;;UAGO;EACf,OAAO,SAAS,gBAAgB;;EAEhC,KAAK,cAAc"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../types.cjs"),n=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.cjs"),r=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.cjs"),i=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs"),a=require("./client.cjs");let o=require("inversify");require("reflect-metadata/lite");let s=require("node:crypto"),c=require("node:fs");c=e.__toESM(c,1);let l=require("node:path");l=e.__toESM(l,1);let u=require("node:net");u=e.__toESM(u,1);let d=require("node:os");d=e.__toESM(d,1);let f=class{paths;server;target;connections=new Set;constructor(e){this.paths=e}async arm(e){if(this.target)return this.target;try{this.paths.ensureDirectories(e);let t=this.socketPath(e);c.default.rmSync(t,{force:!0});let n=u.default.createServer(e=>{e.unref(),e.resume(),this.connections.add(e),e.on(`close`,()=>this.connections.delete(e))});return await p(n,t),c.default.chmodSync(t,384),n.unref(),this.server=n,this.target=t,process.env[a.LIFELINE_ENV]=t,t}catch(e){process.emitWarning(`Could not arm the doom-runner lifeline: ${String(e)}`);return}}path(){return this.target}dispose(){for(let e of this.connections)e.destroy();if(this.connections.clear(),this.server){try{this.server.close()}catch(e){process.emitWarning(`Could not close the doom-runner lifeline: ${String(e)}`)}this.server=void 0}if(this.target){try{c.default.rmSync(this.target,{force:!0})}catch(e){process.emitWarning(`Could not remove the doom-runner lifeline: ${String(e)}`)}this.target=void 0}process.env.DOOM_RUNNER_LIFELINE&&delete process.env[a.LIFELINE_ENV]}socketPath(e){let t=l.default.join(this.paths.stateDirectory(e),`lifeline.sock`);if(Buffer.byteLength(t)<=100)return t;let n=(0,s.createHash)(`sha256`).update(t).digest(`hex`).slice(0,12);return l.default.join(d.default.tmpdir(),`doom-runner-${n}.sock`)}};f=i.default([(0,o.injectable)(),r.default(0,(0,o.inject)(t.TYPES.RunnerPaths)),n.default(`design:paramtypes`,[Object])],f);function p(e,t){return new Promise((n,r)=>{e.once(`error`,r),e.listen(t,()=>{e.removeListener(`error`,r),e.on(`error`,e=>process.emitWarning(`doom-runner lifeline failed: ${e.message}`)),n()})})}Object.defineProperty(exports,"NodeLifeline",{enumerable:!0,get:function(){return f}});
|
|
2
|
+
//# sourceMappingURL=NodeLifeline.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeLifeline.cjs","names":["net","LIFELINE_ENV","path","createHash","os","injectable","inject","TYPES"],"sources":["../../../src/services/Lifeline/NodeLifeline.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport net from 'node:net';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { inject, injectable } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { TYPES } from '../../types.ts';\nimport type { IRunnerPaths } from '../RunnerPaths/index.ts';\nimport { LIFELINE_ENV } from './client.ts';\nimport type { ILifeline } from './types.ts';\n\nconst SOCKET_NAME = 'lifeline.sock';\n/** Unix socket paths are capped at 104 bytes, so a long agent directory falls back to the temp dir. */\nconst SOCKET_PATH_LIMIT = 100;\nconst SOCKET_HASH_LENGTH = 12;\nconst SOCKET_MODE = 0o600;\n\n@injectable()\nexport class NodeLifeline implements ILifeline {\n private server: net.Server | undefined;\n private target: string | undefined;\n /** Closing a server stops it accepting; only the connections carry the death signal. */\n private readonly connections = new Set<net.Socket>();\n\n constructor(@inject(TYPES.RunnerPaths) private readonly paths: IRunnerPaths) {}\n\n async arm(sessionId: string): Promise<string | undefined> {\n if (this.target) return this.target;\n try {\n this.paths.ensureDirectories(sessionId);\n const target = this.socketPath(sessionId);\n // A socket left behind by a SIGKILLed predecessor refuses connections, never accepts them.\n fs.rmSync(target, { force: true });\n const server = net.createServer((connection) => {\n // Runners need only the close edge, so their liveness and their data are equally irrelevant.\n connection.unref();\n connection.resume();\n this.connections.add(connection);\n connection.on('close', () => this.connections.delete(connection));\n });\n await listen(server, target);\n fs.chmodSync(target, SOCKET_MODE);\n // The lifeline must never be the reason pi stays alive.\n server.unref();\n this.server = server;\n this.target = target;\n process.env[LIFELINE_ENV] = target;\n return target;\n } catch (error) {\n // Runners stay unwatched rather than unlaunchable, so a session without a\n // lifeline degrades to running them unsupervised instead of failing.\n process.emitWarning(`Could not arm the doom-runner lifeline: ${String(error)}`);\n return undefined;\n }\n }\n\n path(): string | undefined {\n return this.target;\n }\n\n dispose(): void {\n // Dropping the connections is what a runner sees, and it is the whole point\n // of disposing: closing the server alone would leave every runner waiting.\n for (const connection of this.connections) connection.destroy();\n this.connections.clear();\n if (this.server) {\n try {\n this.server.close();\n } catch (error) {\n process.emitWarning(`Could not close the doom-runner lifeline: ${String(error)}`);\n }\n this.server = undefined;\n }\n if (this.target) {\n try {\n fs.rmSync(this.target, { force: true });\n } catch (error) {\n process.emitWarning(`Could not remove the doom-runner lifeline: ${String(error)}`);\n }\n this.target = undefined;\n }\n if (process.env[LIFELINE_ENV]) delete process.env[LIFELINE_ENV];\n }\n\n /** Keeps the socket beside the session it belongs to unless that path is too long to bind. */\n private socketPath(sessionId: string): string {\n const preferred = path.join(this.paths.stateDirectory(sessionId), SOCKET_NAME);\n if (Buffer.byteLength(preferred) <= SOCKET_PATH_LIMIT) return preferred;\n const hash = createHash('sha256').update(preferred).digest('hex').slice(0, SOCKET_HASH_LENGTH);\n return path.join(os.tmpdir(), `doom-runner-${hash}.sock`);\n }\n}\n\n/** Binding must complete before the first runner launches, so arming waits for it. */\nfunction listen(server: net.Server, target: string): Promise<void> {\n return new Promise((resolve, reject) => {\n server.once('error', reject);\n server.listen(target, () => {\n server.removeListener('error', reject);\n // Later errors would otherwise reach the process as unhandled.\n server.on('error', (error: Error) => process.emitWarning(`doom-runner lifeline failed: ${error.message}`));\n resolve();\n });\n });\n}\n"],"mappings":"wrBAmBO,IAAM,EAAN,KAAwC,CAMW,MALxD,OACA,OAEA,YAA+B,IAAI,IAEnC,YAAY,EAAiE,CAArB,KAAA,MAAA,CAAsB,CAE9E,MAAM,IAAI,EAAgD,CACxD,GAAI,KAAK,OAAQ,OAAO,KAAK,OAC7B,GAAI,CACF,KAAK,MAAM,kBAAkB,CAAS,EACtC,IAAM,EAAS,KAAK,WAAW,CAAS,EAExC,EAAA,QAAG,OAAO,EAAQ,CAAE,MAAO,EAAK,CAAC,EACjC,IAAM,EAASA,EAAAA,QAAI,aAAc,GAAe,CAE9C,EAAW,MAAM,EACjB,EAAW,OAAO,EAClB,KAAK,YAAY,IAAI,CAAU,EAC/B,EAAW,GAAG,YAAe,KAAK,YAAY,OAAO,CAAU,CAAC,CAClE,CAAC,EAQD,OAPA,MAAM,EAAO,EAAQ,CAAM,EAC3B,EAAA,QAAG,UAAU,EAAQ,GAAW,EAEhC,EAAO,MAAM,EACb,KAAK,OAAS,EACd,KAAK,OAAS,EACd,QAAQ,IAAIC,EAAAA,cAAgB,EACrB,CACT,OAAS,EAAO,CAGd,QAAQ,YAAY,2CAA2C,OAAO,CAAK,GAAG,EAC9E,MACF,CACF,CAEA,MAA2B,CACzB,OAAO,KAAK,MACd,CAEA,SAAgB,CAGd,IAAK,IAAM,KAAc,KAAK,YAAa,EAAW,QAAQ,EAE9D,GADA,KAAK,YAAY,MAAM,EACnB,KAAK,OAAQ,CACf,GAAI,CACF,KAAK,OAAO,MAAM,CACpB,OAAS,EAAO,CACd,QAAQ,YAAY,6CAA6C,OAAO,CAAK,GAAG,CAClF,CACA,KAAK,OAAS,IAAA,EAChB,CACA,GAAI,KAAK,OAAQ,CACf,GAAI,CACF,EAAA,QAAG,OAAO,KAAK,OAAQ,CAAE,MAAO,EAAK,CAAC,CACxC,OAAS,EAAO,CACd,QAAQ,YAAY,8CAA8C,OAAO,CAAK,GAAG,CACnF,CACA,KAAK,OAAS,IAAA,EAChB,CACI,QAAQ,IAAA,sBAAmB,OAAO,QAAQ,IAAIA,EAAAA,aACpD,CAGA,WAAmB,EAA2B,CAC5C,IAAM,EAAYC,EAAAA,QAAK,KAAK,KAAK,MAAM,eAAe,CAAS,EAAG,eAAW,EAC7E,GAAI,OAAO,WAAW,CAAS,GAAK,IAAmB,OAAO,EAC9D,IAAM,GAAA,EAAOC,EAAAA,WAAAA,CAAW,QAAQ,CAAC,CAAC,OAAO,CAAS,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,EAAkB,EAC7F,OAAOD,EAAAA,QAAK,KAAKE,EAAAA,QAAG,OAAO,EAAG,eAAe,EAAK,MAAM,CAC1D,CACF,gBA1ECC,EAAAA,EAAAA,WAAAA,CAAW,EAOGC,EAAAA,QAAAA,GAAAA,EAAAA,EAAAA,OAAAA,CAAOC,EAAAA,MAAM,WAAW,CAAA,8CAsEvC,SAAS,EAAO,EAAoB,EAA+B,CACjE,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,EAAO,KAAK,QAAS,CAAM,EAC3B,EAAO,OAAO,MAAc,CAC1B,EAAO,eAAe,QAAS,CAAM,EAErC,EAAO,GAAG,QAAU,GAAiB,QAAQ,YAAY,gCAAgC,EAAM,SAAS,CAAC,EACzG,EAAQ,CACV,CAAC,CACH,CAAC,CACH"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IRunnerPaths } from "../RunnerPaths/types.cjs";
|
|
2
|
+
import "../RunnerPaths/index.cjs";
|
|
3
|
+
import { ILifeline } from "./types.cjs";
|
|
4
|
+
import "reflect-metadata/lite";
|
|
5
|
+
//#region src/services/Lifeline/NodeLifeline.d.ts
|
|
6
|
+
declare class NodeLifeline implements ILifeline {
|
|
7
|
+
private readonly paths;
|
|
8
|
+
private server;
|
|
9
|
+
private target;
|
|
10
|
+
/** Closing a server stops it accepting; only the connections carry the death signal. */
|
|
11
|
+
private readonly connections;
|
|
12
|
+
constructor(paths: IRunnerPaths);
|
|
13
|
+
arm(sessionId: string): Promise<string | undefined>;
|
|
14
|
+
path(): string | undefined;
|
|
15
|
+
dispose(): void;
|
|
16
|
+
/** Keeps the socket beside the session it belongs to unless that path is too long to bind. */
|
|
17
|
+
private socketPath;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { NodeLifeline };
|
|
21
|
+
//# sourceMappingURL=NodeLifeline.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeLifeline.d.cts","names":[],"sources":["../../../src/services/Lifeline/NodeLifeline.ts"],"mappings":";;;;;cAmBa,wBAAwB;mBAMqB;UALhD;UACA;;mBAES;EAEuC,YAAA,OAAO;EAEzD,IAAI,oBAAoB;EA8B9B;EAIA;;UAyBQ"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IRunnerPaths } from "../RunnerPaths/types.mjs";
|
|
2
|
+
import "../RunnerPaths/index.mjs";
|
|
3
|
+
import { ILifeline } from "./types.mjs";
|
|
4
|
+
import "reflect-metadata/lite";
|
|
5
|
+
//#region src/services/Lifeline/NodeLifeline.d.ts
|
|
6
|
+
declare class NodeLifeline implements ILifeline {
|
|
7
|
+
private readonly paths;
|
|
8
|
+
private server;
|
|
9
|
+
private target;
|
|
10
|
+
/** Closing a server stops it accepting; only the connections carry the death signal. */
|
|
11
|
+
private readonly connections;
|
|
12
|
+
constructor(paths: IRunnerPaths);
|
|
13
|
+
arm(sessionId: string): Promise<string | undefined>;
|
|
14
|
+
path(): string | undefined;
|
|
15
|
+
dispose(): void;
|
|
16
|
+
/** Keeps the socket beside the session it belongs to unless that path is too long to bind. */
|
|
17
|
+
private socketPath;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { NodeLifeline };
|
|
21
|
+
//# sourceMappingURL=NodeLifeline.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeLifeline.d.mts","names":[],"sources":["../../../src/services/Lifeline/NodeLifeline.ts"],"mappings":";;;;;cAmBa,wBAAwB;mBAMqB;UALhD;UACA;;mBAES;EAEuC,YAAA,OAAO;EAEzD,IAAI,oBAAoB;EA8B9B;EAIA;;UAyBQ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{TYPES as e}from"../../types.mjs";import t from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.mjs";import n from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.mjs";import r from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{LIFELINE_ENV as i}from"./client.mjs";import{inject as a,injectable as o}from"inversify";import"reflect-metadata/lite";import{createHash as s}from"node:crypto";import c from"node:fs";import l from"node:path";import u from"node:net";import d from"node:os";let f=class{paths;server;target;connections=new Set;constructor(e){this.paths=e}async arm(e){if(this.target)return this.target;try{this.paths.ensureDirectories(e);let t=this.socketPath(e);c.rmSync(t,{force:!0});let n=u.createServer(e=>{e.unref(),e.resume(),this.connections.add(e),e.on(`close`,()=>this.connections.delete(e))});return await p(n,t),c.chmodSync(t,384),n.unref(),this.server=n,this.target=t,process.env[i]=t,t}catch(e){process.emitWarning(`Could not arm the doom-runner lifeline: ${String(e)}`);return}}path(){return this.target}dispose(){for(let e of this.connections)e.destroy();if(this.connections.clear(),this.server){try{this.server.close()}catch(e){process.emitWarning(`Could not close the doom-runner lifeline: ${String(e)}`)}this.server=void 0}if(this.target){try{c.rmSync(this.target,{force:!0})}catch(e){process.emitWarning(`Could not remove the doom-runner lifeline: ${String(e)}`)}this.target=void 0}process.env.DOOM_RUNNER_LIFELINE&&delete process.env[i]}socketPath(e){let t=l.join(this.paths.stateDirectory(e),`lifeline.sock`);if(Buffer.byteLength(t)<=100)return t;let n=s(`sha256`).update(t).digest(`hex`).slice(0,12);return l.join(d.tmpdir(),`doom-runner-${n}.sock`)}};f=r([o(),n(0,a(e.RunnerPaths)),t(`design:paramtypes`,[Object])],f);function p(e,t){return new Promise((n,r)=>{e.once(`error`,r),e.listen(t,()=>{e.removeListener(`error`,r),e.on(`error`,e=>process.emitWarning(`doom-runner lifeline failed: ${e.message}`)),n()})})}export{f as NodeLifeline};
|
|
2
|
+
//# sourceMappingURL=NodeLifeline.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeLifeline.mjs","names":[],"sources":["../../../src/services/Lifeline/NodeLifeline.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport net from 'node:net';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { inject, injectable } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { TYPES } from '../../types.ts';\nimport type { IRunnerPaths } from '../RunnerPaths/index.ts';\nimport { LIFELINE_ENV } from './client.ts';\nimport type { ILifeline } from './types.ts';\n\nconst SOCKET_NAME = 'lifeline.sock';\n/** Unix socket paths are capped at 104 bytes, so a long agent directory falls back to the temp dir. */\nconst SOCKET_PATH_LIMIT = 100;\nconst SOCKET_HASH_LENGTH = 12;\nconst SOCKET_MODE = 0o600;\n\n@injectable()\nexport class NodeLifeline implements ILifeline {\n private server: net.Server | undefined;\n private target: string | undefined;\n /** Closing a server stops it accepting; only the connections carry the death signal. */\n private readonly connections = new Set<net.Socket>();\n\n constructor(@inject(TYPES.RunnerPaths) private readonly paths: IRunnerPaths) {}\n\n async arm(sessionId: string): Promise<string | undefined> {\n if (this.target) return this.target;\n try {\n this.paths.ensureDirectories(sessionId);\n const target = this.socketPath(sessionId);\n // A socket left behind by a SIGKILLed predecessor refuses connections, never accepts them.\n fs.rmSync(target, { force: true });\n const server = net.createServer((connection) => {\n // Runners need only the close edge, so their liveness and their data are equally irrelevant.\n connection.unref();\n connection.resume();\n this.connections.add(connection);\n connection.on('close', () => this.connections.delete(connection));\n });\n await listen(server, target);\n fs.chmodSync(target, SOCKET_MODE);\n // The lifeline must never be the reason pi stays alive.\n server.unref();\n this.server = server;\n this.target = target;\n process.env[LIFELINE_ENV] = target;\n return target;\n } catch (error) {\n // Runners stay unwatched rather than unlaunchable, so a session without a\n // lifeline degrades to running them unsupervised instead of failing.\n process.emitWarning(`Could not arm the doom-runner lifeline: ${String(error)}`);\n return undefined;\n }\n }\n\n path(): string | undefined {\n return this.target;\n }\n\n dispose(): void {\n // Dropping the connections is what a runner sees, and it is the whole point\n // of disposing: closing the server alone would leave every runner waiting.\n for (const connection of this.connections) connection.destroy();\n this.connections.clear();\n if (this.server) {\n try {\n this.server.close();\n } catch (error) {\n process.emitWarning(`Could not close the doom-runner lifeline: ${String(error)}`);\n }\n this.server = undefined;\n }\n if (this.target) {\n try {\n fs.rmSync(this.target, { force: true });\n } catch (error) {\n process.emitWarning(`Could not remove the doom-runner lifeline: ${String(error)}`);\n }\n this.target = undefined;\n }\n if (process.env[LIFELINE_ENV]) delete process.env[LIFELINE_ENV];\n }\n\n /** Keeps the socket beside the session it belongs to unless that path is too long to bind. */\n private socketPath(sessionId: string): string {\n const preferred = path.join(this.paths.stateDirectory(sessionId), SOCKET_NAME);\n if (Buffer.byteLength(preferred) <= SOCKET_PATH_LIMIT) return preferred;\n const hash = createHash('sha256').update(preferred).digest('hex').slice(0, SOCKET_HASH_LENGTH);\n return path.join(os.tmpdir(), `doom-runner-${hash}.sock`);\n }\n}\n\n/** Binding must complete before the first runner launches, so arming waits for it. */\nfunction listen(server: net.Server, target: string): Promise<void> {\n return new Promise((resolve, reject) => {\n server.once('error', reject);\n server.listen(target, () => {\n server.removeListener('error', reject);\n // Later errors would otherwise reach the process as unhandled.\n server.on('error', (error: Error) => process.emitWarning(`doom-runner lifeline failed: ${error.message}`));\n resolve();\n });\n });\n}\n"],"mappings":"yjBAmBO,IAAM,EAAN,KAAwC,CAMW,MALxD,OACA,OAEA,YAA+B,IAAI,IAEnC,YAAY,EAAiE,CAArB,KAAA,MAAA,CAAsB,CAE9E,MAAM,IAAI,EAAgD,CACxD,GAAI,KAAK,OAAQ,OAAO,KAAK,OAC7B,GAAI,CACF,KAAK,MAAM,kBAAkB,CAAS,EACtC,IAAM,EAAS,KAAK,WAAW,CAAS,EAExC,EAAG,OAAO,EAAQ,CAAE,MAAO,EAAK,CAAC,EACjC,IAAM,EAAS,EAAI,aAAc,GAAe,CAE9C,EAAW,MAAM,EACjB,EAAW,OAAO,EAClB,KAAK,YAAY,IAAI,CAAU,EAC/B,EAAW,GAAG,YAAe,KAAK,YAAY,OAAO,CAAU,CAAC,CAClE,CAAC,EAQD,OAPA,MAAM,EAAO,EAAQ,CAAM,EAC3B,EAAG,UAAU,EAAQ,GAAW,EAEhC,EAAO,MAAM,EACb,KAAK,OAAS,EACd,KAAK,OAAS,EACd,QAAQ,IAAI,GAAgB,EACrB,CACT,OAAS,EAAO,CAGd,QAAQ,YAAY,2CAA2C,OAAO,CAAK,GAAG,EAC9E,MACF,CACF,CAEA,MAA2B,CACzB,OAAO,KAAK,MACd,CAEA,SAAgB,CAGd,IAAK,IAAM,KAAc,KAAK,YAAa,EAAW,QAAQ,EAE9D,GADA,KAAK,YAAY,MAAM,EACnB,KAAK,OAAQ,CACf,GAAI,CACF,KAAK,OAAO,MAAM,CACpB,OAAS,EAAO,CACd,QAAQ,YAAY,6CAA6C,OAAO,CAAK,GAAG,CAClF,CACA,KAAK,OAAS,IAAA,EAChB,CACA,GAAI,KAAK,OAAQ,CACf,GAAI,CACF,EAAG,OAAO,KAAK,OAAQ,CAAE,MAAO,EAAK,CAAC,CACxC,OAAS,EAAO,CACd,QAAQ,YAAY,8CAA8C,OAAO,CAAK,GAAG,CACnF,CACA,KAAK,OAAS,IAAA,EAChB,CACI,QAAQ,IAAA,sBAAmB,OAAO,QAAQ,IAAI,EACpD,CAGA,WAAmB,EAA2B,CAC5C,IAAM,EAAY,EAAK,KAAK,KAAK,MAAM,eAAe,CAAS,EAAG,eAAW,EAC7E,GAAI,OAAO,WAAW,CAAS,GAAK,IAAmB,OAAO,EAC9D,IAAM,EAAO,EAAW,QAAQ,CAAC,CAAC,OAAO,CAAS,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,EAAkB,EAC7F,OAAO,EAAK,KAAK,EAAG,OAAO,EAAG,eAAe,EAAK,MAAM,CAC1D,CACF,OA1EC,EAAW,EAOG,EAAA,EAAA,EAAO,EAAM,WAAW,CAAA,sCAsEvC,SAAS,EAAO,EAAoB,EAA+B,CACjE,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,EAAO,KAAK,QAAS,CAAM,EAC3B,EAAO,OAAO,MAAc,CAC1B,EAAO,eAAe,QAAS,CAAM,EAErC,EAAO,GAAG,QAAU,GAAiB,QAAQ,YAAY,gCAAgC,EAAM,SAAS,CAAC,EACzG,EAAQ,CACV,CAAC,CACH,CAAC,CACH"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../_virtual/_rolldown/runtime.cjs");let t=require("node:net");t=e.__toESM(t,1);const n=`DOOM_RUNNER_LIFELINE`;function r(e,r=process.env[n]){if(!r)return()=>void 0;let i=!1,a=()=>{i||(i=!0,e())},o;try{o=t.default.connect(r)}catch(e){return process.emitWarning(`Could not watch the doom-runner lifeline: ${String(e)}`),()=>void 0}return o.unref(),o.on(`connect`,()=>o.resume()),o.on(`error`,a),o.on(`close`,a),()=>{i=!0,o.destroy()}}exports.LIFELINE_ENV=n,exports.watchOwner=r;
|
|
2
|
+
//# sourceMappingURL=client.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.cjs","names":["net"],"sources":["../../../src/services/Lifeline/client.ts"],"sourcesContent":["import net from 'node:net';\n\n/** Environment variable carrying the lifeline socket path to every runner supervisor. */\nexport const LIFELINE_ENV = 'DOOM_RUNNER_LIFELINE';\n\n/**\n * Reports the owning pi process dying to a runner's supervisor.\n *\n * A connected Unix socket drops the moment the owner's descriptors close, which\n * happens on every exit path including SIGKILL, so it is the one death signal a\n * graceful shutdown handler cannot provide. Connecting never blocks, the close\n * edge arrives through the event loop rather than a poll, and an unref'd socket\n * can never keep the supervisor alive: the watcher is therefore incapable of\n * outliving the process that installed it.\n *\n * A refused or missing socket means the owner died before this runner started,\n * which is reported the same way as a later death rather than left to hang.\n *\n * Runners run unwatched when no lifeline is armed, so a missing environment\n * variable can never be mistaken for a dead owner.\n */\nexport function watchOwner(\n onOwnerLost: () => void,\n target: string | undefined = process.env[LIFELINE_ENV],\n): () => void {\n if (!target) return () => undefined;\n\n let settled = false;\n const settle = (): void => {\n if (settled) return;\n settled = true;\n onOwnerLost();\n };\n\n let connection: net.Socket;\n try {\n connection = net.connect(target);\n } catch (error) {\n process.emitWarning(`Could not watch the doom-runner lifeline: ${String(error)}`);\n return () => undefined;\n }\n\n // The supervisor's own exit must never wait on this socket.\n connection.unref();\n // The owner never sends anything, so drain rather than accumulate.\n connection.on('connect', () => connection.resume());\n connection.on('error', settle);\n connection.on('close', settle);\n\n return () => {\n settled = true;\n connection.destroy();\n };\n}\n"],"mappings":"sKAGA,MAAa,EAAe,uBAkB5B,SAAgB,EACd,EACA,EAA6B,QAAQ,IAAI,GAC7B,CACZ,GAAI,CAAC,EAAQ,UAAa,IAAA,GAE1B,IAAI,EAAU,GACR,MAAqB,CACrB,IACJ,EAAU,GACV,EAAY,EACd,EAEI,EACJ,GAAI,CACF,EAAaA,EAAAA,QAAI,QAAQ,CAAM,CACjC,OAAS,EAAO,CAEd,OADA,QAAQ,YAAY,6CAA6C,OAAO,CAAK,GAAG,MACnE,IAAA,EACf,CASA,OANA,EAAW,MAAM,EAEjB,EAAW,GAAG,cAAiB,EAAW,OAAO,CAAC,EAClD,EAAW,GAAG,QAAS,CAAM,EAC7B,EAAW,GAAG,QAAS,CAAM,MAEhB,CACX,EAAU,GACV,EAAW,QAAQ,CACrB,CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/services/Lifeline/client.d.ts
|
|
2
|
+
/** Environment variable carrying the lifeline socket path to every runner supervisor. */
|
|
3
|
+
declare const LIFELINE_ENV = "DOOM_RUNNER_LIFELINE";
|
|
4
|
+
/**
|
|
5
|
+
* Reports the owning pi process dying to a runner's supervisor.
|
|
6
|
+
*
|
|
7
|
+
* A connected Unix socket drops the moment the owner's descriptors close, which
|
|
8
|
+
* happens on every exit path including SIGKILL, so it is the one death signal a
|
|
9
|
+
* graceful shutdown handler cannot provide. Connecting never blocks, the close
|
|
10
|
+
* edge arrives through the event loop rather than a poll, and an unref'd socket
|
|
11
|
+
* can never keep the supervisor alive: the watcher is therefore incapable of
|
|
12
|
+
* outliving the process that installed it.
|
|
13
|
+
*
|
|
14
|
+
* A refused or missing socket means the owner died before this runner started,
|
|
15
|
+
* which is reported the same way as a later death rather than left to hang.
|
|
16
|
+
*
|
|
17
|
+
* Runners run unwatched when no lifeline is armed, so a missing environment
|
|
18
|
+
* variable can never be mistaken for a dead owner.
|
|
19
|
+
*/
|
|
20
|
+
declare function watchOwner(onOwnerLost: () => void, target?: string | undefined): () => void;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { LIFELINE_ENV, watchOwner };
|
|
23
|
+
//# sourceMappingURL=client.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.cts","names":[],"sources":["../../../src/services/Lifeline/client.ts"],"mappings":";;cAGa;;;;;;;;;;;;;;;;;iBAkBG,WACd,yBACA"}
|