@displaydev/cli 0.2.1 → 0.3.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 +31 -0
- package/dist/main.js +130 -55
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -18,6 +18,37 @@ dsp login
|
|
|
18
18
|
export DISPLAYDEV_API_KEY=sk_live_...
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
### Agent-native login
|
|
22
|
+
|
|
23
|
+
`dsp login` is designed to be driven entirely by an AI agent that has inbox
|
|
24
|
+
access (Gmail/IMAP via MCP, etc.) — no human-in-the-loop required.
|
|
25
|
+
|
|
26
|
+
The command adapts to its environment:
|
|
27
|
+
|
|
28
|
+
| Invocation | Behavior |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `dsp login --email you@acme.com` **(TTY)** | Sends OTP, prompts for the code in the terminal. |
|
|
31
|
+
| `dsp login --email you@acme.com` **(non-TTY)** | Sends OTP and exits 0. Caller reads the code (e.g. from inbox) and re-invokes. |
|
|
32
|
+
| `dsp login --email you@acme.com --code 123456` | Verifies the code, persists the token, exits. |
|
|
33
|
+
|
|
34
|
+
For structured output that doesn't rely on prose parsing:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
dsp login --email you@acme.com --json
|
|
38
|
+
# → {"status":"otp_sent","email":"you@acme.com",
|
|
39
|
+
# "next":{"command":"dsp login","args":["--email","you@acme.com","--code","<code>"]}}
|
|
40
|
+
|
|
41
|
+
dsp login --email you@acme.com --code 123456 --json
|
|
42
|
+
# → {"status":"authenticated","method":"otp","email":"you@acme.com"}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**OTP email format** is stable and regex-parseable:
|
|
46
|
+
|
|
47
|
+
- Subject: `123456 is your display.dev sign-in code`
|
|
48
|
+
- Body: `Your verification code is: 123456`
|
|
49
|
+
|
|
50
|
+
Extraction pattern: `/Your verification code is: (\d{6})/`.
|
|
51
|
+
|
|
21
52
|
## Usage
|
|
22
53
|
|
|
23
54
|
```bash
|
package/dist/main.js
CHANGED
|
@@ -513,12 +513,28 @@ function sleep(ms) {
|
|
|
513
513
|
});
|
|
514
514
|
}
|
|
515
515
|
// --- login ---
|
|
516
|
-
program.command('login').description('Authenticate with display.dev').option('--email <email>', 'Email address').option('--api-key [key]', 'Authenticate with an API key').action(function(opts) {
|
|
516
|
+
program.command('login').description('Authenticate with display.dev').option('--email <email>', 'Email address').option('--code <code>', 'OTP code (verify step; pair with --email)').option('--api-key [key]', 'Authenticate with an API key').option('--json', 'Machine-readable output (structured status, no prose)').action(function(opts) {
|
|
517
517
|
return _async_to_generator(function() {
|
|
518
|
-
var _process_env_DISPLAYDEV_API_URL, apiUrl, client, key, rl, validation, email, rl1, method, check, unused, err, msg,
|
|
518
|
+
var _process_env_DISPLAYDEV_API_URL, emit, emitErr, apiUrl, client, key, rl, validation, email, rl1, method, check, unused, err, msg, code, rl2, result, unused1, deviceResult, unused2, device_code, verification_uri_complete, initialInterval, interval, tokenResult, unused3, _$err;
|
|
519
519
|
return _ts_generator(this, function(_state) {
|
|
520
520
|
switch(_state.label){
|
|
521
521
|
case 0:
|
|
522
|
+
// Small helper: emit either prose (default) or a JSON line. Agents use
|
|
523
|
+
// --json to avoid string-matching against the prose hints.
|
|
524
|
+
emit = function emit(prose, json) {
|
|
525
|
+
if (opts.json) {
|
|
526
|
+
console.log(JSON.stringify(json));
|
|
527
|
+
} else {
|
|
528
|
+
console.log(prose);
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
emitErr = function emitErr(prose, json) {
|
|
532
|
+
if (opts.json) {
|
|
533
|
+
console.log(JSON.stringify(json));
|
|
534
|
+
} else {
|
|
535
|
+
console.error(prose);
|
|
536
|
+
}
|
|
537
|
+
};
|
|
522
538
|
apiUrl = (_process_env_DISPLAYDEV_API_URL = process.env.DISPLAYDEV_API_URL) !== null && _process_env_DISPLAYDEV_API_URL !== void 0 ? _process_env_DISPLAYDEV_API_URL : DEFAULT_API_URL;
|
|
523
539
|
client = new ApiClient({
|
|
524
540
|
baseUrl: apiUrl,
|
|
@@ -610,7 +626,10 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
610
626
|
case 6:
|
|
611
627
|
validation = _state.sent();
|
|
612
628
|
if (validation === 'invalid') {
|
|
613
|
-
|
|
629
|
+
emitErr('Invalid API key. Check the key and try again.', {
|
|
630
|
+
status: 'error',
|
|
631
|
+
error: 'invalid_api_key'
|
|
632
|
+
});
|
|
614
633
|
process.exit(1);
|
|
615
634
|
}
|
|
616
635
|
if (validation === 'network_error') {
|
|
@@ -625,7 +644,10 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
625
644
|
];
|
|
626
645
|
case 7:
|
|
627
646
|
_state.sent();
|
|
628
|
-
|
|
647
|
+
emit('Authenticated.', {
|
|
648
|
+
status: 'authenticated',
|
|
649
|
+
method: 'api_key'
|
|
650
|
+
});
|
|
629
651
|
return [
|
|
630
652
|
2
|
|
631
653
|
];
|
|
@@ -684,7 +706,11 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
684
706
|
case 14:
|
|
685
707
|
if (!(method === 'otp')) return [
|
|
686
708
|
3,
|
|
687
|
-
|
|
709
|
+
27
|
|
710
|
+
];
|
|
711
|
+
if (!!opts.code) return [
|
|
712
|
+
3,
|
|
713
|
+
19
|
|
688
714
|
];
|
|
689
715
|
_state.label = 15;
|
|
690
716
|
case 15:
|
|
@@ -708,9 +734,15 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
708
734
|
err = _state.sent();
|
|
709
735
|
msg = _instanceof(err, Error) ? err.message : 'Something went wrong';
|
|
710
736
|
if (msg.includes('requires SSO')) {
|
|
711
|
-
|
|
737
|
+
emitErr('Your organization requires SSO. Run dsp login again.', {
|
|
738
|
+
status: 'error',
|
|
739
|
+
error: 'sso_required'
|
|
740
|
+
});
|
|
712
741
|
} else {
|
|
713
|
-
|
|
742
|
+
emitErr('Something went wrong. Check your connection and try again.', {
|
|
743
|
+
status: 'error',
|
|
744
|
+
error: 'send_failed'
|
|
745
|
+
});
|
|
714
746
|
}
|
|
715
747
|
process.exit(1);
|
|
716
748
|
return [
|
|
@@ -718,11 +750,47 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
718
750
|
18
|
|
719
751
|
];
|
|
720
752
|
case 18:
|
|
721
|
-
console.log("Code sent to ".concat(email));
|
|
722
753
|
if (!process.stdin.isTTY) {
|
|
723
|
-
|
|
724
|
-
|
|
754
|
+
// Non-interactive: exit after sending. The caller (typically an
|
|
755
|
+
// agent) will collect the OTP from the user and re-invoke with --code.
|
|
756
|
+
if (opts.json) {
|
|
757
|
+
console.log(JSON.stringify({
|
|
758
|
+
status: 'otp_sent',
|
|
759
|
+
email: email,
|
|
760
|
+
next: {
|
|
761
|
+
command: 'dsp login',
|
|
762
|
+
args: [
|
|
763
|
+
'--email',
|
|
764
|
+
email,
|
|
765
|
+
'--code',
|
|
766
|
+
'<code>'
|
|
767
|
+
]
|
|
768
|
+
}
|
|
769
|
+
}));
|
|
770
|
+
} else {
|
|
771
|
+
console.log("Code sent to ".concat(email));
|
|
772
|
+
console.log("Re-run with --code <6-digit code> to complete login.");
|
|
773
|
+
}
|
|
774
|
+
return [
|
|
775
|
+
2
|
|
776
|
+
];
|
|
725
777
|
}
|
|
778
|
+
// TTY path prints the same prose hint then prompts.
|
|
779
|
+
if (!opts.json) {
|
|
780
|
+
console.log("Code sent to ".concat(email));
|
|
781
|
+
}
|
|
782
|
+
_state.label = 19;
|
|
783
|
+
case 19:
|
|
784
|
+
if (!opts.code) return [
|
|
785
|
+
3,
|
|
786
|
+
20
|
|
787
|
+
];
|
|
788
|
+
code = opts.code;
|
|
789
|
+
return [
|
|
790
|
+
3,
|
|
791
|
+
22
|
|
792
|
+
];
|
|
793
|
+
case 20:
|
|
726
794
|
rl2 = createInterface({
|
|
727
795
|
input: process.stdin,
|
|
728
796
|
output: process.stdout
|
|
@@ -731,22 +799,22 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
731
799
|
4,
|
|
732
800
|
rl2.question('Enter the 6-digit code: ')
|
|
733
801
|
];
|
|
734
|
-
case
|
|
802
|
+
case 21:
|
|
735
803
|
code = _state.sent();
|
|
736
804
|
rl2.close();
|
|
737
|
-
_state.label =
|
|
738
|
-
case
|
|
805
|
+
_state.label = 22;
|
|
806
|
+
case 22:
|
|
739
807
|
_state.trys.push([
|
|
740
|
-
|
|
741
|
-
|
|
808
|
+
22,
|
|
809
|
+
25,
|
|
742
810
|
,
|
|
743
|
-
|
|
811
|
+
26
|
|
744
812
|
]);
|
|
745
813
|
return [
|
|
746
814
|
4,
|
|
747
815
|
client.verifyOtp(email, code.trim())
|
|
748
816
|
];
|
|
749
|
-
case
|
|
817
|
+
case 23:
|
|
750
818
|
result = _state.sent();
|
|
751
819
|
return [
|
|
752
820
|
4,
|
|
@@ -755,56 +823,63 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
755
823
|
apiUrl: apiUrl
|
|
756
824
|
})
|
|
757
825
|
];
|
|
758
|
-
case
|
|
826
|
+
case 24:
|
|
759
827
|
_state.sent();
|
|
760
|
-
|
|
828
|
+
emit("Logged in as ".concat(email), {
|
|
829
|
+
status: 'authenticated',
|
|
830
|
+
method: 'otp',
|
|
831
|
+
email: email
|
|
832
|
+
});
|
|
761
833
|
return [
|
|
762
834
|
3,
|
|
763
|
-
|
|
835
|
+
26
|
|
764
836
|
];
|
|
765
|
-
case
|
|
837
|
+
case 25:
|
|
766
838
|
unused1 = _state.sent();
|
|
767
|
-
|
|
839
|
+
emitErr('Invalid or expired code. Try again.', {
|
|
840
|
+
status: 'error',
|
|
841
|
+
error: 'invalid_or_expired_code'
|
|
842
|
+
});
|
|
768
843
|
process.exit(1);
|
|
769
844
|
return [
|
|
770
845
|
3,
|
|
771
|
-
|
|
846
|
+
26
|
|
772
847
|
];
|
|
773
|
-
case
|
|
848
|
+
case 26:
|
|
774
849
|
return [
|
|
775
850
|
3,
|
|
776
|
-
|
|
851
|
+
40
|
|
777
852
|
];
|
|
778
|
-
case
|
|
853
|
+
case 27:
|
|
779
854
|
// --- Mode 2: SSO device flow ---
|
|
780
855
|
console.log('Your organization requires SSO. Opening browser...');
|
|
781
|
-
_state.label =
|
|
782
|
-
case
|
|
856
|
+
_state.label = 28;
|
|
857
|
+
case 28:
|
|
783
858
|
_state.trys.push([
|
|
784
|
-
26,
|
|
785
859
|
28,
|
|
860
|
+
30,
|
|
786
861
|
,
|
|
787
|
-
|
|
862
|
+
31
|
|
788
863
|
]);
|
|
789
864
|
return [
|
|
790
865
|
4,
|
|
791
866
|
client.requestDeviceCode('dsp-cli')
|
|
792
867
|
];
|
|
793
|
-
case
|
|
868
|
+
case 29:
|
|
794
869
|
deviceResult = _state.sent();
|
|
795
870
|
return [
|
|
796
871
|
3,
|
|
797
|
-
|
|
872
|
+
31
|
|
798
873
|
];
|
|
799
|
-
case
|
|
874
|
+
case 30:
|
|
800
875
|
unused2 = _state.sent();
|
|
801
876
|
console.error('Something went wrong. Check your connection and try again.');
|
|
802
877
|
process.exit(1);
|
|
803
878
|
return [
|
|
804
879
|
3,
|
|
805
|
-
|
|
880
|
+
31
|
|
806
881
|
];
|
|
807
|
-
case
|
|
882
|
+
case 31:
|
|
808
883
|
device_code = deviceResult.device_code, verification_uri_complete = deviceResult.verification_uri_complete, initialInterval = deviceResult.interval;
|
|
809
884
|
console.log();
|
|
810
885
|
console.log(" ".concat(verification_uri_complete));
|
|
@@ -813,48 +888,48 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
813
888
|
// Poll for token
|
|
814
889
|
interval = (initialInterval || 5) * 1000;
|
|
815
890
|
process.stdout.write('Waiting for authentication...');
|
|
816
|
-
_state.label =
|
|
817
|
-
case
|
|
891
|
+
_state.label = 32;
|
|
892
|
+
case 32:
|
|
818
893
|
if (!true) return [
|
|
819
894
|
3,
|
|
820
|
-
|
|
895
|
+
40
|
|
821
896
|
];
|
|
822
897
|
return [
|
|
823
898
|
4,
|
|
824
899
|
sleep(interval)
|
|
825
900
|
];
|
|
826
|
-
case
|
|
901
|
+
case 33:
|
|
827
902
|
_state.sent();
|
|
828
903
|
tokenResult = void 0;
|
|
829
|
-
_state.label =
|
|
830
|
-
case
|
|
904
|
+
_state.label = 34;
|
|
905
|
+
case 34:
|
|
831
906
|
_state.trys.push([
|
|
832
|
-
32,
|
|
833
907
|
34,
|
|
908
|
+
36,
|
|
834
909
|
,
|
|
835
|
-
|
|
910
|
+
37
|
|
836
911
|
]);
|
|
837
912
|
return [
|
|
838
913
|
4,
|
|
839
914
|
client.pollDeviceToken(device_code, 'dsp-cli')
|
|
840
915
|
];
|
|
841
|
-
case
|
|
916
|
+
case 35:
|
|
842
917
|
tokenResult = _state.sent();
|
|
843
918
|
return [
|
|
844
919
|
3,
|
|
845
|
-
|
|
920
|
+
37
|
|
846
921
|
];
|
|
847
|
-
case
|
|
922
|
+
case 36:
|
|
848
923
|
unused3 = _state.sent();
|
|
849
924
|
// Transient network error — retry on next interval
|
|
850
925
|
return [
|
|
851
926
|
3,
|
|
852
|
-
|
|
927
|
+
32
|
|
853
928
|
];
|
|
854
|
-
case
|
|
929
|
+
case 37:
|
|
855
930
|
if (!('access_token' in tokenResult)) return [
|
|
856
931
|
3,
|
|
857
|
-
|
|
932
|
+
39
|
|
858
933
|
];
|
|
859
934
|
console.log(' done');
|
|
860
935
|
return [
|
|
@@ -864,25 +939,25 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
864
939
|
apiUrl: apiUrl
|
|
865
940
|
})
|
|
866
941
|
];
|
|
867
|
-
case
|
|
942
|
+
case 38:
|
|
868
943
|
_state.sent();
|
|
869
944
|
console.log("Logged in as ".concat(email));
|
|
870
945
|
return [
|
|
871
946
|
2
|
|
872
947
|
];
|
|
873
|
-
case
|
|
948
|
+
case 39:
|
|
874
949
|
_$err = tokenResult;
|
|
875
950
|
if (_$err.error === 'authorization_pending') {
|
|
876
951
|
return [
|
|
877
952
|
3,
|
|
878
|
-
|
|
953
|
+
32
|
|
879
954
|
];
|
|
880
955
|
}
|
|
881
956
|
if (_$err.error === 'slow_down') {
|
|
882
957
|
interval += 5000;
|
|
883
958
|
return [
|
|
884
959
|
3,
|
|
885
|
-
|
|
960
|
+
32
|
|
886
961
|
];
|
|
887
962
|
}
|
|
888
963
|
if (_$err.error === 'access_denied') {
|
|
@@ -901,9 +976,9 @@ program.command('login').description('Authenticate with display.dev').option('--
|
|
|
901
976
|
process.exit(1);
|
|
902
977
|
return [
|
|
903
978
|
3,
|
|
904
|
-
|
|
979
|
+
32
|
|
905
980
|
];
|
|
906
|
-
case
|
|
981
|
+
case 40:
|
|
907
982
|
return [
|
|
908
983
|
2
|
|
909
984
|
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@displaydev/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dsp": "dist/main.js"
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "swc src -d dist --strip-leading-paths",
|
|
14
14
|
"typecheck": "tsgo --project tsconfig.json --noEmit",
|
|
15
|
+
"lint": "oxlint --deny-warnings .",
|
|
15
16
|
"test": "vitest run"
|
|
16
17
|
},
|
|
17
18
|
"dependencies": {
|