@harars/opencode-switch-openai-auth-plugin 0.1.3 → 0.1.5
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/index.js +85 -27
- package/dist/tui.js +85 -27
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -39,6 +39,7 @@ import { insert as _$insert } from "@opentui/solid";
|
|
|
39
39
|
import { setProp as _$setProp } from "@opentui/solid";
|
|
40
40
|
import { createElement as _$createElement } from "@opentui/solid";
|
|
41
41
|
import { TextAttributes } from "@opentui/core";
|
|
42
|
+
import { onMount } from "solid-js";
|
|
42
43
|
import { useKeyboard } from "@opentui/solid";
|
|
43
44
|
|
|
44
45
|
// src/login-helpers.ts
|
|
@@ -74,12 +75,23 @@ async function clip(text) {
|
|
|
74
75
|
function target(authz) {
|
|
75
76
|
return authz.instructions.match(/[A-Z0-9]{4}-[A-Z0-9]{4,5}/)?.[0] ?? authz.url;
|
|
76
77
|
}
|
|
78
|
+
function detail(err) {
|
|
79
|
+
if (err instanceof Error)
|
|
80
|
+
return err.message;
|
|
81
|
+
if (typeof err === "string")
|
|
82
|
+
return err;
|
|
83
|
+
try {
|
|
84
|
+
return JSON.stringify(err);
|
|
85
|
+
} catch {
|
|
86
|
+
return String(err);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
77
89
|
async function runOAuthCallback(callback, input) {
|
|
78
90
|
try {
|
|
79
91
|
const res = await callback(input);
|
|
80
|
-
return
|
|
81
|
-
} catch {
|
|
82
|
-
return false;
|
|
92
|
+
return res.error ? { ok: false, error: res.error } : { ok: true };
|
|
93
|
+
} catch (err) {
|
|
94
|
+
return { ok: false, error: detail(err) };
|
|
83
95
|
}
|
|
84
96
|
}
|
|
85
97
|
|
|
@@ -428,6 +440,8 @@ function visible(prompt, values) {
|
|
|
428
440
|
if (!prompt.when)
|
|
429
441
|
return true;
|
|
430
442
|
const cur = values[prompt.when.key];
|
|
443
|
+
if (cur === undefined)
|
|
444
|
+
return false;
|
|
431
445
|
if (prompt.when.op === "eq")
|
|
432
446
|
return cur === prompt.when.value;
|
|
433
447
|
return cur !== prompt.when.value;
|
|
@@ -437,6 +451,39 @@ function same(prev, next) {
|
|
|
437
451
|
return false;
|
|
438
452
|
return prev.refresh === next.refresh;
|
|
439
453
|
}
|
|
454
|
+
function unwrap(input) {
|
|
455
|
+
if (!input || typeof input !== "object") {
|
|
456
|
+
return {
|
|
457
|
+
ok: true,
|
|
458
|
+
data: input
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
if ("error" in input && input.error !== undefined) {
|
|
462
|
+
return {
|
|
463
|
+
ok: false,
|
|
464
|
+
error: input.error
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
if ("data" in input) {
|
|
468
|
+
return input.data === undefined ? {
|
|
469
|
+
ok: false,
|
|
470
|
+
error: "Missing response data"
|
|
471
|
+
} : {
|
|
472
|
+
ok: true,
|
|
473
|
+
data: input.data
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
ok: true,
|
|
478
|
+
data: input
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
async function authMethods(api) {
|
|
482
|
+
const res = unwrap(await api.client.provider.auth());
|
|
483
|
+
if (!res.ok)
|
|
484
|
+
return [];
|
|
485
|
+
return res.data.openai ?? [];
|
|
486
|
+
}
|
|
440
487
|
function bind(api, authz) {
|
|
441
488
|
useKeyboard((evt) => {
|
|
442
489
|
if (evt.name !== "c" || evt.ctrl || evt.meta)
|
|
@@ -451,6 +498,9 @@ function bind(api, authz) {
|
|
|
451
498
|
}
|
|
452
499
|
function WaitView(props) {
|
|
453
500
|
bind(props.api, props.authz);
|
|
501
|
+
onMount(() => {
|
|
502
|
+
props.run();
|
|
503
|
+
});
|
|
454
504
|
return (() => {
|
|
455
505
|
var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("text"), _el$4 = _$createElement("text"), _el$5 = _$createElement("text"), _el$7 = _$createElement("text");
|
|
456
506
|
_$insertNode(_el$, _el$2);
|
|
@@ -501,9 +551,9 @@ function wait(api, title, authz, run) {
|
|
|
501
551
|
api.ui.dialog.replace(() => _$createComponent(WaitView, {
|
|
502
552
|
api,
|
|
503
553
|
title,
|
|
504
|
-
authz
|
|
554
|
+
authz,
|
|
555
|
+
run
|
|
505
556
|
}));
|
|
506
|
-
run();
|
|
507
557
|
}
|
|
508
558
|
async function choose(api, methods) {
|
|
509
559
|
if (methods.length === 1)
|
|
@@ -629,19 +679,25 @@ async function code(api, index, method, authz) {
|
|
|
629
679
|
},
|
|
630
680
|
authz,
|
|
631
681
|
onConfirm: async (value) => {
|
|
632
|
-
resolve(await runOAuthCallback(api.client.provider.oauth.callback, {
|
|
682
|
+
resolve(await runOAuthCallback((input) => api.client.provider.oauth.callback(input), {
|
|
633
683
|
providerID: "openai",
|
|
634
684
|
method: index,
|
|
635
685
|
code: value
|
|
636
686
|
}));
|
|
637
687
|
},
|
|
638
|
-
onCancel: () => resolve(
|
|
639
|
-
|
|
688
|
+
onCancel: () => resolve({
|
|
689
|
+
ok: false,
|
|
690
|
+
error: "Cancelled"
|
|
691
|
+
})
|
|
692
|
+
}), () => resolve({
|
|
693
|
+
ok: false,
|
|
694
|
+
error: "Cancelled"
|
|
695
|
+
}));
|
|
640
696
|
});
|
|
641
|
-
if (!ok) {
|
|
697
|
+
if (!ok.ok) {
|
|
642
698
|
api.ui.toast({
|
|
643
699
|
variant: "error",
|
|
644
|
-
message:
|
|
700
|
+
message: `Login failed: ${detail(ok.error)}`
|
|
645
701
|
});
|
|
646
702
|
return false;
|
|
647
703
|
}
|
|
@@ -651,16 +707,16 @@ async function auto(api, index, method, authz) {
|
|
|
651
707
|
const prev = await readCurrentAuth();
|
|
652
708
|
const ok = await new Promise((resolve) => {
|
|
653
709
|
wait(api, method.label, authz, async () => {
|
|
654
|
-
resolve(await runOAuthCallback(api.client.provider.oauth.callback, {
|
|
710
|
+
resolve(await runOAuthCallback((input) => api.client.provider.oauth.callback(input), {
|
|
655
711
|
providerID: "openai",
|
|
656
712
|
method: index
|
|
657
713
|
}));
|
|
658
714
|
});
|
|
659
715
|
});
|
|
660
|
-
if (!ok) {
|
|
716
|
+
if (!ok.ok) {
|
|
661
717
|
api.ui.toast({
|
|
662
718
|
variant: "error",
|
|
663
|
-
message:
|
|
719
|
+
message: `Login failed: ${detail(ok.error)}`
|
|
664
720
|
});
|
|
665
721
|
return false;
|
|
666
722
|
}
|
|
@@ -668,17 +724,15 @@ async function auto(api, index, method, authz) {
|
|
|
668
724
|
}
|
|
669
725
|
async function hasLogin(api) {
|
|
670
726
|
try {
|
|
671
|
-
|
|
672
|
-
const methods = res.data?.openai ?? [];
|
|
673
|
-
return methods.some((item) => item.type === "oauth");
|
|
727
|
+
return (await authMethods(api)).some((item) => item.type === "oauth");
|
|
674
728
|
} catch {
|
|
675
729
|
return false;
|
|
676
730
|
}
|
|
677
731
|
}
|
|
678
732
|
async function loginOpenAI(api) {
|
|
679
733
|
try {
|
|
680
|
-
const
|
|
681
|
-
const methods =
|
|
734
|
+
const available = await authMethods(api);
|
|
735
|
+
const methods = available.map((method2, index2) => ({
|
|
682
736
|
method: method2,
|
|
683
737
|
index: index2
|
|
684
738
|
})).filter((item) => item.method.type === "oauth");
|
|
@@ -694,18 +748,22 @@ async function loginOpenAI(api) {
|
|
|
694
748
|
return false;
|
|
695
749
|
const picked = methods[index];
|
|
696
750
|
const method = picked.method;
|
|
697
|
-
|
|
698
|
-
if (method.prompts?.length
|
|
699
|
-
|
|
700
|
-
|
|
751
|
+
let inputs;
|
|
752
|
+
if (method.prompts?.length) {
|
|
753
|
+
const value = await prompts(api, method.label, method);
|
|
754
|
+
if (!value)
|
|
755
|
+
return false;
|
|
756
|
+
inputs = value;
|
|
757
|
+
}
|
|
758
|
+
const authz = unwrap(await api.client.provider.oauth.authorize({
|
|
701
759
|
providerID: "openai",
|
|
702
760
|
method: picked.index,
|
|
703
761
|
inputs
|
|
704
|
-
});
|
|
705
|
-
if (
|
|
762
|
+
}));
|
|
763
|
+
if (!authz.ok) {
|
|
706
764
|
api.ui.toast({
|
|
707
765
|
variant: "error",
|
|
708
|
-
message:
|
|
766
|
+
message: `Login failed: ${detail(authz.error)}`
|
|
709
767
|
});
|
|
710
768
|
return false;
|
|
711
769
|
}
|
|
@@ -718,10 +776,10 @@ async function loginOpenAI(api) {
|
|
|
718
776
|
message: "Unsupported auth method"
|
|
719
777
|
});
|
|
720
778
|
return false;
|
|
721
|
-
} catch {
|
|
779
|
+
} catch (err) {
|
|
722
780
|
api.ui.toast({
|
|
723
781
|
variant: "error",
|
|
724
|
-
message:
|
|
782
|
+
message: `Login failed: ${detail(err)}`
|
|
725
783
|
});
|
|
726
784
|
return false;
|
|
727
785
|
}
|
package/dist/tui.js
CHANGED
|
@@ -39,6 +39,7 @@ import { insert as _$insert } from "@opentui/solid";
|
|
|
39
39
|
import { setProp as _$setProp } from "@opentui/solid";
|
|
40
40
|
import { createElement as _$createElement } from "@opentui/solid";
|
|
41
41
|
import { TextAttributes } from "@opentui/core";
|
|
42
|
+
import { onMount } from "solid-js";
|
|
42
43
|
import { useKeyboard } from "@opentui/solid";
|
|
43
44
|
|
|
44
45
|
// src/login-helpers.ts
|
|
@@ -74,12 +75,23 @@ async function clip(text) {
|
|
|
74
75
|
function target(authz) {
|
|
75
76
|
return authz.instructions.match(/[A-Z0-9]{4}-[A-Z0-9]{4,5}/)?.[0] ?? authz.url;
|
|
76
77
|
}
|
|
78
|
+
function detail(err) {
|
|
79
|
+
if (err instanceof Error)
|
|
80
|
+
return err.message;
|
|
81
|
+
if (typeof err === "string")
|
|
82
|
+
return err;
|
|
83
|
+
try {
|
|
84
|
+
return JSON.stringify(err);
|
|
85
|
+
} catch {
|
|
86
|
+
return String(err);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
77
89
|
async function runOAuthCallback(callback, input) {
|
|
78
90
|
try {
|
|
79
91
|
const res = await callback(input);
|
|
80
|
-
return
|
|
81
|
-
} catch {
|
|
82
|
-
return false;
|
|
92
|
+
return res.error ? { ok: false, error: res.error } : { ok: true };
|
|
93
|
+
} catch (err) {
|
|
94
|
+
return { ok: false, error: detail(err) };
|
|
83
95
|
}
|
|
84
96
|
}
|
|
85
97
|
|
|
@@ -428,6 +440,8 @@ function visible(prompt, values) {
|
|
|
428
440
|
if (!prompt.when)
|
|
429
441
|
return true;
|
|
430
442
|
const cur = values[prompt.when.key];
|
|
443
|
+
if (cur === undefined)
|
|
444
|
+
return false;
|
|
431
445
|
if (prompt.when.op === "eq")
|
|
432
446
|
return cur === prompt.when.value;
|
|
433
447
|
return cur !== prompt.when.value;
|
|
@@ -437,6 +451,39 @@ function same(prev, next) {
|
|
|
437
451
|
return false;
|
|
438
452
|
return prev.refresh === next.refresh;
|
|
439
453
|
}
|
|
454
|
+
function unwrap(input) {
|
|
455
|
+
if (!input || typeof input !== "object") {
|
|
456
|
+
return {
|
|
457
|
+
ok: true,
|
|
458
|
+
data: input
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
if ("error" in input && input.error !== undefined) {
|
|
462
|
+
return {
|
|
463
|
+
ok: false,
|
|
464
|
+
error: input.error
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
if ("data" in input) {
|
|
468
|
+
return input.data === undefined ? {
|
|
469
|
+
ok: false,
|
|
470
|
+
error: "Missing response data"
|
|
471
|
+
} : {
|
|
472
|
+
ok: true,
|
|
473
|
+
data: input.data
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
ok: true,
|
|
478
|
+
data: input
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
async function authMethods(api) {
|
|
482
|
+
const res = unwrap(await api.client.provider.auth());
|
|
483
|
+
if (!res.ok)
|
|
484
|
+
return [];
|
|
485
|
+
return res.data.openai ?? [];
|
|
486
|
+
}
|
|
440
487
|
function bind(api, authz) {
|
|
441
488
|
useKeyboard((evt) => {
|
|
442
489
|
if (evt.name !== "c" || evt.ctrl || evt.meta)
|
|
@@ -451,6 +498,9 @@ function bind(api, authz) {
|
|
|
451
498
|
}
|
|
452
499
|
function WaitView(props) {
|
|
453
500
|
bind(props.api, props.authz);
|
|
501
|
+
onMount(() => {
|
|
502
|
+
props.run();
|
|
503
|
+
});
|
|
454
504
|
return (() => {
|
|
455
505
|
var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("text"), _el$4 = _$createElement("text"), _el$5 = _$createElement("text"), _el$7 = _$createElement("text");
|
|
456
506
|
_$insertNode(_el$, _el$2);
|
|
@@ -501,9 +551,9 @@ function wait(api, title, authz, run) {
|
|
|
501
551
|
api.ui.dialog.replace(() => _$createComponent(WaitView, {
|
|
502
552
|
api,
|
|
503
553
|
title,
|
|
504
|
-
authz
|
|
554
|
+
authz,
|
|
555
|
+
run
|
|
505
556
|
}));
|
|
506
|
-
run();
|
|
507
557
|
}
|
|
508
558
|
async function choose(api, methods) {
|
|
509
559
|
if (methods.length === 1)
|
|
@@ -629,19 +679,25 @@ async function code(api, index, method, authz) {
|
|
|
629
679
|
},
|
|
630
680
|
authz,
|
|
631
681
|
onConfirm: async (value) => {
|
|
632
|
-
resolve(await runOAuthCallback(api.client.provider.oauth.callback, {
|
|
682
|
+
resolve(await runOAuthCallback((input) => api.client.provider.oauth.callback(input), {
|
|
633
683
|
providerID: "openai",
|
|
634
684
|
method: index,
|
|
635
685
|
code: value
|
|
636
686
|
}));
|
|
637
687
|
},
|
|
638
|
-
onCancel: () => resolve(
|
|
639
|
-
|
|
688
|
+
onCancel: () => resolve({
|
|
689
|
+
ok: false,
|
|
690
|
+
error: "Cancelled"
|
|
691
|
+
})
|
|
692
|
+
}), () => resolve({
|
|
693
|
+
ok: false,
|
|
694
|
+
error: "Cancelled"
|
|
695
|
+
}));
|
|
640
696
|
});
|
|
641
|
-
if (!ok) {
|
|
697
|
+
if (!ok.ok) {
|
|
642
698
|
api.ui.toast({
|
|
643
699
|
variant: "error",
|
|
644
|
-
message:
|
|
700
|
+
message: `Login failed: ${detail(ok.error)}`
|
|
645
701
|
});
|
|
646
702
|
return false;
|
|
647
703
|
}
|
|
@@ -651,16 +707,16 @@ async function auto(api, index, method, authz) {
|
|
|
651
707
|
const prev = await readCurrentAuth();
|
|
652
708
|
const ok = await new Promise((resolve) => {
|
|
653
709
|
wait(api, method.label, authz, async () => {
|
|
654
|
-
resolve(await runOAuthCallback(api.client.provider.oauth.callback, {
|
|
710
|
+
resolve(await runOAuthCallback((input) => api.client.provider.oauth.callback(input), {
|
|
655
711
|
providerID: "openai",
|
|
656
712
|
method: index
|
|
657
713
|
}));
|
|
658
714
|
});
|
|
659
715
|
});
|
|
660
|
-
if (!ok) {
|
|
716
|
+
if (!ok.ok) {
|
|
661
717
|
api.ui.toast({
|
|
662
718
|
variant: "error",
|
|
663
|
-
message:
|
|
719
|
+
message: `Login failed: ${detail(ok.error)}`
|
|
664
720
|
});
|
|
665
721
|
return false;
|
|
666
722
|
}
|
|
@@ -668,17 +724,15 @@ async function auto(api, index, method, authz) {
|
|
|
668
724
|
}
|
|
669
725
|
async function hasLogin(api) {
|
|
670
726
|
try {
|
|
671
|
-
|
|
672
|
-
const methods = res.data?.openai ?? [];
|
|
673
|
-
return methods.some((item) => item.type === "oauth");
|
|
727
|
+
return (await authMethods(api)).some((item) => item.type === "oauth");
|
|
674
728
|
} catch {
|
|
675
729
|
return false;
|
|
676
730
|
}
|
|
677
731
|
}
|
|
678
732
|
async function loginOpenAI(api) {
|
|
679
733
|
try {
|
|
680
|
-
const
|
|
681
|
-
const methods =
|
|
734
|
+
const available = await authMethods(api);
|
|
735
|
+
const methods = available.map((method2, index2) => ({
|
|
682
736
|
method: method2,
|
|
683
737
|
index: index2
|
|
684
738
|
})).filter((item) => item.method.type === "oauth");
|
|
@@ -694,18 +748,22 @@ async function loginOpenAI(api) {
|
|
|
694
748
|
return false;
|
|
695
749
|
const picked = methods[index];
|
|
696
750
|
const method = picked.method;
|
|
697
|
-
|
|
698
|
-
if (method.prompts?.length
|
|
699
|
-
|
|
700
|
-
|
|
751
|
+
let inputs;
|
|
752
|
+
if (method.prompts?.length) {
|
|
753
|
+
const value = await prompts(api, method.label, method);
|
|
754
|
+
if (!value)
|
|
755
|
+
return false;
|
|
756
|
+
inputs = value;
|
|
757
|
+
}
|
|
758
|
+
const authz = unwrap(await api.client.provider.oauth.authorize({
|
|
701
759
|
providerID: "openai",
|
|
702
760
|
method: picked.index,
|
|
703
761
|
inputs
|
|
704
|
-
});
|
|
705
|
-
if (
|
|
762
|
+
}));
|
|
763
|
+
if (!authz.ok) {
|
|
706
764
|
api.ui.toast({
|
|
707
765
|
variant: "error",
|
|
708
|
-
message:
|
|
766
|
+
message: `Login failed: ${detail(authz.error)}`
|
|
709
767
|
});
|
|
710
768
|
return false;
|
|
711
769
|
}
|
|
@@ -718,10 +776,10 @@ async function loginOpenAI(api) {
|
|
|
718
776
|
message: "Unsupported auth method"
|
|
719
777
|
});
|
|
720
778
|
return false;
|
|
721
|
-
} catch {
|
|
779
|
+
} catch (err) {
|
|
722
780
|
api.ui.toast({
|
|
723
781
|
variant: "error",
|
|
724
|
-
message:
|
|
782
|
+
message: `Login failed: ${detail(err)}`
|
|
725
783
|
});
|
|
726
784
|
return false;
|
|
727
785
|
}
|