@namzu/cli 29.0.0 → 29.1.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/CHANGELOG.md +146 -0
- package/README.md +20 -0
- package/dist/browser/commands.d.ts +29 -0
- package/dist/browser/commands.d.ts.map +1 -0
- package/dist/browser/commands.js +361 -0
- package/dist/browser/commands.js.map +1 -0
- package/dist/browser/control.d.ts +79 -0
- package/dist/browser/control.d.ts.map +1 -0
- package/dist/browser/control.js +140 -0
- package/dist/browser/control.js.map +1 -0
- package/dist/browser/describe.d.ts +12 -0
- package/dist/browser/describe.d.ts.map +1 -0
- package/dist/browser/describe.js +27 -0
- package/dist/browser/describe.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +29 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/acp.d.ts.map +1 -1
- package/dist/commands/acp.js +1 -0
- package/dist/commands/acp.js.map +1 -1
- package/dist/commands/browser.d.ts +7 -0
- package/dist/commands/browser.d.ts.map +1 -0
- package/dist/commands/browser.js +16 -0
- package/dist/commands/browser.js.map +1 -0
- package/dist/commands/drain.d.ts +2 -1
- package/dist/commands/drain.d.ts.map +1 -1
- package/dist/commands/drain.js +6 -3
- package/dist/commands/drain.js.map +1 -1
- package/dist/commands/exec-flags.d.ts +2 -1
- package/dist/commands/exec-flags.d.ts.map +1 -1
- package/dist/commands/exec-flags.js +6 -3
- package/dist/commands/exec-flags.js.map +1 -1
- package/dist/commands/exec-json.d.ts.map +1 -1
- package/dist/commands/exec-json.js +2 -1
- package/dist/commands/exec-json.js.map +1 -1
- package/dist/commands/exec.d.ts.map +1 -1
- package/dist/commands/exec.js +2 -1
- package/dist/commands/exec.js.map +1 -1
- package/dist/commands/host-queries.d.ts.map +1 -1
- package/dist/commands/host-queries.js +10 -3
- package/dist/commands/host-queries.js.map +1 -1
- package/dist/commands/schedule.d.ts +9 -0
- package/dist/commands/schedule.d.ts.map +1 -0
- package/dist/commands/schedule.js +126 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/commands/serve.d.ts +3 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +5 -3
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/skills.d.ts +10 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +23 -7
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/upgrade.d.ts +5 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +11 -0
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/config/load.d.ts +39 -0
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +232 -1
- package/dist/config/load.js.map +1 -1
- package/dist/config/schema.d.ts +78 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/config/user-config.d.ts +23 -0
- package/dist/config/user-config.d.ts.map +1 -0
- package/dist/config/user-config.js +48 -0
- package/dist/config/user-config.js.map +1 -0
- package/dist/context/capabilities.d.ts +1 -1
- package/dist/context/capabilities.d.ts.map +1 -1
- package/dist/context/capabilities.js +1 -0
- package/dist/context/capabilities.js.map +1 -1
- package/dist/doctor/checks/browser.d.ts +15 -0
- package/dist/doctor/checks/browser.d.ts.map +1 -0
- package/dist/doctor/checks/browser.js +63 -0
- package/dist/doctor/checks/browser.js.map +1 -0
- package/dist/doctor/checks/index.d.ts +4 -1
- package/dist/doctor/checks/index.d.ts.map +1 -1
- package/dist/doctor/checks/index.js +8 -1
- package/dist/doctor/checks/index.js.map +1 -1
- package/dist/doctor/checks/scheduler.d.ts +10 -0
- package/dist/doctor/checks/scheduler.d.ts.map +1 -0
- package/dist/doctor/checks/scheduler.js +74 -0
- package/dist/doctor/checks/scheduler.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/notifications/desktop/freedesktop.d.ts +10 -0
- package/dist/integrations/notifications/desktop/freedesktop.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/freedesktop.js +33 -0
- package/dist/integrations/notifications/desktop/freedesktop.js.map +1 -0
- package/dist/integrations/notifications/desktop/macos.d.ts +6 -0
- package/dist/integrations/notifications/desktop/macos.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/macos.js +17 -0
- package/dist/integrations/notifications/desktop/macos.js.map +1 -0
- package/dist/integrations/notifications/desktop/sanitize.d.ts +16 -0
- package/dist/integrations/notifications/desktop/sanitize.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/sanitize.js +49 -0
- package/dist/integrations/notifications/desktop/sanitize.js.map +1 -0
- package/dist/integrations/notifications/desktop/throttle.d.ts +10 -0
- package/dist/integrations/notifications/desktop/throttle.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/throttle.js +39 -0
- package/dist/integrations/notifications/desktop/throttle.js.map +1 -0
- package/dist/integrations/notifications/desktop/windows-toast.d.ts +23 -0
- package/dist/integrations/notifications/desktop/windows-toast.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/windows-toast.js +56 -0
- package/dist/integrations/notifications/desktop/windows-toast.js.map +1 -0
- package/dist/integrations/notifications/desktop.d.ts +82 -0
- package/dist/integrations/notifications/desktop.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop.js +198 -0
- package/dist/integrations/notifications/desktop.js.map +1 -0
- package/dist/integrations/resident/session-step.d.ts.map +1 -1
- package/dist/integrations/resident/session-step.js +1 -0
- package/dist/integrations/resident/session-step.js.map +1 -1
- package/dist/integrations/subagents/runtime.d.ts +6 -0
- package/dist/integrations/subagents/runtime.d.ts.map +1 -1
- package/dist/integrations/subagents/runtime.js +14 -5
- package/dist/integrations/subagents/runtime.js.map +1 -1
- package/dist/permissions/browser-sites.d.ts +95 -0
- package/dist/permissions/browser-sites.d.ts.map +1 -0
- package/dist/permissions/browser-sites.js +270 -0
- package/dist/permissions/browser-sites.js.map +1 -0
- package/dist/permissions/checks.d.ts.map +1 -1
- package/dist/permissions/checks.js +7 -1
- package/dist/permissions/checks.js.map +1 -1
- package/dist/permissions/rules.d.ts.map +1 -1
- package/dist/permissions/rules.js +4 -8
- package/dist/permissions/rules.js.map +1 -1
- package/dist/schedule/build.d.ts +79 -0
- package/dist/schedule/build.d.ts.map +1 -0
- package/dist/schedule/build.js +246 -0
- package/dist/schedule/build.js.map +1 -0
- package/dist/schedule/changes.d.ts +22 -0
- package/dist/schedule/changes.d.ts.map +1 -0
- package/dist/schedule/changes.js +55 -0
- package/dist/schedule/changes.js.map +1 -0
- package/dist/schedule/commands/add.d.ts +24 -0
- package/dist/schedule/commands/add.d.ts.map +1 -0
- package/dist/schedule/commands/add.js +459 -0
- package/dist/schedule/commands/add.js.map +1 -0
- package/dist/schedule/commands/args.d.ts +22 -0
- package/dist/schedule/commands/args.d.ts.map +1 -0
- package/dist/schedule/commands/args.js +80 -0
- package/dist/schedule/commands/args.js.map +1 -0
- package/dist/schedule/commands/confirm-prompt.d.ts +6 -0
- package/dist/schedule/commands/confirm-prompt.d.ts.map +1 -0
- package/dist/schedule/commands/confirm-prompt.js +21 -0
- package/dist/schedule/commands/confirm-prompt.js.map +1 -0
- package/dist/schedule/commands/lifecycle.d.ts +39 -0
- package/dist/schedule/commands/lifecycle.d.ts.map +1 -0
- package/dist/schedule/commands/lifecycle.js +585 -0
- package/dist/schedule/commands/lifecycle.js.map +1 -0
- package/dist/schedule/commands/list.d.ts +33 -0
- package/dist/schedule/commands/list.d.ts.map +1 -0
- package/dist/schedule/commands/list.js +202 -0
- package/dist/schedule/commands/list.js.map +1 -0
- package/dist/schedule/commands/logs.d.ts +7 -0
- package/dist/schedule/commands/logs.d.ts.map +1 -0
- package/dist/schedule/commands/logs.js +106 -0
- package/dist/schedule/commands/logs.js.map +1 -0
- package/dist/schedule/commands/service.d.ts +16 -0
- package/dist/schedule/commands/service.d.ts.map +1 -0
- package/dist/schedule/commands/service.js +458 -0
- package/dist/schedule/commands/service.js.map +1 -0
- package/dist/schedule/daemon/daemon.d.ts +156 -0
- package/dist/schedule/daemon/daemon.d.ts.map +1 -0
- package/dist/schedule/daemon/daemon.js +1248 -0
- package/dist/schedule/daemon/daemon.js.map +1 -0
- package/dist/schedule/daemon/endpoint.d.ts +38 -0
- package/dist/schedule/daemon/endpoint.d.ts.map +1 -0
- package/dist/schedule/daemon/endpoint.js +158 -0
- package/dist/schedule/daemon/endpoint.js.map +1 -0
- package/dist/schedule/daemon/exit.d.ts +8 -0
- package/dist/schedule/daemon/exit.d.ts.map +1 -0
- package/dist/schedule/daemon/exit.js +8 -0
- package/dist/schedule/daemon/exit.js.map +1 -0
- package/dist/schedule/daemon/log.d.ts +12 -0
- package/dist/schedule/daemon/log.d.ts.map +1 -0
- package/dist/schedule/daemon/log.js +53 -0
- package/dist/schedule/daemon/log.js.map +1 -0
- package/dist/schedule/daemon/notify.d.ts +31 -0
- package/dist/schedule/daemon/notify.d.ts.map +1 -0
- package/dist/schedule/daemon/notify.js +89 -0
- package/dist/schedule/daemon/notify.js.map +1 -0
- package/dist/schedule/daemon/retention.d.ts +16 -0
- package/dist/schedule/daemon/retention.d.ts.map +1 -0
- package/dist/schedule/daemon/retention.js +46 -0
- package/dist/schedule/daemon/retention.js.map +1 -0
- package/dist/schedule/daemon/sessions.d.ts +23 -0
- package/dist/schedule/daemon/sessions.d.ts.map +1 -0
- package/dist/schedule/daemon/sessions.js +52 -0
- package/dist/schedule/daemon/sessions.js.map +1 -0
- package/dist/schedule/env.d.ts +28 -0
- package/dist/schedule/env.d.ts.map +1 -0
- package/dist/schedule/env.js +99 -0
- package/dist/schedule/env.js.map +1 -0
- package/dist/schedule/fire/browser-preflight.d.ts +41 -0
- package/dist/schedule/fire/browser-preflight.d.ts.map +1 -0
- package/dist/schedule/fire/browser-preflight.js +73 -0
- package/dist/schedule/fire/browser-preflight.js.map +1 -0
- package/dist/schedule/fire/fire.d.ts +78 -0
- package/dist/schedule/fire/fire.d.ts.map +1 -0
- package/dist/schedule/fire/fire.js +482 -0
- package/dist/schedule/fire/fire.js.map +1 -0
- package/dist/schedule/fire/result.d.ts +13 -0
- package/dist/schedule/fire/result.d.ts.map +1 -0
- package/dist/schedule/fire/result.js +18 -0
- package/dist/schedule/fire/result.js.map +1 -0
- package/dist/schedule/fire/unattended-note.d.ts +22 -0
- package/dist/schedule/fire/unattended-note.d.ts.map +1 -0
- package/dist/schedule/fire/unattended-note.js +46 -0
- package/dist/schedule/fire/unattended-note.js.map +1 -0
- package/dist/schedule/floor.d.ts +116 -0
- package/dist/schedule/floor.d.ts.map +1 -0
- package/dist/schedule/floor.js +1051 -0
- package/dist/schedule/floor.js.map +1 -0
- package/dist/schedule/folder.d.ts +34 -0
- package/dist/schedule/folder.d.ts.map +1 -0
- package/dist/schedule/folder.js +84 -0
- package/dist/schedule/folder.js.map +1 -0
- package/dist/schedule/paths.d.ts +49 -0
- package/dist/schedule/paths.d.ts.map +1 -0
- package/dist/schedule/paths.js +53 -0
- package/dist/schedule/paths.js.map +1 -0
- package/dist/schedule/policy.d.ts +141 -0
- package/dist/schedule/policy.d.ts.map +1 -0
- package/dist/schedule/policy.js +378 -0
- package/dist/schedule/policy.js.map +1 -0
- package/dist/schedule/resume-command.d.ts +36 -0
- package/dist/schedule/resume-command.d.ts.map +1 -0
- package/dist/schedule/resume-command.js +72 -0
- package/dist/schedule/resume-command.js.map +1 -0
- package/dist/schedule/service/detect.d.ts +22 -0
- package/dist/schedule/service/detect.d.ts.map +1 -0
- package/dist/schedule/service/detect.js +29 -0
- package/dist/schedule/service/detect.js.map +1 -0
- package/dist/schedule/service/index.d.ts +48 -0
- package/dist/schedule/service/index.d.ts.map +1 -0
- package/dist/schedule/service/index.js +352 -0
- package/dist/schedule/service/index.js.map +1 -0
- package/dist/schedule/service/launchd.d.ts +24 -0
- package/dist/schedule/service/launchd.d.ts.map +1 -0
- package/dist/schedule/service/launchd.js +84 -0
- package/dist/schedule/service/launchd.js.map +1 -0
- package/dist/schedule/service/manifest.d.ts +44 -0
- package/dist/schedule/service/manifest.d.ts.map +1 -0
- package/dist/schedule/service/manifest.js +16 -0
- package/dist/schedule/service/manifest.js.map +1 -0
- package/dist/schedule/service/names.d.ts +9 -0
- package/dist/schedule/service/names.d.ts.map +1 -0
- package/dist/schedule/service/names.js +22 -0
- package/dist/schedule/service/names.js.map +1 -0
- package/dist/schedule/service/quote.d.ts +24 -0
- package/dist/schedule/service/quote.d.ts.map +1 -0
- package/dist/schedule/service/quote.js +64 -0
- package/dist/schedule/service/quote.js.map +1 -0
- package/dist/schedule/service/runner.d.ts +17 -0
- package/dist/schedule/service/runner.d.ts.map +1 -0
- package/dist/schedule/service/runner.js +31 -0
- package/dist/schedule/service/runner.js.map +1 -0
- package/dist/schedule/service/systemd.d.ts +37 -0
- package/dist/schedule/service/systemd.d.ts.map +1 -0
- package/dist/schedule/service/systemd.js +96 -0
- package/dist/schedule/service/systemd.js.map +1 -0
- package/dist/schedule/service/windows-task.d.ts +51 -0
- package/dist/schedule/service/windows-task.d.ts.map +1 -0
- package/dist/schedule/service/windows-task.js +134 -0
- package/dist/schedule/service/windows-task.js.map +1 -0
- package/dist/schedule/service/wsl.d.ts +57 -0
- package/dist/schedule/service/wsl.d.ts.map +1 -0
- package/dist/schedule/service/wsl.js +111 -0
- package/dist/schedule/service/wsl.js.map +1 -0
- package/dist/schedule/store/atomic.d.ts +43 -0
- package/dist/schedule/store/atomic.d.ts.map +1 -0
- package/dist/schedule/store/atomic.js +135 -0
- package/dist/schedule/store/atomic.js.map +1 -0
- package/dist/schedule/store/claims.d.ts +26 -0
- package/dist/schedule/store/claims.d.ts.map +1 -0
- package/dist/schedule/store/claims.js +57 -0
- package/dist/schedule/store/claims.js.map +1 -0
- package/dist/schedule/store/digest.d.ts +18 -0
- package/dist/schedule/store/digest.d.ts.map +1 -0
- package/dist/schedule/store/digest.js +139 -0
- package/dist/schedule/store/digest.js.map +1 -0
- package/dist/schedule/store/history.d.ts +21 -0
- package/dist/schedule/store/history.d.ts.map +1 -0
- package/dist/schedule/store/history.js +114 -0
- package/dist/schedule/store/history.js.map +1 -0
- package/dist/schedule/store/jobs.d.ts +61 -0
- package/dist/schedule/store/jobs.d.ts.map +1 -0
- package/dist/schedule/store/jobs.js +210 -0
- package/dist/schedule/store/jobs.js.map +1 -0
- package/dist/schedule/store/state.d.ts +19 -0
- package/dist/schedule/store/state.d.ts.map +1 -0
- package/dist/schedule/store/state.js +38 -0
- package/dist/schedule/store/state.js.map +1 -0
- package/dist/schedule/types.d.ts +256 -0
- package/dist/schedule/types.d.ts.map +1 -0
- package/dist/schedule/types.js +9 -0
- package/dist/schedule/types.js.map +1 -0
- package/dist/skills/catalog.d.ts +96 -0
- package/dist/skills/catalog.d.ts.map +1 -0
- package/dist/skills/catalog.js +226 -0
- package/dist/skills/catalog.js.map +1 -0
- package/dist/skills/save.d.ts +148 -0
- package/dist/skills/save.d.ts.map +1 -0
- package/dist/skills/save.js +344 -0
- package/dist/skills/save.js.map +1 -0
- package/dist/skills/store.d.ts +103 -16
- package/dist/skills/store.d.ts.map +1 -1
- package/dist/skills/store.js +230 -29
- package/dist/skills/store.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +591 -72
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/LiveActivity.d.ts +8 -1
- package/dist/tui/LiveActivity.d.ts.map +1 -1
- package/dist/tui/LiveActivity.js +20 -4
- package/dist/tui/LiveActivity.js.map +1 -1
- package/dist/tui/PermissionOverlay.d.ts +24 -4
- package/dist/tui/PermissionOverlay.d.ts.map +1 -1
- package/dist/tui/PermissionOverlay.js +113 -15
- package/dist/tui/PermissionOverlay.js.map +1 -1
- package/dist/tui/SaveSkillOverlay.d.ts +33 -0
- package/dist/tui/SaveSkillOverlay.d.ts.map +1 -0
- package/dist/tui/SaveSkillOverlay.js +118 -0
- package/dist/tui/SaveSkillOverlay.js.map +1 -0
- package/dist/tui/agent.d.ts +185 -5
- package/dist/tui/agent.d.ts.map +1 -1
- package/dist/tui/agent.js +325 -54
- package/dist/tui/agent.js.map +1 -1
- package/dist/tui/browser-notices.d.ts +33 -0
- package/dist/tui/browser-notices.d.ts.map +1 -0
- package/dist/tui/browser-notices.js +102 -0
- package/dist/tui/browser-notices.js.map +1 -0
- package/dist/tui/permission-review.d.ts.map +1 -1
- package/dist/tui/permission-review.js +53 -4
- package/dist/tui/permission-review.js.map +1 -1
- package/dist/tui/schedule/host-commands.d.ts +34 -0
- package/dist/tui/schedule/host-commands.d.ts.map +1 -0
- package/dist/tui/schedule/host-commands.js +309 -0
- package/dist/tui/schedule/host-commands.js.map +1 -0
- package/dist/tui/schedule/integration.d.ts +62 -0
- package/dist/tui/schedule/integration.d.ts.map +1 -0
- package/dist/tui/schedule/integration.js +145 -0
- package/dist/tui/schedule/integration.js.map +1 -0
- package/dist/tui/schedule/loop-host.d.ts +42 -0
- package/dist/tui/schedule/loop-host.d.ts.map +1 -0
- package/dist/tui/schedule/loop-host.js +153 -0
- package/dist/tui/schedule/loop-host.js.map +1 -0
- package/dist/tui/schedule/resume.d.ts +122 -0
- package/dist/tui/schedule/resume.d.ts.map +1 -0
- package/dist/tui/schedule/resume.js +324 -0
- package/dist/tui/schedule/resume.js.map +1 -0
- package/dist/tui/schedule/startup.d.ts +11 -0
- package/dist/tui/schedule/startup.d.ts.map +1 -0
- package/dist/tui/schedule/startup.js +121 -0
- package/dist/tui/schedule/startup.js.map +1 -0
- package/dist/tui/schedule/tool-host.d.ts +44 -0
- package/dist/tui/schedule/tool-host.d.ts.map +1 -0
- package/dist/tui/schedule/tool-host.js +294 -0
- package/dist/tui/schedule/tool-host.js.map +1 -0
- package/dist/tui/skills/learning.d.ts +74 -0
- package/dist/tui/skills/learning.d.ts.map +1 -0
- package/dist/tui/skills/learning.js +131 -0
- package/dist/tui/skills/learning.js.map +1 -0
- package/dist/tui/skills/suggest-setting.d.ts +22 -0
- package/dist/tui/skills/suggest-setting.d.ts.map +1 -0
- package/dist/tui/skills/suggest-setting.js +55 -0
- package/dist/tui/skills/suggest-setting.js.map +1 -0
- package/dist/tui/skills/suggestion-ledger.d.ts +35 -0
- package/dist/tui/skills/suggestion-ledger.d.ts.map +1 -0
- package/dist/tui/skills/suggestion-ledger.js +52 -0
- package/dist/tui/skills/suggestion-ledger.js.map +1 -0
- package/dist/tui/slashCommands.d.ts +20 -0
- package/dist/tui/slashCommands.d.ts.map +1 -1
- package/dist/tui/slashCommands.js +76 -2
- package/dist/tui/slashCommands.js.map +1 -1
- package/dist/tui/turn-interruption.d.ts +20 -1
- package/dist/tui/turn-interruption.d.ts.map +1 -1
- package/dist/tui/turn-interruption.js +43 -0
- package/dist/tui/turn-interruption.js.map +1 -1
- package/dist/tui/types.d.ts +9 -1
- package/dist/tui/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/skills/README.md +15 -0
- package/skills/browser-automation/SKILL.md +84 -0
- package/skills/schedule-task/SKILL.md +140 -0
- package/skills/skill-creator/SKILL.md +101 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quoting for each supervisor's file format. Paths are data; each format's
|
|
3
|
+
* special characters are escaped, never interpreted.
|
|
4
|
+
*/
|
|
5
|
+
/** A word in a systemd unit's `ExecStart=`: double-quoted, `%` and `$` doubled. */
|
|
6
|
+
export declare function systemdWord(text: string): string;
|
|
7
|
+
/** A value in a systemd `Environment=` assignment, quoted as a whole. */
|
|
8
|
+
export declare function systemdAssignment(key: string, value: string): string;
|
|
9
|
+
/** Text in XML content or an attribute. */
|
|
10
|
+
export declare function xmlText(text: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* A Windows command-line argument, quoted by the rules `CommandLineToArgvW`
|
|
13
|
+
* applies: backslashes before a quote are doubled, quotes are escaped.
|
|
14
|
+
*/
|
|
15
|
+
export declare function windowsArgument(text: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* A path `wsl.exe` passes on unchanged. Its command line is re-parsed on the
|
|
18
|
+
* Linux side, so a space, `$`, a quote or a backtick would split or change
|
|
19
|
+
* it; rather than an escape layer that has to be right twice, such a path is
|
|
20
|
+
* refused.
|
|
21
|
+
*/
|
|
22
|
+
export declare const WSL_SAFE_PATH: RegExp;
|
|
23
|
+
export declare function checkWslPath(label: string, path: string): string;
|
|
24
|
+
//# sourceMappingURL=quote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../../src/schedule/service/quote.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,2CAA2C;AAC3C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO5C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBpD;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,QAAyB,CAAA;AAEnD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAOhE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quoting for each supervisor's file format. Paths are data; each format's
|
|
3
|
+
* special characters are escaped, never interpreted.
|
|
4
|
+
*/
|
|
5
|
+
/** A word in a systemd unit's `ExecStart=`: double-quoted, `%` and `$` doubled. */
|
|
6
|
+
export function systemdWord(text) {
|
|
7
|
+
const escaped = text
|
|
8
|
+
.replaceAll('\\', '\\\\')
|
|
9
|
+
.replaceAll('"', '\\"')
|
|
10
|
+
.replaceAll('%', '%%')
|
|
11
|
+
.replaceAll('$', '$$$$');
|
|
12
|
+
return `"${escaped}"`;
|
|
13
|
+
}
|
|
14
|
+
/** A value in a systemd `Environment=` assignment, quoted as a whole. */
|
|
15
|
+
export function systemdAssignment(key, value) {
|
|
16
|
+
return systemdWord(`${key}=${value}`);
|
|
17
|
+
}
|
|
18
|
+
/** Text in XML content or an attribute. */
|
|
19
|
+
export function xmlText(text) {
|
|
20
|
+
return text
|
|
21
|
+
.replaceAll('&', '&')
|
|
22
|
+
.replaceAll('<', '<')
|
|
23
|
+
.replaceAll('>', '>')
|
|
24
|
+
.replaceAll('"', '"')
|
|
25
|
+
.replaceAll("'", ''');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A Windows command-line argument, quoted by the rules `CommandLineToArgvW`
|
|
29
|
+
* applies: backslashes before a quote are doubled, quotes are escaped.
|
|
30
|
+
*/
|
|
31
|
+
export function windowsArgument(text) {
|
|
32
|
+
if (text !== '' && !/[\s"]/.test(text))
|
|
33
|
+
return text;
|
|
34
|
+
let out = '"';
|
|
35
|
+
let slashes = 0;
|
|
36
|
+
for (const ch of text) {
|
|
37
|
+
if (ch === '\\') {
|
|
38
|
+
slashes++;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (ch === '"') {
|
|
42
|
+
out += `${'\\'.repeat(slashes * 2 + 1)}"`;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
out += '\\'.repeat(slashes) + ch;
|
|
46
|
+
}
|
|
47
|
+
slashes = 0;
|
|
48
|
+
}
|
|
49
|
+
return `${out}${'\\'.repeat(slashes * 2)}"`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A path `wsl.exe` passes on unchanged. Its command line is re-parsed on the
|
|
53
|
+
* Linux side, so a space, `$`, a quote or a backtick would split or change
|
|
54
|
+
* it; rather than an escape layer that has to be right twice, such a path is
|
|
55
|
+
* refused.
|
|
56
|
+
*/
|
|
57
|
+
export const WSL_SAFE_PATH = /^[A-Za-z0-9._/@+-]+$/;
|
|
58
|
+
export function checkWslPath(label, path) {
|
|
59
|
+
if (!WSL_SAFE_PATH.test(path)) {
|
|
60
|
+
throw new Error(`${label} ${path} contains characters wsl.exe would re-read (only letters, digits and . _ / @ + - are passed through safely); install node and namzu under a plain path, or use --platform systemd-user`);
|
|
61
|
+
}
|
|
62
|
+
return path;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=quote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quote.js","sourceRoot":"","sources":["../../../src/schedule/service/quote.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mFAAmF;AACnF,MAAM,UAAU,WAAW,CAAC,IAAY;IACvC,MAAM,OAAO,GAAG,IAAI;SAClB,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC;SACtB,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC;SACrB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IACzB,OAAO,IAAI,OAAO,GAAG,CAAA;AACtB,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,KAAa;IAC3D,OAAO,WAAW,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAA;AACtC,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,OAAO,CAAC,IAAY;IACnC,OAAO,IAAI;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC3C,IAAI,IAAI,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IACnD,IAAI,GAAG,GAAG,GAAG,CAAA;IACb,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACjB,OAAO,EAAE,CAAA;YACT,SAAQ;QACT,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAChB,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAA;QAC1C,CAAC;aAAM,CAAC;YACP,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAA;QACjC,CAAC;QACD,OAAO,GAAG,CAAC,CAAA;IACZ,CAAC;IACD,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAA;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,sBAAsB,CAAA;AAEnD,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,IAAY;IACvD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACd,GAAG,KAAK,IAAI,IAAI,wLAAwL,CACxM,CAAA;IACF,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the installers run the supervisor's commands: argv only, never a
|
|
3
|
+
* shell, with a timeout. Injectable, so an installer is tested against a
|
|
4
|
+
* recording fake instead of this machine's service manager.
|
|
5
|
+
*/
|
|
6
|
+
export interface CommandResult {
|
|
7
|
+
readonly code: number;
|
|
8
|
+
readonly stdout: string;
|
|
9
|
+
readonly stderr: string;
|
|
10
|
+
}
|
|
11
|
+
export type CommandRunner = (command: string, args: readonly string[], options?: {
|
|
12
|
+
readonly timeoutMs?: number;
|
|
13
|
+
readonly cwd?: string;
|
|
14
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
15
|
+
}) => Promise<CommandResult>;
|
|
16
|
+
export declare const runCommand: CommandRunner;
|
|
17
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/schedule/service/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE;IACT,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAChC,KACG,OAAO,CAAC,aAAa,CAAC,CAAA;AAE3B,eAAO,MAAM,UAAU,EAAE,aAkBtB,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the installers run the supervisor's commands: argv only, never a
|
|
3
|
+
* shell, with a timeout. Injectable, so an installer is tested against a
|
|
4
|
+
* recording fake instead of this machine's service manager.
|
|
5
|
+
*/
|
|
6
|
+
import { execFile } from 'node:child_process';
|
|
7
|
+
export const runCommand = (command, args, options = {}) => new Promise((resolve) => {
|
|
8
|
+
execFile(command, [...args], {
|
|
9
|
+
timeout: options.timeoutMs ?? 30_000,
|
|
10
|
+
windowsHide: true,
|
|
11
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
12
|
+
...(options.cwd ? { cwd: options.cwd } : {}),
|
|
13
|
+
...(options.env ? { env: options.env } : {}),
|
|
14
|
+
encoding: 'buffer',
|
|
15
|
+
}, (error, stdout, stderr) => {
|
|
16
|
+
const code = error ? (typeof error.code === 'number' ? error.code : 127) : 0;
|
|
17
|
+
resolve({ code, stdout: decode(stdout), stderr: decode(stderr) });
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
/** Windows tools answer in UTF-16 or the console code page; read both. */
|
|
21
|
+
function decode(buffer) {
|
|
22
|
+
if (typeof buffer === 'string')
|
|
23
|
+
return buffer;
|
|
24
|
+
if (buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xfe)
|
|
25
|
+
return buffer.subarray(2).toString('utf16le');
|
|
26
|
+
// UTF-16LE without a BOM: every other byte of ASCII text is zero.
|
|
27
|
+
if (buffer.length >= 4 && buffer[1] === 0 && buffer[3] === 0)
|
|
28
|
+
return buffer.toString('utf16le');
|
|
29
|
+
return buffer.toString('utf8');
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/schedule/service/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAkB7C,MAAM,CAAC,MAAM,UAAU,GAAkB,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE,CACxE,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;IACvB,QAAQ,CACP,OAAO,EACP,CAAC,GAAG,IAAI,CAAC,EACT;QACC,OAAO,EAAE,OAAO,CAAC,SAAS,IAAI,MAAM;QACpC,WAAW,EAAE,IAAI;QACjB,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;QAC1B,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,QAAQ,EAAE,QAAQ;KAClB,EACD,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;QACzB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC5E,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAClE,CAAC,CACD,CAAA;AACF,CAAC,CAAC,CAAA;AAEH,0EAA0E;AAC1E,SAAS,MAAM,CAAC,MAAuB;IACtC,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAA;IAC7C,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;QACjE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;IAC9C,kEAAkE;IAClE,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;IAC/F,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AAC/B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linux: a systemd user unit.
|
|
3
|
+
*
|
|
4
|
+
* `Restart=always` with no start limit: a second daemon waits on standby
|
|
5
|
+
* instead of exiting, and a daemon that exits 0 after an upgrade is started
|
|
6
|
+
* again on the new code. The one exit that must not restart is a daemon
|
|
7
|
+
* finding `schedule stop`'s request: it exits `EXIT_STOP_REQUESTED`, which
|
|
8
|
+
* `RestartPreventExitStatus=` names (and `SuccessExitStatus=`, so the unit
|
|
9
|
+
* is inactive rather than failed). `schedule stop` also DISABLES the unit,
|
|
10
|
+
* and `start` enables it again, so a stopped scheduler is not started at the
|
|
11
|
+
* next login.
|
|
12
|
+
* `KillMode=process`: stopping or restarting the daemon leaves runs in
|
|
13
|
+
* progress alone; they finish, record their result and the next daemon
|
|
14
|
+
* adopts them.
|
|
15
|
+
*/
|
|
16
|
+
import type { CommandRunner } from './runner.js';
|
|
17
|
+
export interface ServiceProgram {
|
|
18
|
+
readonly node: string;
|
|
19
|
+
readonly bin: string;
|
|
20
|
+
readonly namzuHome: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function systemdUnitPath(name: string, env?: NodeJS.ProcessEnv, home?: string): string;
|
|
23
|
+
export declare function systemdUnit(program: ServiceProgram): string;
|
|
24
|
+
export interface SystemdSteps {
|
|
25
|
+
readonly run: CommandRunner;
|
|
26
|
+
readonly systemctl?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function installSystemd(name: string, program: ServiceProgram, steps: SystemdSteps, unitPath?: string): Promise<string[]>;
|
|
29
|
+
export declare function uninstallSystemd(name: string, steps: SystemdSteps, unitPath?: string): Promise<string[]>;
|
|
30
|
+
export declare function systemdState(name: string, steps: SystemdSteps): Promise<string>;
|
|
31
|
+
/** Enable and start: `stop` disabled it. */
|
|
32
|
+
export declare function startSystemd(name: string, steps: SystemdSteps): Promise<string[]>;
|
|
33
|
+
/** Disable and stop, so the next login does not start it again. */
|
|
34
|
+
export declare function stopSystemd(name: string, steps: SystemdSteps): Promise<string[]>;
|
|
35
|
+
/** Whether a systemd user manager answers here. */
|
|
36
|
+
export declare function systemdUserAvailable(steps: SystemdSteps): Promise<boolean>;
|
|
37
|
+
//# sourceMappingURL=systemd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemd.d.ts","sourceRoot":"","sources":["../../../src/schedule/service/systemd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC1B;AAED,wBAAgB,eAAe,CAC9B,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,IAAI,SAAY,GACd,MAAM,CAGR;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAsB3D;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAA;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC3B;AAMD,wBAAsB,cAAc,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,YAAY,EACnB,QAAQ,SAAwB,GAC9B,OAAO,CAAC,MAAM,EAAE,CAAC,CAYnB;AAED,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,YAAY,EACnB,QAAQ,SAAwB,GAC9B,OAAO,CAAC,MAAM,EAAE,CAAC,CAWnB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrF;AAED,4CAA4C;AAC5C,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGvF;AAED,mEAAmE;AACnE,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGtF;AAED,mDAAmD;AACnD,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAIhF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linux: a systemd user unit.
|
|
3
|
+
*
|
|
4
|
+
* `Restart=always` with no start limit: a second daemon waits on standby
|
|
5
|
+
* instead of exiting, and a daemon that exits 0 after an upgrade is started
|
|
6
|
+
* again on the new code. The one exit that must not restart is a daemon
|
|
7
|
+
* finding `schedule stop`'s request: it exits `EXIT_STOP_REQUESTED`, which
|
|
8
|
+
* `RestartPreventExitStatus=` names (and `SuccessExitStatus=`, so the unit
|
|
9
|
+
* is inactive rather than failed). `schedule stop` also DISABLES the unit,
|
|
10
|
+
* and `start` enables it again, so a stopped scheduler is not started at the
|
|
11
|
+
* next login.
|
|
12
|
+
* `KillMode=process`: stopping or restarting the daemon leaves runs in
|
|
13
|
+
* progress alone; they finish, record their result and the next daemon
|
|
14
|
+
* adopts them.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
17
|
+
import { homedir } from 'node:os';
|
|
18
|
+
import { dirname, join } from 'node:path';
|
|
19
|
+
import { EXIT_STOP_REQUESTED } from '../daemon/exit.js';
|
|
20
|
+
import { systemdAssignment, systemdWord } from './quote.js';
|
|
21
|
+
export function systemdUnitPath(name, env = process.env, home = homedir()) {
|
|
22
|
+
const config = env.XDG_CONFIG_HOME || join(home, '.config');
|
|
23
|
+
return join(config, 'systemd', 'user', `${name}.service`);
|
|
24
|
+
}
|
|
25
|
+
export function systemdUnit(program) {
|
|
26
|
+
return [
|
|
27
|
+
'[Unit]',
|
|
28
|
+
`Description=namzu scheduler (NAMZU_HOME=${program.namzuHome.replaceAll('%', '%%')})`,
|
|
29
|
+
'Documentation=https://github.com/cogitave/namzu/blob/main/docs/cli/scheduler-service.md',
|
|
30
|
+
'StartLimitIntervalSec=0',
|
|
31
|
+
'',
|
|
32
|
+
'[Service]',
|
|
33
|
+
'Type=simple',
|
|
34
|
+
`ExecStart=${[program.node, program.bin, 'schedule', 'daemon', '--home', program.namzuHome].map(systemdWord).join(' ')}`,
|
|
35
|
+
`Environment=${systemdAssignment('NAMZU_HOME', program.namzuHome)}`,
|
|
36
|
+
'Restart=always',
|
|
37
|
+
'RestartSec=10',
|
|
38
|
+
`SuccessExitStatus=${EXIT_STOP_REQUESTED}`,
|
|
39
|
+
`RestartPreventExitStatus=${EXIT_STOP_REQUESTED}`,
|
|
40
|
+
'KillMode=process',
|
|
41
|
+
'TimeoutStopSec=20',
|
|
42
|
+
'',
|
|
43
|
+
'[Install]',
|
|
44
|
+
'WantedBy=default.target',
|
|
45
|
+
'',
|
|
46
|
+
].join('\n');
|
|
47
|
+
}
|
|
48
|
+
async function systemctl(steps, ...args) {
|
|
49
|
+
return steps.run(steps.systemctl ?? 'systemctl', ['--user', ...args]);
|
|
50
|
+
}
|
|
51
|
+
export async function installSystemd(name, program, steps, unitPath = systemdUnitPath(name)) {
|
|
52
|
+
mkdirSync(dirname(unitPath), { recursive: true });
|
|
53
|
+
writeFileSync(unitPath, systemdUnit(program), { mode: 0o644 });
|
|
54
|
+
const problems = [];
|
|
55
|
+
for (const args of [['daemon-reload'], ['enable', '--now', `${name}.service`]]) {
|
|
56
|
+
const result = await systemctl(steps, ...args);
|
|
57
|
+
if (result.code !== 0)
|
|
58
|
+
problems.push(`systemctl --user ${args.join(' ')}: ${result.stderr.trim() || `exit ${result.code}`}`);
|
|
59
|
+
}
|
|
60
|
+
return problems;
|
|
61
|
+
}
|
|
62
|
+
export async function uninstallSystemd(name, steps, unitPath = systemdUnitPath(name)) {
|
|
63
|
+
const problems = [];
|
|
64
|
+
await systemctl(steps, 'disable', '--now', `${name}.service`);
|
|
65
|
+
rmSync(unitPath, { force: true });
|
|
66
|
+
await systemctl(steps, 'daemon-reload');
|
|
67
|
+
await systemctl(steps, 'reset-failed', `${name}.service`);
|
|
68
|
+
if (existsSync(unitPath))
|
|
69
|
+
problems.push(`${unitPath} is still there`);
|
|
70
|
+
const shown = await systemctl(steps, 'show', `${name}.service`, '--property=LoadState');
|
|
71
|
+
if (shown.code === 0 && /LoadState=loaded/.test(shown.stdout))
|
|
72
|
+
problems.push(`${name}.service is still loaded`);
|
|
73
|
+
return problems;
|
|
74
|
+
}
|
|
75
|
+
export async function systemdState(name, steps) {
|
|
76
|
+
const result = await systemctl(steps, 'is-active', `${name}.service`);
|
|
77
|
+
return result.stdout.trim() || result.stderr.trim() || 'unknown';
|
|
78
|
+
}
|
|
79
|
+
/** Enable and start: `stop` disabled it. */
|
|
80
|
+
export async function startSystemd(name, steps) {
|
|
81
|
+
const result = await systemctl(steps, 'enable', '--now', `${name}.service`);
|
|
82
|
+
return result.code === 0 ? [] : [result.stderr.trim() || `exit ${result.code}`];
|
|
83
|
+
}
|
|
84
|
+
/** Disable and stop, so the next login does not start it again. */
|
|
85
|
+
export async function stopSystemd(name, steps) {
|
|
86
|
+
const result = await systemctl(steps, 'disable', '--now', `${name}.service`);
|
|
87
|
+
return result.code === 0 ? [] : [result.stderr.trim() || `exit ${result.code}`];
|
|
88
|
+
}
|
|
89
|
+
/** Whether a systemd user manager answers here. */
|
|
90
|
+
export async function systemdUserAvailable(steps) {
|
|
91
|
+
if (!existsSync('/run/systemd/system'))
|
|
92
|
+
return false;
|
|
93
|
+
const result = await systemctl(steps, 'show-environment');
|
|
94
|
+
return result.code === 0;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=systemd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemd.js","sourceRoot":"","sources":["../../../src/schedule/service/systemd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows Task Scheduler, natively and from WSL.
|
|
3
|
+
*
|
|
4
|
+
* Two triggers: at the user's logon, and a time trigger that repeats every
|
|
5
|
+
* five minutes forever. Task Scheduler's restart-on-failure reacts to a task
|
|
6
|
+
* that fails to LAUNCH, not to a non-zero exit, so after `wsl --shutdown` or a
|
|
7
|
+
* crash only the repetition brings the daemon back. `IgnoreNew` makes a
|
|
8
|
+
* repetition a no-op while the daemon runs; `schedule stop` therefore DISABLES
|
|
9
|
+
* the task (ending it would be undone within five minutes).
|
|
10
|
+
*
|
|
11
|
+
* The task names its user (`DOMAIN\user`) on the principal and on the logon
|
|
12
|
+
* trigger: a logon trigger without one applies to every user and needs
|
|
13
|
+
* elevation to register. "Run only when the user is logged on"
|
|
14
|
+
* (InteractiveToken): WSL fails to start from a non-interactive task.
|
|
15
|
+
*
|
|
16
|
+
* `schtasks /XML` reads UTF-16; the file is written UTF-16LE with a BOM to
|
|
17
|
+
* match its declaration.
|
|
18
|
+
*/
|
|
19
|
+
export interface TaskDefinition {
|
|
20
|
+
/** `DOMAIN\user`, from `whoami.exe`. */
|
|
21
|
+
readonly userId: string;
|
|
22
|
+
readonly description: string;
|
|
23
|
+
/** Windows path of the program. */
|
|
24
|
+
readonly command: string;
|
|
25
|
+
readonly args: readonly string[];
|
|
26
|
+
/** When the repetition starts; any past instant. */
|
|
27
|
+
readonly startBoundary?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function taskXml(task: TaskDefinition): string;
|
|
30
|
+
/** The task file's bytes: UTF-16LE with a byte-order mark. */
|
|
31
|
+
export declare function taskXmlBytes(xml: string): Buffer;
|
|
32
|
+
/** The task's path in the scheduler's library. */
|
|
33
|
+
export declare function taskPath(name: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Delete the `\namzu` Task Scheduler folder that `/Create` made, when no
|
|
36
|
+
* task (hidden ones included) and no subfolder is left in it. `schtasks
|
|
37
|
+
* /Delete` removes a task and never its folder, and `schtasks /Query` does not
|
|
38
|
+
* show an empty folder, so without this an uninstall left one behind.
|
|
39
|
+
* Exits 1 only when the folder is still there and empty. A constant: nothing
|
|
40
|
+
* is interpolated into it.
|
|
41
|
+
*/
|
|
42
|
+
export declare const REMOVE_EMPTY_TASK_FOLDER_SCRIPT: string;
|
|
43
|
+
/** `powershell.exe` arguments that run {@link REMOVE_EMPTY_TASK_FOLDER_SCRIPT}. */
|
|
44
|
+
export declare function removeEmptyTaskFolderArguments(): string[];
|
|
45
|
+
/** `schtasks /Query … /FO LIST /V` → the fields a status line needs. */
|
|
46
|
+
export declare function parseTaskQuery(output: string): {
|
|
47
|
+
status?: string;
|
|
48
|
+
state?: string;
|
|
49
|
+
lastResult?: string;
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=windows-task.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows-task.d.ts","sourceRoot":"","sources":["../../../src/schedule/service/windows-task.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,MAAM,WAAW,cAAc;IAC9B,wCAAwC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,mCAAmC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,oDAAoD;IACpD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CA0DpD;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,kDAAkD;AAClD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,QAQhC,CAAA;AAEZ,mFAAmF;AACnF,wBAAgB,8BAA8B,IAAI,MAAM,EAAE,CASzD;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB,CAgBA"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows Task Scheduler, natively and from WSL.
|
|
3
|
+
*
|
|
4
|
+
* Two triggers: at the user's logon, and a time trigger that repeats every
|
|
5
|
+
* five minutes forever. Task Scheduler's restart-on-failure reacts to a task
|
|
6
|
+
* that fails to LAUNCH, not to a non-zero exit, so after `wsl --shutdown` or a
|
|
7
|
+
* crash only the repetition brings the daemon back. `IgnoreNew` makes a
|
|
8
|
+
* repetition a no-op while the daemon runs; `schedule stop` therefore DISABLES
|
|
9
|
+
* the task (ending it would be undone within five minutes).
|
|
10
|
+
*
|
|
11
|
+
* The task names its user (`DOMAIN\user`) on the principal and on the logon
|
|
12
|
+
* trigger: a logon trigger without one applies to every user and needs
|
|
13
|
+
* elevation to register. "Run only when the user is logged on"
|
|
14
|
+
* (InteractiveToken): WSL fails to start from a non-interactive task.
|
|
15
|
+
*
|
|
16
|
+
* `schtasks /XML` reads UTF-16; the file is written UTF-16LE with a BOM to
|
|
17
|
+
* match its declaration.
|
|
18
|
+
*/
|
|
19
|
+
import { windowsArgument, xmlText } from './quote.js';
|
|
20
|
+
export function taskXml(task) {
|
|
21
|
+
const start = task.startBoundary ?? '2026-01-01T00:00:00';
|
|
22
|
+
return [
|
|
23
|
+
'<?xml version="1.0" encoding="UTF-16"?>',
|
|
24
|
+
'<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">',
|
|
25
|
+
' <RegistrationInfo>',
|
|
26
|
+
` <Description>${xmlText(task.description)}</Description>`,
|
|
27
|
+
` <Author>${xmlText(task.userId)}</Author>`,
|
|
28
|
+
' </RegistrationInfo>',
|
|
29
|
+
' <Triggers>',
|
|
30
|
+
' <LogonTrigger>',
|
|
31
|
+
' <Enabled>true</Enabled>',
|
|
32
|
+
` <UserId>${xmlText(task.userId)}</UserId>`,
|
|
33
|
+
' </LogonTrigger>',
|
|
34
|
+
' <TimeTrigger>',
|
|
35
|
+
' <Repetition>',
|
|
36
|
+
' <Interval>PT5M</Interval>',
|
|
37
|
+
' <StopAtDurationEnd>false</StopAtDurationEnd>',
|
|
38
|
+
' </Repetition>',
|
|
39
|
+
` <StartBoundary>${xmlText(start)}</StartBoundary>`,
|
|
40
|
+
' <Enabled>true</Enabled>',
|
|
41
|
+
' </TimeTrigger>',
|
|
42
|
+
' </Triggers>',
|
|
43
|
+
' <Principals>',
|
|
44
|
+
' <Principal id="Author">',
|
|
45
|
+
` <UserId>${xmlText(task.userId)}</UserId>`,
|
|
46
|
+
' <LogonType>InteractiveToken</LogonType>',
|
|
47
|
+
' <RunLevel>LeastPrivilege</RunLevel>',
|
|
48
|
+
' </Principal>',
|
|
49
|
+
' </Principals>',
|
|
50
|
+
' <Settings>',
|
|
51
|
+
' <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>',
|
|
52
|
+
' <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>',
|
|
53
|
+
' <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>',
|
|
54
|
+
' <AllowHardTerminate>true</AllowHardTerminate>',
|
|
55
|
+
' <StartWhenAvailable>true</StartWhenAvailable>',
|
|
56
|
+
' <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>',
|
|
57
|
+
' <IdleSettings>',
|
|
58
|
+
' <StopOnIdleEnd>false</StopOnIdleEnd>',
|
|
59
|
+
' <RestartOnIdle>false</RestartOnIdle>',
|
|
60
|
+
' </IdleSettings>',
|
|
61
|
+
' <AllowStartOnDemand>true</AllowStartOnDemand>',
|
|
62
|
+
' <Enabled>true</Enabled>',
|
|
63
|
+
' <Hidden>false</Hidden>',
|
|
64
|
+
' <RunOnlyIfIdle>false</RunOnlyIfIdle>',
|
|
65
|
+
' <WakeToRun>false</WakeToRun>',
|
|
66
|
+
' <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>',
|
|
67
|
+
' <Priority>7</Priority>',
|
|
68
|
+
' </Settings>',
|
|
69
|
+
' <Actions Context="Author">',
|
|
70
|
+
' <Exec>',
|
|
71
|
+
` <Command>${xmlText(task.command)}</Command>`,
|
|
72
|
+
` <Arguments>${xmlText(task.args.map(windowsArgument).join(' '))}</Arguments>`,
|
|
73
|
+
' </Exec>',
|
|
74
|
+
' </Actions>',
|
|
75
|
+
'</Task>',
|
|
76
|
+
'',
|
|
77
|
+
].join('\r\n');
|
|
78
|
+
}
|
|
79
|
+
/** The task file's bytes: UTF-16LE with a byte-order mark. */
|
|
80
|
+
export function taskXmlBytes(xml) {
|
|
81
|
+
return Buffer.concat([Buffer.from([0xff, 0xfe]), Buffer.from(xml, 'utf16le')]);
|
|
82
|
+
}
|
|
83
|
+
/** The task's path in the scheduler's library. */
|
|
84
|
+
export function taskPath(name) {
|
|
85
|
+
return `\\namzu\\${name}`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Delete the `\namzu` Task Scheduler folder that `/Create` made, when no
|
|
89
|
+
* task (hidden ones included) and no subfolder is left in it. `schtasks
|
|
90
|
+
* /Delete` removes a task and never its folder, and `schtasks /Query` does not
|
|
91
|
+
* show an empty folder, so without this an uninstall left one behind.
|
|
92
|
+
* Exits 1 only when the folder is still there and empty. A constant: nothing
|
|
93
|
+
* is interpolated into it.
|
|
94
|
+
*/
|
|
95
|
+
export const REMOVE_EMPTY_TASK_FOLDER_SCRIPT = [
|
|
96
|
+
"$ErrorActionPreference = 'Stop'",
|
|
97
|
+
'$s = New-Object -ComObject Schedule.Service',
|
|
98
|
+
'$s.Connect()',
|
|
99
|
+
"try { $f = $s.GetFolder('\\namzu') } catch { exit 0 }",
|
|
100
|
+
'if ($f.GetTasks(1).Count -gt 0 -or $f.GetFolders(0).Count -gt 0) { exit 0 }',
|
|
101
|
+
"try { $s.GetFolder('\\').DeleteFolder('namzu', 0) } catch { exit 1 }",
|
|
102
|
+
'exit 0',
|
|
103
|
+
].join('; ');
|
|
104
|
+
/** `powershell.exe` arguments that run {@link REMOVE_EMPTY_TASK_FOLDER_SCRIPT}. */
|
|
105
|
+
export function removeEmptyTaskFolderArguments() {
|
|
106
|
+
return [
|
|
107
|
+
'-NoProfile',
|
|
108
|
+
'-NonInteractive',
|
|
109
|
+
'-ExecutionPolicy',
|
|
110
|
+
'Bypass',
|
|
111
|
+
'-EncodedCommand',
|
|
112
|
+
Buffer.from(REMOVE_EMPTY_TASK_FOLDER_SCRIPT, 'utf16le').toString('base64'),
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
/** `schtasks /Query … /FO LIST /V` → the fields a status line needs. */
|
|
116
|
+
export function parseTaskQuery(output) {
|
|
117
|
+
const field = (label) => {
|
|
118
|
+
for (const line of output.split(/\r?\n/)) {
|
|
119
|
+
const match = /^([^:]+):\s*(.*)$/.exec(line);
|
|
120
|
+
if (match && label.test((match[1] ?? '').trim()))
|
|
121
|
+
return (match[2] ?? '').trim();
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
124
|
+
};
|
|
125
|
+
const status = field(/^Status$/i);
|
|
126
|
+
const state = field(/^Scheduled Task State$/i);
|
|
127
|
+
const lastResult = field(/^Last Result$/i);
|
|
128
|
+
return {
|
|
129
|
+
...(status !== undefined ? { status } : {}),
|
|
130
|
+
...(state !== undefined ? { state } : {}),
|
|
131
|
+
...(lastResult !== undefined ? { lastResult } : {}),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=windows-task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows-task.js","sourceRoot":"","sources":["../../../src/schedule/service/windows-task.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WSL: the daemon runs inside the distro, supervised by Windows Task
|
|
3
|
+
* Scheduler through `wsl.exe`.
|
|
4
|
+
*
|
|
5
|
+
* A distro is not running after Windows logs on until something starts it,
|
|
6
|
+
* and a systemd unit inside the distro cannot start its own distro; the
|
|
7
|
+
* `wsl.exe` process the task holds open both starts it and keeps WSL's idle
|
|
8
|
+
* shutdown away. The Windows programs are resolved once, here, from their
|
|
9
|
+
* fixed locations — never through PATH, whose `/mnt` entries make a failed
|
|
10
|
+
* lookup cost seconds — and recorded in the manifest.
|
|
11
|
+
*
|
|
12
|
+
* Refused at install: interop that does not answer, a node or CLI whose path
|
|
13
|
+
* `wsl.exe` would re-parse into something else, and a CLI running from the
|
|
14
|
+
* npx cache (it disappears).
|
|
15
|
+
*/
|
|
16
|
+
import type { CommandRunner } from './runner.js';
|
|
17
|
+
import { type TaskDefinition, taskPath } from './windows-task.js';
|
|
18
|
+
export interface WindowsTools {
|
|
19
|
+
readonly systemRoot: string;
|
|
20
|
+
readonly cmd: string;
|
|
21
|
+
readonly schtasks: string;
|
|
22
|
+
readonly powershell: string;
|
|
23
|
+
readonly whoami: string;
|
|
24
|
+
readonly conhost: string;
|
|
25
|
+
readonly wsl: string;
|
|
26
|
+
}
|
|
27
|
+
export declare const DEFAULT_SYSTEM32 = "/mnt/c/Windows/System32";
|
|
28
|
+
export declare function windowsTools(system32?: string): WindowsTools;
|
|
29
|
+
/** Interop answers: a Windows program starts and exits 0. */
|
|
30
|
+
export declare function probeInterop(run: CommandRunner, tools: WindowsTools, env?: NodeJS.ProcessEnv): Promise<{
|
|
31
|
+
ok: true;
|
|
32
|
+
} | {
|
|
33
|
+
ok: false;
|
|
34
|
+
reason: string;
|
|
35
|
+
}>;
|
|
36
|
+
/** `DOMAIN\user` of the Windows account, from `whoami.exe`. */
|
|
37
|
+
export declare function windowsUser(run: CommandRunner, tools: WindowsTools): Promise<string>;
|
|
38
|
+
/** A Linux path as Windows sees it, through `wslpath -w`. */
|
|
39
|
+
export declare function toWindowsPath(run: CommandRunner, path: string): Promise<string>;
|
|
40
|
+
/** Whether a CLI path is inside the npx cache, which is not kept. */
|
|
41
|
+
export declare function isEphemeralBin(bin: string): boolean;
|
|
42
|
+
export declare function wslTaskName(name: string, distro: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* The task that runs the daemon in the distro. `conhost.exe --headless` keeps
|
|
45
|
+
* a console window from appearing at logon.
|
|
46
|
+
*/
|
|
47
|
+
export declare function wslTaskDefinition(options: {
|
|
48
|
+
readonly userId: string;
|
|
49
|
+
readonly distro: string;
|
|
50
|
+
readonly linuxUser: string;
|
|
51
|
+
readonly node: string;
|
|
52
|
+
readonly bin: string;
|
|
53
|
+
readonly namzuHome: string;
|
|
54
|
+
readonly systemRoot?: string;
|
|
55
|
+
}): TaskDefinition;
|
|
56
|
+
export { taskPath };
|
|
57
|
+
//# sourceMappingURL=wsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wsl.d.ts","sourceRoot":"","sources":["../../../src/schedule/service/wsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,KAAK,cAAc,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjE,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACpB;AAED,eAAO,MAAM,gBAAgB,4BAA4B,CAAA;AAEzD,wBAAgB,YAAY,CAAC,QAAQ,SAAmB,GAAG,YAAY,CAUtE;AAED,6DAA6D;AAC7D,wBAAsB,YAAY,CACjC,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,YAAY,EACnB,GAAG,GAAE,MAAM,CAAC,UAAwB,GAClC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBvD;AAED,+DAA+D;AAC/D,wBAAsB,WAAW,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1F;AAED,6DAA6D;AAC7D,wBAAsB,aAAa,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIrF;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC5B,GAAG,cAAc,CAiCjB;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|