@burdenoff/microfe-vibecontrols 2026.527.16 → 2026.528.1

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 (52) hide show
  1. package/dist/components/gitops/GitOpsProviderPicker.js +29 -0
  2. package/dist/components/gitops/GitOpsProviderPicker.js.map +1 -0
  3. package/dist/components/gitops/GitOpsSetup.js +148 -102
  4. package/dist/components/gitops/GitOpsSetup.js.map +1 -1
  5. package/dist/components/gitops/VibeGitOpsTab.js +231 -223
  6. package/dist/components/gitops/VibeGitOpsTab.js.map +1 -1
  7. package/dist/components/gitops/types.js +65 -0
  8. package/dist/components/gitops/types.js.map +1 -0
  9. package/dist/components/security/SecurityEmptyState.js +2 -32
  10. package/dist/components/security/SecurityTabPanel.js +40 -97
  11. package/dist/components/security/SecurityTabPanel.js.map +1 -1
  12. package/dist/components/security/index.js +1 -6
  13. package/dist/components/security/types.js +3 -5
  14. package/dist/components/security/types.js.map +1 -1
  15. package/dist/components/settings/SettingsForm.js +30 -32
  16. package/dist/components/settings/SettingsForm.js.map +1 -1
  17. package/dist/components/settings/WorkspaceDefaultsSection.js +113 -118
  18. package/dist/components/settings/WorkspaceDefaultsSection.js.map +1 -1
  19. package/dist/components/shared/ConfirmDialog.js +51 -108
  20. package/dist/components/shared/ConfirmDialog.js.map +1 -1
  21. package/dist/components/shared/EmptyState.js +9 -102
  22. package/dist/components/shared/EmptyState.js.map +1 -1
  23. package/dist/components/shared/PageHeader.js +16 -47
  24. package/dist/components/shared/PageHeader.js.map +1 -1
  25. package/dist/components/tunnels/TunnelCreateWizard.js +17 -14
  26. package/dist/components/tunnels/TunnelCreateWizard.js.map +1 -1
  27. package/dist/constants/pluginCatalog.js +139 -4
  28. package/dist/constants/pluginCatalog.js.map +1 -1
  29. package/dist/hooks/useGitops.js +135 -0
  30. package/dist/hooks/useGitops.js.map +1 -0
  31. package/dist/pages/GettingStartedPage.js +6 -6
  32. package/dist/pages/PluginStandalonePage.js +12 -12
  33. package/dist/pages/VibeDetailsPage.js +4 -1
  34. package/dist/pages/VibeDetailsPage.js.map +1 -1
  35. package/dist/pages/VibesPage.js +304 -291
  36. package/dist/pages/VibesPage.js.map +1 -1
  37. package/dist/services/gitopsApi.js +128 -0
  38. package/dist/services/gitopsApi.js.map +1 -0
  39. package/package.json +2 -2
  40. package/dist/components/security/SecurityEmptyState.js.map +0 -1
  41. package/dist/components/security/SecurityEvidenceList.js +0 -42
  42. package/dist/components/security/SecurityEvidenceList.js.map +0 -1
  43. package/dist/components/security/SecurityFindingsTable.js +0 -201
  44. package/dist/components/security/SecurityFindingsTable.js.map +0 -1
  45. package/dist/components/security/SecurityHeaderStrip.js +0 -67
  46. package/dist/components/security/SecurityHeaderStrip.js.map +0 -1
  47. package/dist/components/security/SecurityLifecycleStepper.js +0 -66
  48. package/dist/components/security/SecurityLifecycleStepper.js.map +0 -1
  49. package/dist/components/security/SecurityProviderDrawer.js +0 -187
  50. package/dist/components/security/SecurityProviderDrawer.js.map +0 -1
  51. package/dist/components/security/gql.js +0 -128
  52. package/dist/components/security/gql.js.map +0 -1
@@ -0,0 +1,29 @@
1
+ import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
+ //#region src/components/gitops/GitOpsProviderPicker.tsx
3
+ var n = {
4
+ github: "GitHub",
5
+ gitlab: "GitLab",
6
+ bitbucket: "Bitbucket",
7
+ azdevops: "Azure DevOps"
8
+ }, r = ({ providers: r, selected: i, onChange: a }) => r.length === 0 ? null : r.length === 1 && r[0] ? /* @__PURE__ */ e("span", {
9
+ className: "inline-flex items-center px-2 py-0.5 text-xs rounded-md bg-bg-sunken text-text-secondary",
10
+ "data-testid": "gitops-provider-badge",
11
+ children: n[r[0]]
12
+ }) : /* @__PURE__ */ t("select", {
13
+ "aria-label": "GitOps provider",
14
+ "data-testid": "gitops-provider-picker",
15
+ value: i ?? "",
16
+ onChange: (e) => a(e.target.value),
17
+ className: "px-2 py-1 text-xs rounded-md border border-border-default bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40",
18
+ children: [!i && /* @__PURE__ */ e("option", {
19
+ value: "",
20
+ children: "Select…"
21
+ }), r.map((t) => /* @__PURE__ */ e("option", {
22
+ value: t,
23
+ children: n[t]
24
+ }, t))]
25
+ });
26
+ //#endregion
27
+ export { r as GitOpsProviderPicker };
28
+
29
+ //# sourceMappingURL=GitOpsProviderPicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitOpsProviderPicker.js","names":[],"sources":["../../../src/components/gitops/GitOpsProviderPicker.tsx"],"sourcesContent":["/**\n * GitOpsProviderPicker — small select to switch between authenticated\n * providers (github / gitlab / bitbucket / azdevops).\n *\n * Only providers that the user has authenticated against are surfaced.\n */\nimport type { FC } from 'react';\n\nimport type { ProviderName } from './types';\n\nconst LABELS: Record<ProviderName, string> = {\n github: 'GitHub',\n gitlab: 'GitLab',\n bitbucket: 'Bitbucket',\n azdevops: 'Azure DevOps',\n};\n\ninterface GitOpsProviderPickerProps {\n providers: ProviderName[];\n selected: ProviderName | null;\n onChange: (next: ProviderName) => void;\n}\n\nexport const GitOpsProviderPicker: FC<GitOpsProviderPickerProps> = ({\n providers,\n selected,\n onChange,\n}) => {\n if (providers.length === 0) return null;\n if (providers.length === 1 && providers[0]) {\n return (\n <span\n className=\"inline-flex items-center px-2 py-0.5 text-xs rounded-md bg-bg-sunken text-text-secondary\"\n data-testid=\"gitops-provider-badge\"\n >\n {LABELS[providers[0]]}\n </span>\n );\n }\n return (\n <select\n aria-label=\"GitOps provider\"\n data-testid=\"gitops-provider-picker\"\n value={selected ?? ''}\n onChange={(e) => onChange(e.target.value as ProviderName)}\n className=\"px-2 py-1 text-xs rounded-md border border-border-default bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40\"\n >\n {!selected && <option value=\"\">Select…</option>}\n {providers.map((p) => (\n <option key={p} value={p}>\n {LABELS[p]}\n </option>\n ))}\n </select>\n );\n};\n"],"mappings":";;AAUA,IAAM,IAAuC;CAC3C,QAAQ;CACR,QAAQ;CACR,WAAW;CACX,UAAU;CACX,EAQY,KAAuD,EAClE,cACA,aACA,kBAEI,EAAU,WAAW,IAAU,OAC/B,EAAU,WAAW,KAAK,EAAU,KAEpC,kBAAC,QAAD;CACE,WAAU;CACV,eAAY;WAEX,EAAO,EAAU;CACb,CAAA,GAIT,kBAAC,UAAD;CACE,cAAW;CACX,eAAY;CACZ,OAAO,KAAY;CACnB,WAAW,MAAM,EAAS,EAAE,OAAO,MAAsB;CACzD,WAAU;WALZ,CAOG,CAAC,KAAY,kBAAC,UAAD;EAAQ,OAAM;YAAG;EAAgB,CAAA,EAC9C,EAAU,KAAK,MACd,kBAAC,UAAD;EAAgB,OAAO;YACpB,EAAO;EACD,EAFI,EAEJ,CACT,CACK"}
@@ -1,150 +1,196 @@
1
1
  import { useTr as e } from "../../shared/hooks/useTr.js";
2
- import { useCreateGitopsProviderMutation as t } from "../../generated/wspace-operations.js";
2
+ import { useGitopsAuth as t } from "../../hooks/useGitops.js";
3
3
  import { useCallback as n, useMemo as r, useState as i } from "react";
4
- import { GitMerge as a, Loader2 as o } from "lucide-react";
5
- import { jsx as s, jsxs as c } from "react/jsx-runtime";
4
+ import { ExternalLink as a, GitMerge as o, Loader2 as s } from "lucide-react";
5
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
6
  //#region src/components/gitops/GitOpsSetup.tsx
7
- var l = [
7
+ var u = [
8
8
  {
9
- value: "GITHUB",
10
- label: "GitHub"
9
+ value: "github",
10
+ label: "GitHub",
11
+ tokenLabel: "Personal Access Token",
12
+ tokenPlaceholder: "ghp_xxxxxxxxxxxxxxxxxxxx",
13
+ helpUrl: "https://github.com/settings/tokens",
14
+ helpText: "Required scopes: repo, workflow, read:org, security_events"
11
15
  },
12
16
  {
13
- value: "GITLAB",
14
- label: "GitLab"
17
+ value: "gitlab",
18
+ label: "GitLab",
19
+ tokenLabel: "Personal Access Token",
20
+ tokenPlaceholder: "glpat-xxxxxxxxxxxxxxxxxxxx",
21
+ helpUrl: "https://gitlab.com/-/profile/personal_access_tokens",
22
+ helpText: "Required scope: api. For self-hosted instances, set the host below.",
23
+ showHost: !0
15
24
  },
16
25
  {
17
- value: "BITBUCKET",
18
- label: "Bitbucket"
26
+ value: "bitbucket",
27
+ label: "Bitbucket Cloud",
28
+ tokenLabel: "username:app_password",
29
+ tokenPlaceholder: "vignesh:ATBBxxxxxxxxxxxxxx",
30
+ helpUrl: "https://bitbucket.org/account/settings/app-passwords/",
31
+ helpText: "Required permissions: Repositories Read, Pull Requests Read, Pipelines Read"
19
32
  },
20
33
  {
21
- value: "AZURE_DEVOPS",
22
- label: "Azure DevOps"
34
+ value: "azdevops",
35
+ label: "Azure DevOps",
36
+ tokenLabel: "Personal Access Token",
37
+ tokenPlaceholder: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
38
+ helpUrl: "https://dev.azure.com/_usersSettings/tokens",
39
+ helpText: "Required scopes: Code Read, Pull Request Read, Build Read",
40
+ showOrg: !0
23
41
  }
24
- ];
25
- function u(e) {
26
- let t = e.toLowerCase();
27
- return t.includes("github.com") || t.includes("github.") ? "GITHUB" : t.includes("gitlab.com") || t.includes("gitlab.") ? "GITLAB" : t.includes("bitbucket.org") || t.includes("bitbucket.") ? "BITBUCKET" : t.includes("dev.azure.com") || t.includes("visualstudio.com") ? "AZURE_DEVOPS" : null;
28
- }
29
- var d = ({ workspaceId: d, agents: f, onCreated: p }) => {
30
- let m = e(), [h, g] = i(""), [_, v] = i(""), [y, b] = i("GITHUB"), [x, S] = i(f[0]?.id ?? ""), [C, w] = i(""), [T, { loading: E }] = t(), D = n((e) => {
31
- v(e);
32
- let t = u(e);
33
- t && b(t);
34
- }, []), O = r(() => h.trim().length > 0 && _.trim().length > 0 && x.length > 0, [
35
- h,
36
- _,
37
- x
38
- ]), k = n(async (e) => {
39
- if (e.preventDefault(), w(""), O) try {
40
- await T({ variables: { input: {
41
- name: h.trim(),
42
- providerType: y,
43
- repoUrl: _.trim()
44
- } } }), p();
42
+ ], d = ({ ctx: d, onCreated: f, onCancel: p }) => {
43
+ let m = e(), [h, g] = i("github"), [_, v] = i(""), [y, b] = i(""), [x, S] = i(""), [C, w] = i(""), [T, E] = i(null), D = r(() => u.find((e) => e.value === h) ?? u[0], [h]), O = t(d), k = r(() => !(_.trim().length === 0 || D.showOrg && y.trim().length === 0), [
44
+ D.showOrg,
45
+ y,
46
+ _
47
+ ]), A = n(async (e) => {
48
+ if (e.preventDefault(), w(""), E(null), !k) return;
49
+ let t = {};
50
+ D.showOrg && y && (t.organization = y.trim()), D.showHost && x && (t.host = x.trim());
51
+ try {
52
+ let e = await O.mutateAsync({
53
+ provider: h,
54
+ input: {
55
+ kind: "pat",
56
+ token: _.trim(),
57
+ meta: Object.keys(t).length ? t : void 0
58
+ }
59
+ });
60
+ E(e), e.ok ? (v(""), f()) : e.message && w(e.message);
45
61
  } catch (e) {
46
- w(e instanceof Error ? e.message : "Failed to connect repository");
62
+ w(e instanceof Error ? e.message : "Failed to save credentials");
47
63
  }
48
64
  }, [
49
65
  O,
50
- T,
51
- d,
52
- h,
53
- y,
54
- _,
55
66
  x,
56
- p
67
+ k,
68
+ f,
69
+ D.showHost,
70
+ D.showOrg,
71
+ y,
72
+ h,
73
+ _
57
74
  ]);
58
- return /* @__PURE__ */ s("div", {
75
+ return /* @__PURE__ */ c("div", {
59
76
  className: "max-w-xl mx-auto",
60
- children: /* @__PURE__ */ c("div", {
77
+ children: /* @__PURE__ */ l("div", {
61
78
  className: "bg-bg-surface border border-border-default rounded-xl shadow-sm p-6 sm:p-8",
62
- children: [/* @__PURE__ */ c("div", {
79
+ children: [/* @__PURE__ */ l("div", {
63
80
  className: "flex flex-col items-center text-center mb-6",
64
81
  children: [
65
- /* @__PURE__ */ s("div", {
82
+ /* @__PURE__ */ c("div", {
66
83
  className: "size-12 rounded-xl bg-bg-sunken flex items-center justify-center mb-4",
67
- children: /* @__PURE__ */ s(a, { className: "size-6 text-text-secondary" })
84
+ children: /* @__PURE__ */ c(o, { className: "size-6 text-text-secondary" })
68
85
  }),
69
- /* @__PURE__ */ s("h2", {
86
+ /* @__PURE__ */ c("h2", {
70
87
  className: "text-lg font-semibold text-text-primary",
71
- children: m("vibecontrols.gitops.setup.title", "Connect a Repository")
88
+ children: m("vibecontrols.gitops.setup.title", "Connect a provider")
72
89
  }),
73
- /* @__PURE__ */ s("p", {
90
+ /* @__PURE__ */ c("p", {
74
91
  className: "text-sm text-text-secondary mt-1",
75
- children: m("vibecontrols.gitops.setup.description", "Add a Git repository to monitor stats and CI/CD pipelines")
92
+ children: m("vibecontrols.gitops.setup.description", "Paste a personal access token. It is stored encrypted on your agent — never sent to the backend.")
76
93
  })
77
94
  ]
78
- }), /* @__PURE__ */ c("form", {
79
- onSubmit: k,
95
+ }), /* @__PURE__ */ l("form", {
96
+ onSubmit: A,
80
97
  className: "space-y-4",
81
98
  children: [
82
- /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("label", {
83
- htmlFor: "gitops-name",
99
+ /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("label", {
100
+ htmlFor: "gitops-provider",
84
101
  className: "block text-sm font-medium text-text-primary mb-1",
85
- children: m("vibecontrols.gitops.setup.name", "Name")
86
- }), /* @__PURE__ */ s("input", {
87
- "aria-label": "My Repository",
88
- id: "gitops-name",
89
- type: "text",
102
+ children: m("vibecontrols.gitops.setup.providerType", "Provider")
103
+ }), /* @__PURE__ */ c("select", {
104
+ id: "gitops-provider",
90
105
  value: h,
91
106
  onChange: (e) => g(e.target.value),
92
- placeholder: "My Repository",
93
- className: "w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 focus:border-action-primary-bg transition-colors"
94
- })] }),
95
- /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("label", {
96
- htmlFor: "gitops-url",
97
- className: "block text-sm font-medium text-text-primary mb-1",
98
- children: m("vibecontrols.gitops.setup.repoUrl", "Repository URL")
99
- }), /* @__PURE__ */ s("input", {
100
- "aria-label": "https://github.com/org/repo",
101
- id: "gitops-url",
102
- type: "url",
103
- value: _,
104
- onChange: (e) => D(e.target.value),
105
- placeholder: "https://github.com/org/repo",
106
- className: "w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 focus:border-action-primary-bg transition-colors"
107
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40",
108
+ children: u.map((e) => /* @__PURE__ */ c("option", {
109
+ value: e.value,
110
+ children: e.label
111
+ }, e.value))
107
112
  })] }),
108
- /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("label", {
109
- htmlFor: "gitops-provider",
113
+ D.showOrg && /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("label", {
114
+ htmlFor: "gitops-org",
110
115
  className: "block text-sm font-medium text-text-primary mb-1",
111
- children: m("vibecontrols.gitops.setup.providerType", "Provider Type")
112
- }), /* @__PURE__ */ s("select", {
113
- id: "gitops-provider",
116
+ children: m("vibecontrols.gitops.setup.organization", "Organisation")
117
+ }), /* @__PURE__ */ c("input", {
118
+ id: "gitops-org",
119
+ type: "text",
114
120
  value: y,
115
121
  onChange: (e) => b(e.target.value),
116
- className: "w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 focus:border-action-primary-bg transition-colors",
117
- children: l.map((e) => /* @__PURE__ */ s("option", {
118
- value: e.value,
119
- children: e.label
120
- }, e.value))
122
+ placeholder: "my-org",
123
+ "aria-label": "Azure DevOps organisation",
124
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40"
121
125
  })] }),
122
- /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("label", {
123
- htmlFor: "gitops-agent",
126
+ D.showHost && /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("label", {
127
+ htmlFor: "gitops-host",
124
128
  className: "block text-sm font-medium text-text-primary mb-1",
125
- children: m("vibecontrols.gitops.setup.agent", "Agent")
126
- }), f.length === 0 ? /* @__PURE__ */ s("p", {
127
- className: "text-sm text-status-warning-text",
128
- children: m("vibecontrols.gitops.setup.noAgents", "No agents available. Please configure an agent first for CLI access.")
129
- }) : /* @__PURE__ */ s("select", {
130
- id: "gitops-agent",
129
+ children: m("vibecontrols.gitops.setup.host", "GitLab host (optional, for self-hosted)")
130
+ }), /* @__PURE__ */ c("input", {
131
+ id: "gitops-host",
132
+ type: "url",
131
133
  value: x,
132
134
  onChange: (e) => S(e.target.value),
133
- className: "w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 focus:border-action-primary-bg transition-colors",
134
- children: f.map((e) => /* @__PURE__ */ s("option", {
135
- value: e.id,
136
- children: e.name
137
- }, e.id))
135
+ placeholder: "https://gitlab.acme.com",
136
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40"
138
137
  })] }),
139
- C && /* @__PURE__ */ s("div", {
138
+ /* @__PURE__ */ l("div", { children: [
139
+ /* @__PURE__ */ c("label", {
140
+ htmlFor: "gitops-token",
141
+ className: "block text-sm font-medium text-text-primary mb-1",
142
+ children: D.tokenLabel
143
+ }),
144
+ /* @__PURE__ */ c("input", {
145
+ id: "gitops-token",
146
+ type: "password",
147
+ value: _,
148
+ onChange: (e) => v(e.target.value),
149
+ placeholder: D.tokenPlaceholder,
150
+ "aria-label": "Personal access token",
151
+ autoComplete: "off",
152
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40"
153
+ }),
154
+ /* @__PURE__ */ l("p", {
155
+ className: "text-xs text-text-secondary mt-1.5 flex items-center gap-1",
156
+ children: [
157
+ D.helpText,
158
+ " ",
159
+ /* @__PURE__ */ l("a", {
160
+ href: D.helpUrl,
161
+ target: "_blank",
162
+ rel: "noopener noreferrer",
163
+ className: "inline-flex items-center text-action-primary-bg hover:underline",
164
+ children: ["Create token ", /* @__PURE__ */ c(a, { className: "size-3 ml-0.5" })]
165
+ })
166
+ ]
167
+ })
168
+ ] }),
169
+ T?.ok && /* @__PURE__ */ l("div", {
170
+ className: "text-sm text-status-success-text bg-status-success-bg-subtle rounded-lg px-3 py-2",
171
+ children: [
172
+ m("vibecontrols.gitops.setup.validated", "Token validated"),
173
+ T.account ? ` — ${T.account}` : "",
174
+ T.scopes?.length ? ` (scopes: ${T.scopes.join(", ")})` : ""
175
+ ]
176
+ }),
177
+ C && /* @__PURE__ */ c("div", {
140
178
  className: "text-sm text-status-error-text bg-status-error-bg-subtle rounded-lg px-3 py-2",
141
179
  children: C
142
180
  }),
143
- /* @__PURE__ */ c("button", {
144
- type: "submit",
145
- disabled: E || !O,
146
- className: "w-full flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium rounded-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
147
- children: [E && /* @__PURE__ */ s(o, { className: "size-4 animate-spin" }), m("vibecontrols.gitops.setup.connect", "Connect Repository")]
181
+ /* @__PURE__ */ l("div", {
182
+ className: "flex items-center gap-3",
183
+ children: [/* @__PURE__ */ l("button", {
184
+ type: "submit",
185
+ disabled: O.isPending || !k,
186
+ className: "flex-1 flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium rounded-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
187
+ children: [O.isPending && /* @__PURE__ */ c(s, { className: "size-4 animate-spin" }), m("vibecontrols.gitops.setup.connect", "Save and connect")]
188
+ }), p && /* @__PURE__ */ c("button", {
189
+ type: "button",
190
+ onClick: p,
191
+ className: "px-4 py-2.5 text-sm font-medium rounded-lg border border-border-default text-text-secondary hover:text-text-primary transition-colors",
192
+ children: m("vibecontrols.gitops.setup.cancel", "Cancel")
193
+ })]
148
194
  })
149
195
  ]
150
196
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"GitOpsSetup.js","names":[],"sources":["../../../src/components/gitops/GitOpsSetup.tsx"],"sourcesContent":["import { useState, useCallback, useMemo } from 'react';\nimport type { FC, FormEvent } from 'react';\nimport { GitMerge, Loader2 } from 'lucide-react';\nimport { useCreateGitopsProviderMutation } from '../../generated/wspace-operations';\nimport type { GitProviderType } from './types';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface GitOpsSetupProps {\n workspaceId: string;\n agents: Array<{ id: string; name: string }>;\n onCreated: () => void;\n}\n\nconst PROVIDER_OPTIONS: { value: GitProviderType; label: string }[] = [\n { value: 'GITHUB', label: 'GitHub' },\n { value: 'GITLAB', label: 'GitLab' },\n { value: 'BITBUCKET', label: 'Bitbucket' },\n { value: 'AZURE_DEVOPS', label: 'Azure DevOps' },\n];\n\nfunction detectProvider(url: string): GitProviderType | null {\n const lower = url.toLowerCase();\n if (lower.includes('github.com') || lower.includes('github.')) return 'GITHUB';\n if (lower.includes('gitlab.com') || lower.includes('gitlab.')) return 'GITLAB';\n if (lower.includes('bitbucket.org') || lower.includes('bitbucket.')) return 'BITBUCKET';\n if (lower.includes('dev.azure.com') || lower.includes('visualstudio.com')) return 'AZURE_DEVOPS';\n return null;\n}\n\n/**\n * GitOpsSetup shows a first-time provider setup form when no providers are configured.\n */\nexport const GitOpsSetup: FC<GitOpsSetupProps> = ({ workspaceId, agents, onCreated }) => {\n const tr = useTr();\n const [name, setName] = useState('');\n const [repoUrl, setRepoUrl] = useState('');\n const [providerType, setProviderType] = useState<GitProviderType>('GITHUB');\n const [agentId, setAgentId] = useState(agents[0]?.id ?? '');\n const [error, setError] = useState('');\n\n const [createProvider, { loading }] = useCreateGitopsProviderMutation();\n\n const handleUrlChange = useCallback((url: string) => {\n setRepoUrl(url);\n const detected = detectProvider(url);\n if (detected) setProviderType(detected);\n }, []);\n\n const isValid = useMemo(\n () => name.trim().length > 0 && repoUrl.trim().length > 0 && agentId.length > 0,\n [name, repoUrl, agentId]\n );\n\n const handleSubmit = useCallback(\n async (e: FormEvent) => {\n e.preventDefault();\n setError('');\n\n if (!isValid) return;\n\n try {\n await createProvider({\n variables: {\n input: {\n name: name.trim(),\n providerType,\n repoUrl: repoUrl.trim(),\n },\n },\n });\n onCreated();\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to connect repository');\n }\n },\n [isValid, createProvider, workspaceId, name, providerType, repoUrl, agentId, onCreated]\n );\n\n return (\n <div className=\"max-w-xl mx-auto\">\n <div className=\"bg-bg-surface border border-border-default rounded-xl shadow-sm p-6 sm:p-8\">\n <div className=\"flex flex-col items-center text-center mb-6\">\n <div className=\"size-12 rounded-xl bg-bg-sunken flex items-center justify-center mb-4\">\n <GitMerge className=\"size-6 text-text-secondary\" />\n </div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('vibecontrols.gitops.setup.title', 'Connect a Repository')}\n </h2>\n <p className=\"text-sm text-text-secondary mt-1\">\n {tr(\n 'vibecontrols.gitops.setup.description',\n 'Add a Git repository to monitor stats and CI/CD pipelines'\n )}\n </p>\n </div>\n\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {/* Name */}\n <div>\n <label\n htmlFor=\"gitops-name\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('vibecontrols.gitops.setup.name', 'Name')}\n </label>\n <input\n aria-label=\"My Repository\"\n id=\"gitops-name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"My Repository\"\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 focus:border-action-primary-bg transition-colors\"\n />\n </div>\n\n {/* Repository URL */}\n <div>\n <label\n htmlFor=\"gitops-url\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('vibecontrols.gitops.setup.repoUrl', 'Repository URL')}\n </label>\n <input\n aria-label=\"https://github.com/org/repo\"\n id=\"gitops-url\"\n type=\"url\"\n value={repoUrl}\n onChange={(e) => handleUrlChange(e.target.value)}\n placeholder=\"https://github.com/org/repo\"\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 focus:border-action-primary-bg transition-colors\"\n />\n </div>\n\n {/* Provider Type */}\n <div>\n <label\n htmlFor=\"gitops-provider\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('vibecontrols.gitops.setup.providerType', 'Provider Type')}\n </label>\n <select\n id=\"gitops-provider\"\n value={providerType}\n onChange={(e) => setProviderType(e.target.value as GitProviderType)}\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 focus:border-action-primary-bg transition-colors\"\n >\n {PROVIDER_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n\n {/* Agent */}\n <div>\n <label\n htmlFor=\"gitops-agent\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('vibecontrols.gitops.setup.agent', 'Agent')}\n </label>\n {agents.length === 0 ? (\n <p className=\"text-sm text-status-warning-text\">\n {tr(\n 'vibecontrols.gitops.setup.noAgents',\n 'No agents available. Please configure an agent first for CLI access.'\n )}\n </p>\n ) : (\n <select\n id=\"gitops-agent\"\n value={agentId}\n onChange={(e) => setAgentId(e.target.value)}\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 focus:border-action-primary-bg transition-colors\"\n >\n {agents.map((agent) => (\n <option key={agent.id} value={agent.id}>\n {agent.name}\n </option>\n ))}\n </select>\n )}\n </div>\n\n {error && (\n <div className=\"text-sm text-status-error-text bg-status-error-bg-subtle rounded-lg px-3 py-2\">\n {error}\n </div>\n )}\n\n <button\n type=\"submit\"\n disabled={loading || !isValid}\n className=\"w-full flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium rounded-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {loading && <Loader2 className=\"size-4 animate-spin\" />}\n {tr('vibecontrols.gitops.setup.connect', 'Connect Repository')}\n </button>\n </form>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"GitOpsSetup.js","names":[],"sources":["../../../src/components/gitops/GitOpsSetup.tsx"],"sourcesContent":["/**\n * GitOpsSetup — v2: PAT entry flow.\n *\n * User picks a provider (github / gitlab / bitbucket / azdevops), pastes a\n * PAT, and the agent stores it in encrypted SQLite. No backend record is\n * created. After save, `validateCredentials` is called via the same POST\n * so the user sees `ok: true, scopes: [...]` immediately.\n *\n * Azure DevOps requires an `organization` field — surfaced conditionally.\n * Bitbucket expects `username:app_password` format — documented inline.\n * GitLab supports a `host` override for self-hosted instances.\n */\nimport { useCallback, useMemo, useState, type FC, type FormEvent } from 'react';\nimport { GitMerge, Loader2, ExternalLink } from 'lucide-react';\n\nimport { useTr } from '../../shared/hooks/useTr';\nimport { useGitopsAuth, type UseGitopsContext } from '@/hooks/useGitops';\nimport type { ProviderName } from './types';\n\ninterface GitOpsSetupProps {\n ctx: UseGitopsContext;\n onCreated: () => void;\n onCancel?: () => void;\n}\n\ninterface ProviderOption {\n value: ProviderName;\n label: string;\n tokenLabel: string;\n tokenPlaceholder: string;\n helpUrl: string;\n helpText: string;\n showOrg?: boolean;\n showHost?: boolean;\n}\n\nconst PROVIDER_OPTIONS: ProviderOption[] = [\n {\n value: 'github',\n label: 'GitHub',\n tokenLabel: 'Personal Access Token',\n tokenPlaceholder: 'ghp_xxxxxxxxxxxxxxxxxxxx',\n helpUrl: 'https://github.com/settings/tokens',\n helpText: 'Required scopes: repo, workflow, read:org, security_events',\n },\n {\n value: 'gitlab',\n label: 'GitLab',\n tokenLabel: 'Personal Access Token',\n tokenPlaceholder: 'glpat-xxxxxxxxxxxxxxxxxxxx',\n helpUrl: 'https://gitlab.com/-/profile/personal_access_tokens',\n helpText: 'Required scope: api. For self-hosted instances, set the host below.',\n showHost: true,\n },\n {\n value: 'bitbucket',\n label: 'Bitbucket Cloud',\n tokenLabel: 'username:app_password',\n tokenPlaceholder: 'vignesh:ATBBxxxxxxxxxxxxxx',\n helpUrl: 'https://bitbucket.org/account/settings/app-passwords/',\n helpText: 'Required permissions: Repositories Read, Pull Requests Read, Pipelines Read',\n },\n {\n value: 'azdevops',\n label: 'Azure DevOps',\n tokenLabel: 'Personal Access Token',\n tokenPlaceholder: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',\n helpUrl: 'https://dev.azure.com/_usersSettings/tokens',\n helpText: 'Required scopes: Code Read, Pull Request Read, Build Read',\n showOrg: true,\n },\n];\n\nexport const GitOpsSetup: FC<GitOpsSetupProps> = ({ ctx, onCreated, onCancel }) => {\n const tr = useTr();\n const [providerType, setProviderType] = useState<ProviderName>('github');\n const [token, setToken] = useState('');\n const [organization, setOrganization] = useState('');\n const [host, setHost] = useState('');\n const [error, setError] = useState('');\n const [validation, setValidation] = useState<{\n ok: boolean;\n account?: string;\n scopes?: string[];\n message?: string;\n } | null>(null);\n\n const opt = useMemo(\n () => PROVIDER_OPTIONS.find((o) => o.value === providerType) ?? PROVIDER_OPTIONS[0]!,\n [providerType]\n );\n\n const authMutation = useGitopsAuth(ctx);\n\n const isValid = useMemo(() => {\n if (token.trim().length === 0) return false;\n if (opt.showOrg && organization.trim().length === 0) return false;\n return true;\n }, [opt.showOrg, organization, token]);\n\n const handleSubmit = useCallback(\n async (e: FormEvent) => {\n e.preventDefault();\n setError('');\n setValidation(null);\n if (!isValid) return;\n\n const meta: Record<string, string> = {};\n if (opt.showOrg && organization) meta.organization = organization.trim();\n if (opt.showHost && host) meta.host = host.trim();\n\n try {\n const result = await authMutation.mutateAsync({\n provider: providerType,\n input: {\n kind: 'pat',\n token: token.trim(),\n meta: Object.keys(meta).length ? meta : undefined,\n },\n });\n setValidation(result);\n if (result.ok) {\n setToken('');\n onCreated();\n } else if (result.message) {\n setError(result.message);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to save credentials');\n }\n },\n [\n authMutation,\n host,\n isValid,\n onCreated,\n opt.showHost,\n opt.showOrg,\n organization,\n providerType,\n token,\n ]\n );\n\n return (\n <div className=\"max-w-xl mx-auto\">\n <div className=\"bg-bg-surface border border-border-default rounded-xl shadow-sm p-6 sm:p-8\">\n <div className=\"flex flex-col items-center text-center mb-6\">\n <div className=\"size-12 rounded-xl bg-bg-sunken flex items-center justify-center mb-4\">\n <GitMerge className=\"size-6 text-text-secondary\" />\n </div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('vibecontrols.gitops.setup.title', 'Connect a provider')}\n </h2>\n <p className=\"text-sm text-text-secondary mt-1\">\n {tr(\n 'vibecontrols.gitops.setup.description',\n 'Paste a personal access token. It is stored encrypted on your agent — never sent to the backend.'\n )}\n </p>\n </div>\n\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <div>\n <label\n htmlFor=\"gitops-provider\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('vibecontrols.gitops.setup.providerType', 'Provider')}\n </label>\n <select\n id=\"gitops-provider\"\n value={providerType}\n onChange={(e) => setProviderType(e.target.value as ProviderName)}\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40\"\n >\n {PROVIDER_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </div>\n\n {opt.showOrg && (\n <div>\n <label\n htmlFor=\"gitops-org\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('vibecontrols.gitops.setup.organization', 'Organisation')}\n </label>\n <input\n id=\"gitops-org\"\n type=\"text\"\n value={organization}\n onChange={(e) => setOrganization(e.target.value)}\n placeholder=\"my-org\"\n aria-label=\"Azure DevOps organisation\"\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40\"\n />\n </div>\n )}\n\n {opt.showHost && (\n <div>\n <label\n htmlFor=\"gitops-host\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('vibecontrols.gitops.setup.host', 'GitLab host (optional, for self-hosted)')}\n </label>\n <input\n id=\"gitops-host\"\n type=\"url\"\n value={host}\n onChange={(e) => setHost(e.target.value)}\n placeholder=\"https://gitlab.acme.com\"\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40\"\n />\n </div>\n )}\n\n <div>\n <label\n htmlFor=\"gitops-token\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {opt.tokenLabel}\n </label>\n <input\n id=\"gitops-token\"\n type=\"password\"\n value={token}\n onChange={(e) => setToken(e.target.value)}\n placeholder={opt.tokenPlaceholder}\n aria-label=\"Personal access token\"\n autoComplete=\"off\"\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border-default bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40\"\n />\n <p className=\"text-xs text-text-secondary mt-1.5 flex items-center gap-1\">\n {opt.helpText}{' '}\n <a\n href={opt.helpUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center text-action-primary-bg hover:underline\"\n >\n Create token <ExternalLink className=\"size-3 ml-0.5\" />\n </a>\n </p>\n </div>\n\n {validation?.ok && (\n <div className=\"text-sm text-status-success-text bg-status-success-bg-subtle rounded-lg px-3 py-2\">\n {tr('vibecontrols.gitops.setup.validated', 'Token validated')}\n {validation.account ? ` — ${validation.account}` : ''}\n {validation.scopes?.length ? ` (scopes: ${validation.scopes.join(', ')})` : ''}\n </div>\n )}\n {error && (\n <div className=\"text-sm text-status-error-text bg-status-error-bg-subtle rounded-lg px-3 py-2\">\n {error}\n </div>\n )}\n\n <div className=\"flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={authMutation.isPending || !isValid}\n className=\"flex-1 flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium rounded-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {authMutation.isPending && <Loader2 className=\"size-4 animate-spin\" />}\n {tr('vibecontrols.gitops.setup.connect', 'Save and connect')}\n </button>\n {onCancel && (\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-4 py-2.5 text-sm font-medium rounded-lg border border-border-default text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr('vibecontrols.gitops.setup.cancel', 'Cancel')}\n </button>\n )}\n </div>\n </form>\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;AAoCA,IAAM,IAAqC;CACzC;EACE,OAAO;EACP,OAAO;EACP,YAAY;EACZ,kBAAkB;EAClB,SAAS;EACT,UAAU;EACX;CACD;EACE,OAAO;EACP,OAAO;EACP,YAAY;EACZ,kBAAkB;EAClB,SAAS;EACT,UAAU;EACV,UAAU;EACX;CACD;EACE,OAAO;EACP,OAAO;EACP,YAAY;EACZ,kBAAkB;EAClB,SAAS;EACT,UAAU;EACX;CACD;EACE,OAAO;EACP,OAAO;EACP,YAAY;EACZ,kBAAkB;EAClB,SAAS;EACT,UAAU;EACV,SAAS;EACV;CACF,EAEY,KAAqC,EAAE,QAAK,cAAW,kBAAe;CACjF,IAAM,IAAK,GAAO,EACZ,CAAC,GAAc,KAAmB,EAAuB,SAAS,EAClE,CAAC,GAAO,KAAY,EAAS,GAAG,EAChC,CAAC,GAAc,KAAmB,EAAS,GAAG,EAC9C,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAO,KAAY,EAAS,GAAG,EAChC,CAAC,GAAY,KAAiB,EAK1B,KAAK,EAET,IAAM,QACJ,EAAiB,MAAM,MAAM,EAAE,UAAU,EAAa,IAAI,EAAiB,IACjF,CAAC,EAAa,CACf,EAEK,IAAe,EAAc,EAAI,EAEjC,IAAU,QAEd,EADI,EAAM,MAAM,CAAC,WAAW,KACxB,EAAI,WAAW,EAAa,MAAM,CAAC,WAAW,IAEjD;EAAC,EAAI;EAAS;EAAc;EAAM,CAAC,EAEhC,IAAe,EACnB,OAAO,MAAiB;AAItB,MAHA,EAAE,gBAAgB,EAClB,EAAS,GAAG,EACZ,EAAc,KAAK,EACf,CAAC,EAAS;EAEd,IAAM,IAA+B,EAAE;AAEvC,EADI,EAAI,WAAW,MAAc,EAAK,eAAe,EAAa,MAAM,GACpE,EAAI,YAAY,MAAM,EAAK,OAAO,EAAK,MAAM;AAEjD,MAAI;GACF,IAAM,IAAS,MAAM,EAAa,YAAY;IAC5C,UAAU;IACV,OAAO;KACL,MAAM;KACN,OAAO,EAAM,MAAM;KACnB,MAAM,OAAO,KAAK,EAAK,CAAC,SAAS,IAAO,KAAA;KACzC;IACF,CAAC;AAEF,GADA,EAAc,EAAO,EACjB,EAAO,MACT,EAAS,GAAG,EACZ,GAAW,IACF,EAAO,WAChB,EAAS,EAAO,QAAQ;WAEnB,GAAK;AACZ,KAAS,aAAe,QAAQ,EAAI,UAAU,6BAA6B;;IAG/E;EACE;EACA;EACA;EACA;EACA,EAAI;EACJ,EAAI;EACJ;EACA;EACA;EACD,CACF;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAU,WAAU,8BAA+B,CAAA;MAC/C,CAAA;KACN,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAG,mCAAmC,qBAAqB;MACzD,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,yCACA,mGACD;MACC,CAAA;KACA;OAEN,kBAAC,QAAD;IAAM,UAAU;IAAc,WAAU;cAAxC;KACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MACE,SAAQ;MACR,WAAU;gBAET,EAAG,0CAA0C,WAAW;MACnD,CAAA,EACR,kBAAC,UAAD;MACE,IAAG;MACH,OAAO;MACP,WAAW,MAAM,EAAgB,EAAE,OAAO,MAAsB;MAChE,WAAU;gBAET,EAAiB,KAAK,MACrB,kBAAC,UAAD;OAAsB,OAAO,EAAE;iBAC5B,EAAE;OACI,EAFI,EAAE,MAEN,CACT;MACK,CAAA,CACL,EAAA,CAAA;KAEL,EAAI,WACH,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MACE,SAAQ;MACR,WAAU;gBAET,EAAG,0CAA0C,eAAe;MACvD,CAAA,EACR,kBAAC,SAAD;MACE,IAAG;MACH,MAAK;MACL,OAAO;MACP,WAAW,MAAM,EAAgB,EAAE,OAAO,MAAM;MAChD,aAAY;MACZ,cAAW;MACX,WAAU;MACV,CAAA,CACE,EAAA,CAAA;KAGP,EAAI,YACH,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MACE,SAAQ;MACR,WAAU;gBAET,EAAG,kCAAkC,0CAA0C;MAC1E,CAAA,EACR,kBAAC,SAAD;MACE,IAAG;MACH,MAAK;MACL,OAAO;MACP,WAAW,MAAM,EAAQ,EAAE,OAAO,MAAM;MACxC,aAAY;MACZ,WAAU;MACV,CAAA,CACE,EAAA,CAAA;KAGR,kBAAC,OAAD,EAAA,UAAA;MACE,kBAAC,SAAD;OACE,SAAQ;OACR,WAAU;iBAET,EAAI;OACC,CAAA;MACR,kBAAC,SAAD;OACE,IAAG;OACH,MAAK;OACL,OAAO;OACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;OACzC,aAAa,EAAI;OACjB,cAAW;OACX,cAAa;OACb,WAAU;OACV,CAAA;MACF,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAI;QAAU;QACf,kBAAC,KAAD;SACE,MAAM,EAAI;SACV,QAAO;SACP,KAAI;SACJ,WAAU;mBAJZ,CAKC,iBACc,kBAAC,GAAD,EAAc,WAAU,iBAAkB,CAAA,CACrD;;QACF;;MACA,EAAA,CAAA;KAEL,GAAY,MACX,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACG,EAAG,uCAAuC,kBAAkB;OAC5D,EAAW,UAAU,MAAM,EAAW,YAAY;OAClD,EAAW,QAAQ,SAAS,aAAa,EAAW,OAAO,KAAK,KAAK,CAAC,KAAK;OACxE;;KAEP,KACC,kBAAC,OAAD;MAAK,WAAU;gBACZ;MACG,CAAA;KAGR,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,EAAa,aAAa,CAAC;OACrC,WAAU;iBAHZ,CAKG,EAAa,aAAa,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,EACrE,EAAG,qCAAqC,mBAAmB,CACrD;UACR,KACC,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,WAAU;iBAET,EAAG,oCAAoC,SAAS;OAC1C,CAAA,CAEP;;KACD;MACH;;EACF,CAAA"}