@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,37 @@
|
|
|
1
|
+
import { IRunnerPaths } from "./services/RunnerPaths/types.mjs";
|
|
2
|
+
import "./services/RunnerPaths/index.mjs";
|
|
3
|
+
import { IProcessControl } from "./services/ProcessControl/types.mjs";
|
|
4
|
+
import "./services/ProcessControl/index.mjs";
|
|
5
|
+
import { ILauncher } from "./services/Launcher/types.mjs";
|
|
6
|
+
import "./services/Launcher/index.mjs";
|
|
7
|
+
import { IRmuxBackend } from "./services/RmuxBackend/types.mjs";
|
|
8
|
+
import "./services/RmuxBackend/index.mjs";
|
|
9
|
+
import { IRunnerRegistry, RunnerRecord } from "./services/RunnerRegistry/types.mjs";
|
|
10
|
+
import "./services/RunnerRegistry/index.mjs";
|
|
11
|
+
//#region src/reconcile.d.ts
|
|
12
|
+
interface ReconcileDependencies {
|
|
13
|
+
registry: IRunnerRegistry;
|
|
14
|
+
launcher: ILauncher;
|
|
15
|
+
rmuxBackend: IRmuxBackend;
|
|
16
|
+
processControl: IProcessControl;
|
|
17
|
+
currentHostPid: number;
|
|
18
|
+
startup: boolean;
|
|
19
|
+
active?: readonly RunnerRecord[];
|
|
20
|
+
}
|
|
21
|
+
interface RunnerReconcileResult {
|
|
22
|
+
reclaimed: string[];
|
|
23
|
+
errors: string[];
|
|
24
|
+
}
|
|
25
|
+
declare function stopRunnerProcess(record: RunnerRecord, launcher: ILauncher, rmuxBackend: IRmuxBackend): Promise<boolean>;
|
|
26
|
+
/** Repairs active registry entries that lost their original completion observer. */
|
|
27
|
+
declare function reconcileActiveRunners(dependencies: ReconcileDependencies): Promise<RunnerReconcileResult>;
|
|
28
|
+
interface LegacyCleanupDependencies extends Omit<ReconcileDependencies, 'startup'> {
|
|
29
|
+
paths: IRunnerPaths;
|
|
30
|
+
}
|
|
31
|
+
/** Deletes the legacy Git store only after no live foreign runner uses it. */
|
|
32
|
+
declare function cleanupLegacyRunnerStore(dependencies: LegacyCleanupDependencies): Promise<RunnerReconcileResult & {
|
|
33
|
+
removed?: string;
|
|
34
|
+
}>;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { RunnerReconcileResult, cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess };
|
|
37
|
+
//# sourceMappingURL=reconcile.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.mts","names":[],"sources":["../src/reconcile.ts"],"mappings":";;;;;;;;;;;UAUU;EACR,UAAU;EACV,UAAU;EACV,aAAa;EACb,gBAAgB;EAChB;EACA;EACA,kBAAkB;;UAGH;EACf;EACA;;iBAGoB,kBACpB,QAAQ,cACR,UAAU,WACV,aAAa,eACZ;;iBASmB,uBAAuB,cAAc,wBAAwB,QAAQ;UAsEjF,kCAAkC,KAAK;EAC/C,OAAO;;;iBAIa,yBACpB,cAAc,4BACb,QAAQ;EAA0B"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"node:path";const t=`completed`,n=`rmux`;async function r(e,t,r){return e.backend===n&&e.backendTarget&&await r.stop(e.backendTarget,e.pid)?!0:t.stop(e.pid)}async function i(e){let i={reclaimed:[],errors:[]},a=e.active??await e.registry.list();for(let o of a)try{if((await e.registry.get(o.id,o.sessionId))?.state===t){await e.registry.release(o.id),i.reclaimed.push(o.id);continue}let a=o.backend===n?e.rmuxBackend.readOutcome(o.id,o.sessionId):void 0;if(a){await e.registry.complete(o.id,{reason:a.signal?`signaled`:a.code===0?t:`failed`,code:a.code,signal:a.signal},o.sessionId),i.reclaimed.push(o.id);continue}if(!e.processControl.isAlive(o.pid)){await e.registry.complete(o.id,{reason:`backend_lost`,code:null,signal:null},o.sessionId),i.reclaimed.push(o.id);continue}let s=e.startup&&o.hostPid===e.currentHostPid,c=!e.processControl.isAlive(o.hostPid);if(!s&&!c)continue;if(!await r(o,e.launcher,e.rmuxBackend)&&e.processControl.isAlive(o.pid)){i.errors.push(`Could not stop orphaned runner ${o.id}`);continue}await e.registry.complete(o.id,{reason:`stopped`,code:null,signal:`SIGTERM`,stopReason:`owner session ended`},o.sessionId),i.reclaimed.push(o.id)}catch(e){i.errors.push(`Could not reconcile runner ${o.id}: ${String(e)}`)}return i}function a(t,n){let r=e.relative(e.resolve(t),e.resolve(n));return r===``||!r.startsWith(`..`)&&!e.isAbsolute(r)}async function o(e){let t={reclaimed:[],errors:[]},n=e.paths.legacyDirectory();if(!n)return t;let i=(await e.registry.list()).filter(e=>a(n,e.logPath));for(let n of i){let i=e.processControl.isAlive(n.pid),a=e.processControl.isAlive(n.hostPid),o=n.hostPid===e.currentHostPid;if(!(i&&a&&!o))try{if(i&&!await r(n,e.launcher,e.rmuxBackend)&&e.processControl.isAlive(n.pid)){t.errors.push(`Could not stop legacy runner ${n.id}`);continue}await e.registry.release(n.id),t.reclaimed.push(n.id)}catch(e){t.errors.push(`Could not reclaim legacy runner ${n.id}: ${String(e)}`)}}let o;try{o=(await e.registry.listAcrossRepositories()).filter(t=>a(n,t.logPath)&&e.processControl.isAlive(t.pid))}catch(e){return t.errors.push(`Could not verify legacy runner dependencies: ${String(e)}`),t}return o.length===0&&(t.removed=e.paths.removeLegacyStore()),t}export{o as cleanupLegacyRunnerStore,i as reconcileActiveRunners,r as stopRunnerProcess};
|
|
2
|
+
//# sourceMappingURL=reconcile.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.mjs","names":[],"sources":["../src/reconcile.ts"],"sourcesContent":["import path from 'node:path';\nimport type { ILauncher } from './services/Launcher/index.ts';\nimport type { IProcessControl } from './services/ProcessControl/index.ts';\nimport type { IRunnerPaths } from './services/RunnerPaths/index.ts';\nimport type { IRmuxBackend } from './services/RmuxBackend/index.ts';\nimport type { IRunnerRegistry, RunnerRecord } from './services/RunnerRegistry/index.ts';\n\nconst COMPLETED_STATE = 'completed';\nconst RMUX_BACKEND = 'rmux';\n\ninterface ReconcileDependencies {\n registry: IRunnerRegistry;\n launcher: ILauncher;\n rmuxBackend: IRmuxBackend;\n processControl: IProcessControl;\n currentHostPid: number;\n startup: boolean;\n active?: readonly RunnerRecord[];\n}\n\nexport interface RunnerReconcileResult {\n reclaimed: string[];\n errors: string[];\n}\n\nexport async function stopRunnerProcess(\n record: RunnerRecord,\n launcher: ILauncher,\n rmuxBackend: IRmuxBackend,\n): Promise<boolean> {\n if (record.backend === RMUX_BACKEND && record.backendTarget) {\n const stopped = await rmuxBackend.stop(record.backendTarget, record.pid);\n if (stopped) return true;\n }\n return launcher.stop(record.pid);\n}\n\n/** Repairs active registry entries that lost their original completion observer. */\nexport async function reconcileActiveRunners(dependencies: ReconcileDependencies): Promise<RunnerReconcileResult> {\n const result: RunnerReconcileResult = { reclaimed: [], errors: [] };\n const active = dependencies.active ?? (await dependencies.registry.list());\n for (const record of active) {\n try {\n const persisted = await dependencies.registry.get(record.id, record.sessionId);\n if (persisted?.state === COMPLETED_STATE) {\n await dependencies.registry.release(record.id);\n result.reclaimed.push(record.id);\n continue;\n }\n\n const rmuxOutcome =\n record.backend === RMUX_BACKEND ? dependencies.rmuxBackend.readOutcome(record.id, record.sessionId) : undefined;\n if (rmuxOutcome) {\n await dependencies.registry.complete(\n record.id,\n {\n reason: rmuxOutcome.signal ? 'signaled' : rmuxOutcome.code === 0 ? COMPLETED_STATE : 'failed',\n code: rmuxOutcome.code,\n signal: rmuxOutcome.signal,\n },\n record.sessionId,\n );\n result.reclaimed.push(record.id);\n continue;\n }\n\n if (!dependencies.processControl.isAlive(record.pid)) {\n await dependencies.registry.complete(\n record.id,\n { reason: 'backend_lost', code: null, signal: null },\n record.sessionId,\n );\n result.reclaimed.push(record.id);\n continue;\n }\n\n const previousRuntime = dependencies.startup && record.hostPid === dependencies.currentHostPid;\n const ownerLost = !dependencies.processControl.isAlive(record.hostPid);\n if (!previousRuntime && !ownerLost) continue;\n\n const stopped = await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend);\n if (!stopped && dependencies.processControl.isAlive(record.pid)) {\n result.errors.push(`Could not stop orphaned runner ${record.id}`);\n continue;\n }\n await dependencies.registry.complete(\n record.id,\n {\n reason: 'stopped',\n code: null,\n signal: 'SIGTERM',\n stopReason: 'owner session ended',\n },\n record.sessionId,\n );\n result.reclaimed.push(record.id);\n } catch (error) {\n result.errors.push(`Could not reconcile runner ${record.id}: ${String(error)}`);\n }\n }\n return result;\n}\n\nfunction isWithin(root: string, candidate: string): boolean {\n const relative = path.relative(path.resolve(root), path.resolve(candidate));\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\ninterface LegacyCleanupDependencies extends Omit<ReconcileDependencies, 'startup'> {\n paths: IRunnerPaths;\n}\n\n/** Deletes the legacy Git store only after no live foreign runner uses it. */\nexport async function cleanupLegacyRunnerStore(\n dependencies: LegacyCleanupDependencies,\n): Promise<RunnerReconcileResult & { removed?: string }> {\n const result: RunnerReconcileResult & { removed?: string } = { reclaimed: [], errors: [] };\n const legacyDirectory = dependencies.paths.legacyDirectory();\n if (!legacyDirectory) return result;\n\n const legacyRecords = (await dependencies.registry.list()).filter((record) =>\n isWithin(legacyDirectory, record.logPath),\n );\n for (const record of legacyRecords) {\n const childAlive = dependencies.processControl.isAlive(record.pid);\n const ownerAlive = dependencies.processControl.isAlive(record.hostPid);\n const ownedByPreviousRuntime = record.hostPid === dependencies.currentHostPid;\n if (childAlive && ownerAlive && !ownedByPreviousRuntime) continue;\n try {\n if (childAlive) {\n const stopped = await stopRunnerProcess(record, dependencies.launcher, dependencies.rmuxBackend);\n if (!stopped && dependencies.processControl.isAlive(record.pid)) {\n result.errors.push(`Could not stop legacy runner ${record.id}`);\n continue;\n }\n }\n await dependencies.registry.release(record.id);\n result.reclaimed.push(record.id);\n } catch (error) {\n result.errors.push(`Could not reclaim legacy runner ${record.id}: ${String(error)}`);\n }\n }\n\n let liveDependencies: RunnerRecord[];\n try {\n liveDependencies = (await dependencies.registry.listAcrossRepositories()).filter(\n (record) => isWithin(legacyDirectory, record.logPath) && dependencies.processControl.isAlive(record.pid),\n );\n } catch (error) {\n result.errors.push(`Could not verify legacy runner dependencies: ${String(error)}`);\n return result;\n }\n if (liveDependencies.length === 0) result.removed = dependencies.paths.removeLegacyStore();\n return result;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./_virtual/_rolldown/runtime.cjs");let t=require("node:fs");t=e.__toESM(t,1);let n=require("node:path");n=e.__toESM(n,1);let r=require("node:url");const i={GIT_PAGER:`cat`,PAGER:`cat`,GIT_TERMINAL_PROMPT:`0`},a=`ENOENT`;function o(e,t){return{spec:n.default.join(e,`${t}.command.json`),gate:n.default.join(e,`${t}.gate`),exit:n.default.join(e,`${t}.exit.json`),logDone:n.default.join(e,`${t}.log.done`)}}function s(e,n){t.default.writeFileSync(e,`${JSON.stringify(n)}\n`,{mode:384})}function c(e){try{let n=JSON.parse(t.default.readFileSync(e,`utf8`));if(typeof n!=`object`||!n)return;let r=n;return{code:typeof r.code==`number`?r.code:null,signal:typeof r.signal==`string`?r.signal:null}}catch(t){t.code!==a&&process.emitWarning(`Could not read runner exit metadata ${e}: ${String(t)}`);return}}function l(e){for(let n of Object.values(e))try{t.default.unlinkSync(n)}catch(e){e.code!==a&&process.emitWarning(String(e))}}function u(e){let t=require("url").pathToFileURL(__filename).href.endsWith(`.ts`)?`ts`:`mjs`;return(0,r.fileURLToPath)(new URL(`./bin/${e}.${t}`,require("url").pathToFileURL(__filename).href))}function d(e){return`exec ${f([process.execPath,u(`runnerHost`),e.spec,e.gate,e.exit])}`}function f(e){return e.map(e=>`'${e.replaceAll(`'`,`'"'"'`)}'`).join(` `)}exports.NO_TERMINAL_INPUT_ENV=i,exports.cleanupSupervisorFiles=l,exports.readExitMetadata=c,exports.runtimeEntry=u,exports.shellJoin=f,exports.supervisorCommand=d,exports.supervisorPaths=o,exports.writeCommandSpec=s;
|
|
2
|
+
//# sourceMappingURL=runnerSpec.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runnerSpec.cjs","names":["path","fs","fileURLToPath"],"sources":["../src/runnerSpec.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/** What a supervisor needs to run one command. */\nexport interface CommandSpec {\n command: string;\n cwd: string;\n env: Record<string, string>;\n}\n\n/** Exit status the supervisor records once its command is gone. */\nexport interface ExitMetadata {\n code: number | null;\n signal: NodeJS.Signals | null;\n}\n\n/** Sidecars a supervised run reads and writes beside its log. */\nexport interface SupervisorPaths {\n spec: string;\n gate: string;\n exit: string;\n logDone: string;\n}\n\n/**\n * Settings that make a terminal safe for a caller with no keyboard.\n *\n * Commands run inside an rmux pane, so their stdout is a real tty. Git and\n * friends take that as permission to open a pager, and `less` then waits at\n * `(END)` for a keypress nobody is there to send, so the run hangs until its\n * timeout. The same tty invites credential prompts, which hang the same way.\n * A conventional piped stdout disables both automatically; a pane has to be\n * told. A command that genuinely wants a pager can still ask for one, as in\n * `git -c core.pager=less log`.\n */\nexport const NO_TERMINAL_INPUT_ENV = {\n GIT_PAGER: 'cat',\n PAGER: 'cat',\n GIT_TERMINAL_PROMPT: '0',\n};\n\nconst SPEC_MODE = 0o600;\nconst NOT_FOUND_ERROR_CODE = 'ENOENT';\n\nexport function supervisorPaths(directory: string, id: string): SupervisorPaths {\n return {\n spec: path.join(directory, `${id}.command.json`),\n gate: path.join(directory, `${id}.gate`),\n exit: path.join(directory, `${id}.exit.json`),\n logDone: path.join(directory, `${id}.log.done`),\n };\n}\n\nexport function writeCommandSpec(target: string, spec: CommandSpec): void {\n fs.writeFileSync(target, `${JSON.stringify(spec)}\\n`, { mode: SPEC_MODE });\n}\n\nexport function readExitMetadata(target: string): ExitMetadata | undefined {\n try {\n const value: unknown = JSON.parse(fs.readFileSync(target, 'utf8'));\n if (typeof value !== 'object' || value === null) return undefined;\n const metadata = value as Partial<ExitMetadata>;\n const code = typeof metadata.code === 'number' ? metadata.code : null;\n const signal = typeof metadata.signal === 'string' ? (metadata.signal as NodeJS.Signals) : null;\n return { code, signal };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== NOT_FOUND_ERROR_CODE) {\n process.emitWarning(`Could not read runner exit metadata ${target}: ${String(error)}`);\n }\n return undefined;\n }\n}\n\nexport function cleanupSupervisorFiles(paths: SupervisorPaths): void {\n for (const target of Object.values(paths)) {\n try {\n fs.unlinkSync(target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== NOT_FOUND_ERROR_CODE) process.emitWarning(String(error));\n }\n }\n}\n\n/** Resolves a bundled entry point in whichever form the package is running from. */\nexport function runtimeEntry(name: 'runnerHost' | 'logSink'): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n return fileURLToPath(new URL(`./bin/${name}.${extension}`, import.meta.url));\n}\n\n/**\n * Replaces the shell rather than nesting under it, so the pid handed back is the\n * supervisor's and a group signal reaches it directly.\n */\nexport function supervisorCommand(paths: SupervisorPaths): string {\n return `exec ${shellJoin([process.execPath, runtimeEntry('runnerHost'), paths.spec, paths.gate, paths.exit])}`;\n}\n\nexport function shellJoin(values: readonly string[]): string {\n return values.map((value) => `'${value.replaceAll(\"'\", `'\"'\"'`)}'`).join(' ');\n}\n"],"mappings":"uOAoCA,MAAa,EAAwB,CACnC,UAAW,MACX,MAAO,MACP,oBAAqB,GACvB,EAGM,EAAuB,SAE7B,SAAgB,EAAgB,EAAmB,EAA6B,CAC9E,MAAO,CACL,KAAMA,EAAAA,QAAK,KAAK,EAAW,GAAG,EAAG,cAAc,EAC/C,KAAMA,EAAAA,QAAK,KAAK,EAAW,GAAG,EAAG,MAAM,EACvC,KAAMA,EAAAA,QAAK,KAAK,EAAW,GAAG,EAAG,WAAW,EAC5C,QAASA,EAAAA,QAAK,KAAK,EAAW,GAAG,EAAG,UAAU,CAChD,CACF,CAEA,SAAgB,EAAiB,EAAgB,EAAyB,CACxE,EAAA,QAAG,cAAc,EAAQ,GAAG,KAAK,UAAU,CAAI,EAAE,IAAK,CAAE,KAAM,GAAU,CAAC,CAC3E,CAEA,SAAgB,EAAiB,EAA0C,CACzE,GAAI,CACF,IAAM,EAAiB,KAAK,MAAMC,EAAAA,QAAG,aAAa,EAAQ,MAAM,CAAC,EACjE,GAAI,OAAO,GAAU,WAAY,EAAgB,OACjD,IAAM,EAAW,EAGjB,MAAO,CAAE,KAFI,OAAO,EAAS,MAAS,SAAW,EAAS,KAAO,KAElD,OADA,OAAO,EAAS,QAAW,SAAY,EAAS,OAA4B,IACrE,CACxB,OAAS,EAAO,CACT,EAAgC,OAAS,GAC5C,QAAQ,YAAY,uCAAuC,EAAO,IAAI,OAAO,CAAK,GAAG,EAEvF,MACF,CACF,CAEA,SAAgB,EAAuB,EAA8B,CACnE,IAAK,IAAM,KAAU,OAAO,OAAO,CAAK,EACtC,GAAI,CACF,EAAA,QAAG,WAAW,CAAM,CACtB,OAAS,EAAO,CACT,EAAgC,OAAS,GAAsB,QAAQ,YAAY,OAAO,CAAK,CAAC,CACvG,CAEJ,CAGA,SAAgB,EAAa,EAAwC,CACnE,IAAM,EAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,KAA4B,SAAS,KAAK,EAAI,KAAO,MAC3D,OAAA,EAAOC,EAAAA,cAAAA,CAAc,IAAI,IAAI,SAAS,EAAK,GAAG,IAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,IAA4B,CAAC,CAC7E,CAMA,SAAgB,EAAkB,EAAgC,CAChE,MAAO,QAAQ,EAAU,CAAC,QAAQ,SAAU,EAAa,YAAY,EAAG,EAAM,KAAM,EAAM,KAAM,EAAM,IAAI,CAAC,GAC7G,CAEA,SAAgB,EAAU,EAAmC,CAC3D,OAAO,EAAO,IAAK,GAAU,IAAI,EAAM,WAAW,IAAK,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAC9E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/runnerSpec.d.ts
|
|
2
|
+
/** What a supervisor needs to run one command. */
|
|
3
|
+
interface CommandSpec {
|
|
4
|
+
command: string;
|
|
5
|
+
cwd: string;
|
|
6
|
+
env: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
/** Exit status the supervisor records once its command is gone. */
|
|
9
|
+
interface ExitMetadata {
|
|
10
|
+
code: number | null;
|
|
11
|
+
signal: NodeJS.Signals | null;
|
|
12
|
+
}
|
|
13
|
+
/** Sidecars a supervised run reads and writes beside its log. */
|
|
14
|
+
interface SupervisorPaths {
|
|
15
|
+
spec: string;
|
|
16
|
+
gate: string;
|
|
17
|
+
exit: string;
|
|
18
|
+
logDone: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Settings that make a terminal safe for a caller with no keyboard.
|
|
22
|
+
*
|
|
23
|
+
* Commands run inside an rmux pane, so their stdout is a real tty. Git and
|
|
24
|
+
* friends take that as permission to open a pager, and `less` then waits at
|
|
25
|
+
* `(END)` for a keypress nobody is there to send, so the run hangs until its
|
|
26
|
+
* timeout. The same tty invites credential prompts, which hang the same way.
|
|
27
|
+
* A conventional piped stdout disables both automatically; a pane has to be
|
|
28
|
+
* told. A command that genuinely wants a pager can still ask for one, as in
|
|
29
|
+
* `git -c core.pager=less log`.
|
|
30
|
+
*/
|
|
31
|
+
declare const NO_TERMINAL_INPUT_ENV: {
|
|
32
|
+
GIT_PAGER: string;
|
|
33
|
+
PAGER: string;
|
|
34
|
+
GIT_TERMINAL_PROMPT: string;
|
|
35
|
+
};
|
|
36
|
+
declare function supervisorPaths(directory: string, id: string): SupervisorPaths;
|
|
37
|
+
declare function writeCommandSpec(target: string, spec: CommandSpec): void;
|
|
38
|
+
declare function readExitMetadata(target: string): ExitMetadata | undefined;
|
|
39
|
+
declare function cleanupSupervisorFiles(paths: SupervisorPaths): void;
|
|
40
|
+
/** Resolves a bundled entry point in whichever form the package is running from. */
|
|
41
|
+
declare function runtimeEntry(name: 'runnerHost' | 'logSink'): string;
|
|
42
|
+
/**
|
|
43
|
+
* Replaces the shell rather than nesting under it, so the pid handed back is the
|
|
44
|
+
* supervisor's and a group signal reaches it directly.
|
|
45
|
+
*/
|
|
46
|
+
declare function supervisorCommand(paths: SupervisorPaths): string;
|
|
47
|
+
declare function shellJoin(values: readonly string[]): string;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { CommandSpec, ExitMetadata, NO_TERMINAL_INPUT_ENV, SupervisorPaths, cleanupSupervisorFiles, readExitMetadata, runtimeEntry, shellJoin, supervisorCommand, supervisorPaths, writeCommandSpec };
|
|
50
|
+
//# sourceMappingURL=runnerSpec.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runnerSpec.d.cts","names":[],"sources":["../src/runnerSpec.ts"],"mappings":";;UAKiB;EACf;EACA;EACA,KAAK;;;UAIU;EACf;EACA,QAAQ,OAAO;;;UAIA;EACf;EACA;EACA;EACA;;;;;;;;;;;;;cAcW;;;;;iBASG,gBAAgB,mBAAmB,aAAa;iBAShD,iBAAiB,gBAAgB,MAAM;iBAIvC,iBAAiB,iBAAiB;iBAgBlC,uBAAuB,OAAO;;iBAW9B,aAAa;;;;;iBASb,kBAAkB,OAAO;iBAIzB,UAAU"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/runnerSpec.d.ts
|
|
2
|
+
/** What a supervisor needs to run one command. */
|
|
3
|
+
interface CommandSpec {
|
|
4
|
+
command: string;
|
|
5
|
+
cwd: string;
|
|
6
|
+
env: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
/** Exit status the supervisor records once its command is gone. */
|
|
9
|
+
interface ExitMetadata {
|
|
10
|
+
code: number | null;
|
|
11
|
+
signal: NodeJS.Signals | null;
|
|
12
|
+
}
|
|
13
|
+
/** Sidecars a supervised run reads and writes beside its log. */
|
|
14
|
+
interface SupervisorPaths {
|
|
15
|
+
spec: string;
|
|
16
|
+
gate: string;
|
|
17
|
+
exit: string;
|
|
18
|
+
logDone: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Settings that make a terminal safe for a caller with no keyboard.
|
|
22
|
+
*
|
|
23
|
+
* Commands run inside an rmux pane, so their stdout is a real tty. Git and
|
|
24
|
+
* friends take that as permission to open a pager, and `less` then waits at
|
|
25
|
+
* `(END)` for a keypress nobody is there to send, so the run hangs until its
|
|
26
|
+
* timeout. The same tty invites credential prompts, which hang the same way.
|
|
27
|
+
* A conventional piped stdout disables both automatically; a pane has to be
|
|
28
|
+
* told. A command that genuinely wants a pager can still ask for one, as in
|
|
29
|
+
* `git -c core.pager=less log`.
|
|
30
|
+
*/
|
|
31
|
+
declare const NO_TERMINAL_INPUT_ENV: {
|
|
32
|
+
GIT_PAGER: string;
|
|
33
|
+
PAGER: string;
|
|
34
|
+
GIT_TERMINAL_PROMPT: string;
|
|
35
|
+
};
|
|
36
|
+
declare function supervisorPaths(directory: string, id: string): SupervisorPaths;
|
|
37
|
+
declare function writeCommandSpec(target: string, spec: CommandSpec): void;
|
|
38
|
+
declare function readExitMetadata(target: string): ExitMetadata | undefined;
|
|
39
|
+
declare function cleanupSupervisorFiles(paths: SupervisorPaths): void;
|
|
40
|
+
/** Resolves a bundled entry point in whichever form the package is running from. */
|
|
41
|
+
declare function runtimeEntry(name: 'runnerHost' | 'logSink'): string;
|
|
42
|
+
/**
|
|
43
|
+
* Replaces the shell rather than nesting under it, so the pid handed back is the
|
|
44
|
+
* supervisor's and a group signal reaches it directly.
|
|
45
|
+
*/
|
|
46
|
+
declare function supervisorCommand(paths: SupervisorPaths): string;
|
|
47
|
+
declare function shellJoin(values: readonly string[]): string;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { CommandSpec, ExitMetadata, NO_TERMINAL_INPUT_ENV, SupervisorPaths, cleanupSupervisorFiles, readExitMetadata, runtimeEntry, shellJoin, supervisorCommand, supervisorPaths, writeCommandSpec };
|
|
50
|
+
//# sourceMappingURL=runnerSpec.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runnerSpec.d.mts","names":[],"sources":["../src/runnerSpec.ts"],"mappings":";;UAKiB;EACf;EACA;EACA,KAAK;;;UAIU;EACf;EACA,QAAQ,OAAO;;;UAIA;EACf;EACA;EACA;EACA;;;;;;;;;;;;;cAcW;;;;;iBASG,gBAAgB,mBAAmB,aAAa;iBAShD,iBAAiB,gBAAgB,MAAM;iBAIvC,iBAAiB,iBAAiB;iBAgBlC,uBAAuB,OAAO;;iBAW9B,aAAa;;;;;iBASb,kBAAkB,OAAO;iBAIzB,UAAU"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"node:fs";import t from"node:path";import{fileURLToPath as n}from"node:url";const r={GIT_PAGER:`cat`,PAGER:`cat`,GIT_TERMINAL_PROMPT:`0`},i=`ENOENT`;function a(e,n){return{spec:t.join(e,`${n}.command.json`),gate:t.join(e,`${n}.gate`),exit:t.join(e,`${n}.exit.json`),logDone:t.join(e,`${n}.log.done`)}}function o(t,n){e.writeFileSync(t,`${JSON.stringify(n)}\n`,{mode:384})}function s(t){try{let n=JSON.parse(e.readFileSync(t,`utf8`));if(typeof n!=`object`||!n)return;let r=n;return{code:typeof r.code==`number`?r.code:null,signal:typeof r.signal==`string`?r.signal:null}}catch(e){e.code!==i&&process.emitWarning(`Could not read runner exit metadata ${t}: ${String(e)}`);return}}function c(t){for(let n of Object.values(t))try{e.unlinkSync(n)}catch(e){e.code!==i&&process.emitWarning(String(e))}}function l(e){let t=import.meta.url.endsWith(`.ts`)?`ts`:`mjs`;return n(new URL(`./bin/${e}.${t}`,import.meta.url))}function u(e){return`exec ${d([process.execPath,l(`runnerHost`),e.spec,e.gate,e.exit])}`}function d(e){return e.map(e=>`'${e.replaceAll(`'`,`'"'"'`)}'`).join(` `)}export{r as NO_TERMINAL_INPUT_ENV,c as cleanupSupervisorFiles,s as readExitMetadata,l as runtimeEntry,d as shellJoin,u as supervisorCommand,a as supervisorPaths,o as writeCommandSpec};
|
|
2
|
+
//# sourceMappingURL=runnerSpec.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runnerSpec.mjs","names":[],"sources":["../src/runnerSpec.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/** What a supervisor needs to run one command. */\nexport interface CommandSpec {\n command: string;\n cwd: string;\n env: Record<string, string>;\n}\n\n/** Exit status the supervisor records once its command is gone. */\nexport interface ExitMetadata {\n code: number | null;\n signal: NodeJS.Signals | null;\n}\n\n/** Sidecars a supervised run reads and writes beside its log. */\nexport interface SupervisorPaths {\n spec: string;\n gate: string;\n exit: string;\n logDone: string;\n}\n\n/**\n * Settings that make a terminal safe for a caller with no keyboard.\n *\n * Commands run inside an rmux pane, so their stdout is a real tty. Git and\n * friends take that as permission to open a pager, and `less` then waits at\n * `(END)` for a keypress nobody is there to send, so the run hangs until its\n * timeout. The same tty invites credential prompts, which hang the same way.\n * A conventional piped stdout disables both automatically; a pane has to be\n * told. A command that genuinely wants a pager can still ask for one, as in\n * `git -c core.pager=less log`.\n */\nexport const NO_TERMINAL_INPUT_ENV = {\n GIT_PAGER: 'cat',\n PAGER: 'cat',\n GIT_TERMINAL_PROMPT: '0',\n};\n\nconst SPEC_MODE = 0o600;\nconst NOT_FOUND_ERROR_CODE = 'ENOENT';\n\nexport function supervisorPaths(directory: string, id: string): SupervisorPaths {\n return {\n spec: path.join(directory, `${id}.command.json`),\n gate: path.join(directory, `${id}.gate`),\n exit: path.join(directory, `${id}.exit.json`),\n logDone: path.join(directory, `${id}.log.done`),\n };\n}\n\nexport function writeCommandSpec(target: string, spec: CommandSpec): void {\n fs.writeFileSync(target, `${JSON.stringify(spec)}\\n`, { mode: SPEC_MODE });\n}\n\nexport function readExitMetadata(target: string): ExitMetadata | undefined {\n try {\n const value: unknown = JSON.parse(fs.readFileSync(target, 'utf8'));\n if (typeof value !== 'object' || value === null) return undefined;\n const metadata = value as Partial<ExitMetadata>;\n const code = typeof metadata.code === 'number' ? metadata.code : null;\n const signal = typeof metadata.signal === 'string' ? (metadata.signal as NodeJS.Signals) : null;\n return { code, signal };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== NOT_FOUND_ERROR_CODE) {\n process.emitWarning(`Could not read runner exit metadata ${target}: ${String(error)}`);\n }\n return undefined;\n }\n}\n\nexport function cleanupSupervisorFiles(paths: SupervisorPaths): void {\n for (const target of Object.values(paths)) {\n try {\n fs.unlinkSync(target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== NOT_FOUND_ERROR_CODE) process.emitWarning(String(error));\n }\n }\n}\n\n/** Resolves a bundled entry point in whichever form the package is running from. */\nexport function runtimeEntry(name: 'runnerHost' | 'logSink'): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n return fileURLToPath(new URL(`./bin/${name}.${extension}`, import.meta.url));\n}\n\n/**\n * Replaces the shell rather than nesting under it, so the pid handed back is the\n * supervisor's and a group signal reaches it directly.\n */\nexport function supervisorCommand(paths: SupervisorPaths): string {\n return `exec ${shellJoin([process.execPath, runtimeEntry('runnerHost'), paths.spec, paths.gate, paths.exit])}`;\n}\n\nexport function shellJoin(values: readonly string[]): string {\n return values.map((value) => `'${value.replaceAll(\"'\", `'\"'\"'`)}'`).join(' ');\n}\n"],"mappings":"yFAoCA,MAAa,EAAwB,CACnC,UAAW,MACX,MAAO,MACP,oBAAqB,GACvB,EAGM,EAAuB,SAE7B,SAAgB,EAAgB,EAAmB,EAA6B,CAC9E,MAAO,CACL,KAAM,EAAK,KAAK,EAAW,GAAG,EAAG,cAAc,EAC/C,KAAM,EAAK,KAAK,EAAW,GAAG,EAAG,MAAM,EACvC,KAAM,EAAK,KAAK,EAAW,GAAG,EAAG,WAAW,EAC5C,QAAS,EAAK,KAAK,EAAW,GAAG,EAAG,UAAU,CAChD,CACF,CAEA,SAAgB,EAAiB,EAAgB,EAAyB,CACxE,EAAG,cAAc,EAAQ,GAAG,KAAK,UAAU,CAAI,EAAE,IAAK,CAAE,KAAM,GAAU,CAAC,CAC3E,CAEA,SAAgB,EAAiB,EAA0C,CACzE,GAAI,CACF,IAAM,EAAiB,KAAK,MAAM,EAAG,aAAa,EAAQ,MAAM,CAAC,EACjE,GAAI,OAAO,GAAU,WAAY,EAAgB,OACjD,IAAM,EAAW,EAGjB,MAAO,CAAE,KAFI,OAAO,EAAS,MAAS,SAAW,EAAS,KAAO,KAElD,OADA,OAAO,EAAS,QAAW,SAAY,EAAS,OAA4B,IACrE,CACxB,OAAS,EAAO,CACT,EAAgC,OAAS,GAC5C,QAAQ,YAAY,uCAAuC,EAAO,IAAI,OAAO,CAAK,GAAG,EAEvF,MACF,CACF,CAEA,SAAgB,EAAuB,EAA8B,CACnE,IAAK,IAAM,KAAU,OAAO,OAAO,CAAK,EACtC,GAAI,CACF,EAAG,WAAW,CAAM,CACtB,OAAS,EAAO,CACT,EAAgC,OAAS,GAAsB,QAAQ,YAAY,OAAO,CAAK,CAAC,CACvG,CAEJ,CAGA,SAAgB,EAAa,EAAwC,CACnE,IAAM,EAAY,YAAY,IAAI,SAAS,KAAK,EAAI,KAAO,MAC3D,OAAO,EAAc,IAAI,IAAI,SAAS,EAAK,GAAG,IAAa,YAAY,GAAG,CAAC,CAC7E,CAMA,SAAgB,EAAkB,EAAgC,CAChE,MAAO,QAAQ,EAAU,CAAC,QAAQ,SAAU,EAAa,YAAY,EAAG,EAAM,KAAM,EAAM,KAAM,EAAM,IAAI,CAAC,GAC7G,CAEA,SAAgB,EAAU,EAAmC,CAC3D,OAAO,EAAO,IAAK,GAAU,IAAI,EAAM,WAAW,IAAK,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAC9E"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=new RegExp([`\\u001B\\[[0-9;?]*[ -/]*[@-~]`,`\\u001B\\][^\\u0007\\u001B]*(?:\\u0007|\\u001B\\\\)`,`\\u001B[@-Z\\\\-_]`,`\\u001B[=><]`].join(`|`),`g`),t=RegExp(`[\\u0007\\u0008]`,`g`),n=new RegExp([`\\u001B\\[[0-9;?]*[ -/]*[@-ln-~]`,`\\u001B\\][^\\u0007\\u001B]*(?:\\u0007|\\u001B\\\\)`,`\\u001B[@-Z\\\\-_]`,`\\u001B[=><]`].join(`|`),`g`);function r(n){return n.replace(e,``).replace(t,``)}function i(e){return e.replace(n,``).replace(t,``)}function a(e){return e.replace(/\r\n/g,`
|
|
2
|
+
`).split(`
|
|
3
|
+
`).map(e=>e.includes(`\r`)?e.split(`\r`).at(-1)??``:e).join(`
|
|
4
|
+
`)}function o(e){return a(i(e))}function s(e){return a(r(e))}exports.collapseCarriageReturns=a,exports.scrubTerminalOutput=o,exports.scrubTerminalOutputToPlainText=s,exports.stripAnsi=r,exports.stripAnsiKeepingColour=i;
|
|
5
|
+
//# sourceMappingURL=ansiScrub.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansiScrub.cjs","names":[],"sources":["../../../src/services/AnsiScrub/ansiScrub.ts"],"sourcesContent":["/**\n * Turns terminal output into text worth grepping.\n *\n * PTY output is written for a screen, not a file: colours, cursor moves and\n * carriage-return redraws all end up in the byte stream. Without this a single\n * progress bar becomes thousands of near-identical log lines.\n */\n\n/**\n * CSI sequences (colours, cursor moves), OSC strings, the two-byte Fe escapes,\n * and the keypad-mode escapes shells emit around every prompt.\n */\nconst ANSI_PATTERN = new RegExp(\n [\n '\\\\u001B\\\\[[0-9;?]*[ -/]*[@-~]',\n '\\\\u001B\\\\][^\\\\u0007\\\\u001B]*(?:\\\\u0007|\\\\u001B\\\\\\\\)',\n '\\\\u001B[@-Z\\\\\\\\-_]',\n '\\\\u001B[=><]',\n ].join('|'),\n 'g',\n);\n\n/** Bell and backspace, which a terminal consumes rather than displays. */\n// oxlint-disable-next-line no-control-regex -- matching terminal control bytes is the whole job\nconst CONTROL_PATTERN = new RegExp('[\\\\u0007\\\\u0008]', 'g');\n\n/**\n * The same set minus SGR, the sequence that only sets colour and weight.\n *\n * The final byte class omits `m`, so `ESC[32m` survives while cursor moves,\n * OSC strings and keypad escapes are still removed.\n */\nconst ANSI_PATTERN_KEEPING_COLOUR = new RegExp(\n [\n '\\\\u001B\\\\[[0-9;?]*[ -/]*[@-ln-~]',\n '\\\\u001B\\\\][^\\\\u0007\\\\u001B]*(?:\\\\u0007|\\\\u001B\\\\\\\\)',\n '\\\\u001B[@-Z\\\\\\\\-_]',\n '\\\\u001B[=><]',\n ].join('|'),\n 'g',\n);\n\n/** Removes escape sequences, leaving the characters a user would have seen. */\nexport function stripAnsi(text: string): string {\n return text.replace(ANSI_PATTERN, '').replace(CONTROL_PATTERN, '');\n}\n\n/**\n * Removes everything `stripAnsi` does except colour.\n *\n * Logs are read back by a terminal renderer as well as by grep, and a command\n * that colours its own output has already said how it should look.\n */\nexport function stripAnsiKeepingColour(text: string): string {\n return text.replace(ANSI_PATTERN_KEEPING_COLOUR, '').replace(CONTROL_PATTERN, '');\n}\n\n/**\n * Collapses carriage-return redraws.\n *\n * A bare `\\r` returns the cursor to the start of the current line, so whatever\n * follows overwrites it. Only the final state of each line is kept. The `\\r` of\n * a CRLF pair is a line terminator rather than a redraw, so it is normalised\n * away first: a pseudo terminal ends every line that way, and treating it as a\n * redraw would blank the whole log.\n */\nexport function collapseCarriageReturns(text: string): string {\n return text\n .replace(/\\r\\n/g, '\\n')\n .split('\\n')\n .map((line) => (line.includes('\\r') ? (line.split('\\r').at(-1) ?? '') : line))\n .join('\\n');\n}\n\n/** Full scrub applied to PTY output before it reaches the log file. */\nexport function scrubTerminalOutput(text: string): string {\n return collapseCarriageReturns(stripAnsiKeepingColour(text));\n}\n\n/** Plain-text scrub, for the copy the model reads. */\nexport function scrubTerminalOutputToPlainText(text: string): string {\n return collapseCarriageReturns(stripAnsi(text));\n}\n"],"mappings":"mEAYA,MAAM,EAAe,IAAI,OACvB,CACE,gCACA,sDACA,qBACA,cACF,CAAC,CAAC,KAAK,GAAG,EACV,GACF,EAIM,EAAsB,OAAO,mBAAoB,GAAG,EAQpD,EAA8B,IAAI,OACtC,CACE,mCACA,sDACA,qBACA,cACF,CAAC,CAAC,KAAK,GAAG,EACV,GACF,EAGA,SAAgB,EAAU,EAAsB,CAC9C,OAAO,EAAK,QAAQ,EAAc,EAAE,CAAC,CAAC,QAAQ,EAAiB,EAAE,CACnE,CAQA,SAAgB,EAAuB,EAAsB,CAC3D,OAAO,EAAK,QAAQ,EAA6B,EAAE,CAAC,CAAC,QAAQ,EAAiB,EAAE,CAClF,CAWA,SAAgB,EAAwB,EAAsB,CAC5D,OAAO,EACJ,QAAQ,QAAS;CAAI,CAAC,CACtB,MAAM;CAAI,CAAC,CACX,IAAK,GAAU,EAAK,SAAS,IAAI,EAAK,EAAK,MAAM,IAAI,CAAC,CAAC,GAAG,EAAE,GAAK,GAAM,CAAK,CAAC,CAC7E,KAAK;CAAI,CACd,CAGA,SAAgB,EAAoB,EAAsB,CACxD,OAAO,EAAwB,EAAuB,CAAI,CAAC,CAC7D,CAGA,SAAgB,EAA+B,EAAsB,CACnE,OAAO,EAAwB,EAAU,CAAI,CAAC,CAChD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/services/AnsiScrub/ansiScrub.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Turns terminal output into text worth grepping.
|
|
4
|
+
*
|
|
5
|
+
* PTY output is written for a screen, not a file: colours, cursor moves and
|
|
6
|
+
* carriage-return redraws all end up in the byte stream. Without this a single
|
|
7
|
+
* progress bar becomes thousands of near-identical log lines.
|
|
8
|
+
*/
|
|
9
|
+
/** Removes escape sequences, leaving the characters a user would have seen. */
|
|
10
|
+
declare function stripAnsi(text: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Removes everything `stripAnsi` does except colour.
|
|
13
|
+
*
|
|
14
|
+
* Logs are read back by a terminal renderer as well as by grep, and a command
|
|
15
|
+
* that colours its own output has already said how it should look.
|
|
16
|
+
*/
|
|
17
|
+
declare function stripAnsiKeepingColour(text: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Collapses carriage-return redraws.
|
|
20
|
+
*
|
|
21
|
+
* A bare `\r` returns the cursor to the start of the current line, so whatever
|
|
22
|
+
* follows overwrites it. Only the final state of each line is kept. The `\r` of
|
|
23
|
+
* a CRLF pair is a line terminator rather than a redraw, so it is normalised
|
|
24
|
+
* away first: a pseudo terminal ends every line that way, and treating it as a
|
|
25
|
+
* redraw would blank the whole log.
|
|
26
|
+
*/
|
|
27
|
+
declare function collapseCarriageReturns(text: string): string;
|
|
28
|
+
/** Full scrub applied to PTY output before it reaches the log file. */
|
|
29
|
+
declare function scrubTerminalOutput(text: string): string;
|
|
30
|
+
/** Plain-text scrub, for the copy the model reads. */
|
|
31
|
+
declare function scrubTerminalOutputToPlainText(text: string): string;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { collapseCarriageReturns, scrubTerminalOutput, scrubTerminalOutputToPlainText, stripAnsi, stripAnsiKeepingColour };
|
|
34
|
+
//# sourceMappingURL=ansiScrub.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansiScrub.d.cts","names":[],"sources":["../../../src/services/AnsiScrub/ansiScrub.ts"],"mappings":";;;;;;;;;iBA2CgB,UAAU;;;;;;;iBAUV,uBAAuB;;;;;;;;;;iBAavB,wBAAwB;;iBASxB,oBAAoB;;iBAKpB,+BAA+B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/services/AnsiScrub/ansiScrub.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Turns terminal output into text worth grepping.
|
|
4
|
+
*
|
|
5
|
+
* PTY output is written for a screen, not a file: colours, cursor moves and
|
|
6
|
+
* carriage-return redraws all end up in the byte stream. Without this a single
|
|
7
|
+
* progress bar becomes thousands of near-identical log lines.
|
|
8
|
+
*/
|
|
9
|
+
/** Removes escape sequences, leaving the characters a user would have seen. */
|
|
10
|
+
declare function stripAnsi(text: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Removes everything `stripAnsi` does except colour.
|
|
13
|
+
*
|
|
14
|
+
* Logs are read back by a terminal renderer as well as by grep, and a command
|
|
15
|
+
* that colours its own output has already said how it should look.
|
|
16
|
+
*/
|
|
17
|
+
declare function stripAnsiKeepingColour(text: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Collapses carriage-return redraws.
|
|
20
|
+
*
|
|
21
|
+
* A bare `\r` returns the cursor to the start of the current line, so whatever
|
|
22
|
+
* follows overwrites it. Only the final state of each line is kept. The `\r` of
|
|
23
|
+
* a CRLF pair is a line terminator rather than a redraw, so it is normalised
|
|
24
|
+
* away first: a pseudo terminal ends every line that way, and treating it as a
|
|
25
|
+
* redraw would blank the whole log.
|
|
26
|
+
*/
|
|
27
|
+
declare function collapseCarriageReturns(text: string): string;
|
|
28
|
+
/** Full scrub applied to PTY output before it reaches the log file. */
|
|
29
|
+
declare function scrubTerminalOutput(text: string): string;
|
|
30
|
+
/** Plain-text scrub, for the copy the model reads. */
|
|
31
|
+
declare function scrubTerminalOutputToPlainText(text: string): string;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { collapseCarriageReturns, scrubTerminalOutput, scrubTerminalOutputToPlainText, stripAnsi, stripAnsiKeepingColour };
|
|
34
|
+
//# sourceMappingURL=ansiScrub.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansiScrub.d.mts","names":[],"sources":["../../../src/services/AnsiScrub/ansiScrub.ts"],"mappings":";;;;;;;;;iBA2CgB,UAAU;;;;;;;iBAUV,uBAAuB;;;;;;;;;;iBAavB,wBAAwB;;iBASxB,oBAAoB;;iBAKpB,+BAA+B"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const e=new RegExp([`\\u001B\\[[0-9;?]*[ -/]*[@-~]`,`\\u001B\\][^\\u0007\\u001B]*(?:\\u0007|\\u001B\\\\)`,`\\u001B[@-Z\\\\-_]`,`\\u001B[=><]`].join(`|`),`g`),t=RegExp(`[\\u0007\\u0008]`,`g`),n=new RegExp([`\\u001B\\[[0-9;?]*[ -/]*[@-ln-~]`,`\\u001B\\][^\\u0007\\u001B]*(?:\\u0007|\\u001B\\\\)`,`\\u001B[@-Z\\\\-_]`,`\\u001B[=><]`].join(`|`),`g`);function r(n){return n.replace(e,``).replace(t,``)}function i(e){return e.replace(n,``).replace(t,``)}function a(e){return e.replace(/\r\n/g,`
|
|
2
|
+
`).split(`
|
|
3
|
+
`).map(e=>e.includes(`\r`)?e.split(`\r`).at(-1)??``:e).join(`
|
|
4
|
+
`)}function o(e){return a(i(e))}function s(e){return a(r(e))}export{a as collapseCarriageReturns,o as scrubTerminalOutput,s as scrubTerminalOutputToPlainText,r as stripAnsi,i as stripAnsiKeepingColour};
|
|
5
|
+
//# sourceMappingURL=ansiScrub.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansiScrub.mjs","names":[],"sources":["../../../src/services/AnsiScrub/ansiScrub.ts"],"sourcesContent":["/**\n * Turns terminal output into text worth grepping.\n *\n * PTY output is written for a screen, not a file: colours, cursor moves and\n * carriage-return redraws all end up in the byte stream. Without this a single\n * progress bar becomes thousands of near-identical log lines.\n */\n\n/**\n * CSI sequences (colours, cursor moves), OSC strings, the two-byte Fe escapes,\n * and the keypad-mode escapes shells emit around every prompt.\n */\nconst ANSI_PATTERN = new RegExp(\n [\n '\\\\u001B\\\\[[0-9;?]*[ -/]*[@-~]',\n '\\\\u001B\\\\][^\\\\u0007\\\\u001B]*(?:\\\\u0007|\\\\u001B\\\\\\\\)',\n '\\\\u001B[@-Z\\\\\\\\-_]',\n '\\\\u001B[=><]',\n ].join('|'),\n 'g',\n);\n\n/** Bell and backspace, which a terminal consumes rather than displays. */\n// oxlint-disable-next-line no-control-regex -- matching terminal control bytes is the whole job\nconst CONTROL_PATTERN = new RegExp('[\\\\u0007\\\\u0008]', 'g');\n\n/**\n * The same set minus SGR, the sequence that only sets colour and weight.\n *\n * The final byte class omits `m`, so `ESC[32m` survives while cursor moves,\n * OSC strings and keypad escapes are still removed.\n */\nconst ANSI_PATTERN_KEEPING_COLOUR = new RegExp(\n [\n '\\\\u001B\\\\[[0-9;?]*[ -/]*[@-ln-~]',\n '\\\\u001B\\\\][^\\\\u0007\\\\u001B]*(?:\\\\u0007|\\\\u001B\\\\\\\\)',\n '\\\\u001B[@-Z\\\\\\\\-_]',\n '\\\\u001B[=><]',\n ].join('|'),\n 'g',\n);\n\n/** Removes escape sequences, leaving the characters a user would have seen. */\nexport function stripAnsi(text: string): string {\n return text.replace(ANSI_PATTERN, '').replace(CONTROL_PATTERN, '');\n}\n\n/**\n * Removes everything `stripAnsi` does except colour.\n *\n * Logs are read back by a terminal renderer as well as by grep, and a command\n * that colours its own output has already said how it should look.\n */\nexport function stripAnsiKeepingColour(text: string): string {\n return text.replace(ANSI_PATTERN_KEEPING_COLOUR, '').replace(CONTROL_PATTERN, '');\n}\n\n/**\n * Collapses carriage-return redraws.\n *\n * A bare `\\r` returns the cursor to the start of the current line, so whatever\n * follows overwrites it. Only the final state of each line is kept. The `\\r` of\n * a CRLF pair is a line terminator rather than a redraw, so it is normalised\n * away first: a pseudo terminal ends every line that way, and treating it as a\n * redraw would blank the whole log.\n */\nexport function collapseCarriageReturns(text: string): string {\n return text\n .replace(/\\r\\n/g, '\\n')\n .split('\\n')\n .map((line) => (line.includes('\\r') ? (line.split('\\r').at(-1) ?? '') : line))\n .join('\\n');\n}\n\n/** Full scrub applied to PTY output before it reaches the log file. */\nexport function scrubTerminalOutput(text: string): string {\n return collapseCarriageReturns(stripAnsiKeepingColour(text));\n}\n\n/** Plain-text scrub, for the copy the model reads. */\nexport function scrubTerminalOutputToPlainText(text: string): string {\n return collapseCarriageReturns(stripAnsi(text));\n}\n"],"mappings":"AAYA,MAAM,EAAe,IAAI,OACvB,CACE,gCACA,sDACA,qBACA,cACF,CAAC,CAAC,KAAK,GAAG,EACV,GACF,EAIM,EAAsB,OAAO,mBAAoB,GAAG,EAQpD,EAA8B,IAAI,OACtC,CACE,mCACA,sDACA,qBACA,cACF,CAAC,CAAC,KAAK,GAAG,EACV,GACF,EAGA,SAAgB,EAAU,EAAsB,CAC9C,OAAO,EAAK,QAAQ,EAAc,EAAE,CAAC,CAAC,QAAQ,EAAiB,EAAE,CACnE,CAQA,SAAgB,EAAuB,EAAsB,CAC3D,OAAO,EAAK,QAAQ,EAA6B,EAAE,CAAC,CAAC,QAAQ,EAAiB,EAAE,CAClF,CAWA,SAAgB,EAAwB,EAAsB,CAC5D,OAAO,EACJ,QAAQ,QAAS;CAAI,CAAC,CACtB,MAAM;CAAI,CAAC,CACX,IAAK,GAAU,EAAK,SAAS,IAAI,EAAK,EAAK,MAAM,IAAI,CAAC,CAAC,GAAG,EAAE,GAAK,GAAM,CAAK,CAAC,CAC7E,KAAK;CAAI,CACd,CAGA,SAAgB,EAAoB,EAAsB,CACxD,OAAO,EAAwB,EAAuB,CAAI,CAAC,CAC7D,CAGA,SAAgB,EAA+B,EAAsB,CACnE,OAAO,EAAwB,EAAU,CAAI,CAAC,CAChD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./ansiScrub.cjs");exports.collapseCarriageReturns=e.collapseCarriageReturns,exports.scrubTerminalOutput=e.scrubTerminalOutput,exports.scrubTerminalOutputToPlainText=e.scrubTerminalOutputToPlainText,exports.stripAnsi=e.stripAnsi,exports.stripAnsiKeepingColour=e.stripAnsiKeepingColour;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{collapseCarriageReturns as e,scrubTerminalOutput as t,scrubTerminalOutputToPlainText as n,stripAnsi as r,stripAnsiKeepingColour as i}from"./ansiScrub.mjs";export{e as collapseCarriageReturns,t as scrubTerminalOutput,n as scrubTerminalOutputToPlainText,r as stripAnsi,i as stripAnsiKeepingColour};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../config.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");let a=require("inversify");require("reflect-metadata/lite");let o=require("node:crypto");const s=Symbol(`threshold-reached`),c=Symbol(`deadline-reached`),l=`completed`,u=`failed`,d=`launcher_error`,f=`signaled`;function p(){return`${Date.now().toString(36)}-${(0,o.randomBytes)(3).toString(`base64url`)}`}let m=class{launcher;rmuxBackend;ptyHost;namer;registry;clock;constructor(e,t,n,r,i,a){this.launcher=e,this.rmuxBackend=t,this.ptyHost=n,this.namer=r,this.registry=i,this.clock=a}async run(e){let t=p(),n=await this.namer.allocate(e.command,e.sessionId,e.name),r=e.cwd??process.cwd(),i=e.interactive===!0,a;try{a=await this.rmuxBackend.launch({id:t,name:n,command:e.command,cwd:r,sessionId:e.sessionId,interactive:i})??(i?await this.ptyHost.launch({id:t,name:n,command:e.command,cwd:r,sessionId:e.sessionId}):this.launcher.launch({id:t,name:n,command:e.command,cwd:r,sessionId:e.sessionId}))}catch(e){return{kind:u,id:t,name:n,error:e instanceof Error?e.message:String(e)}}if(a.pid===void 0)return{kind:u,id:t,name:n,error:`The command did not start, so it cannot be supervised`};try{await this.registry.register({id:t,name:n,pid:a.pid,command:e.command,cwd:r,logPath:a.logPath,interactive:i,sessionId:e.sessionId,backend:a.backend,...a.backendTarget?{backendTarget:a.backendTarget}:{}})}catch(e){return await a.stop(),{kind:u,id:t,name:n,error:e instanceof Error?e.message:String(e)}}if(e.background===!0||i)return this.promote(a,e.background===!0?`requested`:`interactive`);let o=e.onOutput?this.followOutput(a,e.onOutput):void 0;try{let r=await this.race(a,e.timeoutMs);return o?.flush(),r===s?this.promote(a,`threshold`):r===c?(await a.stop(),o?.flush(),await this.registry.complete(t,{reason:`timed_out`,code:null,signal:`SIGTERM`}),{kind:l,id:t,name:n,output:a.output(),exitCode:null,signal:`SIGTERM`,logPath:a.logPath,backend:a.backend,timedOut:!0}):r instanceof Error?(await this.registry.complete(t,{reason:d,code:null,signal:null}),{kind:u,id:t,name:n,error:r.message}):(await this.registry.complete(t,{reason:r.signal?f:r.code===0?l:u,code:r.code,signal:r.signal}),{kind:l,id:t,name:n,output:a.output(),exitCode:r.code,signal:r.signal,logPath:a.logPath,backend:a.backend})}finally{o?.dispose()}}followOutput(e,t){let n=!0,r=``,i,a=()=>{if(!n)return;let i=e.output();i!==r&&(r=i,t(i))},o=()=>{n&&(a(),n&&(i=this.clock.after(100,o)))};return i=this.clock.after(100,o),{flush:a,dispose:()=>{n=!1,i?.(),i=void 0}}}async race(t,n){let r=[],i=[t.completion().catch(e=>e)];i.push(new Promise(t=>{r.push(this.clock.after(e.getBackgroundThresholdMs(),()=>t(s)))})),n!==void 0&&n>0&&i.push(new Promise(e=>{r.push(this.clock.after(n,()=>e(c)))}));try{return await Promise.race(i)}finally{for(let e of r)e()}}async promote(e,t){return e.pid===void 0?{kind:u,id:e.id,name:e.name,error:`The command did not start`}:(await this.registry.markPromoted(e.id),e.detach(),e.completion().then(t=>this.registry.complete(e.id,{reason:t.signal?f:t.code===0?l:u,code:t.code,signal:t.signal}),()=>this.registry.complete(e.id,{reason:d,code:null,signal:null})).catch(t=>{let n=t instanceof Error?t.message:String(t);process.emitWarning(`Failed to complete runner ${e.id}: ${n}`)}),{kind:`promoted`,id:e.id,name:e.name,pid:e.pid,logPath:e.logPath,backend:e.backend,reason:t})}};m=i.default([(0,a.injectable)(),r.default(0,(0,a.inject)(t.TYPES.Launcher)),r.default(1,(0,a.inject)(t.TYPES.RmuxBackend)),r.default(2,(0,a.inject)(t.TYPES.PtyHost)),r.default(3,(0,a.inject)(t.TYPES.RunnerNamer)),r.default(4,(0,a.inject)(t.TYPES.RunnerRegistry)),r.default(5,(0,a.inject)(t.TYPES.Clock)),n.default(`design:paramtypes`,[Object,Object,Object,Object,Object,Object])],m),Object.defineProperty(exports,"BashRunService",{enumerable:!0,get:function(){return m}});
|
|
2
|
+
//# sourceMappingURL=BashRunService.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BashRunService.cjs","names":["randomBytes","getBackgroundThresholdMs","injectable","inject","TYPES"],"sources":["../../../src/services/BashRunService/BashRunService.ts"],"sourcesContent":["import { inject, injectable } from 'inversify';\nimport { randomBytes } from 'node:crypto';\nimport 'reflect-metadata/lite';\nimport { getBackgroundThresholdMs } from '../../config.ts';\nimport { TYPES } from '../../types.ts';\nimport type { IClock } from '../Clock/index.ts';\nimport type { ILauncher, RunHandle } from '../Launcher/index.ts';\nimport type { IPtyHost } from '../PtyHost/index.ts';\nimport type { IRmuxBackend } from '../RmuxBackend/index.ts';\nimport type { IRunnerNamer } from '../RunnerNamer/index.ts';\nimport type { IRunnerRegistry } from '../RunnerRegistry/index.ts';\nimport type { BashRunRequest, BashRunResult, IBashRunService, PromotedRun } from './types.ts';\n\n/** The command outlived the background threshold and should be promoted. */\nconst TIMED_OUT = Symbol('threshold-reached');\n/** The command outlived the caller's explicit timeout and should be stopped. */\nconst DEADLINE = Symbol('deadline-reached');\nconst RUNNER_ID_RANDOM_BYTES = 3;\nconst OUTPUT_UPDATE_POLL_MS = 100;\nconst COMPLETED = 'completed';\nconst FAILED = 'failed';\nconst LAUNCHER_ERROR = 'launcher_error';\nconst SIGNALED = 'signaled';\n\nfunction runnerId(): string {\n const timestamp = Date.now().toString(36);\n const random = randomBytes(RUNNER_ID_RANDOM_BYTES).toString('base64url');\n return `${timestamp}-${random}`;\n}\n\n@injectable()\nexport class BashRunService implements IBashRunService {\n constructor(\n @inject(TYPES.Launcher) private readonly launcher: ILauncher,\n @inject(TYPES.RmuxBackend) private readonly rmuxBackend: IRmuxBackend,\n @inject(TYPES.PtyHost) private readonly ptyHost: IPtyHost,\n @inject(TYPES.RunnerNamer) private readonly namer: IRunnerNamer,\n @inject(TYPES.RunnerRegistry) private readonly registry: IRunnerRegistry,\n @inject(TYPES.Clock) private readonly clock: IClock,\n ) {}\n\n async run(request: BashRunRequest): Promise<BashRunResult> {\n const id = runnerId();\n const name = await this.namer.allocate(request.command, request.sessionId, request.name);\n const cwd = request.cwd ?? process.cwd();\n const interactive = request.interactive === true;\n\n let handle: RunHandle;\n try {\n const rmuxHandle = await this.rmuxBackend.launch({\n id,\n name,\n command: request.command,\n cwd,\n sessionId: request.sessionId,\n interactive,\n });\n handle =\n rmuxHandle ??\n (interactive\n ? await this.ptyHost.launch({ id, name, command: request.command, cwd, sessionId: request.sessionId })\n : this.launcher.launch({ id, name, command: request.command, cwd, sessionId: request.sessionId }));\n } catch (error) {\n // Loading node-pty is the one launch step that can fail before a process\n // exists, and it must not take the whole tool call down.\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n if (handle.pid === undefined) {\n return { kind: FAILED, id, name, error: 'The command did not start, so it cannot be supervised' };\n }\n\n try {\n await this.registry.register({\n id,\n name,\n pid: handle.pid,\n command: request.command,\n cwd,\n logPath: handle.logPath,\n interactive,\n sessionId: request.sessionId,\n backend: handle.backend,\n ...(handle.backendTarget ? { backendTarget: handle.backendTarget } : {}),\n });\n } catch (error) {\n await handle.stop();\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n // An interactive run has nothing to wait for: it is going to prompt, so\n // the model needs the runner name before it can answer.\n if (request.background === true || interactive) {\n return this.promote(handle, request.background === true ? 'requested' : 'interactive');\n }\n\n const outputUpdates = request.onOutput ? this.followOutput(handle, request.onOutput) : undefined;\n try {\n const outcome = await this.race(handle, request.timeoutMs);\n outputUpdates?.flush();\n if (outcome === TIMED_OUT) {\n return this.promote(handle, 'threshold');\n }\n if (outcome === DEADLINE) {\n // An explicit timeout means the caller wants the command dead, not\n // supervised, so it is stopped rather than promoted.\n await handle.stop();\n outputUpdates?.flush();\n await this.registry.complete(id, { reason: 'timed_out', code: null, signal: 'SIGTERM' });\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: null,\n signal: 'SIGTERM',\n logPath: handle.logPath,\n backend: handle.backend,\n timedOut: true,\n };\n }\n if (outcome instanceof Error) {\n await this.registry.complete(id, { reason: LAUNCHER_ERROR, code: null, signal: null });\n return { kind: FAILED, id, name, error: outcome.message };\n }\n\n await this.registry.complete(id, {\n reason: outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED,\n code: outcome.code,\n signal: outcome.signal,\n });\n\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: outcome.code,\n signal: outcome.signal,\n logPath: handle.logPath,\n backend: handle.backend,\n };\n } finally {\n outputUpdates?.dispose();\n }\n }\n\n private followOutput(\n handle: RunHandle,\n onOutput: NonNullable<BashRunRequest['onOutput']>,\n ): { flush(): void; dispose(): void } {\n let active = true;\n let previous = '';\n let cancelPoll: (() => void) | undefined;\n const flush = (): void => {\n if (!active) return;\n const output = handle.output();\n if (output === previous) return;\n previous = output;\n onOutput(output);\n };\n const poll = (): void => {\n if (!active) return;\n flush();\n if (active) cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n };\n cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n return {\n flush,\n dispose: () => {\n active = false;\n cancelPoll?.();\n cancelPoll = undefined;\n },\n };\n }\n\n /**\n * Waits for the command, giving up at the background threshold or at the\n * caller's timeout, whichever comes first.\n *\n * A rejected completion is returned rather than thrown so the caller can\n * report a start failure as a tool result instead of an exception.\n */\n private async race(\n handle: RunHandle,\n timeoutMs: number | undefined,\n ): Promise<Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT | typeof DEADLINE> {\n const cancels: Array<() => void> = [];\n const racers: Array<Promise<unknown>> = [handle.completion().catch((error: Error) => error)];\n\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(getBackgroundThresholdMs(), () => resolve(TIMED_OUT)));\n }),\n );\n if (timeoutMs !== undefined && timeoutMs > 0) {\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(timeoutMs, () => resolve(DEADLINE)));\n }),\n );\n }\n\n try {\n return (await Promise.race(racers)) as Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT;\n } finally {\n for (const cancel of cancels) cancel();\n }\n }\n\n private async promote(handle: RunHandle, reason: PromotedRun['reason']): Promise<BashRunResult> {\n if (handle.pid === undefined)\n return { kind: FAILED, id: handle.id, name: handle.name, error: 'The command did not start' };\n await this.registry.markPromoted(handle.id);\n // Registration first: an unregistered runner is invisible, and the handle\n // stops buffering the moment it is detached.\n handle.detach();\n void handle\n .completion()\n .then(\n (outcome) =>\n this.registry.complete(handle.id, {\n reason: outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED,\n code: outcome.code,\n signal: outcome.signal,\n }),\n () => this.registry.complete(handle.id, { reason: LAUNCHER_ERROR, code: null, signal: null }),\n )\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.emitWarning(`Failed to complete runner ${handle.id}: ${message}`);\n });\n\n return {\n kind: 'promoted',\n id: handle.id,\n name: handle.name,\n pid: handle.pid,\n logPath: handle.logPath,\n backend: handle.backend,\n reason,\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { IClock } from "../Clock/types.cjs";
|
|
2
|
+
import "../Clock/index.cjs";
|
|
3
|
+
import { ILauncher } from "../Launcher/types.cjs";
|
|
4
|
+
import "../Launcher/index.cjs";
|
|
5
|
+
import { IPtyHost } from "../PtyHost/types.cjs";
|
|
6
|
+
import "../PtyHost/index.cjs";
|
|
7
|
+
import { IRmuxBackend } from "../RmuxBackend/types.cjs";
|
|
8
|
+
import "../RmuxBackend/index.cjs";
|
|
9
|
+
import { IRunnerRegistry } from "../RunnerRegistry/types.cjs";
|
|
10
|
+
import "../RunnerRegistry/index.cjs";
|
|
11
|
+
import { IRunnerNamer } from "../RunnerNamer/types.cjs";
|
|
12
|
+
import "../RunnerNamer/index.cjs";
|
|
13
|
+
import { BashRunRequest, BashRunResult, IBashRunService } from "./types.cjs";
|
|
14
|
+
import "reflect-metadata/lite";
|
|
15
|
+
//#region src/services/BashRunService/BashRunService.d.ts
|
|
16
|
+
declare class BashRunService implements IBashRunService {
|
|
17
|
+
private readonly launcher;
|
|
18
|
+
private readonly rmuxBackend;
|
|
19
|
+
private readonly ptyHost;
|
|
20
|
+
private readonly namer;
|
|
21
|
+
private readonly registry;
|
|
22
|
+
private readonly clock;
|
|
23
|
+
constructor(launcher: ILauncher, rmuxBackend: IRmuxBackend, ptyHost: IPtyHost, namer: IRunnerNamer, registry: IRunnerRegistry, clock: IClock);
|
|
24
|
+
run(request: BashRunRequest): Promise<BashRunResult>;
|
|
25
|
+
private followOutput;
|
|
26
|
+
/**
|
|
27
|
+
* Waits for the command, giving up at the background threshold or at the
|
|
28
|
+
* caller's timeout, whichever comes first.
|
|
29
|
+
*
|
|
30
|
+
* A rejected completion is returned rather than thrown so the caller can
|
|
31
|
+
* report a start failure as a tool result instead of an exception.
|
|
32
|
+
*/
|
|
33
|
+
private race;
|
|
34
|
+
private promote;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { BashRunService };
|
|
38
|
+
//# sourceMappingURL=BashRunService.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BashRunService.d.cts","names":[],"sources":["../../../src/services/BashRunService/BashRunService.ts"],"mappings":";;;;;;;;;;;;;;;cA+Ba,0BAA0B;mBAEM;mBACG;mBACJ;mBACI;mBACG;mBACT;EALG,YAAA,UAAU,WACP,aAAa,cACjB,SAAS,UACL,OAAO,cACJ,UAAU,iBACnB,OAAO;EAGzC,IAAI,SAAS,iBAAiB,QAAQ;UA0GpC;;;;;;;;UAqCM;UA2BA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { IClock } from "../Clock/types.mjs";
|
|
2
|
+
import "../Clock/index.mjs";
|
|
3
|
+
import { ILauncher } from "../Launcher/types.mjs";
|
|
4
|
+
import "../Launcher/index.mjs";
|
|
5
|
+
import { IPtyHost } from "../PtyHost/types.mjs";
|
|
6
|
+
import "../PtyHost/index.mjs";
|
|
7
|
+
import { IRmuxBackend } from "../RmuxBackend/types.mjs";
|
|
8
|
+
import "../RmuxBackend/index.mjs";
|
|
9
|
+
import { IRunnerRegistry } from "../RunnerRegistry/types.mjs";
|
|
10
|
+
import "../RunnerRegistry/index.mjs";
|
|
11
|
+
import { IRunnerNamer } from "../RunnerNamer/types.mjs";
|
|
12
|
+
import "../RunnerNamer/index.mjs";
|
|
13
|
+
import { BashRunRequest, BashRunResult, IBashRunService } from "./types.mjs";
|
|
14
|
+
import "reflect-metadata/lite";
|
|
15
|
+
//#region src/services/BashRunService/BashRunService.d.ts
|
|
16
|
+
declare class BashRunService implements IBashRunService {
|
|
17
|
+
private readonly launcher;
|
|
18
|
+
private readonly rmuxBackend;
|
|
19
|
+
private readonly ptyHost;
|
|
20
|
+
private readonly namer;
|
|
21
|
+
private readonly registry;
|
|
22
|
+
private readonly clock;
|
|
23
|
+
constructor(launcher: ILauncher, rmuxBackend: IRmuxBackend, ptyHost: IPtyHost, namer: IRunnerNamer, registry: IRunnerRegistry, clock: IClock);
|
|
24
|
+
run(request: BashRunRequest): Promise<BashRunResult>;
|
|
25
|
+
private followOutput;
|
|
26
|
+
/**
|
|
27
|
+
* Waits for the command, giving up at the background threshold or at the
|
|
28
|
+
* caller's timeout, whichever comes first.
|
|
29
|
+
*
|
|
30
|
+
* A rejected completion is returned rather than thrown so the caller can
|
|
31
|
+
* report a start failure as a tool result instead of an exception.
|
|
32
|
+
*/
|
|
33
|
+
private race;
|
|
34
|
+
private promote;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { BashRunService };
|
|
38
|
+
//# sourceMappingURL=BashRunService.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BashRunService.d.mts","names":[],"sources":["../../../src/services/BashRunService/BashRunService.ts"],"mappings":";;;;;;;;;;;;;;;cA+Ba,0BAA0B;mBAEM;mBACG;mBACJ;mBACI;mBACG;mBACT;EALG,YAAA,UAAU,WACP,aAAa,cACjB,SAAS,UACL,OAAO,cACJ,UAAU,iBACnB,OAAO;EAGzC,IAAI,SAAS,iBAAiB,QAAQ;UA0GpC;;;;;;;;UAqCM;UA2BA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{getBackgroundThresholdMs 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{inject as a,injectable as o}from"inversify";import"reflect-metadata/lite";import{randomBytes as s}from"node:crypto";const c=Symbol(`threshold-reached`),l=Symbol(`deadline-reached`),u=`completed`,d=`failed`,f=`launcher_error`,p=`signaled`;function m(){return`${Date.now().toString(36)}-${s(3).toString(`base64url`)}`}let h=class{launcher;rmuxBackend;ptyHost;namer;registry;clock;constructor(e,t,n,r,i,a){this.launcher=e,this.rmuxBackend=t,this.ptyHost=n,this.namer=r,this.registry=i,this.clock=a}async run(e){let t=m(),n=await this.namer.allocate(e.command,e.sessionId,e.name),r=e.cwd??process.cwd(),i=e.interactive===!0,a;try{a=await this.rmuxBackend.launch({id:t,name:n,command:e.command,cwd:r,sessionId:e.sessionId,interactive:i})??(i?await this.ptyHost.launch({id:t,name:n,command:e.command,cwd:r,sessionId:e.sessionId}):this.launcher.launch({id:t,name:n,command:e.command,cwd:r,sessionId:e.sessionId}))}catch(e){return{kind:d,id:t,name:n,error:e instanceof Error?e.message:String(e)}}if(a.pid===void 0)return{kind:d,id:t,name:n,error:`The command did not start, so it cannot be supervised`};try{await this.registry.register({id:t,name:n,pid:a.pid,command:e.command,cwd:r,logPath:a.logPath,interactive:i,sessionId:e.sessionId,backend:a.backend,...a.backendTarget?{backendTarget:a.backendTarget}:{}})}catch(e){return await a.stop(),{kind:d,id:t,name:n,error:e instanceof Error?e.message:String(e)}}if(e.background===!0||i)return this.promote(a,e.background===!0?`requested`:`interactive`);let o=e.onOutput?this.followOutput(a,e.onOutput):void 0;try{let r=await this.race(a,e.timeoutMs);return o?.flush(),r===c?this.promote(a,`threshold`):r===l?(await a.stop(),o?.flush(),await this.registry.complete(t,{reason:`timed_out`,code:null,signal:`SIGTERM`}),{kind:u,id:t,name:n,output:a.output(),exitCode:null,signal:`SIGTERM`,logPath:a.logPath,backend:a.backend,timedOut:!0}):r instanceof Error?(await this.registry.complete(t,{reason:f,code:null,signal:null}),{kind:d,id:t,name:n,error:r.message}):(await this.registry.complete(t,{reason:r.signal?p:r.code===0?u:d,code:r.code,signal:r.signal}),{kind:u,id:t,name:n,output:a.output(),exitCode:r.code,signal:r.signal,logPath:a.logPath,backend:a.backend})}finally{o?.dispose()}}followOutput(e,t){let n=!0,r=``,i,a=()=>{if(!n)return;let i=e.output();i!==r&&(r=i,t(i))},o=()=>{n&&(a(),n&&(i=this.clock.after(100,o)))};return i=this.clock.after(100,o),{flush:a,dispose:()=>{n=!1,i?.(),i=void 0}}}async race(t,n){let r=[],i=[t.completion().catch(e=>e)];i.push(new Promise(t=>{r.push(this.clock.after(e(),()=>t(c)))})),n!==void 0&&n>0&&i.push(new Promise(e=>{r.push(this.clock.after(n,()=>e(l)))}));try{return await Promise.race(i)}finally{for(let e of r)e()}}async promote(e,t){return e.pid===void 0?{kind:d,id:e.id,name:e.name,error:`The command did not start`}:(await this.registry.markPromoted(e.id),e.detach(),e.completion().then(t=>this.registry.complete(e.id,{reason:t.signal?p:t.code===0?u:d,code:t.code,signal:t.signal}),()=>this.registry.complete(e.id,{reason:f,code:null,signal:null})).catch(t=>{let n=t instanceof Error?t.message:String(t);process.emitWarning(`Failed to complete runner ${e.id}: ${n}`)}),{kind:`promoted`,id:e.id,name:e.name,pid:e.pid,logPath:e.logPath,backend:e.backend,reason:t})}};h=i([o(),r(0,a(t.Launcher)),r(1,a(t.RmuxBackend)),r(2,a(t.PtyHost)),r(3,a(t.RunnerNamer)),r(4,a(t.RunnerRegistry)),r(5,a(t.Clock)),n(`design:paramtypes`,[Object,Object,Object,Object,Object,Object])],h);export{h as BashRunService};
|
|
2
|
+
//# sourceMappingURL=BashRunService.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BashRunService.mjs","names":[],"sources":["../../../src/services/BashRunService/BashRunService.ts"],"sourcesContent":["import { inject, injectable } from 'inversify';\nimport { randomBytes } from 'node:crypto';\nimport 'reflect-metadata/lite';\nimport { getBackgroundThresholdMs } from '../../config.ts';\nimport { TYPES } from '../../types.ts';\nimport type { IClock } from '../Clock/index.ts';\nimport type { ILauncher, RunHandle } from '../Launcher/index.ts';\nimport type { IPtyHost } from '../PtyHost/index.ts';\nimport type { IRmuxBackend } from '../RmuxBackend/index.ts';\nimport type { IRunnerNamer } from '../RunnerNamer/index.ts';\nimport type { IRunnerRegistry } from '../RunnerRegistry/index.ts';\nimport type { BashRunRequest, BashRunResult, IBashRunService, PromotedRun } from './types.ts';\n\n/** The command outlived the background threshold and should be promoted. */\nconst TIMED_OUT = Symbol('threshold-reached');\n/** The command outlived the caller's explicit timeout and should be stopped. */\nconst DEADLINE = Symbol('deadline-reached');\nconst RUNNER_ID_RANDOM_BYTES = 3;\nconst OUTPUT_UPDATE_POLL_MS = 100;\nconst COMPLETED = 'completed';\nconst FAILED = 'failed';\nconst LAUNCHER_ERROR = 'launcher_error';\nconst SIGNALED = 'signaled';\n\nfunction runnerId(): string {\n const timestamp = Date.now().toString(36);\n const random = randomBytes(RUNNER_ID_RANDOM_BYTES).toString('base64url');\n return `${timestamp}-${random}`;\n}\n\n@injectable()\nexport class BashRunService implements IBashRunService {\n constructor(\n @inject(TYPES.Launcher) private readonly launcher: ILauncher,\n @inject(TYPES.RmuxBackend) private readonly rmuxBackend: IRmuxBackend,\n @inject(TYPES.PtyHost) private readonly ptyHost: IPtyHost,\n @inject(TYPES.RunnerNamer) private readonly namer: IRunnerNamer,\n @inject(TYPES.RunnerRegistry) private readonly registry: IRunnerRegistry,\n @inject(TYPES.Clock) private readonly clock: IClock,\n ) {}\n\n async run(request: BashRunRequest): Promise<BashRunResult> {\n const id = runnerId();\n const name = await this.namer.allocate(request.command, request.sessionId, request.name);\n const cwd = request.cwd ?? process.cwd();\n const interactive = request.interactive === true;\n\n let handle: RunHandle;\n try {\n const rmuxHandle = await this.rmuxBackend.launch({\n id,\n name,\n command: request.command,\n cwd,\n sessionId: request.sessionId,\n interactive,\n });\n handle =\n rmuxHandle ??\n (interactive\n ? await this.ptyHost.launch({ id, name, command: request.command, cwd, sessionId: request.sessionId })\n : this.launcher.launch({ id, name, command: request.command, cwd, sessionId: request.sessionId }));\n } catch (error) {\n // Loading node-pty is the one launch step that can fail before a process\n // exists, and it must not take the whole tool call down.\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n if (handle.pid === undefined) {\n return { kind: FAILED, id, name, error: 'The command did not start, so it cannot be supervised' };\n }\n\n try {\n await this.registry.register({\n id,\n name,\n pid: handle.pid,\n command: request.command,\n cwd,\n logPath: handle.logPath,\n interactive,\n sessionId: request.sessionId,\n backend: handle.backend,\n ...(handle.backendTarget ? { backendTarget: handle.backendTarget } : {}),\n });\n } catch (error) {\n await handle.stop();\n return { kind: FAILED, id, name, error: error instanceof Error ? error.message : String(error) };\n }\n\n // An interactive run has nothing to wait for: it is going to prompt, so\n // the model needs the runner name before it can answer.\n if (request.background === true || interactive) {\n return this.promote(handle, request.background === true ? 'requested' : 'interactive');\n }\n\n const outputUpdates = request.onOutput ? this.followOutput(handle, request.onOutput) : undefined;\n try {\n const outcome = await this.race(handle, request.timeoutMs);\n outputUpdates?.flush();\n if (outcome === TIMED_OUT) {\n return this.promote(handle, 'threshold');\n }\n if (outcome === DEADLINE) {\n // An explicit timeout means the caller wants the command dead, not\n // supervised, so it is stopped rather than promoted.\n await handle.stop();\n outputUpdates?.flush();\n await this.registry.complete(id, { reason: 'timed_out', code: null, signal: 'SIGTERM' });\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: null,\n signal: 'SIGTERM',\n logPath: handle.logPath,\n backend: handle.backend,\n timedOut: true,\n };\n }\n if (outcome instanceof Error) {\n await this.registry.complete(id, { reason: LAUNCHER_ERROR, code: null, signal: null });\n return { kind: FAILED, id, name, error: outcome.message };\n }\n\n await this.registry.complete(id, {\n reason: outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED,\n code: outcome.code,\n signal: outcome.signal,\n });\n\n return {\n kind: COMPLETED,\n id,\n name,\n output: handle.output(),\n exitCode: outcome.code,\n signal: outcome.signal,\n logPath: handle.logPath,\n backend: handle.backend,\n };\n } finally {\n outputUpdates?.dispose();\n }\n }\n\n private followOutput(\n handle: RunHandle,\n onOutput: NonNullable<BashRunRequest['onOutput']>,\n ): { flush(): void; dispose(): void } {\n let active = true;\n let previous = '';\n let cancelPoll: (() => void) | undefined;\n const flush = (): void => {\n if (!active) return;\n const output = handle.output();\n if (output === previous) return;\n previous = output;\n onOutput(output);\n };\n const poll = (): void => {\n if (!active) return;\n flush();\n if (active) cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n };\n cancelPoll = this.clock.after(OUTPUT_UPDATE_POLL_MS, poll);\n return {\n flush,\n dispose: () => {\n active = false;\n cancelPoll?.();\n cancelPoll = undefined;\n },\n };\n }\n\n /**\n * Waits for the command, giving up at the background threshold or at the\n * caller's timeout, whichever comes first.\n *\n * A rejected completion is returned rather than thrown so the caller can\n * report a start failure as a tool result instead of an exception.\n */\n private async race(\n handle: RunHandle,\n timeoutMs: number | undefined,\n ): Promise<Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT | typeof DEADLINE> {\n const cancels: Array<() => void> = [];\n const racers: Array<Promise<unknown>> = [handle.completion().catch((error: Error) => error)];\n\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(getBackgroundThresholdMs(), () => resolve(TIMED_OUT)));\n }),\n );\n if (timeoutMs !== undefined && timeoutMs > 0) {\n racers.push(\n new Promise((resolve) => {\n cancels.push(this.clock.after(timeoutMs, () => resolve(DEADLINE)));\n }),\n );\n }\n\n try {\n return (await Promise.race(racers)) as Awaited<ReturnType<RunHandle['completion']>> | Error | typeof TIMED_OUT;\n } finally {\n for (const cancel of cancels) cancel();\n }\n }\n\n private async promote(handle: RunHandle, reason: PromotedRun['reason']): Promise<BashRunResult> {\n if (handle.pid === undefined)\n return { kind: FAILED, id: handle.id, name: handle.name, error: 'The command did not start' };\n await this.registry.markPromoted(handle.id);\n // Registration first: an unregistered runner is invisible, and the handle\n // stops buffering the moment it is detached.\n handle.detach();\n void handle\n .completion()\n .then(\n (outcome) =>\n this.registry.complete(handle.id, {\n reason: outcome.signal ? SIGNALED : outcome.code === 0 ? COMPLETED : FAILED,\n code: outcome.code,\n signal: outcome.signal,\n }),\n () => this.registry.complete(handle.id, { reason: LAUNCHER_ERROR, code: null, signal: null }),\n )\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.emitWarning(`Failed to complete runner ${handle.id}: ${message}`);\n });\n\n return {\n kind: 'promoted',\n id: handle.id,\n name: handle.name,\n pid: handle.pid,\n logPath: handle.logPath,\n backend: handle.backend,\n reason,\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./BashRunService.cjs");Object.defineProperty(exports,"BashRunService",{enumerable:!0,get:function(){return e.BashRunService}});
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { BashRunRequest, BashRunResult, CompletedRun, FailedRun, IBashRunService, PromotedRun } from "./types.cjs";
|
|
2
|
+
import { BashRunService } from "./BashRunService.cjs";
|
|
3
|
+
export { type BashRunRequest, type BashRunResult, BashRunService, type CompletedRun, type FailedRun, type IBashRunService, type PromotedRun };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { BashRunRequest, BashRunResult, CompletedRun, FailedRun, IBashRunService, PromotedRun } from "./types.mjs";
|
|
2
|
+
import { BashRunService } from "./BashRunService.mjs";
|
|
3
|
+
export { type BashRunRequest, type BashRunResult, BashRunService, type CompletedRun, type FailedRun, type IBashRunService, type PromotedRun };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{BashRunService as e}from"./BashRunService.mjs";export{e as BashRunService};
|