reflex-agent 0.2.2 → 0.2.4

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 (156) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +97 -97
  3. package/.next/app-path-routes-manifest.json +10 -10
  4. package/.next/build-manifest.json +5 -5
  5. package/.next/prerender-manifest.json +3 -51
  6. package/.next/react-loadable-manifest.json +1 -1
  7. package/.next/server/app/_not-found/page.js +1 -1
  8. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/_not-found.html +1 -1
  10. package/.next/server/app/_not-found.rsc +3 -3
  11. package/.next/server/app/agents/[agentId]/page.js +2 -2
  12. package/.next/server/app/agents/[agentId]/page_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/agents/[agentId]/respond/route.js +1 -1
  14. package/.next/server/app/api/agents/[agentId]/respond/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/images/[rootId]/[file]/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/oauth/callback/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/oauth/start/route_client-reference-manifest.js +1 -1
  18. package/.next/server/app/api/roots/[id]/attachments/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/roots/[id]/chat/[topicId]/send/route.js +1 -1
  20. package/.next/server/app/api/roots/[id]/chat/[topicId]/send/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/roots/[id]/chat/[topicId]/stop/route.js +1 -1
  22. package/.next/server/app/api/roots/[id]/chat/[topicId]/stop/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/roots/[id]/chat/[topicId]/stream/route.js +1 -1
  24. package/.next/server/app/api/roots/[id]/chat/[topicId]/stream/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/roots/[id]/dashboard/route.js +1 -1
  26. package/.next/server/app/api/roots/[id]/dashboard/route.js.nft.json +1 -1
  27. package/.next/server/app/api/roots/[id]/dashboard/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/roots/[id]/suggestions/route.js +1 -1
  29. package/.next/server/app/api/roots/[id]/suggestions/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/utilities/[scope]/[id]/bundle.js/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/utilities/[scope]/[id]/host/route.js +1 -1
  32. package/.next/server/app/api/utilities/[scope]/[id]/host/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/utilities/[scope]/[id]/host-api.mjs/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/utilities/[scope]/[id]/host-ui.mjs/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/utilities/[scope]/[id]/iframe/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/utilities/[scope]/[id]/style.css/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/audit/page.js +1 -1
  38. package/.next/server/app/audit/page.js.nft.json +1 -1
  39. package/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  40. package/.next/server/app/index.html +1 -1
  41. package/.next/server/app/index.rsc +3 -3
  42. package/.next/server/app/onboarding/page.js +2 -2
  43. package/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  44. package/.next/server/app/page.js +2 -2
  45. package/.next/server/app/page.js.nft.json +1 -1
  46. package/.next/server/app/page_client-reference-manifest.js +1 -1
  47. package/.next/server/app/roots/[id]/chat/[topicId]/page.js +2 -2
  48. package/.next/server/app/roots/[id]/chat/[topicId]/page.js.nft.json +1 -1
  49. package/.next/server/app/roots/[id]/chat/[topicId]/page_client-reference-manifest.js +1 -1
  50. package/.next/server/app/roots/[id]/kb/[...slug]/page.js +3 -3
  51. package/.next/server/app/roots/[id]/kb/[...slug]/page.js.nft.json +1 -1
  52. package/.next/server/app/roots/[id]/kb/[...slug]/page_client-reference-manifest.js +1 -1
  53. package/.next/server/app/roots/[id]/page.js +3 -3
  54. package/.next/server/app/roots/[id]/page.js.nft.json +1 -1
  55. package/.next/server/app/roots/[id]/page_client-reference-manifest.js +1 -1
  56. package/.next/server/app/roots/[id]/workflows/[wfId]/page.js +2 -2
  57. package/.next/server/app/roots/[id]/workflows/[wfId]/page_client-reference-manifest.js +1 -1
  58. package/.next/server/app/roots/[id]/workflows/page.js +1 -1
  59. package/.next/server/app/roots/[id]/workflows/page.js.nft.json +1 -1
  60. package/.next/server/app/roots/[id]/workflows/page_client-reference-manifest.js +1 -1
  61. package/.next/server/app/roots/new/page.js +2 -2
  62. package/.next/server/app/roots/new/page_client-reference-manifest.js +1 -1
  63. package/.next/server/app/settings/page.js +5 -5
  64. package/.next/server/app/settings/page.js.nft.json +1 -1
  65. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  66. package/.next/server/app/share/[id]/file/page.js +1 -1
  67. package/.next/server/app/share/[id]/file/page_client-reference-manifest.js +1 -1
  68. package/.next/server/app/share/[id]/page.js +2 -2
  69. package/.next/server/app/share/[id]/page.js.nft.json +1 -1
  70. package/.next/server/app/share/[id]/page_client-reference-manifest.js +1 -1
  71. package/.next/server/app/utilities/[scope]/[id]/page.js +2 -2
  72. package/.next/server/app/utilities/[scope]/[id]/page.js.nft.json +1 -1
  73. package/.next/server/app/utilities/[scope]/[id]/page_client-reference-manifest.js +1 -1
  74. package/.next/server/app/utilities/page.js +4 -4
  75. package/.next/server/app/utilities/page_client-reference-manifest.js +1 -1
  76. package/.next/server/app-paths-manifest.json +10 -10
  77. package/.next/server/chunks/133.js +5 -5
  78. package/.next/server/chunks/{3610.js → 1410.js} +1 -1
  79. package/.next/server/chunks/1960.js +1 -1
  80. package/.next/server/chunks/1986.js +1 -1
  81. package/.next/server/chunks/2448.js +3 -0
  82. package/.next/server/chunks/3332.js +1 -1
  83. package/.next/server/chunks/3953.js +4 -0
  84. package/.next/server/chunks/4031.js +1 -1
  85. package/.next/server/chunks/5754.js +3 -0
  86. package/.next/server/chunks/{1455.js → 7097.js} +1 -1
  87. package/.next/server/chunks/7782.js +1 -0
  88. package/.next/server/chunks/7987.js +1 -0
  89. package/.next/server/chunks/810.js +1 -0
  90. package/.next/server/chunks/9098.js +1 -1
  91. package/.next/server/chunks/9328.js +1 -1
  92. package/.next/server/chunks/9579.js +1 -1
  93. package/.next/server/middleware-build-manifest.js +1 -1
  94. package/.next/server/middleware-manifest.json +5 -5
  95. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  96. package/.next/server/pages/404.html +1 -1
  97. package/.next/server/pages/500.html +1 -1
  98. package/.next/server/server-reference-manifest.js +1 -1
  99. package/.next/server/server-reference-manifest.json +1 -1
  100. package/.next/static/chunks/2488-c9590facb4b9f184.js +1 -0
  101. package/.next/static/chunks/2684-257d38989ef53935.js +1 -0
  102. package/.next/static/chunks/4108.fb9f99a9c899ef54.js +1 -0
  103. package/.next/static/chunks/6231-d83c1544bbea8424.js +1 -0
  104. package/.next/static/chunks/9496-75ccd3fadb294fba.js +1 -0
  105. package/.next/static/chunks/992-4e7b7f722c629e21.js +1 -0
  106. package/.next/static/chunks/app/layout-9a59ed07c18cb786.js +1 -0
  107. package/.next/static/chunks/app/onboarding/{page-21cb4c231aa388b2.js → page-79f07a813ea2abfe.js} +1 -1
  108. package/.next/static/chunks/app/page-27f4b98b02ac4f79.js +1 -0
  109. package/.next/static/chunks/app/roots/[id]/chat/[topicId]/{page-495551937b420b76.js → page-8db2d0b75cd333c8.js} +1 -1
  110. package/.next/static/chunks/app/roots/[id]/kb/[...slug]/page-873b131eec3a2f30.js +1 -0
  111. package/.next/static/chunks/app/roots/[id]/page-270d0d49eb668784.js +1 -0
  112. package/.next/static/chunks/app/roots/[id]/workflows/[wfId]/page-7c1f10dbe0bcb9ad.js +1 -0
  113. package/.next/static/chunks/app/roots/new/page-ac1a9f6379710ca2.js +1 -0
  114. package/.next/static/chunks/app/settings/page-81cb1393e817dfc3.js +1 -0
  115. package/.next/static/chunks/app/share/[id]/page-2d123f0a99e1606f.js +1 -0
  116. package/.next/static/chunks/app/utilities/[scope]/[id]/page-0bbb8d17af80c1da.js +1 -0
  117. package/.next/static/chunks/app/utilities/page-e6ce673b9357bf1f.js +1 -0
  118. package/.next/static/chunks/{webpack-5a9c11af9261dd8a.js → webpack-5fca180586957874.js} +1 -1
  119. package/.next/trace +46 -46
  120. package/README.md +4 -1
  121. package/dist/bin/preload.js +12 -4
  122. package/dist/bin/preload.js.map +1 -1
  123. package/dist/lib/reflex/commands/start.js +33 -0
  124. package/dist/lib/reflex/commands/start.js.map +1 -1
  125. package/lib/server/utilities/worker-bootstrap.js +87 -0
  126. package/package.json +4 -3
  127. package/.next/server/app/roots/new.html +0 -1
  128. package/.next/server/app/roots/new.meta +0 -7
  129. package/.next/server/app/roots/new.rsc +0 -21
  130. package/.next/server/app/settings.html +0 -1
  131. package/.next/server/app/settings.meta +0 -7
  132. package/.next/server/app/settings.rsc +0 -22
  133. package/.next/server/chunks/2977.js +0 -1
  134. package/.next/server/chunks/3076.js +0 -1
  135. package/.next/server/chunks/4567.js +0 -3
  136. package/.next/server/chunks/6809.js +0 -3
  137. package/.next/server/chunks/9731.js +0 -4
  138. package/.next/server/chunks/9905.js +0 -1
  139. package/.next/static/chunks/1521-747af538ca131a44.js +0 -1
  140. package/.next/static/chunks/2641-a7e626d59cd967e8.js +0 -1
  141. package/.next/static/chunks/2994-8b82d24eeb6d4a3d.js +0 -1
  142. package/.next/static/chunks/4108.610ef39d7984f25f.js +0 -1
  143. package/.next/static/chunks/6330-d46c4ceb6e522567.js +0 -1
  144. package/.next/static/chunks/9837-49687140bc7ce084.js +0 -1
  145. package/.next/static/chunks/app/layout-e51afdc17d552d1a.js +0 -1
  146. package/.next/static/chunks/app/page-1fa224b4a5160227.js +0 -1
  147. package/.next/static/chunks/app/roots/[id]/kb/[...slug]/page-1b67558878e2cc43.js +0 -1
  148. package/.next/static/chunks/app/roots/[id]/page-0431ab3465b742f1.js +0 -1
  149. package/.next/static/chunks/app/roots/[id]/workflows/[wfId]/page-62fa8cfbf3c85457.js +0 -1
  150. package/.next/static/chunks/app/roots/new/page-918f809668694de6.js +0 -1
  151. package/.next/static/chunks/app/settings/page-9cf2f101424ec84c.js +0 -1
  152. package/.next/static/chunks/app/share/[id]/page-325593b9c70ca17c.js +0 -1
  153. package/.next/static/chunks/app/utilities/[scope]/[id]/page-fe0e445961d83cc2.js +0 -1
  154. package/.next/static/chunks/app/utilities/page-a1359423e5a9e7de.js +0 -1
  155. /package/.next/static/{6-mOMrzbiPmI97utKVIuW → og_wC7UPkGtJDiapaTgBr}/_buildManifest.js +0 -0
  156. /package/.next/static/{6-mOMrzbiPmI97utKVIuW → og_wC7UPkGtJDiapaTgBr}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -24,6 +24,9 @@ reflex start # opens http://localhost:3210 in your browser
24
24
  reflex start --port 4000 --no-open
25
25
  ```
26
26
 
27
+ Dev runs on `:3211` by default so a `pnpm dev` and an installed
28
+ `reflex start` can co-exist without a port collision.
29
+
27
30
  Home page lists registered "Reflex roots". Add a directory via the built-in
28
31
  file picker, then click **Run init** on the detail page to have the agent
29
32
  build the KB. The left sidebar shows the resulting MD tree under `.reflex/`;
@@ -42,7 +45,7 @@ reflex chat <dir> # open a chat scoped to dir's KB
42
45
 
43
46
  ```sh
44
47
  pnpm install
45
- pnpm dev # http://localhost:3210 (Next dev server with HMR)
48
+ pnpm dev # http://localhost:3211 (Next dev server with HMR)
46
49
  pnpm build # produce dist/ + .next/ for `reflex start`
47
50
  ```
48
51
 
@@ -1,14 +1,22 @@
1
- // Sets REFLEX_HOME for the prod CLI before any module reads it.
1
+ // Sets env vars the prod CLI needs before any module reads them.
2
2
  //
3
3
  // ESM evaluates imports in DFS post-order, so importing this file first
4
- // from `bin/cli.ts` guarantees the env var is set before sibling imports
5
- // (registry, settings, etc.) read it at their module-load time.
4
+ // from `bin/cli.ts` guarantees these are set before sibling imports
5
+ // (registry, settings, worker-pool, etc.) read them at module-load time.
6
6
  //
7
7
  // Dev (`pnpm dev` → Next directly) doesn't go through bin/, so it keeps
8
- // the `~/.reflex` default from `reflexHome()`.
8
+ // the `~/.reflex` default and process.cwd()-based fallbacks.
9
9
  import os from "node:os";
10
10
  import path from "node:path";
11
+ import { fileURLToPath } from "node:url";
11
12
  if (!process.env.REFLEX_HOME) {
12
13
  process.env.REFLEX_HOME = path.join(os.homedir(), ".reflex-agent");
13
14
  }
15
+ // Package install root. dist/bin/preload.js → repo root is 2 levels up.
16
+ // Used by worker-pool to locate `lib/server/utilities/worker-bootstrap.js`
17
+ // without depending on `process.cwd()` (which is the user's current dir,
18
+ // not the package install location).
19
+ if (!process.env.REFLEX_PKG_ROOT) {
20
+ process.env.REFLEX_PKG_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
21
+ }
14
22
  //# sourceMappingURL=preload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"preload.js","sourceRoot":"","sources":["../../bin/preload.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AACzE,gEAAgE;AAChE,EAAE;AACF,wEAAwE;AACxE,+CAA+C;AAC/C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AACrE,CAAC"}
1
+ {"version":3,"file":"preload.js","sourceRoot":"","sources":["../../bin/preload.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,wEAAwE;AACxE,oEAAoE;AACpE,yEAAyE;AACzE,EAAE;AACF,wEAAwE;AACxE,6DAA6D;AAC7D,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AACrE,CAAC;AAED,wEAAwE;AACxE,2EAA2E;AAC3E,yEAAyE;AACzE,qCAAqC;AACrC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC,OAAO,CACxC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAC5C,IAAI,EACJ,IAAI,CACL,CAAC;AACJ,CAAC"}
@@ -7,6 +7,7 @@ import { reflexHome } from "../home.js";
7
7
  export async function runStart(opts) {
8
8
  const pkgRoot = await findPackageRoot();
9
9
  await assertBuilt(pkgRoot);
10
+ await rewriteBuildPaths(pkgRoot);
10
11
  // Lazy-import to avoid pulling Next into CLI-only commands.
11
12
  const nextMod = (await import("next"));
12
13
  const app = nextMod.default({ dev: false, dir: pkgRoot });
@@ -47,6 +48,38 @@ async function assertBuilt(pkgRoot) {
47
48
  throw new Error(`Reflex web bundle not found at ${pkgRoot}/.next. If running from source, run \`pnpm run build\` first.`);
48
49
  }
49
50
  }
51
+ /**
52
+ * Next bakes the build-time project path into `required-server-files.json`
53
+ * (`appDir`, `outputFileTracingRoot`). When the package is built in CI and
54
+ * installed on a user's machine those paths point at `/home/runner/...`
55
+ * which doesn't exist — rewrite them to the actual install location.
56
+ *
57
+ * Idempotent: if the values already match `pkgRoot`, skip the write.
58
+ */
59
+ async function rewriteBuildPaths(pkgRoot) {
60
+ const file = path.join(pkgRoot, ".next", "required-server-files.json");
61
+ let raw;
62
+ try {
63
+ raw = await fs.readFile(file, "utf8");
64
+ }
65
+ catch {
66
+ return;
67
+ }
68
+ const data = JSON.parse(raw);
69
+ let changed = false;
70
+ if (data.appDir && data.appDir !== pkgRoot) {
71
+ data.appDir = pkgRoot;
72
+ changed = true;
73
+ }
74
+ if (data.config?.outputFileTracingRoot &&
75
+ data.config.outputFileTracingRoot !== pkgRoot) {
76
+ data.config.outputFileTracingRoot = pkgRoot;
77
+ changed = true;
78
+ }
79
+ if (changed) {
80
+ await fs.writeFile(file, JSON.stringify(data, null, 2));
81
+ }
82
+ }
50
83
  function displayHost(host) {
51
84
  if (host === "0.0.0.0" || host === "::")
52
85
  return "localhost";
@@ -1 +1 @@
1
- {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../../lib/reflex/commands/start.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../../lib/reflex/commands/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ // Static entry for every utility server-action Worker. We hand-roll plain JS
2
+ // (no TS) so we don't need a build step for this file. It:
3
+ // 1. Sets up a `reflex` host stub that RPC-calls the parent thread.
4
+ // 2. Dynamically imports the action bundle.
5
+ // 3. Awaits the named export with the args + host, returns the result.
6
+ // 4. Times out and exits cleanly.
7
+ //
8
+ // The action bundle is built by lib/server/utilities/build.ts with
9
+ // `external: ["@host/api"]`, so the bundle has `import { reflex } from
10
+ // "@host/api"`. We intercept that via Node's loader hook (worker_threads
11
+ // resolveAliases) — but since we can't easily inject one, we expose the
12
+ // host via globalThis and rewrite the bundle's import at build time?
13
+ //
14
+ // Practical solution: the build step injects a small shim file at the top
15
+ // that aliases `@host/api` to `globalThis.__reflexHost`. See build.ts.
16
+ // This bootstrap just sets up that global.
17
+
18
+ // Node treats this file as ESM (package.json has "type": "module"), so we
19
+ // use top-level `import` instead of `require`.
20
+ import { parentPort, workerData } from "node:worker_threads";
21
+
22
+ if (!parentPort) {
23
+ throw new Error("worker-bootstrap.js must be loaded as a worker_threads child");
24
+ }
25
+
26
+ const pending = new Map();
27
+ let nextRpcId = 1;
28
+
29
+ const reflex = new Proxy(
30
+ {},
31
+ {
32
+ get(_target, namespace) {
33
+ if (typeof namespace !== "string") return undefined;
34
+ return new Proxy(
35
+ {},
36
+ {
37
+ get(_t, method) {
38
+ if (typeof method !== "string") return undefined;
39
+ return (args) =>
40
+ new Promise((resolve, reject) => {
41
+ const id = nextRpcId++;
42
+ pending.set(id, { resolve, reject });
43
+ parentPort.postMessage({
44
+ type: "host-rpc",
45
+ id,
46
+ method: `${namespace}.${method}`,
47
+ args,
48
+ });
49
+ });
50
+ },
51
+ },
52
+ );
53
+ },
54
+ },
55
+ );
56
+
57
+ globalThis.__reflexHost = reflex;
58
+
59
+ parentPort.on("message", async (msg) => {
60
+ if (msg && msg.type === "host-rpc-result") {
61
+ const slot = pending.get(msg.id);
62
+ if (!slot) return;
63
+ pending.delete(msg.id);
64
+ if (msg.ok) slot.resolve(msg.result);
65
+ else slot.reject(new Error(msg.error || "rpc failed"));
66
+ return;
67
+ }
68
+ if (msg && msg.type === "invoke") {
69
+ try {
70
+ const mod = await import(workerData.bundleUrl);
71
+ const fn = mod[workerData.actionName] ?? mod.default;
72
+ if (typeof fn !== "function") {
73
+ throw new Error(
74
+ `action "${workerData.actionName}" must export a function (named export or default)`,
75
+ );
76
+ }
77
+ const result = await fn(msg.args, reflex);
78
+ parentPort.postMessage({ type: "invoke-result", ok: true, result });
79
+ } catch (err) {
80
+ parentPort.postMessage({
81
+ type: "invoke-result",
82
+ ok: false,
83
+ error: err && err.message ? err.message : String(err),
84
+ });
85
+ }
86
+ }
87
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reflex-agent",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "private": false,
5
5
  "description": "Local-first knowledge base built by an agent over a chosen directory.",
6
6
  "license": "MIT",
@@ -21,6 +21,7 @@
21
21
  "dist",
22
22
  ".next",
23
23
  "next.config.ts",
24
+ "lib/server/utilities/worker-bootstrap.js",
24
25
  "packages/utilities",
25
26
  "README.md",
26
27
  "LICENSE"
@@ -29,8 +30,8 @@
29
30
  "access": "public"
30
31
  },
31
32
  "scripts": {
32
- "dev": "next dev -p 3210",
33
- "start": "next start -p 3210",
33
+ "dev": "next dev -p 3211",
34
+ "start": "next start -p 3211",
34
35
  "build": "next build && pnpm run build:cli",
35
36
  "build:cli": "tsc -p tsconfig.cli.json",
36
37
  "typecheck": "tsc --noEmit && tsc -p tsconfig.cli.json --noEmit",
@@ -1 +0,0 @@
1
- <!DOCTYPE html><!--6_mOMrzbiPmI97utKVIuW--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/87e01f779d555d04.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-5a9c11af9261dd8a.js"/><script src="/_next/static/chunks/6fe292aa-7126ff9d6732e864.js" async=""></script><script src="/_next/static/chunks/146-ccee3b26755b68c8.js" async=""></script><script src="/_next/static/chunks/main-app-ebe67847147d19aa.js" async=""></script><script src="/_next/static/chunks/4400-cdb1f7913ae34e09.js" async=""></script><script src="/_next/static/chunks/1217-407174d9b164a499.js" async=""></script><script src="/_next/static/chunks/3335-5647a38ab2cfa88d.js" async=""></script><script src="/_next/static/chunks/5097-f07f6aeee3f60a33.js" async=""></script><script src="/_next/static/chunks/app/roots/new/page-918f809668694de6.js" async=""></script><script src="/_next/static/chunks/9045-731ff0865352dd95.js" async=""></script><script src="/_next/static/chunks/app/layout-e51afdc17d552d1a.js" async=""></script><title>Reflex</title><meta name="description" content="Local-first knowledge base built by an agent."/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div class="h-screen flex"><aside class="w-72 shrink-0 border-r bg-muted/30 flex flex-col"><div class="px-4 py-4 flex items-center gap-2 border-b"><span class="reflex-gradient inline-flex h-7 w-7 items-center justify-center rounded-lg text-white shadow-sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles h-4 w-4"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"></path><path d="M20 3v4"></path><path d="M22 5h-4"></path><path d="M4 17v2"></path><path d="M5 18H3"></path></svg></span><div class="leading-tight"><a class="text-sm font-semibold tracking-tight hover:underline" href="/">Reflex</a><div class="text-[10px] uppercase tracking-wider text-muted-foreground">knowledge base</div></div></div><div dir="ltr" data-slot="scroll-area" class="relative flex-1" style="position:relative;--radix-scroll-area-corner-width:0px;--radix-scroll-area-corner-height:0px"><style>[data-radix-scroll-area-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-scroll-area-viewport]::-webkit-scrollbar{display:none}</style><div data-radix-scroll-area-viewport="" data-slot="scroll-area-viewport" class="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1" style="overflow-x:hidden;overflow-y:hidden"><div style="min-width:100%;display:table"><nav class="px-2 pt-3 pb-6"><div class="px-2 mb-1 text-[10px] uppercase tracking-wider text-muted-foreground">Пространства</div><div class="px-2 py-3 text-xs text-muted-foreground">Пока пусто.</div><div class="mt-2 px-2"><a data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 h-7 w-full justify-start text-xs" href="/roots/new"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-plus mr-1 h-3.5 w-3.5"><path d="M12 10v6"></path><path d="M9 13h6"></path><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"></path></svg> Добавить пространство</a></div></nav></div></div></div><div data-orientation="horizontal" role="none" data-slot="separator" class="shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px"></div><div class="px-2 py-2 space-y-0.5"><a data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 w-full justify-start" href="/utilities"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-boxes mr-2 h-4 w-4"><path d="M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z"></path><path d="m7 16.5-4.74-2.85"></path><path d="m7 16.5 5-3"></path><path d="M7 16.5v5.17"></path><path d="M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z"></path><path d="m17 16.5-5-3"></path><path d="m17 16.5 4.74-2.85"></path><path d="M17 16.5v5.17"></path><path d="M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z"></path><path d="M12 8 7.26 5.15"></path><path d="m12 8 4.74-2.85"></path><path d="M12 13.5V8"></path></svg> Мини-приложения</a><a data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 w-full justify-start" href="/audit"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-search mr-2 h-4 w-4"><path d="M14 2v4a2 2 0 0 0 2 2h4"></path><path d="M4.268 21a2 2 0 0 0 1.727 1H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"></path><path d="m9 18-1.5-1.5"></path><circle cx="5" cy="14" r="3"></circle></svg> Аудит</a><a data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 w-full justify-start" href="/settings"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-settings mr-2 h-4 w-4"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"></path><circle cx="12" cy="12" r="3"></circle></svg> Settings</a></div></aside><main class="flex-1 min-w-0 flex flex-col"><main class="mx-auto w-full max-w-4xl flex-1 px-6 py-10"><header class="mb-8"><a data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 mb-2 -ml-3" href="/"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-left mr-1 h-4 w-4"><path d="m12 19-7-7 7-7"></path><path d="M19 12H5"></path></svg> Back</a><h1 class="text-3xl font-semibold tracking-tight">Add a directory</h1><p class="text-muted-foreground mt-1">Pick the directory you want Reflex to index. After it&#x27;s registered, you can run the initial analysis from the directory page.</p></header><div data-slot="card" class="flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm"><div data-slot="card-header" class="@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6"><div data-slot="card-title" class="leading-none font-semibold flex items-center justify-between gap-4"><span>Browse</span><button data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-house mr-1 h-4 w-4"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"></path><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path></svg> Home</button></div><form class="flex gap-2 mt-2"><input data-slot="input" class="h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 font-mono text-xs" placeholder="/absolute/path" value="/home/runner"/><button data-slot="button" data-variant="secondary" data-size="default" class="inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 bg-secondary text-secondary-foreground hover:bg-secondary/80 h-9 px-4 py-2 has-[&gt;svg]:px-3" type="submit"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-refresh-cw h-4 w-4"><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path><path d="M21 3v5h-5"></path><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path><path d="M8 16H3v5"></path></svg></button></form></div><div data-orientation="horizontal" role="none" data-slot="separator" class="shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px"></div><div data-slot="card-content" class="px-2 py-2"><div dir="ltr" data-slot="scroll-area" class="relative h-[460px]" style="position:relative;--radix-scroll-area-corner-width:0px;--radix-scroll-area-corner-height:0px"><style>[data-radix-scroll-area-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-scroll-area-viewport]::-webkit-scrollbar{display:none}</style><div data-radix-scroll-area-viewport="" data-slot="scroll-area-viewport" class="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1" style="overflow-x:hidden;overflow-y:hidden"><div style="min-width:100%;display:table"><div class="px-2 py-1 flex items-center gap-2"><button data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 h-8" disabled=""><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-up mr-1 h-4 w-4"><path d="m18 15-6-6-6 6"></path></svg> Up</button><button type="button" class="flex-1 flex items-center gap-2 px-2 py-1 text-sm rounded-md hover:bg-accent bg-accent" title="/home/runner"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-open h-4 w-4 text-muted-foreground shrink-0"><path d="m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2"></path></svg><span class="truncate font-mono text-xs">.</span><span class="text-muted-foreground text-[11px] truncate">(<!-- -->runner<!-- -->)</span></button><button data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 h-8" title="Создать папку в runner"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-plus mr-1 h-4 w-4"><path d="M12 10v6"></path><path d="M9 13h6"></path><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"></path></svg> Создать</button><label class="flex items-center gap-1 text-xs text-muted-foreground select-none"><input type="checkbox"/>hidden</label></div><div data-orientation="horizontal" role="none" data-slot="separator" class="shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px my-1"></div><div class="px-4 py-10 text-center text-sm text-muted-foreground">No subdirectories.</div></div></div></div></div><div data-orientation="horizontal" role="none" data-slot="separator" class="shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px"></div><div data-slot="card-footer" class="px-6 [.border-t]:pt-6 flex items-center justify-between gap-4"><div class="text-xs text-muted-foreground font-mono truncate">Selected: <!-- -->/home/runner</div><button data-slot="button" data-variant="default" data-size="default" class="inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 bg-primary text-primary-foreground hover:bg-primary/90 h-9 px-4 py-2 has-[&gt;svg]:px-3">Add this directory</button></div></div></main><!--$--><!--/$--></main></div><section aria-label="Notifications alt+T" tabindex="-1" aria-live="polite" aria-relevant="additions text" aria-atomic="false"></section><script src="/_next/static/chunks/webpack-5a9c11af9261dd8a.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n3:I[26957,[],\"\"]\n4:I[97369,[],\"\"]\n6:I[21968,[],\"OutletBoundary\"]\n8:I[33705,[],\"AsyncMetadataOutlet\"]\na:I[21968,[],\"ViewportBoundary\"]\nc:I[21968,[],\"MetadataBoundary\"]\nd:\"$Sreact.suspense\"\nf:I[6287,[],\"\"]\n:HL[\"/_next/static/css/87e01f779d555d04.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"6-mOMrzbiPmI97utKVIuW\",\"p\":\"\",\"c\":[\"\",\"roots\",\"new\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"roots\",{\"children\":[\"new\",{\"children\":[\"__PAGE__\",{}]}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/87e01f779d555d04.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],\"$L2\"]}],{\"children\":[\"roots\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"new\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[\"$L5\",null,[\"$\",\"$L6\",null,{\"children\":[\"$L7\",[\"$\",\"$L8\",null,{\"promise\":\"$@9\"}]]}]]}],{},null,false]},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],null],[\"$\",\"$Lc\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$d\",null,{\"fallback\":null,\"children\":\"$Le\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"10:I[54400,[\"4400\",\"static/chunks/4400-cdb1f7913ae34e09.js\",\"1217\",\"static/chunks/1217-407174d9b164a499.js\",\"3335\",\"static/chunks/3335-5647a38ab2cfa88d.js\",\"5097\",\"static/chunks/5097-f07f6aeee3f60a33.js\",\"9429\",\"static/chunks/app/roots/new/page-918f809668694de6.js\"],\"\"]\n11:I[6797,[\"4400\",\"static/chunks/4400-cdb1f7913ae34e09.js\",\"1217\",\"static/chunks/1217-407174d9b164a499.js\",\"3335\",\"static/chunks/3335-5647a38ab2cfa88d.js\",\"5097\",\"static/chunks/5097-f07f6aeee3f60a33.js\",\"9429\",\"static/chunks/app/roots/new/page-918f809668694de6.js\"],\"DirectoryPicker\"]\n"])</script><script>self.__next_f.push([1,"5:[\"$\",\"main\",null,{\"className\":\"mx-auto w-full max-w-4xl flex-1 px-6 py-10\",\"children\":[[\"$\",\"header\",null,{\"className\":\"mb-8\",\"children\":[[\"$\",\"$L10\",null,{\"href\":\"/\",\"children\":[[\"$\",\"svg\",null,{\"ref\":\"$undefined\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"width\":24,\"height\":24,\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":2,\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"className\":\"lucide lucide-arrow-left mr-1 h-4 w-4\",\"children\":[[\"$\",\"path\",\"1l729n\",{\"d\":\"m12 19-7-7 7-7\"}],[\"$\",\"path\",\"x3x0zl\",{\"d\":\"M19 12H5\"}],\"$undefined\"]}],\" Back\"],\"data-slot\":\"button\",\"data-variant\":\"ghost\",\"data-size\":\"sm\",\"className\":\"inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [\u0026_svg]:pointer-events-none [\u0026_svg]:shrink-0 [\u0026_svg:not([class*='size-'])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[\u003esvg]:px-2.5 mb-2 -ml-3\",\"ref\":null}],[\"$\",\"h1\",null,{\"className\":\"text-3xl font-semibold tracking-tight\",\"children\":\"Add a directory\"}],[\"$\",\"p\",null,{\"className\":\"text-muted-foreground mt-1\",\"children\":\"Pick the directory you want Reflex to index. After it's registered, you can run the initial analysis from the directory page.\"}]]}],[\"$\",\"$L11\",null,{\"initialPath\":\"/home/runner\"}]]}]\n"])</script><script>self.__next_f.push([1,"b:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n7:null\n"])</script><script>self.__next_f.push([1,"9:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Reflex\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Local-first knowledge base built by an agent.\"}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"e:\"$9:metadata\"\n"])</script><script>self.__next_f.push([1,"12:I[10607,[\"4400\",\"static/chunks/4400-cdb1f7913ae34e09.js\",\"1217\",\"static/chunks/1217-407174d9b164a499.js\",\"5097\",\"static/chunks/5097-f07f6aeee3f60a33.js\",\"9045\",\"static/chunks/9045-731ff0865352dd95.js\",\"7177\",\"static/chunks/app/layout-e51afdc17d552d1a.js\"],\"AppSidebar\"]\n13:I[43450,[\"4400\",\"static/chunks/4400-cdb1f7913ae34e09.js\",\"1217\",\"static/chunks/1217-407174d9b164a499.js\",\"5097\",\"static/chunks/5097-f07f6aeee3f60a33.js\",\"9045\",\"static/chunks/9045-731ff0865352dd95.js\",\"7177\",\"static/chunks/app/layout-e51afdc17d552d1a.js\"],\"Toaster\"]\n"])</script><script>self.__next_f.push([1,"2:[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"children\":[[\"$\",\"div\",null,{\"className\":\"h-screen flex\",\"children\":[[\"$\",\"$L12\",null,{\"initialRoots\":[]}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 flex flex-col\",\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}],[\"$\",\"$L13\",null,{\"richColors\":true,\"closeButton\":true}]]}]}]\n"])</script></body></html>
@@ -1,7 +0,0 @@
1
- {
2
- "headers": {
3
- "x-nextjs-stale-time": "300",
4
- "x-nextjs-prerender": "1",
5
- "x-next-cache-tags": "_N_T_/layout,_N_T_/roots/layout,_N_T_/roots/new/layout,_N_T_/roots/new/page,_N_T_/roots/new"
6
- }
7
- }
@@ -1,21 +0,0 @@
1
- 1:"$Sreact.fragment"
2
- 3:I[26957,[],""]
3
- 4:I[97369,[],""]
4
- 6:I[21968,[],"OutletBoundary"]
5
- 8:I[33705,[],"AsyncMetadataOutlet"]
6
- a:I[21968,[],"ViewportBoundary"]
7
- c:I[21968,[],"MetadataBoundary"]
8
- d:"$Sreact.suspense"
9
- f:I[6287,[],""]
10
- :HL["/_next/static/css/87e01f779d555d04.css","style"]
11
- 0:{"P":null,"b":"6-mOMrzbiPmI97utKVIuW","p":"","c":["","roots","new"],"i":false,"f":[[["",{"children":["roots",{"children":["new",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/87e01f779d555d04.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],"$L2"]}],{"children":["roots",["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["new",["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":["$L5",null,["$","$L6",null,{"children":["$L7",["$","$L8",null,{"promise":"$@9"}]]}]]}],{},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$La",null,{"children":"$Lb"}],null],["$","$Lc",null,{"children":["$","div",null,{"hidden":true,"children":["$","$d",null,{"fallback":null,"children":"$Le"}]}]}]]}],false]],"m":"$undefined","G":["$f",[]],"s":false,"S":true}
12
- 10:I[54400,["4400","static/chunks/4400-cdb1f7913ae34e09.js","1217","static/chunks/1217-407174d9b164a499.js","3335","static/chunks/3335-5647a38ab2cfa88d.js","5097","static/chunks/5097-f07f6aeee3f60a33.js","9429","static/chunks/app/roots/new/page-918f809668694de6.js"],""]
13
- 11:I[6797,["4400","static/chunks/4400-cdb1f7913ae34e09.js","1217","static/chunks/1217-407174d9b164a499.js","3335","static/chunks/3335-5647a38ab2cfa88d.js","5097","static/chunks/5097-f07f6aeee3f60a33.js","9429","static/chunks/app/roots/new/page-918f809668694de6.js"],"DirectoryPicker"]
14
- 5:["$","main",null,{"className":"mx-auto w-full max-w-4xl flex-1 px-6 py-10","children":[["$","header",null,{"className":"mb-8","children":[["$","$L10",null,{"href":"/","children":[["$","svg",null,{"ref":"$undefined","xmlns":"http://www.w3.org/2000/svg","width":24,"height":24,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","strokeWidth":2,"strokeLinecap":"round","strokeLinejoin":"round","className":"lucide lucide-arrow-left mr-1 h-4 w-4","children":[["$","path","1l729n",{"d":"m12 19-7-7 7-7"}],["$","path","x3x0zl",{"d":"M19 12H5"}],"$undefined"]}]," Back"],"data-slot":"button","data-variant":"ghost","data-size":"sm","className":"inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5 mb-2 -ml-3","ref":null}],["$","h1",null,{"className":"text-3xl font-semibold tracking-tight","children":"Add a directory"}],["$","p",null,{"className":"text-muted-foreground mt-1","children":"Pick the directory you want Reflex to index. After it's registered, you can run the initial analysis from the directory page."}]]}],["$","$L11",null,{"initialPath":"/home/runner"}]]}]
15
- b:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
16
- 7:null
17
- 9:{"metadata":[["$","title","0",{"children":"Reflex"}],["$","meta","1",{"name":"description","content":"Local-first knowledge base built by an agent."}]],"error":null,"digest":"$undefined"}
18
- e:"$9:metadata"
19
- 12:I[10607,["4400","static/chunks/4400-cdb1f7913ae34e09.js","1217","static/chunks/1217-407174d9b164a499.js","5097","static/chunks/5097-f07f6aeee3f60a33.js","9045","static/chunks/9045-731ff0865352dd95.js","7177","static/chunks/app/layout-e51afdc17d552d1a.js"],"AppSidebar"]
20
- 13:I[43450,["4400","static/chunks/4400-cdb1f7913ae34e09.js","1217","static/chunks/1217-407174d9b164a499.js","5097","static/chunks/5097-f07f6aeee3f60a33.js","9045","static/chunks/9045-731ff0865352dd95.js","7177","static/chunks/app/layout-e51afdc17d552d1a.js"],"Toaster"]
21
- 2:["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"children":[["$","div",null,{"className":"h-screen flex","children":[["$","$L12",null,{"initialRoots":[]}],["$","main",null,{"className":"flex-1 min-w-0 flex flex-col","children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]]}],["$","$L13",null,{"richColors":true,"closeButton":true}]]}]}]
@@ -1 +0,0 @@
1
- <!DOCTYPE html><!--6_mOMrzbiPmI97utKVIuW--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/87e01f779d555d04.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-5a9c11af9261dd8a.js"/><script src="/_next/static/chunks/6fe292aa-7126ff9d6732e864.js" async=""></script><script src="/_next/static/chunks/146-ccee3b26755b68c8.js" async=""></script><script src="/_next/static/chunks/main-app-ebe67847147d19aa.js" async=""></script><script src="/_next/static/chunks/4400-cdb1f7913ae34e09.js" async=""></script><script src="/_next/static/chunks/1217-407174d9b164a499.js" async=""></script><script src="/_next/static/chunks/5097-f07f6aeee3f60a33.js" async=""></script><script src="/_next/static/chunks/9045-731ff0865352dd95.js" async=""></script><script src="/_next/static/chunks/app/layout-e51afdc17d552d1a.js" async=""></script><script src="/_next/static/chunks/3335-5647a38ab2cfa88d.js" async=""></script><script src="/_next/static/chunks/5235-990ba9c4c8446446.js" async=""></script><script src="/_next/static/chunks/app/settings/page-9cf2f101424ec84c.js" async=""></script><title>Reflex</title><meta name="description" content="Local-first knowledge base built by an agent."/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div class="h-screen flex"><aside class="w-72 shrink-0 border-r bg-muted/30 flex flex-col"><div class="px-4 py-4 flex items-center gap-2 border-b"><span class="reflex-gradient inline-flex h-7 w-7 items-center justify-center rounded-lg text-white shadow-sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles h-4 w-4"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"></path><path d="M20 3v4"></path><path d="M22 5h-4"></path><path d="M4 17v2"></path><path d="M5 18H3"></path></svg></span><div class="leading-tight"><a class="text-sm font-semibold tracking-tight hover:underline" href="/">Reflex</a><div class="text-[10px] uppercase tracking-wider text-muted-foreground">knowledge base</div></div></div><div dir="ltr" data-slot="scroll-area" class="relative flex-1" style="position:relative;--radix-scroll-area-corner-width:0px;--radix-scroll-area-corner-height:0px"><style>[data-radix-scroll-area-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-scroll-area-viewport]::-webkit-scrollbar{display:none}</style><div data-radix-scroll-area-viewport="" data-slot="scroll-area-viewport" class="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1" style="overflow-x:hidden;overflow-y:hidden"><div style="min-width:100%;display:table"><nav class="px-2 pt-3 pb-6"><div class="px-2 mb-1 text-[10px] uppercase tracking-wider text-muted-foreground">Пространства</div><div class="px-2 py-3 text-xs text-muted-foreground">Пока пусто.</div><div class="mt-2 px-2"><a data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 h-7 w-full justify-start text-xs" href="/roots/new"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-plus mr-1 h-3.5 w-3.5"><path d="M12 10v6"></path><path d="M9 13h6"></path><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"></path></svg> Добавить пространство</a></div></nav></div></div></div><div data-orientation="horizontal" role="none" data-slot="separator" class="shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px"></div><div class="px-2 py-2 space-y-0.5"><a data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 w-full justify-start" href="/utilities"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-boxes mr-2 h-4 w-4"><path d="M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z"></path><path d="m7 16.5-4.74-2.85"></path><path d="m7 16.5 5-3"></path><path d="M7 16.5v5.17"></path><path d="M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z"></path><path d="m17 16.5-5-3"></path><path d="m17 16.5 4.74-2.85"></path><path d="M17 16.5v5.17"></path><path d="M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z"></path><path d="M12 8 7.26 5.15"></path><path d="m12 8 4.74-2.85"></path><path d="M12 13.5V8"></path></svg> Мини-приложения</a><a data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 w-full justify-start" href="/audit"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-search mr-2 h-4 w-4"><path d="M14 2v4a2 2 0 0 0 2 2h4"></path><path d="M4.268 21a2 2 0 0 0 1.727 1H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"></path><path d="m9 18-1.5-1.5"></path><circle cx="5" cy="14" r="3"></circle></svg> Аудит</a><a data-slot="button" data-variant="secondary" data-size="sm" class="inline-flex shrink-0 items-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 bg-secondary text-secondary-foreground hover:bg-secondary/80 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 w-full justify-start" href="/settings"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-settings mr-2 h-4 w-4"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"></path><circle cx="12" cy="12" r="3"></circle></svg> Settings</a></div></aside><main class="flex-1 min-w-0 flex flex-col"><main class="mx-auto w-full max-w-4xl flex-1 px-6 py-10"><header class="mb-8"><a data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5 mb-2 -ml-3" href="/"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-left mr-1 h-4 w-4"><path d="m12 19-7-7 7-7"></path><path d="M19 12H5"></path></svg> Roots</a><h1 class="text-3xl font-semibold tracking-tight">Settings</h1><p class="text-muted-foreground mt-1">Pick which harness runs each kind of task and which model it uses. Agentic work (analyze / chat) goes to Claude Code or Codex; RAG and embedding work goes to Ollama by default.</p></header><div data-orientation="horizontal" role="none" data-slot="separator" class="shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px mb-6"></div><div class="space-y-8"><div data-slot="card" class="flex flex-col gap-6 rounded-xl border py-6 text-card-foreground shadow-sm border-violet-200 dark:border-violet-900/50 bg-violet-50/40 dark:bg-violet-950/20"><div data-slot="card-content" class="px-6 pt-5 pb-5 flex items-center gap-3"><div class="flex-1"><div class="text-sm font-medium">Простой режим</div><p class="text-xs text-muted-foreground mt-0.5">Видны только основные настройки. Включи расширенный, чтобы поменять модели, подключения и промпты.</p></div><button data-slot="button" data-variant="default" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 bg-primary text-primary-foreground hover:bg-primary/90 h-8 gap-1.5 rounded-md px-3 has-[&gt;svg]:px-2.5" type="button">Расширенный режим</button></div></div><section><h2 class="text-lg font-semibold mb-3">Output language</h2><div data-slot="card" class="flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm"><div data-slot="card-content" class="px-6 pt-6"><p class="text-sm text-muted-foreground mb-3">The agent injects this into every system prompt and writes all Markdown artifacts in this language. Code, paths, and quoted source stay verbatim.</p><div class="flex items-center gap-3 max-w-xl"><div class="flex-1"><label data-slot="label" class="flex items-center gap-2 font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 text-xs text-muted-foreground">Preset</label><button type="button" role="combobox" aria-controls="radix-_R_2d2qnpfjb_" aria-expanded="false" aria-autocomplete="none" dir="ltr" data-state="closed" data-slot="select-trigger" data-size="default" class="flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 [&amp;_svg:not([class*=&#x27;text-&#x27;])]:text-muted-foreground mt-1"><span data-slot="select-value" style="pointer-events:none"></span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down size-4 opacity-50" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg></button><select aria-hidden="true" tabindex="-1" style="position:absolute;border:0;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;word-wrap:normal"></select></div></div></div></div></section><section><h2 class="text-lg font-semibold mb-3">Обработка изображений</h2><div data-slot="card" class="flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm"><div data-slot="card-content" class="px-6 pt-6 space-y-4"><div class="flex items-start justify-between gap-4"><div><p class="text-sm">Reflex автоматически ресайзит и перекодирует прикреплённые изображения перед сохранением в<!-- --> <code class="font-mono text-xs">.reflex/attachments/</code>.</p><p class="text-xs text-muted-foreground mt-1">Сокращает токены модели и место на диске. Векторы (SVG) и анимированные GIF/WebP остаются как есть.</p></div><div class="flex items-center gap-2 shrink-0"><label data-slot="label" class="flex items-center gap-2 font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 text-xs" for="img-enabled">включено</label><button type="button" role="switch" aria-checked="true" data-state="checked" value="on" data-slot="switch" data-size="default" class="peer group/switch inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80" id="img-enabled"><span data-state="checked" data-slot="switch-thumb" class="pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0 dark:data-[state=checked]:bg-primary-foreground dark:data-[state=unchecked]:bg-foreground"></span></button><input type="checkbox" aria-hidden="true" style="transform:translateX(-100%);position:absolute;pointer-events:none;opacity:0;margin:0" tabindex="-1" checked="" value="on"/></div></div><div class="space-y-4"><div><div class="flex items-center justify-between mb-2"><label data-slot="label" class="flex items-center gap-2 font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 text-xs text-muted-foreground">Макс. сторона</label><span class="font-mono text-xs">2000<!-- -->px</span></div><span dir="ltr" data-orientation="horizontal" aria-disabled="false" data-slot="slider" class="relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col" style="--radix-slider-thumb-transform:translateX(-50%)"><span data-orientation="horizontal" data-slot="slider-track" class="relative grow overflow-hidden rounded-full bg-muted data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"><span data-orientation="horizontal" data-slot="slider-range" class="absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full" style="left:0%;right:78.0241935483871%"></span></span><span style="transform:var(--radix-slider-thumb-transform);position:absolute;left:calc(0% + 0px)"><span role="slider" aria-valuemin="256" aria-valuemax="8192" aria-orientation="horizontal" data-orientation="horizontal" tabindex="0" data-slot="slider-thumb" class="block size-4 shrink-0 rounded-full border border-primary bg-white shadow-sm ring-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50" style="display:none" data-radix-collection-item=""></span><input style="display:none"/></span></span><div class="flex justify-between text-[10px] text-muted-foreground mt-1"><span>256</span><span>2048</span><span>4096</span><span>8192</span></div></div><div><div class="flex items-center justify-between mb-2"><label data-slot="label" class="flex items-center gap-2 font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 text-xs text-muted-foreground">Качество (JPEG / WebP)</label><span class="font-mono text-xs">85</span></div><span dir="ltr" data-orientation="horizontal" aria-disabled="false" data-slot="slider" class="relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col" style="--radix-slider-thumb-transform:translateX(-50%)"><span data-orientation="horizontal" data-slot="slider-track" class="relative grow overflow-hidden rounded-full bg-muted data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"><span data-orientation="horizontal" data-slot="slider-range" class="absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full" style="left:0%;right:25%"></span></span><span style="transform:var(--radix-slider-thumb-transform);position:absolute;left:calc(0% + 0px)"><span role="slider" aria-valuemin="40" aria-valuemax="100" aria-orientation="horizontal" data-orientation="horizontal" tabindex="0" data-slot="slider-thumb" class="block size-4 shrink-0 rounded-full border border-primary bg-white shadow-sm ring-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50" style="display:none" data-radix-collection-item=""></span><input style="display:none"/></span></span></div><div class="max-w-xs"><label data-slot="label" class="flex items-center gap-2 font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 text-xs text-muted-foreground">Формат</label><button type="button" role="combobox" aria-controls="radix-_R_2t3qnpfjb_" aria-expanded="false" aria-autocomplete="none" dir="ltr" data-state="closed" data-slot="select-trigger" data-size="default" class="flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 [&amp;_svg:not([class*=&#x27;text-&#x27;])]:text-muted-foreground mt-1"><span data-slot="select-value" style="pointer-events:none"></span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down size-4 opacity-50" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg></button><select aria-hidden="true" tabindex="-1" style="position:absolute;border:0;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;word-wrap:normal"></select></div></div></div></div></section><section><h2 class="text-lg font-semibold mb-3">Gemini</h2><div data-slot="card" class="flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm"><div data-slot="card-content" class="px-6 pt-5 space-y-4"><div class="flex items-center gap-2 text-sm font-medium"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles h-4 w-4"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"></path><path d="M20 3v4"></path><path d="M22 5h-4"></path><path d="M4 17v2"></path><path d="M5 18H3"></path></svg><span>Gemini API</span><span data-slot="badge" data-variant="outline" class="inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;&gt;svg]:pointer-events-none [&amp;&gt;svg]:size-3 border-border text-foreground [a&amp;]:hover:bg-accent [a&amp;]:hover:text-accent-foreground">не настроен</span></div><p class="text-xs text-muted-foreground">Используется для суммаризации YouTube (нативная поддержка мультимодальных URL) <strong>и для генерации картинок</strong> <!-- -->через модель Nano Banana (<code class="font-mono">gemini-2.5-flash-image</code>, ~$0.04 за картинку). Ключ хранится локально в<!-- --> <code class="font-mono">~/.reflex/api-keys/gemini.json</code> <!-- -->(0600), агентам не передаётся. Возьми ключ в<!-- --> <a href="https://aistudio.google.com/apikey" target="_blank" rel="noopener noreferrer" class="inline-flex items-center gap-1 text-violet-700 hover:underline">aistudio.google.com/apikey<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-3 w-3"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a> <!-- -->— есть бесплатный tier (15 RPM / 1500 RPD).</p><div class="space-y-1.5"><label data-slot="label" class="font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 text-xs flex items-center gap-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-key-round h-3 w-3"><path d="M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"></path><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"></circle></svg>API key</label><div class="flex gap-2"><input type="password" data-slot="input" class="w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 font-mono text-sm flex-1 h-8" placeholder="AIza…" value=""/><button data-slot="button" data-variant="default" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 bg-primary text-primary-foreground hover:bg-primary/90 rounded-md px-3 has-[&gt;svg]:px-2.5 h-8 gap-1" type="button" disabled=""><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-save h-3 w-3"><path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"></path><path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"></path><path d="M7 3v4a1 1 0 0 0 1 1h7"></path></svg>Сохранить</button></div></div></div></div></section><section><h2 class="text-lg font-semibold mb-3">Картинки</h2><div data-slot="card" class="flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm"><div data-slot="card-content" class="px-6 pt-5 space-y-5"><div class="flex items-center gap-2 text-sm font-medium"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-image h-4 w-4"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path></svg><span>Картинки из сети</span></div><p class="text-xs text-muted-foreground">Ключи к API stock-фотобанков. Используются виджетом «Картинка в KB» и хост-API утилит (<code class="font-mono">reflex.images.search</code>). Хранятся локально в <code class="font-mono">~/.reflex/api-keys/</code> (0600).</p><div class="space-y-2"><div class="flex items-center gap-2"><span class="text-sm font-medium">Unsplash</span><span data-slot="badge" data-variant="outline" class="inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;&gt;svg]:pointer-events-none [&amp;&gt;svg]:size-3 border-border text-foreground [a&amp;]:hover:bg-accent [a&amp;]:hover:text-accent-foreground">не настроен</span><a href="https://unsplash.com/developers" target="_blank" rel="noopener noreferrer" class="ml-auto inline-flex items-center gap-1 text-xs text-violet-700 hover:underline">docs <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-3 w-3"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></div><p class="text-[11px] text-muted-foreground">Бесплатно 50 запросов/час. Атрибуция авторов обязательна — модалка вставляет её автоматически.</p><div class="flex gap-2"><label data-slot="label" class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 sr-only" for="unsplash-key"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-key-round h-3 w-3"><path d="M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"></path><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"></circle></svg> <!-- -->Unsplash<!-- --> key</label><input type="password" data-slot="input" class="w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 font-mono text-sm flex-1 h-8" id="unsplash-key" placeholder="Unsplash access key" value=""/><button data-slot="button" data-variant="default" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 bg-primary text-primary-foreground hover:bg-primary/90 rounded-md px-3 has-[&gt;svg]:px-2.5 h-8 gap-1" type="button" disabled=""><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-save h-3 w-3"><path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"></path><path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"></path><path d="M7 3v4a1 1 0 0 0 1 1h7"></path></svg>Сохранить</button></div></div><div class="space-y-2"><div class="flex items-center gap-2"><span class="text-sm font-medium">Pexels</span><span data-slot="badge" data-variant="outline" class="inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;&gt;svg]:pointer-events-none [&amp;&gt;svg]:size-3 border-border text-foreground [a&amp;]:hover:bg-accent [a&amp;]:hover:text-accent-foreground">не настроен</span><a href="https://pexels.com/api/" target="_blank" rel="noopener noreferrer" class="ml-auto inline-flex items-center gap-1 text-xs text-violet-700 hover:underline">docs <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-3 w-3"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></div><p class="text-[11px] text-muted-foreground">Без жёсткого лимита для разумного использования. Атрибуция рекомендована.</p><div class="flex gap-2"><label data-slot="label" class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 sr-only" for="pexels-key"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-key-round h-3 w-3"><path d="M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"></path><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"></circle></svg> <!-- -->Pexels<!-- --> key</label><input type="password" data-slot="input" class="w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 font-mono text-sm flex-1 h-8" id="pexels-key" placeholder="Pexels access key" value=""/><button data-slot="button" data-variant="default" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 bg-primary text-primary-foreground hover:bg-primary/90 rounded-md px-3 has-[&gt;svg]:px-2.5 h-8 gap-1" type="button" disabled=""><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-save h-3 w-3"><path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"></path><path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"></path><path d="M7 3v4a1 1 0 0 0 1 1h7"></path></svg>Сохранить</button></div></div><div class="space-y-2"><div class="flex items-center gap-2"><span class="text-sm font-medium">Brave (весь веб)</span><span data-slot="badge" data-variant="outline" class="inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;&gt;svg]:pointer-events-none [&amp;&gt;svg]:size-3 border-border text-foreground [a&amp;]:hover:bg-accent [a&amp;]:hover:text-accent-foreground">не настроен</span><a href="https://api-dashboard.search.brave.com/app/keys" target="_blank" rel="noopener noreferrer" class="ml-auto inline-flex items-center gap-1 text-xs text-violet-700 hover:underline">docs <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-3 w-3"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></div><p class="text-[11px] text-muted-foreground">Поиск картинок по всему вебу (не только stock). Если у тебя уже подключён Brave Search MCP — ключ оттуда подхватится автоматически, поле можно не заполнять.</p><div class="flex gap-2"><label data-slot="label" class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 sr-only" for="brave-key"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-key-round h-3 w-3"><path d="M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"></path><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"></circle></svg> <!-- -->Brave (весь веб)<!-- --> key</label><input type="password" data-slot="input" class="w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 font-mono text-sm flex-1 h-8" id="brave-key" placeholder="Brave (весь веб) access key" value=""/><button data-slot="button" data-variant="default" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 bg-primary text-primary-foreground hover:bg-primary/90 rounded-md px-3 has-[&gt;svg]:px-2.5 h-8 gap-1" type="button" disabled=""><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-save h-3 w-3"><path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"></path><path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"></path><path d="M7 3v4a1 1 0 0 0 1 1h7"></path></svg>Сохранить</button></div></div></div></div></section><section><h2 class="text-lg font-semibold mb-3">OAuth providers</h2><p class="text-sm text-muted-foreground mb-3">Reflex держит локально access/refresh-токены и сам обновляет их при истечении. Используй <code>$oauth:&lt;provider&gt;</code> в env/headers MCP-сервера — Reflex подставит свежий токен при каждом вызове. Redirect URI:<!-- --> <code class="font-mono">http://localhost:3210/api/oauth/callback</code>.</p><div class="space-y-2"><button data-slot="button" data-variant="ghost" data-size="sm" class="inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 rounded-md px-3 has-[&gt;svg]:px-2.5 gap-2 text-muted-foreground" type="button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-plus h-4 w-4"><path d="M5 12h14"></path><path d="M12 5v14"></path></svg>Добавить кастомный provider</button></div></section><section><h2 class="text-lg font-semibold mb-3">Сервисы маршрутов</h2><p class="text-sm text-muted-foreground mb-3">Какие сервисы навигации появятся в попапе «Маршрут в…» на каждой точке map-виджета. Reflex генерирует deep-link из координат — без посредников, без аккаунтов.</p><div data-slot="card" class="flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm"><div data-slot="card-content" class="px-6 pt-5 space-y-3"><div class="flex items-center gap-2 text-sm font-medium"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-map h-4 w-4 text-emerald-700"><path d="M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z"></path><path d="M15 5.764v15"></path><path d="M9 3.236v15"></path></svg><span>Сервисы маршрутов</span></div><p class="text-xs text-muted-foreground">Выбранные сервисы появятся в попапе на каждой точке карта-виджета — «Маршрут в…». Ссылка генерится прямо из координат, без посредников. Можно проверить превью-ссылку (точка по умолчанию — центр Москвы).</p><ul class="space-y-1.5"><li class="flex items-start gap-2 rounded-md border bg-card px-3 py-2"><input id="map-svc-google" type="checkbox" class="mt-1 h-3.5 w-3.5" checked=""/><label for="map-svc-google" class="min-w-0 flex-1 cursor-pointer"><div class="text-sm font-medium">Google Maps</div><p class="text-[11px] text-muted-foreground mt-0.5 leading-snug">Глобальный, navigation+street view. Работает везде кроме РФ-блокировок.</p></label><a href="https://www.google.com/maps/dir/?api=1&amp;destination=55.7558,37.6173" target="_blank" rel="noopener noreferrer" class="text-[10px] text-muted-foreground hover:underline inline-flex items-center gap-0.5 shrink-0 mt-1" title="Открыть превью-ссылку">превью<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-2.5 w-2.5"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></li><li class="flex items-start gap-2 rounded-md border bg-card px-3 py-2"><input id="map-svc-yandex" type="checkbox" class="mt-1 h-3.5 w-3.5" checked=""/><label for="map-svc-yandex" class="min-w-0 flex-1 cursor-pointer"><div class="text-sm font-medium">Яндекс.Карты</div><p class="text-[11px] text-muted-foreground mt-0.5 leading-snug">СНГ, лучшая детализация по РФ и пробки в реальном времени.</p></label><a href="https://yandex.ru/maps/?rtext=~55.7558,37.6173&amp;rtt=auto" target="_blank" rel="noopener noreferrer" class="text-[10px] text-muted-foreground hover:underline inline-flex items-center gap-0.5 shrink-0 mt-1" title="Открыть превью-ссылку">превью<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-2.5 w-2.5"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></li><li class="flex items-start gap-2 rounded-md border bg-card px-3 py-2"><input id="map-svc-2gis" type="checkbox" class="mt-1 h-3.5 w-3.5"/><label for="map-svc-2gis" class="min-w-0 flex-1 cursor-pointer"><div class="text-sm font-medium">2ГИС</div><p class="text-[11px] text-muted-foreground mt-0.5 leading-snug">СНГ, точные адреса и POI. Уникальная свойственность РФ-городов.</p></label><a href="https://2gis.ru/routeSearch/to/37.6173,55.7558" target="_blank" rel="noopener noreferrer" class="text-[10px] text-muted-foreground hover:underline inline-flex items-center gap-0.5 shrink-0 mt-1" title="Открыть превью-ссылку">превью<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-2.5 w-2.5"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></li><li class="flex items-start gap-2 rounded-md border bg-card px-3 py-2"><input id="map-svc-apple" type="checkbox" class="mt-1 h-3.5 w-3.5" checked=""/><label for="map-svc-apple" class="min-w-0 flex-1 cursor-pointer"><div class="text-sm font-medium">Apple Maps</div><p class="text-[11px] text-muted-foreground mt-0.5 leading-snug">Откроется в нативном приложении на iOS/macOS, иначе на сайте.</p></label><a href="https://maps.apple.com/?daddr=55.7558,37.6173" target="_blank" rel="noopener noreferrer" class="text-[10px] text-muted-foreground hover:underline inline-flex items-center gap-0.5 shrink-0 mt-1" title="Открыть превью-ссылку">превью<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-2.5 w-2.5"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></li><li class="flex items-start gap-2 rounded-md border bg-card px-3 py-2"><input id="map-svc-osm" type="checkbox" class="mt-1 h-3.5 w-3.5" checked=""/><label for="map-svc-osm" class="min-w-0 flex-1 cursor-pointer"><div class="text-sm font-medium">OpenStreetMap</div><p class="text-[11px] text-muted-foreground mt-0.5 leading-snug">Открытые данные, без аккаунта. Базовая навигация.</p></label><a href="https://www.openstreetmap.org/directions?to=55.7558,37.6173" target="_blank" rel="noopener noreferrer" class="text-[10px] text-muted-foreground hover:underline inline-flex items-center gap-0.5 shrink-0 mt-1" title="Открыть превью-ссылку">превью<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-2.5 w-2.5"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></li><li class="flex items-start gap-2 rounded-md border bg-card px-3 py-2"><input id="map-svc-waze" type="checkbox" class="mt-1 h-3.5 w-3.5"/><label for="map-svc-waze" class="min-w-0 flex-1 cursor-pointer"><div class="text-sm font-medium">Waze</div><p class="text-[11px] text-muted-foreground mt-0.5 leading-snug">Авто-навигация с краудсорсингом пробок и предупреждений.</p></label><a href="https://waze.com/ul?ll=55.7558,37.6173&amp;navigate=yes" target="_blank" rel="noopener noreferrer" class="text-[10px] text-muted-foreground hover:underline inline-flex items-center gap-0.5 shrink-0 mt-1" title="Открыть превью-ссылку">превью<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-2.5 w-2.5"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></li><li class="flex items-start gap-2 rounded-md border bg-card px-3 py-2"><input id="map-svc-organic" type="checkbox" class="mt-1 h-3.5 w-3.5"/><label for="map-svc-organic" class="min-w-0 flex-1 cursor-pointer"><div class="text-sm font-medium">Organic Maps</div><p class="text-[11px] text-muted-foreground mt-0.5 leading-snug">Офлайн-карты с открытыми данными. Открывается в приложении.</p></label><a href="om://map?ll=55.7558,37.6173" target="_blank" rel="noopener noreferrer" class="text-[10px] text-muted-foreground hover:underline inline-flex items-center gap-0.5 shrink-0 mt-1" title="Открыть превью-ссылку">превью<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-external-link h-2.5 w-2.5"><path d="M15 3h6v6"></path><path d="M10 14 21 3"></path><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path></svg></a></li></ul></div></div></section><section><h2 class="text-lg font-semibold mb-3">Публичные ссылки (ngrok)</h2><p class="text-sm text-muted-foreground mb-3">Сделать утилиту, KB-файл или дашборд доступным из интернета через ngrok-туннель. Каждая ссылка опционально защищена паролем; middleware закрывает все остальные пути на ngrok-хосте.</p><div data-slot="card" class="flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm"><div data-slot="card-content" class="px-6 pt-5 space-y-4"><div class="flex items-center gap-2 text-sm font-medium"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe h-4 w-4 text-violet-600"><circle cx="12" cy="12" r="10"></circle><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"></path><path d="M2 12h20"></path></svg><span>Публичные ссылки через ngrok</span><span class="text-[10px] text-destructive ml-1 inline-flex items-center gap-0.5"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-triangle-alert h-3 w-3"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"></path><path d="M12 9v4"></path><path d="M12 17h.01"></path></svg>ngrok CLI не найден</span></div><p class="text-xs text-muted-foreground">Reflex запускает <code class="font-mono">ngrok http</code> с твоим токеном; на ngrok-домене разрешены только пути<!-- --> <code class="font-mono">/share/*</code>. Установи<!-- --> <a href="https://ngrok.com/download" target="_blank" rel="noopener noreferrer" class="underline">ngrok CLI</a> <!-- -->в PATH перед запуском.</p><div class="grid gap-2"><label class="text-xs font-medium" for="ngrok-token">Authtoken (agent)</label><input id="ngrok-token" type="password" autoComplete="off" placeholder="2abc...xyz" class="rounded border bg-background px-2 py-1.5 text-xs font-mono focus:outline-none focus:ring-1 focus:ring-violet-400" value=""/><p class="text-[10px] text-muted-foreground">Найди в<!-- --> <a href="https://dashboard.ngrok.com/get-started/your-authtoken" target="_blank" rel="noopener noreferrer" class="underline">ngrok dashboard → Your Authtoken</a>. Сохраняется в <code class="font-mono">~/.reflex/ngrok.yml</code> <!-- -->(0600).</p></div><div class="grid gap-2"><label class="text-xs font-medium" for="ngrok-apikey">API key (для списка доменов, опционально)</label><input id="ngrok-apikey" type="password" autoComplete="off" placeholder="2abc...xyz" class="rounded border bg-background px-2 py-1.5 text-xs font-mono focus:outline-none focus:ring-1 focus:ring-violet-400" value=""/><p class="text-[10px] text-muted-foreground">Возьми в<!-- --> <a href="https://dashboard.ngrok.com/api" target="_blank" rel="noopener noreferrer" class="underline">dashboard → API → API keys</a>. Используется только для GET-запроса списка reserved-доменов.</p></div><div class="grid gap-2"><div class="flex items-center justify-between"><label class="text-xs font-medium" for="ngrok-domain">Reserved domain (если есть)</label><button type="button" disabled="" class="text-[11px] inline-flex items-center gap-1 text-violet-700 hover:underline disabled:opacity-50"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-refresh-cw h-3 w-3"><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path><path d="M21 3v5h-5"></path><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path><path d="M8 16H3v5"></path></svg>Обновить список</button></div><input id="ngrok-domain" type="text" placeholder="my-app.ngrok-free.app или оставь пустым" class="rounded border bg-background px-2 py-1.5 text-xs font-mono focus:outline-none focus:ring-1 focus:ring-violet-400" value=""/></div><div class="grid grid-cols-[1fr_auto] gap-2 items-end"><div><label class="text-xs font-medium" for="ngrok-port">Локальный порт</label><input id="ngrok-port" type="number" min="1" max="65535" class="mt-1 w-32 rounded border bg-background px-2 py-1.5 text-xs font-mono focus:outline-none focus:ring-1 focus:ring-violet-400" value="3210"/></div><button type="button" disabled="" class="rounded bg-violet-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-violet-700 disabled:opacity-50 inline-flex items-center gap-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-play h-3 w-3"><polygon points="6 3 20 12 6 21 6 3"></polygon></svg>Запустить</button></div><hr class="my-3"/><div><h3 class="text-xs font-semibold mb-2">Активные ссылки (<!-- -->0<!-- -->)</h3><p class="text-[11px] text-muted-foreground">Пока ничего не расшарено. На странице утилиты, KB-файла или дашборда появится кнопка «Поделиться».</p></div></div></div></section><div class="flex justify-end"><button data-slot="button" data-variant="default" data-size="default" class="inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 bg-primary text-primary-foreground hover:bg-primary/90 h-9 px-4 py-2 has-[&gt;svg]:px-3"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-save mr-2 h-4 w-4"><path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"></path><path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"></path><path d="M7 3v4a1 1 0 0 0 1 1h7"></path></svg> Save settings</button></div></div></main><!--$--><!--/$--></main></div><section aria-label="Notifications alt+T" tabindex="-1" aria-live="polite" aria-relevant="additions text" aria-atomic="false"></section><script src="/_next/static/chunks/webpack-5a9c11af9261dd8a.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n3:I[26957,[],\"\"]\n4:I[97369,[],\"\"]\n6:I[21968,[],\"OutletBoundary\"]\n8:I[33705,[],\"AsyncMetadataOutlet\"]\na:I[21968,[],\"ViewportBoundary\"]\nc:I[21968,[],\"MetadataBoundary\"]\nd:\"$Sreact.suspense\"\nf:I[6287,[],\"\"]\n:HL[\"/_next/static/css/87e01f779d555d04.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"6-mOMrzbiPmI97utKVIuW\",\"p\":\"\",\"c\":[\"\",\"settings\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"settings\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/87e01f779d555d04.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],\"$L2\"]}],{\"children\":[\"settings\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[\"$L5\",null,[\"$\",\"$L6\",null,{\"children\":[\"$L7\",[\"$\",\"$L8\",null,{\"promise\":\"$@9\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],null],[\"$\",\"$Lc\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$d\",null,{\"fallback\":null,\"children\":\"$Le\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"b:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n7:null\n"])</script><script>self.__next_f.push([1,"9:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Reflex\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Local-first knowledge base built by an agent.\"}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"e:\"$9:metadata\"\n"])</script><script>self.__next_f.push([1,"10:I[10607,[\"4400\",\"static/chunks/4400-cdb1f7913ae34e09.js\",\"1217\",\"static/chunks/1217-407174d9b164a499.js\",\"5097\",\"static/chunks/5097-f07f6aeee3f60a33.js\",\"9045\",\"static/chunks/9045-731ff0865352dd95.js\",\"7177\",\"static/chunks/app/layout-e51afdc17d552d1a.js\"],\"AppSidebar\"]\n11:I[43450,[\"4400\",\"static/chunks/4400-cdb1f7913ae34e09.js\",\"1217\",\"static/chunks/1217-407174d9b164a499.js\",\"5097\",\"static/chunks/5097-f07f6aeee3f60a33.js\",\"9045\",\"static/chunks/9045-731ff0865352dd95.js\",\"7177\",\"static/chunks/app/layout-e51afdc17d552d1a.js\"],\"Toaster\"]\n12:I[54400,[\"4400\",\"static/chunks/4400-cdb1f7913ae34e09.js\",\"1217\",\"static/chunks/1217-407174d9b164a499.js\",\"3335\",\"static/chunks/3335-5647a38ab2cfa88d.js\",\"5097\",\"static/chunks/5097-f07f6aeee3f60a33.js\",\"5235\",\"static/chunks/5235-990ba9c4c8446446.js\",\"4662\",\"static/chunks/app/settings/page-9cf2f101424ec84c.js\"],\"\"]\n13:I[91074,[\"4400\",\"static/chunks/4400-cdb1f7913ae34e09.js\",\"1217\",\"static/chunks/1217-407174d9b164a499.js\",\"3335\",\"static/chunks/3335-5647a38ab2cfa88d.js\",\"5097\",\"static/chunks/5097-f07f6aeee3f60a33.js\",\"5235\",\"static/chunks/5235-990ba9c4c8446446.js\",\"4662\",\"static/chunks/app/settings/page-9cf2f101424ec84c.js\"],\"Separator\"]\n14:I[67410,[\"4400\",\"static/chunks/4400-cdb1f7913ae34e09.js\",\"1217\",\"static/chunks/1217-407174d9b164a499.js\",\"3335\",\"static/chunks/3335-5647a38ab2cfa88d.js\",\"5097\",\"static/chunks/5097-f07f6aeee3f60a33.js\",\"5235\",\"static/chunks/5235-990ba9c4c8446446.js\",\"4662\",\"static/chunks/app/settings/page-9cf2f101424ec84c.js\"],\"SettingsForm\"]\n"])</script><script>self.__next_f.push([1,"2:[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"children\":[[\"$\",\"div\",null,{\"className\":\"h-screen flex\",\"children\":[[\"$\",\"$L10\",null,{\"initialRoots\":[]}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 flex flex-col\",\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}],[\"$\",\"$L11\",null,{\"richColors\":true,\"closeButton\":true}]]}]}]\n"])</script><script>self.__next_f.push([1,"5:[\"$\",\"main\",null,{\"className\":\"mx-auto w-full max-w-4xl flex-1 px-6 py-10\",\"children\":[[\"$\",\"header\",null,{\"className\":\"mb-8\",\"children\":[[\"$\",\"$L12\",null,{\"href\":\"/\",\"children\":[[\"$\",\"svg\",null,{\"ref\":\"$undefined\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"width\":24,\"height\":24,\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":2,\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"className\":\"lucide lucide-arrow-left mr-1 h-4 w-4\",\"children\":[[\"$\",\"path\",\"1l729n\",{\"d\":\"m12 19-7-7 7-7\"}],[\"$\",\"path\",\"x3x0zl\",{\"d\":\"M19 12H5\"}],\"$undefined\"]}],\" Roots\"],\"data-slot\":\"button\",\"data-variant\":\"ghost\",\"data-size\":\"sm\",\"className\":\"inline-flex shrink-0 items-center justify-center text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [\u0026_svg]:pointer-events-none [\u0026_svg]:shrink-0 [\u0026_svg:not([class*='size-'])]:size-4 hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-8 gap-1.5 rounded-md px-3 has-[\u003esvg]:px-2.5 mb-2 -ml-3\",\"ref\":null}],[\"$\",\"h1\",null,{\"className\":\"text-3xl font-semibold tracking-tight\",\"children\":\"Settings\"}],[\"$\",\"p\",null,{\"className\":\"text-muted-foreground mt-1\",\"children\":\"Pick which harness runs each kind of task and which model it uses. Agentic work (analyze / chat) goes to Claude Code or Codex; RAG and embedding work goes to Ollama by default.\"}]]}],[\"$\",\"$L13\",null,{\"className\":\"mb-6\"}],[\"$\",\"$L14\",null,{\"initialSettings\":{\"version\":1,\"language\":\"english\",\"userName\":\"\",\"timezone\":\"\",\"uiMode\":\"simple\",\"imageProcessing\":{\"enabled\":true,\"maxDimension\":2000,\"quality\":85,\"format\":\"auto\"},\"harnesses\":{\"claude-code\":{\"enabled\":true},\"codex\":{\"enabled\":true},\"ollama\":{\"enabled\":true,\"baseUrl\":\"http://localhost:11434\"}},\"assignments\":{\"analyze\":{\"harness\":\"claude-code\",\"model\":\"claude-opus-4-7\",\"allowedTools\":[\"Read\",\"Write\",\"Edit\",\"LS\",\"Glob\",\"Grep\",\"WebSearch\",\"WebFetch\"]},\"chat\":{\"harness\":\"claude-code\",\"model\":\"claude-sonnet-4-6\",\"allowedTools\":[\"Read\",\"LS\",\"Glob\",\"Grep\",\"WebSearch\",\"WebFetch\"]},\"rag\":{\"harness\":\"ollama\",\"model\":\"llama3.1:8b\",\"allowedTools\":[]},\"embed\":{\"harness\":\"ollama\",\"model\":\"nomic-embed-text\",\"allowedTools\":[]},\"quick\":{\"harness\":\"claude-code\",\"model\":\"claude-haiku-4-5\",\"allowedTools\":[]}},\"mapServices\":{\"enabled\":[\"google\",\"yandex\",\"apple\",\"osm\"]},\"ngrok\":{\"authtoken\":\"\",\"apiKey\":\"\",\"domain\":\"\",\"port\":3210}},\"harnesses\":[{\"id\":\"claude-code\",\"label\":\"Claude Code\",\"supports\":[\"analyze\",\"chat\",\"quick\"]},{\"id\":\"codex\",\"label\":\"Codex\",\"supports\":[\"analyze\",\"chat\",\"quick\"]},{\"id\":\"ollama\",\"label\":\"Ollama\",\"supports\":[\"rag\",\"embed\",\"chat\",\"quick\"]}]}]]}]\n"])</script></body></html>
@@ -1,7 +0,0 @@
1
- {
2
- "headers": {
3
- "x-nextjs-stale-time": "300",
4
- "x-nextjs-prerender": "1",
5
- "x-next-cache-tags": "_N_T_/layout,_N_T_/settings/layout,_N_T_/settings/page,_N_T_/settings"
6
- }
7
- }