workos 0.1.2 → 0.2.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/dist/src/commands/login.js +1 -1
- package/dist/src/commands/login.js.map +1 -1
- package/dist/src/lib/adapters/cli-adapter.d.ts +21 -0
- package/dist/src/lib/adapters/cli-adapter.js +165 -21
- package/dist/src/lib/adapters/cli-adapter.js.map +1 -1
- package/dist/src/lib/adapters/dashboard-adapter.js +13 -0
- package/dist/src/lib/adapters/dashboard-adapter.js.map +1 -1
- package/dist/src/lib/ai-content.d.ts +10 -0
- package/dist/src/lib/ai-content.js +68 -0
- package/dist/src/lib/ai-content.js.map +1 -0
- package/dist/src/lib/credential-discovery.d.ts +42 -0
- package/dist/src/lib/credential-discovery.js +100 -0
- package/dist/src/lib/credential-discovery.js.map +1 -0
- package/dist/src/lib/credentials.d.ts +22 -0
- package/dist/src/lib/credentials.js +29 -0
- package/dist/src/lib/credentials.js.map +1 -1
- package/dist/src/lib/device-auth.d.ts +44 -0
- package/dist/src/lib/device-auth.js +137 -0
- package/dist/src/lib/device-auth.js.map +1 -0
- package/dist/src/lib/events.d.ts +75 -0
- package/dist/src/lib/events.js.map +1 -1
- package/dist/src/lib/post-install.d.ts +8 -0
- package/dist/src/lib/post-install.js +51 -0
- package/dist/src/lib/post-install.js.map +1 -0
- package/dist/src/lib/run-with-core.js +107 -1
- package/dist/src/lib/run-with-core.js.map +1 -1
- package/dist/src/lib/staging-api.d.ts +22 -0
- package/dist/src/lib/staging-api.js +74 -0
- package/dist/src/lib/staging-api.js.map +1 -0
- package/dist/src/lib/wizard-core.d.ts +300 -8
- package/dist/src/lib/wizard-core.js +622 -27
- package/dist/src/lib/wizard-core.js.map +1 -1
- package/dist/src/lib/wizard-core.types.d.ts +64 -1
- package/dist/src/lib/wizard-core.types.js.map +1 -1
- package/dist/src/run.d.ts +1 -0
- package/dist/src/run.js +1 -0
- package/dist/src/run.js.map +1 -1
- package/dist/src/utils/debug.js +15 -9
- package/dist/src/utils/debug.js.map +1 -1
- package/dist/src/utils/git-utils.d.ts +23 -0
- package/dist/src/utils/git-utils.js +86 -0
- package/dist/src/utils/git-utils.js.map +1 -0
- package/dist/src/utils/types.d.ts +4 -0
- package/dist/src/utils/types.js.map +1 -1
- package/package.json +6 -6
- package/skills/workos-authkit-base/SKILL.md +24 -14
- package/skills/workos-authkit-nextjs/SKILL.md +12 -1
- package/skills/workos-authkit-react/SKILL.md +4 -4
- package/skills/workos-authkit-react-router/SKILL.md +11 -10
- package/skills/workos-authkit-tanstack-start/SKILL.md +8 -6
- package/skills/workos-authkit-vanilla-js/SKILL.md +10 -8
- package/dist/package.json +0 -87
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { setup, assign, fromPromise } from 'xstate';
|
|
2
|
+
import { getManualPrInstructions } from './post-install.js';
|
|
3
|
+
import { hasGhCli } from '../utils/git-utils.js';
|
|
2
4
|
export const wizardMachine = setup({
|
|
3
5
|
types: {
|
|
4
6
|
context: {},
|
|
@@ -51,6 +53,32 @@ export const wizardMachine = setup({
|
|
|
51
53
|
emitGitCancelled: ({ context }) => {
|
|
52
54
|
context.emitter.emit('git:dirty:cancelled', {});
|
|
53
55
|
},
|
|
56
|
+
emitBranchChecking: ({ context }) => {
|
|
57
|
+
context.emitter.emit('branch:checking', {});
|
|
58
|
+
},
|
|
59
|
+
emitBranchProtected: ({ context }) => {
|
|
60
|
+
if (context.currentBranch) {
|
|
61
|
+
context.emitter.emit('branch:protected', { branch: context.currentBranch });
|
|
62
|
+
context.emitter.emit('branch:prompt', { branch: context.currentBranch });
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
emitBranchCreated: ({ context }, params) => {
|
|
66
|
+
context.emitter.emit('branch:created', { branch: params.branch });
|
|
67
|
+
},
|
|
68
|
+
emitBranchCreateFailed: ({ context }) => {
|
|
69
|
+
const message = context.error?.message ?? 'Failed to create branch';
|
|
70
|
+
context.emitter.emit('branch:create:failed', { error: message });
|
|
71
|
+
},
|
|
72
|
+
assignBranchResult: assign({
|
|
73
|
+
currentBranch: ({ event }) => {
|
|
74
|
+
const doneEvent = event;
|
|
75
|
+
return doneEvent.output?.branch ?? undefined;
|
|
76
|
+
},
|
|
77
|
+
isProtectedBranch: ({ event }) => {
|
|
78
|
+
const doneEvent = event;
|
|
79
|
+
return doneEvent.output?.isProtected ?? false;
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
54
82
|
emitCredentialsGathering: ({ context }) => {
|
|
55
83
|
const requiresApiKey = ['nextjs', 'tanstack-start', 'react-router'].includes(context.integration ?? '');
|
|
56
84
|
context.emitter.emit('credentials:gathering', { requiresApiKey });
|
|
@@ -59,6 +87,44 @@ export const wizardMachine = setup({
|
|
|
59
87
|
emitCredentialsFound: ({ context }) => {
|
|
60
88
|
context.emitter.emit('credentials:found', {});
|
|
61
89
|
},
|
|
90
|
+
emitEnvDetected: ({ context }) => {
|
|
91
|
+
context.emitter.emit('credentials:env:detected', { files: context.envFilesDetected ?? [] });
|
|
92
|
+
},
|
|
93
|
+
emitEnvScanPrompt: ({ context }) => {
|
|
94
|
+
context.emitter.emit('credentials:env:prompt', { files: context.envFilesDetected ?? [] });
|
|
95
|
+
},
|
|
96
|
+
emitEnvScanning: ({ context }) => {
|
|
97
|
+
context.emitter.emit('credentials:env:scanning', {});
|
|
98
|
+
},
|
|
99
|
+
emitEnvCredentialsFound: ({ context }) => {
|
|
100
|
+
context.emitter.emit('credentials:env:found', { sourcePath: context.envCredentialPath ?? '.env' });
|
|
101
|
+
},
|
|
102
|
+
emitEnvNotFound: ({ context }) => {
|
|
103
|
+
context.emitter.emit('credentials:env:notfound', {});
|
|
104
|
+
},
|
|
105
|
+
emitDeviceAuthStart: () => {
|
|
106
|
+
// Emitted by actor when it has verification URL
|
|
107
|
+
},
|
|
108
|
+
emitDeviceAuthSuccess: ({ context }) => {
|
|
109
|
+
context.emitter.emit('device:success', { email: undefined });
|
|
110
|
+
},
|
|
111
|
+
emitDeviceAuthError: ({ context }) => {
|
|
112
|
+
const message = context.error?.message ?? 'Device authorization failed';
|
|
113
|
+
context.emitter.emit('device:error', { message });
|
|
114
|
+
},
|
|
115
|
+
emitDeviceTimeout: ({ context }) => {
|
|
116
|
+
context.emitter.emit('device:timeout', {});
|
|
117
|
+
},
|
|
118
|
+
emitStagingFetching: ({ context }) => {
|
|
119
|
+
context.emitter.emit('staging:fetching', {});
|
|
120
|
+
},
|
|
121
|
+
emitStagingSuccess: ({ context }) => {
|
|
122
|
+
context.emitter.emit('staging:success', {});
|
|
123
|
+
},
|
|
124
|
+
emitStagingError: ({ context }) => {
|
|
125
|
+
const message = context.error?.message ?? 'Failed to fetch staging credentials';
|
|
126
|
+
context.emitter.emit('staging:error', { message });
|
|
127
|
+
},
|
|
62
128
|
emitConfigStart: ({ context }) => {
|
|
63
129
|
context.emitter.emit('config:start', {});
|
|
64
130
|
},
|
|
@@ -121,12 +187,93 @@ export const wizardMachine = setup({
|
|
|
121
187
|
context.emitter.emit('error', { message, stack: context.error?.stack });
|
|
122
188
|
context.emitter.emit('complete', { success: false, summary: message });
|
|
123
189
|
},
|
|
190
|
+
// Post-install actions
|
|
191
|
+
assignChangedFiles: assign({
|
|
192
|
+
changedFiles: ({ event }) => {
|
|
193
|
+
const doneEvent = event;
|
|
194
|
+
return doneEvent.output?.files ?? [];
|
|
195
|
+
},
|
|
196
|
+
}),
|
|
197
|
+
emitChangesDetected: ({ context }) => {
|
|
198
|
+
context.emitter.emit('postinstall:changes', { files: context.changedFiles ?? [] });
|
|
199
|
+
},
|
|
200
|
+
emitNoChanges: ({ context }) => {
|
|
201
|
+
context.emitter.emit('postinstall:nochanges', {});
|
|
202
|
+
},
|
|
203
|
+
emitCommitPrompt: ({ context }) => {
|
|
204
|
+
context.emitter.emit('postinstall:commit:prompt', {});
|
|
205
|
+
},
|
|
206
|
+
emitGeneratingCommitMessage: ({ context }) => {
|
|
207
|
+
context.emitter.emit('postinstall:commit:generating', {});
|
|
208
|
+
},
|
|
209
|
+
assignCommitMessage: assign({
|
|
210
|
+
commitMessage: ({ event }) => {
|
|
211
|
+
const doneEvent = event;
|
|
212
|
+
return doneEvent.output;
|
|
213
|
+
},
|
|
214
|
+
}),
|
|
215
|
+
emitCommitting: ({ context }) => {
|
|
216
|
+
context.emitter.emit('postinstall:commit:committing', { message: context.commitMessage ?? '' });
|
|
217
|
+
},
|
|
218
|
+
emitCommitSuccess: ({ context }) => {
|
|
219
|
+
context.emitter.emit('postinstall:commit:success', { message: context.commitMessage ?? '' });
|
|
220
|
+
},
|
|
221
|
+
emitCommitFailed: ({ context }) => {
|
|
222
|
+
const message = context.error?.message ?? 'Commit failed';
|
|
223
|
+
context.emitter.emit('postinstall:commit:failed', { error: message });
|
|
224
|
+
},
|
|
225
|
+
emitPrPrompt: ({ context }) => {
|
|
226
|
+
context.emitter.emit('postinstall:pr:prompt', {});
|
|
227
|
+
},
|
|
228
|
+
emitGeneratingPrDescription: ({ context }) => {
|
|
229
|
+
context.emitter.emit('postinstall:pr:generating', {});
|
|
230
|
+
},
|
|
231
|
+
assignPrDescription: assign({
|
|
232
|
+
prDescription: ({ event }) => {
|
|
233
|
+
const doneEvent = event;
|
|
234
|
+
return doneEvent.output;
|
|
235
|
+
},
|
|
236
|
+
}),
|
|
237
|
+
emitPushing: ({ context }) => {
|
|
238
|
+
context.emitter.emit('postinstall:pr:pushing', {});
|
|
239
|
+
},
|
|
240
|
+
emitPushFailed: ({ context }) => {
|
|
241
|
+
const message = context.error?.message ?? 'Push failed';
|
|
242
|
+
context.emitter.emit('postinstall:push:failed', { error: message });
|
|
243
|
+
},
|
|
244
|
+
emitCreatingPr: ({ context }) => {
|
|
245
|
+
context.emitter.emit('postinstall:pr:creating', {});
|
|
246
|
+
},
|
|
247
|
+
assignPrUrl: assign({
|
|
248
|
+
prUrl: ({ event }) => {
|
|
249
|
+
const doneEvent = event;
|
|
250
|
+
return doneEvent.output;
|
|
251
|
+
},
|
|
252
|
+
}),
|
|
253
|
+
emitPrCreated: ({ context }) => {
|
|
254
|
+
context.emitter.emit('postinstall:pr:success', { url: context.prUrl ?? '' });
|
|
255
|
+
},
|
|
256
|
+
emitPrFailed: ({ context }) => {
|
|
257
|
+
const message = context.error?.message ?? 'PR creation failed';
|
|
258
|
+
context.emitter.emit('postinstall:pr:failed', { error: message });
|
|
259
|
+
},
|
|
260
|
+
emitManualInstructions: ({ context }) => {
|
|
261
|
+
const branch = context.currentBranch ?? 'HEAD';
|
|
262
|
+
const instructions = getManualPrInstructions(branch);
|
|
263
|
+
context.emitter.emit('postinstall:manual', { instructions });
|
|
264
|
+
},
|
|
265
|
+
emitComplete: ({ context }) => {
|
|
266
|
+
const summary = context.agentSummary ?? 'WorkOS AuthKit installed successfully!';
|
|
267
|
+
context.emitter.emit('complete', { success: true, summary });
|
|
268
|
+
},
|
|
124
269
|
},
|
|
125
270
|
guards: {
|
|
126
271
|
shouldSkipAuth: ({ context }) => context.options.skipAuth === true,
|
|
127
272
|
gitIsClean: ({ context }) => context.gitIsClean === true,
|
|
128
273
|
hasCredentials: ({ context }) => context.options.apiKey !== undefined && context.options.clientId !== undefined,
|
|
129
274
|
hasIntegration: ({ context }) => context.integration !== undefined,
|
|
275
|
+
shouldSkipPostInstall: ({ context }) => context.options.noCommit === true,
|
|
276
|
+
hasGhCli: () => hasGhCli(),
|
|
130
277
|
},
|
|
131
278
|
actors: {
|
|
132
279
|
checkAuthentication: fromPromise(async () => {
|
|
@@ -144,6 +291,48 @@ export const wizardMachine = setup({
|
|
|
144
291
|
runAgent: fromPromise(async () => {
|
|
145
292
|
throw new Error('runAgent not implemented - provide via machine.provide()');
|
|
146
293
|
}),
|
|
294
|
+
// Credential discovery actors
|
|
295
|
+
detectEnvFiles: fromPromise(async () => {
|
|
296
|
+
throw new Error('detectEnvFiles not implemented - provide via machine.provide()');
|
|
297
|
+
}),
|
|
298
|
+
scanEnvFiles: fromPromise(async () => {
|
|
299
|
+
throw new Error('scanEnvFiles not implemented - provide via machine.provide()');
|
|
300
|
+
}),
|
|
301
|
+
checkStoredAuth: fromPromise(async () => {
|
|
302
|
+
throw new Error('checkStoredAuth not implemented - provide via machine.provide()');
|
|
303
|
+
}),
|
|
304
|
+
runDeviceAuth: fromPromise(async () => {
|
|
305
|
+
throw new Error('runDeviceAuth not implemented - provide via machine.provide()');
|
|
306
|
+
}),
|
|
307
|
+
fetchStagingCredentials: fromPromise(async () => {
|
|
308
|
+
throw new Error('fetchStagingCredentials not implemented - provide via machine.provide()');
|
|
309
|
+
}),
|
|
310
|
+
// Branch check actors
|
|
311
|
+
checkBranch: fromPromise(async () => {
|
|
312
|
+
throw new Error('checkBranch not implemented - provide via machine.provide()');
|
|
313
|
+
}),
|
|
314
|
+
createBranch: fromPromise(async () => {
|
|
315
|
+
throw new Error('createBranch not implemented - provide via machine.provide()');
|
|
316
|
+
}),
|
|
317
|
+
// Post-install actors
|
|
318
|
+
detectChanges: fromPromise(async () => {
|
|
319
|
+
throw new Error('detectChanges not implemented - provide via machine.provide()');
|
|
320
|
+
}),
|
|
321
|
+
generateCommitMessage: fromPromise(async () => {
|
|
322
|
+
throw new Error('generateCommitMessage not implemented - provide via machine.provide()');
|
|
323
|
+
}),
|
|
324
|
+
commitChanges: fromPromise(async () => {
|
|
325
|
+
throw new Error('commitChanges not implemented - provide via machine.provide()');
|
|
326
|
+
}),
|
|
327
|
+
generatePrDescription: fromPromise(async () => {
|
|
328
|
+
throw new Error('generatePrDescription not implemented - provide via machine.provide()');
|
|
329
|
+
}),
|
|
330
|
+
pushBranch: fromPromise(async () => {
|
|
331
|
+
throw new Error('pushBranch not implemented - provide via machine.provide()');
|
|
332
|
+
}),
|
|
333
|
+
createPr: fromPromise(async () => {
|
|
334
|
+
throw new Error('createPr not implemented - provide via machine.provide()');
|
|
335
|
+
}),
|
|
147
336
|
},
|
|
148
337
|
}).createMachine({
|
|
149
338
|
id: 'wizard',
|
|
@@ -278,6 +467,73 @@ export const wizardMachine = setup({
|
|
|
278
467
|
},
|
|
279
468
|
},
|
|
280
469
|
},
|
|
470
|
+
branchCheck: {
|
|
471
|
+
initial: 'running',
|
|
472
|
+
states: {
|
|
473
|
+
running: {
|
|
474
|
+
entry: ['emitBranchChecking'],
|
|
475
|
+
invoke: {
|
|
476
|
+
id: 'checkBranch',
|
|
477
|
+
src: 'checkBranch',
|
|
478
|
+
onDone: [
|
|
479
|
+
{
|
|
480
|
+
target: 'awaitingConfirmation',
|
|
481
|
+
guard: ({ event }) => event.output.isProtected,
|
|
482
|
+
actions: ['assignBranchResult', 'emitBranchProtected'],
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
target: 'done',
|
|
486
|
+
actions: ['assignBranchResult'],
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
onError: {
|
|
490
|
+
// Branch check failure is non-fatal
|
|
491
|
+
target: 'done',
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
},
|
|
495
|
+
awaitingConfirmation: {
|
|
496
|
+
on: {
|
|
497
|
+
BRANCH_CREATE: {
|
|
498
|
+
target: 'creating',
|
|
499
|
+
},
|
|
500
|
+
BRANCH_CONTINUE: {
|
|
501
|
+
target: 'done',
|
|
502
|
+
},
|
|
503
|
+
BRANCH_CANCEL: {
|
|
504
|
+
target: '#wizard.cancelled',
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
creating: {
|
|
509
|
+
invoke: {
|
|
510
|
+
id: 'createBranch',
|
|
511
|
+
src: 'createBranch',
|
|
512
|
+
input: () => ({
|
|
513
|
+
name: 'feat/add-workos-authkit',
|
|
514
|
+
fallbackName: `feat/add-workos-authkit-${Date.now()}`,
|
|
515
|
+
}),
|
|
516
|
+
onDone: {
|
|
517
|
+
target: 'done',
|
|
518
|
+
actions: [
|
|
519
|
+
{
|
|
520
|
+
type: 'emitBranchCreated',
|
|
521
|
+
params: ({ event }) => ({ branch: event.output.branch }),
|
|
522
|
+
},
|
|
523
|
+
],
|
|
524
|
+
},
|
|
525
|
+
onError: {
|
|
526
|
+
// Branch creation failure is non-fatal
|
|
527
|
+
target: 'done',
|
|
528
|
+
actions: ['assignError', 'emitBranchCreateFailed'],
|
|
529
|
+
},
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
done: {
|
|
533
|
+
type: 'final',
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
},
|
|
281
537
|
},
|
|
282
538
|
onDone: [
|
|
283
539
|
{
|
|
@@ -296,26 +552,194 @@ export const wizardMachine = setup({
|
|
|
296
552
|
},
|
|
297
553
|
gatheringCredentials: {
|
|
298
554
|
entry: [{ type: 'emitStateEnter', params: { state: 'gatheringCredentials' } }],
|
|
299
|
-
initial: '
|
|
555
|
+
initial: 'checkingCliFlags',
|
|
300
556
|
states: {
|
|
301
|
-
|
|
557
|
+
// Step 1: Check CLI flags (highest priority)
|
|
558
|
+
checkingCliFlags: {
|
|
302
559
|
always: [
|
|
303
560
|
{
|
|
304
561
|
target: '#wizard.configuring',
|
|
305
562
|
guard: 'hasCredentials',
|
|
306
|
-
actions: [
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
563
|
+
actions: [
|
|
564
|
+
assign({ credentialSource: () => 'cli' }),
|
|
565
|
+
'emitCredentialsFound',
|
|
566
|
+
{ type: 'emitStateExit', params: { state: 'gatheringCredentials' } },
|
|
567
|
+
],
|
|
310
568
|
},
|
|
569
|
+
{ target: 'detectingEnvFiles' },
|
|
311
570
|
],
|
|
312
571
|
},
|
|
313
|
-
|
|
572
|
+
// Step 2: Check if env files exist (don't read yet)
|
|
573
|
+
detectingEnvFiles: {
|
|
574
|
+
invoke: {
|
|
575
|
+
id: 'detectEnvFiles',
|
|
576
|
+
src: 'detectEnvFiles',
|
|
577
|
+
input: ({ context }) => ({ installDir: context.options.installDir }),
|
|
578
|
+
onDone: [
|
|
579
|
+
{
|
|
580
|
+
target: 'promptingEnvScan',
|
|
581
|
+
guard: ({ event }) => {
|
|
582
|
+
const output = event.output;
|
|
583
|
+
return output.exists;
|
|
584
|
+
},
|
|
585
|
+
actions: [
|
|
586
|
+
assign({
|
|
587
|
+
envFilesDetected: ({ event }) => {
|
|
588
|
+
const output = event.output;
|
|
589
|
+
return output.files;
|
|
590
|
+
},
|
|
591
|
+
}),
|
|
592
|
+
'emitEnvDetected',
|
|
593
|
+
],
|
|
594
|
+
},
|
|
595
|
+
{ target: 'checkingStoredAuth' },
|
|
596
|
+
],
|
|
597
|
+
onError: {
|
|
598
|
+
target: 'checkingStoredAuth', // Non-fatal, continue
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
// Step 3: Ask user for consent to scan env files
|
|
603
|
+
promptingEnvScan: {
|
|
604
|
+
entry: ['emitEnvScanPrompt'],
|
|
605
|
+
on: {
|
|
606
|
+
ENV_SCAN_APPROVED: {
|
|
607
|
+
target: 'scanningEnvFiles',
|
|
608
|
+
actions: assign({ envScanConsent: () => true }),
|
|
609
|
+
},
|
|
610
|
+
ENV_SCAN_DECLINED: {
|
|
611
|
+
target: 'checkingStoredAuth',
|
|
612
|
+
actions: assign({ envScanConsent: () => false }),
|
|
613
|
+
},
|
|
614
|
+
CANCEL: {
|
|
615
|
+
target: '#wizard.cancelled',
|
|
616
|
+
actions: { type: 'emitStateExit', params: { state: 'gatheringCredentials' } },
|
|
617
|
+
},
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
// Step 4: Scan env files for credentials (with consent)
|
|
621
|
+
scanningEnvFiles: {
|
|
622
|
+
entry: ['emitEnvScanning'],
|
|
623
|
+
invoke: {
|
|
624
|
+
id: 'scanEnvFiles',
|
|
625
|
+
src: 'scanEnvFiles',
|
|
626
|
+
input: ({ context }) => ({ installDir: context.options.installDir }),
|
|
627
|
+
onDone: [
|
|
628
|
+
{
|
|
629
|
+
target: '#wizard.configuring',
|
|
630
|
+
guard: ({ event }) => {
|
|
631
|
+
const result = event.output;
|
|
632
|
+
return result.found && !!result.clientId;
|
|
633
|
+
},
|
|
634
|
+
actions: [
|
|
635
|
+
assign({
|
|
636
|
+
credentials: ({ event }) => {
|
|
637
|
+
const result = event.output;
|
|
638
|
+
return { clientId: result.clientId, apiKey: result.apiKey };
|
|
639
|
+
},
|
|
640
|
+
credentialSource: () => 'env',
|
|
641
|
+
envCredentialPath: ({ event }) => event.output.sourcePath,
|
|
642
|
+
}),
|
|
643
|
+
'emitEnvCredentialsFound',
|
|
644
|
+
{ type: 'emitStateExit', params: { state: 'gatheringCredentials' } },
|
|
645
|
+
],
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
target: 'checkingStoredAuth',
|
|
649
|
+
actions: ['emitEnvNotFound'],
|
|
650
|
+
},
|
|
651
|
+
],
|
|
652
|
+
onError: {
|
|
653
|
+
target: 'checkingStoredAuth',
|
|
654
|
+
},
|
|
655
|
+
},
|
|
656
|
+
},
|
|
657
|
+
// Step 5: Check for stored auth token
|
|
658
|
+
checkingStoredAuth: {
|
|
659
|
+
invoke: {
|
|
660
|
+
id: 'checkStoredAuth',
|
|
661
|
+
src: 'checkStoredAuth',
|
|
662
|
+
onDone: [
|
|
663
|
+
{
|
|
664
|
+
target: 'fetchingStagingCredentials',
|
|
665
|
+
guard: ({ event }) => event.output === true,
|
|
666
|
+
},
|
|
667
|
+
{ target: 'runningDeviceAuth' },
|
|
668
|
+
],
|
|
669
|
+
onError: {
|
|
670
|
+
target: 'runningDeviceAuth',
|
|
671
|
+
},
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
// Step 6: Run device authorization flow
|
|
675
|
+
runningDeviceAuth: {
|
|
676
|
+
entry: ['emitDeviceAuthStart'],
|
|
677
|
+
invoke: {
|
|
678
|
+
id: 'runDeviceAuth',
|
|
679
|
+
src: 'runDeviceAuth',
|
|
680
|
+
input: ({ context }) => ({ emitter: context.emitter }),
|
|
681
|
+
onDone: {
|
|
682
|
+
target: 'fetchingStagingCredentials',
|
|
683
|
+
actions: [
|
|
684
|
+
'emitDeviceAuthSuccess',
|
|
685
|
+
assign({
|
|
686
|
+
deviceAuth: ({ event }) => {
|
|
687
|
+
const output = event.output;
|
|
688
|
+
return {
|
|
689
|
+
verificationUri: output.deviceAuth.verification_uri,
|
|
690
|
+
verificationUriComplete: output.deviceAuth.verification_uri_complete,
|
|
691
|
+
userCode: output.deviceAuth.user_code,
|
|
692
|
+
};
|
|
693
|
+
},
|
|
694
|
+
}),
|
|
695
|
+
],
|
|
696
|
+
},
|
|
697
|
+
onError: {
|
|
698
|
+
target: 'promptingManual',
|
|
699
|
+
actions: ['assignError', 'emitDeviceAuthError'],
|
|
700
|
+
},
|
|
701
|
+
},
|
|
702
|
+
},
|
|
703
|
+
// Step 7: Fetch staging credentials from API
|
|
704
|
+
fetchingStagingCredentials: {
|
|
705
|
+
entry: ['emitStagingFetching'],
|
|
706
|
+
invoke: {
|
|
707
|
+
id: 'fetchStagingCredentials',
|
|
708
|
+
src: 'fetchStagingCredentials',
|
|
709
|
+
onDone: {
|
|
710
|
+
target: '#wizard.configuring',
|
|
711
|
+
actions: [
|
|
712
|
+
assign({
|
|
713
|
+
credentials: ({ event }) => {
|
|
714
|
+
const staging = event.output;
|
|
715
|
+
return { clientId: staging.clientId, apiKey: staging.apiKey };
|
|
716
|
+
},
|
|
717
|
+
credentialSource: ({ context }) => context.deviceAuth ? 'device' : 'stored',
|
|
718
|
+
}),
|
|
719
|
+
'emitStagingSuccess',
|
|
720
|
+
{ type: 'emitStateExit', params: { state: 'gatheringCredentials' } },
|
|
721
|
+
],
|
|
722
|
+
},
|
|
723
|
+
onError: {
|
|
724
|
+
target: 'promptingManual',
|
|
725
|
+
actions: ['assignError', 'emitStagingError'],
|
|
726
|
+
},
|
|
727
|
+
},
|
|
728
|
+
},
|
|
729
|
+
// Step 8: Manual fallback
|
|
730
|
+
promptingManual: {
|
|
314
731
|
entry: ['emitCredentialsGathering'],
|
|
315
732
|
on: {
|
|
316
733
|
CREDENTIALS_SUBMITTED: {
|
|
317
734
|
target: '#wizard.configuring',
|
|
318
|
-
actions: [
|
|
735
|
+
actions: [
|
|
736
|
+
'assignCredentials',
|
|
737
|
+
assign({ credentialSource: () => 'manual' }),
|
|
738
|
+
{ type: 'emitStateExit', params: { state: 'gatheringCredentials' } },
|
|
739
|
+
],
|
|
740
|
+
},
|
|
741
|
+
RETRY_AUTH: {
|
|
742
|
+
target: 'runningDeviceAuth',
|
|
319
743
|
},
|
|
320
744
|
CANCEL: {
|
|
321
745
|
target: '#wizard.cancelled',
|
|
@@ -347,37 +771,208 @@ export const wizardMachine = setup({
|
|
|
347
771
|
id: 'runAgent',
|
|
348
772
|
src: 'runAgent',
|
|
349
773
|
input: ({ context }) => ({ context }),
|
|
350
|
-
onDone:
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
({
|
|
774
|
+
onDone: [
|
|
775
|
+
{
|
|
776
|
+
target: 'error',
|
|
777
|
+
guard: ({ event }) => {
|
|
354
778
|
const output = event.output;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
|
|
779
|
+
return !output.success;
|
|
780
|
+
},
|
|
781
|
+
actions: [
|
|
782
|
+
({ context, event }) => {
|
|
783
|
+
const output = event.output;
|
|
360
784
|
context.emitter.emit('agent:failure', {
|
|
361
785
|
message: output.error?.message ?? 'Agent failed',
|
|
362
786
|
});
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
787
|
+
},
|
|
788
|
+
assign({
|
|
789
|
+
error: ({ event }) => {
|
|
790
|
+
const output = event.output;
|
|
791
|
+
return output.error ?? new Error('Agent failed');
|
|
792
|
+
},
|
|
793
|
+
}),
|
|
794
|
+
{ type: 'emitStateExit', params: { state: 'runningAgent' } },
|
|
795
|
+
],
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
target: 'postInstall',
|
|
799
|
+
actions: [
|
|
800
|
+
assign({
|
|
801
|
+
agentSummary: ({ event }) => {
|
|
802
|
+
const output = event.output;
|
|
803
|
+
return output.summary;
|
|
804
|
+
},
|
|
805
|
+
}),
|
|
806
|
+
({ context, event }) => {
|
|
807
|
+
const output = event.output;
|
|
808
|
+
context.emitter.emit('agent:success', { summary: output.summary });
|
|
809
|
+
},
|
|
810
|
+
{ type: 'emitStateExit', params: { state: 'runningAgent' } },
|
|
811
|
+
],
|
|
812
|
+
},
|
|
813
|
+
],
|
|
372
814
|
onError: {
|
|
373
815
|
target: 'error',
|
|
374
816
|
actions: ['assignError', 'emitAgentFailure', { type: 'emitStateExit', params: { state: 'runningAgent' } }],
|
|
375
817
|
},
|
|
376
818
|
},
|
|
377
819
|
},
|
|
820
|
+
postInstall: {
|
|
821
|
+
initial: 'checking',
|
|
822
|
+
entry: [{ type: 'emitStateEnter', params: { state: 'postInstall' } }],
|
|
823
|
+
states: {
|
|
824
|
+
checking: {
|
|
825
|
+
always: [
|
|
826
|
+
{
|
|
827
|
+
target: '#wizard.complete',
|
|
828
|
+
guard: 'shouldSkipPostInstall',
|
|
829
|
+
},
|
|
830
|
+
{ target: 'detectingChanges' },
|
|
831
|
+
],
|
|
832
|
+
},
|
|
833
|
+
detectingChanges: {
|
|
834
|
+
invoke: {
|
|
835
|
+
id: 'detectChanges',
|
|
836
|
+
src: 'detectChanges',
|
|
837
|
+
onDone: [
|
|
838
|
+
{
|
|
839
|
+
target: 'promptingCommit',
|
|
840
|
+
guard: ({ event }) => event.output.hasChanges,
|
|
841
|
+
actions: ['assignChangedFiles', 'emitChangesDetected'],
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
target: 'done',
|
|
845
|
+
actions: ['emitNoChanges'],
|
|
846
|
+
},
|
|
847
|
+
],
|
|
848
|
+
onError: { target: 'done' },
|
|
849
|
+
},
|
|
850
|
+
},
|
|
851
|
+
promptingCommit: {
|
|
852
|
+
entry: ['emitCommitPrompt'],
|
|
853
|
+
on: {
|
|
854
|
+
COMMIT_APPROVED: { target: 'generatingCommitMessage' },
|
|
855
|
+
COMMIT_DECLINED: { target: 'done' },
|
|
856
|
+
CANCEL: { target: '#wizard.cancelled' },
|
|
857
|
+
},
|
|
858
|
+
},
|
|
859
|
+
generatingCommitMessage: {
|
|
860
|
+
entry: ['emitGeneratingCommitMessage'],
|
|
861
|
+
invoke: {
|
|
862
|
+
id: 'generateCommitMessage',
|
|
863
|
+
src: 'generateCommitMessage',
|
|
864
|
+
input: ({ context }) => ({
|
|
865
|
+
integration: context.integration ?? 'project',
|
|
866
|
+
files: context.changedFiles ?? [],
|
|
867
|
+
}),
|
|
868
|
+
onDone: {
|
|
869
|
+
target: 'committing',
|
|
870
|
+
actions: ['assignCommitMessage'],
|
|
871
|
+
},
|
|
872
|
+
},
|
|
873
|
+
},
|
|
874
|
+
committing: {
|
|
875
|
+
entry: ['emitCommitting'],
|
|
876
|
+
invoke: {
|
|
877
|
+
id: 'commitChanges',
|
|
878
|
+
src: 'commitChanges',
|
|
879
|
+
input: ({ context }) => ({
|
|
880
|
+
message: context.commitMessage ?? '',
|
|
881
|
+
cwd: context.options.installDir,
|
|
882
|
+
}),
|
|
883
|
+
onDone: {
|
|
884
|
+
target: 'checkingGhCli',
|
|
885
|
+
actions: ['emitCommitSuccess'],
|
|
886
|
+
},
|
|
887
|
+
onError: {
|
|
888
|
+
target: 'done',
|
|
889
|
+
actions: ['assignError', 'emitCommitFailed'],
|
|
890
|
+
},
|
|
891
|
+
},
|
|
892
|
+
},
|
|
893
|
+
checkingGhCli: {
|
|
894
|
+
always: [
|
|
895
|
+
{
|
|
896
|
+
target: 'promptingPr',
|
|
897
|
+
guard: 'hasGhCli',
|
|
898
|
+
},
|
|
899
|
+
{
|
|
900
|
+
target: 'showingManualInstructions',
|
|
901
|
+
},
|
|
902
|
+
],
|
|
903
|
+
},
|
|
904
|
+
promptingPr: {
|
|
905
|
+
entry: ['emitPrPrompt'],
|
|
906
|
+
on: {
|
|
907
|
+
PR_APPROVED: { target: 'generatingPrDescription' },
|
|
908
|
+
PR_DECLINED: { target: 'done' },
|
|
909
|
+
CANCEL: { target: '#wizard.cancelled' },
|
|
910
|
+
},
|
|
911
|
+
},
|
|
912
|
+
generatingPrDescription: {
|
|
913
|
+
entry: ['emitGeneratingPrDescription'],
|
|
914
|
+
invoke: {
|
|
915
|
+
id: 'generatePrDescription',
|
|
916
|
+
src: 'generatePrDescription',
|
|
917
|
+
input: ({ context }) => ({
|
|
918
|
+
integration: context.integration ?? 'project',
|
|
919
|
+
files: context.changedFiles ?? [],
|
|
920
|
+
commitMessage: context.commitMessage ?? '',
|
|
921
|
+
}),
|
|
922
|
+
onDone: {
|
|
923
|
+
target: 'pushing',
|
|
924
|
+
actions: ['assignPrDescription'],
|
|
925
|
+
},
|
|
926
|
+
},
|
|
927
|
+
},
|
|
928
|
+
pushing: {
|
|
929
|
+
entry: ['emitPushing'],
|
|
930
|
+
invoke: {
|
|
931
|
+
id: 'pushBranch',
|
|
932
|
+
src: 'pushBranch',
|
|
933
|
+
input: ({ context }) => ({ cwd: context.options.installDir }),
|
|
934
|
+
onDone: { target: 'creatingPr' },
|
|
935
|
+
onError: {
|
|
936
|
+
target: 'showingManualInstructions',
|
|
937
|
+
actions: ['assignError', 'emitPushFailed'],
|
|
938
|
+
},
|
|
939
|
+
},
|
|
940
|
+
},
|
|
941
|
+
creatingPr: {
|
|
942
|
+
entry: ['emitCreatingPr'],
|
|
943
|
+
invoke: {
|
|
944
|
+
id: 'createPr',
|
|
945
|
+
src: 'createPr',
|
|
946
|
+
input: ({ context }) => ({
|
|
947
|
+
title: context.commitMessage ?? '',
|
|
948
|
+
body: context.prDescription ?? '',
|
|
949
|
+
cwd: context.options.installDir,
|
|
950
|
+
}),
|
|
951
|
+
onDone: {
|
|
952
|
+
target: 'done',
|
|
953
|
+
actions: ['assignPrUrl', 'emitPrCreated'],
|
|
954
|
+
},
|
|
955
|
+
onError: {
|
|
956
|
+
target: 'done',
|
|
957
|
+
actions: ['assignError', 'emitPrFailed'],
|
|
958
|
+
},
|
|
959
|
+
},
|
|
960
|
+
},
|
|
961
|
+
showingManualInstructions: {
|
|
962
|
+
entry: ['emitManualInstructions'],
|
|
963
|
+
always: { target: 'done' },
|
|
964
|
+
},
|
|
965
|
+
done: {
|
|
966
|
+
type: 'final',
|
|
967
|
+
},
|
|
968
|
+
},
|
|
969
|
+
onDone: {
|
|
970
|
+
target: 'complete',
|
|
971
|
+
},
|
|
972
|
+
},
|
|
378
973
|
complete: {
|
|
379
974
|
type: 'final',
|
|
380
|
-
entry: { type: 'emitStateEnter', params: { state: 'complete' } },
|
|
975
|
+
entry: [{ type: 'emitStateEnter', params: { state: 'complete' } }, 'emitComplete'],
|
|
381
976
|
},
|
|
382
977
|
cancelled: {
|
|
383
978
|
type: 'final',
|