@earendil-works/pi-coding-agent 0.83.0 → 0.84.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +227 -0
- package/README.md +5 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +22 -3
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-check.d.ts +19 -0
- package/dist/cli/auth-check.d.ts.map +1 -0
- package/dist/cli/auth-check.js +50 -0
- package/dist/cli/auth-check.js.map +1 -0
- package/dist/cli/auth-command.d.ts +24 -0
- package/dist/cli/auth-command.d.ts.map +1 -0
- package/dist/cli/auth-command.js +102 -0
- package/dist/cli/auth-command.js.map +1 -0
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +2 -2
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts +5 -15
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +42 -82
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/cli/experimental/auth.d.ts +16 -0
- package/dist/cli/experimental/auth.d.ts.map +1 -0
- package/dist/cli/experimental/auth.js +13 -0
- package/dist/cli/experimental/auth.js.map +1 -0
- package/dist/cli/experimental/cli.d.ts +6 -0
- package/dist/cli/experimental/cli.d.ts.map +1 -0
- package/dist/cli/experimental/cli.js +5 -0
- package/dist/cli/experimental/cli.js.map +1 -0
- package/dist/cli/experimental/command-options.d.ts +17 -0
- package/dist/cli/experimental/command-options.d.ts.map +1 -0
- package/dist/cli/experimental/command-options.js +35 -0
- package/dist/cli/experimental/command-options.js.map +1 -0
- package/dist/cli/experimental/command.d.ts +63 -0
- package/dist/cli/experimental/command.d.ts.map +1 -0
- package/dist/cli/experimental/command.js +130 -0
- package/dist/cli/experimental/command.js.map +1 -0
- package/dist/cli/experimental/commands/client.d.ts +13 -0
- package/dist/cli/experimental/commands/client.d.ts.map +1 -0
- package/dist/cli/experimental/commands/client.js +25 -0
- package/dist/cli/experimental/commands/client.js.map +1 -0
- package/dist/cli/experimental/commands/pi.d.ts +15 -0
- package/dist/cli/experimental/commands/pi.d.ts.map +1 -0
- package/dist/cli/experimental/commands/pi.js +28 -0
- package/dist/cli/experimental/commands/pi.js.map +1 -0
- package/dist/cli/experimental/commands/server.d.ts +13 -0
- package/dist/cli/experimental/commands/server.d.ts.map +1 -0
- package/dist/cli/experimental/commands/server.js +25 -0
- package/dist/cli/experimental/commands/server.js.map +1 -0
- package/dist/cli/experimental/transport-address.d.ts +10 -0
- package/dist/cli/experimental/transport-address.d.ts.map +1 -0
- package/dist/cli/experimental/transport-address.js +38 -0
- package/dist/cli/experimental/transport-address.js.map +1 -0
- package/dist/cli/list-models.d.ts +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +2 -2
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/startup-ui.d.ts +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -2
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/remote-session.d.ts +53 -0
- package/dist/client/remote-session.d.ts.map +1 -0
- package/dist/client/remote-session.js +340 -0
- package/dist/client/remote-session.js.map +1 -0
- package/dist/client/transcript.d.ts +12 -0
- package/dist/client/transcript.d.ts.map +1 -0
- package/dist/client/transcript.js +98 -0
- package/dist/client/transcript.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -10
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +72 -70
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +25 -9
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +237 -39
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +43 -20
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +2 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +26 -3
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +5 -0
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/keybindings.d.ts +44 -4
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/model-config.d.ts +29 -5
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +4 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -3
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +13 -10
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +4 -3
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +42 -10
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +30 -13
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +233 -73
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/models-store.d.ts +12 -7
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +83 -14
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/package-manager.d.ts +4 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +63 -36
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts +8 -0
- package/dist/core/pi-manifest.d.ts.map +1 -0
- package/dist/core/pi-manifest.js +25 -0
- package/dist/core/pi-manifest.js.map +1 -0
- package/dist/core/provider-composer.d.ts +4 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +36 -15
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +73 -67
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +2 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts +5 -5
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +11 -8
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +3 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +12 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +40 -16
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts +4 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +6 -4
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts +4 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +11 -7
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts +7 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +16 -19
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +4 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +5 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts +4 -0
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +5 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +4 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +7 -3
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts +4 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +6 -2
- package/dist/core/tools/write.js.map +1 -1
- package/dist/extensions/llama/index.d.ts.map +1 -1
- package/dist/extensions/llama/index.js +11 -2
- package/dist/extensions/llama/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +21 -7
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +70 -25
- package/dist/main.js.map +1 -1
- package/dist/modes/index.d.ts +1 -0
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +5 -2
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +13 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +7 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
- package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
- package/dist/modes/interactive/components/markdown-transform.js +19 -0
- package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
- package/dist/modes/interactive/components/mermaid.d.ts +11 -0
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
- package/dist/modes/interactive/components/mermaid.js +75 -0
- package/dist/modes/interactive/components/mermaid.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +16 -4
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +4 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +26 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +8 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +30 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +3 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +9 -2
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +36 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +454 -138
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -0
- package/dist/modes/interactive/theme/light.json +1 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +3 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +10 -1
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +5 -1
- package/dist/modes/interactive/theme/theme.d.ts +2 -2
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +24 -6
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +28 -0
- package/dist/modes/json-event.d.ts.map +1 -0
- package/dist/modes/json-event.js +12 -0
- package/dist/modes/json-event.js.map +1 -0
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +12 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +5 -4
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +4 -3
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +11 -9
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/rpc-entry.d.ts.map +1 -1
- package/dist/rpc-entry.js +1 -0
- package/dist/rpc-entry.js.map +1 -1
- package/dist/server/create-harness.d.ts +26 -0
- package/dist/server/create-harness.d.ts.map +1 -0
- package/dist/server/create-harness.js +104 -0
- package/dist/server/create-harness.js.map +1 -0
- package/dist/utils/abort.d.ts +5 -0
- package/dist/utils/abort.d.ts.map +1 -0
- package/dist/utils/abort.js +48 -0
- package/dist/utils/abort.js.map +1 -0
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +22 -2
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/management-http.d.ts +23 -0
- package/dist/utils/management-http.d.ts.map +1 -0
- package/dist/utils/management-http.js +50 -0
- package/dist/utils/management-http.js.map +1 -0
- package/dist/utils/paths.d.ts +3 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +23 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/tool-result-images.d.ts +19 -0
- package/dist/utils/tool-result-images.d.ts.map +1 -0
- package/dist/utils/tool-result-images.js +45 -0
- package/dist/utils/tool-result-images.js.map +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +4 -6
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +4 -0
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +20 -2
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +2 -2
- package/docs/custom-provider.md +7 -5
- package/docs/extensions.md +30 -5
- package/docs/json.md +19 -14
- package/docs/keybindings.md +46 -14
- package/docs/models.md +24 -3
- package/docs/providers.md +9 -1
- package/docs/quickstart.md +2 -0
- package/docs/rpc.md +13 -11
- package/docs/sdk.md +21 -2
- package/docs/security.md +1 -1
- package/docs/settings.md +4 -1
- package/docs/themes.md +5 -3
- package/docs/usage.md +7 -0
- package/examples/extensions/custom-compaction.ts +1 -16
- package/examples/extensions/custom-provider-anthropic/index.ts +2 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/handoff.ts +2 -11
- package/examples/extensions/qna.ts +3 -7
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +7 -18
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/rpc-extension-ui.ts +11 -2
- package/examples/sdk/02-custom-model.ts +1 -2
- package/examples/sdk/09-api-keys-and-oauth.ts +1 -1
- package/examples/sdk/12-full-control.ts +1 -1
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +64 -20
- package/package.json +13 -6
|
@@ -1,116 +1,76 @@
|
|
|
1
1
|
import { resolveCliModel } from "../core/model-resolver.js";
|
|
2
|
+
import { AuthCommandError, getAuthCredential, validateAuthCommandArgs } from "./auth-command.js";
|
|
2
3
|
const DEFAULT_BEARER_TOKEN_MIN_EXPIRY_MS = 30 * 60_000;
|
|
3
|
-
export class CredentialPrintError extends Error {
|
|
4
|
-
}
|
|
5
|
-
export function isCredentialPrintHelp(args) {
|
|
6
|
-
return (args[0] === "auth" && (args[1] === undefined || args[1] === "help" || args[1] === "--help" || args[1] === "-h"));
|
|
7
|
-
}
|
|
8
|
-
export function printCredentialPrintHelp() {
|
|
9
|
-
console.log(`Usage:
|
|
10
|
-
pi auth print-api-key --model <model> [--provider <provider>]
|
|
11
|
-
pi auth print-bearer-token --model <model> [--provider <provider>] [--min-expiry <duration>]
|
|
12
|
-
|
|
13
|
-
Prints the configured credential alone on stdout. Provider inference uses configured credentials; specify --provider to select explicitly. Bearer tokens have a 30-minute minimum expiry by default. --min-expiry accepts ms, s, m, or h (for example, 30m).`);
|
|
14
|
-
}
|
|
15
|
-
/** Parse the small, extensible `pi auth` command surface before normal startup. */
|
|
16
|
-
export function parseCredentialPrintCommand(args) {
|
|
17
|
-
if (args[0] !== "auth")
|
|
18
|
-
return undefined;
|
|
19
|
-
const kind = args[1] === "print-api-key" ? "api_key" : args[1] === "print-bearer-token" ? "bearer_token" : undefined;
|
|
20
|
-
if (!kind) {
|
|
21
|
-
throw new CredentialPrintError(`Unknown auth command "${args[1] ?? ""}". Use "pi auth print-api-key" or "pi auth print-bearer-token".`);
|
|
22
|
-
}
|
|
23
|
-
const commandArgs = [];
|
|
24
|
-
let minExpiryMs;
|
|
25
|
-
for (let index = 2; index < args.length; index++) {
|
|
26
|
-
if (args[index] !== "--min-expiry") {
|
|
27
|
-
commandArgs.push(args[index]);
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
if (kind !== "bearer_token") {
|
|
31
|
-
throw new CredentialPrintError("--min-expiry is only supported by print-bearer-token");
|
|
32
|
-
}
|
|
33
|
-
const value = args[++index];
|
|
34
|
-
const match = value ? /^(\d+)(ms|s|m|h)$/iu.exec(value) : undefined;
|
|
35
|
-
if (!match) {
|
|
36
|
-
throw new CredentialPrintError("--min-expiry must use a duration such as 30m or 1h");
|
|
37
|
-
}
|
|
38
|
-
const amount = Number(match[1]);
|
|
39
|
-
const unit = match[2];
|
|
40
|
-
minExpiryMs = amount * (unit === "ms" ? 1 : unit === "s" ? 1_000 : unit === "m" ? 60_000 : 3_600_000);
|
|
41
|
-
}
|
|
42
|
-
return minExpiryMs === undefined ? { kind, args: commandArgs } : { kind, args: commandArgs, minExpiryMs };
|
|
43
|
-
}
|
|
44
|
-
export function validateCredentialPrintArgs(args) {
|
|
45
|
-
if (!args.model?.trim()) {
|
|
46
|
-
throw new CredentialPrintError("Credential printing requires --model <model>");
|
|
47
|
-
}
|
|
48
|
-
if (args.apiKey !== undefined) {
|
|
49
|
-
throw new CredentialPrintError("Credential printing reads configured credentials; --api-key is not supported");
|
|
50
|
-
}
|
|
51
|
-
if (args.messages.length > 0 || args.fileArgs.length > 0 || args.unknownFlags.size > 0) {
|
|
52
|
-
throw new CredentialPrintError("Credential printing only accepts --provider and --model");
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
4
|
/**
|
|
56
|
-
* Resolve one
|
|
5
|
+
* Resolve one configured provider credential.
|
|
57
6
|
*
|
|
58
7
|
* This intentionally calls ModelRuntime.getAuth(), which refreshes and persists
|
|
59
8
|
* OAuth credentials with less than five minutes remaining through the normal request-auth path.
|
|
60
9
|
*/
|
|
61
|
-
export async function resolveCredentialForPrint(args, modelRuntime, kind, minExpiryMs) {
|
|
62
|
-
|
|
63
|
-
const credentialTypes = new Map((await modelRuntime.listCredentials()).map((credential) => [credential.providerId, credential.type]));
|
|
64
|
-
const
|
|
65
|
-
if (
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
throw new
|
|
10
|
+
export async function resolveCredentialForPrint(args, modelRuntime, kind, minExpiryMs, signal) {
|
|
11
|
+
const { provider: cliProvider, model: cliModel } = validateAuthCommandArgs(args, kind);
|
|
12
|
+
const credentialTypes = new Map((await modelRuntime.listCredentials({ signal })).map((credential) => [credential.providerId, credential.type]));
|
|
13
|
+
const providers = [];
|
|
14
|
+
if (cliProvider) {
|
|
15
|
+
const provider = modelRuntime.getProvider(cliProvider);
|
|
16
|
+
if (!provider) {
|
|
17
|
+
throw new AuthCommandError(`Unknown provider "${cliProvider}". Use --list-models to see available providers.`);
|
|
18
|
+
}
|
|
19
|
+
if (cliModel) {
|
|
20
|
+
const resolved = resolveCliModel({ cliProvider: provider.id, cliModel, modelRuntime });
|
|
21
|
+
if (resolved.error || !resolved.model) {
|
|
22
|
+
throw new AuthCommandError(resolved.error ?? "Unable to resolve the requested provider/model");
|
|
23
|
+
}
|
|
24
|
+
providers.push({ id: provider.id, model: resolved.model });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
providers.push({ id: provider.id });
|
|
69
28
|
}
|
|
70
|
-
models.push(resolved.model);
|
|
71
29
|
}
|
|
72
30
|
else {
|
|
73
31
|
for (const provider of modelRuntime.getProviders()) {
|
|
74
32
|
if (!credentialTypes.has(provider.id))
|
|
75
33
|
continue;
|
|
76
|
-
const resolved = resolveCliModel({ cliProvider: provider.id, cliModel:
|
|
34
|
+
const resolved = resolveCliModel({ cliProvider: provider.id, cliModel: cliModel, modelRuntime });
|
|
77
35
|
if (resolved.model && !resolved.error && !resolved.warning?.includes("Using custom model id")) {
|
|
78
|
-
|
|
36
|
+
providers.push({ id: provider.id, model: resolved.model });
|
|
79
37
|
}
|
|
80
38
|
}
|
|
81
|
-
if (
|
|
82
|
-
throw new
|
|
39
|
+
if (providers.length === 0) {
|
|
40
|
+
throw new AuthCommandError(`Model "${cliModel}" not found. Use --list-models to see available models.`);
|
|
83
41
|
}
|
|
84
42
|
}
|
|
85
43
|
const credentials = [];
|
|
86
|
-
for (const
|
|
87
|
-
const type = credentialTypes.get(
|
|
44
|
+
for (const provider of providers) {
|
|
45
|
+
const type = credentialTypes.get(provider.id);
|
|
88
46
|
if (kind === "api_key" && type === "oauth")
|
|
89
47
|
continue;
|
|
90
48
|
if (kind === "bearer_token" && type !== "oauth")
|
|
91
49
|
continue;
|
|
92
|
-
const
|
|
93
|
-
? { minOAuthValidityMs: minExpiryMs ?? DEFAULT_BEARER_TOKEN_MIN_EXPIRY_MS }
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
50
|
+
const authOptions = {
|
|
51
|
+
...(kind === "bearer_token" ? { minOAuthValidityMs: minExpiryMs ?? DEFAULT_BEARER_TOKEN_MIN_EXPIRY_MS } : {}),
|
|
52
|
+
signal,
|
|
53
|
+
};
|
|
54
|
+
const auth = provider.model
|
|
55
|
+
? await modelRuntime.getAuth(provider.model, authOptions)
|
|
56
|
+
: await modelRuntime.getAuth(provider.id, authOptions);
|
|
57
|
+
const value = getAuthCredential(auth);
|
|
98
58
|
if (value)
|
|
99
|
-
credentials.push({ providerId:
|
|
59
|
+
credentials.push({ providerId: provider.id, value });
|
|
100
60
|
}
|
|
101
61
|
if (credentials.length === 1)
|
|
102
62
|
return credentials[0].value;
|
|
103
63
|
if (credentials.length === 0) {
|
|
104
|
-
const providerId =
|
|
64
|
+
const providerId = providers[0]?.id;
|
|
105
65
|
const type = providerId ? credentialTypes.get(providerId) : undefined;
|
|
106
|
-
if (
|
|
107
|
-
throw new
|
|
66
|
+
if (cliProvider && kind === "api_key" && type === "oauth") {
|
|
67
|
+
throw new AuthCommandError(`Provider "${providerId}" is configured with OAuth, not an API key`);
|
|
108
68
|
}
|
|
109
|
-
if (
|
|
110
|
-
throw new
|
|
69
|
+
if (cliProvider && kind === "bearer_token" && type !== "oauth") {
|
|
70
|
+
throw new AuthCommandError(`Provider "${providerId}" is not configured with an OAuth bearer token`);
|
|
111
71
|
}
|
|
112
|
-
throw new
|
|
72
|
+
throw new AuthCommandError(`No usable ${kind === "api_key" ? "API key" : "OAuth bearer token"} is configured`);
|
|
113
73
|
}
|
|
114
|
-
throw new
|
|
74
|
+
throw new AuthCommandError(`Multiple configured providers matched (${credentials.map(({ providerId }) => providerId).join(", ")}). Specify --provider.`);
|
|
115
75
|
}
|
|
116
76
|
//# sourceMappingURL=credential-print.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential-print.js","sourceRoot":"","sources":["../../src/cli/credential-print.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, CredentialInfo, Model } from \"@earendil-works/pi-ai\";\nimport { resolveCliModel } from \"../core/model-resolver.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\nimport type { Args } from \"./args.ts\";\n\nexport type CredentialPrintKind = \"api_key\" | \"bearer_token\";\n\nconst DEFAULT_BEARER_TOKEN_MIN_EXPIRY_MS = 30 * 60_000;\n\nexport interface CredentialPrintCommand {\n\tkind: CredentialPrintKind;\n\targs: string[];\n\tminExpiryMs?: number;\n}\n\nexport class CredentialPrintError extends Error {}\n\nexport function isCredentialPrintHelp(args: string[]): boolean {\n\treturn (\n\t\targs[0] === \"auth\" && (args[1] === undefined || args[1] === \"help\" || args[1] === \"--help\" || args[1] === \"-h\")\n\t);\n}\n\nexport function printCredentialPrintHelp(): void {\n\tconsole.log(`Usage:\n pi auth print-api-key --model <model> [--provider <provider>]\n pi auth print-bearer-token --model <model> [--provider <provider>] [--min-expiry <duration>]\n\nPrints the configured credential alone on stdout. Provider inference uses configured credentials; specify --provider to select explicitly. Bearer tokens have a 30-minute minimum expiry by default. --min-expiry accepts ms, s, m, or h (for example, 30m).`);\n}\n\n/** Parse the small, extensible `pi auth` command surface before normal startup. */\nexport function parseCredentialPrintCommand(args: string[]): CredentialPrintCommand | undefined {\n\tif (args[0] !== \"auth\") return undefined;\n\n\tconst kind = args[1] === \"print-api-key\" ? \"api_key\" : args[1] === \"print-bearer-token\" ? \"bearer_token\" : undefined;\n\tif (!kind) {\n\t\tthrow new CredentialPrintError(\n\t\t\t`Unknown auth command \"${args[1] ?? \"\"}\". Use \"pi auth print-api-key\" or \"pi auth print-bearer-token\".`,\n\t\t);\n\t}\n\n\tconst commandArgs: string[] = [];\n\tlet minExpiryMs: number | undefined;\n\tfor (let index = 2; index < args.length; index++) {\n\t\tif (args[index] !== \"--min-expiry\") {\n\t\t\tcommandArgs.push(args[index]);\n\t\t\tcontinue;\n\t\t}\n\t\tif (kind !== \"bearer_token\") {\n\t\t\tthrow new CredentialPrintError(\"--min-expiry is only supported by print-bearer-token\");\n\t\t}\n\t\tconst value = args[++index];\n\t\tconst match = value ? /^(\\d+)(ms|s|m|h)$/iu.exec(value) : undefined;\n\t\tif (!match) {\n\t\t\tthrow new CredentialPrintError(\"--min-expiry must use a duration such as 30m or 1h\");\n\t\t}\n\t\tconst amount = Number(match[1]);\n\t\tconst unit = match[2];\n\t\tminExpiryMs = amount * (unit === \"ms\" ? 1 : unit === \"s\" ? 1_000 : unit === \"m\" ? 60_000 : 3_600_000);\n\t}\n\n\treturn minExpiryMs === undefined ? { kind, args: commandArgs } : { kind, args: commandArgs, minExpiryMs };\n}\n\nexport function validateCredentialPrintArgs(args: Args): void {\n\tif (!args.model?.trim()) {\n\t\tthrow new CredentialPrintError(\"Credential printing requires --model <model>\");\n\t}\n\tif (args.apiKey !== undefined) {\n\t\tthrow new CredentialPrintError(\"Credential printing reads configured credentials; --api-key is not supported\");\n\t}\n\tif (args.messages.length > 0 || args.fileArgs.length > 0 || args.unknownFlags.size > 0) {\n\t\tthrow new CredentialPrintError(\"Credential printing only accepts --provider and --model\");\n\t}\n}\n\n/**\n * Resolve one request credential for a specific provider/model pair.\n *\n * This intentionally calls ModelRuntime.getAuth(), which refreshes and persists\n * OAuth credentials with less than five minutes remaining through the normal request-auth path.\n */\nexport async function resolveCredentialForPrint(\n\targs: Args,\n\tmodelRuntime: ModelRuntime,\n\tkind: CredentialPrintKind,\n\tminExpiryMs?: number,\n): Promise<string> {\n\tvalidateCredentialPrintArgs(args);\n\n\tconst credentialTypes = new Map<string, CredentialInfo[\"type\"]>(\n\t\t(await modelRuntime.listCredentials()).map((credential) => [credential.providerId, credential.type]),\n\t);\n\tconst models: Model<Api>[] = [];\n\tif (args.provider) {\n\t\tconst resolved = resolveCliModel({ cliProvider: args.provider, cliModel: args.model, modelRuntime });\n\t\tif (resolved.error || !resolved.model) {\n\t\t\tthrow new CredentialPrintError(resolved.error ?? \"Unable to resolve the requested provider/model\");\n\t\t}\n\t\tmodels.push(resolved.model);\n\t} else {\n\t\tfor (const provider of modelRuntime.getProviders()) {\n\t\t\tif (!credentialTypes.has(provider.id)) continue;\n\t\t\tconst resolved = resolveCliModel({ cliProvider: provider.id, cliModel: args.model, modelRuntime });\n\t\t\tif (resolved.model && !resolved.error && !resolved.warning?.includes(\"Using custom model id\")) {\n\t\t\t\tmodels.push(resolved.model);\n\t\t\t}\n\t\t}\n\t\tif (models.length === 0) {\n\t\t\tthrow new CredentialPrintError(`Model \"${args.model}\" not found. Use --list-models to see available models.`);\n\t\t}\n\t}\n\n\tconst credentials: Array<{ providerId: string; value: string }> = [];\n\tfor (const model of models) {\n\t\tconst type = credentialTypes.get(model.provider);\n\t\tif (kind === \"api_key\" && type === \"oauth\") continue;\n\t\tif (kind === \"bearer_token\" && type !== \"oauth\") continue;\n\n\t\tconst auth = await modelRuntime.getAuth(\n\t\t\tmodel,\n\t\t\tkind === \"bearer_token\"\n\t\t\t\t? { minOAuthValidityMs: minExpiryMs ?? DEFAULT_BEARER_TOKEN_MIN_EXPIRY_MS }\n\t\t\t\t: undefined,\n\t\t);\n\t\tconst authorization = Object.entries(auth?.auth.headers ?? {}).find(\n\t\t\t([name]) => name.toLowerCase() === \"authorization\",\n\t\t)?.[1];\n\t\tconst bearerToken = typeof authorization === \"string\" ? /^Bearer\\s+(.+)$/iu.exec(authorization)?.[1] : undefined;\n\t\tconst value = kind === \"bearer_token\" ? (auth?.auth.apiKey ?? bearerToken) : auth?.auth.apiKey;\n\t\tif (value) credentials.push({ providerId: model.provider, value });\n\t}\n\n\tif (credentials.length === 1) return credentials[0].value;\n\tif (credentials.length === 0) {\n\t\tconst providerId = models[0]?.provider;\n\t\tconst type = providerId ? credentialTypes.get(providerId) : undefined;\n\t\tif (args.provider && kind === \"api_key\" && type === \"oauth\") {\n\t\t\tthrow new CredentialPrintError(`Provider \"${providerId}\" is configured with OAuth, not an API key`);\n\t\t}\n\t\tif (args.provider && kind === \"bearer_token\" && type !== \"oauth\") {\n\t\t\tthrow new CredentialPrintError(`Provider \"${providerId}\" is not configured with an OAuth bearer token`);\n\t\t}\n\t\tthrow new CredentialPrintError(\n\t\t\t`No usable ${kind === \"api_key\" ? \"API key\" : \"OAuth bearer token\"} is configured`,\n\t\t);\n\t}\n\tthrow new CredentialPrintError(\n\t\t`Model \"${args.model}\" has multiple configured providers (${credentials.map(({ providerId }) => providerId).join(\", \")}). Specify --provider.`,\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"credential-print.js","sourceRoot":"","sources":["../../src/cli/credential-print.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, CredentialInfo, Model } from \"@earendil-works/pi-ai\";\nimport { resolveCliModel } from \"../core/model-resolver.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\nimport type { Args } from \"./args.ts\";\nimport { AuthCommandError, type AuthCommandKind, getAuthCredential, validateAuthCommandArgs } from \"./auth-command.ts\";\n\nconst DEFAULT_BEARER_TOKEN_MIN_EXPIRY_MS = 30 * 60_000;\n\ntype CredentialPrintKind = Exclude<AuthCommandKind, \"check\">;\n\n/**\n * Resolve one configured provider credential.\n *\n * This intentionally calls ModelRuntime.getAuth(), which refreshes and persists\n * OAuth credentials with less than five minutes remaining through the normal request-auth path.\n */\nexport async function resolveCredentialForPrint(\n\targs: Args,\n\tmodelRuntime: ModelRuntime,\n\tkind: CredentialPrintKind,\n\tminExpiryMs?: number,\n\tsignal?: AbortSignal,\n): Promise<string> {\n\tconst { provider: cliProvider, model: cliModel } = validateAuthCommandArgs(args, kind);\n\tconst credentialTypes = new Map<string, CredentialInfo[\"type\"]>(\n\t\t(await modelRuntime.listCredentials({ signal })).map((credential) => [credential.providerId, credential.type]),\n\t);\n\tconst providers: Array<{ id: string; model?: Model<Api> }> = [];\n\tif (cliProvider) {\n\t\tconst provider = modelRuntime.getProvider(cliProvider);\n\t\tif (!provider) {\n\t\t\tthrow new AuthCommandError(`Unknown provider \"${cliProvider}\". Use --list-models to see available providers.`);\n\t\t}\n\t\tif (cliModel) {\n\t\t\tconst resolved = resolveCliModel({ cliProvider: provider.id, cliModel, modelRuntime });\n\t\t\tif (resolved.error || !resolved.model) {\n\t\t\t\tthrow new AuthCommandError(resolved.error ?? \"Unable to resolve the requested provider/model\");\n\t\t\t}\n\t\t\tproviders.push({ id: provider.id, model: resolved.model });\n\t\t} else {\n\t\t\tproviders.push({ id: provider.id });\n\t\t}\n\t} else {\n\t\tfor (const provider of modelRuntime.getProviders()) {\n\t\t\tif (!credentialTypes.has(provider.id)) continue;\n\t\t\tconst resolved = resolveCliModel({ cliProvider: provider.id, cliModel: cliModel!, modelRuntime });\n\t\t\tif (resolved.model && !resolved.error && !resolved.warning?.includes(\"Using custom model id\")) {\n\t\t\t\tproviders.push({ id: provider.id, model: resolved.model });\n\t\t\t}\n\t\t}\n\t\tif (providers.length === 0) {\n\t\t\tthrow new AuthCommandError(`Model \"${cliModel}\" not found. Use --list-models to see available models.`);\n\t\t}\n\t}\n\n\tconst credentials: Array<{ providerId: string; value: string }> = [];\n\tfor (const provider of providers) {\n\t\tconst type = credentialTypes.get(provider.id);\n\t\tif (kind === \"api_key\" && type === \"oauth\") continue;\n\t\tif (kind === \"bearer_token\" && type !== \"oauth\") continue;\n\t\tconst authOptions = {\n\t\t\t...(kind === \"bearer_token\" ? { minOAuthValidityMs: minExpiryMs ?? DEFAULT_BEARER_TOKEN_MIN_EXPIRY_MS } : {}),\n\t\t\tsignal,\n\t\t};\n\t\tconst auth = provider.model\n\t\t\t? await modelRuntime.getAuth(provider.model, authOptions)\n\t\t\t: await modelRuntime.getAuth(provider.id, authOptions);\n\t\tconst value = getAuthCredential(auth);\n\t\tif (value) credentials.push({ providerId: provider.id, value });\n\t}\n\n\tif (credentials.length === 1) return credentials[0].value;\n\tif (credentials.length === 0) {\n\t\tconst providerId = providers[0]?.id;\n\t\tconst type = providerId ? credentialTypes.get(providerId) : undefined;\n\t\tif (cliProvider && kind === \"api_key\" && type === \"oauth\") {\n\t\t\tthrow new AuthCommandError(`Provider \"${providerId}\" is configured with OAuth, not an API key`);\n\t\t}\n\t\tif (cliProvider && kind === \"bearer_token\" && type !== \"oauth\") {\n\t\t\tthrow new AuthCommandError(`Provider \"${providerId}\" is not configured with an OAuth bearer token`);\n\t\t}\n\t\tthrow new AuthCommandError(`No usable ${kind === \"api_key\" ? \"API key\" : \"OAuth bearer token\"} is configured`);\n\t}\n\tthrow new AuthCommandError(\n\t\t`Multiple configured providers matched (${credentials.map(({ providerId }) => providerId).join(\", \")}). Specify --provider.`,\n\t);\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type AuthInput = {
|
|
2
|
+
readonly type: "token";
|
|
3
|
+
readonly token: string;
|
|
4
|
+
} | {
|
|
5
|
+
readonly type: "file";
|
|
6
|
+
readonly path: string;
|
|
7
|
+
};
|
|
8
|
+
export interface RawAuthOptions {
|
|
9
|
+
readonly authToken?: string;
|
|
10
|
+
readonly authTokenFile?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function parseAuthInput(options: RawAuthOptions): {
|
|
13
|
+
auth?: AuthInput;
|
|
14
|
+
errors: string[];
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/cli/experimental/auth.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAW9F","sourcesContent":["export type AuthInput =\n\t| { readonly type: \"token\"; readonly token: string }\n\t| { readonly type: \"file\"; readonly path: string };\n\nexport interface RawAuthOptions {\n\treadonly authToken?: string;\n\treadonly authTokenFile?: string;\n}\n\nexport function parseAuthInput(options: RawAuthOptions): { auth?: AuthInput; errors: string[] } {\n\tif (options.authToken !== undefined && options.authTokenFile !== undefined) {\n\t\treturn { errors: [\"--auth-token and --auth-token-file are mutually exclusive\"] };\n\t}\n\tif (options.authToken !== undefined) {\n\t\treturn { auth: { type: \"token\", token: options.authToken }, errors: [] };\n\t}\n\tif (options.authTokenFile !== undefined) {\n\t\treturn { auth: { type: \"file\", path: options.authTokenFile }, errors: [] };\n\t}\n\treturn { errors: [] };\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function parseAuthInput(options) {
|
|
2
|
+
if (options.authToken !== undefined && options.authTokenFile !== undefined) {
|
|
3
|
+
return { errors: ["--auth-token and --auth-token-file are mutually exclusive"] };
|
|
4
|
+
}
|
|
5
|
+
if (options.authToken !== undefined) {
|
|
6
|
+
return { auth: { type: "token", token: options.authToken }, errors: [] };
|
|
7
|
+
}
|
|
8
|
+
if (options.authTokenFile !== undefined) {
|
|
9
|
+
return { auth: { type: "file", path: options.authTokenFile }, errors: [] };
|
|
10
|
+
}
|
|
11
|
+
return { errors: [] };
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/cli/experimental/auth.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,cAAc,CAAC,OAAuB,EAA0C;IAC/F,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAC5E,OAAO,EAAE,MAAM,EAAE,CAAC,2DAA2D,CAAC,EAAE,CAAC;IAClF,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC1E,CAAC;IACD,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACzC,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC5E,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAAA,CACtB","sourcesContent":["export type AuthInput =\n\t| { readonly type: \"token\"; readonly token: string }\n\t| { readonly type: \"file\"; readonly path: string };\n\nexport interface RawAuthOptions {\n\treadonly authToken?: string;\n\treadonly authTokenFile?: string;\n}\n\nexport function parseAuthInput(options: RawAuthOptions): { auth?: AuthInput; errors: string[] } {\n\tif (options.authToken !== undefined && options.authTokenFile !== undefined) {\n\t\treturn { errors: [\"--auth-token and --auth-token-file are mutually exclusive\"] };\n\t}\n\tif (options.authToken !== undefined) {\n\t\treturn { auth: { type: \"token\", token: options.authToken }, errors: [] };\n\t}\n\tif (options.authTokenFile !== undefined) {\n\t\treturn { auth: { type: \"file\", path: options.authTokenFile }, errors: [] };\n\t}\n\treturn { errors: [] };\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ClientCommandContext } from "./commands/client.ts";
|
|
2
|
+
import { type PiCommandContext } from "./commands/pi.ts";
|
|
3
|
+
import { type ServerCommandContext } from "./commands/server.ts";
|
|
4
|
+
export type ExperimentalCliContext = PiCommandContext & ServerCommandContext & ClientCommandContext;
|
|
5
|
+
export declare const experimentalCli: import("./command.ts").Command<import("./commands/pi.ts").PiCommand, PiCommandContext & ServerCommandContext & ClientCommandContext, import("./commands/client.ts").ClientCommand | import("./commands/pi.ts").PiCommand | import("./commands/server.ts").ServerCommand>;
|
|
6
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/experimental/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAiB,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,KAAK,gBAAgB,EAAa,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,KAAK,oBAAoB,EAAiB,MAAM,sBAAsB,CAAC;AAEhF,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,GAAG,oBAAoB,GAAG,oBAAoB,CAAC;AAEpG,eAAO,MAAM,eAAe,0QAA0D,CAAC","sourcesContent":["import { type ClientCommandContext, clientCommand } from \"./commands/client.ts\";\nimport { type PiCommandContext, piCommand } from \"./commands/pi.ts\";\nimport { type ServerCommandContext, serverCommand } from \"./commands/server.ts\";\n\nexport type ExperimentalCliContext = PiCommandContext & ServerCommandContext & ClientCommandContext;\n\nexport const experimentalCli = piCommand.command(serverCommand).command(clientCommand);\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { clientCommand } from "./commands/client.js";
|
|
2
|
+
import { piCommand } from "./commands/pi.js";
|
|
3
|
+
import { serverCommand } from "./commands/server.js";
|
|
4
|
+
export const experimentalCli = piCommand.command(serverCommand).command(clientCommand);
|
|
5
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli/experimental/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAyB,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAA6B,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIhF,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC","sourcesContent":["import { type ClientCommandContext, clientCommand } from \"./commands/client.ts\";\nimport { type PiCommandContext, piCommand } from \"./commands/pi.ts\";\nimport { type ServerCommandContext, serverCommand } from \"./commands/server.ts\";\n\nexport type ExperimentalCliContext = PiCommandContext & ServerCommandContext & ClientCommandContext;\n\nexport const experimentalCli = piCommand.command(serverCommand).command(clientCommand);\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Args } from "../args.ts";
|
|
2
|
+
import { type AuthInput } from "./auth.ts";
|
|
3
|
+
import { type CommandOption, type ParsedCommandInput } from "./command.ts";
|
|
4
|
+
import { type TransportAddress } from "./transport-address.ts";
|
|
5
|
+
export declare const authTokenOption: CommandOption<string>;
|
|
6
|
+
export declare const authTokenFileOption: CommandOption<string>;
|
|
7
|
+
export declare function transportOption(name: "--listen" | "--connect"): CommandOption<TransportAddress>;
|
|
8
|
+
export declare function parseAuth(input: ParsedCommandInput): {
|
|
9
|
+
auth?: AuthInput;
|
|
10
|
+
errors: string[];
|
|
11
|
+
};
|
|
12
|
+
export declare function parseLegacyOptions(input: ParsedCommandInput): {
|
|
13
|
+
options: Args;
|
|
14
|
+
errors: string[];
|
|
15
|
+
};
|
|
16
|
+
export declare function unsupportedLegacyOptions(command: string, input: ParsedCommandInput): string[];
|
|
17
|
+
//# sourceMappingURL=command-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-options.d.ts","sourceRoot":"","sources":["../../../src/cli/experimental/command-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAa,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,KAAK,SAAS,EAAkB,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAA6B,MAAM,cAAc,CAAC;AACtG,OAAO,EAAyB,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAEtF,eAAO,MAAM,eAAe,uBAA+B,CAAC;AAC5D,eAAO,MAAM,mBAAmB,uBAAoC,CAAC;AAErE,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAO/F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,kBAAkB,GAAG;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAK3F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAQjG;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAG7F","sourcesContent":["import { type Args, parseArgs } from \"../args.ts\";\nimport { type AuthInput, parseAuthInput } from \"./auth.ts\";\nimport { type CommandOption, type ParsedCommandInput, stringOption, valueOption } from \"./command.ts\";\nimport { parseTransportAddress, type TransportAddress } from \"./transport-address.ts\";\n\nexport const authTokenOption = stringOption(\"--auth-token\");\nexport const authTokenFileOption = stringOption(\"--auth-token-file\");\n\nexport function transportOption(name: \"--listen\" | \"--connect\"): CommandOption<TransportAddress> {\n\treturn valueOption(name, (value) => {\n\t\tconst result = parseTransportAddress(value, name);\n\t\treturn result.address\n\t\t\t? { ok: true, value: result.address }\n\t\t\t: { ok: false, error: result.error ?? `Invalid ${name} address \"${value}\"` };\n\t});\n}\n\nexport function parseAuth(input: ParsedCommandInput): { auth?: AuthInput; errors: string[] } {\n\treturn parseAuthInput({\n\t\tauthToken: input.value(authTokenOption),\n\t\tauthTokenFile: input.value(authTokenFileOption),\n\t});\n}\n\nexport function parseLegacyOptions(input: ParsedCommandInput): { options: Args; errors: string[] } {\n\tconst options = parseArgs([...input.remainingArgs]);\n\treturn {\n\t\toptions,\n\t\terrors: options.diagnostics\n\t\t\t.filter((diagnostic) => diagnostic.type === \"error\")\n\t\t\t.map((diagnostic) => diagnostic.message),\n\t};\n}\n\nexport function unsupportedLegacyOptions(command: string, input: ParsedCommandInput): string[] {\n\tif (input.remainingArgs.length === 0) return [];\n\treturn [`The experimental ${command} command does not support existing CLI options yet`];\n}\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { parseArgs } from "../args.js";
|
|
2
|
+
import { parseAuthInput } from "./auth.js";
|
|
3
|
+
import { stringOption, valueOption } from "./command.js";
|
|
4
|
+
import { parseTransportAddress } from "./transport-address.js";
|
|
5
|
+
export const authTokenOption = stringOption("--auth-token");
|
|
6
|
+
export const authTokenFileOption = stringOption("--auth-token-file");
|
|
7
|
+
export function transportOption(name) {
|
|
8
|
+
return valueOption(name, (value) => {
|
|
9
|
+
const result = parseTransportAddress(value, name);
|
|
10
|
+
return result.address
|
|
11
|
+
? { ok: true, value: result.address }
|
|
12
|
+
: { ok: false, error: result.error ?? `Invalid ${name} address "${value}"` };
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export function parseAuth(input) {
|
|
16
|
+
return parseAuthInput({
|
|
17
|
+
authToken: input.value(authTokenOption),
|
|
18
|
+
authTokenFile: input.value(authTokenFileOption),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export function parseLegacyOptions(input) {
|
|
22
|
+
const options = parseArgs([...input.remainingArgs]);
|
|
23
|
+
return {
|
|
24
|
+
options,
|
|
25
|
+
errors: options.diagnostics
|
|
26
|
+
.filter((diagnostic) => diagnostic.type === "error")
|
|
27
|
+
.map((diagnostic) => diagnostic.message),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function unsupportedLegacyOptions(command, input) {
|
|
31
|
+
if (input.remainingArgs.length === 0)
|
|
32
|
+
return [];
|
|
33
|
+
return [`The experimental ${command} command does not support existing CLI options yet`];
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=command-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-options.js","sourceRoot":"","sources":["../../../src/cli/experimental/command-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,SAAS,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAkB,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAA+C,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAyB,MAAM,wBAAwB,CAAC;AAEtF,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;AAErE,MAAM,UAAU,eAAe,CAAC,IAA8B,EAAmC;IAChG,OAAO,WAAW,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAClD,OAAO,MAAM,CAAC,OAAO;YACpB,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE;YACrC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,WAAW,IAAI,aAAa,KAAK,GAAG,EAAE,CAAC;IAAA,CAC9E,CAAC,CAAC;AAAA,CACH;AAED,MAAM,UAAU,SAAS,CAAC,KAAyB,EAA0C;IAC5F,OAAO,cAAc,CAAC;QACrB,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC;QACvC,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC;KAC/C,CAAC,CAAC;AAAA,CACH;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAyB,EAAuC;IAClG,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IACpD,OAAO;QACN,OAAO;QACP,MAAM,EAAE,OAAO,CAAC,WAAW;aACzB,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,KAAK,OAAO,CAAC;aACnD,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;KACzC,CAAC;AAAA,CACF;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAe,EAAE,KAAyB,EAAY;IAC9F,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChD,OAAO,CAAC,oBAAoB,OAAO,oDAAoD,CAAC,CAAC;AAAA,CACzF","sourcesContent":["import { type Args, parseArgs } from \"../args.ts\";\nimport { type AuthInput, parseAuthInput } from \"./auth.ts\";\nimport { type CommandOption, type ParsedCommandInput, stringOption, valueOption } from \"./command.ts\";\nimport { parseTransportAddress, type TransportAddress } from \"./transport-address.ts\";\n\nexport const authTokenOption = stringOption(\"--auth-token\");\nexport const authTokenFileOption = stringOption(\"--auth-token-file\");\n\nexport function transportOption(name: \"--listen\" | \"--connect\"): CommandOption<TransportAddress> {\n\treturn valueOption(name, (value) => {\n\t\tconst result = parseTransportAddress(value, name);\n\t\treturn result.address\n\t\t\t? { ok: true, value: result.address }\n\t\t\t: { ok: false, error: result.error ?? `Invalid ${name} address \"${value}\"` };\n\t});\n}\n\nexport function parseAuth(input: ParsedCommandInput): { auth?: AuthInput; errors: string[] } {\n\treturn parseAuthInput({\n\t\tauthToken: input.value(authTokenOption),\n\t\tauthTokenFile: input.value(authTokenFileOption),\n\t});\n}\n\nexport function parseLegacyOptions(input: ParsedCommandInput): { options: Args; errors: string[] } {\n\tconst options = parseArgs([...input.remainingArgs]);\n\treturn {\n\t\toptions,\n\t\terrors: options.diagnostics\n\t\t\t.filter((diagnostic) => diagnostic.type === \"error\")\n\t\t\t.map((diagnostic) => diagnostic.message),\n\t};\n}\n\nexport function unsupportedLegacyOptions(command: string, input: ParsedCommandInput): string[] {\n\tif (input.remainingArgs.length === 0) return [];\n\treturn [`The experimental ${command} command does not support existing CLI options yet`];\n}\n"]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export interface NamedCommandInvocation {
|
|
2
|
+
readonly command: string;
|
|
3
|
+
}
|
|
4
|
+
export type CommandParseResult<TInvocation extends NamedCommandInvocation = NamedCommandInvocation> = {
|
|
5
|
+
readonly ok: true;
|
|
6
|
+
readonly command: TInvocation;
|
|
7
|
+
} | {
|
|
8
|
+
readonly ok: false;
|
|
9
|
+
readonly errors: readonly string[];
|
|
10
|
+
};
|
|
11
|
+
export type CommandExecutionResult<TInvocation extends NamedCommandInvocation = NamedCommandInvocation> = {
|
|
12
|
+
readonly ok: true;
|
|
13
|
+
readonly command: TInvocation;
|
|
14
|
+
} | {
|
|
15
|
+
readonly ok: false;
|
|
16
|
+
readonly errors: readonly string[];
|
|
17
|
+
};
|
|
18
|
+
export type CommandOptionParseResult<TValue> = {
|
|
19
|
+
readonly ok: true;
|
|
20
|
+
readonly value: TValue;
|
|
21
|
+
} | {
|
|
22
|
+
readonly ok: false;
|
|
23
|
+
readonly error: string;
|
|
24
|
+
};
|
|
25
|
+
export interface CommandOption<TValue> {
|
|
26
|
+
readonly name: `--${string}`;
|
|
27
|
+
parse(value: string): CommandOptionParseResult<TValue>;
|
|
28
|
+
}
|
|
29
|
+
export declare function valueOption<TValue>(name: `--${string}`, parse: (value: string) => CommandOptionParseResult<TValue>): CommandOption<TValue>;
|
|
30
|
+
export declare function stringOption(name: `--${string}`): CommandOption<string>;
|
|
31
|
+
export interface ParsedCommandInput {
|
|
32
|
+
readonly remainingArgs: readonly string[];
|
|
33
|
+
value<TValue>(option: CommandOption<TValue>): TValue | undefined;
|
|
34
|
+
values<TValue>(option: CommandOption<TValue>): readonly TValue[];
|
|
35
|
+
}
|
|
36
|
+
export type CommandBuildResult<TInvocation extends NamedCommandInvocation> = {
|
|
37
|
+
readonly ok: true;
|
|
38
|
+
readonly command: TInvocation;
|
|
39
|
+
} | {
|
|
40
|
+
readonly ok: false;
|
|
41
|
+
readonly errors: readonly string[];
|
|
42
|
+
};
|
|
43
|
+
type CommandBuilder<TInvocation extends NamedCommandInvocation> = (input: ParsedCommandInput) => CommandBuildResult<TInvocation>;
|
|
44
|
+
type CommandAction<TInvocation extends NamedCommandInvocation, TContext> = (command: TInvocation, context: TContext) => void | Promise<void>;
|
|
45
|
+
export declare class Command<TOwnInvocation extends NamedCommandInvocation, TContext, TInvocation extends NamedCommandInvocation = TOwnInvocation> {
|
|
46
|
+
readonly name: string;
|
|
47
|
+
private readonly options;
|
|
48
|
+
private readonly subcommands;
|
|
49
|
+
private builder?;
|
|
50
|
+
private commandAction?;
|
|
51
|
+
constructor(name: string);
|
|
52
|
+
option<TValue>(option: CommandOption<TValue>): this;
|
|
53
|
+
build(builder: CommandBuilder<TOwnInvocation>): this;
|
|
54
|
+
action(action: CommandAction<TOwnInvocation, TContext>): this;
|
|
55
|
+
command<TSubcommandOwnInvocation extends NamedCommandInvocation, TSubcommandContext, TSubcommandInvocation extends NamedCommandInvocation>(command: Command<TSubcommandOwnInvocation, TSubcommandContext, TSubcommandInvocation>): Command<TOwnInvocation, TContext & TSubcommandContext, TInvocation | TSubcommandInvocation>;
|
|
56
|
+
parse(argv: readonly string[]): CommandParseResult<TInvocation>;
|
|
57
|
+
execute(argv: readonly string[], context: TContext): Promise<CommandExecutionResult<TInvocation>>;
|
|
58
|
+
private select;
|
|
59
|
+
private parseOwn;
|
|
60
|
+
private parseOptions;
|
|
61
|
+
}
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/cli/experimental/command.ts"],"names":[],"mappings":"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","sourcesContent":["export interface NamedCommandInvocation {\n\treadonly command: string;\n}\n\nexport type CommandParseResult<TInvocation extends NamedCommandInvocation = NamedCommandInvocation> =\n\t| { readonly ok: true; readonly command: TInvocation }\n\t| { readonly ok: false; readonly errors: readonly string[] };\n\nexport type CommandExecutionResult<TInvocation extends NamedCommandInvocation = NamedCommandInvocation> =\n\t| { readonly ok: true; readonly command: TInvocation }\n\t| { readonly ok: false; readonly errors: readonly string[] };\n\nexport type CommandOptionParseResult<TValue> =\n\t| { readonly ok: true; readonly value: TValue }\n\t| { readonly ok: false; readonly error: string };\n\nexport interface CommandOption<TValue> {\n\treadonly name: `--${string}`;\n\tparse(value: string): CommandOptionParseResult<TValue>;\n}\n\nexport function valueOption<TValue>(\n\tname: `--${string}`,\n\tparse: (value: string) => CommandOptionParseResult<TValue>,\n): CommandOption<TValue> {\n\treturn { name, parse };\n}\n\nexport function stringOption(name: `--${string}`): CommandOption<string> {\n\treturn valueOption(name, (value) => ({ ok: true, value }));\n}\n\nexport interface ParsedCommandInput {\n\treadonly remainingArgs: readonly string[];\n\tvalue<TValue>(option: CommandOption<TValue>): TValue | undefined;\n\tvalues<TValue>(option: CommandOption<TValue>): readonly TValue[];\n}\n\nexport type CommandBuildResult<TInvocation extends NamedCommandInvocation> =\n\t| { readonly ok: true; readonly command: TInvocation }\n\t| { readonly ok: false; readonly errors: readonly string[] };\n\ninterface MutableParsedCommandInput {\n\treadonly values: Map<string, unknown[]>;\n\treadonly remainingArgs: string[];\n\treadonly errors: string[];\n}\n\ntype CommandBuilder<TInvocation extends NamedCommandInvocation> = (\n\tinput: ParsedCommandInput,\n) => CommandBuildResult<TInvocation>;\n\ntype CommandAction<TInvocation extends NamedCommandInvocation, TContext> = (\n\tcommand: TInvocation,\n\tcontext: TContext,\n) => void | Promise<void>;\n\ninterface RegisteredCommand {\n\tparse(argv: readonly string[]): CommandParseResult;\n\texecute(argv: readonly string[], context: unknown): Promise<CommandExecutionResult>;\n}\n\nexport class Command<\n\tTOwnInvocation extends NamedCommandInvocation,\n\tTContext,\n\tTInvocation extends NamedCommandInvocation = TOwnInvocation,\n> {\n\treadonly name: string;\n\tprivate readonly options = new Map<string, CommandOption<unknown>>();\n\tprivate readonly subcommands = new Map<string, RegisteredCommand>();\n\tprivate builder?: CommandBuilder<TOwnInvocation>;\n\tprivate commandAction?: CommandAction<TOwnInvocation, TContext>;\n\n\tconstructor(name: string) {\n\t\tthis.name = name;\n\t}\n\n\toption<TValue>(option: CommandOption<TValue>): this {\n\t\tif (this.options.has(option.name)) {\n\t\t\tthrow new Error(`Option ${option.name} is already registered for ${this.name}`);\n\t\t}\n\t\tthis.options.set(option.name, option);\n\t\treturn this;\n\t}\n\n\tbuild(builder: CommandBuilder<TOwnInvocation>): this {\n\t\tthis.builder = builder;\n\t\treturn this;\n\t}\n\n\taction(action: CommandAction<TOwnInvocation, TContext>): this {\n\t\tthis.commandAction = action;\n\t\treturn this;\n\t}\n\n\tcommand<\n\t\tTSubcommandOwnInvocation extends NamedCommandInvocation,\n\t\tTSubcommandContext,\n\t\tTSubcommandInvocation extends NamedCommandInvocation,\n\t>(\n\t\tcommand: Command<TSubcommandOwnInvocation, TSubcommandContext, TSubcommandInvocation>,\n\t): Command<TOwnInvocation, TContext & TSubcommandContext, TInvocation | TSubcommandInvocation> {\n\t\tif (this.subcommands.has(command.name)) throw new Error(`Command ${command.name} is already registered`);\n\t\tthis.subcommands.set(command.name, {\n\t\t\tparse: (argv) => command.parse(argv),\n\t\t\texecute: (argv, context) => command.execute(argv, context as TSubcommandContext),\n\t\t});\n\t\treturn this as unknown as Command<\n\t\t\tTOwnInvocation,\n\t\t\tTContext & TSubcommandContext,\n\t\t\tTInvocation | TSubcommandInvocation\n\t\t>;\n\t}\n\n\tparse(argv: readonly string[]): CommandParseResult<TInvocation> {\n\t\tconst selected = this.select(argv);\n\t\tif (selected) return selected.command.parse(selected.argv) as CommandParseResult<TInvocation>;\n\t\treturn this.parseOwn(argv) as CommandParseResult<TInvocation>;\n\t}\n\n\tasync execute(argv: readonly string[], context: TContext): Promise<CommandExecutionResult<TInvocation>> {\n\t\tconst selected = this.select(argv);\n\t\tif (selected) {\n\t\t\treturn selected.command.execute(selected.argv, context) as Promise<CommandExecutionResult<TInvocation>>;\n\t\t}\n\n\t\tconst parsed = this.parseOwn(argv);\n\t\tif (!parsed.ok) return parsed;\n\t\tif (!this.commandAction) throw new Error(`Command ${this.name} does not define an action`);\n\t\tawait this.commandAction(parsed.command, context);\n\t\treturn { ok: true, command: parsed.command as unknown as TInvocation };\n\t}\n\n\tprivate select(argv: readonly string[]): { command: RegisteredCommand; argv: readonly string[] } | undefined {\n\t\tconst candidate = argv[0];\n\t\tif (candidate === undefined) return undefined;\n\t\tconst command = this.subcommands.get(candidate);\n\t\treturn command ? { command, argv: argv.slice(1) } : undefined;\n\t}\n\n\tprivate parseOwn(argv: readonly string[]): CommandParseResult<TOwnInvocation> {\n\t\tif (!this.builder) throw new Error(`Command ${this.name} does not define a builder`);\n\t\tconst parsed = this.parseOptions(argv);\n\t\tconst input: ParsedCommandInput = {\n\t\t\tremainingArgs: parsed.remainingArgs,\n\t\t\tvalue: <TValue>(option: CommandOption<TValue>) => parsed.values.get(option.name)?.[0] as TValue | undefined,\n\t\t\tvalues: <TValue>(option: CommandOption<TValue>) => (parsed.values.get(option.name) ?? []) as readonly TValue[],\n\t\t};\n\t\tconst built = this.builder(input);\n\t\tconst errors = [...parsed.errors, ...(built.ok ? [] : built.errors)];\n\t\tif (errors.length > 0) return { ok: false, errors };\n\t\tif (!built.ok) throw new Error(`Command ${this.name} failed without an error`);\n\t\treturn { ok: true, command: built.command };\n\t}\n\n\tprivate parseOptions(argv: readonly string[]): MutableParsedCommandInput {\n\t\tconst parsed: MutableParsedCommandInput = {\n\t\t\tvalues: new Map(),\n\t\t\tremainingArgs: [],\n\t\t\terrors: [],\n\t\t};\n\t\tfor (let index = 0; index < argv.length; index++) {\n\t\t\tconst argument = argv[index]!;\n\t\t\tif (argument === \"--\") {\n\t\t\t\tparsed.remainingArgs.push(...argv.slice(index));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst equals = argument.indexOf(\"=\");\n\t\t\tconst name = equals === -1 ? argument : argument.slice(0, equals);\n\t\t\tconst option = this.options.get(name);\n\t\t\tif (!option) {\n\t\t\t\tparsed.remainingArgs.push(...argv.slice(index));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tlet value = equals === -1 ? undefined : argument.slice(equals + 1);\n\t\t\tif (value === undefined) {\n\t\t\t\tconst next = argv[index + 1];\n\t\t\t\tif (next !== undefined && !next.startsWith(\"-\")) {\n\t\t\t\t\tvalue = next;\n\t\t\t\t\tindex++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (value === undefined || value === \"\") {\n\t\t\t\tparsed.errors.push(`${name} requires a value`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst values = parsed.values.get(name) ?? [];\n\t\t\tif (values.length > 0) {\n\t\t\t\tparsed.errors.push(`${name} may only be specified once`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst result = option.parse(value);\n\t\t\tif (!result.ok) {\n\t\t\t\tparsed.errors.push(result.error);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalues.push(result.value);\n\t\t\tparsed.values.set(name, values);\n\t\t}\n\t\treturn parsed;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
export function valueOption(name, parse) {
|
|
2
|
+
return { name, parse };
|
|
3
|
+
}
|
|
4
|
+
export function stringOption(name) {
|
|
5
|
+
return valueOption(name, (value) => ({ ok: true, value }));
|
|
6
|
+
}
|
|
7
|
+
export class Command {
|
|
8
|
+
name;
|
|
9
|
+
options = new Map();
|
|
10
|
+
subcommands = new Map();
|
|
11
|
+
builder;
|
|
12
|
+
commandAction;
|
|
13
|
+
constructor(name) {
|
|
14
|
+
this.name = name;
|
|
15
|
+
}
|
|
16
|
+
option(option) {
|
|
17
|
+
if (this.options.has(option.name)) {
|
|
18
|
+
throw new Error(`Option ${option.name} is already registered for ${this.name}`);
|
|
19
|
+
}
|
|
20
|
+
this.options.set(option.name, option);
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
build(builder) {
|
|
24
|
+
this.builder = builder;
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
action(action) {
|
|
28
|
+
this.commandAction = action;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
command(command) {
|
|
32
|
+
if (this.subcommands.has(command.name))
|
|
33
|
+
throw new Error(`Command ${command.name} is already registered`);
|
|
34
|
+
this.subcommands.set(command.name, {
|
|
35
|
+
parse: (argv) => command.parse(argv),
|
|
36
|
+
execute: (argv, context) => command.execute(argv, context),
|
|
37
|
+
});
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
parse(argv) {
|
|
41
|
+
const selected = this.select(argv);
|
|
42
|
+
if (selected)
|
|
43
|
+
return selected.command.parse(selected.argv);
|
|
44
|
+
return this.parseOwn(argv);
|
|
45
|
+
}
|
|
46
|
+
async execute(argv, context) {
|
|
47
|
+
const selected = this.select(argv);
|
|
48
|
+
if (selected) {
|
|
49
|
+
return selected.command.execute(selected.argv, context);
|
|
50
|
+
}
|
|
51
|
+
const parsed = this.parseOwn(argv);
|
|
52
|
+
if (!parsed.ok)
|
|
53
|
+
return parsed;
|
|
54
|
+
if (!this.commandAction)
|
|
55
|
+
throw new Error(`Command ${this.name} does not define an action`);
|
|
56
|
+
await this.commandAction(parsed.command, context);
|
|
57
|
+
return { ok: true, command: parsed.command };
|
|
58
|
+
}
|
|
59
|
+
select(argv) {
|
|
60
|
+
const candidate = argv[0];
|
|
61
|
+
if (candidate === undefined)
|
|
62
|
+
return undefined;
|
|
63
|
+
const command = this.subcommands.get(candidate);
|
|
64
|
+
return command ? { command, argv: argv.slice(1) } : undefined;
|
|
65
|
+
}
|
|
66
|
+
parseOwn(argv) {
|
|
67
|
+
if (!this.builder)
|
|
68
|
+
throw new Error(`Command ${this.name} does not define a builder`);
|
|
69
|
+
const parsed = this.parseOptions(argv);
|
|
70
|
+
const input = {
|
|
71
|
+
remainingArgs: parsed.remainingArgs,
|
|
72
|
+
value: (option) => parsed.values.get(option.name)?.[0],
|
|
73
|
+
values: (option) => (parsed.values.get(option.name) ?? []),
|
|
74
|
+
};
|
|
75
|
+
const built = this.builder(input);
|
|
76
|
+
const errors = [...parsed.errors, ...(built.ok ? [] : built.errors)];
|
|
77
|
+
if (errors.length > 0)
|
|
78
|
+
return { ok: false, errors };
|
|
79
|
+
if (!built.ok)
|
|
80
|
+
throw new Error(`Command ${this.name} failed without an error`);
|
|
81
|
+
return { ok: true, command: built.command };
|
|
82
|
+
}
|
|
83
|
+
parseOptions(argv) {
|
|
84
|
+
const parsed = {
|
|
85
|
+
values: new Map(),
|
|
86
|
+
remainingArgs: [],
|
|
87
|
+
errors: [],
|
|
88
|
+
};
|
|
89
|
+
for (let index = 0; index < argv.length; index++) {
|
|
90
|
+
const argument = argv[index];
|
|
91
|
+
if (argument === "--") {
|
|
92
|
+
parsed.remainingArgs.push(...argv.slice(index));
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
const equals = argument.indexOf("=");
|
|
96
|
+
const name = equals === -1 ? argument : argument.slice(0, equals);
|
|
97
|
+
const option = this.options.get(name);
|
|
98
|
+
if (!option) {
|
|
99
|
+
parsed.remainingArgs.push(...argv.slice(index));
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
let value = equals === -1 ? undefined : argument.slice(equals + 1);
|
|
103
|
+
if (value === undefined) {
|
|
104
|
+
const next = argv[index + 1];
|
|
105
|
+
if (next !== undefined && !next.startsWith("-")) {
|
|
106
|
+
value = next;
|
|
107
|
+
index++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (value === undefined || value === "") {
|
|
111
|
+
parsed.errors.push(`${name} requires a value`);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const values = parsed.values.get(name) ?? [];
|
|
115
|
+
if (values.length > 0) {
|
|
116
|
+
parsed.errors.push(`${name} may only be specified once`);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const result = option.parse(value);
|
|
120
|
+
if (!result.ok) {
|
|
121
|
+
parsed.errors.push(result.error);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
values.push(result.value);
|
|
125
|
+
parsed.values.set(name, values);
|
|
126
|
+
}
|
|
127
|
+
return parsed;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/cli/experimental/command.ts"],"names":[],"mappings":"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","sourcesContent":["export interface NamedCommandInvocation {\n\treadonly command: string;\n}\n\nexport type CommandParseResult<TInvocation extends NamedCommandInvocation = NamedCommandInvocation> =\n\t| { readonly ok: true; readonly command: TInvocation }\n\t| { readonly ok: false; readonly errors: readonly string[] };\n\nexport type CommandExecutionResult<TInvocation extends NamedCommandInvocation = NamedCommandInvocation> =\n\t| { readonly ok: true; readonly command: TInvocation }\n\t| { readonly ok: false; readonly errors: readonly string[] };\n\nexport type CommandOptionParseResult<TValue> =\n\t| { readonly ok: true; readonly value: TValue }\n\t| { readonly ok: false; readonly error: string };\n\nexport interface CommandOption<TValue> {\n\treadonly name: `--${string}`;\n\tparse(value: string): CommandOptionParseResult<TValue>;\n}\n\nexport function valueOption<TValue>(\n\tname: `--${string}`,\n\tparse: (value: string) => CommandOptionParseResult<TValue>,\n): CommandOption<TValue> {\n\treturn { name, parse };\n}\n\nexport function stringOption(name: `--${string}`): CommandOption<string> {\n\treturn valueOption(name, (value) => ({ ok: true, value }));\n}\n\nexport interface ParsedCommandInput {\n\treadonly remainingArgs: readonly string[];\n\tvalue<TValue>(option: CommandOption<TValue>): TValue | undefined;\n\tvalues<TValue>(option: CommandOption<TValue>): readonly TValue[];\n}\n\nexport type CommandBuildResult<TInvocation extends NamedCommandInvocation> =\n\t| { readonly ok: true; readonly command: TInvocation }\n\t| { readonly ok: false; readonly errors: readonly string[] };\n\ninterface MutableParsedCommandInput {\n\treadonly values: Map<string, unknown[]>;\n\treadonly remainingArgs: string[];\n\treadonly errors: string[];\n}\n\ntype CommandBuilder<TInvocation extends NamedCommandInvocation> = (\n\tinput: ParsedCommandInput,\n) => CommandBuildResult<TInvocation>;\n\ntype CommandAction<TInvocation extends NamedCommandInvocation, TContext> = (\n\tcommand: TInvocation,\n\tcontext: TContext,\n) => void | Promise<void>;\n\ninterface RegisteredCommand {\n\tparse(argv: readonly string[]): CommandParseResult;\n\texecute(argv: readonly string[], context: unknown): Promise<CommandExecutionResult>;\n}\n\nexport class Command<\n\tTOwnInvocation extends NamedCommandInvocation,\n\tTContext,\n\tTInvocation extends NamedCommandInvocation = TOwnInvocation,\n> {\n\treadonly name: string;\n\tprivate readonly options = new Map<string, CommandOption<unknown>>();\n\tprivate readonly subcommands = new Map<string, RegisteredCommand>();\n\tprivate builder?: CommandBuilder<TOwnInvocation>;\n\tprivate commandAction?: CommandAction<TOwnInvocation, TContext>;\n\n\tconstructor(name: string) {\n\t\tthis.name = name;\n\t}\n\n\toption<TValue>(option: CommandOption<TValue>): this {\n\t\tif (this.options.has(option.name)) {\n\t\t\tthrow new Error(`Option ${option.name} is already registered for ${this.name}`);\n\t\t}\n\t\tthis.options.set(option.name, option);\n\t\treturn this;\n\t}\n\n\tbuild(builder: CommandBuilder<TOwnInvocation>): this {\n\t\tthis.builder = builder;\n\t\treturn this;\n\t}\n\n\taction(action: CommandAction<TOwnInvocation, TContext>): this {\n\t\tthis.commandAction = action;\n\t\treturn this;\n\t}\n\n\tcommand<\n\t\tTSubcommandOwnInvocation extends NamedCommandInvocation,\n\t\tTSubcommandContext,\n\t\tTSubcommandInvocation extends NamedCommandInvocation,\n\t>(\n\t\tcommand: Command<TSubcommandOwnInvocation, TSubcommandContext, TSubcommandInvocation>,\n\t): Command<TOwnInvocation, TContext & TSubcommandContext, TInvocation | TSubcommandInvocation> {\n\t\tif (this.subcommands.has(command.name)) throw new Error(`Command ${command.name} is already registered`);\n\t\tthis.subcommands.set(command.name, {\n\t\t\tparse: (argv) => command.parse(argv),\n\t\t\texecute: (argv, context) => command.execute(argv, context as TSubcommandContext),\n\t\t});\n\t\treturn this as unknown as Command<\n\t\t\tTOwnInvocation,\n\t\t\tTContext & TSubcommandContext,\n\t\t\tTInvocation | TSubcommandInvocation\n\t\t>;\n\t}\n\n\tparse(argv: readonly string[]): CommandParseResult<TInvocation> {\n\t\tconst selected = this.select(argv);\n\t\tif (selected) return selected.command.parse(selected.argv) as CommandParseResult<TInvocation>;\n\t\treturn this.parseOwn(argv) as CommandParseResult<TInvocation>;\n\t}\n\n\tasync execute(argv: readonly string[], context: TContext): Promise<CommandExecutionResult<TInvocation>> {\n\t\tconst selected = this.select(argv);\n\t\tif (selected) {\n\t\t\treturn selected.command.execute(selected.argv, context) as Promise<CommandExecutionResult<TInvocation>>;\n\t\t}\n\n\t\tconst parsed = this.parseOwn(argv);\n\t\tif (!parsed.ok) return parsed;\n\t\tif (!this.commandAction) throw new Error(`Command ${this.name} does not define an action`);\n\t\tawait this.commandAction(parsed.command, context);\n\t\treturn { ok: true, command: parsed.command as unknown as TInvocation };\n\t}\n\n\tprivate select(argv: readonly string[]): { command: RegisteredCommand; argv: readonly string[] } | undefined {\n\t\tconst candidate = argv[0];\n\t\tif (candidate === undefined) return undefined;\n\t\tconst command = this.subcommands.get(candidate);\n\t\treturn command ? { command, argv: argv.slice(1) } : undefined;\n\t}\n\n\tprivate parseOwn(argv: readonly string[]): CommandParseResult<TOwnInvocation> {\n\t\tif (!this.builder) throw new Error(`Command ${this.name} does not define a builder`);\n\t\tconst parsed = this.parseOptions(argv);\n\t\tconst input: ParsedCommandInput = {\n\t\t\tremainingArgs: parsed.remainingArgs,\n\t\t\tvalue: <TValue>(option: CommandOption<TValue>) => parsed.values.get(option.name)?.[0] as TValue | undefined,\n\t\t\tvalues: <TValue>(option: CommandOption<TValue>) => (parsed.values.get(option.name) ?? []) as readonly TValue[],\n\t\t};\n\t\tconst built = this.builder(input);\n\t\tconst errors = [...parsed.errors, ...(built.ok ? [] : built.errors)];\n\t\tif (errors.length > 0) return { ok: false, errors };\n\t\tif (!built.ok) throw new Error(`Command ${this.name} failed without an error`);\n\t\treturn { ok: true, command: built.command };\n\t}\n\n\tprivate parseOptions(argv: readonly string[]): MutableParsedCommandInput {\n\t\tconst parsed: MutableParsedCommandInput = {\n\t\t\tvalues: new Map(),\n\t\t\tremainingArgs: [],\n\t\t\terrors: [],\n\t\t};\n\t\tfor (let index = 0; index < argv.length; index++) {\n\t\t\tconst argument = argv[index]!;\n\t\t\tif (argument === \"--\") {\n\t\t\t\tparsed.remainingArgs.push(...argv.slice(index));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst equals = argument.indexOf(\"=\");\n\t\t\tconst name = equals === -1 ? argument : argument.slice(0, equals);\n\t\t\tconst option = this.options.get(name);\n\t\t\tif (!option) {\n\t\t\t\tparsed.remainingArgs.push(...argv.slice(index));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tlet value = equals === -1 ? undefined : argument.slice(equals + 1);\n\t\t\tif (value === undefined) {\n\t\t\t\tconst next = argv[index + 1];\n\t\t\t\tif (next !== undefined && !next.startsWith(\"-\")) {\n\t\t\t\t\tvalue = next;\n\t\t\t\t\tindex++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (value === undefined || value === \"\") {\n\t\t\t\tparsed.errors.push(`${name} requires a value`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst values = parsed.values.get(name) ?? [];\n\t\t\tif (values.length > 0) {\n\t\t\t\tparsed.errors.push(`${name} may only be specified once`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst result = option.parse(value);\n\t\t\tif (!result.ok) {\n\t\t\t\tparsed.errors.push(result.error);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalues.push(result.value);\n\t\t\tparsed.values.set(name, values);\n\t\t}\n\t\treturn parsed;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AuthInput } from "../auth.ts";
|
|
2
|
+
import { Command } from "../command.ts";
|
|
3
|
+
import type { TransportAddress } from "../transport-address.ts";
|
|
4
|
+
export interface ClientCommand {
|
|
5
|
+
readonly command: "client";
|
|
6
|
+
readonly auth?: AuthInput;
|
|
7
|
+
readonly connect?: TransportAddress;
|
|
8
|
+
}
|
|
9
|
+
export interface ClientCommandContext {
|
|
10
|
+
runClient(command: ClientCommand): void | Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare const clientCommand: Command<ClientCommand, ClientCommandContext, ClientCommand>;
|
|
13
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/cli/experimental/commands/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AASxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACpC,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAID,eAAO,MAAM,aAAa,6DAmBgC,CAAC","sourcesContent":["import type { AuthInput } from \"../auth.ts\";\nimport { Command } from \"../command.ts\";\nimport {\n\tauthTokenFileOption,\n\tauthTokenOption,\n\tparseAuth,\n\tparseLegacyOptions,\n\ttransportOption,\n\tunsupportedLegacyOptions,\n} from \"../command-options.ts\";\nimport type { TransportAddress } from \"../transport-address.ts\";\n\nexport interface ClientCommand {\n\treadonly command: \"client\";\n\treadonly auth?: AuthInput;\n\treadonly connect?: TransportAddress;\n}\n\nexport interface ClientCommandContext {\n\trunClient(command: ClientCommand): void | Promise<void>;\n}\n\nconst connectOption = transportOption(\"--connect\");\n\nexport const clientCommand = new Command<ClientCommand, ClientCommandContext>(\"client\")\n\t.option(connectOption)\n\t.option(authTokenOption)\n\t.option(authTokenFileOption)\n\t.build((input) => {\n\t\tconst { auth, errors: authErrors } = parseAuth(input);\n\t\tconst connect = input.value(connectOption);\n\t\tconst { errors: optionErrors } = parseLegacyOptions(input);\n\t\tconst errors = [...authErrors, ...optionErrors, ...unsupportedLegacyOptions(\"client\", input)];\n\t\tif (errors.length > 0) return { ok: false, errors };\n\t\treturn {\n\t\t\tok: true,\n\t\t\tcommand: {\n\t\t\t\tcommand: \"client\",\n\t\t\t\t...(auth === undefined ? {} : { auth }),\n\t\t\t\t...(connect === undefined ? {} : { connect }),\n\t\t\t},\n\t\t};\n\t})\n\t.action((command, context) => context.runClient(command));\n"]}
|