@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,32 @@
|
|
|
1
|
+
//#region src/config.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extension configuration, read from the environment.
|
|
4
|
+
*
|
|
5
|
+
* Env rather than a config file, matching doom-task: doom-pi already carries
|
|
6
|
+
* per-launch state to Pi through env vars.
|
|
7
|
+
*/
|
|
8
|
+
declare const BG_THRESHOLD_MS_ENV = "DOOM_RUNNER_BG_THRESHOLD_MS";
|
|
9
|
+
declare const RESULT_MAX_BYTES_ENV = "DOOM_RUNNER_RESULT_MAX_BYTES";
|
|
10
|
+
declare const LOG_MAX_BYTES_ENV = "DOOM_RUNNER_LOG_MAX_BYTES";
|
|
11
|
+
declare const LOG_TTL_MS_ENV = "DOOM_RUNNER_LOG_TTL_MS";
|
|
12
|
+
/** Unscoped override for the runner log directory. */
|
|
13
|
+
declare const LOG_DIR_ENV = "DOOM_RUNNER_LOG_DIR";
|
|
14
|
+
/** A bash call still running at this point is promoted to a named runner. */
|
|
15
|
+
declare const DEFAULT_BG_THRESHOLD_MS = 60000;
|
|
16
|
+
/** Tool results past this size are tail-truncated and spilled to the log file. */
|
|
17
|
+
declare const DEFAULT_RESULT_MAX_BYTES = 51200;
|
|
18
|
+
/** A runner log rotates once to `.log.1` at this size. */
|
|
19
|
+
declare const DEFAULT_LOG_MAX_BYTES: number;
|
|
20
|
+
/** Retention window for logs with no live registry record. */
|
|
21
|
+
declare const DEFAULT_LOG_TTL_MS: number;
|
|
22
|
+
/** Age at which a bash call becomes a background runner. */
|
|
23
|
+
declare function getBackgroundThresholdMs(env?: NodeJS.ProcessEnv): number;
|
|
24
|
+
/** Byte ceiling for a single tool result before tail truncation kicks in. */
|
|
25
|
+
declare function getResultMaxBytes(env?: NodeJS.ProcessEnv): number;
|
|
26
|
+
/** Byte ceiling for a runner log before it rotates. */
|
|
27
|
+
declare function getLogMaxBytes(env?: NodeJS.ProcessEnv): number;
|
|
28
|
+
/** Retention window for orphaned runner logs. */
|
|
29
|
+
declare function getLogTtlMs(env?: NodeJS.ProcessEnv): number;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes };
|
|
32
|
+
//# sourceMappingURL=config.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.cts","names":[],"sources":["../src/config.ts"],"mappings":";;;;;;;cAOa;cACA;cACA;cACA;;cAEA;;cAGA;;cAEA;;cAEA;;cAEA;;iBAQG,yBAAyB,MAAK,OAAO;;iBAKrC,kBAAkB,MAAK,OAAO;;iBAK9B,eAAe,MAAK,OAAO;;iBAK3B,YAAY,MAAK,OAAO"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/config.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extension configuration, read from the environment.
|
|
4
|
+
*
|
|
5
|
+
* Env rather than a config file, matching doom-task: doom-pi already carries
|
|
6
|
+
* per-launch state to Pi through env vars.
|
|
7
|
+
*/
|
|
8
|
+
declare const BG_THRESHOLD_MS_ENV = "DOOM_RUNNER_BG_THRESHOLD_MS";
|
|
9
|
+
declare const RESULT_MAX_BYTES_ENV = "DOOM_RUNNER_RESULT_MAX_BYTES";
|
|
10
|
+
declare const LOG_MAX_BYTES_ENV = "DOOM_RUNNER_LOG_MAX_BYTES";
|
|
11
|
+
declare const LOG_TTL_MS_ENV = "DOOM_RUNNER_LOG_TTL_MS";
|
|
12
|
+
/** Unscoped override for the runner log directory. */
|
|
13
|
+
declare const LOG_DIR_ENV = "DOOM_RUNNER_LOG_DIR";
|
|
14
|
+
/** A bash call still running at this point is promoted to a named runner. */
|
|
15
|
+
declare const DEFAULT_BG_THRESHOLD_MS = 60000;
|
|
16
|
+
/** Tool results past this size are tail-truncated and spilled to the log file. */
|
|
17
|
+
declare const DEFAULT_RESULT_MAX_BYTES = 51200;
|
|
18
|
+
/** A runner log rotates once to `.log.1` at this size. */
|
|
19
|
+
declare const DEFAULT_LOG_MAX_BYTES: number;
|
|
20
|
+
/** Retention window for logs with no live registry record. */
|
|
21
|
+
declare const DEFAULT_LOG_TTL_MS: number;
|
|
22
|
+
/** Age at which a bash call becomes a background runner. */
|
|
23
|
+
declare function getBackgroundThresholdMs(env?: NodeJS.ProcessEnv): number;
|
|
24
|
+
/** Byte ceiling for a single tool result before tail truncation kicks in. */
|
|
25
|
+
declare function getResultMaxBytes(env?: NodeJS.ProcessEnv): number;
|
|
26
|
+
/** Byte ceiling for a runner log before it rotates. */
|
|
27
|
+
declare function getLogMaxBytes(env?: NodeJS.ProcessEnv): number;
|
|
28
|
+
/** Retention window for orphaned runner logs. */
|
|
29
|
+
declare function getLogTtlMs(env?: NodeJS.ProcessEnv): number;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { BG_THRESHOLD_MS_ENV, DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, LOG_DIR_ENV, LOG_MAX_BYTES_ENV, LOG_TTL_MS_ENV, RESULT_MAX_BYTES_ENV, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes };
|
|
32
|
+
//# sourceMappingURL=config.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.mts","names":[],"sources":["../src/config.ts"],"mappings":";;;;;;;cAOa;cACA;cACA;cACA;;cAEA;;cAGA;;cAEA;;cAEA;;cAEA;;iBAQG,yBAAyB,MAAK,OAAO;;iBAKrC,kBAAkB,MAAK,OAAO;;iBAK9B,eAAe,MAAK,OAAO;;iBAK3B,YAAY,MAAK,OAAO"}
|
package/dist/config.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=`DOOM_RUNNER_BG_THRESHOLD_MS`,t=`DOOM_RUNNER_RESULT_MAX_BYTES`,n=`DOOM_RUNNER_LOG_MAX_BYTES`,r=`DOOM_RUNNER_LOG_TTL_MS`,i=`DOOM_RUNNER_LOG_DIR`,a=6e4,o=51200,s=5242880,c=6048e5;function l(e,t){let n=Number(e);return Number.isFinite(n)&&n>0?n:t}function u(t=process.env){return l(t[e],a)}function d(e=process.env){return l(e[t],o)}function f(e=process.env){return l(e[n],s)}function p(e=process.env){return l(e[r],c)}export{e as BG_THRESHOLD_MS_ENV,a as DEFAULT_BG_THRESHOLD_MS,s as DEFAULT_LOG_MAX_BYTES,c as DEFAULT_LOG_TTL_MS,o as DEFAULT_RESULT_MAX_BYTES,i as LOG_DIR_ENV,n as LOG_MAX_BYTES_ENV,r as LOG_TTL_MS_ENV,t as RESULT_MAX_BYTES_ENV,u as getBackgroundThresholdMs,f as getLogMaxBytes,p as getLogTtlMs,d as getResultMaxBytes};
|
|
2
|
+
//# sourceMappingURL=config.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["/**\n * Extension configuration, read from the environment.\n *\n * Env rather than a config file, matching doom-task: doom-pi already carries\n * per-launch state to Pi through env vars.\n */\n\nexport const BG_THRESHOLD_MS_ENV = 'DOOM_RUNNER_BG_THRESHOLD_MS';\nexport const RESULT_MAX_BYTES_ENV = 'DOOM_RUNNER_RESULT_MAX_BYTES';\nexport const LOG_MAX_BYTES_ENV = 'DOOM_RUNNER_LOG_MAX_BYTES';\nexport const LOG_TTL_MS_ENV = 'DOOM_RUNNER_LOG_TTL_MS';\n/** Unscoped override for the runner log directory. */\nexport const LOG_DIR_ENV = 'DOOM_RUNNER_LOG_DIR';\n\n/** A bash call still running at this point is promoted to a named runner. */\nexport const DEFAULT_BG_THRESHOLD_MS = 60_000;\n/** Tool results past this size are tail-truncated and spilled to the log file. */\nexport const DEFAULT_RESULT_MAX_BYTES = 51_200;\n/** A runner log rotates once to `.log.1` at this size. */\nexport const DEFAULT_LOG_MAX_BYTES = 5 * 1024 * 1024;\n/** Retention window for logs with no live registry record. */\nexport const DEFAULT_LOG_TTL_MS = 7 * 24 * 60 * 60 * 1000;\n\nfunction positiveNumber(raw: string | undefined, fallback: number): number {\n const value = Number(raw);\n return Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\n/** Age at which a bash call becomes a background runner. */\nexport function getBackgroundThresholdMs(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[BG_THRESHOLD_MS_ENV], DEFAULT_BG_THRESHOLD_MS);\n}\n\n/** Byte ceiling for a single tool result before tail truncation kicks in. */\nexport function getResultMaxBytes(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[RESULT_MAX_BYTES_ENV], DEFAULT_RESULT_MAX_BYTES);\n}\n\n/** Byte ceiling for a runner log before it rotates. */\nexport function getLogMaxBytes(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[LOG_MAX_BYTES_ENV], DEFAULT_LOG_MAX_BYTES);\n}\n\n/** Retention window for orphaned runner logs. */\nexport function getLogTtlMs(env: NodeJS.ProcessEnv = process.env): number {\n return positiveNumber(env[LOG_TTL_MS_ENV], DEFAULT_LOG_TTL_MS);\n}\n"],"mappings":"AAOA,MAAa,EAAsB,8BACtB,EAAuB,+BACvB,EAAoB,4BACpB,EAAiB,yBAEjB,EAAc,sBAGd,EAA0B,IAE1B,EAA2B,MAE3B,EAAwB,QAExB,EAAqB,OAElC,SAAS,EAAe,EAAyB,EAA0B,CACzE,IAAM,EAAQ,OAAO,CAAG,EACxB,OAAO,OAAO,SAAS,CAAK,GAAK,EAAQ,EAAI,EAAQ,CACvD,CAGA,SAAgB,EAAyB,EAAyB,QAAQ,IAAa,CACrF,OAAO,EAAe,EAAI,GAAsB,CAAuB,CACzE,CAGA,SAAgB,EAAkB,EAAyB,QAAQ,IAAa,CAC9E,OAAO,EAAe,EAAI,GAAuB,CAAwB,CAC3E,CAGA,SAAgB,EAAe,EAAyB,QAAQ,IAAa,CAC3E,OAAO,EAAe,EAAI,GAAoB,CAAqB,CACrE,CAGA,SAAgB,EAAY,EAAyB,QAAQ,IAAa,CACxE,OAAO,EAAe,EAAI,GAAiB,CAAkB,CAC/D"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../types.cjs"),t=require("../services/BashRunService/BashRunService.cjs");require("../services/BashRunService/index.cjs");const n=require("../services/Clock/SystemClock.cjs");require("../services/Clock/index.cjs");const r=require("../services/Launcher/Launcher.cjs");require("../services/Launcher/index.cjs");const i=require("../services/Lifeline/NodeLifeline.cjs");require("../services/Lifeline/index.cjs");const a=require("../services/PtyHost/PtyHost.cjs");require("../services/PtyHost/index.cjs");const o=require("../services/LogFile/LogFile.cjs");require("../services/LogFile/index.cjs");const s=require("../services/LogReader/LogReader.cjs");require("../services/LogReader/index.cjs");const c=require("../services/ProcessControl/NodeProcessControl.cjs");require("../services/ProcessControl/index.cjs");const l=require("../services/PtySpawner/NodePtySpawner.cjs");require("../services/PtySpawner/index.cjs");const u=require("../services/RunnerNamer/RunnerNamer.cjs");require("../services/RunnerNamer/index.cjs");const d=require("../services/RunnerPaths/RunnerPaths.cjs");require("../services/RunnerPaths/index.cjs");const f=require("../services/RmuxBackend/RmuxBackend.cjs");require("../services/RmuxBackend/index.cjs");const p=require("../services/RunnerRegistry/RunnerRegistry.cjs");require("../services/RunnerRegistry/index.cjs");const m=require("../services/Spawner/NodeSpawner.cjs");require("../services/Spawner/index.cjs");let h=require("inversify");require("reflect-metadata/lite");function g(){let g=new h.Container;return g.bind(e.TYPES.Clock).to(n.SystemClock).inSingletonScope(),g.bind(e.TYPES.Spawner).to(m.NodeSpawner).inSingletonScope(),g.bind(e.TYPES.ProcessControl).to(c.NodeProcessControl).inSingletonScope(),g.bind(e.TYPES.PtySpawner).to(l.NodePtySpawner).inSingletonScope(),g.bind(e.TYPES.RunnerPaths).to(d.RunnerPaths).inSingletonScope(),g.bind(e.TYPES.Lifeline).to(i.NodeLifeline).inSingletonScope(),g.bind(e.TYPES.ProcessRegistry).toDynamicValue(()=>p.createDefaultProcessRegistry()).inSingletonScope(),g.bind(e.TYPES.RunnerRegistry).to(p.RunnerRegistry).inSingletonScope(),g.bind(e.TYPES.RunnerNamer).to(u.RunnerNamer).inSingletonScope(),g.bind(e.TYPES.LogFile).to(o.LogFile).inSingletonScope(),g.bind(e.TYPES.LogReader).to(s.LogReader).inSingletonScope(),g.bind(e.TYPES.Launcher).to(r.Launcher).inSingletonScope(),g.bind(e.TYPES.RmuxBackend).to(f.RmuxBackend).inSingletonScope(),g.bind(e.TYPES.PtyHost).to(a.PtyHost).inSingletonScope(),g.bind(e.TYPES.BashRunService).to(t.BashRunService).inSingletonScope(),g}exports.createRunnerContainer=g;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Container","TYPES","SystemClock","NodeSpawner","NodeProcessControl","NodePtySpawner","RunnerPaths","NodeLifeline","createDefaultProcessRegistry","RunnerRegistry","RunnerNamer","LogFile","LogReader","Launcher","RmuxBackend","PtyHost","BashRunService"],"sources":["../../src/container/index.ts"],"sourcesContent":["import { Container } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { BashRunService, type IBashRunService } from '../services/BashRunService/index.ts';\nimport { type IClock, SystemClock } from '../services/Clock/index.ts';\nimport { type ILauncher, Launcher } from '../services/Launcher/index.ts';\nimport { type ILifeline, NodeLifeline } from '../services/Lifeline/index.ts';\nimport { type IPtyHost, PtyHost } from '../services/PtyHost/index.ts';\nimport { type ILogFile, LogFile } from '../services/LogFile/index.ts';\nimport { type ILogReader, LogReader } from '../services/LogReader/index.ts';\nimport { type IProcessControl, NodeProcessControl } from '../services/ProcessControl/index.ts';\nimport { type IPtySpawner, NodePtySpawner } from '../services/PtySpawner/index.ts';\nimport { type IRunnerNamer, RunnerNamer } from '../services/RunnerNamer/index.ts';\nimport { type IRunnerPaths, RunnerPaths } from '../services/RunnerPaths/index.ts';\nimport { type IRmuxBackend, RmuxBackend } from '../services/RmuxBackend/index.ts';\nimport {\n createDefaultProcessRegistry,\n type IRunnerRegistry,\n type ProcessRegistryPort,\n RunnerRegistry,\n} from '../services/RunnerRegistry/index.ts';\nimport { type ISpawner, NodeSpawner } from '../services/Spawner/index.ts';\nimport { TYPES } from '../types.ts';\n\n/**\n * Builds the extension's service graph.\n *\n * A factory rather than a module-level singleton: the extension owns one\n * container per session, and tests get a fresh graph they can rebind ports on\n * without leaking state between cases.\n */\nexport function createRunnerContainer(): Container {\n const container = new Container();\n\n container.bind<IClock>(TYPES.Clock).to(SystemClock).inSingletonScope();\n container.bind<ISpawner>(TYPES.Spawner).to(NodeSpawner).inSingletonScope();\n container.bind<IProcessControl>(TYPES.ProcessControl).to(NodeProcessControl).inSingletonScope();\n container.bind<IPtySpawner>(TYPES.PtySpawner).to(NodePtySpawner).inSingletonScope();\n\n container.bind<IRunnerPaths>(TYPES.RunnerPaths).to(RunnerPaths).inSingletonScope();\n container.bind<ILifeline>(TYPES.Lifeline).to(NodeLifeline).inSingletonScope();\n // Dynamic value rather than a class binding: opening the SQLite registry is\n // deferred until something actually needs a runner.\n container\n .bind<ProcessRegistryPort>(TYPES.ProcessRegistry)\n .toDynamicValue(() => createDefaultProcessRegistry())\n .inSingletonScope();\n container.bind<IRunnerRegistry>(TYPES.RunnerRegistry).to(RunnerRegistry).inSingletonScope();\n container.bind<IRunnerNamer>(TYPES.RunnerNamer).to(RunnerNamer).inSingletonScope();\n container.bind<ILogFile>(TYPES.LogFile).to(LogFile).inSingletonScope();\n container.bind<ILogReader>(TYPES.LogReader).to(LogReader).inSingletonScope();\n container.bind<ILauncher>(TYPES.Launcher).to(Launcher).inSingletonScope();\n container.bind<IRmuxBackend>(TYPES.RmuxBackend).to(RmuxBackend).inSingletonScope();\n container.bind<IPtyHost>(TYPES.PtyHost).to(PtyHost).inSingletonScope();\n container.bind<IBashRunService>(TYPES.BashRunService).to(BashRunService).inSingletonScope();\n\n return container;\n}\n"],"mappings":"yiDA8BA,SAAgB,GAAmC,CACjD,IAAM,EAAY,IAAIA,EAAAA,UAwBtB,OAtBA,EAAU,KAAaC,EAAAA,MAAM,KAAK,CAAC,CAAC,GAAGC,EAAAA,WAAW,CAAC,CAAC,iBAAiB,EACrE,EAAU,KAAeD,EAAAA,MAAM,OAAO,CAAC,CAAC,GAAGE,EAAAA,WAAW,CAAC,CAAC,iBAAiB,EACzE,EAAU,KAAsBF,EAAAA,MAAM,cAAc,CAAC,CAAC,GAAGG,EAAAA,kBAAkB,CAAC,CAAC,iBAAiB,EAC9F,EAAU,KAAkBH,EAAAA,MAAM,UAAU,CAAC,CAAC,GAAGI,EAAAA,cAAc,CAAC,CAAC,iBAAiB,EAElF,EAAU,KAAmBJ,EAAAA,MAAM,WAAW,CAAC,CAAC,GAAGK,EAAAA,WAAW,CAAC,CAAC,iBAAiB,EACjF,EAAU,KAAgBL,EAAAA,MAAM,QAAQ,CAAC,CAAC,GAAGM,EAAAA,YAAY,CAAC,CAAC,iBAAiB,EAG5E,EACG,KAA0BN,EAAAA,MAAM,eAAe,CAAC,CAChD,mBAAqBO,EAAAA,6BAA6B,CAAC,CAAC,CACpD,iBAAiB,EACpB,EAAU,KAAsBP,EAAAA,MAAM,cAAc,CAAC,CAAC,GAAGQ,EAAAA,cAAc,CAAC,CAAC,iBAAiB,EAC1F,EAAU,KAAmBR,EAAAA,MAAM,WAAW,CAAC,CAAC,GAAGS,EAAAA,WAAW,CAAC,CAAC,iBAAiB,EACjF,EAAU,KAAeT,EAAAA,MAAM,OAAO,CAAC,CAAC,GAAGU,EAAAA,OAAO,CAAC,CAAC,iBAAiB,EACrE,EAAU,KAAiBV,EAAAA,MAAM,SAAS,CAAC,CAAC,GAAGW,EAAAA,SAAS,CAAC,CAAC,iBAAiB,EAC3E,EAAU,KAAgBX,EAAAA,MAAM,QAAQ,CAAC,CAAC,GAAGY,EAAAA,QAAQ,CAAC,CAAC,iBAAiB,EACxE,EAAU,KAAmBZ,EAAAA,MAAM,WAAW,CAAC,CAAC,GAAGa,EAAAA,WAAW,CAAC,CAAC,iBAAiB,EACjF,EAAU,KAAeb,EAAAA,MAAM,OAAO,CAAC,CAAC,GAAGc,EAAAA,OAAO,CAAC,CAAC,iBAAiB,EACrE,EAAU,KAAsBd,EAAAA,MAAM,cAAc,CAAC,CAAC,GAAGe,EAAAA,cAAc,CAAC,CAAC,iBAAiB,EAEnF,CACT"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import "reflect-metadata/lite";
|
|
2
|
+
import { Container } from "inversify";
|
|
3
|
+
//#region src/container/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Builds the extension's service graph.
|
|
6
|
+
*
|
|
7
|
+
* A factory rather than a module-level singleton: the extension owns one
|
|
8
|
+
* container per session, and tests get a fresh graph they can rebind ports on
|
|
9
|
+
* without leaking state between cases.
|
|
10
|
+
*/
|
|
11
|
+
declare function createRunnerContainer(): Container;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { createRunnerContainer };
|
|
14
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/container/index.ts"],"mappings":";;;;;;;;;;iBA8BgB,yBAAyB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Container } from "inversify";
|
|
2
|
+
import "reflect-metadata/lite";
|
|
3
|
+
//#region src/container/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Builds the extension's service graph.
|
|
6
|
+
*
|
|
7
|
+
* A factory rather than a module-level singleton: the extension owns one
|
|
8
|
+
* container per session, and tests get a fresh graph they can rebind ports on
|
|
9
|
+
* without leaking state between cases.
|
|
10
|
+
*/
|
|
11
|
+
declare function createRunnerContainer(): Container;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { createRunnerContainer };
|
|
14
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/container/index.ts"],"mappings":";;;;;;;;;;iBA8BgB,yBAAyB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{TYPES as e}from"../types.mjs";import{BashRunService as t}from"../services/BashRunService/BashRunService.mjs";import"../services/BashRunService/index.mjs";import{SystemClock as n}from"../services/Clock/SystemClock.mjs";import"../services/Clock/index.mjs";import{Launcher as r}from"../services/Launcher/Launcher.mjs";import"../services/Launcher/index.mjs";import{NodeLifeline as i}from"../services/Lifeline/NodeLifeline.mjs";import"../services/Lifeline/index.mjs";import{PtyHost as a}from"../services/PtyHost/PtyHost.mjs";import"../services/PtyHost/index.mjs";import{LogFile as o}from"../services/LogFile/LogFile.mjs";import"../services/LogFile/index.mjs";import{LogReader as s}from"../services/LogReader/LogReader.mjs";import"../services/LogReader/index.mjs";import{NodeProcessControl as c}from"../services/ProcessControl/NodeProcessControl.mjs";import"../services/ProcessControl/index.mjs";import{NodePtySpawner as l}from"../services/PtySpawner/NodePtySpawner.mjs";import"../services/PtySpawner/index.mjs";import{RunnerNamer as u}from"../services/RunnerNamer/RunnerNamer.mjs";import"../services/RunnerNamer/index.mjs";import{RunnerPaths as d}from"../services/RunnerPaths/RunnerPaths.mjs";import"../services/RunnerPaths/index.mjs";import{RmuxBackend as f}from"../services/RmuxBackend/RmuxBackend.mjs";import"../services/RmuxBackend/index.mjs";import{RunnerRegistry as p,createDefaultProcessRegistry as m}from"../services/RunnerRegistry/RunnerRegistry.mjs";import"../services/RunnerRegistry/index.mjs";import{NodeSpawner as h}from"../services/Spawner/NodeSpawner.mjs";import"../services/Spawner/index.mjs";import{Container as g}from"inversify";import"reflect-metadata/lite";function _(){let _=new g;return _.bind(e.Clock).to(n).inSingletonScope(),_.bind(e.Spawner).to(h).inSingletonScope(),_.bind(e.ProcessControl).to(c).inSingletonScope(),_.bind(e.PtySpawner).to(l).inSingletonScope(),_.bind(e.RunnerPaths).to(d).inSingletonScope(),_.bind(e.Lifeline).to(i).inSingletonScope(),_.bind(e.ProcessRegistry).toDynamicValue(()=>m()).inSingletonScope(),_.bind(e.RunnerRegistry).to(p).inSingletonScope(),_.bind(e.RunnerNamer).to(u).inSingletonScope(),_.bind(e.LogFile).to(o).inSingletonScope(),_.bind(e.LogReader).to(s).inSingletonScope(),_.bind(e.Launcher).to(r).inSingletonScope(),_.bind(e.RmuxBackend).to(f).inSingletonScope(),_.bind(e.PtyHost).to(a).inSingletonScope(),_.bind(e.BashRunService).to(t).inSingletonScope(),_}export{_ as createRunnerContainer};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/container/index.ts"],"sourcesContent":["import { Container } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { BashRunService, type IBashRunService } from '../services/BashRunService/index.ts';\nimport { type IClock, SystemClock } from '../services/Clock/index.ts';\nimport { type ILauncher, Launcher } from '../services/Launcher/index.ts';\nimport { type ILifeline, NodeLifeline } from '../services/Lifeline/index.ts';\nimport { type IPtyHost, PtyHost } from '../services/PtyHost/index.ts';\nimport { type ILogFile, LogFile } from '../services/LogFile/index.ts';\nimport { type ILogReader, LogReader } from '../services/LogReader/index.ts';\nimport { type IProcessControl, NodeProcessControl } from '../services/ProcessControl/index.ts';\nimport { type IPtySpawner, NodePtySpawner } from '../services/PtySpawner/index.ts';\nimport { type IRunnerNamer, RunnerNamer } from '../services/RunnerNamer/index.ts';\nimport { type IRunnerPaths, RunnerPaths } from '../services/RunnerPaths/index.ts';\nimport { type IRmuxBackend, RmuxBackend } from '../services/RmuxBackend/index.ts';\nimport {\n createDefaultProcessRegistry,\n type IRunnerRegistry,\n type ProcessRegistryPort,\n RunnerRegistry,\n} from '../services/RunnerRegistry/index.ts';\nimport { type ISpawner, NodeSpawner } from '../services/Spawner/index.ts';\nimport { TYPES } from '../types.ts';\n\n/**\n * Builds the extension's service graph.\n *\n * A factory rather than a module-level singleton: the extension owns one\n * container per session, and tests get a fresh graph they can rebind ports on\n * without leaking state between cases.\n */\nexport function createRunnerContainer(): Container {\n const container = new Container();\n\n container.bind<IClock>(TYPES.Clock).to(SystemClock).inSingletonScope();\n container.bind<ISpawner>(TYPES.Spawner).to(NodeSpawner).inSingletonScope();\n container.bind<IProcessControl>(TYPES.ProcessControl).to(NodeProcessControl).inSingletonScope();\n container.bind<IPtySpawner>(TYPES.PtySpawner).to(NodePtySpawner).inSingletonScope();\n\n container.bind<IRunnerPaths>(TYPES.RunnerPaths).to(RunnerPaths).inSingletonScope();\n container.bind<ILifeline>(TYPES.Lifeline).to(NodeLifeline).inSingletonScope();\n // Dynamic value rather than a class binding: opening the SQLite registry is\n // deferred until something actually needs a runner.\n container\n .bind<ProcessRegistryPort>(TYPES.ProcessRegistry)\n .toDynamicValue(() => createDefaultProcessRegistry())\n .inSingletonScope();\n container.bind<IRunnerRegistry>(TYPES.RunnerRegistry).to(RunnerRegistry).inSingletonScope();\n container.bind<IRunnerNamer>(TYPES.RunnerNamer).to(RunnerNamer).inSingletonScope();\n container.bind<ILogFile>(TYPES.LogFile).to(LogFile).inSingletonScope();\n container.bind<ILogReader>(TYPES.LogReader).to(LogReader).inSingletonScope();\n container.bind<ILauncher>(TYPES.Launcher).to(Launcher).inSingletonScope();\n container.bind<IRmuxBackend>(TYPES.RmuxBackend).to(RmuxBackend).inSingletonScope();\n container.bind<IPtyHost>(TYPES.PtyHost).to(PtyHost).inSingletonScope();\n container.bind<IBashRunService>(TYPES.BashRunService).to(BashRunService).inSingletonScope();\n\n return container;\n}\n"],"mappings":"+oDA8BA,SAAgB,GAAmC,CACjD,IAAM,EAAY,IAAI,EAwBtB,OAtBA,EAAU,KAAa,EAAM,KAAK,CAAC,CAAC,GAAG,CAAW,CAAC,CAAC,iBAAiB,EACrE,EAAU,KAAe,EAAM,OAAO,CAAC,CAAC,GAAG,CAAW,CAAC,CAAC,iBAAiB,EACzE,EAAU,KAAsB,EAAM,cAAc,CAAC,CAAC,GAAG,CAAkB,CAAC,CAAC,iBAAiB,EAC9F,EAAU,KAAkB,EAAM,UAAU,CAAC,CAAC,GAAG,CAAc,CAAC,CAAC,iBAAiB,EAElF,EAAU,KAAmB,EAAM,WAAW,CAAC,CAAC,GAAG,CAAW,CAAC,CAAC,iBAAiB,EACjF,EAAU,KAAgB,EAAM,QAAQ,CAAC,CAAC,GAAG,CAAY,CAAC,CAAC,iBAAiB,EAG5E,EACG,KAA0B,EAAM,eAAe,CAAC,CAChD,mBAAqB,EAA6B,CAAC,CAAC,CACpD,iBAAiB,EACpB,EAAU,KAAsB,EAAM,cAAc,CAAC,CAAC,GAAG,CAAc,CAAC,CAAC,iBAAiB,EAC1F,EAAU,KAAmB,EAAM,WAAW,CAAC,CAAC,GAAG,CAAW,CAAC,CAAC,iBAAiB,EACjF,EAAU,KAAe,EAAM,OAAO,CAAC,CAAC,GAAG,CAAO,CAAC,CAAC,iBAAiB,EACrE,EAAU,KAAiB,EAAM,SAAS,CAAC,CAAC,GAAG,CAAS,CAAC,CAAC,iBAAiB,EAC3E,EAAU,KAAgB,EAAM,QAAQ,CAAC,CAAC,GAAG,CAAQ,CAAC,CAAC,iBAAiB,EACxE,EAAU,KAAmB,EAAM,WAAW,CAAC,CAAC,GAAG,CAAW,CAAC,CAAC,iBAAiB,EACjF,EAAU,KAAe,EAAM,OAAO,CAAC,CAAC,GAAG,CAAO,CAAC,CAAC,iBAAiB,EACrE,EAAU,KAAsB,EAAM,cAAc,CAAC,CAAC,GAAG,CAAc,CAAC,CAAC,iBAAiB,EAEnF,CACT"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./config.cjs"),t=require("./types.cjs"),n=require("./container/index.cjs"),r=require("./compaction.cjs"),i=require("./ptyProvider.cjs"),a=require("./reconcile.cjs"),o=require("./tool/bashTool.cjs"),s=require("./tui/format.cjs"),c=require("./tui/runnerSpace.cjs");let l=require("@agimon-ai/doompi-extension-contracts/child-process"),u=require("@agimon-ai/doompi-telemetry"),d=require("@agimon-ai/doompi-extension-contracts/protocol"),f=require("@agimon-ai/doompi-ui/footer"),p=require("@agimon-ai/doompi-ui/leader");const m=`@agimon-ai/doompi-runner`,h=`runners`,g=`completed`,_=`stopped`,v=`doom-runner-runners`;function y(y){let b=n.createRunnerContainer(),x=b.get(t.TYPES.RunnerRegistry),S=b.get(t.TYPES.Launcher),C=b.get(t.TYPES.RmuxBackend),w=b.get(t.TYPES.LogReader),T=b.get(t.TYPES.PtyHost),E=b.get(t.TYPES.BashRunService),D=b.get(t.TYPES.RunnerPaths),O=b.get(t.TYPES.ProcessControl),k=b.get(t.TYPES.Lifeline),A,j,M=[],N,P,F,I=!1,L=!1,R=!1,z,B=!1,V=!1,H,U=new Set,W=new Set,G=e=>(F??=(0,u.createDoomTelemetry)({serviceName:`doom-runner`,packageName:`@agimon-ai/doompi-runner`,cwd:e.cwd,env:process.env,enableLogs:!0,enableTraces:!0}),F),K=(0,f.registerDoomFooterContribution)(y,{source:m,id:`runner-count`,order:10}),q=async e=>{let t=A;if(!t||L)return;let n=await x.list();if(L)return;let r=n;if(e){let e=await a.reconcileActiveRunners({registry:x,launcher:S,rmuxBackend:C,processControl:O,currentHostPid:process.pid,startup:!1,active:n});for(let t of e.errors)process.emitWarning(t);if(e.reclaimed.length>0){let t=new Set(e.reclaimed);r=n.filter(e=>!t.has(e.id))}}if(L)return;M=r.filter(e=>e.sessionId===t);let i=(j?r.filter(e=>(e.rootSessionId??e.sessionId)===j):[]).length;H!==i&&(H=i,K.update(s.formatRunnerFooterContribution(i)),N?.hasUI&&N.ui.setStatus(v,s.formatRunnerStatus(i)));let o=[...W],c=await Promise.all(o.map(e=>x.get(e,t)));if(!L)for(let[e,n]of c.entries()){let r=o[e];if(!r)continue;if(!n||n.sessionId!==t){W.delete(r);continue}if(n.state!==g||(W.delete(n.id),U.has(n.id)))continue;U.add(n.id);let i=n.exit?.reason??g,a=n.exit?.code===null||n.exit?.code===void 0?``:`, exit code ${n.exit.code}`,s=[`Background runner ${n.name} exited: ${i}${a}.`,`Runner ID: ${n.id}`,`Log: ${n.logPath}`,`Inspect: doom-runner logs ${n.id}`].join(`
|
|
2
|
+
`);y.sendMessage({customType:`doom-runner-finished`,content:s,display:!0},{triggerTurn:!0,deliverAs:`steer`}),N&&G(N).recordEvent(`doom_runner.process_finished`,{outcome:`completed`,"runner.exit_code":n.exit?.code??0,"runner.backend":n.backend,...Number.isFinite(Date.parse(n.startedAt))?{duration_ms:Math.max(0,Date.now()-Date.parse(n.startedAt))}:{}})}},J=(e=!0)=>{if(!A||!I||L)return Promise.resolve();if(z)return B=!0,V||=e,z;let t=(async()=>{let t=e;do B=!1,V=!1,await q(t),t=V;while(B&&!L)})().finally(()=>{z===t&&(z=void 0)});return z=t,t},Y=e=>{L||(N&&G(N).recordError(`doom_runner.refresh_failed`,e),process.emitWarning(`Could not refresh doom-runner: ${String(e)}`))},X=e=>{J(e).catch(Y)},Z=x.subscribe(()=>X(!1)),Q=setInterval(()=>X(!0),500);Q.unref?.(),o.registerBashTool(y,{bashRunService:E,getSessionId:()=>{if(!A)throw Error(`doom-runner requires an active Pi session`);return A},onRunnerStarted:e=>{W.add(e),X(!1)}}),r.registerRunnerCompactionRecovery(y,{getSessionId:()=>A,listBySession:e=>x.listBySession(e)}),y.registerCommand(h,{description:`Open Runner Space: background processes started by bash`,handler:async(e,t)=>{if(!t.hasUI){t.ui.notify(`/runners requires interactive mode`,`error`);return}await J(),await c.openRunnerSpace(t,{getRunners:()=>M,getPtyRun:e=>C.get(e)??T.get(e),readLog:e=>w.read(e,{lines:1e3}).text,stopRunner:async(e,t)=>{let n=M.find(t=>t.id===e);n&&(n.backend===`rmux`&&n.backendTarget?await C.stop(n.backendTarget,n.pid):await S.stop(n.pid),await x.complete(n.id,{reason:_,code:null,signal:null,stopReason:t},n.sessionId),await J())}})}}),(0,p.registerDoomLeaderContribution)(y,{source:m,bindings:[{id:`runners.open`,path:[{key:`r`,label:`runners`,order:67},{key:`r`,label:`open`,detail:`background processes`}],command:{name:h}}]}),y.on(`session_start`,async(t,n)=>{let r=n,o=G(r);o.recordEvent(`doom_runner.session_started`,{outcome:`started`}),A=r.sessionManager.getSessionId(),D.setSessionId(A),j=(0,l.resolveRootSessionId)(A),N=r,I=!1,H=void 0,U.clear(),W.clear(),await k.arm(A),P?.(),P=i.provideRunnerPty((0,d.createProtocolRuntime)({bus:y.events,source:m,sessionId:A}),{ptyHost:T,sessionId:()=>A,onError:(e,t)=>void o.recordError(`doom_runner.pty_launch_failed`,e,{"run.id":t})});let s=await x.listAll(A);for(let e of s)e.state===g?U.add(e.id):e.promoted&&W.add(e.id);let c=await a.cleanupLegacyRunnerStore({registry:x,launcher:S,rmuxBackend:C,processControl:O,currentHostPid:process.pid,paths:D}),u=await a.reconcileActiveRunners({registry:x,launcher:S,rmuxBackend:C,processControl:O,currentHostPid:process.pid,startup:!0});I=!0,await J(!1);let f=D.sweepHistory(e.getLogTtlMs()),p=[...c.errors,...u.errors,...f.errors];for(let e of p)process.emitWarning(e);let h=c.reclaimed.length+u.reclaimed.length;h>0&&r.hasUI&&r.ui.notify(`Reclaimed ${h} stale runner record(s)`,`warning`),o.recordEvent(`doom_runner.reconciled`,{"runner.reclaimed_count":h,"runner.error_count":p.length,outcome:p.length===0?`completed`:`degraded`})}),y.on(`session_shutdown`,async()=>{if(R)return;R=!0,I=!1,L=!0,clearInterval(Q),Z();let e=z;if(e)try{await e}catch(e){process.emitWarning(`Could not settle doom-runner refresh during shutdown: ${String(e)}`)}try{try{P?.(),P=void 0,await T.disposeAll()}catch(e){process.emitWarning(`Could not dispose doom-runner PTYs: ${String(e)}`)}let e=A?await x.listBySession(A):[];for(let t of e)try{let e=await a.stopRunnerProcess(t,S,C);if(!e&&O.isAlive(t.pid)){process.emitWarning(`Could not stop runner ${t.id} during session shutdown`);continue}await x.complete(t.id,{reason:_,code:null,signal:e?`SIGTERM`:null,stopReason:`session ended`},t.sessionId)}catch(e){process.emitWarning(`Could not clean up runner ${t.id}: ${String(e)}`)}}finally{k.dispose(),K.dispose(),N?.hasUI&&N.ui.setStatus(v,void 0),x.close(),await F?.recordEvent(`doom_runner.session_finished`,{outcome:`stopped`}),await F?.shutdown(),F=void 0}})}exports.runnerExtension=y;
|
|
3
|
+
//# sourceMappingURL=extension.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.cjs","names":["createRunnerContainer","TYPES","createDoomTelemetry","registerDoomFooterContribution","reconcileActiveRunners","formatRunnerFooterContribution","formatRunnerStatus","openRunnerSpace","resolveRootSessionId","provideRunnerPty","createProtocolRuntime","cleanupLegacyRunnerStore","getLogTtlMs","stopRunnerProcess"],"sources":["../src/extension.ts"],"sourcesContent":["import { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { createProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport { registerDoomFooterContribution } from '@agimon-ai/doompi-ui/footer';\nimport { registerDoomLeaderContribution } from '@agimon-ai/doompi-ui/leader';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { getLogTtlMs } from './config.ts';\nimport { createRunnerContainer } from './container/index.ts';\nimport { provideRunnerPty } from './ptyProvider.ts';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from './reconcile.ts';\nimport type { IBashRunService } from './services/BashRunService/index.ts';\nimport type { ILauncher } from './services/Launcher/index.ts';\nimport type { ILifeline } from './services/Lifeline/index.ts';\nimport type { ILogReader } from './services/LogReader/index.ts';\nimport type { IProcessControl } from './services/ProcessControl/index.ts';\nimport type { IPtyHost } from './services/PtyHost/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';\nimport { registerBashTool } from './tool/bashTool.ts';\nimport { registerRunnerCompactionRecovery } from './compaction.ts';\nimport { formatRunnerFooterContribution, formatRunnerStatus } from './tui/format.ts';\nimport { openRunnerSpace } from './tui/runnerSpace.ts';\nimport { TYPES } from './types.ts';\n\nconst LEADER_SOURCE = '@agimon-ai/doompi-runner';\n/** After doom-task's `t` (65) and before the core help group (70). */\nconst LEADER_GROUP_ORDER = 67;\nconst COMMAND_NAME = 'runners';\nconst ERR_REQUIRES_INTERACTIVE = '/runners requires interactive mode';\n\nconst SESSION_START_EVENT = 'session_start';\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\nconst RUNNER_FINISHED_MESSAGE = 'doom-runner-finished';\nconst COMPLETED_STATE = 'completed';\nconst RMUX_BACKEND = 'rmux';\nconst STOPPED_REASON = 'stopped';\nconst RUNNER_STATUS_KEY = 'doom-runner-runners';\nconst RUNNER_FOOTER_ORDER = 10;\nconst RUNNER_STATUS_POLL_MS = 500;\n\n/**\n * doom-runner: replaces pi's `bash` tool with a supervised one and provides a\n * CLI for anything it leaves running.\n */\nexport function runnerExtension(pi: ExtensionAPI): void {\n const container = createRunnerContainer();\n const registry = container.get<IRunnerRegistry>(TYPES.RunnerRegistry);\n const launcher = container.get<ILauncher>(TYPES.Launcher);\n const rmuxBackend = container.get<IRmuxBackend>(TYPES.RmuxBackend);\n const logReader = container.get<ILogReader>(TYPES.LogReader);\n const ptyHost = container.get<IPtyHost>(TYPES.PtyHost);\n const bashRunService = container.get<IBashRunService>(TYPES.BashRunService);\n const paths = container.get<IRunnerPaths>(TYPES.RunnerPaths);\n const processControl = container.get<IProcessControl>(TYPES.ProcessControl);\n const lifeline = container.get<ILifeline>(TYPES.Lifeline);\n\n let sessionId: string | undefined;\n let rootSessionId: string | undefined;\n let runners: RunnerRecord[] = [];\n let sessionContext: ExtensionContext | undefined;\n let disposePtyProvider: (() => void) | undefined;\n let telemetry: DoomTelemetry | undefined;\n let sessionReady = false;\n let disposed = false;\n let shutdownStarted = false;\n let refreshInFlight: Promise<void> | undefined;\n let refreshQueued = false;\n let queuedReconciliation = false;\n let lastRunnerCount: number | undefined;\n const notifiedRunnerIds = new Set<string>();\n const pendingPromotedRunnerIds = new Set<string>();\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-runner',\n packageName: '@agimon-ai/doompi-runner',\n cwd: ctx.cwd,\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\n };\n const footerContribution = registerDoomFooterContribution(pi, {\n source: LEADER_SOURCE,\n id: 'runner-count',\n order: RUNNER_FOOTER_ORDER,\n });\n\n /** Performs one bounded pass over active state and explicitly monitored runners. */\n const refreshNow = async (shouldReconcile: boolean): Promise<void> => {\n const activeSessionId = sessionId;\n if (!activeSessionId || disposed) return;\n\n const active = await registry.list();\n if (disposed) return;\n let visibleActive = active;\n if (shouldReconcile) {\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: false,\n active,\n });\n for (const error of reconciled.errors) process.emitWarning(error);\n if (reconciled.reclaimed.length > 0) {\n const reclaimedIds = new Set(reconciled.reclaimed);\n visibleActive = active.filter((record) => !reclaimedIds.has(record.id));\n }\n }\n if (disposed) return;\n\n runners = visibleActive.filter((record) => record.sessionId === activeSessionId);\n const rootRunners = rootSessionId\n ? visibleActive.filter((record) => (record.rootSessionId ?? record.sessionId) === rootSessionId)\n : [];\n const runnerCount = rootRunners.length;\n if (lastRunnerCount !== runnerCount) {\n lastRunnerCount = runnerCount;\n footerContribution.update(formatRunnerFooterContribution(runnerCount));\n if (sessionContext?.hasUI) sessionContext.ui.setStatus(RUNNER_STATUS_KEY, formatRunnerStatus(runnerCount));\n }\n\n const pendingIds = [...pendingPromotedRunnerIds];\n const monitored = await Promise.all(pendingIds.map((id) => registry.get(id, activeSessionId)));\n if (disposed) return;\n for (const [index, record] of monitored.entries()) {\n const id = pendingIds[index];\n if (!id) continue;\n if (!record || record.sessionId !== activeSessionId) {\n pendingPromotedRunnerIds.delete(id);\n continue;\n }\n if (record.state !== COMPLETED_STATE) continue;\n pendingPromotedRunnerIds.delete(record.id);\n if (notifiedRunnerIds.has(record.id)) continue;\n notifiedRunnerIds.add(record.id);\n const outcome = record.exit?.reason ?? COMPLETED_STATE;\n const code =\n record.exit?.code === null || record.exit?.code === undefined ? '' : `, exit code ${record.exit.code}`;\n const content = [\n `Background runner ${record.name} exited: ${outcome}${code}.`,\n `Runner ID: ${record.id}`,\n `Log: ${record.logPath}`,\n `Inspect: doom-runner logs ${record.id}`,\n ].join('\\n');\n pi.sendMessage(\n { customType: RUNNER_FINISHED_MESSAGE, content, display: true },\n { triggerTurn: true, deliverAs: 'steer' },\n );\n if (sessionContext) {\n void getTelemetry(sessionContext).recordEvent('doom_runner.process_finished', {\n outcome: 'completed',\n 'runner.exit_code': record.exit?.code ?? 0,\n 'runner.backend': record.backend,\n ...(Number.isFinite(Date.parse(record.startedAt))\n ? { duration_ms: Math.max(0, Date.now() - Date.parse(record.startedAt)) }\n : {}),\n });\n }\n }\n };\n\n /** Coalesces timer and event triggers without losing a requested reconciliation pass. */\n const refresh = (shouldReconcile = true): Promise<void> => {\n if (!sessionId || !sessionReady || disposed) return Promise.resolve();\n if (refreshInFlight) {\n refreshQueued = true;\n queuedReconciliation ||= shouldReconcile;\n return refreshInFlight;\n }\n\n const execution = (async () => {\n let reconcileNext = shouldReconcile;\n do {\n refreshQueued = false;\n queuedReconciliation = false;\n await refreshNow(reconcileNext);\n reconcileNext = queuedReconciliation;\n } while (refreshQueued && !disposed);\n })().finally(() => {\n if (refreshInFlight === execution) refreshInFlight = undefined;\n });\n refreshInFlight = execution;\n return execution;\n };\n\n const reportRefreshError = (error: unknown): void => {\n if (disposed) return;\n if (sessionContext) void getTelemetry(sessionContext).recordError('doom_runner.refresh_failed', error);\n process.emitWarning(`Could not refresh doom-runner: ${String(error)}`);\n };\n const scheduleRefresh = (shouldReconcile: boolean): void => {\n void refresh(shouldReconcile).catch(reportRefreshError);\n };\n const unsubscribeRegistry = registry.subscribe(() => scheduleRefresh(false));\n const statusPoll = setInterval(() => scheduleRefresh(true), RUNNER_STATUS_POLL_MS);\n statusPoll.unref?.();\n\n registerBashTool(pi, {\n bashRunService,\n getSessionId: () => {\n if (!sessionId) throw new Error('doom-runner requires an active Pi session');\n return sessionId;\n },\n onRunnerStarted: (id) => {\n pendingPromotedRunnerIds.add(id);\n scheduleRefresh(false);\n },\n });\n\n registerRunnerCompactionRecovery(pi, {\n getSessionId: () => sessionId,\n listBySession: (activeSessionId) => registry.listBySession(activeSessionId),\n });\n\n pi.registerCommand(COMMAND_NAME, {\n description: 'Open Runner Space: background processes started by bash',\n handler: async (_args, ctx) => {\n if (!ctx.hasUI) {\n ctx.ui.notify(ERR_REQUIRES_INTERACTIVE, 'error');\n return;\n }\n await refresh();\n await openRunnerSpace(ctx, {\n getRunners: () => runners,\n getPtyRun: (name) => rmuxBackend.get(name) ?? ptyHost.get(name),\n readLog: (logPath) => logReader.read(logPath, { lines: 1_000 }).text,\n stopRunner: async (id, reason) => {\n const record = runners.find((candidate) => candidate.id === id);\n if (!record) return;\n if (record.backend === RMUX_BACKEND && record.backendTarget) {\n await rmuxBackend.stop(record.backendTarget, record.pid);\n } else await launcher.stop(record.pid);\n await registry.complete(\n record.id,\n { reason: STOPPED_REASON, code: null, signal: null, stopReason: reason },\n record.sessionId,\n );\n await refresh();\n },\n });\n },\n });\n\n registerDoomLeaderContribution(pi, {\n source: LEADER_SOURCE,\n bindings: [\n {\n id: 'runners.open',\n path: [\n { key: 'r', label: 'runners', order: LEADER_GROUP_ORDER },\n { key: 'r', label: 'open', detail: 'background processes' },\n ],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n\n pi.on(SESSION_START_EVENT, async (_event, ctx) => {\n const context = ctx as ExtensionContext;\n const activeTelemetry = getTelemetry(context);\n void activeTelemetry.recordEvent('doom_runner.session_started', { outcome: 'started' });\n sessionId = context.sessionManager.getSessionId();\n paths.setSessionId(sessionId);\n rootSessionId = resolveRootSessionId(sessionId);\n sessionContext = context;\n sessionReady = false;\n lastRunnerCount = undefined;\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n // Awaited before anything can launch, so every runner this session starts\n // finds a lifeline it can connect to rather than a socket that is not\n // listening yet, which would read as an owner that is already gone.\n await lifeline.arm(sessionId);\n\n // This package owns the only pty in the workspace, so it lends one to any\n // extension that needs a command the user can watch and answer.\n disposePtyProvider?.();\n disposePtyProvider = provideRunnerPty(createProtocolRuntime({ bus: pi.events, source: LEADER_SOURCE, sessionId }), {\n ptyHost,\n sessionId: () => sessionId,\n onError: (error, id) =>\n void activeTelemetry.recordError('doom_runner.pty_launch_failed', error, { 'run.id': id }),\n });\n\n const retained = await registry.listAll(sessionId);\n for (const record of retained) {\n if (record.state === COMPLETED_STATE) notifiedRunnerIds.add(record.id);\n else if (record.promoted) pendingPromotedRunnerIds.add(record.id);\n }\n const legacy = await cleanupLegacyRunnerStore({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n paths,\n });\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: true,\n });\n sessionReady = true;\n await refresh(false);\n const sweep = paths.sweepHistory(getLogTtlMs());\n const errors = [...legacy.errors, ...reconciled.errors, ...sweep.errors];\n for (const error of errors) process.emitWarning(error);\n const reclaimedCount = legacy.reclaimed.length + reconciled.reclaimed.length;\n if (reclaimedCount > 0 && context.hasUI) {\n context.ui.notify(`Reclaimed ${reclaimedCount} stale runner record(s)`, 'warning');\n }\n void activeTelemetry.recordEvent('doom_runner.reconciled', {\n 'runner.reclaimed_count': reclaimedCount,\n 'runner.error_count': errors.length,\n outcome: errors.length === 0 ? 'completed' : 'degraded',\n });\n });\n\n pi.on(SESSION_SHUTDOWN_EVENT, async () => {\n if (shutdownStarted) return;\n shutdownStarted = true;\n sessionReady = false;\n disposed = true;\n clearInterval(statusPoll);\n unsubscribeRegistry();\n const activeRefresh = refreshInFlight;\n if (activeRefresh) {\n try {\n await activeRefresh;\n } catch (error) {\n process.emitWarning(`Could not settle doom-runner refresh during shutdown: ${String(error)}`);\n }\n }\n try {\n try {\n disposePtyProvider?.();\n disposePtyProvider = undefined;\n await ptyHost.disposeAll();\n } catch (error) {\n process.emitWarning(`Could not dispose doom-runner PTYs: ${String(error)}`);\n }\n const owned = sessionId ? await registry.listBySession(sessionId) : [];\n for (const record of owned) {\n try {\n const stopped = await stopRunnerProcess(record, launcher, rmuxBackend);\n if (!stopped && processControl.isAlive(record.pid)) {\n process.emitWarning(`Could not stop runner ${record.id} during session shutdown`);\n continue;\n }\n await registry.complete(\n record.id,\n {\n reason: STOPPED_REASON,\n code: null,\n signal: stopped ? 'SIGTERM' : null,\n stopReason: 'session ended',\n },\n record.sessionId,\n );\n } catch (error) {\n process.emitWarning(`Could not clean up runner ${record.id}: ${String(error)}`);\n }\n }\n } finally {\n // Last, and in `finally`: closing the lifeline reaps anything the loop\n // above failed to stop, so a partial cleanup still leaves nothing behind.\n lifeline.dispose();\n footerContribution.dispose();\n if (sessionContext?.hasUI) sessionContext.ui.setStatus(RUNNER_STATUS_KEY, undefined);\n registry.close();\n await telemetry?.recordEvent('doom_runner.session_finished', { outcome: 'stopped' });\n await telemetry?.shutdown();\n telemetry = undefined;\n }\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
//#region src/extension.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* doom-runner: replaces pi's `bash` tool with a supervised one and provides a
|
|
5
|
+
* CLI for anything it leaves running.
|
|
6
|
+
*/
|
|
7
|
+
declare function runnerExtension(pi: ExtensionAPI): void;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { runnerExtension };
|
|
10
|
+
//# sourceMappingURL=extension.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.d.cts","names":[],"sources":["../src/extension.ts"],"mappings":";;;;;;iBA6CgB,gBAAgB,IAAI"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
//#region src/extension.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* doom-runner: replaces pi's `bash` tool with a supervised one and provides a
|
|
5
|
+
* CLI for anything it leaves running.
|
|
6
|
+
*/
|
|
7
|
+
declare function runnerExtension(pi: ExtensionAPI): void;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { runnerExtension };
|
|
10
|
+
//# sourceMappingURL=extension.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.d.mts","names":[],"sources":["../src/extension.ts"],"mappings":";;;;;;iBA6CgB,gBAAgB,IAAI"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{getLogTtlMs as e}from"./config.mjs";import{TYPES as t}from"./types.mjs";import{createRunnerContainer as n}from"./container/index.mjs";import{registerRunnerCompactionRecovery as r}from"./compaction.mjs";import{provideRunnerPty as i}from"./ptyProvider.mjs";import{cleanupLegacyRunnerStore as a,reconcileActiveRunners as o,stopRunnerProcess as s}from"./reconcile.mjs";import{registerBashTool as c}from"./tool/bashTool.mjs";import{formatRunnerFooterContribution as l,formatRunnerStatus as u}from"./tui/format.mjs";import{openRunnerSpace as d}from"./tui/runnerSpace.mjs";import{resolveRootSessionId as f}from"@agimon-ai/doompi-extension-contracts/child-process";import{createDoomTelemetry as p}from"@agimon-ai/doompi-telemetry";import{createProtocolRuntime as m}from"@agimon-ai/doompi-extension-contracts/protocol";import{registerDoomFooterContribution as h}from"@agimon-ai/doompi-ui/footer";import{registerDoomLeaderContribution as g}from"@agimon-ai/doompi-ui/leader";const _=`@agimon-ai/doompi-runner`,v=`runners`,y=`completed`,b=`stopped`,x=`doom-runner-runners`;function S(S){let C=n(),w=C.get(t.RunnerRegistry),T=C.get(t.Launcher),E=C.get(t.RmuxBackend),D=C.get(t.LogReader),O=C.get(t.PtyHost),k=C.get(t.BashRunService),A=C.get(t.RunnerPaths),j=C.get(t.ProcessControl),M=C.get(t.Lifeline),N,P,F=[],I,L,R,z=!1,B=!1,V=!1,H,U=!1,W=!1,G,K=new Set,q=new Set,J=e=>(R??=p({serviceName:`doom-runner`,packageName:`@agimon-ai/doompi-runner`,cwd:e.cwd,env:process.env,enableLogs:!0,enableTraces:!0}),R),Y=h(S,{source:_,id:`runner-count`,order:10}),X=async e=>{let t=N;if(!t||B)return;let n=await w.list();if(B)return;let r=n;if(e){let e=await o({registry:w,launcher:T,rmuxBackend:E,processControl:j,currentHostPid:process.pid,startup:!1,active:n});for(let t of e.errors)process.emitWarning(t);if(e.reclaimed.length>0){let t=new Set(e.reclaimed);r=n.filter(e=>!t.has(e.id))}}if(B)return;F=r.filter(e=>e.sessionId===t);let i=(P?r.filter(e=>(e.rootSessionId??e.sessionId)===P):[]).length;G!==i&&(G=i,Y.update(l(i)),I?.hasUI&&I.ui.setStatus(x,u(i)));let a=[...q],s=await Promise.all(a.map(e=>w.get(e,t)));if(!B)for(let[e,n]of s.entries()){let r=a[e];if(!r)continue;if(!n||n.sessionId!==t){q.delete(r);continue}if(n.state!==y||(q.delete(n.id),K.has(n.id)))continue;K.add(n.id);let i=n.exit?.reason??y,o=n.exit?.code===null||n.exit?.code===void 0?``:`, exit code ${n.exit.code}`,s=[`Background runner ${n.name} exited: ${i}${o}.`,`Runner ID: ${n.id}`,`Log: ${n.logPath}`,`Inspect: doom-runner logs ${n.id}`].join(`
|
|
2
|
+
`);S.sendMessage({customType:`doom-runner-finished`,content:s,display:!0},{triggerTurn:!0,deliverAs:`steer`}),I&&J(I).recordEvent(`doom_runner.process_finished`,{outcome:`completed`,"runner.exit_code":n.exit?.code??0,"runner.backend":n.backend,...Number.isFinite(Date.parse(n.startedAt))?{duration_ms:Math.max(0,Date.now()-Date.parse(n.startedAt))}:{}})}},Z=(e=!0)=>{if(!N||!z||B)return Promise.resolve();if(H)return U=!0,W||=e,H;let t=(async()=>{let t=e;do U=!1,W=!1,await X(t),t=W;while(U&&!B)})().finally(()=>{H===t&&(H=void 0)});return H=t,t},ee=e=>{B||(I&&J(I).recordError(`doom_runner.refresh_failed`,e),process.emitWarning(`Could not refresh doom-runner: ${String(e)}`))},Q=e=>{Z(e).catch(ee)},te=w.subscribe(()=>Q(!1)),$=setInterval(()=>Q(!0),500);$.unref?.(),c(S,{bashRunService:k,getSessionId:()=>{if(!N)throw Error(`doom-runner requires an active Pi session`);return N},onRunnerStarted:e=>{q.add(e),Q(!1)}}),r(S,{getSessionId:()=>N,listBySession:e=>w.listBySession(e)}),S.registerCommand(v,{description:`Open Runner Space: background processes started by bash`,handler:async(e,t)=>{if(!t.hasUI){t.ui.notify(`/runners requires interactive mode`,`error`);return}await Z(),await d(t,{getRunners:()=>F,getPtyRun:e=>E.get(e)??O.get(e),readLog:e=>D.read(e,{lines:1e3}).text,stopRunner:async(e,t)=>{let n=F.find(t=>t.id===e);n&&(n.backend===`rmux`&&n.backendTarget?await E.stop(n.backendTarget,n.pid):await T.stop(n.pid),await w.complete(n.id,{reason:b,code:null,signal:null,stopReason:t},n.sessionId),await Z())}})}}),g(S,{source:_,bindings:[{id:`runners.open`,path:[{key:`r`,label:`runners`,order:67},{key:`r`,label:`open`,detail:`background processes`}],command:{name:v}}]}),S.on(`session_start`,async(t,n)=>{let r=n,s=J(r);s.recordEvent(`doom_runner.session_started`,{outcome:`started`}),N=r.sessionManager.getSessionId(),A.setSessionId(N),P=f(N),I=r,z=!1,G=void 0,K.clear(),q.clear(),await M.arm(N),L?.(),L=i(m({bus:S.events,source:_,sessionId:N}),{ptyHost:O,sessionId:()=>N,onError:(e,t)=>void s.recordError(`doom_runner.pty_launch_failed`,e,{"run.id":t})});let c=await w.listAll(N);for(let e of c)e.state===y?K.add(e.id):e.promoted&&q.add(e.id);let l=await a({registry:w,launcher:T,rmuxBackend:E,processControl:j,currentHostPid:process.pid,paths:A}),u=await o({registry:w,launcher:T,rmuxBackend:E,processControl:j,currentHostPid:process.pid,startup:!0});z=!0,await Z(!1);let d=A.sweepHistory(e()),p=[...l.errors,...u.errors,...d.errors];for(let e of p)process.emitWarning(e);let h=l.reclaimed.length+u.reclaimed.length;h>0&&r.hasUI&&r.ui.notify(`Reclaimed ${h} stale runner record(s)`,`warning`),s.recordEvent(`doom_runner.reconciled`,{"runner.reclaimed_count":h,"runner.error_count":p.length,outcome:p.length===0?`completed`:`degraded`})}),S.on(`session_shutdown`,async()=>{if(V)return;V=!0,z=!1,B=!0,clearInterval($),te();let e=H;if(e)try{await e}catch(e){process.emitWarning(`Could not settle doom-runner refresh during shutdown: ${String(e)}`)}try{try{L?.(),L=void 0,await O.disposeAll()}catch(e){process.emitWarning(`Could not dispose doom-runner PTYs: ${String(e)}`)}let e=N?await w.listBySession(N):[];for(let t of e)try{let e=await s(t,T,E);if(!e&&j.isAlive(t.pid)){process.emitWarning(`Could not stop runner ${t.id} during session shutdown`);continue}await w.complete(t.id,{reason:b,code:null,signal:e?`SIGTERM`:null,stopReason:`session ended`},t.sessionId)}catch(e){process.emitWarning(`Could not clean up runner ${t.id}: ${String(e)}`)}}finally{M.dispose(),Y.dispose(),I?.hasUI&&I.ui.setStatus(x,void 0),w.close(),await R?.recordEvent(`doom_runner.session_finished`,{outcome:`stopped`}),await R?.shutdown(),R=void 0}})}export{S as runnerExtension};
|
|
3
|
+
//# sourceMappingURL=extension.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.mjs","names":[],"sources":["../src/extension.ts"],"sourcesContent":["import { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { createProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport { registerDoomFooterContribution } from '@agimon-ai/doompi-ui/footer';\nimport { registerDoomLeaderContribution } from '@agimon-ai/doompi-ui/leader';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { getLogTtlMs } from './config.ts';\nimport { createRunnerContainer } from './container/index.ts';\nimport { provideRunnerPty } from './ptyProvider.ts';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from './reconcile.ts';\nimport type { IBashRunService } from './services/BashRunService/index.ts';\nimport type { ILauncher } from './services/Launcher/index.ts';\nimport type { ILifeline } from './services/Lifeline/index.ts';\nimport type { ILogReader } from './services/LogReader/index.ts';\nimport type { IProcessControl } from './services/ProcessControl/index.ts';\nimport type { IPtyHost } from './services/PtyHost/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';\nimport { registerBashTool } from './tool/bashTool.ts';\nimport { registerRunnerCompactionRecovery } from './compaction.ts';\nimport { formatRunnerFooterContribution, formatRunnerStatus } from './tui/format.ts';\nimport { openRunnerSpace } from './tui/runnerSpace.ts';\nimport { TYPES } from './types.ts';\n\nconst LEADER_SOURCE = '@agimon-ai/doompi-runner';\n/** After doom-task's `t` (65) and before the core help group (70). */\nconst LEADER_GROUP_ORDER = 67;\nconst COMMAND_NAME = 'runners';\nconst ERR_REQUIRES_INTERACTIVE = '/runners requires interactive mode';\n\nconst SESSION_START_EVENT = 'session_start';\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\nconst RUNNER_FINISHED_MESSAGE = 'doom-runner-finished';\nconst COMPLETED_STATE = 'completed';\nconst RMUX_BACKEND = 'rmux';\nconst STOPPED_REASON = 'stopped';\nconst RUNNER_STATUS_KEY = 'doom-runner-runners';\nconst RUNNER_FOOTER_ORDER = 10;\nconst RUNNER_STATUS_POLL_MS = 500;\n\n/**\n * doom-runner: replaces pi's `bash` tool with a supervised one and provides a\n * CLI for anything it leaves running.\n */\nexport function runnerExtension(pi: ExtensionAPI): void {\n const container = createRunnerContainer();\n const registry = container.get<IRunnerRegistry>(TYPES.RunnerRegistry);\n const launcher = container.get<ILauncher>(TYPES.Launcher);\n const rmuxBackend = container.get<IRmuxBackend>(TYPES.RmuxBackend);\n const logReader = container.get<ILogReader>(TYPES.LogReader);\n const ptyHost = container.get<IPtyHost>(TYPES.PtyHost);\n const bashRunService = container.get<IBashRunService>(TYPES.BashRunService);\n const paths = container.get<IRunnerPaths>(TYPES.RunnerPaths);\n const processControl = container.get<IProcessControl>(TYPES.ProcessControl);\n const lifeline = container.get<ILifeline>(TYPES.Lifeline);\n\n let sessionId: string | undefined;\n let rootSessionId: string | undefined;\n let runners: RunnerRecord[] = [];\n let sessionContext: ExtensionContext | undefined;\n let disposePtyProvider: (() => void) | undefined;\n let telemetry: DoomTelemetry | undefined;\n let sessionReady = false;\n let disposed = false;\n let shutdownStarted = false;\n let refreshInFlight: Promise<void> | undefined;\n let refreshQueued = false;\n let queuedReconciliation = false;\n let lastRunnerCount: number | undefined;\n const notifiedRunnerIds = new Set<string>();\n const pendingPromotedRunnerIds = new Set<string>();\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-runner',\n packageName: '@agimon-ai/doompi-runner',\n cwd: ctx.cwd,\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\n };\n const footerContribution = registerDoomFooterContribution(pi, {\n source: LEADER_SOURCE,\n id: 'runner-count',\n order: RUNNER_FOOTER_ORDER,\n });\n\n /** Performs one bounded pass over active state and explicitly monitored runners. */\n const refreshNow = async (shouldReconcile: boolean): Promise<void> => {\n const activeSessionId = sessionId;\n if (!activeSessionId || disposed) return;\n\n const active = await registry.list();\n if (disposed) return;\n let visibleActive = active;\n if (shouldReconcile) {\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: false,\n active,\n });\n for (const error of reconciled.errors) process.emitWarning(error);\n if (reconciled.reclaimed.length > 0) {\n const reclaimedIds = new Set(reconciled.reclaimed);\n visibleActive = active.filter((record) => !reclaimedIds.has(record.id));\n }\n }\n if (disposed) return;\n\n runners = visibleActive.filter((record) => record.sessionId === activeSessionId);\n const rootRunners = rootSessionId\n ? visibleActive.filter((record) => (record.rootSessionId ?? record.sessionId) === rootSessionId)\n : [];\n const runnerCount = rootRunners.length;\n if (lastRunnerCount !== runnerCount) {\n lastRunnerCount = runnerCount;\n footerContribution.update(formatRunnerFooterContribution(runnerCount));\n if (sessionContext?.hasUI) sessionContext.ui.setStatus(RUNNER_STATUS_KEY, formatRunnerStatus(runnerCount));\n }\n\n const pendingIds = [...pendingPromotedRunnerIds];\n const monitored = await Promise.all(pendingIds.map((id) => registry.get(id, activeSessionId)));\n if (disposed) return;\n for (const [index, record] of monitored.entries()) {\n const id = pendingIds[index];\n if (!id) continue;\n if (!record || record.sessionId !== activeSessionId) {\n pendingPromotedRunnerIds.delete(id);\n continue;\n }\n if (record.state !== COMPLETED_STATE) continue;\n pendingPromotedRunnerIds.delete(record.id);\n if (notifiedRunnerIds.has(record.id)) continue;\n notifiedRunnerIds.add(record.id);\n const outcome = record.exit?.reason ?? COMPLETED_STATE;\n const code =\n record.exit?.code === null || record.exit?.code === undefined ? '' : `, exit code ${record.exit.code}`;\n const content = [\n `Background runner ${record.name} exited: ${outcome}${code}.`,\n `Runner ID: ${record.id}`,\n `Log: ${record.logPath}`,\n `Inspect: doom-runner logs ${record.id}`,\n ].join('\\n');\n pi.sendMessage(\n { customType: RUNNER_FINISHED_MESSAGE, content, display: true },\n { triggerTurn: true, deliverAs: 'steer' },\n );\n if (sessionContext) {\n void getTelemetry(sessionContext).recordEvent('doom_runner.process_finished', {\n outcome: 'completed',\n 'runner.exit_code': record.exit?.code ?? 0,\n 'runner.backend': record.backend,\n ...(Number.isFinite(Date.parse(record.startedAt))\n ? { duration_ms: Math.max(0, Date.now() - Date.parse(record.startedAt)) }\n : {}),\n });\n }\n }\n };\n\n /** Coalesces timer and event triggers without losing a requested reconciliation pass. */\n const refresh = (shouldReconcile = true): Promise<void> => {\n if (!sessionId || !sessionReady || disposed) return Promise.resolve();\n if (refreshInFlight) {\n refreshQueued = true;\n queuedReconciliation ||= shouldReconcile;\n return refreshInFlight;\n }\n\n const execution = (async () => {\n let reconcileNext = shouldReconcile;\n do {\n refreshQueued = false;\n queuedReconciliation = false;\n await refreshNow(reconcileNext);\n reconcileNext = queuedReconciliation;\n } while (refreshQueued && !disposed);\n })().finally(() => {\n if (refreshInFlight === execution) refreshInFlight = undefined;\n });\n refreshInFlight = execution;\n return execution;\n };\n\n const reportRefreshError = (error: unknown): void => {\n if (disposed) return;\n if (sessionContext) void getTelemetry(sessionContext).recordError('doom_runner.refresh_failed', error);\n process.emitWarning(`Could not refresh doom-runner: ${String(error)}`);\n };\n const scheduleRefresh = (shouldReconcile: boolean): void => {\n void refresh(shouldReconcile).catch(reportRefreshError);\n };\n const unsubscribeRegistry = registry.subscribe(() => scheduleRefresh(false));\n const statusPoll = setInterval(() => scheduleRefresh(true), RUNNER_STATUS_POLL_MS);\n statusPoll.unref?.();\n\n registerBashTool(pi, {\n bashRunService,\n getSessionId: () => {\n if (!sessionId) throw new Error('doom-runner requires an active Pi session');\n return sessionId;\n },\n onRunnerStarted: (id) => {\n pendingPromotedRunnerIds.add(id);\n scheduleRefresh(false);\n },\n });\n\n registerRunnerCompactionRecovery(pi, {\n getSessionId: () => sessionId,\n listBySession: (activeSessionId) => registry.listBySession(activeSessionId),\n });\n\n pi.registerCommand(COMMAND_NAME, {\n description: 'Open Runner Space: background processes started by bash',\n handler: async (_args, ctx) => {\n if (!ctx.hasUI) {\n ctx.ui.notify(ERR_REQUIRES_INTERACTIVE, 'error');\n return;\n }\n await refresh();\n await openRunnerSpace(ctx, {\n getRunners: () => runners,\n getPtyRun: (name) => rmuxBackend.get(name) ?? ptyHost.get(name),\n readLog: (logPath) => logReader.read(logPath, { lines: 1_000 }).text,\n stopRunner: async (id, reason) => {\n const record = runners.find((candidate) => candidate.id === id);\n if (!record) return;\n if (record.backend === RMUX_BACKEND && record.backendTarget) {\n await rmuxBackend.stop(record.backendTarget, record.pid);\n } else await launcher.stop(record.pid);\n await registry.complete(\n record.id,\n { reason: STOPPED_REASON, code: null, signal: null, stopReason: reason },\n record.sessionId,\n );\n await refresh();\n },\n });\n },\n });\n\n registerDoomLeaderContribution(pi, {\n source: LEADER_SOURCE,\n bindings: [\n {\n id: 'runners.open',\n path: [\n { key: 'r', label: 'runners', order: LEADER_GROUP_ORDER },\n { key: 'r', label: 'open', detail: 'background processes' },\n ],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n\n pi.on(SESSION_START_EVENT, async (_event, ctx) => {\n const context = ctx as ExtensionContext;\n const activeTelemetry = getTelemetry(context);\n void activeTelemetry.recordEvent('doom_runner.session_started', { outcome: 'started' });\n sessionId = context.sessionManager.getSessionId();\n paths.setSessionId(sessionId);\n rootSessionId = resolveRootSessionId(sessionId);\n sessionContext = context;\n sessionReady = false;\n lastRunnerCount = undefined;\n notifiedRunnerIds.clear();\n pendingPromotedRunnerIds.clear();\n // Awaited before anything can launch, so every runner this session starts\n // finds a lifeline it can connect to rather than a socket that is not\n // listening yet, which would read as an owner that is already gone.\n await lifeline.arm(sessionId);\n\n // This package owns the only pty in the workspace, so it lends one to any\n // extension that needs a command the user can watch and answer.\n disposePtyProvider?.();\n disposePtyProvider = provideRunnerPty(createProtocolRuntime({ bus: pi.events, source: LEADER_SOURCE, sessionId }), {\n ptyHost,\n sessionId: () => sessionId,\n onError: (error, id) =>\n void activeTelemetry.recordError('doom_runner.pty_launch_failed', error, { 'run.id': id }),\n });\n\n const retained = await registry.listAll(sessionId);\n for (const record of retained) {\n if (record.state === COMPLETED_STATE) notifiedRunnerIds.add(record.id);\n else if (record.promoted) pendingPromotedRunnerIds.add(record.id);\n }\n const legacy = await cleanupLegacyRunnerStore({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n paths,\n });\n const reconciled = await reconcileActiveRunners({\n registry,\n launcher,\n rmuxBackend,\n processControl,\n currentHostPid: process.pid,\n startup: true,\n });\n sessionReady = true;\n await refresh(false);\n const sweep = paths.sweepHistory(getLogTtlMs());\n const errors = [...legacy.errors, ...reconciled.errors, ...sweep.errors];\n for (const error of errors) process.emitWarning(error);\n const reclaimedCount = legacy.reclaimed.length + reconciled.reclaimed.length;\n if (reclaimedCount > 0 && context.hasUI) {\n context.ui.notify(`Reclaimed ${reclaimedCount} stale runner record(s)`, 'warning');\n }\n void activeTelemetry.recordEvent('doom_runner.reconciled', {\n 'runner.reclaimed_count': reclaimedCount,\n 'runner.error_count': errors.length,\n outcome: errors.length === 0 ? 'completed' : 'degraded',\n });\n });\n\n pi.on(SESSION_SHUTDOWN_EVENT, async () => {\n if (shutdownStarted) return;\n shutdownStarted = true;\n sessionReady = false;\n disposed = true;\n clearInterval(statusPoll);\n unsubscribeRegistry();\n const activeRefresh = refreshInFlight;\n if (activeRefresh) {\n try {\n await activeRefresh;\n } catch (error) {\n process.emitWarning(`Could not settle doom-runner refresh during shutdown: ${String(error)}`);\n }\n }\n try {\n try {\n disposePtyProvider?.();\n disposePtyProvider = undefined;\n await ptyHost.disposeAll();\n } catch (error) {\n process.emitWarning(`Could not dispose doom-runner PTYs: ${String(error)}`);\n }\n const owned = sessionId ? await registry.listBySession(sessionId) : [];\n for (const record of owned) {\n try {\n const stopped = await stopRunnerProcess(record, launcher, rmuxBackend);\n if (!stopped && processControl.isAlive(record.pid)) {\n process.emitWarning(`Could not stop runner ${record.id} during session shutdown`);\n continue;\n }\n await registry.complete(\n record.id,\n {\n reason: STOPPED_REASON,\n code: null,\n signal: stopped ? 'SIGTERM' : null,\n stopReason: 'session ended',\n },\n record.sessionId,\n );\n } catch (error) {\n process.emitWarning(`Could not clean up runner ${record.id}: ${String(error)}`);\n }\n }\n } finally {\n // Last, and in `finally`: closing the lifeline reaps anything the loop\n // above failed to stop, so a partial cleanup still leaves nothing behind.\n lifeline.dispose();\n footerContribution.dispose();\n if (sessionContext?.hasUI) sessionContext.ui.setStatus(RUNNER_STATUS_KEY, undefined);\n registry.close();\n await telemetry?.recordEvent('doom_runner.session_finished', { outcome: 'stopped' });\n await telemetry?.shutdown();\n telemetry = undefined;\n }\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.cjs","names":["runnerExtension"],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { runnerExtension } from '../extension.ts';\n\nexport default runnerExtension;\n"],"mappings":"AAEA,IAAA,4BAAeA,CAAAA,CAAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.mjs","names":[],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { runnerExtension } from '../extension.ts';\n\nexport default runnerExtension;\n"],"mappings":"mDAEA,IAAA,EAAe"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./config.cjs"),t=require("./types.cjs"),n=require("./services/RmuxBackend/RmuxBackend.cjs");require("./services/RmuxBackend/index.cjs");const r=require("./container/index.cjs");exports.DEFAULT_BG_THRESHOLD_MS=e.DEFAULT_BG_THRESHOLD_MS,exports.DEFAULT_LOG_MAX_BYTES=e.DEFAULT_LOG_MAX_BYTES,exports.DEFAULT_LOG_TTL_MS=e.DEFAULT_LOG_TTL_MS,exports.DEFAULT_RESULT_MAX_BYTES=e.DEFAULT_RESULT_MAX_BYTES,Object.defineProperty(exports,"RmuxBackend",{enumerable:!0,get:function(){return n.RmuxBackend}}),exports.TYPES=t.TYPES,exports.createRunnerContainer=r.createRunnerContainer,exports.getBackgroundThresholdMs=e.getBackgroundThresholdMs,exports.getLogMaxBytes=e.getLogMaxBytes,exports.getLogTtlMs=e.getLogTtlMs,exports.getResultMaxBytes=e.getResultMaxBytes;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IRmuxBackend, RmuxLaunchRequest } from "./services/RmuxBackend/types.cjs";
|
|
2
|
+
import { RmuxBackend } from "./services/RmuxBackend/RmuxBackend.cjs";
|
|
3
|
+
import "./services/RmuxBackend/index.cjs";
|
|
4
|
+
import { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes } from "./config.cjs";
|
|
5
|
+
import { createRunnerContainer } from "./container/index.cjs";
|
|
6
|
+
import { TYPES } from "./types.cjs";
|
|
7
|
+
export { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, type IRmuxBackend, RmuxBackend, type RmuxLaunchRequest, TYPES, createRunnerContainer, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IRmuxBackend, RmuxLaunchRequest } from "./services/RmuxBackend/types.mjs";
|
|
2
|
+
import { RmuxBackend } from "./services/RmuxBackend/RmuxBackend.mjs";
|
|
3
|
+
import "./services/RmuxBackend/index.mjs";
|
|
4
|
+
import { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes } from "./config.mjs";
|
|
5
|
+
import { createRunnerContainer } from "./container/index.mjs";
|
|
6
|
+
import { TYPES } from "./types.mjs";
|
|
7
|
+
export { DEFAULT_BG_THRESHOLD_MS, DEFAULT_LOG_MAX_BYTES, DEFAULT_LOG_TTL_MS, DEFAULT_RESULT_MAX_BYTES, type IRmuxBackend, RmuxBackend, type RmuxLaunchRequest, TYPES, createRunnerContainer, getBackgroundThresholdMs, getLogMaxBytes, getLogTtlMs, getResultMaxBytes };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DEFAULT_BG_THRESHOLD_MS as e,DEFAULT_LOG_MAX_BYTES as t,DEFAULT_LOG_TTL_MS as n,DEFAULT_RESULT_MAX_BYTES as r,getBackgroundThresholdMs as i,getLogMaxBytes as a,getLogTtlMs as o,getResultMaxBytes as s}from"./config.mjs";import{TYPES as c}from"./types.mjs";import{RmuxBackend as l}from"./services/RmuxBackend/RmuxBackend.mjs";import"./services/RmuxBackend/index.mjs";import{createRunnerContainer as u}from"./container/index.mjs";export{e as DEFAULT_BG_THRESHOLD_MS,t as DEFAULT_LOG_MAX_BYTES,n as DEFAULT_LOG_TTL_MS,r as DEFAULT_RESULT_MAX_BYTES,l as RmuxBackend,c as TYPES,u as createRunnerContainer,i as getBackgroundThresholdMs,a as getLogMaxBytes,o as getLogTtlMs,s as getResultMaxBytes};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@agimon-ai/doompi-extension-contracts/runner-pty");function t(e,t){return`ext:${e}:${t}`.replaceAll(/[^A-Za-z0-9._-]/gu,`-`)}function n(n,r){let i=new Map,a=e=>{let t=i.get(e);t&&(i.delete(e),t.dispose())},o=[n.provide(e.RunnerPtyLaunchProtocol,async(o,s)=>{let c=r.sessionId();if(!c)return{launched:!1,reason:`No runner session is active.`};let l=t(s.source,o.id);if(i.has(l))return{launched:!1,reason:`A run named ${o.id} is already active.`};try{let t=await r.ptyHost.launch({id:l,name:l,command:o.command,cwd:o.cwd,sessionId:c,...o.cols===void 0?{}:{cols:o.cols},...o.rows===void 0?{}:{rows:o.rows}}),s=t.onData(t=>n.notify(e.RunnerPtyData,{id:o.id,chunk:t}));return i.set(l,{run:t,dispose:s}),t.completion().then(t=>n.notify(e.RunnerPtyExit,{id:o.id,...typeof t.code==`number`?{code:t.code}:{},...t.signal?{signal:String(t.signal)}:{}})).catch(()=>n.notify(e.RunnerPtyExit,{id:o.id,code:-1})).finally(()=>a(l)),{launched:!0}}catch(e){return r.onError?.(e,o.id),{launched:!1,reason:e instanceof Error?e.message:String(e)}}}),n.onNotification(e.RunnerPtyInput,({id:e,text:n},r)=>{i.get(t(r.source,e))?.run.write(`${n}\n`)}),n.onNotification(e.RunnerPtyStop,async({id:e},n)=>{let r=t(n.source,e),o=i.get(r);o&&(a(r),await o.run.stop())})],s=!1;return()=>{if(!s){s=!0;for(let e of o)e();for(let e of i.values())e.dispose();i.clear()}}}exports.provideRunnerPty=n;
|
|
2
|
+
//# sourceMappingURL=ptyProvider.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptyProvider.cjs","names":["RunnerPtyLaunchProtocol","RunnerPtyData","RunnerPtyExit","RunnerPtyInput","RunnerPtyStop"],"sources":["../src/ptyProvider.ts"],"sourcesContent":["/**\n * Lends this package's pseudo terminals to other extensions.\n *\n * doom-runner is the only package that carries `node-pty`, and the only one that\n * knows how to keep a terminal alive for a session and tear it down with one.\n * Rather than have every extension that needs an answerable command grow its own\n * copy of that, they ask over the bus and the terminal stays here.\n *\n * Output is forwarded raw, chunk by chunk, because the caller is usually\n * rendering a tail and needs the partial line a prompt sits on. Reassembling\n * lines is the caller's problem, not the terminal's.\n *\n * AVOID:\n * - Keeping a run past the session that asked for it\n * - Swallowing an exit; a caller waiting on one would hang forever\n */\n\nimport {\n RunnerPtyData,\n RunnerPtyExit,\n RunnerPtyInput,\n RunnerPtyLaunchProtocol,\n RunnerPtyStop,\n} from '@agimon-ai/doompi-extension-contracts/runner-pty';\nimport type { ProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport type { IPtyHost, PtyRun } from './services/PtyHost/index.ts';\n\n/** Namespaced so a borrowed terminal is distinguishable in the runner list. */\nconst RUN_NAME_PREFIX = 'ext';\n\n/**\n * Collapses a caller and its run id into one safe path segment.\n *\n * The id becomes a log file name, and package-scoped sources carry a `/`, which\n * `path.join` would turn into a directory nobody created.\n */\nfunction runKey(source: string, id: string): string {\n return `${RUN_NAME_PREFIX}:${source}:${id}`.replaceAll(/[^A-Za-z0-9._-]/gu, '-');\n}\n\nexport interface PtyProviderOptions {\n ptyHost: IPtyHost;\n sessionId: () => string | undefined;\n onError?: (error: unknown, id: string) => void;\n}\n\nexport function provideRunnerPty(runtime: ProtocolRuntime, options: PtyProviderOptions): () => void {\n const runs = new Map<string, { run: PtyRun; dispose: () => void }>();\n\n const release = (id: string): void => {\n const entry = runs.get(id);\n if (!entry) return;\n runs.delete(id);\n entry.dispose();\n };\n\n const disposers = [\n runtime.provide(RunnerPtyLaunchProtocol, async (request, identity) => {\n const sessionId = options.sessionId();\n if (!sessionId) return { launched: false, reason: 'No runner session is active.' };\n // Keyed by the caller too, so two extensions choosing the same id cannot\n // collide or read each other's output.\n const key = runKey(identity.source, request.id);\n if (runs.has(key)) return { launched: false, reason: `A run named ${request.id} is already active.` };\n try {\n const run = await options.ptyHost.launch({\n id: key,\n // The host keys its runs by name, so this is the unique one rather\n // than the caller's label; two callers naming a run `install` would\n // otherwise clobber each other.\n name: key,\n command: request.command,\n cwd: request.cwd,\n sessionId,\n ...(request.cols === undefined ? {} : { cols: request.cols }),\n ...(request.rows === undefined ? {} : { rows: request.rows }),\n });\n const unsubscribe = run.onData((chunk) => runtime.notify(RunnerPtyData, { id: request.id, chunk }));\n runs.set(key, { run, dispose: unsubscribe });\n void run\n .completion()\n .then((result) =>\n runtime.notify(RunnerPtyExit, {\n id: request.id,\n ...(typeof result.code === 'number' ? { code: result.code } : {}),\n ...(result.signal ? { signal: String(result.signal) } : {}),\n }),\n )\n // A caller blocked on the exit would wait forever otherwise, so a\n // failure to observe one is still reported as an exit.\n .catch(() => runtime.notify(RunnerPtyExit, { id: request.id, code: -1 }))\n .finally(() => release(key));\n return { launched: true };\n } catch (error) {\n options.onError?.(error, request.id);\n return { launched: false, reason: error instanceof Error ? error.message : String(error) };\n }\n }),\n runtime.onNotification(RunnerPtyInput, ({ id, text }, identity) => {\n runs.get(runKey(identity.source, id))?.run.write(`${text}\\n`);\n }),\n runtime.onNotification(RunnerPtyStop, async ({ id }, identity) => {\n const key = runKey(identity.source, id);\n const entry = runs.get(key);\n if (!entry) return;\n release(key);\n await entry.run.stop();\n }),\n ];\n\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) dispose();\n for (const entry of runs.values()) entry.dispose();\n runs.clear();\n };\n}\n"],"mappings":"qIAoCA,SAAS,EAAO,EAAgB,EAAoB,CAClD,MAAO,OAAsB,EAAO,GAAG,IAAK,WAAW,oBAAqB,GAAG,CACjF,CAQA,SAAgB,EAAiB,EAA0B,EAAyC,CAClG,IAAM,EAAO,IAAI,IAEX,EAAW,GAAqB,CACpC,IAAM,EAAQ,EAAK,IAAI,CAAE,EACpB,IACL,EAAK,OAAO,CAAE,EACd,EAAM,QAAQ,EAChB,EAEM,EAAY,CAChB,EAAQ,QAAQA,EAAAA,wBAAyB,MAAO,EAAS,IAAa,CACpE,IAAM,EAAY,EAAQ,UAAU,EACpC,GAAI,CAAC,EAAW,MAAO,CAAE,SAAU,GAAO,OAAQ,8BAA+B,EAGjF,IAAM,EAAM,EAAO,EAAS,OAAQ,EAAQ,EAAE,EAC9C,GAAI,EAAK,IAAI,CAAG,EAAG,MAAO,CAAE,SAAU,GAAO,OAAQ,eAAe,EAAQ,GAAG,oBAAqB,EACpG,GAAI,CACF,IAAM,EAAM,MAAM,EAAQ,QAAQ,OAAO,CACvC,GAAI,EAIJ,KAAM,EACN,QAAS,EAAQ,QACjB,IAAK,EAAQ,IACb,YACA,GAAI,EAAQ,OAAS,IAAA,GAAY,CAAC,EAAI,CAAE,KAAM,EAAQ,IAAK,EAC3D,GAAI,EAAQ,OAAS,IAAA,GAAY,CAAC,EAAI,CAAE,KAAM,EAAQ,IAAK,CAC7D,CAAC,EACK,EAAc,EAAI,OAAQ,GAAU,EAAQ,OAAOC,EAAAA,cAAe,CAAE,GAAI,EAAQ,GAAI,OAAM,CAAC,CAAC,EAelG,OAdA,EAAK,IAAI,EAAK,CAAE,MAAK,QAAS,CAAY,CAAC,EAC3C,EACG,WAAW,CAAC,CACZ,KAAM,GACL,EAAQ,OAAOC,EAAAA,cAAe,CAC5B,GAAI,EAAQ,GACZ,GAAI,OAAO,EAAO,MAAS,SAAW,CAAE,KAAM,EAAO,IAAK,EAAI,CAAC,EAC/D,GAAI,EAAO,OAAS,CAAE,OAAQ,OAAO,EAAO,MAAM,CAAE,EAAI,CAAC,CAC3D,CAAC,CACH,CAAC,CAGA,UAAY,EAAQ,OAAOA,EAAAA,cAAe,CAAE,GAAI,EAAQ,GAAI,KAAM,EAAG,CAAC,CAAC,CAAC,CACxE,YAAc,EAAQ,CAAG,CAAC,EACtB,CAAE,SAAU,EAAK,CAC1B,OAAS,EAAO,CAEd,OADA,EAAQ,UAAU,EAAO,EAAQ,EAAE,EAC5B,CAAE,SAAU,GAAO,OAAQ,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAE,CAC3F,CACF,CAAC,EACD,EAAQ,eAAeC,EAAAA,gBAAiB,CAAE,KAAI,QAAQ,IAAa,CACjE,EAAK,IAAI,EAAO,EAAS,OAAQ,CAAE,CAAC,CAAC,EAAE,IAAI,MAAM,GAAG,EAAK,GAAG,CAC9D,CAAC,EACD,EAAQ,eAAeC,EAAAA,cAAe,MAAO,CAAE,MAAM,IAAa,CAChE,IAAM,EAAM,EAAO,EAAS,OAAQ,CAAE,EAChC,EAAQ,EAAK,IAAI,CAAG,EACrB,IACL,EAAQ,CAAG,EACX,MAAM,EAAM,IAAI,KAAK,EACvB,CAAC,CACH,EAEI,EAAW,GACf,UAAa,CACP,MACJ,GAAW,GACX,IAAK,IAAM,KAAW,EAAW,EAAQ,EACzC,IAAK,IAAM,KAAS,EAAK,OAAO,EAAG,EAAM,QAAQ,EACjD,EAAK,MAAM,CAHA,CAIb,CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IPtyHost } from "./services/PtyHost/types.cjs";
|
|
2
|
+
import "./services/PtyHost/index.cjs";
|
|
3
|
+
import { ProtocolRuntime } from "@agimon-ai/doompi-extension-contracts/protocol";
|
|
4
|
+
//#region src/ptyProvider.d.ts
|
|
5
|
+
interface PtyProviderOptions {
|
|
6
|
+
ptyHost: IPtyHost;
|
|
7
|
+
sessionId: () => string | undefined;
|
|
8
|
+
onError?: (error: unknown, id: string) => void;
|
|
9
|
+
}
|
|
10
|
+
declare function provideRunnerPty(runtime: ProtocolRuntime, options: PtyProviderOptions): () => void;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { PtyProviderOptions, provideRunnerPty };
|
|
13
|
+
//# sourceMappingURL=ptyProvider.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptyProvider.d.cts","names":[],"sources":["../src/ptyProvider.ts"],"mappings":";;;;UAwCiB;EACf,SAAS;EACT;EACA,WAAW,gBAAgB;;iBAGb,iBAAiB,SAAS,iBAAiB,SAAS"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IPtyHost } from "./services/PtyHost/types.mjs";
|
|
2
|
+
import "./services/PtyHost/index.mjs";
|
|
3
|
+
import { ProtocolRuntime } from "@agimon-ai/doompi-extension-contracts/protocol";
|
|
4
|
+
//#region src/ptyProvider.d.ts
|
|
5
|
+
interface PtyProviderOptions {
|
|
6
|
+
ptyHost: IPtyHost;
|
|
7
|
+
sessionId: () => string | undefined;
|
|
8
|
+
onError?: (error: unknown, id: string) => void;
|
|
9
|
+
}
|
|
10
|
+
declare function provideRunnerPty(runtime: ProtocolRuntime, options: PtyProviderOptions): () => void;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { PtyProviderOptions, provideRunnerPty };
|
|
13
|
+
//# sourceMappingURL=ptyProvider.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptyProvider.d.mts","names":[],"sources":["../src/ptyProvider.ts"],"mappings":";;;;UAwCiB;EACf,SAAS;EACT;EACA,WAAW,gBAAgB;;iBAGb,iBAAiB,SAAS,iBAAiB,SAAS"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{RunnerPtyData as e,RunnerPtyExit as t,RunnerPtyInput as n,RunnerPtyLaunchProtocol as r,RunnerPtyStop as i}from"@agimon-ai/doompi-extension-contracts/runner-pty";function a(e,t){return`ext:${e}:${t}`.replaceAll(/[^A-Za-z0-9._-]/gu,`-`)}function o(o,s){let c=new Map,l=e=>{let t=c.get(e);t&&(c.delete(e),t.dispose())},u=[o.provide(r,async(n,r)=>{let i=s.sessionId();if(!i)return{launched:!1,reason:`No runner session is active.`};let u=a(r.source,n.id);if(c.has(u))return{launched:!1,reason:`A run named ${n.id} is already active.`};try{let r=await s.ptyHost.launch({id:u,name:u,command:n.command,cwd:n.cwd,sessionId:i,...n.cols===void 0?{}:{cols:n.cols},...n.rows===void 0?{}:{rows:n.rows}}),a=r.onData(t=>o.notify(e,{id:n.id,chunk:t}));return c.set(u,{run:r,dispose:a}),r.completion().then(e=>o.notify(t,{id:n.id,...typeof e.code==`number`?{code:e.code}:{},...e.signal?{signal:String(e.signal)}:{}})).catch(()=>o.notify(t,{id:n.id,code:-1})).finally(()=>l(u)),{launched:!0}}catch(e){return s.onError?.(e,n.id),{launched:!1,reason:e instanceof Error?e.message:String(e)}}}),o.onNotification(n,({id:e,text:t},n)=>{c.get(a(n.source,e))?.run.write(`${t}\n`)}),o.onNotification(i,async({id:e},t)=>{let n=a(t.source,e),r=c.get(n);r&&(l(n),await r.run.stop())})],d=!1;return()=>{if(!d){d=!0;for(let e of u)e();for(let e of c.values())e.dispose();c.clear()}}}export{o as provideRunnerPty};
|
|
2
|
+
//# sourceMappingURL=ptyProvider.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptyProvider.mjs","names":[],"sources":["../src/ptyProvider.ts"],"sourcesContent":["/**\n * Lends this package's pseudo terminals to other extensions.\n *\n * doom-runner is the only package that carries `node-pty`, and the only one that\n * knows how to keep a terminal alive for a session and tear it down with one.\n * Rather than have every extension that needs an answerable command grow its own\n * copy of that, they ask over the bus and the terminal stays here.\n *\n * Output is forwarded raw, chunk by chunk, because the caller is usually\n * rendering a tail and needs the partial line a prompt sits on. Reassembling\n * lines is the caller's problem, not the terminal's.\n *\n * AVOID:\n * - Keeping a run past the session that asked for it\n * - Swallowing an exit; a caller waiting on one would hang forever\n */\n\nimport {\n RunnerPtyData,\n RunnerPtyExit,\n RunnerPtyInput,\n RunnerPtyLaunchProtocol,\n RunnerPtyStop,\n} from '@agimon-ai/doompi-extension-contracts/runner-pty';\nimport type { ProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport type { IPtyHost, PtyRun } from './services/PtyHost/index.ts';\n\n/** Namespaced so a borrowed terminal is distinguishable in the runner list. */\nconst RUN_NAME_PREFIX = 'ext';\n\n/**\n * Collapses a caller and its run id into one safe path segment.\n *\n * The id becomes a log file name, and package-scoped sources carry a `/`, which\n * `path.join` would turn into a directory nobody created.\n */\nfunction runKey(source: string, id: string): string {\n return `${RUN_NAME_PREFIX}:${source}:${id}`.replaceAll(/[^A-Za-z0-9._-]/gu, '-');\n}\n\nexport interface PtyProviderOptions {\n ptyHost: IPtyHost;\n sessionId: () => string | undefined;\n onError?: (error: unknown, id: string) => void;\n}\n\nexport function provideRunnerPty(runtime: ProtocolRuntime, options: PtyProviderOptions): () => void {\n const runs = new Map<string, { run: PtyRun; dispose: () => void }>();\n\n const release = (id: string): void => {\n const entry = runs.get(id);\n if (!entry) return;\n runs.delete(id);\n entry.dispose();\n };\n\n const disposers = [\n runtime.provide(RunnerPtyLaunchProtocol, async (request, identity) => {\n const sessionId = options.sessionId();\n if (!sessionId) return { launched: false, reason: 'No runner session is active.' };\n // Keyed by the caller too, so two extensions choosing the same id cannot\n // collide or read each other's output.\n const key = runKey(identity.source, request.id);\n if (runs.has(key)) return { launched: false, reason: `A run named ${request.id} is already active.` };\n try {\n const run = await options.ptyHost.launch({\n id: key,\n // The host keys its runs by name, so this is the unique one rather\n // than the caller's label; two callers naming a run `install` would\n // otherwise clobber each other.\n name: key,\n command: request.command,\n cwd: request.cwd,\n sessionId,\n ...(request.cols === undefined ? {} : { cols: request.cols }),\n ...(request.rows === undefined ? {} : { rows: request.rows }),\n });\n const unsubscribe = run.onData((chunk) => runtime.notify(RunnerPtyData, { id: request.id, chunk }));\n runs.set(key, { run, dispose: unsubscribe });\n void run\n .completion()\n .then((result) =>\n runtime.notify(RunnerPtyExit, {\n id: request.id,\n ...(typeof result.code === 'number' ? { code: result.code } : {}),\n ...(result.signal ? { signal: String(result.signal) } : {}),\n }),\n )\n // A caller blocked on the exit would wait forever otherwise, so a\n // failure to observe one is still reported as an exit.\n .catch(() => runtime.notify(RunnerPtyExit, { id: request.id, code: -1 }))\n .finally(() => release(key));\n return { launched: true };\n } catch (error) {\n options.onError?.(error, request.id);\n return { launched: false, reason: error instanceof Error ? error.message : String(error) };\n }\n }),\n runtime.onNotification(RunnerPtyInput, ({ id, text }, identity) => {\n runs.get(runKey(identity.source, id))?.run.write(`${text}\\n`);\n }),\n runtime.onNotification(RunnerPtyStop, async ({ id }, identity) => {\n const key = runKey(identity.source, id);\n const entry = runs.get(key);\n if (!entry) return;\n release(key);\n await entry.run.stop();\n }),\n ];\n\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) dispose();\n for (const entry of runs.values()) entry.dispose();\n runs.clear();\n };\n}\n"],"mappings":"wKAoCA,SAAS,EAAO,EAAgB,EAAoB,CAClD,MAAO,OAAsB,EAAO,GAAG,IAAK,WAAW,oBAAqB,GAAG,CACjF,CAQA,SAAgB,EAAiB,EAA0B,EAAyC,CAClG,IAAM,EAAO,IAAI,IAEX,EAAW,GAAqB,CACpC,IAAM,EAAQ,EAAK,IAAI,CAAE,EACpB,IACL,EAAK,OAAO,CAAE,EACd,EAAM,QAAQ,EAChB,EAEM,EAAY,CAChB,EAAQ,QAAQ,EAAyB,MAAO,EAAS,IAAa,CACpE,IAAM,EAAY,EAAQ,UAAU,EACpC,GAAI,CAAC,EAAW,MAAO,CAAE,SAAU,GAAO,OAAQ,8BAA+B,EAGjF,IAAM,EAAM,EAAO,EAAS,OAAQ,EAAQ,EAAE,EAC9C,GAAI,EAAK,IAAI,CAAG,EAAG,MAAO,CAAE,SAAU,GAAO,OAAQ,eAAe,EAAQ,GAAG,oBAAqB,EACpG,GAAI,CACF,IAAM,EAAM,MAAM,EAAQ,QAAQ,OAAO,CACvC,GAAI,EAIJ,KAAM,EACN,QAAS,EAAQ,QACjB,IAAK,EAAQ,IACb,YACA,GAAI,EAAQ,OAAS,IAAA,GAAY,CAAC,EAAI,CAAE,KAAM,EAAQ,IAAK,EAC3D,GAAI,EAAQ,OAAS,IAAA,GAAY,CAAC,EAAI,CAAE,KAAM,EAAQ,IAAK,CAC7D,CAAC,EACK,EAAc,EAAI,OAAQ,GAAU,EAAQ,OAAO,EAAe,CAAE,GAAI,EAAQ,GAAI,OAAM,CAAC,CAAC,EAelG,OAdA,EAAK,IAAI,EAAK,CAAE,MAAK,QAAS,CAAY,CAAC,EAC3C,EACG,WAAW,CAAC,CACZ,KAAM,GACL,EAAQ,OAAO,EAAe,CAC5B,GAAI,EAAQ,GACZ,GAAI,OAAO,EAAO,MAAS,SAAW,CAAE,KAAM,EAAO,IAAK,EAAI,CAAC,EAC/D,GAAI,EAAO,OAAS,CAAE,OAAQ,OAAO,EAAO,MAAM,CAAE,EAAI,CAAC,CAC3D,CAAC,CACH,CAAC,CAGA,UAAY,EAAQ,OAAO,EAAe,CAAE,GAAI,EAAQ,GAAI,KAAM,EAAG,CAAC,CAAC,CAAC,CACxE,YAAc,EAAQ,CAAG,CAAC,EACtB,CAAE,SAAU,EAAK,CAC1B,OAAS,EAAO,CAEd,OADA,EAAQ,UAAU,EAAO,EAAQ,EAAE,EAC5B,CAAE,SAAU,GAAO,OAAQ,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAE,CAC3F,CACF,CAAC,EACD,EAAQ,eAAe,GAAiB,CAAE,KAAI,QAAQ,IAAa,CACjE,EAAK,IAAI,EAAO,EAAS,OAAQ,CAAE,CAAC,CAAC,EAAE,IAAI,MAAM,GAAG,EAAK,GAAG,CAC9D,CAAC,EACD,EAAQ,eAAe,EAAe,MAAO,CAAE,MAAM,IAAa,CAChE,IAAM,EAAM,EAAO,EAAS,OAAQ,CAAE,EAChC,EAAQ,EAAK,IAAI,CAAG,EACrB,IACL,EAAQ,CAAG,EACX,MAAM,EAAM,IAAI,KAAK,EACvB,CAAC,CACH,EAEI,EAAW,GACf,UAAa,CACP,MACJ,GAAW,GACX,IAAK,IAAM,KAAW,EAAW,EAAQ,EACzC,IAAK,IAAM,KAAS,EAAK,OAAO,EAAG,EAAM,QAAQ,EACjD,EAAK,MAAM,CAHA,CAIb,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./_virtual/_rolldown/runtime.cjs");let t=require("node:path");t=e.__toESM(t,1);const n=`completed`,r=`rmux`;async function i(e,t,n){return e.backend===r&&e.backendTarget&&await n.stop(e.backendTarget,e.pid)?!0:t.stop(e.pid)}async function a(e){let t={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===n){await e.registry.release(o.id),t.reclaimed.push(o.id);continue}let a=o.backend===r?e.rmuxBackend.readOutcome(o.id,o.sessionId):void 0;if(a){await e.registry.complete(o.id,{reason:a.signal?`signaled`:a.code===0?n:`failed`,code:a.code,signal:a.signal},o.sessionId),t.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),t.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 i(o,e.launcher,e.rmuxBackend)&&e.processControl.isAlive(o.pid)){t.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),t.reclaimed.push(o.id)}catch(e){t.errors.push(`Could not reconcile runner ${o.id}: ${String(e)}`)}return t}function o(e,n){let r=t.default.relative(t.default.resolve(e),t.default.resolve(n));return r===``||!r.startsWith(`..`)&&!t.default.isAbsolute(r)}async function s(e){let t={reclaimed:[],errors:[]},n=e.paths.legacyDirectory();if(!n)return t;let r=(await e.registry.list()).filter(e=>o(n,e.logPath));for(let n of r){let r=e.processControl.isAlive(n.pid),a=e.processControl.isAlive(n.hostPid),o=n.hostPid===e.currentHostPid;if(!(r&&a&&!o))try{if(r&&!await i(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 a;try{a=(await e.registry.listAcrossRepositories()).filter(t=>o(n,t.logPath)&&e.processControl.isAlive(t.pid))}catch(e){return t.errors.push(`Could not verify legacy runner dependencies: ${String(e)}`),t}return a.length===0&&(t.removed=e.paths.removeLegacyStore()),t}exports.cleanupLegacyRunnerStore=s,exports.reconcileActiveRunners=a,exports.stopRunnerProcess=i;
|
|
2
|
+
//# sourceMappingURL=reconcile.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.cjs","names":["path"],"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,37 @@
|
|
|
1
|
+
import { IRunnerPaths } from "./services/RunnerPaths/types.cjs";
|
|
2
|
+
import "./services/RunnerPaths/index.cjs";
|
|
3
|
+
import { IProcessControl } from "./services/ProcessControl/types.cjs";
|
|
4
|
+
import "./services/ProcessControl/index.cjs";
|
|
5
|
+
import { ILauncher } from "./services/Launcher/types.cjs";
|
|
6
|
+
import "./services/Launcher/index.cjs";
|
|
7
|
+
import { IRmuxBackend } from "./services/RmuxBackend/types.cjs";
|
|
8
|
+
import "./services/RmuxBackend/index.cjs";
|
|
9
|
+
import { IRunnerRegistry, RunnerRecord } from "./services/RunnerRegistry/types.cjs";
|
|
10
|
+
import "./services/RunnerRegistry/index.cjs";
|
|
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.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.cts","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"}
|