@agentrhq/webcmd 0.1.1 → 0.1.2
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/README.md +317 -24
- package/dist/src/adapter-shadow.d.ts +11 -0
- package/dist/src/adapter-shadow.js +72 -0
- package/dist/src/adapter-shadow.test.d.ts +1 -0
- package/dist/src/adapter-shadow.test.js +49 -0
- package/dist/src/adapter-source.d.ts +11 -0
- package/dist/src/adapter-source.js +24 -0
- package/dist/src/adapter-source.test.d.ts +1 -0
- package/dist/src/adapter-source.test.js +29 -0
- package/dist/src/brand.d.ts +9 -0
- package/dist/src/brand.js +9 -0
- package/dist/src/brand.test.d.ts +1 -0
- package/dist/src/brand.test.js +15 -0
- package/dist/src/browser/analyze.d.ts +118 -0
- package/dist/src/browser/analyze.js +405 -0
- package/dist/src/browser/analyze.test.d.ts +1 -0
- package/dist/src/browser/analyze.test.js +209 -0
- package/dist/src/browser/article-extract.d.ts +57 -0
- package/dist/src/browser/article-extract.e2e.test.d.ts +1 -0
- package/dist/src/browser/article-extract.e2e.test.js +105 -0
- package/dist/src/browser/article-extract.js +169 -0
- package/dist/src/browser/article-extract.test.d.ts +1 -0
- package/dist/src/browser/article-extract.test.js +94 -0
- package/dist/src/browser/ax-snapshot.d.ts +37 -0
- package/dist/src/browser/ax-snapshot.js +217 -0
- package/dist/src/browser/ax-snapshot.test.d.ts +1 -0
- package/dist/src/browser/ax-snapshot.test.js +91 -0
- package/dist/src/browser/base-page.d.ts +151 -0
- package/dist/src/browser/base-page.js +1060 -0
- package/dist/src/browser/base-page.test.d.ts +1 -0
- package/dist/src/browser/base-page.test.js +803 -0
- package/dist/src/browser/bridge-readiness.d.ts +14 -0
- package/dist/src/browser/bridge-readiness.js +24 -0
- package/dist/src/browser/bridge-readiness.test.d.ts +1 -0
- package/dist/src/browser/bridge-readiness.test.js +58 -0
- package/dist/src/browser/bridge.d.ts +26 -0
- package/dist/src/browser/bridge.js +58 -0
- package/dist/src/browser/cdp-click-fixture.test.d.ts +1 -0
- package/dist/src/browser/cdp-click-fixture.test.js +87 -0
- package/dist/src/browser/cdp.d.ts +46 -0
- package/dist/src/browser/cdp.js +536 -0
- package/dist/src/browser/cdp.test.d.ts +1 -0
- package/dist/src/browser/cdp.test.js +79 -0
- package/dist/src/browser/compound.d.ts +59 -0
- package/dist/src/browser/compound.js +112 -0
- package/dist/src/browser/compound.test.d.ts +1 -0
- package/dist/src/browser/compound.test.js +175 -0
- package/dist/src/browser/config.d.ts +2 -0
- package/dist/src/browser/config.js +14 -0
- package/dist/src/browser/daemon-client.d.ts +32 -0
- package/dist/src/browser/daemon-client.js +135 -0
- package/dist/src/browser/daemon-client.test.d.ts +1 -0
- package/dist/src/browser/daemon-client.test.js +326 -0
- package/dist/src/browser/daemon-lifecycle.d.ts +37 -0
- package/dist/src/browser/daemon-lifecycle.js +147 -0
- package/dist/src/browser/daemon-transport.d.ts +54 -0
- package/dist/src/browser/daemon-transport.js +68 -0
- package/dist/src/browser/daemon-version.d.ts +4 -0
- package/dist/src/browser/daemon-version.js +12 -0
- package/dist/src/browser/dom-helpers.d.ts +41 -0
- package/dist/src/browser/dom-helpers.js +239 -0
- package/dist/src/browser/dom-helpers.test.d.ts +1 -0
- package/dist/src/browser/dom-helpers.test.js +106 -0
- package/dist/src/browser/dom-snapshot.d.ts +93 -0
- package/dist/src/browser/dom-snapshot.js +894 -0
- package/dist/src/browser/dom-snapshot.test.d.ts +11 -0
- package/dist/src/browser/dom-snapshot.test.js +313 -0
- package/dist/src/browser/errors.d.ts +38 -0
- package/dist/src/browser/errors.js +79 -0
- package/dist/src/browser/errors.test.d.ts +1 -0
- package/dist/src/browser/errors.test.js +60 -0
- package/dist/src/browser/extract.d.ts +69 -0
- package/dist/src/browser/extract.js +132 -0
- package/dist/src/browser/extract.test.d.ts +1 -0
- package/dist/src/browser/extract.test.js +129 -0
- package/dist/src/browser/find.d.ts +84 -0
- package/dist/src/browser/find.js +398 -0
- package/dist/src/browser/find.test.d.ts +1 -0
- package/dist/src/browser/find.test.js +180 -0
- package/dist/src/browser/html-tree.d.ts +75 -0
- package/dist/src/browser/html-tree.js +112 -0
- package/dist/src/browser/html-tree.test.d.ts +1 -0
- package/dist/src/browser/html-tree.test.js +181 -0
- package/dist/src/browser/index.d.ts +14 -0
- package/dist/src/browser/index.js +12 -0
- package/dist/src/browser/network-cache.d.ts +49 -0
- package/dist/src/browser/network-cache.js +78 -0
- package/dist/src/browser/network-cache.test.d.ts +1 -0
- package/dist/src/browser/network-cache.test.js +75 -0
- package/dist/src/browser/network-interceptor.d.ts +11 -0
- package/dist/src/browser/network-interceptor.js +11 -0
- package/dist/src/browser/network-key.d.ts +22 -0
- package/dist/src/browser/network-key.js +66 -0
- package/dist/src/browser/network-key.test.d.ts +1 -0
- package/dist/src/browser/network-key.test.js +49 -0
- package/dist/src/browser/page.d.ts +83 -0
- package/dist/src/browser/page.js +453 -0
- package/dist/src/browser/page.test.d.ts +1 -0
- package/dist/src/browser/page.test.js +406 -0
- package/dist/src/browser/profile.d.ts +14 -0
- package/dist/src/browser/profile.js +86 -0
- package/dist/src/browser/protocol.d.ts +63 -0
- package/dist/src/browser/protocol.js +1 -0
- package/dist/src/browser/runtime/local-cloak/actions.d.ts +3 -0
- package/dist/src/browser/runtime/local-cloak/actions.js +240 -0
- package/dist/src/browser/runtime/local-cloak/downloads.d.ts +3 -0
- package/dist/src/browser/runtime/local-cloak/downloads.js +28 -0
- package/dist/src/browser/runtime/local-cloak/network.d.ts +28 -0
- package/dist/src/browser/runtime/local-cloak/network.js +120 -0
- package/dist/src/browser/runtime/local-cloak/network.test.d.ts +1 -0
- package/dist/src/browser/runtime/local-cloak/network.test.js +124 -0
- package/dist/src/browser/runtime/local-cloak/profiles.d.ts +6 -0
- package/dist/src/browser/runtime/local-cloak/profiles.js +17 -0
- package/dist/src/browser/runtime/local-cloak/profiles.test.d.ts +1 -0
- package/dist/src/browser/runtime/local-cloak/profiles.test.js +19 -0
- package/dist/src/browser/runtime/local-cloak/provider.d.ts +15 -0
- package/dist/src/browser/runtime/local-cloak/provider.js +27 -0
- package/dist/src/browser/runtime/local-cloak/provider.test.d.ts +1 -0
- package/dist/src/browser/runtime/local-cloak/provider.test.js +244 -0
- package/dist/src/browser/runtime/local-cloak/session-manager.d.ts +77 -0
- package/dist/src/browser/runtime/local-cloak/session-manager.js +280 -0
- package/dist/src/browser/runtime/local-cloak/session-manager.test.d.ts +1 -0
- package/dist/src/browser/runtime/local-cloak/session-manager.test.js +92 -0
- package/dist/src/browser/runtime/provider.d.ts +9 -0
- package/dist/src/browser/runtime/provider.js +1 -0
- package/dist/src/browser/runtime/provider.test.d.ts +2 -0
- package/dist/src/browser/runtime/provider.test.js +49 -0
- package/dist/src/browser/shape-filter.d.ts +52 -0
- package/dist/src/browser/shape-filter.js +101 -0
- package/dist/src/browser/shape-filter.test.d.ts +1 -0
- package/dist/src/browser/shape-filter.test.js +101 -0
- package/dist/src/browser/shape.d.ts +23 -0
- package/dist/src/browser/shape.js +95 -0
- package/dist/src/browser/shape.test.d.ts +1 -0
- package/dist/src/browser/shape.test.js +82 -0
- package/dist/src/browser/stealth.d.ts +11 -0
- package/dist/src/browser/stealth.js +359 -0
- package/dist/src/browser/stealth.test.d.ts +1 -0
- package/dist/src/browser/stealth.test.js +134 -0
- package/dist/src/browser/tabs.d.ts +13 -0
- package/dist/src/browser/tabs.js +70 -0
- package/dist/src/browser/target-errors.d.ts +39 -0
- package/dist/src/browser/target-errors.js +45 -0
- package/dist/src/browser/target-errors.test.d.ts +1 -0
- package/dist/src/browser/target-errors.test.js +94 -0
- package/dist/src/browser/target-resolver.d.ts +158 -0
- package/dist/src/browser/target-resolver.js +570 -0
- package/dist/src/browser/target-resolver.test.d.ts +1 -0
- package/dist/src/browser/target-resolver.test.js +118 -0
- package/dist/src/browser/utils.d.ts +20 -0
- package/dist/src/browser/utils.js +64 -0
- package/dist/src/browser/utils.test.d.ts +1 -0
- package/dist/src/browser/utils.test.js +29 -0
- package/dist/src/browser/verify-fixture.d.ts +65 -0
- package/dist/src/browser/verify-fixture.js +318 -0
- package/dist/src/browser/verify-fixture.test.d.ts +1 -0
- package/dist/src/browser/verify-fixture.test.js +219 -0
- package/dist/src/browser/visual-refs.d.ts +11 -0
- package/dist/src/browser/visual-refs.js +108 -0
- package/dist/src/browser.test.d.ts +1 -0
- package/dist/src/browser.test.js +297 -0
- package/dist/src/build-manifest.d.ts +103 -0
- package/dist/src/build-manifest.js +363 -0
- package/dist/src/build-manifest.test.d.ts +1 -0
- package/dist/src/build-manifest.test.js +341 -0
- package/dist/src/capabilityRouting.d.ts +19 -0
- package/dist/src/capabilityRouting.js +56 -0
- package/dist/src/capabilityRouting.test.d.ts +1 -0
- package/dist/src/capabilityRouting.test.js +63 -0
- package/dist/src/cli-argv-preprocess.d.ts +63 -0
- package/dist/src/cli-argv-preprocess.js +303 -0
- package/dist/src/cli-argv-preprocess.test.d.ts +1 -0
- package/dist/src/cli-argv-preprocess.test.js +304 -0
- package/dist/src/cli.d.ts +79 -0
- package/dist/src/cli.js +3350 -0
- package/dist/src/cli.test.d.ts +1 -0
- package/dist/src/cli.test.js +3041 -0
- package/dist/src/commanderAdapter.d.ts +21 -0
- package/dist/src/commanderAdapter.js +208 -0
- package/dist/src/commanderAdapter.test.d.ts +1 -0
- package/dist/src/commanderAdapter.test.js +352 -0
- package/dist/src/commands/auth.d.ts +40 -0
- package/dist/src/commands/auth.js +434 -0
- package/dist/src/commands/auth.test.d.ts +1 -0
- package/dist/src/commands/auth.test.js +252 -0
- package/dist/src/commands/daemon.d.ts +9 -0
- package/dist/src/commands/daemon.js +91 -0
- package/dist/src/commands/daemon.test.d.ts +1 -0
- package/dist/src/commands/daemon.test.js +293 -0
- package/dist/src/completion-fast.d.ts +22 -0
- package/dist/src/completion-fast.js +88 -0
- package/dist/src/completion-shared.d.ts +13 -0
- package/dist/src/completion-shared.js +61 -0
- package/dist/src/completion.d.ts +21 -0
- package/dist/src/completion.js +68 -0
- package/dist/src/completion.test.d.ts +1 -0
- package/dist/src/completion.test.js +24 -0
- package/dist/src/constants.d.ts +18 -0
- package/dist/src/constants.js +41 -0
- package/dist/src/convention-audit.d.ts +50 -0
- package/dist/src/convention-audit.js +553 -0
- package/dist/src/convention-audit.test.d.ts +1 -0
- package/dist/src/convention-audit.test.js +255 -0
- package/dist/src/daemon/server.d.ts +13 -0
- package/dist/src/daemon/server.js +185 -0
- package/dist/src/daemon/server.test.d.ts +1 -0
- package/dist/src/daemon/server.test.js +132 -0
- package/dist/src/daemon-utils.d.ts +18 -0
- package/dist/src/daemon-utils.js +37 -0
- package/dist/src/daemon.d.ts +1 -0
- package/dist/src/daemon.js +27 -0
- package/dist/src/daemon.test.d.ts +1 -0
- package/dist/src/daemon.test.js +60 -0
- package/dist/src/discovery.d.ts +46 -0
- package/dist/src/discovery.js +341 -0
- package/dist/src/doctor.d.ts +39 -0
- package/dist/src/doctor.js +168 -0
- package/dist/src/doctor.test.d.ts +1 -0
- package/dist/src/doctor.test.js +302 -0
- package/dist/src/download/article-download.d.ts +72 -0
- package/dist/src/download/article-download.js +305 -0
- package/dist/src/download/article-download.test.d.ts +1 -0
- package/dist/src/download/article-download.test.js +235 -0
- package/dist/src/download/index.d.ts +71 -0
- package/dist/src/download/index.js +363 -0
- package/dist/src/download/index.test.d.ts +1 -0
- package/dist/src/download/index.test.js +174 -0
- package/dist/src/download/media-download.d.ts +49 -0
- package/dist/src/download/media-download.js +127 -0
- package/dist/src/download/media-download.test.d.ts +1 -0
- package/dist/src/download/media-download.test.js +112 -0
- package/dist/src/download/progress.d.ts +36 -0
- package/dist/src/download/progress.js +120 -0
- package/dist/src/download/progress.test.d.ts +1 -0
- package/dist/src/download/progress.test.js +36 -0
- package/dist/src/electron-apps.d.ts +31 -0
- package/dist/src/electron-apps.js +91 -0
- package/dist/src/electron-apps.test.d.ts +1 -0
- package/dist/src/electron-apps.test.js +76 -0
- package/dist/src/engine.test.d.ts +1 -0
- package/dist/src/engine.test.js +312 -0
- package/dist/src/errors.d.ts +114 -0
- package/dist/src/errors.js +174 -0
- package/dist/src/errors.test.d.ts +1 -0
- package/dist/src/errors.test.js +109 -0
- package/dist/src/execution.d.ts +24 -0
- package/dist/src/execution.js +509 -0
- package/dist/src/execution.test.d.ts +1 -0
- package/dist/src/execution.test.js +645 -0
- package/dist/src/external.d.ts +49 -0
- package/dist/src/external.js +211 -0
- package/dist/src/external.test.d.ts +1 -0
- package/dist/src/external.test.js +110 -0
- package/dist/src/help.d.ts +88 -0
- package/dist/src/help.js +556 -0
- package/dist/src/help.test.d.ts +1 -0
- package/dist/src/help.test.js +58 -0
- package/dist/src/hooks.d.ts +46 -0
- package/dist/src/hooks.js +58 -0
- package/dist/src/hooks.test.d.ts +4 -0
- package/dist/src/hooks.test.js +92 -0
- package/dist/src/interceptor.d.ts +44 -0
- package/dist/src/interceptor.js +183 -0
- package/dist/src/interceptor.test.d.ts +4 -0
- package/dist/src/interceptor.test.js +81 -0
- package/dist/src/launcher.d.ts +41 -0
- package/dist/src/launcher.js +226 -0
- package/dist/src/launcher.test.d.ts +1 -0
- package/dist/src/launcher.test.js +153 -0
- package/dist/src/logger.d.ts +26 -0
- package/dist/src/logger.js +49 -0
- package/dist/src/main.d.ts +5 -0
- package/dist/src/main.js +177 -0
- package/dist/src/manifest-types.d.ts +43 -0
- package/dist/src/manifest-types.js +9 -0
- package/dist/src/node-network.d.ts +10 -0
- package/dist/src/node-network.js +174 -0
- package/dist/src/node-network.test.d.ts +1 -0
- package/dist/src/node-network.test.js +55 -0
- package/dist/src/observation/artifact.d.ts +16 -0
- package/dist/src/observation/artifact.js +260 -0
- package/dist/src/observation/artifact.test.d.ts +1 -0
- package/dist/src/observation/artifact.test.js +121 -0
- package/dist/src/observation/events.d.ts +89 -0
- package/dist/src/observation/events.js +1 -0
- package/dist/src/observation/index.d.ts +7 -0
- package/dist/src/observation/index.js +7 -0
- package/dist/src/observation/manager.d.ts +9 -0
- package/dist/src/observation/manager.js +27 -0
- package/dist/src/observation/manager.test.d.ts +1 -0
- package/dist/src/observation/manager.test.js +13 -0
- package/dist/src/observation/redaction.d.ts +11 -0
- package/dist/src/observation/redaction.js +81 -0
- package/dist/src/observation/redaction.test.d.ts +1 -0
- package/dist/src/observation/redaction.test.js +32 -0
- package/dist/src/observation/retention.d.ts +32 -0
- package/dist/src/observation/retention.js +160 -0
- package/dist/src/observation/retention.test.d.ts +1 -0
- package/dist/src/observation/retention.test.js +118 -0
- package/dist/src/observation/ring-buffer.d.ts +22 -0
- package/dist/src/observation/ring-buffer.js +45 -0
- package/dist/src/observation/ring-buffer.test.d.ts +1 -0
- package/dist/src/observation/ring-buffer.test.js +22 -0
- package/dist/src/observation/session.d.ts +25 -0
- package/dist/src/observation/session.js +50 -0
- package/dist/src/output.d.ts +14 -0
- package/dist/src/output.js +152 -0
- package/dist/src/output.test.d.ts +1 -0
- package/dist/src/output.test.js +53 -0
- package/dist/src/package-exports.test.d.ts +1 -0
- package/dist/src/package-exports.test.js +112 -0
- package/dist/src/package-paths.d.ts +8 -0
- package/dist/src/package-paths.js +41 -0
- package/dist/src/pipeline/executor.d.ts +11 -0
- package/dist/src/pipeline/executor.js +93 -0
- package/dist/src/pipeline/executor.test.d.ts +4 -0
- package/dist/src/pipeline/executor.test.js +182 -0
- package/dist/src/pipeline/index.d.ts +5 -0
- package/dist/src/pipeline/index.js +5 -0
- package/dist/src/pipeline/registry.d.ts +28 -0
- package/dist/src/pipeline/registry.js +55 -0
- package/dist/src/pipeline/steps/browser.d.ts +13 -0
- package/dist/src/pipeline/steps/browser.js +86 -0
- package/dist/src/pipeline/steps/download.d.ts +18 -0
- package/dist/src/pipeline/steps/download.js +252 -0
- package/dist/src/pipeline/steps/download.test.d.ts +1 -0
- package/dist/src/pipeline/steps/download.test.js +102 -0
- package/dist/src/pipeline/steps/fetch.d.ts +5 -0
- package/dist/src/pipeline/steps/fetch.js +122 -0
- package/dist/src/pipeline/steps/fetch.test.d.ts +1 -0
- package/dist/src/pipeline/steps/fetch.test.js +117 -0
- package/dist/src/pipeline/steps/intercept.d.ts +5 -0
- package/dist/src/pipeline/steps/intercept.js +50 -0
- package/dist/src/pipeline/steps/tap.d.ts +12 -0
- package/dist/src/pipeline/steps/tap.js +93 -0
- package/dist/src/pipeline/steps/transform.d.ts +9 -0
- package/dist/src/pipeline/steps/transform.js +70 -0
- package/dist/src/pipeline/template.d.ts +17 -0
- package/dist/src/pipeline/template.js +344 -0
- package/dist/src/pipeline/template.test.d.ts +4 -0
- package/dist/src/pipeline/template.test.js +197 -0
- package/dist/src/pipeline/transform.test.d.ts +4 -0
- package/dist/src/pipeline/transform.test.js +133 -0
- package/dist/src/plugin-manifest.d.ts +70 -0
- package/dist/src/plugin-manifest.js +160 -0
- package/dist/src/plugin-manifest.test.d.ts +4 -0
- package/dist/src/plugin-manifest.test.js +179 -0
- package/dist/src/plugin-scaffold.d.ts +28 -0
- package/dist/src/plugin-scaffold.js +143 -0
- package/dist/src/plugin-scaffold.test.d.ts +4 -0
- package/dist/src/plugin-scaffold.test.js +83 -0
- package/dist/src/plugin.d.ts +146 -0
- package/dist/src/plugin.js +1303 -0
- package/dist/src/plugin.test.d.ts +4 -0
- package/dist/src/plugin.test.js +1363 -0
- package/dist/src/registry-api.d.ts +13 -0
- package/dist/src/registry-api.js +10 -0
- package/dist/src/registry.d.ts +123 -0
- package/dist/src/registry.js +125 -0
- package/dist/src/registry.test.d.ts +4 -0
- package/dist/src/registry.test.js +209 -0
- package/dist/src/runtime-copy.test.d.ts +1 -0
- package/dist/src/runtime-copy.test.js +29 -0
- package/dist/src/runtime-detect.d.ts +31 -0
- package/dist/src/runtime-detect.js +47 -0
- package/dist/src/runtime-detect.test.d.ts +1 -0
- package/dist/src/runtime-detect.test.js +39 -0
- package/dist/src/runtime-identity.test.d.ts +1 -0
- package/dist/src/runtime-identity.test.js +18 -0
- package/dist/src/runtime.d.ts +47 -0
- package/dist/src/runtime.js +54 -0
- package/dist/src/scripts/framework.d.ts +7 -0
- package/dist/src/scripts/framework.js +25 -0
- package/dist/src/scripts/interact.d.ts +4 -0
- package/dist/src/scripts/interact.js +20 -0
- package/dist/src/scripts/store.d.ts +13 -0
- package/dist/src/scripts/store.js +48 -0
- package/dist/src/serialization.d.ts +42 -0
- package/dist/src/serialization.js +103 -0
- package/dist/src/serialization.test.d.ts +1 -0
- package/dist/src/serialization.test.js +78 -0
- package/dist/src/skills.d.ts +14 -0
- package/dist/src/skills.js +127 -0
- package/dist/src/skills.test.d.ts +1 -0
- package/dist/src/skills.test.js +71 -0
- package/dist/src/snapshotFormatter.d.ts +11 -0
- package/dist/src/snapshotFormatter.js +338 -0
- package/dist/src/snapshotFormatter.test.d.ts +7 -0
- package/dist/src/snapshotFormatter.test.js +521 -0
- package/dist/src/tui.d.ts +28 -0
- package/dist/src/tui.js +179 -0
- package/dist/src/tui.test.d.ts +1 -0
- package/dist/src/tui.test.js +19 -0
- package/dist/src/types.d.ts +236 -0
- package/dist/src/types.js +7 -0
- package/dist/src/update-check.d.ts +66 -0
- package/dist/src/update-check.js +206 -0
- package/dist/src/update-check.test.d.ts +1 -0
- package/dist/src/update-check.test.js +117 -0
- package/dist/src/utils.d.ts +57 -0
- package/dist/src/utils.js +152 -0
- package/dist/src/utils.test.d.ts +1 -0
- package/dist/src/utils.test.js +155 -0
- package/dist/src/validate.d.ts +21 -0
- package/dist/src/validate.js +130 -0
- package/dist/src/validate.test.d.ts +9 -0
- package/dist/src/validate.test.js +90 -0
- package/dist/src/verify.d.ts +26 -0
- package/dist/src/verify.js +67 -0
- package/dist/src/version.d.ts +4 -0
- package/dist/src/version.js +22 -0
- package/dist/src/weixin-download.test.d.ts +1 -0
- package/dist/src/weixin-download.test.js +45 -0
- package/package.json +4 -3
- package/scripts/check-package-bin.mjs +95 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI commands for daemon lifecycle:
|
|
3
|
+
* webcmd daemon status — show daemon state
|
|
4
|
+
* webcmd daemon stop — graceful shutdown
|
|
5
|
+
* webcmd daemon restart — graceful shutdown, then start a fresh daemon
|
|
6
|
+
*/
|
|
7
|
+
export declare function daemonStatus(): Promise<void>;
|
|
8
|
+
export declare function daemonStop(): Promise<void>;
|
|
9
|
+
export declare function daemonRestart(): Promise<void>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI commands for daemon lifecycle:
|
|
3
|
+
* webcmd daemon status — show daemon state
|
|
4
|
+
* webcmd daemon stop — graceful shutdown
|
|
5
|
+
* webcmd daemon restart — graceful shutdown, then start a fresh daemon
|
|
6
|
+
*/
|
|
7
|
+
import { fetchDaemonStatus, requestDaemonShutdown } from '../browser/daemon-transport.js';
|
|
8
|
+
import { restartDaemon } from '../browser/daemon-lifecycle.js';
|
|
9
|
+
import { formatDuration } from '../download/progress.js';
|
|
10
|
+
import { log } from '../logger.js';
|
|
11
|
+
import { PKG_VERSION } from '../version.js';
|
|
12
|
+
import { formatDaemonVersion, isDaemonStale } from '../browser/daemon-version.js';
|
|
13
|
+
export async function daemonStatus() {
|
|
14
|
+
const status = await fetchDaemonStatus();
|
|
15
|
+
if (!status) {
|
|
16
|
+
console.log('Daemon: not running');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// GH #1575: ``Runtime: disconnected`` used to be printed for THREE
|
|
20
|
+
// structurally different states — zero profiles (accurate), 2+
|
|
21
|
+
// profiles connected with no default (misleading), and a requested
|
|
22
|
+
// profile that vanished (misleading). The status JSON already
|
|
23
|
+
// distinguishes them; surface that distinction so the user's next
|
|
24
|
+
// step is visible inline instead of "reinstall everything".
|
|
25
|
+
const runtimeLabel = status.runtimeConnected
|
|
26
|
+
? status.runtimeVersion
|
|
27
|
+
? `${status.runtimeName} connected (v${status.runtimeVersion})`
|
|
28
|
+
: `${status.runtimeName} connected`
|
|
29
|
+
: status.profileRequired
|
|
30
|
+
? `${status.profiles?.length ?? 0} ${status.profiles?.length === 1 ? 'profile' : 'profiles'} available, none selected — run \`webcmd profile use <name>\``
|
|
31
|
+
: status.profileDisconnected
|
|
32
|
+
? 'requested profile not connected — run `webcmd profile use <name>`'
|
|
33
|
+
: 'disconnected';
|
|
34
|
+
const daemonVersion = formatDaemonVersion(status);
|
|
35
|
+
const stale = isDaemonStale(status, PKG_VERSION);
|
|
36
|
+
console.log(`Daemon: ${stale ? 'stale' : 'running'} (PID ${status.pid})`);
|
|
37
|
+
console.log(`Version: ${daemonVersion}${stale ? ` (CLI v${PKG_VERSION}; run: webcmd daemon restart)` : ''}`);
|
|
38
|
+
console.log(`Uptime: ${formatDuration(Math.round(status.uptime * 1000))}`);
|
|
39
|
+
console.log(`Runtime: ${runtimeLabel}`);
|
|
40
|
+
if (status.profiles && status.profiles.length > 0) {
|
|
41
|
+
console.log(`Profiles: ${status.profiles.map((profile) => {
|
|
42
|
+
const version = profile.runtimeVersion ? ` v${profile.runtimeVersion}` : '';
|
|
43
|
+
return `${profile.contextId}${version}`;
|
|
44
|
+
}).join(', ')}`);
|
|
45
|
+
}
|
|
46
|
+
console.log(`Memory: ${status.memoryMB} MB`);
|
|
47
|
+
console.log(`Port: ${status.port}`);
|
|
48
|
+
}
|
|
49
|
+
export async function daemonStop() {
|
|
50
|
+
const status = await fetchDaemonStatus();
|
|
51
|
+
if (!status) {
|
|
52
|
+
log.info('Daemon is not running.');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const ok = await requestDaemonShutdown();
|
|
56
|
+
if (ok) {
|
|
57
|
+
log.success('Daemon stopped.');
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
log.error('Failed to stop daemon.');
|
|
61
|
+
process.exitCode = 1;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export async function daemonRestart() {
|
|
65
|
+
const before = await fetchDaemonStatus();
|
|
66
|
+
if (before?.profiles && before.profiles.length > 0) {
|
|
67
|
+
log.warn(`Restarting daemon will disconnect ${before.profiles.length} browser ${before.profiles.length === 1 ? 'profile' : 'profiles'}; Cloak should reconnect automatically.`);
|
|
68
|
+
}
|
|
69
|
+
const result = await restartDaemon();
|
|
70
|
+
if (!result.stopped) {
|
|
71
|
+
log.error('Failed to stop daemon before restart.');
|
|
72
|
+
process.exitCode = 1;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!result.status) {
|
|
76
|
+
log.error('Daemon restart timed out before the new daemon reported status.');
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const action = result.previousStatus ? 'restarted' : 'started';
|
|
81
|
+
const version = formatDaemonVersion(result.status);
|
|
82
|
+
log.success(`Daemon ${action} on port ${result.status.port} (${version}).`);
|
|
83
|
+
if (result.status.runtimeConnected) {
|
|
84
|
+
const profiles = result.status.profiles?.length ?? 0;
|
|
85
|
+
const profileText = profiles > 0 ? `; ${profiles} ${profiles === 1 ? 'profile' : 'profiles'} connected` : '';
|
|
86
|
+
log.status(`Runtime connected${profileText}.`);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
log.warn('Daemon is running, but the Cloak runtime has not connected yet.');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const { fetchDaemonStatusMock, requestDaemonShutdownMock, restartDaemonMock, } = vi.hoisted(() => ({
|
|
3
|
+
fetchDaemonStatusMock: vi.fn(),
|
|
4
|
+
requestDaemonShutdownMock: vi.fn(),
|
|
5
|
+
restartDaemonMock: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
vi.mock('../browser/daemon-transport.js', () => ({
|
|
8
|
+
fetchDaemonStatus: fetchDaemonStatusMock,
|
|
9
|
+
requestDaemonShutdown: requestDaemonShutdownMock,
|
|
10
|
+
}));
|
|
11
|
+
vi.mock('../browser/daemon-lifecycle.js', () => ({
|
|
12
|
+
restartDaemon: restartDaemonMock,
|
|
13
|
+
}));
|
|
14
|
+
import { daemonRestart, daemonStatus, daemonStop } from './daemon.js';
|
|
15
|
+
import { PKG_VERSION } from '../version.js';
|
|
16
|
+
describe('daemonStatus', () => {
|
|
17
|
+
let stdoutSpy;
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
stdoutSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
20
|
+
fetchDaemonStatusMock.mockReset();
|
|
21
|
+
requestDaemonShutdownMock.mockReset();
|
|
22
|
+
});
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
vi.restoreAllMocks();
|
|
25
|
+
});
|
|
26
|
+
it('reports "not running" when daemon is unreachable', async () => {
|
|
27
|
+
fetchDaemonStatusMock.mockResolvedValue(null);
|
|
28
|
+
await daemonStatus();
|
|
29
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('not running'));
|
|
30
|
+
});
|
|
31
|
+
it('shows daemon info when running', async () => {
|
|
32
|
+
fetchDaemonStatusMock.mockResolvedValue({
|
|
33
|
+
ok: true,
|
|
34
|
+
pid: 12345,
|
|
35
|
+
uptime: 3661,
|
|
36
|
+
daemonVersion: PKG_VERSION,
|
|
37
|
+
runtimeConnected: true,
|
|
38
|
+
runtimeName: 'fake',
|
|
39
|
+
runtimeVersion: '1.6.8',
|
|
40
|
+
pending: 0,
|
|
41
|
+
memoryMB: 64,
|
|
42
|
+
port: 19825,
|
|
43
|
+
});
|
|
44
|
+
await daemonStatus();
|
|
45
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('running'));
|
|
46
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('PID 12345'));
|
|
47
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining(`v${PKG_VERSION}`));
|
|
48
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('1h 1m'));
|
|
49
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('connected'));
|
|
50
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('v1.6.8'));
|
|
51
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('64 MB'));
|
|
52
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('19825'));
|
|
53
|
+
});
|
|
54
|
+
it('shows disconnected when runtime is not connected', async () => {
|
|
55
|
+
fetchDaemonStatusMock.mockResolvedValue({
|
|
56
|
+
ok: true,
|
|
57
|
+
pid: 99,
|
|
58
|
+
uptime: 120,
|
|
59
|
+
daemonVersion: PKG_VERSION,
|
|
60
|
+
runtimeConnected: false,
|
|
61
|
+
runtimeName: 'fake',
|
|
62
|
+
pending: 0,
|
|
63
|
+
memoryMB: 32,
|
|
64
|
+
port: 19825,
|
|
65
|
+
});
|
|
66
|
+
await daemonStatus();
|
|
67
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('disconnected'));
|
|
68
|
+
});
|
|
69
|
+
it('shows runtime name when the connected runtime does not report a version', async () => {
|
|
70
|
+
fetchDaemonStatusMock.mockResolvedValue({
|
|
71
|
+
ok: true,
|
|
72
|
+
pid: 99,
|
|
73
|
+
uptime: 120,
|
|
74
|
+
daemonVersion: PKG_VERSION,
|
|
75
|
+
runtimeConnected: true,
|
|
76
|
+
runtimeName: 'fake',
|
|
77
|
+
runtimeVersion: undefined,
|
|
78
|
+
pending: 0,
|
|
79
|
+
memoryMB: 32,
|
|
80
|
+
port: 19825,
|
|
81
|
+
});
|
|
82
|
+
await daemonStatus();
|
|
83
|
+
expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining('fake connected'));
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
// ────────────────────────────────────────────────────────────────────
|
|
87
|
+
// GH #1575: differentiate the three "no route" states. The pre-fix
|
|
88
|
+
// behaviour collapsed multi-profile-no-default + profile-disconnected
|
|
89
|
+
// + zero-profile all to "Runtime: disconnected", sending users on
|
|
90
|
+
// reinstall-everything debug paths when the actual fix was
|
|
91
|
+
// `webcmd profile use <name>`.
|
|
92
|
+
// ────────────────────────────────────────────────────────────────────
|
|
93
|
+
describe('daemonStatus runtime label states (#1575)', () => {
|
|
94
|
+
let stdoutSpy;
|
|
95
|
+
beforeEach(() => {
|
|
96
|
+
stdoutSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
97
|
+
fetchDaemonStatusMock.mockReset();
|
|
98
|
+
});
|
|
99
|
+
afterEach(() => vi.restoreAllMocks());
|
|
100
|
+
async function runtimeLineFor(extra) {
|
|
101
|
+
fetchDaemonStatusMock.mockResolvedValue({
|
|
102
|
+
ok: true,
|
|
103
|
+
pid: 99,
|
|
104
|
+
uptime: 60,
|
|
105
|
+
daemonVersion: PKG_VERSION,
|
|
106
|
+
pending: 0,
|
|
107
|
+
memoryMB: 32,
|
|
108
|
+
port: 19825,
|
|
109
|
+
runtimeName: 'fake',
|
|
110
|
+
...extra,
|
|
111
|
+
});
|
|
112
|
+
await daemonStatus();
|
|
113
|
+
return stdoutSpy.mock.calls
|
|
114
|
+
.map((c) => c[0])
|
|
115
|
+
.find((line) => typeof line === 'string' && line.startsWith('Runtime:'));
|
|
116
|
+
}
|
|
117
|
+
it('prints a route hint for 2+ profiles with no default (not bare "disconnected")', async () => {
|
|
118
|
+
const line = await runtimeLineFor({
|
|
119
|
+
runtimeConnected: false,
|
|
120
|
+
profileRequired: true,
|
|
121
|
+
profiles: [
|
|
122
|
+
{ contextId: 'work', runtimeConnected: true, pending: 0 },
|
|
123
|
+
{ contextId: 'personal', runtimeConnected: true, pending: 0 },
|
|
124
|
+
],
|
|
125
|
+
});
|
|
126
|
+
expect(line).not.toBe('Runtime: disconnected');
|
|
127
|
+
expect(line).toContain('2 profiles available');
|
|
128
|
+
expect(line).toContain('webcmd profile use');
|
|
129
|
+
});
|
|
130
|
+
it('uses the required profile-available label for a one-profile profile-required payload', async () => {
|
|
131
|
+
const line = await runtimeLineFor({
|
|
132
|
+
runtimeConnected: false,
|
|
133
|
+
profileRequired: true,
|
|
134
|
+
profiles: [{ contextId: 'work', runtimeConnected: true, pending: 0 }],
|
|
135
|
+
});
|
|
136
|
+
expect(line).toContain('1 profile available');
|
|
137
|
+
});
|
|
138
|
+
it('prints a route hint when the requested profile is disconnected', async () => {
|
|
139
|
+
const line = await runtimeLineFor({
|
|
140
|
+
runtimeConnected: false,
|
|
141
|
+
profileDisconnected: true,
|
|
142
|
+
});
|
|
143
|
+
expect(line).not.toBe('Runtime: disconnected');
|
|
144
|
+
expect(line).toContain('webcmd profile use');
|
|
145
|
+
});
|
|
146
|
+
it('keeps the plain "disconnected" label when zero profiles are connected', async () => {
|
|
147
|
+
const line = await runtimeLineFor({ runtimeConnected: false });
|
|
148
|
+
expect(line).toBe('Runtime: disconnected');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe('daemonStop', () => {
|
|
152
|
+
let stderrSpy;
|
|
153
|
+
beforeEach(() => {
|
|
154
|
+
stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
155
|
+
fetchDaemonStatusMock.mockReset();
|
|
156
|
+
requestDaemonShutdownMock.mockReset();
|
|
157
|
+
});
|
|
158
|
+
afterEach(() => {
|
|
159
|
+
vi.restoreAllMocks();
|
|
160
|
+
});
|
|
161
|
+
it('reports "not running" when daemon is unreachable', async () => {
|
|
162
|
+
fetchDaemonStatusMock.mockResolvedValue(null);
|
|
163
|
+
await daemonStop();
|
|
164
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('not running'));
|
|
165
|
+
});
|
|
166
|
+
it('sends shutdown and reports success', async () => {
|
|
167
|
+
fetchDaemonStatusMock.mockResolvedValue({
|
|
168
|
+
ok: true,
|
|
169
|
+
pid: 12345,
|
|
170
|
+
uptime: 100,
|
|
171
|
+
daemonVersion: PKG_VERSION,
|
|
172
|
+
runtimeConnected: true,
|
|
173
|
+
runtimeName: 'fake',
|
|
174
|
+
pending: 0,
|
|
175
|
+
memoryMB: 50,
|
|
176
|
+
port: 19825,
|
|
177
|
+
});
|
|
178
|
+
requestDaemonShutdownMock.mockResolvedValue(true);
|
|
179
|
+
await daemonStop();
|
|
180
|
+
expect(requestDaemonShutdownMock).toHaveBeenCalledTimes(1);
|
|
181
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('Daemon stopped'));
|
|
182
|
+
});
|
|
183
|
+
it('reports failure when shutdown request fails', async () => {
|
|
184
|
+
fetchDaemonStatusMock.mockResolvedValue({
|
|
185
|
+
ok: true,
|
|
186
|
+
pid: 12345,
|
|
187
|
+
uptime: 100,
|
|
188
|
+
daemonVersion: PKG_VERSION,
|
|
189
|
+
runtimeConnected: true,
|
|
190
|
+
runtimeName: 'fake',
|
|
191
|
+
pending: 0,
|
|
192
|
+
memoryMB: 50,
|
|
193
|
+
port: 19825,
|
|
194
|
+
});
|
|
195
|
+
requestDaemonShutdownMock.mockResolvedValue(false);
|
|
196
|
+
await daemonStop();
|
|
197
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('Failed to stop daemon'));
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
describe('daemonRestart', () => {
|
|
201
|
+
let stderrSpy;
|
|
202
|
+
beforeEach(() => {
|
|
203
|
+
stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
204
|
+
fetchDaemonStatusMock.mockReset();
|
|
205
|
+
requestDaemonShutdownMock.mockReset();
|
|
206
|
+
restartDaemonMock.mockReset();
|
|
207
|
+
process.exitCode = undefined;
|
|
208
|
+
});
|
|
209
|
+
afterEach(() => {
|
|
210
|
+
vi.restoreAllMocks();
|
|
211
|
+
process.exitCode = undefined;
|
|
212
|
+
});
|
|
213
|
+
it('restarts a running daemon and reports the new version', async () => {
|
|
214
|
+
fetchDaemonStatusMock.mockResolvedValue({
|
|
215
|
+
ok: true,
|
|
216
|
+
pid: 12345,
|
|
217
|
+
uptime: 100,
|
|
218
|
+
daemonVersion: '1.7.6',
|
|
219
|
+
runtimeConnected: true,
|
|
220
|
+
runtimeName: 'fake',
|
|
221
|
+
profiles: [{ contextId: 'work', runtimeConnected: true, pending: 0 }],
|
|
222
|
+
pending: 0,
|
|
223
|
+
memoryMB: 50,
|
|
224
|
+
port: 19825,
|
|
225
|
+
});
|
|
226
|
+
restartDaemonMock.mockResolvedValue({
|
|
227
|
+
previousStatus: { daemonVersion: '1.7.6' },
|
|
228
|
+
stopped: true,
|
|
229
|
+
spawned: true,
|
|
230
|
+
status: {
|
|
231
|
+
ok: true,
|
|
232
|
+
pid: 12346,
|
|
233
|
+
uptime: 1,
|
|
234
|
+
daemonVersion: PKG_VERSION,
|
|
235
|
+
runtimeConnected: true,
|
|
236
|
+
runtimeName: 'fake',
|
|
237
|
+
profiles: [{ contextId: 'work', runtimeConnected: true, pending: 0 }],
|
|
238
|
+
pending: 0,
|
|
239
|
+
memoryMB: 51,
|
|
240
|
+
port: 19825,
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
await daemonRestart();
|
|
244
|
+
expect(restartDaemonMock).toHaveBeenCalledTimes(1);
|
|
245
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('will disconnect 1 browser profile'));
|
|
246
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining(`Daemon restarted on port 19825 (v${PKG_VERSION})`));
|
|
247
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('Runtime connected; 1 profile connected'));
|
|
248
|
+
});
|
|
249
|
+
it('starts a new daemon when none was running', async () => {
|
|
250
|
+
fetchDaemonStatusMock.mockResolvedValue(null);
|
|
251
|
+
restartDaemonMock.mockResolvedValue({
|
|
252
|
+
previousStatus: null,
|
|
253
|
+
stopped: true,
|
|
254
|
+
spawned: true,
|
|
255
|
+
status: {
|
|
256
|
+
ok: true,
|
|
257
|
+
pid: 12346,
|
|
258
|
+
uptime: 1,
|
|
259
|
+
daemonVersion: PKG_VERSION,
|
|
260
|
+
runtimeConnected: false,
|
|
261
|
+
runtimeName: 'fake',
|
|
262
|
+
pending: 0,
|
|
263
|
+
memoryMB: 51,
|
|
264
|
+
port: 19825,
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
await daemonRestart();
|
|
268
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining(`Daemon started on port 19825 (v${PKG_VERSION})`));
|
|
269
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('Cloak runtime has not connected yet'));
|
|
270
|
+
});
|
|
271
|
+
it('reports failure when the daemon cannot stop', async () => {
|
|
272
|
+
fetchDaemonStatusMock.mockResolvedValue({
|
|
273
|
+
ok: true,
|
|
274
|
+
pid: 12345,
|
|
275
|
+
uptime: 100,
|
|
276
|
+
daemonVersion: '1.7.6',
|
|
277
|
+
runtimeConnected: true,
|
|
278
|
+
runtimeName: 'fake',
|
|
279
|
+
pending: 0,
|
|
280
|
+
memoryMB: 50,
|
|
281
|
+
port: 19825,
|
|
282
|
+
});
|
|
283
|
+
restartDaemonMock.mockResolvedValue({
|
|
284
|
+
previousStatus: { daemonVersion: '1.7.6' },
|
|
285
|
+
status: { daemonVersion: '1.7.6' },
|
|
286
|
+
stopped: false,
|
|
287
|
+
spawned: false,
|
|
288
|
+
});
|
|
289
|
+
await daemonRestart();
|
|
290
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('Failed to stop daemon before restart'));
|
|
291
|
+
expect(process.exitCode).toBe(1);
|
|
292
|
+
});
|
|
293
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight manifest-based completion for the fast path.
|
|
3
|
+
*
|
|
4
|
+
* This module MUST NOT import registry, discovery, or any heavy module.
|
|
5
|
+
* It only reads pre-compiled cli-manifest.json files synchronously.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Returns true only if ALL manifest files exist and are readable.
|
|
9
|
+
* If any source lacks a manifest (e.g. user adapters without a compiled manifest),
|
|
10
|
+
* the fast path must not be used — otherwise those adapters would silently
|
|
11
|
+
* disappear from completion results.
|
|
12
|
+
*/
|
|
13
|
+
export declare function hasAllManifests(manifestPaths: string[]): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Lightweight completion that reads directly from manifest JSON files,
|
|
16
|
+
* bypassing full CLI discovery and adapter loading.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getCompletionsFromManifest(words: string[], cursor: number, manifestPaths: string[]): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Print completion script for the given shell. Returns true if handled, false if unknown shell.
|
|
21
|
+
*/
|
|
22
|
+
export declare function printCompletionScriptFast(shell: string): boolean;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight manifest-based completion for the fast path.
|
|
3
|
+
*
|
|
4
|
+
* This module MUST NOT import registry, discovery, or any heavy module.
|
|
5
|
+
* It only reads pre-compiled cli-manifest.json files synchronously.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import { BUILTIN_COMMANDS, bashCompletionScript, zshCompletionScript, fishCompletionScript, } from './completion-shared.js';
|
|
9
|
+
/**
|
|
10
|
+
* Returns true only if ALL manifest files exist and are readable.
|
|
11
|
+
* If any source lacks a manifest (e.g. user adapters without a compiled manifest),
|
|
12
|
+
* the fast path must not be used — otherwise those adapters would silently
|
|
13
|
+
* disappear from completion results.
|
|
14
|
+
*/
|
|
15
|
+
export function hasAllManifests(manifestPaths) {
|
|
16
|
+
for (const p of manifestPaths) {
|
|
17
|
+
try {
|
|
18
|
+
fs.accessSync(p);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return manifestPaths.length > 0;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Lightweight completion that reads directly from manifest JSON files,
|
|
28
|
+
* bypassing full CLI discovery and adapter loading.
|
|
29
|
+
*/
|
|
30
|
+
export function getCompletionsFromManifest(words, cursor, manifestPaths) {
|
|
31
|
+
const entries = loadManifestEntries(manifestPaths);
|
|
32
|
+
if (entries === null) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
if (cursor <= 1) {
|
|
36
|
+
const sites = new Set();
|
|
37
|
+
for (const entry of entries) {
|
|
38
|
+
sites.add(entry.site);
|
|
39
|
+
}
|
|
40
|
+
return [...BUILTIN_COMMANDS, ...sites].sort();
|
|
41
|
+
}
|
|
42
|
+
const site = words[0];
|
|
43
|
+
if (BUILTIN_COMMANDS.includes(site)) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
if (cursor === 2) {
|
|
47
|
+
const subcommands = [];
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
if (entry.site === site) {
|
|
50
|
+
subcommands.push(entry.name);
|
|
51
|
+
if (entry.aliases?.length)
|
|
52
|
+
subcommands.push(...entry.aliases);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return [...new Set(subcommands)].sort();
|
|
56
|
+
}
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
// ── Shell script generators (re-exported from shared, no registry dependency) ───────
|
|
60
|
+
const SHELL_SCRIPTS = {
|
|
61
|
+
bash: bashCompletionScript,
|
|
62
|
+
zsh: zshCompletionScript,
|
|
63
|
+
fish: fishCompletionScript,
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Print completion script for the given shell. Returns true if handled, false if unknown shell.
|
|
67
|
+
*/
|
|
68
|
+
export function printCompletionScriptFast(shell) {
|
|
69
|
+
const gen = SHELL_SCRIPTS[shell];
|
|
70
|
+
if (!gen)
|
|
71
|
+
return false;
|
|
72
|
+
process.stdout.write(gen());
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
function loadManifestEntries(manifestPaths) {
|
|
76
|
+
const entries = [];
|
|
77
|
+
let found = false;
|
|
78
|
+
for (const manifestPath of manifestPaths) {
|
|
79
|
+
try {
|
|
80
|
+
const raw = fs.readFileSync(manifestPath, 'utf-8');
|
|
81
|
+
const manifest = JSON.parse(raw);
|
|
82
|
+
entries.push(...manifest);
|
|
83
|
+
found = true;
|
|
84
|
+
}
|
|
85
|
+
catch { /* skip missing/unreadable */ }
|
|
86
|
+
}
|
|
87
|
+
return found ? entries : null;
|
|
88
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants and shell script generators for tab-completion.
|
|
3
|
+
*
|
|
4
|
+
* This module MUST remain lightweight (no registry, no discovery imports).
|
|
5
|
+
* Both completion.ts (full path) and completion-fast.ts (manifest path) import from here.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Built-in (non-dynamic) top-level commands.
|
|
9
|
+
*/
|
|
10
|
+
export declare const BUILTIN_COMMANDS: string[];
|
|
11
|
+
export declare function bashCompletionScript(): string;
|
|
12
|
+
export declare function zshCompletionScript(): string;
|
|
13
|
+
export declare function fishCompletionScript(): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants and shell script generators for tab-completion.
|
|
3
|
+
*
|
|
4
|
+
* This module MUST remain lightweight (no registry, no discovery imports).
|
|
5
|
+
* Both completion.ts (full path) and completion-fast.ts (manifest path) import from here.
|
|
6
|
+
*/
|
|
7
|
+
import { CLI_COMMAND } from './brand.js';
|
|
8
|
+
/**
|
|
9
|
+
* Built-in (non-dynamic) top-level commands.
|
|
10
|
+
*/
|
|
11
|
+
export const BUILTIN_COMMANDS = [
|
|
12
|
+
'list',
|
|
13
|
+
'validate',
|
|
14
|
+
'verify',
|
|
15
|
+
'auth',
|
|
16
|
+
'browser',
|
|
17
|
+
'tab',
|
|
18
|
+
'doctor',
|
|
19
|
+
'plugin',
|
|
20
|
+
'external',
|
|
21
|
+
'completion',
|
|
22
|
+
];
|
|
23
|
+
// ── Shell script generators ────────────────────────────────────────────────
|
|
24
|
+
export function bashCompletionScript() {
|
|
25
|
+
return `# Bash completion for ${CLI_COMMAND}
|
|
26
|
+
# Add to ~/.bashrc: eval "$(${CLI_COMMAND} completion bash)"
|
|
27
|
+
_${CLI_COMMAND}_completions() {
|
|
28
|
+
local cur words cword
|
|
29
|
+
_get_comp_words_by_ref -n : cur words cword
|
|
30
|
+
|
|
31
|
+
local completions
|
|
32
|
+
completions=$(${CLI_COMMAND} --get-completions --cursor "$cword" "\${words[@]:1}" 2>/dev/null)
|
|
33
|
+
|
|
34
|
+
COMPREPLY=( $(compgen -W "$completions" -- "$cur") )
|
|
35
|
+
__ltrim_colon_completions "$cur"
|
|
36
|
+
}
|
|
37
|
+
complete -F _${CLI_COMMAND}_completions ${CLI_COMMAND}
|
|
38
|
+
`;
|
|
39
|
+
}
|
|
40
|
+
export function zshCompletionScript() {
|
|
41
|
+
return `# Zsh completion for ${CLI_COMMAND}
|
|
42
|
+
# Add to ~/.zshrc: eval "$(${CLI_COMMAND} completion zsh)"
|
|
43
|
+
_${CLI_COMMAND}() {
|
|
44
|
+
local -a completions
|
|
45
|
+
local cword=$((CURRENT - 1))
|
|
46
|
+
completions=(\${(f)"$(${CLI_COMMAND} --get-completions --cursor "$cword" "\${words[@]:1}" 2>/dev/null)"})
|
|
47
|
+
compadd -a completions
|
|
48
|
+
}
|
|
49
|
+
compdef _${CLI_COMMAND} ${CLI_COMMAND}
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
export function fishCompletionScript() {
|
|
53
|
+
return `# Fish completion for ${CLI_COMMAND}
|
|
54
|
+
# Add to ~/.config/fish/config.fish: ${CLI_COMMAND} completion fish | source
|
|
55
|
+
complete -c ${CLI_COMMAND} -f -a '(
|
|
56
|
+
set -l tokens (commandline -cop)
|
|
57
|
+
set -l cursor (count (commandline -cop))
|
|
58
|
+
${CLI_COMMAND} --get-completions --cursor $cursor $tokens[2..] 2>/dev/null
|
|
59
|
+
)'
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell tab-completion support for webcmd.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Shell script generators for bash, zsh, and fish
|
|
6
|
+
* - Dynamic completion logic that returns candidates for the current cursor position
|
|
7
|
+
*/
|
|
8
|
+
import { bashCompletionScript, zshCompletionScript, fishCompletionScript } from './completion-shared.js';
|
|
9
|
+
export { bashCompletionScript, zshCompletionScript, fishCompletionScript };
|
|
10
|
+
/**
|
|
11
|
+
* Return completion candidates given the current command-line words and cursor index.
|
|
12
|
+
* Requires full CLI discovery to have been run (uses getRegistry()).
|
|
13
|
+
*
|
|
14
|
+
* @param words - The argv after 'webcmd' (words[0] is the first arg, e.g. site name)
|
|
15
|
+
* @param cursor - 1-based position of the word being completed (1 = first arg)
|
|
16
|
+
*/
|
|
17
|
+
export declare function getCompletions(words: string[], cursor: number): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Print the completion script for the requested shell.
|
|
20
|
+
*/
|
|
21
|
+
export declare function printCompletionScript(shell: string): void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell tab-completion support for webcmd.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Shell script generators for bash, zsh, and fish
|
|
6
|
+
* - Dynamic completion logic that returns candidates for the current cursor position
|
|
7
|
+
*/
|
|
8
|
+
import { getRegistry } from './registry.js';
|
|
9
|
+
import { CliError } from './errors.js';
|
|
10
|
+
import { BUILTIN_COMMANDS, bashCompletionScript, zshCompletionScript, fishCompletionScript, } from './completion-shared.js';
|
|
11
|
+
// Re-export shell scripts so existing callers (cli.ts) don't break
|
|
12
|
+
export { bashCompletionScript, zshCompletionScript, fishCompletionScript };
|
|
13
|
+
// ── Dynamic completion logic ───────────────────────────────────────────────
|
|
14
|
+
/**
|
|
15
|
+
* Return completion candidates given the current command-line words and cursor index.
|
|
16
|
+
* Requires full CLI discovery to have been run (uses getRegistry()).
|
|
17
|
+
*
|
|
18
|
+
* @param words - The argv after 'webcmd' (words[0] is the first arg, e.g. site name)
|
|
19
|
+
* @param cursor - 1-based position of the word being completed (1 = first arg)
|
|
20
|
+
*/
|
|
21
|
+
export function getCompletions(words, cursor) {
|
|
22
|
+
// cursor === 1 → completing the first argument (site name or built-in command)
|
|
23
|
+
if (cursor <= 1) {
|
|
24
|
+
const sites = new Set();
|
|
25
|
+
for (const [, cmd] of getRegistry()) {
|
|
26
|
+
sites.add(cmd.site);
|
|
27
|
+
}
|
|
28
|
+
return [...BUILTIN_COMMANDS, ...sites].sort();
|
|
29
|
+
}
|
|
30
|
+
const site = words[0];
|
|
31
|
+
// If the first word is a built-in command, no further completion
|
|
32
|
+
if (BUILTIN_COMMANDS.includes(site)) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
// cursor === 2 → completing the sub-command name under a site
|
|
36
|
+
if (cursor === 2) {
|
|
37
|
+
const subcommands = [];
|
|
38
|
+
for (const [, cmd] of getRegistry()) {
|
|
39
|
+
if (cmd.site === site) {
|
|
40
|
+
subcommands.push(cmd.name);
|
|
41
|
+
if (cmd.aliases?.length)
|
|
42
|
+
subcommands.push(...cmd.aliases);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return [...new Set(subcommands)].sort();
|
|
46
|
+
}
|
|
47
|
+
// cursor >= 3 → no further completion
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
// ── Shell script generators ────────────────────────────────────────────────
|
|
51
|
+
/**
|
|
52
|
+
* Print the completion script for the requested shell.
|
|
53
|
+
*/
|
|
54
|
+
export function printCompletionScript(shell) {
|
|
55
|
+
switch (shell) {
|
|
56
|
+
case 'bash':
|
|
57
|
+
process.stdout.write(bashCompletionScript());
|
|
58
|
+
break;
|
|
59
|
+
case 'zsh':
|
|
60
|
+
process.stdout.write(zshCompletionScript());
|
|
61
|
+
break;
|
|
62
|
+
case 'fish':
|
|
63
|
+
process.stdout.write(fishCompletionScript());
|
|
64
|
+
break;
|
|
65
|
+
default:
|
|
66
|
+
throw new CliError('UNSUPPORTED_SHELL', `Unsupported shell: ${shell}. Supported: bash, zsh, fish`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|