@nastechai/agent 0.16.0 → 0.17.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.
Files changed (98) hide show
  1. package/eslint.config.js +23 -0
  2. package/index.html +24 -0
  3. package/package.json +54 -26
  4. package/package.json.bak +89 -0
  5. package/package.json.pub +88 -0
  6. package/src/App.tsx +1173 -0
  7. package/src/components/AuthWidget.tsx +150 -0
  8. package/src/components/AutoField.tsx +206 -0
  9. package/src/components/Backdrop.tsx +93 -0
  10. package/src/components/ChatSidebar.tsx +394 -0
  11. package/src/components/DeleteConfirmDialog.tsx +40 -0
  12. package/src/components/LanguageSwitcher.tsx +186 -0
  13. package/src/components/Markdown.tsx +383 -0
  14. package/src/components/ModelInfoCard.tsx +112 -0
  15. package/src/components/ModelPickerDialog.tsx +470 -0
  16. package/src/components/OAuthLoginModal.tsx +374 -0
  17. package/src/components/OAuthProvidersCard.tsx +287 -0
  18. package/src/components/PlatformsCard.tsx +97 -0
  19. package/src/components/ScheduleBuilder.tsx +273 -0
  20. package/src/components/SidebarFooter.tsx +42 -0
  21. package/src/components/SidebarStatusStrip.tsx +72 -0
  22. package/src/components/SlashPopover.tsx +171 -0
  23. package/src/components/ThemeSwitcher.tsx +243 -0
  24. package/src/components/ToolCall.tsx +228 -0
  25. package/src/components/ToolsetConfigDrawer.tsx +448 -0
  26. package/src/contexts/PageHeaderProvider.tsx +139 -0
  27. package/src/contexts/SystemActions.tsx +120 -0
  28. package/src/contexts/page-header-context.ts +12 -0
  29. package/src/contexts/system-actions-context.ts +18 -0
  30. package/src/contexts/usePageHeader.ts +10 -0
  31. package/src/contexts/useSystemActions.ts +15 -0
  32. package/src/hooks/useModalBehavior.ts +44 -0
  33. package/src/hooks/useSidebarStatus.ts +27 -0
  34. package/src/i18n/af.ts +702 -0
  35. package/src/i18n/context.tsx +123 -0
  36. package/src/i18n/de.ts +701 -0
  37. package/src/i18n/en.ts +708 -0
  38. package/src/i18n/es.ts +701 -0
  39. package/src/i18n/fr.ts +701 -0
  40. package/src/i18n/ga.ts +702 -0
  41. package/src/i18n/hu.ts +702 -0
  42. package/src/i18n/index.ts +2 -0
  43. package/src/i18n/it.ts +701 -0
  44. package/src/i18n/ja.ts +702 -0
  45. package/src/i18n/ko.ts +702 -0
  46. package/src/i18n/pt.ts +702 -0
  47. package/src/i18n/ru.ts +702 -0
  48. package/src/i18n/tr.ts +702 -0
  49. package/src/i18n/types.ts +710 -0
  50. package/src/i18n/uk.ts +702 -0
  51. package/src/i18n/zh-hant.ts +702 -0
  52. package/src/i18n/zh.ts +698 -0
  53. package/src/index.css +274 -0
  54. package/src/lib/api.ts +1585 -0
  55. package/src/lib/dashboard-flags.ts +15 -0
  56. package/src/lib/format.ts +9 -0
  57. package/src/lib/fuzzy.ts +192 -0
  58. package/src/lib/gatewayClient.ts +253 -0
  59. package/src/lib/nested.ts +23 -0
  60. package/src/lib/resolve-page-title.ts +41 -0
  61. package/src/lib/schedule.ts +382 -0
  62. package/src/lib/slashExec.ts +163 -0
  63. package/src/lib/utils.ts +35 -0
  64. package/src/main.tsx +25 -0
  65. package/src/pages/AnalyticsPage.tsx +601 -0
  66. package/src/pages/ChannelsPage.tsx +772 -0
  67. package/src/pages/ChatPage.tsx +889 -0
  68. package/src/pages/ConfigPage.tsx +660 -0
  69. package/src/pages/CronPage.tsx +524 -0
  70. package/src/pages/DocsPage.tsx +69 -0
  71. package/src/pages/EnvPage.tsx +918 -0
  72. package/src/pages/LogsPage.tsx +246 -0
  73. package/src/pages/McpPage.tsx +757 -0
  74. package/src/pages/ModelsPage.tsx +994 -0
  75. package/src/pages/PairingPage.tsx +276 -0
  76. package/src/pages/PluginsPage.tsx +580 -0
  77. package/src/pages/ProfilesPage.tsx +559 -0
  78. package/src/pages/SessionsPage.tsx +936 -0
  79. package/src/pages/SkillsPage.tsx +557 -0
  80. package/src/pages/SystemPage.tsx +1259 -0
  81. package/src/pages/WebhooksPage.tsx +483 -0
  82. package/src/plugins/PluginPage.tsx +64 -0
  83. package/src/plugins/index.ts +6 -0
  84. package/src/plugins/registry.ts +151 -0
  85. package/src/plugins/sdk.d.ts +160 -0
  86. package/src/plugins/slots.ts +199 -0
  87. package/src/plugins/types.ts +37 -0
  88. package/src/plugins/usePlugins.ts +133 -0
  89. package/src/themes/context.tsx +443 -0
  90. package/src/themes/fonts.ts +160 -0
  91. package/src/themes/index.ts +3 -0
  92. package/src/themes/presets.ts +477 -0
  93. package/src/themes/types.ts +187 -0
  94. package/tsconfig.app.json +34 -0
  95. package/tsconfig.json +7 -0
  96. package/tsconfig.node.json +26 -0
  97. package/vite.config.ts +124 -0
  98. package/vite.config.ts.timestamp-1780999102396-af6b77b30ebd8.mjs +105 -0
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2023",
5
+ "lib": ["ES2023"],
6
+ "module": "ESNext",
7
+ "types": ["node"],
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "verbatimModuleSyntax": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+
17
+ /* Linting */
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "erasableSyntaxOnly": true,
22
+ "noFallthroughCasesInSwitch": true,
23
+ "noUncheckedSideEffectImports": true
24
+ },
25
+ "include": ["vite.config.ts"]
26
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,124 @@
1
+ import { defineConfig, type Plugin } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+ import tailwindcss from "@tailwindcss/vite";
4
+ import path from "path";
5
+
6
+ const BACKEND = process.env.NASTECH_DASHBOARD_URL ?? "http://127.0.0.1:9119";
7
+
8
+ /**
9
+ * In production the Python `nastech dashboard` server injects a one-shot
10
+ * session token into `index.html` (see `nastech_cli/web_server.py`). The
11
+ * Vite dev server serves its own `index.html`, so unless we forward that
12
+ * token, every protected `/api/*` call 401s.
13
+ *
14
+ * This plugin fetches the running dashboard's `index.html` on each dev page
15
+ * load, scrapes the `window.__NASTECH_SESSION_TOKEN__` assignment, and
16
+ * re-injects it into the dev HTML. No-op in production builds.
17
+ */
18
+ /**
19
+ * Remap @nastechai/ui → @nastechai/ui so Vite's module resolver
20
+ * follows the package's exports map instead of a raw filesystem path.
21
+ */
22
+ function nastechUiAlias(): Plugin {
23
+ return {
24
+ name: "nastech:ui-alias",
25
+ enforce: "pre",
26
+ resolveId(id, importer, options) {
27
+ if (id.startsWith("@nastechai/ui")) {
28
+ return this.resolve(
29
+ id.replace("@nastechai/ui", "@nastechai/ui"),
30
+ importer,
31
+ options,
32
+ );
33
+ }
34
+ },
35
+ };
36
+ }
37
+
38
+ function nastechDevToken(): Plugin {
39
+ const TOKEN_RE = /window\.__NASTECH_SESSION_TOKEN__\s*=\s*"([^"]+)"/;
40
+ const EMBEDDED_RE =
41
+ /window\.__NASTECH_DASHBOARD_EMBEDDED_CHAT__\s*=\s*(true|false)/;
42
+
43
+ return {
44
+ name: "nastech:dev-session-token",
45
+ apply: "serve",
46
+ async transformIndexHtml() {
47
+ try {
48
+ const res = await fetch(BACKEND, { headers: { accept: "text/html" } });
49
+ const html = await res.text();
50
+ const match = html.match(TOKEN_RE);
51
+ if (!match) {
52
+ console.warn(
53
+ `[nastech] Could not find session token in ${BACKEND} — ` +
54
+ `is \`nastech dashboard\` running? /api calls will 401.`,
55
+ );
56
+ return;
57
+ }
58
+ const embeddedMatch = html.match(EMBEDDED_RE);
59
+ const embeddedJs = embeddedMatch ? embeddedMatch[1] : "true";
60
+ return [
61
+ {
62
+ tag: "script",
63
+ injectTo: "head",
64
+ children:
65
+ `window.__NASTECH_SESSION_TOKEN__="${match[1]}";` +
66
+ `window.__NASTECH_DASHBOARD_EMBEDDED_CHAT__=${embeddedJs};`,
67
+ },
68
+ ];
69
+ } catch (err) {
70
+ console.warn(
71
+ `[nastech] Dashboard at ${BACKEND} unreachable — ` +
72
+ `start it with \`nastech dashboard\` or set NASTECH_DASHBOARD_URL. ` +
73
+ `(${(err as Error).message})`,
74
+ );
75
+ }
76
+ },
77
+ };
78
+ }
79
+
80
+ export default defineConfig({
81
+ plugins: [react(), tailwindcss(), nastechUiAlias(), nastechDevToken()],
82
+ resolve: {
83
+ alias: {
84
+ "@": path.resolve(__dirname, "./src"),
85
+ },
86
+ // When @nastechai/ui is symlinked via `file:../../design-language`,
87
+ // Node's module resolution would pick up shared deps from
88
+ // design-language/node_modules/*, giving us two copies + breaking
89
+ // hooks (useRef-of-null), webgl contexts, etc. Force everything that
90
+ // exists in BOTH places to use the dashboard's copy.
91
+ //
92
+ // Don't list packages here that only exist in the DS (nanostores,
93
+ // @nanostores/react) — Vite dedupe errors out when it can't find
94
+ // them at the project root.
95
+ dedupe: [
96
+ "react",
97
+ "react-dom",
98
+ "@react-three/fiber",
99
+ "@observablehq/plot",
100
+ "three",
101
+ "leva",
102
+ "gsap",
103
+ ],
104
+ },
105
+ build: {
106
+ outDir: "../nastech_cli/web_dist",
107
+ emptyOutDir: true,
108
+ },
109
+ server: {
110
+ host: "0.0.0.0",
111
+ port: 5000,
112
+ allowedHosts: true,
113
+ proxy: {
114
+ "/api": {
115
+ target: BACKEND,
116
+ ws: true,
117
+ },
118
+ // Same host as `nastech dashboard` must serve these; Vite has no
119
+ // dashboard-plugins/* files, so without this, plugin scripts 404
120
+ // or receive index.html in dev.
121
+ "/dashboard-plugins": BACKEND,
122
+ },
123
+ },
124
+ });
@@ -0,0 +1,105 @@
1
+ // vite.config.ts
2
+ import { defineConfig } from "file:///home/runner/workspace/web/node_modules/vite/dist/node/index.js";
3
+ import react from "file:///home/runner/workspace/web/node_modules/@vitejs/plugin-react/dist/index.js";
4
+ import tailwindcss from "file:///home/runner/workspace/node_modules/@tailwindcss/vite/dist/index.mjs";
5
+ import path from "path";
6
+ var __vite_injected_original_dirname = "/home/runner/workspace/web";
7
+ var BACKEND = process.env.NASTECH_DASHBOARD_URL ?? "http://127.0.0.1:9119";
8
+ function nastechUiAlias() {
9
+ return {
10
+ name: "nastech:ui-alias",
11
+ enforce: "pre",
12
+ resolveId(id, importer, options) {
13
+ if (id.startsWith("@nastech-ai/ui")) {
14
+ return this.resolve(
15
+ id.replace("@nastech-ai/ui", "@nastechai/ui"),
16
+ importer,
17
+ options
18
+ );
19
+ }
20
+ }
21
+ };
22
+ }
23
+ function nastechDevToken() {
24
+ const TOKEN_RE = /window\.__NASTECH_SESSION_TOKEN__\s*=\s*"([^"]+)"/;
25
+ const EMBEDDED_RE = /window\.__NASTECH_DASHBOARD_EMBEDDED_CHAT__\s*=\s*(true|false)/;
26
+ return {
27
+ name: "nastech:dev-session-token",
28
+ apply: "serve",
29
+ async transformIndexHtml() {
30
+ try {
31
+ const res = await fetch(BACKEND, { headers: { accept: "text/html" } });
32
+ const html = await res.text();
33
+ const match = html.match(TOKEN_RE);
34
+ if (!match) {
35
+ console.warn(
36
+ `[nastech] Could not find session token in ${BACKEND} \u2014 is \`nastech dashboard\` running? /api calls will 401.`
37
+ );
38
+ return;
39
+ }
40
+ const embeddedMatch = html.match(EMBEDDED_RE);
41
+ const embeddedJs = embeddedMatch ? embeddedMatch[1] : "true";
42
+ return [
43
+ {
44
+ tag: "script",
45
+ injectTo: "head",
46
+ children: `window.__NASTECH_SESSION_TOKEN__="${match[1]}";window.__NASTECH_DASHBOARD_EMBEDDED_CHAT__=${embeddedJs};`
47
+ }
48
+ ];
49
+ } catch (err) {
50
+ console.warn(
51
+ `[nastech] Dashboard at ${BACKEND} unreachable \u2014 start it with \`nastech dashboard\` or set NASTECH_DASHBOARD_URL. (${err.message})`
52
+ );
53
+ }
54
+ }
55
+ };
56
+ }
57
+ var vite_config_default = defineConfig({
58
+ plugins: [react(), tailwindcss(), nastechUiAlias(), nastechDevToken()],
59
+ resolve: {
60
+ alias: {
61
+ "@": path.resolve(__vite_injected_original_dirname, "./src")
62
+ },
63
+ // When @nastech-ai/ui is symlinked via `file:../../design-language`,
64
+ // Node's module resolution would pick up shared deps from
65
+ // design-language/node_modules/*, giving us two copies + breaking
66
+ // hooks (useRef-of-null), webgl contexts, etc. Force everything that
67
+ // exists in BOTH places to use the dashboard's copy.
68
+ //
69
+ // Don't list packages here that only exist in the DS (nanostores,
70
+ // @nanostores/react) — Vite dedupe errors out when it can't find
71
+ // them at the project root.
72
+ dedupe: [
73
+ "react",
74
+ "react-dom",
75
+ "@react-three/fiber",
76
+ "@observablehq/plot",
77
+ "three",
78
+ "leva",
79
+ "gsap"
80
+ ]
81
+ },
82
+ build: {
83
+ outDir: "../nastech_cli/web_dist",
84
+ emptyOutDir: true
85
+ },
86
+ server: {
87
+ host: "0.0.0.0",
88
+ port: 5e3,
89
+ allowedHosts: true,
90
+ proxy: {
91
+ "/api": {
92
+ target: BACKEND,
93
+ ws: true
94
+ },
95
+ // Same host as `nastech dashboard` must serve these; Vite has no
96
+ // dashboard-plugins/* files, so without this, plugin scripts 404
97
+ // or receive index.html in dev.
98
+ "/dashboard-plugins": BACKEND
99
+ }
100
+ }
101
+ });
102
+ export {
103
+ vite_config_default as default
104
+ };
105
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvaG9tZS9ydW5uZXIvd29ya3NwYWNlL3dlYlwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvcnVubmVyL3dvcmtzcGFjZS93ZWIvdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL2hvbWUvcnVubmVyL3dvcmtzcGFjZS93ZWIvdml0ZS5jb25maWcudHNcIjtpbXBvcnQgeyBkZWZpbmVDb25maWcsIHR5cGUgUGx1Z2luIH0gZnJvbSBcInZpdGVcIjtcbmltcG9ydCByZWFjdCBmcm9tIFwiQHZpdGVqcy9wbHVnaW4tcmVhY3RcIjtcbmltcG9ydCB0YWlsd2luZGNzcyBmcm9tIFwiQHRhaWx3aW5kY3NzL3ZpdGVcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5cbmNvbnN0IEJBQ0tFTkQgPSBwcm9jZXNzLmVudi5OQVNURUNIX0RBU0hCT0FSRF9VUkwgPz8gXCJodHRwOi8vMTI3LjAuMC4xOjkxMTlcIjtcblxuLyoqXG4gKiBJbiBwcm9kdWN0aW9uIHRoZSBQeXRob24gYG5hc3RlY2ggZGFzaGJvYXJkYCBzZXJ2ZXIgaW5qZWN0cyBhIG9uZS1zaG90XG4gKiBzZXNzaW9uIHRva2VuIGludG8gYGluZGV4Lmh0bWxgIChzZWUgYG5hc3RlY2hfY2xpL3dlYl9zZXJ2ZXIucHlgKS4gVGhlXG4gKiBWaXRlIGRldiBzZXJ2ZXIgc2VydmVzIGl0cyBvd24gYGluZGV4Lmh0bWxgLCBzbyB1bmxlc3Mgd2UgZm9yd2FyZCB0aGF0XG4gKiB0b2tlbiwgZXZlcnkgcHJvdGVjdGVkIGAvYXBpLypgIGNhbGwgNDAxcy5cbiAqXG4gKiBUaGlzIHBsdWdpbiBmZXRjaGVzIHRoZSBydW5uaW5nIGRhc2hib2FyZCdzIGBpbmRleC5odG1sYCBvbiBlYWNoIGRldiBwYWdlXG4gKiBsb2FkLCBzY3JhcGVzIHRoZSBgd2luZG93Ll9fTkFTVEVDSF9TRVNTSU9OX1RPS0VOX19gIGFzc2lnbm1lbnQsIGFuZFxuICogcmUtaW5qZWN0cyBpdCBpbnRvIHRoZSBkZXYgSFRNTC4gTm8tb3AgaW4gcHJvZHVjdGlvbiBidWlsZHMuXG4gKi9cbi8qKlxuICogUmVtYXAgQG5hc3RlY2gtYWkvdWkgXHUyMTkyIEBuYXN0ZWNoYWkvdWkgc28gVml0ZSdzIG1vZHVsZSByZXNvbHZlclxuICogZm9sbG93cyB0aGUgcGFja2FnZSdzIGV4cG9ydHMgbWFwIGluc3RlYWQgb2YgYSByYXcgZmlsZXN5c3RlbSBwYXRoLlxuICovXG5mdW5jdGlvbiBuYXN0ZWNoVWlBbGlhcygpOiBQbHVnaW4ge1xuICByZXR1cm4ge1xuICAgIG5hbWU6IFwibmFzdGVjaDp1aS1hbGlhc1wiLFxuICAgIGVuZm9yY2U6IFwicHJlXCIsXG4gICAgcmVzb2x2ZUlkKGlkLCBpbXBvcnRlciwgb3B0aW9ucykge1xuICAgICAgaWYgKGlkLnN0YXJ0c1dpdGgoXCJAbmFzdGVjaC1haS91aVwiKSkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlKFxuICAgICAgICAgIGlkLnJlcGxhY2UoXCJAbmFzdGVjaC1haS91aVwiLCBcIkBuYXN0ZWNoYWkvdWlcIiksXG4gICAgICAgICAgaW1wb3J0ZXIsXG4gICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9LFxuICB9O1xufVxuXG5mdW5jdGlvbiBuYXN0ZWNoRGV2VG9rZW4oKTogUGx1Z2luIHtcbiAgY29uc3QgVE9LRU5fUkUgPSAvd2luZG93XFwuX19OQVNURUNIX1NFU1NJT05fVE9LRU5fX1xccyo9XFxzKlwiKFteXCJdKylcIi87XG4gIGNvbnN0IEVNQkVEREVEX1JFID1cbiAgICAvd2luZG93XFwuX19OQVNURUNIX0RBU0hCT0FSRF9FTUJFRERFRF9DSEFUX19cXHMqPVxccyoodHJ1ZXxmYWxzZSkvO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogXCJuYXN0ZWNoOmRldi1zZXNzaW9uLXRva2VuXCIsXG4gICAgYXBwbHk6IFwic2VydmVcIixcbiAgICBhc3luYyB0cmFuc2Zvcm1JbmRleEh0bWwoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaChCQUNLRU5ELCB7IGhlYWRlcnM6IHsgYWNjZXB0OiBcInRleHQvaHRtbFwiIH0gfSk7XG4gICAgICAgIGNvbnN0IGh0bWwgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgICBjb25zdCBtYXRjaCA9IGh0bWwubWF0Y2goVE9LRU5fUkUpO1xuICAgICAgICBpZiAoIW1hdGNoKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgYFtuYXN0ZWNoXSBDb3VsZCBub3QgZmluZCBzZXNzaW9uIHRva2VuIGluICR7QkFDS0VORH0gXHUyMDE0IGAgK1xuICAgICAgICAgICAgICBgaXMgXFxgbmFzdGVjaCBkYXNoYm9hcmRcXGAgcnVubmluZz8gL2FwaSBjYWxscyB3aWxsIDQwMS5gLFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGVtYmVkZGVkTWF0Y2ggPSBodG1sLm1hdGNoKEVNQkVEREVEX1JFKTtcbiAgICAgICAgY29uc3QgZW1iZWRkZWRKcyA9IGVtYmVkZGVkTWF0Y2ggPyBlbWJlZGRlZE1hdGNoWzFdIDogXCJ0cnVlXCI7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdGFnOiBcInNjcmlwdFwiLFxuICAgICAgICAgICAgaW5qZWN0VG86IFwiaGVhZFwiLFxuICAgICAgICAgICAgY2hpbGRyZW46XG4gICAgICAgICAgICAgIGB3aW5kb3cuX19OQVNURUNIX1NFU1NJT05fVE9LRU5fXz1cIiR7bWF0Y2hbMV19XCI7YCArXG4gICAgICAgICAgICAgIGB3aW5kb3cuX19OQVNURUNIX0RBU0hCT0FSRF9FTUJFRERFRF9DSEFUX189JHtlbWJlZGRlZEpzfTtgLFxuICAgICAgICAgIH0sXG4gICAgICAgIF07XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGBbbmFzdGVjaF0gRGFzaGJvYXJkIGF0ICR7QkFDS0VORH0gdW5yZWFjaGFibGUgXHUyMDE0IGAgK1xuICAgICAgICAgICAgYHN0YXJ0IGl0IHdpdGggXFxgbmFzdGVjaCBkYXNoYm9hcmRcXGAgb3Igc2V0IE5BU1RFQ0hfREFTSEJPQVJEX1VSTC4gYCArXG4gICAgICAgICAgICBgKCR7KGVyciBhcyBFcnJvcikubWVzc2FnZX0pYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9LFxuICB9O1xufVxuXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoe1xuICBwbHVnaW5zOiBbcmVhY3QoKSwgdGFpbHdpbmRjc3MoKSwgbmFzdGVjaFVpQWxpYXMoKSwgbmFzdGVjaERldlRva2VuKCldLFxuICByZXNvbHZlOiB7XG4gICAgYWxpYXM6IHtcbiAgICAgIFwiQFwiOiBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCBcIi4vc3JjXCIpLFxuICAgIH0sXG4gICAgLy8gV2hlbiBAbmFzdGVjaC1haS91aSBpcyBzeW1saW5rZWQgdmlhIGBmaWxlOi4uLy4uL2Rlc2lnbi1sYW5ndWFnZWAsXG4gICAgLy8gTm9kZSdzIG1vZHVsZSByZXNvbHV0aW9uIHdvdWxkIHBpY2sgdXAgc2hhcmVkIGRlcHMgZnJvbVxuICAgIC8vIGRlc2lnbi1sYW5ndWFnZS9ub2RlX21vZHVsZXMvKiwgZ2l2aW5nIHVzIHR3byBjb3BpZXMgKyBicmVha2luZ1xuICAgIC8vIGhvb2tzICh1c2VSZWYtb2YtbnVsbCksIHdlYmdsIGNvbnRleHRzLCBldGMuIEZvcmNlIGV2ZXJ5dGhpbmcgdGhhdFxuICAgIC8vIGV4aXN0cyBpbiBCT1RIIHBsYWNlcyB0byB1c2UgdGhlIGRhc2hib2FyZCdzIGNvcHkuXG4gICAgLy9cbiAgICAvLyBEb24ndCBsaXN0IHBhY2thZ2VzIGhlcmUgdGhhdCBvbmx5IGV4aXN0IGluIHRoZSBEUyAobmFub3N0b3JlcyxcbiAgICAvLyBAbmFub3N0b3Jlcy9yZWFjdCkgXHUyMDE0IFZpdGUgZGVkdXBlIGVycm9ycyBvdXQgd2hlbiBpdCBjYW4ndCBmaW5kXG4gICAgLy8gdGhlbSBhdCB0aGUgcHJvamVjdCByb290LlxuICAgIGRlZHVwZTogW1xuICAgICAgXCJyZWFjdFwiLFxuICAgICAgXCJyZWFjdC1kb21cIixcbiAgICAgIFwiQHJlYWN0LXRocmVlL2ZpYmVyXCIsXG4gICAgICBcIkBvYnNlcnZhYmxlaHEvcGxvdFwiLFxuICAgICAgXCJ0aHJlZVwiLFxuICAgICAgXCJsZXZhXCIsXG4gICAgICBcImdzYXBcIixcbiAgICBdLFxuICB9LFxuICBidWlsZDoge1xuICAgIG91dERpcjogXCIuLi9uYXN0ZWNoX2NsaS93ZWJfZGlzdFwiLFxuICAgIGVtcHR5T3V0RGlyOiB0cnVlLFxuICB9LFxuICBzZXJ2ZXI6IHtcbiAgICBob3N0OiBcIjAuMC4wLjBcIixcbiAgICBwb3J0OiA1MDAwLFxuICAgIGFsbG93ZWRIb3N0czogdHJ1ZSxcbiAgICBwcm94eToge1xuICAgICAgXCIvYXBpXCI6IHtcbiAgICAgICAgdGFyZ2V0OiBCQUNLRU5ELFxuICAgICAgICB3czogdHJ1ZSxcbiAgICAgIH0sXG4gICAgICAvLyBTYW1lIGhvc3QgYXMgYG5hc3RlY2ggZGFzaGJvYXJkYCBtdXN0IHNlcnZlIHRoZXNlOyBWaXRlIGhhcyBub1xuICAgICAgLy8gZGFzaGJvYXJkLXBsdWdpbnMvKiBmaWxlcywgc28gd2l0aG91dCB0aGlzLCBwbHVnaW4gc2NyaXB0cyA0MDRcbiAgICAgIC8vIG9yIHJlY2VpdmUgaW5kZXguaHRtbCBpbiBkZXYuXG4gICAgICBcIi9kYXNoYm9hcmQtcGx1Z2luc1wiOiBCQUNLRU5ELFxuICAgIH0sXG4gIH0sXG59KTtcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFB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