workos 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -145
- package/dist/bin.js +129 -50
- package/dist/bin.js.map +1 -1
- package/dist/commands/api/index.js +18 -10
- package/dist/commands/api/index.js.map +1 -1
- package/dist/commands/api/interactive.js +11 -11
- package/dist/commands/api/interactive.js.map +1 -1
- package/dist/commands/claim.js +28 -16
- package/dist/commands/claim.js.map +1 -1
- package/dist/commands/connection.js +3 -3
- package/dist/commands/connection.js.map +1 -1
- package/dist/commands/debug.js +6 -6
- package/dist/commands/debug.js.map +1 -1
- package/dist/commands/dev.d.ts +7 -8
- package/dist/commands/dev.js +14 -14
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/directory.js +3 -3
- package/dist/commands/directory.js.map +1 -1
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/emulate.d.ts +1 -0
- package/dist/commands/emulate.js +3 -2
- package/dist/commands/emulate.js.map +1 -1
- package/dist/commands/env.d.ts +10 -0
- package/dist/commands/env.js +94 -18
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/install.js +8 -13
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.d.ts +25 -15
- package/dist/commands/login.js +126 -71
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +4 -4
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/mcp.js +7 -16
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/migrations.js +2 -1
- package/dist/commands/migrations.js.map +1 -1
- package/dist/commands/seed.js +5 -4
- package/dist/commands/seed.js.map +1 -1
- package/dist/commands/setup.d.ts +50 -0
- package/dist/commands/setup.js +237 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/vault-run.js +3 -2
- package/dist/commands/vault-run.js.map +1 -1
- package/dist/commands/verify-login.d.ts +25 -0
- package/dist/commands/verify-login.js +158 -0
- package/dist/commands/verify-login.js.map +1 -0
- package/dist/doctor/issues.js +3 -2
- package/dist/doctor/issues.js.map +1 -1
- package/dist/doctor/output.js +2 -1
- package/dist/doctor/output.js.map +1 -1
- package/dist/integrations/dotnet/index.js +1 -1
- package/dist/integrations/dotnet/index.js.map +1 -1
- package/dist/integrations/elixir/index.js +1 -1
- package/dist/integrations/elixir/index.js.map +1 -1
- package/dist/integrations/go/index.js +1 -1
- package/dist/integrations/go/index.js.map +1 -1
- package/dist/integrations/nextjs/index.js +8 -5
- package/dist/integrations/nextjs/index.js.map +1 -1
- package/dist/integrations/nextjs/utils.d.ts +1 -1
- package/dist/integrations/nextjs/utils.js +21 -6
- package/dist/integrations/nextjs/utils.js.map +1 -1
- package/dist/integrations/react-router/index.js +5 -5
- package/dist/integrations/react-router/index.js.map +1 -1
- package/dist/integrations/react-router/utils.js +28 -12
- package/dist/integrations/react-router/utils.js.map +1 -1
- package/dist/integrations/ruby/index.js +1 -1
- package/dist/integrations/ruby/index.js.map +1 -1
- package/dist/lib/adapters/cli-adapter.d.ts +33 -4
- package/dist/lib/adapters/cli-adapter.js +251 -135
- package/dist/lib/adapters/cli-adapter.js.map +1 -1
- package/dist/lib/adapters/dashboard-adapter.js +3 -3
- package/dist/lib/adapters/dashboard-adapter.js.map +1 -1
- package/dist/lib/adapters/headless-adapter.d.ts +7 -0
- package/dist/lib/adapters/headless-adapter.js +42 -5
- package/dist/lib/adapters/headless-adapter.js.map +1 -1
- package/dist/lib/agent-interface.js +15 -1
- package/dist/lib/agent-interface.js.map +1 -1
- package/dist/lib/agent-runner.js +1 -1
- package/dist/lib/agent-runner.js.map +1 -1
- package/dist/lib/api-key.js +2 -1
- package/dist/lib/api-key.js.map +1 -1
- package/dist/lib/completion-data.d.ts +33 -0
- package/dist/lib/completion-data.js +33 -0
- package/dist/lib/completion-data.js.map +1 -0
- package/dist/lib/config-store.d.ts +13 -0
- package/dist/lib/config-store.js +24 -0
- package/dist/lib/config-store.js.map +1 -1
- package/dist/lib/config.d.ts +1 -1
- package/dist/lib/config.js +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/constants.d.ts +8 -0
- package/dist/lib/constants.js +8 -0
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/events.d.ts +34 -1
- package/dist/lib/events.js.map +1 -1
- package/dist/lib/framework-config.d.ts +6 -0
- package/dist/lib/framework-config.js.map +1 -1
- package/dist/lib/installer-core.d.ts +14 -1
- package/dist/lib/installer-core.js +24 -5
- package/dist/lib/installer-core.js.map +1 -1
- package/dist/lib/installer-core.types.d.ts +3 -1
- package/dist/lib/installer-core.types.js.map +1 -1
- package/dist/lib/mcp-clients.d.ts +6 -0
- package/dist/lib/mcp-clients.js +13 -0
- package/dist/lib/mcp-clients.js.map +1 -1
- package/dist/lib/port-detection.js +19 -13
- package/dist/lib/port-detection.js.map +1 -1
- package/dist/lib/preferences.d.ts +30 -2
- package/dist/lib/preferences.js +34 -8
- package/dist/lib/preferences.js.map +1 -1
- package/dist/lib/run-with-core.js +40 -3
- package/dist/lib/run-with-core.js.map +1 -1
- package/dist/lib/telemetry-notice.d.ts +5 -5
- package/dist/lib/telemetry-notice.js +7 -8
- package/dist/lib/telemetry-notice.js.map +1 -1
- package/dist/lib/unclaimed-env-provision.js +15 -12
- package/dist/lib/unclaimed-env-provision.js.map +1 -1
- package/dist/lib/unclaimed-warning.js +4 -3
- package/dist/lib/unclaimed-warning.js.map +1 -1
- package/dist/lib/validation/security-checks.js +2 -1
- package/dist/lib/validation/security-checks.js.map +1 -1
- package/dist/lib/validation/validator.js +30 -3
- package/dist/lib/validation/validator.js.map +1 -1
- package/dist/lib/workos-management.js +26 -19
- package/dist/lib/workos-management.js.map +1 -1
- package/dist/run.d.ts +1 -0
- package/dist/run.js +5 -1
- package/dist/run.js.map +1 -1
- package/dist/steps/add-or-update-environment-variables.js +10 -10
- package/dist/steps/add-or-update-environment-variables.js.map +1 -1
- package/dist/steps/run-prettier.js +3 -3
- package/dist/steps/run-prettier.js.map +1 -1
- package/dist/steps/upload-environment-variables/index.js +15 -3
- package/dist/steps/upload-environment-variables/index.js.map +1 -1
- package/dist/steps/upload-environment-variables/providers/vercel.js +2 -2
- package/dist/steps/upload-environment-variables/providers/vercel.js.map +1 -1
- package/dist/utils/box.d.ts +6 -30
- package/dist/utils/box.js +8 -95
- package/dist/utils/box.js.map +1 -1
- package/dist/utils/cli-symbols.d.ts +14 -2
- package/dist/utils/cli-symbols.js +12 -0
- package/dist/utils/cli-symbols.js.map +1 -1
- package/dist/utils/debug.js +3 -3
- package/dist/utils/debug.js.map +1 -1
- package/dist/utils/environment.js +1 -1
- package/dist/utils/environment.js.map +1 -1
- package/dist/utils/help-json.js +115 -4
- package/dist/utils/help-json.js.map +1 -1
- package/dist/utils/package-manager.js +1 -1
- package/dist/utils/package-manager.js.map +1 -1
- package/dist/utils/recovery-hints.d.ts +5 -0
- package/dist/utils/recovery-hints.js +12 -0
- package/dist/utils/recovery-hints.js.map +1 -1
- package/dist/utils/summary-box.d.ts +8 -1
- package/dist/utils/summary-box.js +67 -4
- package/dist/utils/summary-box.js.map +1 -1
- package/dist/utils/types.d.ts +10 -0
- package/dist/utils/types.js.map +1 -1
- package/dist/utils/{clack-utils.d.ts → ui-utils.d.ts} +1 -1
- package/dist/utils/{clack-utils.js → ui-utils.js} +64 -37
- package/dist/utils/ui-utils.js.map +1 -0
- package/dist/utils/ui.d.ts +148 -0
- package/dist/utils/ui.js +368 -0
- package/dist/utils/ui.js.map +1 -0
- package/package.json +5 -13
- package/dist/check-coverage.ts +0 -237
- package/dist/emulate/core/id.d.ts +0 -48
- package/dist/emulate/core/id.js +0 -73
- package/dist/emulate/core/id.js.map +0 -1
- package/dist/emulate/core/index.d.ts +0 -8
- package/dist/emulate/core/index.js +0 -8
- package/dist/emulate/core/index.js.map +0 -1
- package/dist/emulate/core/jwt.d.ts +0 -28
- package/dist/emulate/core/jwt.js +0 -78
- package/dist/emulate/core/jwt.js.map +0 -1
- package/dist/emulate/core/middleware/auth.d.ts +0 -15
- package/dist/emulate/core/middleware/auth.js +0 -17
- package/dist/emulate/core/middleware/auth.js.map +0 -1
- package/dist/emulate/core/middleware/error-handler.d.ts +0 -22
- package/dist/emulate/core/middleware/error-handler.js +0 -72
- package/dist/emulate/core/middleware/error-handler.js.map +0 -1
- package/dist/emulate/core/pagination.d.ts +0 -27
- package/dist/emulate/core/pagination.js +0 -43
- package/dist/emulate/core/pagination.js.map +0 -1
- package/dist/emulate/core/plugin.d.ts +0 -15
- package/dist/emulate/core/plugin.js +0 -2
- package/dist/emulate/core/plugin.js.map +0 -1
- package/dist/emulate/core/server.d.ts +0 -17
- package/dist/emulate/core/server.js +0 -90
- package/dist/emulate/core/server.js.map +0 -1
- package/dist/emulate/core/store.d.ts +0 -44
- package/dist/emulate/core/store.js +0 -169
- package/dist/emulate/core/store.js.map +0 -1
- package/dist/emulate/index.d.ts +0 -25
- package/dist/emulate/index.js +0 -47
- package/dist/emulate/index.js.map +0 -1
- package/dist/emulate/workos/constants.d.ts +0 -56
- package/dist/emulate/workos/constants.js +0 -56
- package/dist/emulate/workos/constants.js.map +0 -1
- package/dist/emulate/workos/entities.d.ts +0 -360
- package/dist/emulate/workos/entities.js +0 -2
- package/dist/emulate/workos/entities.js.map +0 -1
- package/dist/emulate/workos/event-bus.d.ts +0 -17
- package/dist/emulate/workos/event-bus.js +0 -70
- package/dist/emulate/workos/event-bus.js.map +0 -1
- package/dist/emulate/workos/helpers.d.ts +0 -72
- package/dist/emulate/workos/helpers.js +0 -211
- package/dist/emulate/workos/helpers.js.map +0 -1
- package/dist/emulate/workos/index.d.ts +0 -93
- package/dist/emulate/workos/index.js +0 -326
- package/dist/emulate/workos/index.js.map +0 -1
- package/dist/emulate/workos/role-helpers.d.ts +0 -21
- package/dist/emulate/workos/role-helpers.js +0 -130
- package/dist/emulate/workos/role-helpers.js.map +0 -1
- package/dist/emulate/workos/routes/api-keys.d.ts +0 -2
- package/dist/emulate/workos/routes/api-keys.js +0 -32
- package/dist/emulate/workos/routes/api-keys.js.map +0 -1
- package/dist/emulate/workos/routes/audit-logs.d.ts +0 -2
- package/dist/emulate/workos/routes/audit-logs.js +0 -104
- package/dist/emulate/workos/routes/audit-logs.js.map +0 -1
- package/dist/emulate/workos/routes/auth-challenges.d.ts +0 -2
- package/dist/emulate/workos/routes/auth-challenges.js +0 -51
- package/dist/emulate/workos/routes/auth-challenges.js.map +0 -1
- package/dist/emulate/workos/routes/auth-factors.d.ts +0 -2
- package/dist/emulate/workos/routes/auth-factors.js +0 -51
- package/dist/emulate/workos/routes/auth-factors.js.map +0 -1
- package/dist/emulate/workos/routes/auth.d.ts +0 -2
- package/dist/emulate/workos/routes/auth.js +0 -350
- package/dist/emulate/workos/routes/auth.js.map +0 -1
- package/dist/emulate/workos/routes/authorization-checks.d.ts +0 -10
- package/dist/emulate/workos/routes/authorization-checks.js +0 -123
- package/dist/emulate/workos/routes/authorization-checks.js.map +0 -1
- package/dist/emulate/workos/routes/authorization-org-roles.d.ts +0 -2
- package/dist/emulate/workos/routes/authorization-org-roles.js +0 -64
- package/dist/emulate/workos/routes/authorization-org-roles.js.map +0 -1
- package/dist/emulate/workos/routes/authorization-permissions.d.ts +0 -2
- package/dist/emulate/workos/routes/authorization-permissions.js +0 -67
- package/dist/emulate/workos/routes/authorization-permissions.js.map +0 -1
- package/dist/emulate/workos/routes/authorization-resources.d.ts +0 -2
- package/dist/emulate/workos/routes/authorization-resources.js +0 -117
- package/dist/emulate/workos/routes/authorization-resources.js.map +0 -1
- package/dist/emulate/workos/routes/authorization-roles.d.ts +0 -2
- package/dist/emulate/workos/routes/authorization-roles.js +0 -13
- package/dist/emulate/workos/routes/authorization-roles.js.map +0 -1
- package/dist/emulate/workos/routes/config.d.ts +0 -2
- package/dist/emulate/workos/routes/config.js +0 -57
- package/dist/emulate/workos/routes/config.js.map +0 -1
- package/dist/emulate/workos/routes/connect.d.ts +0 -2
- package/dist/emulate/workos/routes/connect.js +0 -65
- package/dist/emulate/workos/routes/connect.js.map +0 -1
- package/dist/emulate/workos/routes/connections.d.ts +0 -2
- package/dist/emulate/workos/routes/connections.js +0 -73
- package/dist/emulate/workos/routes/connections.js.map +0 -1
- package/dist/emulate/workos/routes/data-integrations.d.ts +0 -2
- package/dist/emulate/workos/routes/data-integrations.js +0 -55
- package/dist/emulate/workos/routes/data-integrations.js.map +0 -1
- package/dist/emulate/workos/routes/directories.d.ts +0 -2
- package/dist/emulate/workos/routes/directories.js +0 -90
- package/dist/emulate/workos/routes/directories.js.map +0 -1
- package/dist/emulate/workos/routes/email-verification.d.ts +0 -2
- package/dist/emulate/workos/routes/email-verification.js +0 -49
- package/dist/emulate/workos/routes/email-verification.js.map +0 -1
- package/dist/emulate/workos/routes/events.d.ts +0 -2
- package/dist/emulate/workos/routes/events.js +0 -18
- package/dist/emulate/workos/routes/events.js.map +0 -1
- package/dist/emulate/workos/routes/feature-flags.d.ts +0 -2
- package/dist/emulate/workos/routes/feature-flags.js +0 -103
- package/dist/emulate/workos/routes/feature-flags.js.map +0 -1
- package/dist/emulate/workos/routes/invitations.d.ts +0 -2
- package/dist/emulate/workos/routes/invitations.js +0 -122
- package/dist/emulate/workos/routes/invitations.js.map +0 -1
- package/dist/emulate/workos/routes/legacy-mfa.d.ts +0 -2
- package/dist/emulate/workos/routes/legacy-mfa.js +0 -75
- package/dist/emulate/workos/routes/legacy-mfa.js.map +0 -1
- package/dist/emulate/workos/routes/magic-auth.d.ts +0 -2
- package/dist/emulate/workos/routes/magic-auth.js +0 -32
- package/dist/emulate/workos/routes/magic-auth.js.map +0 -1
- package/dist/emulate/workos/routes/memberships.d.ts +0 -2
- package/dist/emulate/workos/routes/memberships.js +0 -114
- package/dist/emulate/workos/routes/memberships.js.map +0 -1
- package/dist/emulate/workos/routes/organization-domains.d.ts +0 -2
- package/dist/emulate/workos/routes/organization-domains.js +0 -58
- package/dist/emulate/workos/routes/organization-domains.js.map +0 -1
- package/dist/emulate/workos/routes/organizations.d.ts +0 -2
- package/dist/emulate/workos/routes/organizations.js +0 -131
- package/dist/emulate/workos/routes/organizations.js.map +0 -1
- package/dist/emulate/workos/routes/password-reset.d.ts +0 -2
- package/dist/emulate/workos/routes/password-reset.js +0 -61
- package/dist/emulate/workos/routes/password-reset.js.map +0 -1
- package/dist/emulate/workos/routes/pipes.d.ts +0 -2
- package/dist/emulate/workos/routes/pipes.js +0 -82
- package/dist/emulate/workos/routes/pipes.js.map +0 -1
- package/dist/emulate/workos/routes/portal.d.ts +0 -2
- package/dist/emulate/workos/routes/portal.js +0 -18
- package/dist/emulate/workos/routes/portal.js.map +0 -1
- package/dist/emulate/workos/routes/radar.d.ts +0 -2
- package/dist/emulate/workos/routes/radar.js +0 -41
- package/dist/emulate/workos/routes/radar.js.map +0 -1
- package/dist/emulate/workos/routes/sessions.d.ts +0 -2
- package/dist/emulate/workos/routes/sessions.js +0 -51
- package/dist/emulate/workos/routes/sessions.js.map +0 -1
- package/dist/emulate/workos/routes/sso.d.ts +0 -2
- package/dist/emulate/workos/routes/sso.js +0 -161
- package/dist/emulate/workos/routes/sso.js.map +0 -1
- package/dist/emulate/workos/routes/user-features.d.ts +0 -2
- package/dist/emulate/workos/routes/user-features.js +0 -50
- package/dist/emulate/workos/routes/user-features.js.map +0 -1
- package/dist/emulate/workos/routes/users.d.ts +0 -2
- package/dist/emulate/workos/routes/users.js +0 -129
- package/dist/emulate/workos/routes/users.js.map +0 -1
- package/dist/emulate/workos/routes/webhook-endpoints.d.ts +0 -2
- package/dist/emulate/workos/routes/webhook-endpoints.js +0 -67
- package/dist/emulate/workos/routes/webhook-endpoints.js.map +0 -1
- package/dist/emulate/workos/routes/widgets.d.ts +0 -2
- package/dist/emulate/workos/routes/widgets.js +0 -27
- package/dist/emulate/workos/routes/widgets.js.map +0 -1
- package/dist/emulate/workos/store.d.ts +0 -48
- package/dist/emulate/workos/store.js +0 -102
- package/dist/emulate/workos/store.js.map +0 -1
- package/dist/emulate/workos/webhook-signer.d.ts +0 -1
- package/dist/emulate/workos/webhook-signer.js +0 -8
- package/dist/emulate/workos/webhook-signer.js.map +0 -1
- package/dist/gen-routes-lib.spec.ts +0 -659
- package/dist/gen-routes-lib.ts +0 -647
- package/dist/gen-routes.ts +0 -96
- package/dist/lib/mcp-notice.d.ts +0 -72
- package/dist/lib/mcp-notice.js +0 -275
- package/dist/lib/mcp-notice.js.map +0 -1
- package/dist/utils/clack-utils.js.map +0 -1
- package/dist/utils/clack.d.ts +0 -5
- package/dist/utils/clack.js +0 -34
- package/dist/utils/clack.js.map +0 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
import ui, { PromptUnavailableError } from '../../utils/ui.js';
|
|
2
3
|
import chalk from 'chalk';
|
|
3
4
|
import { getConfig } from '../settings.js';
|
|
4
5
|
import { ProgressTracker } from '../progress-tracker.js';
|
|
5
|
-
import { renderCompletionSummary } from '../../utils/summary-box.js';
|
|
6
|
+
import { renderCompletionSummary, renderBrandMark } from '../../utils/summary-box.js';
|
|
6
7
|
import { formatWorkOSCommand } from '../../utils/command-invocation.js';
|
|
7
8
|
/**
|
|
8
|
-
* CLI adapter that renders wizard events via
|
|
9
|
+
* CLI adapter that renders wizard events via ui.
|
|
9
10
|
*
|
|
10
11
|
* Subscribes to InstallerEventEmitter and translates events into
|
|
11
|
-
*
|
|
12
|
+
* UI facade operations (logs, spinners, prompts).
|
|
12
13
|
*/
|
|
13
14
|
export class CLIAdapter {
|
|
14
15
|
emitter;
|
|
@@ -27,8 +28,15 @@ export class CLIAdapter {
|
|
|
27
28
|
pendingLogs = [];
|
|
28
29
|
// SIGINT handler for cleanup
|
|
29
30
|
sigIntHandler = null;
|
|
30
|
-
//
|
|
31
|
-
|
|
31
|
+
// Aborts in-flight/queued prompts when the run ends (cancellation, ctrl-c).
|
|
32
|
+
// The installer's `preparing` state can queue a second prompt behind a live
|
|
33
|
+
// one (git-dirty + protected-branch); if the first is cancelled, this signal
|
|
34
|
+
// stops the queued sibling from opening a now-moot question.
|
|
35
|
+
promptAbort = null;
|
|
36
|
+
// Last phase message shown on the agent spinner, restored after logging above it.
|
|
37
|
+
lastAgentMessage = 'Running AI agent...';
|
|
38
|
+
// Last file path rendered as a step line, to dedupe consecutive same-path ops.
|
|
39
|
+
lastFileOp = null;
|
|
32
40
|
constructor(config) {
|
|
33
41
|
this.emitter = config.emitter;
|
|
34
42
|
this.sendEvent = config.sendEvent;
|
|
@@ -52,29 +60,47 @@ export class CLIAdapter {
|
|
|
52
60
|
const logs = this.pendingLogs.splice(0);
|
|
53
61
|
logs.forEach((fn) => fn());
|
|
54
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Run a prompt with the log queue engaged: mark a prompt active so async log
|
|
65
|
+
* events (detection:complete, branch:created, …) buffer instead of scribbling
|
|
66
|
+
* over the question, then release and flush once it resolves. Wraps every
|
|
67
|
+
* prompt handler so the active/flush lifecycle lives in one place.
|
|
68
|
+
*/
|
|
69
|
+
async withPromptActive(run) {
|
|
70
|
+
this.isPromptActive = true;
|
|
71
|
+
try {
|
|
72
|
+
return await run();
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
this.isPromptActive = false;
|
|
76
|
+
this.flushPendingLogs();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
55
79
|
async start() {
|
|
56
80
|
if (this.isStarted)
|
|
57
81
|
return;
|
|
58
82
|
this.isStarted = true;
|
|
83
|
+
this.promptAbort = new AbortController();
|
|
59
84
|
// Show intro
|
|
60
85
|
const config = getConfig();
|
|
61
86
|
if (config.branding.showAsciiArt) {
|
|
62
|
-
|
|
63
|
-
console.log(
|
|
64
|
-
console.log();
|
|
87
|
+
// Compact brand mark (the lock + wordmark) instead of the full block banner.
|
|
88
|
+
console.log('');
|
|
89
|
+
console.log(renderBrandMark('AuthKit installer'));
|
|
90
|
+
console.log('');
|
|
65
91
|
}
|
|
66
92
|
else {
|
|
67
|
-
|
|
93
|
+
ui.intro('WorkOS', 'AuthKit installer');
|
|
68
94
|
}
|
|
69
95
|
// Handle Ctrl+C gracefully
|
|
70
96
|
const handleSigInt = () => {
|
|
97
|
+
this.promptAbort?.abort();
|
|
71
98
|
if (this.spinner) {
|
|
72
99
|
this.spinner.stop('Cancelled');
|
|
73
100
|
this.spinner = null;
|
|
74
101
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
clack.outro('Your project was not modified');
|
|
102
|
+
ui.log.warn('Installer cancelled');
|
|
103
|
+
ui.outro('Your project was not modified');
|
|
78
104
|
process.exit(0);
|
|
79
105
|
};
|
|
80
106
|
process.on('SIGINT', handleSigInt);
|
|
@@ -93,12 +119,19 @@ export class CLIAdapter {
|
|
|
93
119
|
this.subscribe('credentials:env:prompt', this.handleEnvScanPrompt);
|
|
94
120
|
this.subscribe('device:started', this.handleDeviceStarted);
|
|
95
121
|
this.subscribe('device:success', this.handleDeviceSuccess);
|
|
122
|
+
this.subscribe('device:error', this.handleDeviceError);
|
|
123
|
+
this.subscribe('device:timeout', this.handleDeviceTimeout);
|
|
96
124
|
this.subscribe('staging:fetching', this.handleStagingFetching);
|
|
97
125
|
this.subscribe('staging:success', this.handleStagingSuccess);
|
|
126
|
+
this.subscribe('staging:error', this.handleStagingError);
|
|
98
127
|
this.subscribe('credentials:env:found', this.handleEnvCredentialsFound);
|
|
99
128
|
this.subscribe('config:complete', this.handleConfigComplete);
|
|
100
129
|
this.subscribe('agent:start', this.handleAgentStart);
|
|
101
130
|
this.subscribe('agent:progress', this.handleAgentProgress);
|
|
131
|
+
// Persistent, append-only log of file operations + tool calls above the spinner.
|
|
132
|
+
this.subscribe('file:write', this.handleFileWrite);
|
|
133
|
+
this.subscribe('file:edit', this.handleFileEdit);
|
|
134
|
+
this.subscribe('agent:tool', this.handleAgentTool);
|
|
102
135
|
this.subscribe('validation:start', this.handleValidationStart);
|
|
103
136
|
this.subscribe('validation:issues', this.handleValidationIssues);
|
|
104
137
|
this.subscribe('validation:complete', this.handleValidationComplete);
|
|
@@ -130,13 +163,15 @@ export class CLIAdapter {
|
|
|
130
163
|
async stop() {
|
|
131
164
|
if (!this.isStarted)
|
|
132
165
|
return;
|
|
166
|
+
// Abort any in-flight/queued prompt so a cancelled run can't leave a
|
|
167
|
+
// now-moot sibling question open (e.g. the branch prompt after git-cancel).
|
|
168
|
+
this.promptAbort?.abort();
|
|
169
|
+
this.promptAbort = null;
|
|
133
170
|
// Remove SIGINT handler
|
|
134
171
|
if (this.sigIntHandler) {
|
|
135
172
|
process.off('SIGINT', this.sigIntHandler);
|
|
136
173
|
this.sigIntHandler = null;
|
|
137
174
|
}
|
|
138
|
-
// Stop agent updates
|
|
139
|
-
this.stopAgentUpdates();
|
|
140
175
|
// Unsubscribe from all events
|
|
141
176
|
for (const [event, handler] of this.handlers) {
|
|
142
177
|
this.emitter.off(event, handler);
|
|
@@ -147,15 +182,9 @@ export class CLIAdapter {
|
|
|
147
182
|
this.spinner = null;
|
|
148
183
|
this.isStarted = false;
|
|
149
184
|
}
|
|
150
|
-
|
|
151
|
-
if (this.agentUpdateInterval) {
|
|
152
|
-
clearInterval(this.agentUpdateInterval);
|
|
153
|
-
this.agentUpdateInterval = null;
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
stopSpinner(message) {
|
|
185
|
+
stopSpinner(message, code = 0) {
|
|
157
186
|
if (this.spinner) {
|
|
158
|
-
this.spinner.stop(message);
|
|
187
|
+
this.spinner.stop(message, code);
|
|
159
188
|
this.spinner = null;
|
|
160
189
|
}
|
|
161
190
|
}
|
|
@@ -170,9 +199,43 @@ export class CLIAdapter {
|
|
|
170
199
|
*/
|
|
171
200
|
subscribe(event, handler) {
|
|
172
201
|
const boundHandler = handler.bind(this);
|
|
173
|
-
|
|
174
|
-
|
|
202
|
+
// Handlers are invoked fire-and-forget by a plain EventEmitter, so an async
|
|
203
|
+
// rejection would become an unhandledRejection (silent crash). Route a
|
|
204
|
+
// PromptUnavailableError (prompt attempted where the user can't answer) to a
|
|
205
|
+
// clean fail-fast; re-surface anything else unchanged so real bugs still crash.
|
|
206
|
+
const safeHandler = (payload) => {
|
|
207
|
+
try {
|
|
208
|
+
const result = boundHandler(payload);
|
|
209
|
+
if (result instanceof Promise)
|
|
210
|
+
result.catch((err) => this.onHandlerError(err));
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
this.onHandlerError(err);
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
this.handlers.set(event, safeHandler);
|
|
217
|
+
this.emitter.on(event, safeHandler);
|
|
175
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Terminal handler failure. A PromptUnavailableError means we reached a prompt
|
|
221
|
+
* in a context that can't answer it (non-TTY stdin) — the CLIAdapter only runs
|
|
222
|
+
* in human, non-JSON output, so this is always a real human at a broken input,
|
|
223
|
+
* never a JSON stream. Surface a clear message and exit before anything is
|
|
224
|
+
* written, rather than hanging or crashing. Re-throw anything else.
|
|
225
|
+
*/
|
|
226
|
+
onHandlerError = (error) => {
|
|
227
|
+
if (error instanceof PromptUnavailableError) {
|
|
228
|
+
this.spinner?.clear();
|
|
229
|
+
this.spinner = null;
|
|
230
|
+
ui.log.error(error.message);
|
|
231
|
+
ui.log.hint('Re-run in an interactive terminal, or pass the flags that answer these prompts.');
|
|
232
|
+
// Exit 1 (general error), matching the direct-command classification of
|
|
233
|
+
// this same error in bin.ts. NOT 4 — that's "auth required" (gh
|
|
234
|
+
// convention), which would send scripts into an auth-retry loop.
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
throw error;
|
|
238
|
+
};
|
|
176
239
|
// ===== Event Handlers =====
|
|
177
240
|
handleStateEnter = ({ state }) => {
|
|
178
241
|
this.progress.enterPhase(state);
|
|
@@ -181,39 +244,36 @@ export class CLIAdapter {
|
|
|
181
244
|
this.progress.exitPhase(state);
|
|
182
245
|
};
|
|
183
246
|
handleAuthSuccess = () => {
|
|
184
|
-
|
|
247
|
+
ui.log.success('Authenticated');
|
|
185
248
|
};
|
|
186
249
|
handleAuthFailure = ({ message }) => {
|
|
187
|
-
|
|
188
|
-
|
|
250
|
+
ui.log.error(`Auth failed: ${message}`);
|
|
251
|
+
ui.log.info('Visit https://dashboard.workos.com to verify your account');
|
|
189
252
|
};
|
|
190
253
|
handleDetectionComplete = ({ integration }) => {
|
|
191
|
-
this.queueableLog(() =>
|
|
254
|
+
this.queueableLog(() => ui.log.success(`Detected ${chalk.bold(integration)}`));
|
|
192
255
|
};
|
|
193
256
|
handleDetectionNone = () => {
|
|
194
|
-
this.queueableLog(() =>
|
|
257
|
+
this.queueableLog(() => ui.log.warn('Could not detect framework automatically'));
|
|
195
258
|
};
|
|
196
259
|
handleCredentialsFound = () => {
|
|
197
|
-
|
|
260
|
+
ui.log.success('Found existing WorkOS credentials in .env.local');
|
|
198
261
|
};
|
|
199
262
|
handleEnvScanPrompt = async ({ files }) => {
|
|
200
|
-
this.isPromptActive = true;
|
|
201
263
|
const fileList = files.length === 1 ? files[0] : files.slice(0, 2).join(', ');
|
|
202
|
-
const confirmed = await
|
|
264
|
+
const confirmed = await this.withPromptActive(() => ui.confirm({
|
|
203
265
|
message: `Found ${fileList}. Check for existing WorkOS credentials?`,
|
|
204
266
|
initialValue: true,
|
|
205
|
-
});
|
|
206
|
-
this.isPromptActive = false;
|
|
207
|
-
this.flushPendingLogs();
|
|
267
|
+
}));
|
|
208
268
|
this.sendEvent({
|
|
209
|
-
type:
|
|
269
|
+
type: ui.isCancel(confirmed) || !confirmed ? 'ENV_SCAN_DECLINED' : 'ENV_SCAN_APPROVED',
|
|
210
270
|
});
|
|
211
271
|
};
|
|
212
272
|
handleDeviceStarted = ({ verificationUri, userCode }) => {
|
|
213
|
-
|
|
273
|
+
ui.log.info(`\nOpen this URL in your browser:\n`);
|
|
214
274
|
console.log(` ${chalk.cyan(verificationUri)}`);
|
|
215
275
|
console.log(`\nEnter code: ${chalk.bold(userCode)}\n`);
|
|
216
|
-
this.spinner =
|
|
276
|
+
this.spinner = ui.spinner();
|
|
217
277
|
this.spinner.start('Waiting for authentication...');
|
|
218
278
|
};
|
|
219
279
|
handleDeviceSuccess = () => {
|
|
@@ -223,36 +283,65 @@ export class CLIAdapter {
|
|
|
223
283
|
if (this.spinner) {
|
|
224
284
|
this.spinner.stop('Authenticated');
|
|
225
285
|
}
|
|
226
|
-
this.spinner =
|
|
286
|
+
this.spinner = ui.spinner();
|
|
227
287
|
this.spinner.start('Fetching your WorkOS credentials...');
|
|
228
288
|
};
|
|
229
|
-
handleStagingSuccess = () => {
|
|
230
|
-
|
|
231
|
-
|
|
289
|
+
handleStagingSuccess = ({ source }) => {
|
|
290
|
+
if (source === 'device') {
|
|
291
|
+
this.stopSpinner('Environment ready');
|
|
292
|
+
ui.log.success('Set up a WorkOS environment for this install');
|
|
293
|
+
}
|
|
294
|
+
else if (source === 'stored') {
|
|
295
|
+
this.stopSpinner('Using active environment');
|
|
296
|
+
ui.log.success('Using your active WorkOS environment');
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
this.stopSpinner('Environment ready');
|
|
300
|
+
ui.log.success('Using your WorkOS environment');
|
|
301
|
+
}
|
|
232
302
|
};
|
|
233
303
|
handleEnvCredentialsFound = ({ sourcePath }) => {
|
|
234
|
-
|
|
304
|
+
ui.log.success(`Found existing WorkOS credentials in ${sourcePath}`);
|
|
305
|
+
};
|
|
306
|
+
// Automatic auth / credential fetch can fail and fall back to manual entry.
|
|
307
|
+
// These finalize the spinner with a failure glyph so it isn't left spinning
|
|
308
|
+
// (orphaned) over the manual-credentials prompt that follows.
|
|
309
|
+
handleDeviceError = ({ message }) => {
|
|
310
|
+
this.stopSpinner('Automatic sign-in failed', 1);
|
|
311
|
+
if (this.debug)
|
|
312
|
+
this.debugLog(`[device:error] ${message}`);
|
|
313
|
+
};
|
|
314
|
+
handleDeviceTimeout = () => {
|
|
315
|
+
this.stopSpinner('Sign-in timed out', 1);
|
|
316
|
+
};
|
|
317
|
+
handleStagingError = ({ message }) => {
|
|
318
|
+
this.stopSpinner('Could not fetch WorkOS credentials', 1);
|
|
319
|
+
if (this.debug)
|
|
320
|
+
this.debugLog(`[staging:error] ${message}`);
|
|
235
321
|
};
|
|
236
322
|
handleGitDirty = async ({ files }) => {
|
|
237
|
-
|
|
238
|
-
files.slice(0, 5).forEach((f) =>
|
|
323
|
+
ui.log.warn('You have uncommitted or untracked files:');
|
|
324
|
+
files.slice(0, 5).forEach((f) => ui.log.info(chalk.dim(` ${f}`)));
|
|
239
325
|
if (files.length > 5) {
|
|
240
|
-
|
|
326
|
+
ui.log.info(chalk.dim(` ... and ${files.length - 5} more`));
|
|
241
327
|
}
|
|
242
|
-
this.
|
|
243
|
-
const confirmed = await clack.confirm({
|
|
328
|
+
const confirmed = await this.withPromptActive(() => ui.confirm({
|
|
244
329
|
message: 'Continue anyway?',
|
|
245
330
|
initialValue: false,
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
this.flushPendingLogs();
|
|
331
|
+
signal: this.promptAbort?.signal,
|
|
332
|
+
}));
|
|
249
333
|
this.sendEvent({
|
|
250
|
-
type:
|
|
334
|
+
type: ui.isCancel(confirmed) || !confirmed ? 'GIT_CANCELLED' : 'GIT_CONFIRMED',
|
|
251
335
|
});
|
|
252
336
|
};
|
|
253
337
|
handleCredentialsRequest = async ({ requiresApiKey, }) => {
|
|
254
|
-
|
|
255
|
-
|
|
338
|
+
// Guaranteed chokepoint: promptingManual is the fallback for any auth path,
|
|
339
|
+
// so clear any still-running spinner before the prompt opens (defense in
|
|
340
|
+
// depth on top of the device/staging error handlers and withPrompt's pause).
|
|
341
|
+
this.spinner?.clear();
|
|
342
|
+
this.spinner = null;
|
|
343
|
+
ui.log.step(`Get your credentials from ${chalk.cyan('https://dashboard.workos.com')}`);
|
|
344
|
+
const clientId = await ui.text({
|
|
256
345
|
message: 'Enter your WorkOS Client ID:',
|
|
257
346
|
placeholder: 'client_...',
|
|
258
347
|
validate: (value) => {
|
|
@@ -265,14 +354,14 @@ export class CLIAdapter {
|
|
|
265
354
|
return undefined;
|
|
266
355
|
},
|
|
267
356
|
});
|
|
268
|
-
if (
|
|
357
|
+
if (ui.isCancel(clientId)) {
|
|
269
358
|
this.sendEvent({ type: 'CANCEL' });
|
|
270
359
|
return;
|
|
271
360
|
}
|
|
272
361
|
let apiKey = '';
|
|
273
362
|
if (requiresApiKey) {
|
|
274
|
-
|
|
275
|
-
const apiKeyResult = await
|
|
363
|
+
ui.log.info(chalk.dim('ℹ️ Your API key will be hidden for security and saved to .env.local'));
|
|
364
|
+
const apiKeyResult = await ui.password({
|
|
276
365
|
message: 'Enter your WorkOS API Key:',
|
|
277
366
|
validate: (value) => {
|
|
278
367
|
if (!value || value.trim().length === 0) {
|
|
@@ -284,14 +373,14 @@ export class CLIAdapter {
|
|
|
284
373
|
return undefined;
|
|
285
374
|
},
|
|
286
375
|
});
|
|
287
|
-
if (
|
|
376
|
+
if (ui.isCancel(apiKeyResult)) {
|
|
288
377
|
this.sendEvent({ type: 'CANCEL' });
|
|
289
378
|
return;
|
|
290
379
|
}
|
|
291
380
|
apiKey = apiKeyResult;
|
|
292
381
|
}
|
|
293
382
|
else {
|
|
294
|
-
|
|
383
|
+
ui.log.info(chalk.dim('ℹ️ Client-only SDK - API key not required'));
|
|
295
384
|
}
|
|
296
385
|
this.sendEvent({
|
|
297
386
|
type: 'CREDENTIALS_SUBMITTED',
|
|
@@ -300,93 +389,131 @@ export class CLIAdapter {
|
|
|
300
389
|
});
|
|
301
390
|
};
|
|
302
391
|
handleConfigComplete = () => {
|
|
303
|
-
|
|
392
|
+
ui.log.success('Environment configured');
|
|
304
393
|
};
|
|
305
394
|
handleAgentStart = () => {
|
|
306
|
-
this.spinner =
|
|
307
|
-
this.spinner.start(
|
|
308
|
-
//
|
|
309
|
-
|
|
310
|
-
this.agentUpdateInterval = setInterval(() => {
|
|
311
|
-
dots = (dots + 1) % 4;
|
|
312
|
-
const dotStr = '.'.repeat(dots + 1);
|
|
313
|
-
this.spinner?.message(`Running AI agent${dotStr}`);
|
|
314
|
-
}, 2000);
|
|
395
|
+
this.spinner = ui.spinner();
|
|
396
|
+
this.spinner.start(this.lastAgentMessage);
|
|
397
|
+
// No setInterval: ui animates its own frames, and the old 2s reset
|
|
398
|
+
// clobbered the current phase text set by handleAgentProgress.
|
|
315
399
|
};
|
|
316
400
|
handleAgentProgress = ({ step, detail }) => {
|
|
317
401
|
const message = detail ? `${step}: ${detail}` : step;
|
|
402
|
+
this.lastAgentMessage = message;
|
|
318
403
|
this.spinner?.message(message);
|
|
319
404
|
};
|
|
405
|
+
/**
|
|
406
|
+
* Render a persistent line above the running spinner: stop the spinner to
|
|
407
|
+
* finalize its line, emit the log, then restart it on the last phase message.
|
|
408
|
+
* Mirrors the existing stop→log and stop→start-new-spinner precedents.
|
|
409
|
+
*/
|
|
410
|
+
logAboveSpinner(render) {
|
|
411
|
+
const wasRunning = this.spinner !== null;
|
|
412
|
+
this.spinner?.stop();
|
|
413
|
+
this.spinner = null;
|
|
414
|
+
render();
|
|
415
|
+
if (wasRunning) {
|
|
416
|
+
this.spinner = ui.spinner();
|
|
417
|
+
this.spinner.start(this.lastAgentMessage);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
logFileOp(verb, path) {
|
|
421
|
+
if (path === this.lastFileOp)
|
|
422
|
+
return; // dedupe consecutive same-path ops
|
|
423
|
+
this.lastFileOp = path;
|
|
424
|
+
const rel = relative(process.cwd(), path);
|
|
425
|
+
this.logAboveSpinner(() => ui.log.step(`${verb} ${chalk.dim(rel)}`));
|
|
426
|
+
}
|
|
427
|
+
handleFileWrite = ({ path }) => {
|
|
428
|
+
this.logFileOp('Creating', path);
|
|
429
|
+
};
|
|
430
|
+
handleFileEdit = ({ path }) => {
|
|
431
|
+
this.logFileOp('Editing', path);
|
|
432
|
+
};
|
|
433
|
+
handleAgentTool = ({ detail }) => {
|
|
434
|
+
const cmd = detail.length > 80 ? `${detail.slice(0, 77)}…` : detail;
|
|
435
|
+
this.logAboveSpinner(() => ui.log.step(`Running ${chalk.dim(cmd)}`));
|
|
436
|
+
};
|
|
320
437
|
handleValidationStart = () => {
|
|
321
|
-
this.stopAgentUpdates();
|
|
322
438
|
this.stopSpinner('Agent completed');
|
|
323
439
|
};
|
|
324
440
|
handleValidationIssues = ({ issues }) => {
|
|
325
441
|
for (const issue of issues) {
|
|
326
442
|
if (issue.severity === 'error') {
|
|
327
|
-
|
|
443
|
+
ui.log.error(issue.message);
|
|
328
444
|
}
|
|
329
445
|
else {
|
|
330
|
-
|
|
446
|
+
ui.log.warn(issue.message);
|
|
331
447
|
}
|
|
332
448
|
if (issue.hint) {
|
|
333
|
-
|
|
449
|
+
ui.log.info(`Hint: ${issue.hint}`);
|
|
334
450
|
}
|
|
335
451
|
}
|
|
336
452
|
};
|
|
337
453
|
handleValidationComplete = ({ passed, issueCount }) => {
|
|
338
454
|
if (passed) {
|
|
339
|
-
|
|
455
|
+
ui.log.success('Validation passed');
|
|
340
456
|
}
|
|
341
457
|
else {
|
|
342
|
-
|
|
458
|
+
ui.log.warn(`Validation found ${issueCount} issue(s)`);
|
|
343
459
|
}
|
|
344
460
|
};
|
|
345
|
-
handleComplete = ({ success, summary }) => {
|
|
346
|
-
|
|
461
|
+
handleComplete = ({ success, summary, completion }) => {
|
|
462
|
+
// Fires synchronously during the cancelled-state transition (emitCancelled),
|
|
463
|
+
// BEFORE a queued sibling prompt's microtask runs — so aborting here makes a
|
|
464
|
+
// cancelled run's still-queued prompt (e.g. the branch select after a
|
|
465
|
+
// git-dirty "No") open with an already-aborted signal and resolve to CANCEL
|
|
466
|
+
// without ever rendering a now-moot question.
|
|
467
|
+
this.promptAbort?.abort();
|
|
347
468
|
this.stopSpinner(success ? 'Done' : 'Failed');
|
|
348
469
|
console.log('');
|
|
349
|
-
console.log(renderCompletionSummary(success, summary));
|
|
470
|
+
console.log(renderCompletionSummary(success, summary, completion));
|
|
350
471
|
console.log('');
|
|
351
472
|
// When we scaffolded a fresh app, the install ran in the current dir, so
|
|
352
473
|
// point the user straight at the dev server.
|
|
353
474
|
if (success && this.scaffolded) {
|
|
354
|
-
|
|
475
|
+
ui.log.info(`Start your app: ${chalk.cyan(`${this.scaffoldPackageManager} run dev`)}`);
|
|
355
476
|
}
|
|
356
477
|
};
|
|
357
478
|
handleError = ({ message, stack }) => {
|
|
358
|
-
this.stopSpinner('
|
|
359
|
-
|
|
360
|
-
//
|
|
479
|
+
this.stopSpinner('Failed', 1);
|
|
480
|
+
// Rewrite raw API/SDK errors into user-friendly messages with a next step.
|
|
481
|
+
// Matching is word-boundary / code-based so 'author' doesn't read as 'auth'
|
|
482
|
+
// and 'Module not found' doesn't read as a missing-directory error.
|
|
361
483
|
const isServiceError = /\b50[0-9]\b/.test(message) || /server_error|internal_error|overloaded|service.*unavailable/i.test(message);
|
|
362
|
-
const isRateLimit = /\b429\b/.test(message) ||
|
|
484
|
+
const isRateLimit = /\b429\b/.test(message) || /\brate.?limit/i.test(message);
|
|
363
485
|
const isNetworkError = /ECONNREFUSED|ETIMEDOUT|ENOTFOUND|fetch failed/i.test(message);
|
|
364
486
|
const isProcessExit = /process exited with code/i.test(message);
|
|
487
|
+
const isAuthError = /\b(401|403|unauthorized|forbidden|authentication|authorization)\b/i.test(message);
|
|
488
|
+
const isMissingPath = /\bENOENT\b/.test(message);
|
|
365
489
|
if (isServiceError) {
|
|
366
|
-
|
|
367
|
-
|
|
490
|
+
ui.log.error('The AI service is temporarily unavailable.');
|
|
491
|
+
ui.log.info('This is usually resolved within a few minutes. Please try again shortly.');
|
|
368
492
|
}
|
|
369
493
|
else if (isRateLimit) {
|
|
370
|
-
|
|
371
|
-
|
|
494
|
+
ui.log.error('The AI service is currently rate-limited.');
|
|
495
|
+
ui.log.info('Please wait a minute and try again.');
|
|
372
496
|
}
|
|
373
497
|
else if (isNetworkError) {
|
|
374
|
-
|
|
375
|
-
|
|
498
|
+
ui.log.error('Could not connect to the AI service.');
|
|
499
|
+
ui.log.info('Check your internet connection and try again.');
|
|
376
500
|
}
|
|
377
501
|
else if (isProcessExit) {
|
|
378
|
-
|
|
379
|
-
|
|
502
|
+
ui.log.error('The AI agent process exited unexpectedly.');
|
|
503
|
+
ui.log.info('Try running again. If this persists, run with --debug for details.');
|
|
380
504
|
}
|
|
381
|
-
else {
|
|
382
|
-
|
|
505
|
+
else if (isAuthError) {
|
|
506
|
+
ui.log.error('Authentication failed.');
|
|
507
|
+
ui.log.info(`Try running: ${formatWorkOSCommand('auth logout')} && ${formatWorkOSCommand('install')}`);
|
|
383
508
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
509
|
+
else if (isMissingPath) {
|
|
510
|
+
ui.log.error(message);
|
|
511
|
+
ui.log.info('Make sure you are running this in your project directory.');
|
|
387
512
|
}
|
|
388
|
-
|
|
389
|
-
|
|
513
|
+
else {
|
|
514
|
+
// Unknown error: still give the user somewhere to go next.
|
|
515
|
+
ui.log.error(message);
|
|
516
|
+
ui.log.info(`Re-run with ${chalk.cyan('--debug')} for details, or report it at ${chalk.cyan('https://github.com/workos/cli/issues')}`);
|
|
390
517
|
}
|
|
391
518
|
if (stack && this.debug) {
|
|
392
519
|
this.debugLog(stack);
|
|
@@ -395,20 +522,17 @@ export class CLIAdapter {
|
|
|
395
522
|
// ===== Scaffold Event Handlers =====
|
|
396
523
|
handleScaffoldPrompt = async ({ packageManager }) => {
|
|
397
524
|
this.scaffoldPackageManager = packageManager;
|
|
398
|
-
this.
|
|
399
|
-
const confirmed = await clack.confirm({
|
|
525
|
+
const confirmed = await this.withPromptActive(() => ui.confirm({
|
|
400
526
|
message: 'This directory is empty. Scaffold a new Next.js app with AuthKit here?',
|
|
401
527
|
initialValue: true,
|
|
402
|
-
});
|
|
403
|
-
this.isPromptActive = false;
|
|
404
|
-
this.flushPendingLogs();
|
|
528
|
+
}));
|
|
405
529
|
this.sendEvent({
|
|
406
|
-
type:
|
|
530
|
+
type: ui.isCancel(confirmed) || !confirmed ? 'SCAFFOLD_CANCELLED' : 'SCAFFOLD_CONFIRMED',
|
|
407
531
|
});
|
|
408
532
|
};
|
|
409
533
|
handleScaffoldStart = ({ packageManager }) => {
|
|
410
534
|
this.scaffoldPackageManager = packageManager;
|
|
411
|
-
this.spinner =
|
|
535
|
+
this.spinner = ui.spinner();
|
|
412
536
|
this.spinner.start(`Scaffolding a new Next.js app with ${packageManager} (this can take a minute)...`);
|
|
413
537
|
};
|
|
414
538
|
// create-next-app output is verbose; surface it only under --debug and keep
|
|
@@ -425,21 +549,19 @@ export class CLIAdapter {
|
|
|
425
549
|
};
|
|
426
550
|
handleScaffoldFailed = ({ error }) => {
|
|
427
551
|
this.stopSpinner('Scaffold failed');
|
|
428
|
-
|
|
552
|
+
ui.log.error(`Could not scaffold the app: ${error}`);
|
|
429
553
|
};
|
|
430
554
|
handleBranchPrompt = async ({ branch }) => {
|
|
431
|
-
this.
|
|
432
|
-
const choice = await clack.select({
|
|
555
|
+
const choice = await this.withPromptActive(() => ui.select({
|
|
433
556
|
message: `You are on ${chalk.bold(branch)}. Create a feature branch?`,
|
|
434
557
|
options: [
|
|
435
558
|
{ value: 'create', label: 'Create feat/add-workos-authkit' },
|
|
436
559
|
{ value: 'continue', label: 'Continue on current branch' },
|
|
437
560
|
{ value: 'cancel', label: 'Cancel' },
|
|
438
561
|
],
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
if (clack.isCancel(choice) || choice === 'cancel') {
|
|
562
|
+
signal: this.promptAbort?.signal,
|
|
563
|
+
}));
|
|
564
|
+
if (ui.isCancel(choice) || choice === 'cancel') {
|
|
443
565
|
this.sendEvent({ type: 'BRANCH_CANCEL' });
|
|
444
566
|
}
|
|
445
567
|
else if (choice === 'create') {
|
|
@@ -450,50 +572,44 @@ export class CLIAdapter {
|
|
|
450
572
|
}
|
|
451
573
|
};
|
|
452
574
|
handleBranchCreated = ({ branch }) => {
|
|
453
|
-
this.queueableLog(() =>
|
|
575
|
+
this.queueableLog(() => ui.log.success(`Created branch ${chalk.bold(branch)}`));
|
|
454
576
|
};
|
|
455
577
|
// ===== Post-install Event Handlers =====
|
|
456
578
|
handlePostInstallChanges = ({ files }) => {
|
|
457
579
|
this.debugLog(`Post-install: ${files.length} changed files detected`);
|
|
458
580
|
};
|
|
459
581
|
handleCommitPrompt = async () => {
|
|
460
|
-
this.
|
|
461
|
-
const confirmed = await clack.confirm({
|
|
582
|
+
const confirmed = await this.withPromptActive(() => ui.confirm({
|
|
462
583
|
message: 'Commit the changes?',
|
|
463
584
|
initialValue: true,
|
|
464
|
-
});
|
|
465
|
-
this.isPromptActive = false;
|
|
466
|
-
this.flushPendingLogs();
|
|
585
|
+
}));
|
|
467
586
|
this.sendEvent({
|
|
468
|
-
type:
|
|
587
|
+
type: ui.isCancel(confirmed) || !confirmed ? 'COMMIT_DECLINED' : 'COMMIT_APPROVED',
|
|
469
588
|
});
|
|
470
589
|
};
|
|
471
590
|
handleCommitGenerating = () => {
|
|
472
|
-
this.spinner =
|
|
591
|
+
this.spinner = ui.spinner();
|
|
473
592
|
this.spinner.start('Generating commit message...');
|
|
474
593
|
};
|
|
475
594
|
handleCommitSuccess = ({ message }) => {
|
|
476
595
|
this.stopSpinner('Committed');
|
|
477
|
-
|
|
596
|
+
ui.log.success(`Committed: ${chalk.dim(message)}`);
|
|
478
597
|
};
|
|
479
598
|
handleCommitFailed = ({ error }) => {
|
|
480
599
|
this.stopSpinner('Commit failed');
|
|
481
|
-
|
|
600
|
+
ui.log.error(`Commit failed: ${error}`);
|
|
482
601
|
};
|
|
483
602
|
handlePrPrompt = async () => {
|
|
484
|
-
this.
|
|
485
|
-
const confirmed = await clack.confirm({
|
|
603
|
+
const confirmed = await this.withPromptActive(() => ui.confirm({
|
|
486
604
|
message: 'Create a pull request?',
|
|
487
605
|
initialValue: true,
|
|
488
|
-
});
|
|
489
|
-
this.isPromptActive = false;
|
|
490
|
-
this.flushPendingLogs();
|
|
606
|
+
}));
|
|
491
607
|
this.sendEvent({
|
|
492
|
-
type:
|
|
608
|
+
type: ui.isCancel(confirmed) || !confirmed ? 'PR_DECLINED' : 'PR_APPROVED',
|
|
493
609
|
});
|
|
494
610
|
};
|
|
495
611
|
handlePrGenerating = () => {
|
|
496
|
-
this.spinner =
|
|
612
|
+
this.spinner = ui.spinner();
|
|
497
613
|
this.spinner.start('Generating PR description...');
|
|
498
614
|
};
|
|
499
615
|
handlePrPushing = () => {
|
|
@@ -501,24 +617,24 @@ export class CLIAdapter {
|
|
|
501
617
|
this.spinner.message('Pushing to remote...');
|
|
502
618
|
}
|
|
503
619
|
else {
|
|
504
|
-
this.spinner =
|
|
620
|
+
this.spinner = ui.spinner();
|
|
505
621
|
this.spinner.start('Pushing to remote...');
|
|
506
622
|
}
|
|
507
623
|
};
|
|
508
624
|
handlePrSuccess = ({ url }) => {
|
|
509
625
|
this.stopSpinner('PR created');
|
|
510
|
-
|
|
626
|
+
ui.log.success(`Pull request created: ${chalk.cyan(url)}`);
|
|
511
627
|
};
|
|
512
628
|
handlePrFailed = ({ error }) => {
|
|
513
629
|
this.stopSpinner('PR creation failed');
|
|
514
|
-
|
|
630
|
+
ui.log.error(`PR creation failed: ${error}`);
|
|
515
631
|
};
|
|
516
632
|
handlePushFailed = ({ error }) => {
|
|
517
633
|
this.stopSpinner('Push failed');
|
|
518
|
-
|
|
634
|
+
ui.log.error(`Push failed: ${error}`);
|
|
519
635
|
};
|
|
520
636
|
handleManualInstructions = ({ instructions }) => {
|
|
521
|
-
|
|
637
|
+
ui.log.info('GitHub CLI not found. Manual steps:');
|
|
522
638
|
console.log(chalk.dim(instructions));
|
|
523
639
|
};
|
|
524
640
|
}
|