@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.
Files changed (3) hide show
  1. package/dist/index.js +85 -27
  2. package/dist/tui.js +85 -27
  3. 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 !res.error;
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(false)
639
- }), () => resolve(false));
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: "Login failed"
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: "Login failed"
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
- const res = await api.client.provider.auth();
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 auth = await api.client.provider.auth();
681
- const methods = (auth.data?.openai ?? []).map((method2, index2) => ({
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
- const inputs = await prompts(api, method.label, method);
698
- if (method.prompts?.length && !inputs)
699
- return false;
700
- const authz = await api.client.provider.oauth.authorize({
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 (authz.error || !authz.data) {
762
+ }));
763
+ if (!authz.ok) {
706
764
  api.ui.toast({
707
765
  variant: "error",
708
- message: "Login failed"
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: "Login failed"
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 !res.error;
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(false)
639
- }), () => resolve(false));
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: "Login failed"
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: "Login failed"
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
- const res = await api.client.provider.auth();
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 auth = await api.client.provider.auth();
681
- const methods = (auth.data?.openai ?? []).map((method2, index2) => ({
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
- const inputs = await prompts(api, method.label, method);
698
- if (method.prompts?.length && !inputs)
699
- return false;
700
- const authz = await api.client.provider.oauth.authorize({
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 (authz.error || !authz.data) {
762
+ }));
763
+ if (!authz.ok) {
706
764
  api.ui.toast({
707
765
  variant: "error",
708
- message: "Login failed"
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: "Login failed"
782
+ message: `Login failed: ${detail(err)}`
725
783
  });
726
784
  return false;
727
785
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harars/opencode-switch-openai-auth-plugin",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "OpenCode TUI plugin for switching saved OpenAI OAuth accounts",
5
5
  "repository": {
6
6
  "type": "git",