@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
package/dist/src/help.js
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
import yaml from 'js-yaml';
|
|
2
|
+
import { fullName } from './registry.js';
|
|
3
|
+
import { formatCommandExample } from './serialization.js';
|
|
4
|
+
import { CLI_COMMAND } from './brand.js';
|
|
5
|
+
const COMMON_OPTIONS = [
|
|
6
|
+
{
|
|
7
|
+
flags: '-f, --format <fmt>',
|
|
8
|
+
name: 'format',
|
|
9
|
+
help: 'Output format: table, plain, json, yaml, md, csv',
|
|
10
|
+
default: 'table',
|
|
11
|
+
choices: ['table', 'plain', 'json', 'yaml', 'md', 'csv'],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
flags: '--trace <mode>',
|
|
15
|
+
name: 'trace',
|
|
16
|
+
help: 'Trace capture: off, on, retain-on-failure',
|
|
17
|
+
default: 'off',
|
|
18
|
+
choices: ['off', 'on', 'retain-on-failure'],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
flags: '-v, --verbose',
|
|
22
|
+
name: 'verbose',
|
|
23
|
+
help: 'Debug output',
|
|
24
|
+
default: false,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
flags: '-h, --help',
|
|
28
|
+
name: 'help',
|
|
29
|
+
help: 'display help for command',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
const BROWSER_COMMON_OPTIONS = [
|
|
33
|
+
{
|
|
34
|
+
flags: '--window <mode>',
|
|
35
|
+
name: 'window',
|
|
36
|
+
help: 'Browser window mode: foreground or background',
|
|
37
|
+
choices: ['foreground', 'background'],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
flags: '--site-session <mode>',
|
|
41
|
+
name: 'site-session',
|
|
42
|
+
help: 'Adapter site session lifecycle: ephemeral or persistent',
|
|
43
|
+
choices: ['ephemeral', 'persistent'],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
flags: '--keep-tab <bool>',
|
|
47
|
+
name: 'keep-tab',
|
|
48
|
+
help: 'Keep the browser tab lease after the command finishes',
|
|
49
|
+
choices: ['true', 'false'],
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
function normalizeStructuredHelpFormat(value) {
|
|
53
|
+
const normalized = value?.toLowerCase();
|
|
54
|
+
if (normalized === 'yaml' || normalized === 'yml')
|
|
55
|
+
return 'yaml';
|
|
56
|
+
if (normalized === 'json')
|
|
57
|
+
return 'json';
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
export function getRequestedHelpFormat(argv = process.argv) {
|
|
61
|
+
for (let i = 0; i < argv.length; i++) {
|
|
62
|
+
const token = argv[i];
|
|
63
|
+
if (token === '-f' || token === '--format') {
|
|
64
|
+
return normalizeStructuredHelpFormat(argv[i + 1]);
|
|
65
|
+
}
|
|
66
|
+
if (token.startsWith('--format=')) {
|
|
67
|
+
return normalizeStructuredHelpFormat(token.slice('--format='.length));
|
|
68
|
+
}
|
|
69
|
+
if (token.startsWith('-f') && token.length > 2) {
|
|
70
|
+
return normalizeStructuredHelpFormat(token.slice(2));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
export function renderStructuredHelp(data, format) {
|
|
76
|
+
if (format === 'json')
|
|
77
|
+
return `${JSON.stringify(data, null, 2)}\n`;
|
|
78
|
+
return yaml.dump(data, { sortKeys: false, lineWidth: 120, noRefs: true });
|
|
79
|
+
}
|
|
80
|
+
export function wrapCommaList(items, opts = {}) {
|
|
81
|
+
const width = Math.max(opts.width ?? process.stdout.columns ?? 100, 40);
|
|
82
|
+
const indent = opts.indent ?? ' ';
|
|
83
|
+
const sorted = [...items].sort((a, b) => a.localeCompare(b));
|
|
84
|
+
const lines = [];
|
|
85
|
+
let line = indent;
|
|
86
|
+
sorted.forEach((item, index) => {
|
|
87
|
+
const token = `${item}${index < sorted.length - 1 ? ',' : ''}`;
|
|
88
|
+
const prefix = line === indent ? '' : ' ';
|
|
89
|
+
if (line.length + prefix.length + token.length > width && line.trim()) {
|
|
90
|
+
lines.push(line);
|
|
91
|
+
line = `${indent}${token}`;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
line += `${prefix}${token}`;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
if (line.trim())
|
|
98
|
+
lines.push(line);
|
|
99
|
+
return lines.join('\n');
|
|
100
|
+
}
|
|
101
|
+
function isLocalIpDomain(domain) {
|
|
102
|
+
if (domain === '::1' || domain === '[::1]')
|
|
103
|
+
return true;
|
|
104
|
+
const parts = domain.split('.');
|
|
105
|
+
if (parts.length !== 4)
|
|
106
|
+
return false;
|
|
107
|
+
return parts.every(part => /^\d+$/.test(part) && Number(part) >= 0 && Number(part) <= 255)
|
|
108
|
+
&& Number(parts[0]) === 127;
|
|
109
|
+
}
|
|
110
|
+
export function classifyAdapter(domain) {
|
|
111
|
+
if (!domain)
|
|
112
|
+
return 'site';
|
|
113
|
+
if (isLocalIpDomain(domain))
|
|
114
|
+
return 'app';
|
|
115
|
+
return domain.includes('.') ? 'site' : 'app';
|
|
116
|
+
}
|
|
117
|
+
function formatGroupSection(label, names) {
|
|
118
|
+
if (names.length === 0)
|
|
119
|
+
return [];
|
|
120
|
+
return [
|
|
121
|
+
`${label} (${names.length}):`,
|
|
122
|
+
wrapCommaList(names),
|
|
123
|
+
'',
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
export function formatRootAdapterHelpText(groups) {
|
|
127
|
+
const total = groups.external.length + groups.apps.length + groups.sites.length;
|
|
128
|
+
if (total === 0)
|
|
129
|
+
return '';
|
|
130
|
+
const lines = [''];
|
|
131
|
+
lines.push(...formatGroupSection('External CLIs', groups.external.map(cli => cli.label)));
|
|
132
|
+
lines.push(...formatGroupSection('App adapters', groups.apps));
|
|
133
|
+
lines.push(...formatGroupSection('Site adapters', groups.sites));
|
|
134
|
+
lines.push(`Run '${CLI_COMMAND} list' for full command details, or '${CLI_COMMAND} <site> --help' to inspect one site.`);
|
|
135
|
+
lines.push(`Agent tip: use '${CLI_COMMAND} <site> --help -f yaml' for all command args/options in one structured response.`);
|
|
136
|
+
lines.push('');
|
|
137
|
+
return lines.join('\n');
|
|
138
|
+
}
|
|
139
|
+
function compactArg(arg) {
|
|
140
|
+
return {
|
|
141
|
+
name: arg.name,
|
|
142
|
+
...(arg.type && arg.type !== 'string' ? { type: arg.type } : {}),
|
|
143
|
+
...(arg.positional ? { positional: true } : {}),
|
|
144
|
+
...(arg.required ? { required: true } : {}),
|
|
145
|
+
...(arg.valueRequired ? { valueRequired: true } : {}),
|
|
146
|
+
...(arg.default !== undefined ? { default: arg.default } : {}),
|
|
147
|
+
...(arg.choices?.length ? { choices: arg.choices } : {}),
|
|
148
|
+
...(arg.help ? { help: arg.help } : {}),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function compactCommonOption(option) {
|
|
152
|
+
return {
|
|
153
|
+
name: option.name,
|
|
154
|
+
flags: option.flags,
|
|
155
|
+
help: option.help,
|
|
156
|
+
...('default' in option ? { default: option.default } : {}),
|
|
157
|
+
...('choices' in option ? { choices: option.choices } : {}),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function compactCommanderArgument(arg) {
|
|
161
|
+
return {
|
|
162
|
+
name: arg.name(),
|
|
163
|
+
...(arg.required ? { required: true } : {}),
|
|
164
|
+
...(arg.variadic ? { variadic: true } : {}),
|
|
165
|
+
...(arg.description ? { help: arg.description } : {}),
|
|
166
|
+
...(arg.defaultValue !== undefined ? { default: arg.defaultValue } : {}),
|
|
167
|
+
...(arg.argChoices?.length ? { choices: [...arg.argChoices] } : {}),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function compactCommanderOption(option) {
|
|
171
|
+
if (option.hidden)
|
|
172
|
+
return null;
|
|
173
|
+
return {
|
|
174
|
+
name: option.attributeName(),
|
|
175
|
+
flags: option.flags,
|
|
176
|
+
...(option.description ? { help: option.description } : {}),
|
|
177
|
+
...(option.required ? { takes_value: 'required' } : {}),
|
|
178
|
+
...(option.optional ? { takes_value: 'optional' } : {}),
|
|
179
|
+
...(option.mandatory ? { required: true } : {}),
|
|
180
|
+
...(option.defaultValue !== undefined ? { default: option.defaultValue } : {}),
|
|
181
|
+
...(option.argChoices?.length ? { choices: [...option.argChoices] } : {}),
|
|
182
|
+
...(option.negate ? { negate: true } : {}),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function compactCommanderOptions(options) {
|
|
186
|
+
return options
|
|
187
|
+
.map(compactCommanderOption)
|
|
188
|
+
.filter((option) => option !== null);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Extracts a positional placeholder that should appear immediately after this
|
|
192
|
+
* command's name in user-facing path strings. Reads the leading positional
|
|
193
|
+
* (e.g. `<session>`) from a `.usage()` override; commands without a positional
|
|
194
|
+
* override return `null` so the path stays as-is.
|
|
195
|
+
*
|
|
196
|
+
* Example: `browser` declares `.usage('<session> <command> [options]')`,
|
|
197
|
+
* so `commanderPath(browserClickCmd)` becomes
|
|
198
|
+
* `['webcmd', 'browser', '<session>', 'click']`.
|
|
199
|
+
*/
|
|
200
|
+
export function leadingPositionalFromUsage(command) {
|
|
201
|
+
const usage = command._usage;
|
|
202
|
+
if (!usage)
|
|
203
|
+
return null;
|
|
204
|
+
const match = usage.match(/^\s*(<[^>]+>)/);
|
|
205
|
+
return match ? match[1] : null;
|
|
206
|
+
}
|
|
207
|
+
function commanderPath(command) {
|
|
208
|
+
const parts = [];
|
|
209
|
+
let current = command;
|
|
210
|
+
while (current) {
|
|
211
|
+
const name = current.name();
|
|
212
|
+
if (name) {
|
|
213
|
+
parts.push(name);
|
|
214
|
+
// If this command declares a leading-positional usage override AND we
|
|
215
|
+
// have already collected a child name below it, the positional must
|
|
216
|
+
// appear between this command and the child (i.e. before the names
|
|
217
|
+
// already collected). parts is in reverse order, so push to the end.
|
|
218
|
+
const positional = leadingPositionalFromUsage(current);
|
|
219
|
+
if (positional && parts.length > 1) {
|
|
220
|
+
// We collected child names first (reverse order). Move them up by one
|
|
221
|
+
// and put the positional at index `parts.length - 2` so reverse()
|
|
222
|
+
// places it between this command and the first child name.
|
|
223
|
+
parts.splice(parts.length - 1, 0, positional);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
current = current.parent;
|
|
227
|
+
}
|
|
228
|
+
return parts.reverse();
|
|
229
|
+
}
|
|
230
|
+
function commandPathFromRoot(namespaceRoot, command) {
|
|
231
|
+
const rootPath = commanderPath(namespaceRoot);
|
|
232
|
+
const commandPath = commanderPath(command);
|
|
233
|
+
// Strip placeholder positional segments (e.g. `<session>`) from the relative
|
|
234
|
+
// name so agents can still address subcommands by their leaf name. Display
|
|
235
|
+
// paths in `command` / `usage` still include the placeholders.
|
|
236
|
+
return commandPath.slice(rootPath.length).filter(part => !/^<.+>$/.test(part));
|
|
237
|
+
}
|
|
238
|
+
function collectLeafCommands(command) {
|
|
239
|
+
if (command.commands.length === 0)
|
|
240
|
+
return [command];
|
|
241
|
+
return command.commands.flatMap(child => collectLeafCommands(child));
|
|
242
|
+
}
|
|
243
|
+
function collectDescendantCommands(command) {
|
|
244
|
+
return command.commands.flatMap(child => [child, ...collectDescendantCommands(child)]);
|
|
245
|
+
}
|
|
246
|
+
function formatCommanderPositionals(args) {
|
|
247
|
+
return args
|
|
248
|
+
.map(arg => {
|
|
249
|
+
const name = `${arg.name()}${arg.variadic ? '...' : ''}`;
|
|
250
|
+
return arg.required ? `<${name}>` : `[${name}]`;
|
|
251
|
+
})
|
|
252
|
+
.join(' ');
|
|
253
|
+
}
|
|
254
|
+
function formatCommanderUsage(command, opts = {}) {
|
|
255
|
+
const path = commanderPath(command).join(' ');
|
|
256
|
+
const positionalText = formatCommanderPositionals(command.registeredArguments);
|
|
257
|
+
const hasOptions = compactCommanderOptions(command.options).length > 0
|
|
258
|
+
|| (opts.namespaceRoot ? compactCommanderOptions(opts.namespaceRoot.options).length > 0 : false)
|
|
259
|
+
|| (opts.globalCommand ? compactCommanderOptions(opts.globalCommand.options).length > 0 : false);
|
|
260
|
+
const optionText = hasOptions ? ' [options]' : '';
|
|
261
|
+
return `${path}${positionalText ? ` ${positionalText}` : ''}${optionText}`;
|
|
262
|
+
}
|
|
263
|
+
function compactCommanderCommand(namespaceRoot, command, opts = {}) {
|
|
264
|
+
const relativePath = commandPathFromRoot(namespaceRoot, command);
|
|
265
|
+
return {
|
|
266
|
+
name: relativePath.join(' '),
|
|
267
|
+
command: commanderPath(command).join(' '),
|
|
268
|
+
usage: formatCommanderUsage(command, { namespaceRoot, globalCommand: opts.globalCommand }),
|
|
269
|
+
description: command.description(),
|
|
270
|
+
...(command.aliases().length ? { aliases: command.aliases() } : {}),
|
|
271
|
+
positionals: command.registeredArguments.map(compactCommanderArgument),
|
|
272
|
+
command_options: compactCommanderOptions(command.options),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
export function commanderNamespaceHelpData(namespaceRoot, opts = {}) {
|
|
276
|
+
const leaves = collectLeafCommands(namespaceRoot)
|
|
277
|
+
.filter(command => command !== namespaceRoot)
|
|
278
|
+
.sort((a, b) => commandPathFromRoot(namespaceRoot, a).join(' ').localeCompare(commandPathFromRoot(namespaceRoot, b).join(' ')));
|
|
279
|
+
// Respect commander's `.usage()` override (e.g. `<session> <command> [options]`
|
|
280
|
+
// on `browser`); fall back to the generic `<command> [args] [options]` form.
|
|
281
|
+
// Read the private `_usage` field directly because `.usage()` returns the
|
|
282
|
+
// auto-generated form if no override was set.
|
|
283
|
+
const commandPath = commanderPath(namespaceRoot).join(' ');
|
|
284
|
+
const usageOverride = namespaceRoot._usage;
|
|
285
|
+
const usage = usageOverride
|
|
286
|
+
? `${commandPath} ${usageOverride}`
|
|
287
|
+
: `${commandPath} <command> [args] [options]`;
|
|
288
|
+
return {
|
|
289
|
+
namespace: namespaceRoot.name(),
|
|
290
|
+
command: commandPath,
|
|
291
|
+
usage,
|
|
292
|
+
description: opts.description ?? namespaceRoot.description(),
|
|
293
|
+
command_count: leaves.length,
|
|
294
|
+
commands: leaves.map(command => compactCommanderCommand(namespaceRoot, command, opts)),
|
|
295
|
+
namespace_options: compactCommanderOptions(namespaceRoot.options),
|
|
296
|
+
...(opts.globalCommand ? { global_options: compactCommanderOptions(opts.globalCommand.options) } : {}),
|
|
297
|
+
structured_help: {
|
|
298
|
+
formats: ['yaml', 'json'],
|
|
299
|
+
usage: `${commandPath} --help -f yaml`,
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
export function commanderCommandHelpData(namespaceRoot, command, opts = {}) {
|
|
304
|
+
return {
|
|
305
|
+
namespace: namespaceRoot.name(),
|
|
306
|
+
...compactCommanderCommand(namespaceRoot, command, opts),
|
|
307
|
+
namespace_options: compactCommanderOptions(namespaceRoot.options),
|
|
308
|
+
...(opts.globalCommand ? { global_options: compactCommanderOptions(opts.globalCommand.options) } : {}),
|
|
309
|
+
structured_help: {
|
|
310
|
+
formats: ['yaml', 'json'],
|
|
311
|
+
usage: `${commanderPath(command).join(' ')} --help -f yaml`,
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
export function commanderGroupHelpData(namespaceRoot, groupCommand, opts = {}) {
|
|
316
|
+
const leaves = collectLeafCommands(groupCommand)
|
|
317
|
+
.filter(command => command !== groupCommand)
|
|
318
|
+
.sort((a, b) => commandPathFromRoot(namespaceRoot, a).join(' ').localeCompare(commandPathFromRoot(namespaceRoot, b).join(' ')));
|
|
319
|
+
return {
|
|
320
|
+
namespace: namespaceRoot.name(),
|
|
321
|
+
group: commandPathFromRoot(namespaceRoot, groupCommand).join(' '),
|
|
322
|
+
command: commanderPath(groupCommand).join(' '),
|
|
323
|
+
usage: `${commanderPath(groupCommand).join(' ')} <command> [args] [options]`,
|
|
324
|
+
description: groupCommand.description(),
|
|
325
|
+
command_count: leaves.length,
|
|
326
|
+
commands: leaves.map(command => compactCommanderCommand(namespaceRoot, command, opts)),
|
|
327
|
+
namespace_options: compactCommanderOptions(namespaceRoot.options),
|
|
328
|
+
...(opts.globalCommand ? { global_options: compactCommanderOptions(opts.globalCommand.options) } : {}),
|
|
329
|
+
structured_help: {
|
|
330
|
+
formats: ['yaml', 'json'],
|
|
331
|
+
usage: `${commanderPath(groupCommand).join(' ')} --help -f yaml`,
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
export function installCommanderNamespaceStructuredHelp(namespaceRoot, opts = {}) {
|
|
336
|
+
installStructuredHelp(namespaceRoot, () => commanderNamespaceHelpData(namespaceRoot, opts));
|
|
337
|
+
for (const command of collectDescendantCommands(namespaceRoot)) {
|
|
338
|
+
if (command.commands.length > 0) {
|
|
339
|
+
installStructuredHelp(command, () => commanderGroupHelpData(namespaceRoot, command, opts));
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
installStructuredHelp(command, () => commanderCommandHelpData(namespaceRoot, command, opts));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function positionals(cmd) {
|
|
347
|
+
return cmd.args.filter(arg => arg.positional);
|
|
348
|
+
}
|
|
349
|
+
function commandOptions(cmd) {
|
|
350
|
+
return cmd.args.filter(arg => !arg.positional);
|
|
351
|
+
}
|
|
352
|
+
function formatPositionals(args) {
|
|
353
|
+
return args
|
|
354
|
+
.map(arg => arg.required ? `<${arg.name}>` : `[${arg.name}]`)
|
|
355
|
+
.join(' ');
|
|
356
|
+
}
|
|
357
|
+
function formatCommandOptionTerm(arg) {
|
|
358
|
+
if (arg.required || arg.valueRequired)
|
|
359
|
+
return `--${arg.name} <value>`;
|
|
360
|
+
return `--${arg.name} [value]`;
|
|
361
|
+
}
|
|
362
|
+
export function formatCommandListTerm(cmd) {
|
|
363
|
+
const positionalText = formatPositionals(positionals(cmd));
|
|
364
|
+
const optionText = commandOptions(cmd).length > 0 ? ' [options]' : '';
|
|
365
|
+
return `${cmd.name}${positionalText ? ` ${positionalText}` : ''}${optionText}`;
|
|
366
|
+
}
|
|
367
|
+
function formatUsage(cmd) {
|
|
368
|
+
const positionalText = formatPositionals(positionals(cmd));
|
|
369
|
+
return `${CLI_COMMAND} ${cmd.site} ${cmd.name}${positionalText ? ` ${positionalText}` : ''} [options]`;
|
|
370
|
+
}
|
|
371
|
+
function compactCommand(cmd) {
|
|
372
|
+
return {
|
|
373
|
+
name: cmd.name,
|
|
374
|
+
command: `${CLI_COMMAND} ${cmd.site} ${cmd.name}`,
|
|
375
|
+
usage: formatUsage(cmd),
|
|
376
|
+
access: cmd.access,
|
|
377
|
+
description: cmd.description,
|
|
378
|
+
browser: !!cmd.browser,
|
|
379
|
+
...(cmd.domain ? { domain: cmd.domain } : {}),
|
|
380
|
+
...(cmd.aliases?.length ? { aliases: cmd.aliases } : {}),
|
|
381
|
+
positionals: positionals(cmd).map(compactArg),
|
|
382
|
+
command_options: commandOptions(cmd).map(compactArg),
|
|
383
|
+
...(cmd.browser ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
|
|
384
|
+
example: formatCommandExample(cmd),
|
|
385
|
+
...(cmd.siteSession ? { siteSession: cmd.siteSession } : {}),
|
|
386
|
+
...(cmd.defaultFormat ? { defaultFormat: cmd.defaultFormat } : {}),
|
|
387
|
+
...(cmd.columns?.length ? { columns: cmd.columns } : {}),
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
export function rootHelpData(program, groups) {
|
|
391
|
+
const adapterNames = new Set([...groups.external.map(cli => cli.name), ...groups.apps, ...groups.sites]);
|
|
392
|
+
const commands = program.commands
|
|
393
|
+
.filter(command => !adapterNames.has(command.name()))
|
|
394
|
+
.map(command => ({
|
|
395
|
+
name: command.name(),
|
|
396
|
+
description: command.description(),
|
|
397
|
+
}));
|
|
398
|
+
const sortLocale = (a, b) => a.localeCompare(b);
|
|
399
|
+
return {
|
|
400
|
+
name: program.name(),
|
|
401
|
+
description: program.description(),
|
|
402
|
+
commands,
|
|
403
|
+
external_clis: {
|
|
404
|
+
count: groups.external.length,
|
|
405
|
+
clis: groups.external.map(cli => cli.name).sort(sortLocale),
|
|
406
|
+
display: groups.external.map(cli => cli.label).sort(sortLocale),
|
|
407
|
+
},
|
|
408
|
+
app_adapters: {
|
|
409
|
+
count: groups.apps.length,
|
|
410
|
+
apps: [...groups.apps].sort(sortLocale),
|
|
411
|
+
},
|
|
412
|
+
site_adapters: {
|
|
413
|
+
count: groups.sites.length,
|
|
414
|
+
sites: [...groups.sites].sort(sortLocale),
|
|
415
|
+
},
|
|
416
|
+
next: [
|
|
417
|
+
`${CLI_COMMAND} <site> --help -f yaml`,
|
|
418
|
+
`${CLI_COMMAND} list -f yaml`,
|
|
419
|
+
`${CLI_COMMAND} <site> <command> -f yaml`,
|
|
420
|
+
],
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
export function siteHelpData(site, commands) {
|
|
424
|
+
const unique = [...new Map(commands.map(cmd => [fullName(cmd), cmd])).values()]
|
|
425
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
426
|
+
return {
|
|
427
|
+
site,
|
|
428
|
+
command_count: unique.length,
|
|
429
|
+
commands: unique.map(cmd => compactCommand(cmd)),
|
|
430
|
+
common_options: COMMON_OPTIONS.map(compactCommonOption),
|
|
431
|
+
...(unique.some(cmd => cmd.browser) ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
|
|
432
|
+
next: [
|
|
433
|
+
`${CLI_COMMAND} ${site} <command> --help -f yaml`,
|
|
434
|
+
`${CLI_COMMAND} ${site} <command> -f yaml`,
|
|
435
|
+
],
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
export function commandHelpData(cmd) {
|
|
439
|
+
return {
|
|
440
|
+
site: cmd.site,
|
|
441
|
+
...compactCommand(cmd),
|
|
442
|
+
common_options: COMMON_OPTIONS.map(compactCommonOption),
|
|
443
|
+
...(cmd.browser ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
|
|
444
|
+
output_formats: ['table', 'plain', 'yaml', 'json', 'md', 'csv'],
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
function formatRows(rows) {
|
|
448
|
+
if (rows.length === 0)
|
|
449
|
+
return [];
|
|
450
|
+
const width = Math.min(Math.max(...rows.map(([left]) => left.length)), 34);
|
|
451
|
+
return rows.map(([left, right]) => ` ${left.padEnd(width + 2)}${right}`);
|
|
452
|
+
}
|
|
453
|
+
function formatArgHelp(arg) {
|
|
454
|
+
const parts = [];
|
|
455
|
+
if (arg.help)
|
|
456
|
+
parts.push(arg.help);
|
|
457
|
+
if (arg.default !== undefined)
|
|
458
|
+
parts.push(`default: ${arg.default}`);
|
|
459
|
+
if (arg.choices?.length)
|
|
460
|
+
parts.push(`choices: ${arg.choices.join(', ')}`);
|
|
461
|
+
return parts.join(' ');
|
|
462
|
+
}
|
|
463
|
+
export function formatCommonOptionsHelpText() {
|
|
464
|
+
const rows = COMMON_OPTIONS.map(option => {
|
|
465
|
+
const details = [option.help];
|
|
466
|
+
if ('default' in option)
|
|
467
|
+
details.push(`default: ${option.default}`);
|
|
468
|
+
if ('choices' in option)
|
|
469
|
+
details.push(`choices: ${option.choices.join(', ')}`);
|
|
470
|
+
return [option.flags, details.join(' ')];
|
|
471
|
+
});
|
|
472
|
+
return ['Common options:', ...formatRows(rows)].join('\n');
|
|
473
|
+
}
|
|
474
|
+
export function formatBrowserCommonOptionsHelpText() {
|
|
475
|
+
const rows = BROWSER_COMMON_OPTIONS.map(option => {
|
|
476
|
+
const details = [option.help];
|
|
477
|
+
if ('choices' in option)
|
|
478
|
+
details.push(`choices: ${option.choices.join(', ')}`);
|
|
479
|
+
return [option.flags, details.join(' ')];
|
|
480
|
+
});
|
|
481
|
+
return ['Browser common options:', ...formatRows(rows)].join('\n');
|
|
482
|
+
}
|
|
483
|
+
export function formatSiteHelpText(site, commands) {
|
|
484
|
+
const unique = [...new Map(commands.map(cmd => [fullName(cmd), cmd])).values()]
|
|
485
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
486
|
+
const lines = [
|
|
487
|
+
`Usage: ${CLI_COMMAND} ${site} <command> [args] [options]`,
|
|
488
|
+
'',
|
|
489
|
+
wrapCommaList(unique.map(cmd => cmd.name), { indent: '' }),
|
|
490
|
+
'',
|
|
491
|
+
'Commands:',
|
|
492
|
+
...formatRows(unique.map(cmd => [formatCommandListTerm(cmd), formatSiteCommandDescription(cmd)])),
|
|
493
|
+
'',
|
|
494
|
+
formatCommonOptionsHelpText(),
|
|
495
|
+
...(unique.some(cmd => cmd.browser) ? ['', formatBrowserCommonOptionsHelpText()] : []),
|
|
496
|
+
'',
|
|
497
|
+
`Agent tip: use '${CLI_COMMAND} ${site} --help -f yaml' to get all command args/options in one structured response.`,
|
|
498
|
+
'',
|
|
499
|
+
];
|
|
500
|
+
return lines.join('\n');
|
|
501
|
+
}
|
|
502
|
+
export function formatCommandHelpText(cmd) {
|
|
503
|
+
const lines = [
|
|
504
|
+
`Usage: ${formatUsage(cmd)}`,
|
|
505
|
+
'',
|
|
506
|
+
cmd.description,
|
|
507
|
+
'',
|
|
508
|
+
];
|
|
509
|
+
const positionalRows = positionals(cmd).map(arg => [
|
|
510
|
+
arg.name,
|
|
511
|
+
formatArgHelp(arg),
|
|
512
|
+
]);
|
|
513
|
+
if (positionalRows.length) {
|
|
514
|
+
lines.push('Arguments:', ...formatRows(positionalRows), '');
|
|
515
|
+
}
|
|
516
|
+
const optionRows = commandOptions(cmd).map(arg => [
|
|
517
|
+
formatCommandOptionTerm(arg),
|
|
518
|
+
formatArgHelp(arg),
|
|
519
|
+
]);
|
|
520
|
+
if (optionRows.length) {
|
|
521
|
+
lines.push('Command options:', ...formatRows(optionRows), '');
|
|
522
|
+
}
|
|
523
|
+
lines.push(formatCommonOptionsHelpText(), '');
|
|
524
|
+
if (cmd.browser)
|
|
525
|
+
lines.push(formatBrowserCommonOptionsHelpText(), '');
|
|
526
|
+
const meta = [];
|
|
527
|
+
meta.push(`Access: ${cmd.access}`);
|
|
528
|
+
meta.push(`Browser: ${cmd.browser ? 'yes' : 'no'}`);
|
|
529
|
+
if (cmd.domain)
|
|
530
|
+
meta.push(`Domain: ${cmd.domain}`);
|
|
531
|
+
if (cmd.defaultFormat)
|
|
532
|
+
meta.push(`Default format: ${cmd.defaultFormat}`);
|
|
533
|
+
if (cmd.aliases?.length)
|
|
534
|
+
meta.push(`Aliases: ${cmd.aliases.join(', ')}`);
|
|
535
|
+
lines.push(meta.join(' | '));
|
|
536
|
+
lines.push(`Example: ${formatCommandExample(cmd)}`);
|
|
537
|
+
if (cmd.columns?.length)
|
|
538
|
+
lines.push(`Output columns: ${cmd.columns.join(', ')}`);
|
|
539
|
+
lines.push("Agent tip: use '--help -f yaml' for structured args/options.");
|
|
540
|
+
lines.push('');
|
|
541
|
+
return lines.join('\n');
|
|
542
|
+
}
|
|
543
|
+
export function installStructuredHelp(command, data, textSuffix) {
|
|
544
|
+
const original = command.helpInformation.bind(command);
|
|
545
|
+
command.helpInformation = ((contextOptions) => {
|
|
546
|
+
const format = getRequestedHelpFormat();
|
|
547
|
+
if (format)
|
|
548
|
+
return renderStructuredHelp(data(), format);
|
|
549
|
+
const suffix = typeof textSuffix === 'function' ? textSuffix() : textSuffix ?? '';
|
|
550
|
+
return original(contextOptions) + suffix;
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
export function formatSiteCommandDescription(cmd) {
|
|
554
|
+
const access = cmd.access === 'write' ? '[write]' : '[read]';
|
|
555
|
+
return `${access} ${cmd.description}`;
|
|
556
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { classifyAdapter, formatRootAdapterHelpText } from './help.js';
|
|
3
|
+
describe('classifyAdapter', () => {
|
|
4
|
+
it('classifies DNS-style domains as site', () => {
|
|
5
|
+
expect(classifyAdapter('www.bilibili.com')).toBe('site');
|
|
6
|
+
expect(classifyAdapter('chatgpt.com')).toBe('site');
|
|
7
|
+
expect(classifyAdapter('claude.ai')).toBe('site');
|
|
8
|
+
expect(classifyAdapter('grok.com')).toBe('site');
|
|
9
|
+
});
|
|
10
|
+
it('classifies localhost as app (Electron / osascript desktop integrations)', () => {
|
|
11
|
+
expect(classifyAdapter('localhost')).toBe('app');
|
|
12
|
+
});
|
|
13
|
+
it('classifies non-DNS domain strings as app (e.g. literal "doubao-app")', () => {
|
|
14
|
+
expect(classifyAdapter('doubao-app')).toBe('app');
|
|
15
|
+
});
|
|
16
|
+
it('defaults missing domain to site (most adapters without explicit domain are public web scrapers)', () => {
|
|
17
|
+
expect(classifyAdapter(undefined)).toBe('site');
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('formatRootAdapterHelpText', () => {
|
|
21
|
+
it('renders all three sections in External / App / Site order when populated', () => {
|
|
22
|
+
const text = formatRootAdapterHelpText({
|
|
23
|
+
external: [
|
|
24
|
+
{ name: 'gh', label: 'gh' },
|
|
25
|
+
{ name: 'wx', label: 'wx(wx-cli)' },
|
|
26
|
+
],
|
|
27
|
+
apps: ['chatwise', 'codex'],
|
|
28
|
+
sites: ['bilibili'],
|
|
29
|
+
});
|
|
30
|
+
expect(text).toContain('External CLIs (2):');
|
|
31
|
+
expect(text).toContain('App adapters (2):');
|
|
32
|
+
expect(text).toContain('Site adapters (1):');
|
|
33
|
+
expect(text).toContain('wx(wx-cli)');
|
|
34
|
+
expect(text.indexOf('External CLIs')).toBeLessThan(text.indexOf('App adapters'));
|
|
35
|
+
expect(text.indexOf('App adapters')).toBeLessThan(text.indexOf('Site adapters'));
|
|
36
|
+
});
|
|
37
|
+
it('omits empty sections instead of rendering a (0) header', () => {
|
|
38
|
+
const text = formatRootAdapterHelpText({
|
|
39
|
+
external: [],
|
|
40
|
+
apps: [],
|
|
41
|
+
sites: ['bilibili'],
|
|
42
|
+
});
|
|
43
|
+
expect(text).not.toContain('External CLIs');
|
|
44
|
+
expect(text).not.toContain('App adapters');
|
|
45
|
+
expect(text).toContain('Site adapters (1):');
|
|
46
|
+
});
|
|
47
|
+
it('returns empty string when all groups are empty', () => {
|
|
48
|
+
expect(formatRootAdapterHelpText({ external: [], apps: [], sites: [] })).toBe('');
|
|
49
|
+
});
|
|
50
|
+
it('always renders the agent discovery hint when any section is populated', () => {
|
|
51
|
+
const text = formatRootAdapterHelpText({
|
|
52
|
+
external: [],
|
|
53
|
+
apps: [],
|
|
54
|
+
sites: ['bilibili'],
|
|
55
|
+
});
|
|
56
|
+
expect(text).toContain("'webcmd <site> --help -f yaml'");
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin lifecycle hooks: allows plugins to tap into webcmd's execution lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* Hooks use globalThis (like the command registry) to guarantee a single shared
|
|
5
|
+
* instance across all module copies — critical when TS plugins are loaded via
|
|
6
|
+
* npm link / peerDependency symlinks.
|
|
7
|
+
*
|
|
8
|
+
* Available hooks:
|
|
9
|
+
* onStartup — fired once after all commands & plugins are discovered
|
|
10
|
+
* onBeforeExecute — fired before every command execution
|
|
11
|
+
* onAfterExecute — fired after every command execution (receives result)
|
|
12
|
+
*/
|
|
13
|
+
export type HookName = 'onStartup' | 'onBeforeExecute' | 'onAfterExecute';
|
|
14
|
+
export interface HookContext {
|
|
15
|
+
/** Command full name in "site/name" format, or "__startup__" for onStartup */
|
|
16
|
+
command: string;
|
|
17
|
+
/** Coerced and validated arguments */
|
|
18
|
+
args: Record<string, unknown>;
|
|
19
|
+
/** Epoch ms when execution started (set by executeCommand) */
|
|
20
|
+
startedAt?: number;
|
|
21
|
+
/** Epoch ms when execution finished (set by executeCommand) */
|
|
22
|
+
finishedAt?: number;
|
|
23
|
+
/** Error thrown by the command, if execution failed */
|
|
24
|
+
error?: unknown;
|
|
25
|
+
/** Plugins can attach arbitrary data here for cross-hook communication */
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
}
|
|
28
|
+
export type HookFn = (ctx: HookContext, result?: unknown) => void | Promise<void>;
|
|
29
|
+
declare global {
|
|
30
|
+
var __webcmd_hooks__: Map<HookName, HookFn[]> | undefined;
|
|
31
|
+
}
|
|
32
|
+
/** Register a hook that fires once after all plugins are discovered. */
|
|
33
|
+
export declare function onStartup(fn: HookFn): void;
|
|
34
|
+
/** Register a hook that fires before every command execution. */
|
|
35
|
+
export declare function onBeforeExecute(fn: HookFn): void;
|
|
36
|
+
/** Register a hook that fires after every command execution with the result. */
|
|
37
|
+
export declare function onAfterExecute(fn: HookFn): void;
|
|
38
|
+
/**
|
|
39
|
+
* Trigger all registered handlers for a hook.
|
|
40
|
+
* Each handler is wrapped in try/catch — a failing hook never blocks command execution.
|
|
41
|
+
*/
|
|
42
|
+
export declare function emitHook(name: HookName, ctx: HookContext, result?: unknown): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Remove all registered hooks. Intended for testing only.
|
|
45
|
+
*/
|
|
46
|
+
export declare function clearAllHooks(): void;
|