@rubytech/create-realagent 1.0.794 → 1.0.797

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 (70) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/migrations/003-person-name-eradicate.cypher +24 -0
  3. package/payload/platform/plugins/admin/PLUGIN.md +4 -0
  4. package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-gate.test.sh +166 -0
  5. package/payload/platform/plugins/admin/hooks/archive-ingest-gate.sh +147 -0
  6. package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +9 -5
  7. package/payload/platform/plugins/admin/mcp/dist/index.js +54 -18
  8. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  9. package/payload/platform/plugins/docs/references/internals.md +4 -0
  10. package/payload/platform/plugins/docs/references/settings.md +6 -0
  11. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/SKILL.md +2 -0
  12. package/payload/platform/plugins/memory/PLUGIN.md +4 -2
  13. package/payload/platform/plugins/memory/mcp/dist/index.js +2 -2
  14. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  15. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +11 -0
  16. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -1
  17. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +124 -1
  18. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
  19. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +12 -0
  20. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts.map +1 -1
  21. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +41 -2
  22. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -1
  23. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts +9 -0
  24. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts.map +1 -1
  25. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js +44 -0
  26. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js.map +1 -1
  27. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +20 -2
  28. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
  29. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +1 -1
  30. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
  31. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +0 -1
  32. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
  33. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.d.ts +2 -1
  34. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.d.ts.map +1 -1
  35. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.js.map +1 -1
  36. package/payload/platform/plugins/memory/references/schema-base.md +11 -1
  37. package/payload/platform/plugins/whatsapp-import/PLUGIN.md +4 -0
  38. package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.d.ts +8 -2
  39. package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.d.ts.map +1 -1
  40. package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.js +66 -15
  41. package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.js.map +1 -1
  42. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export.test.ts +175 -0
  43. package/payload/platform/plugins/whatsapp-import/lib/src/parse-export.ts +78 -17
  44. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/SKILL.md +2 -0
  45. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/export-parse.md +8 -6
  46. package/payload/platform/scripts/logs-read.sh +17 -12
  47. package/payload/platform/scripts/seed-neo4j.sh +43 -20
  48. package/payload/platform/templates/agents/admin/IDENTITY.md +6 -0
  49. package/payload/platform/templates/specialists/agents/database-operator.md +2 -0
  50. package/payload/server/chunk-BURNRCKP.js +3405 -0
  51. package/payload/server/chunk-JSBRDJBE.js +30 -0
  52. package/payload/server/chunk-KM23Y7SY.js +9896 -0
  53. package/payload/server/client-pool-PV45NUTN.js +29 -0
  54. package/payload/server/maxy-edge.js +3 -2
  55. package/payload/server/neo4j-migrations-IUSBODOP.js +51 -0
  56. package/payload/server/public/assets/{admin-jGbRjAxV.js → admin-Cz8hUAqx.js} +60 -60
  57. package/payload/server/public/assets/data-BvV94XHO.js +1 -0
  58. package/payload/server/public/assets/graph-CBu0rtrP.js +1 -0
  59. package/payload/server/public/assets/page-BNM63zsb.js +50 -0
  60. package/payload/server/public/assets/page-DM19J3ur.js +1 -0
  61. package/payload/server/public/assets/useAdminFetch-iYCQ9lT0.js +1 -0
  62. package/payload/server/public/data.html +3 -3
  63. package/payload/server/public/graph.html +3 -3
  64. package/payload/server/public/index.html +4 -4
  65. package/payload/server/server.js +116 -137
  66. package/payload/server/public/assets/data-BhrQjgR5.js +0 -1
  67. package/payload/server/public/assets/graph-Jj7seS-w.js +0 -1
  68. package/payload/server/public/assets/page-DIG7s5Jp.js +0 -1
  69. package/payload/server/public/assets/page-sZb3wcOM.js +0 -50
  70. package/payload/server/public/assets/share-2-BndjMKeG.js +0 -1
@@ -49,14 +49,12 @@ import {
49
49
  vncLog,
50
50
  waitForExit,
51
51
  writeChromiumWrapper
52
- } from "./chunk-3SQJW5Y5.js";
52
+ } from "./chunk-KM23Y7SY.js";
53
53
  import {
54
54
  ACCOUNTS_DIR,
55
55
  GREETING_DIRECTIVE,
56
56
  HAIKU_MODEL,
57
57
  PLATFORM_ROOT,
58
- __commonJS,
59
- __toESM,
60
58
  agentLogStream,
61
59
  backfillNullUserIdConversations,
62
60
  bindVisitorToGroup,
@@ -103,6 +101,7 @@ import {
103
101
  resolveAgentConfig,
104
102
  resolveDefaultAgentSlug,
105
103
  resolveUserAccounts,
104
+ runBootMigrations,
106
105
  setAgentSessionId,
107
106
  setConversationIdForSession,
108
107
  setGroupContextForSession,
@@ -113,7 +112,11 @@ import {
113
112
  verifyAndGetConversationUpdatedAt,
114
113
  verifyConversationOwnership,
115
114
  writeAdminUserAndPerson
116
- } from "./chunk-2N7XJW6Q.js";
115
+ } from "./chunk-BURNRCKP.js";
116
+ import {
117
+ __commonJS,
118
+ __toESM
119
+ } from "./chunk-JSBRDJBE.js";
117
120
 
118
121
  // ../lib/graph-trash/dist/index.js
119
122
  var require_dist = __commonJS({
@@ -4726,7 +4729,7 @@ app2.post("/", async (c) => {
4726
4729
  }
4727
4730
  const cookieHeader = c.req.header("cookie");
4728
4731
  if (body.session_key && typeof body.session_key === "string") {
4729
- if (validateSession(body.session_key, "public")) {
4732
+ if (validateSession(body.session_key, "public").ok) {
4730
4733
  const storedAgent = getAgentNameForSession(body.session_key);
4731
4734
  if (storedAgent && storedAgent !== agentSlug) {
4732
4735
  console.log(`[session] hot-resume agent mismatch: session=${body.session_key.slice(0, 8)}\u2026 has=${storedAgent} requested=${agentSlug} \u2014 creating new session`);
@@ -5414,7 +5417,7 @@ app3.post("/", async (c) => {
5414
5417
  if (!session_key) {
5415
5418
  return c.json({ error: "session_key required" }, 400);
5416
5419
  }
5417
- if (!validateSession(session_key, "public")) {
5420
+ if (!validateSession(session_key, "public").ok) {
5418
5421
  return c.json({ error: "Invalid or expired session" }, 401);
5419
5422
  }
5420
5423
  const files = formData.getAll("attachments");
@@ -5483,7 +5486,7 @@ app3.post("/", async (c) => {
5483
5486
  if (!message) {
5484
5487
  return c.json({ error: "message required" }, 400);
5485
5488
  }
5486
- if (!validateSession(session_key, "public")) {
5489
+ if (!validateSession(session_key, "public").ok) {
5487
5490
  return c.json({ error: "Invalid or expired session" }, 401);
5488
5491
  }
5489
5492
  }
@@ -5623,7 +5626,7 @@ app4.get("/messages", async (c) => {
5623
5626
  if (isNaN(sinceDate.getTime())) {
5624
5627
  return c.json({ error: "Invalid since parameter \u2014 expected ISO 8601" }, 400);
5625
5628
  }
5626
- if (!validateSession(sessionKey, "public")) {
5629
+ if (!validateSession(sessionKey, "public").ok) {
5627
5630
  return c.json({ error: "Session expired" }, 401);
5628
5631
  }
5629
5632
  const groupSlug = getGroupSlugForSession(sessionKey);
@@ -6247,7 +6250,7 @@ app5.post("/create-credentials", async (c) => {
6247
6250
  const { session_key, password } = body;
6248
6251
  if (!session_key || typeof session_key !== "string") return c.json({ error: "session_key required" }, 400);
6249
6252
  if (!password || typeof password !== "string") return c.json({ error: "password required" }, 400);
6250
- if (!validateSession(session_key, "public")) {
6253
+ if (!validateSession(session_key, "public").ok) {
6251
6254
  return c.json({ error: "Invalid or expired session" }, 401);
6252
6255
  }
6253
6256
  const grant = getGrantForSession(session_key);
@@ -7813,7 +7816,7 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
7813
7816
  var app10 = new Hono();
7814
7817
  app10.get("/", async (c) => {
7815
7818
  const sessionKey = c.req.query("session_key");
7816
- if (!sessionKey || !validateSession(sessionKey, "admin")) {
7819
+ if (!sessionKey || !validateSession(sessionKey, "admin").ok) {
7817
7820
  return c.json({ error: "Invalid or expired admin session" }, 401);
7818
7821
  }
7819
7822
  const accountId = getAccountIdForSession(sessionKey);
@@ -8210,7 +8213,7 @@ var app11 = new Hono();
8210
8213
  app11.post("/cancel", requireAdminSession, async (c) => {
8211
8214
  const session_key = c.var.sessionKey;
8212
8215
  try {
8213
- const { interruptClient: interruptClient2 } = await import("./client-pool-CTMWNDMO.js");
8216
+ const { interruptClient: interruptClient2 } = await import("./client-pool-PV45NUTN.js");
8214
8217
  await interruptClient2(session_key);
8215
8218
  return c.json({ ok: true });
8216
8219
  } catch (err) {
@@ -8661,10 +8664,15 @@ app13.get("/", async (c) => {
8661
8664
  const filePath = resolve13(dir, safe);
8662
8665
  searched.push(filePath);
8663
8666
  try {
8664
- const content = readFileSync12(filePath, "utf-8");
8665
- const headers = { "Content-Type": "text/plain; charset=utf-8" };
8667
+ const buffer = readFileSync12(filePath);
8668
+ const onDiskBytes = statSync7(filePath).size;
8669
+ const headers = {
8670
+ "Content-Type": "text/plain; charset=utf-8",
8671
+ "Content-Length": String(buffer.byteLength)
8672
+ };
8666
8673
  if (download) headers["Content-Disposition"] = `attachment; filename="${safe}"`;
8667
- return new Response(content, { headers });
8674
+ console.info(`[stream-log-download] file=${safe} bytesServed=${buffer.byteLength} onDiskBytes=${onDiskBytes}`);
8675
+ return new Response(buffer, { headers });
8668
8676
  } catch (err) {
8669
8677
  const reason = err instanceof Error ? err.message : String(err);
8670
8678
  console.debug(`[admin/logs] miss dir=${dir} name=${safe} reason=${reason}`);
@@ -8729,9 +8737,9 @@ app13.get("/", async (c) => {
8729
8737
  const hit = hits[0];
8730
8738
  console.info(`[admin/logs] resolved sessionKey=${sessionKeySlice} conversationId=${conversationIdSlice} shape=${hit.shape} stalePreflushCount=${stalePreflushCount}`);
8731
8739
  try {
8732
- const content = readFileSync12(hit.path, "utf-8");
8733
8740
  const filename = basename5(hit.path);
8734
8741
  if (stalePreflushCount > 0 && !download) {
8742
+ const content = readFileSync12(hit.path, "utf-8");
8735
8743
  return c.json({
8736
8744
  log: content,
8737
8745
  filename,
@@ -8739,9 +8747,15 @@ app13.get("/", async (c) => {
8739
8747
  warnings: stalePreflushPaths.map((path2) => ({ kind: "stale-preflush", path: path2 }))
8740
8748
  });
8741
8749
  }
8742
- const headers = { "Content-Type": "text/plain; charset=utf-8" };
8750
+ const buffer = readFileSync12(hit.path);
8751
+ const onDiskBytes = statSync7(hit.path).size;
8752
+ const headers = {
8753
+ "Content-Type": "text/plain; charset=utf-8",
8754
+ "Content-Length": String(buffer.byteLength)
8755
+ };
8743
8756
  if (download) headers["Content-Disposition"] = `attachment; filename="${filename}"`;
8744
- return new Response(content, { headers });
8757
+ console.info(`[stream-log-download] file=${filename} bytesServed=${buffer.byteLength} onDiskBytes=${onDiskBytes}`);
8758
+ return new Response(buffer, { headers });
8745
8759
  } catch (err) {
8746
8760
  const reason2 = err instanceof Error ? err.message : String(err);
8747
8761
  console.warn(`[admin/logs] read-fail path=${hit.path} reason=${reason2}`);
@@ -11782,57 +11796,16 @@ app30.get("/", requireAdminSession, async (c) => {
11782
11796
  });
11783
11797
  var adherence_default = app30;
11784
11798
 
11785
- // server/routes/admin/sidebar-projects.ts
11786
- import neo4j3 from "neo4j-driver";
11787
- var LIMIT = 50;
11788
- var app31 = new Hono();
11789
- app31.get("/", requireAdminSession, async (c) => {
11790
- const sessionKey = c.var.sessionKey;
11791
- const accountId = getAccountIdForSession(sessionKey);
11792
- if (!accountId) {
11793
- return c.json({ error: "Account not found for session" }, 401);
11794
- }
11795
- const start = Date.now();
11796
- const session = getSession();
11797
- try {
11798
- const result = await session.run(
11799
- `MATCH (p:Project { accountId: $accountId })
11800
- WHERE NOT p:Trashed
11801
- RETURN p.taskId AS id, elementId(p) AS elementId, p.name AS name, p.updatedAt AS updatedAt
11802
- ORDER BY p.updatedAt DESC
11803
- LIMIT $limit`,
11804
- { accountId, limit: neo4j3.int(LIMIT) }
11805
- );
11806
- const projects = result.records.map((r) => ({
11807
- id: r.get("id"),
11808
- elementId: r.get("elementId"),
11809
- name: r.get("name") ?? "",
11810
- updatedAt: r.get("updatedAt") ?? ""
11811
- }));
11812
- const ms = Date.now() - start;
11813
- console.log(`[admin/sidebar-projects] account=${accountId} count=${projects.length} ms=${ms}`);
11814
- return c.json({ projects });
11815
- } catch (err) {
11816
- const ms = Date.now() - start;
11817
- const message = err instanceof Error ? err.message : String(err);
11818
- console.error(`[admin/sidebar-projects] account=${accountId} error="${message}" ms=${ms}`);
11819
- return c.json({ error: "Failed to load projects" }, 500);
11820
- } finally {
11821
- await session.close();
11822
- }
11823
- });
11824
- var sidebar_projects_default = app31;
11825
-
11826
11799
  // server/routes/admin/sidebar-artefacts.ts
11827
- import neo4j4 from "neo4j-driver";
11800
+ import neo4j3 from "neo4j-driver";
11828
11801
  import { readFile as readFile5, readdir as readdir3, stat as stat5 } from "fs/promises";
11829
11802
  import { resolve as resolve20, relative as relative2, isAbsolute } from "path";
11830
11803
  import { existsSync as existsSync19 } from "fs";
11831
- var LIMIT2 = 50;
11804
+ var LIMIT = 50;
11832
11805
  var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
11833
11806
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
11834
- var app32 = new Hono();
11835
- app32.get("/", requireAdminSession, async (c) => {
11807
+ var app31 = new Hono();
11808
+ app31.get("/", requireAdminSession, async (c) => {
11836
11809
  const sessionKey = c.var.sessionKey;
11837
11810
  const accountId = getAccountIdForSession(sessionKey);
11838
11811
  if (!accountId) {
@@ -11847,7 +11820,7 @@ app32.get("/", requireAdminSession, async (c) => {
11847
11820
  const agents = await fetchAgentTemplateRows(accountDir);
11848
11821
  const artefacts = [...docs, ...agents].sort(
11849
11822
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
11850
- ).slice(0, LIMIT2);
11823
+ ).slice(0, LIMIT);
11851
11824
  const ms = Date.now() - start;
11852
11825
  console.log(
11853
11826
  `[admin/sidebar-artefacts] account=${accountId} count=${artefacts.length} docs=${docs.length} agents=${agents.length} ms=${ms}`
@@ -11865,7 +11838,7 @@ async function fetchKnowledgeDocs(accountId) {
11865
11838
  d.attachmentId AS attachmentId, d.encodingFormat AS mimeType
11866
11839
  ORDER BY d.updatedAt DESC
11867
11840
  LIMIT $limit`,
11868
- { accountId, limit: neo4j4.int(LIMIT2) }
11841
+ { accountId, limit: neo4j3.int(LIMIT) }
11869
11842
  );
11870
11843
  metas = result.records.map((r) => ({
11871
11844
  id: r.get("id"),
@@ -12038,7 +12011,7 @@ function isWithin(target, root) {
12038
12011
  const rel = relative2(root, target);
12039
12012
  return !rel.startsWith("..") && !isAbsolute(rel);
12040
12013
  }
12041
- var sidebar_artefacts_default = app32;
12014
+ var sidebar_artefacts_default = app31;
12042
12015
 
12043
12016
  // server/routes/admin/sidebar-artefact-save.ts
12044
12017
  import { mkdir as mkdir4, readdir as readdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
@@ -12046,8 +12019,8 @@ import { resolve as resolve21 } from "path";
12046
12019
  import { existsSync as existsSync20 } from "fs";
12047
12020
  var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
12048
12021
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
12049
- var app33 = new Hono();
12050
- app33.post("/", requireAdminSession, async (c) => {
12022
+ var app32 = new Hono();
12023
+ app32.post("/", requireAdminSession, async (c) => {
12051
12024
  const sessionKey = c.var.sessionKey;
12052
12025
  const accountId = getAccountIdForSession(sessionKey);
12053
12026
  if (!accountId) return c.json({ error: "Account not found for session" }, 401);
@@ -12127,15 +12100,15 @@ async function resolveSavePath(id, accountId, accountDir) {
12127
12100
  function relPath(absPath, root) {
12128
12101
  return absPath.startsWith(root) ? absPath.slice(root.length + 1) : absPath;
12129
12102
  }
12130
- var sidebar_artefact_save_default = app33;
12103
+ var sidebar_artefact_save_default = app32;
12131
12104
 
12132
12105
  // server/routes/admin/sidebar-artefact-content.ts
12133
12106
  import { readFile as readFile6, readdir as readdir5 } from "fs/promises";
12134
12107
  import { existsSync as existsSync21 } from "fs";
12135
12108
  import { resolve as resolve22 } from "path";
12136
12109
  var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
12137
- var app34 = new Hono();
12138
- app34.get("/", requireAdminSession, async (c) => {
12110
+ var app33 = new Hono();
12111
+ app33.get("/", requireAdminSession, async (c) => {
12139
12112
  const sessionKey = c.var.sessionKey;
12140
12113
  const accountId = getAccountIdForSession(sessionKey);
12141
12114
  if (!accountId) return new Response("Unauthorized", { status: 401 });
@@ -12176,36 +12149,35 @@ app34.get("/", requireAdminSession, async (c) => {
12176
12149
  }
12177
12150
  });
12178
12151
  });
12179
- var sidebar_artefact_content_default = app34;
12152
+ var sidebar_artefact_content_default = app33;
12180
12153
 
12181
12154
  // server/routes/admin/index.ts
12182
- var app35 = new Hono();
12183
- app35.route("/session", session_default2);
12184
- app35.route("/chat", chat_default2);
12185
- app35.route("/compact", compact_default);
12186
- app35.route("/logs", logs_default);
12187
- app35.route("/claude-info", claude_info_default);
12188
- app35.route("/attachment", attachment_default);
12189
- app35.route("/agents", agents_default);
12190
- app35.route("/sessions", sessions_default);
12191
- app35.route("/browser", browser_default);
12192
- app35.route("/device-browser", device_browser_default);
12193
- app35.route("/events", events_default);
12194
- app35.route("/cloudflare", cloudflare_default);
12195
- app35.route("/files", files_default);
12196
- app35.route("/graph-search", graph_search_default);
12197
- app35.route("/graph-subgraph", graph_subgraph_default);
12198
- app35.route("/graph-delete", graph_delete_default);
12199
- app35.route("/graph-restore", graph_restore_default);
12200
- app35.route("/graph-labels-in-graph", graph_labels_in_graph_default);
12201
- app35.route("/graph-default-view", graph_default_view_default);
12202
- app35.route("/file-attach", file_attach_default);
12203
- app35.route("/adherence", adherence_default);
12204
- app35.route("/sidebar-projects", sidebar_projects_default);
12205
- app35.route("/sidebar-artefacts", sidebar_artefacts_default);
12206
- app35.route("/sidebar-artefact-save", sidebar_artefact_save_default);
12207
- app35.route("/sidebar-artefact-content", sidebar_artefact_content_default);
12208
- var admin_default = app35;
12155
+ var app34 = new Hono();
12156
+ app34.route("/session", session_default2);
12157
+ app34.route("/chat", chat_default2);
12158
+ app34.route("/compact", compact_default);
12159
+ app34.route("/logs", logs_default);
12160
+ app34.route("/claude-info", claude_info_default);
12161
+ app34.route("/attachment", attachment_default);
12162
+ app34.route("/agents", agents_default);
12163
+ app34.route("/sessions", sessions_default);
12164
+ app34.route("/browser", browser_default);
12165
+ app34.route("/device-browser", device_browser_default);
12166
+ app34.route("/events", events_default);
12167
+ app34.route("/cloudflare", cloudflare_default);
12168
+ app34.route("/files", files_default);
12169
+ app34.route("/graph-search", graph_search_default);
12170
+ app34.route("/graph-subgraph", graph_subgraph_default);
12171
+ app34.route("/graph-delete", graph_delete_default);
12172
+ app34.route("/graph-restore", graph_restore_default);
12173
+ app34.route("/graph-labels-in-graph", graph_labels_in_graph_default);
12174
+ app34.route("/graph-default-view", graph_default_view_default);
12175
+ app34.route("/file-attach", file_attach_default);
12176
+ app34.route("/adherence", adherence_default);
12177
+ app34.route("/sidebar-artefacts", sidebar_artefacts_default);
12178
+ app34.route("/sidebar-artefact-save", sidebar_artefact_save_default);
12179
+ app34.route("/sidebar-artefact-content", sidebar_artefact_content_default);
12180
+ var admin_default = app34;
12209
12181
 
12210
12182
  // app/lib/graph-health.ts
12211
12183
  var HOUR_MS = 60 * 60 * 1e3;
@@ -12359,9 +12331,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
12359
12331
  function isPublicHost(host) {
12360
12332
  return host.startsWith("public.") || aliasDomains.has(host);
12361
12333
  }
12362
- var app36 = new Hono();
12363
- app36.use("*", clientIpMiddleware);
12364
- app36.use("*", async (c, next) => {
12334
+ var app35 = new Hono();
12335
+ app35.use("*", clientIpMiddleware);
12336
+ app35.use("*", async (c, next) => {
12365
12337
  await next();
12366
12338
  c.header("X-Content-Type-Options", "nosniff");
12367
12339
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
@@ -12384,7 +12356,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
12384
12356
  "/g/"
12385
12357
  ];
12386
12358
  var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
12387
- app36.use("*", async (c, next) => {
12359
+ app35.use("*", async (c, next) => {
12388
12360
  const host = (c.req.header("host") ?? "").split(":")[0];
12389
12361
  if (!isPublicHost(host)) {
12390
12362
  await next();
@@ -12424,7 +12396,7 @@ function resolveRemoteAuthOpts() {
12424
12396
  return brandLoginOpts;
12425
12397
  }
12426
12398
  var MAX_LOGIN_BODY = 8 * 1024;
12427
- app36.post("/__remote-auth/login", async (c) => {
12399
+ app35.post("/__remote-auth/login", async (c) => {
12428
12400
  const client = clientFrom(c);
12429
12401
  const clientIp = client.ip || "unknown";
12430
12402
  if (!requestIsTlsTerminated(c)) {
@@ -12468,7 +12440,7 @@ app36.post("/__remote-auth/login", async (c) => {
12468
12440
  }
12469
12441
  });
12470
12442
  });
12471
- app36.get("/__remote-auth/logout", (c) => {
12443
+ app35.get("/__remote-auth/logout", (c) => {
12472
12444
  return new Response(null, {
12473
12445
  status: 302,
12474
12446
  headers: {
@@ -12478,7 +12450,7 @@ app36.get("/__remote-auth/logout", (c) => {
12478
12450
  }
12479
12451
  });
12480
12452
  });
12481
- app36.post("/__remote-auth/change-password", async (c) => {
12453
+ app35.post("/__remote-auth/change-password", async (c) => {
12482
12454
  const client = clientFrom(c);
12483
12455
  const clientIp = client.ip || "unknown";
12484
12456
  const rateLimited = checkRateLimit(client);
@@ -12528,13 +12500,13 @@ app36.post("/__remote-auth/change-password", async (c) => {
12528
12500
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
12529
12501
  }
12530
12502
  });
12531
- app36.get("/__remote-auth/setup", (c) => {
12503
+ app35.get("/__remote-auth/setup", (c) => {
12532
12504
  if (isRemoteAuthConfigured()) {
12533
12505
  return c.redirect("/");
12534
12506
  }
12535
12507
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
12536
12508
  });
12537
- app36.post("/__remote-auth/set-initial-password", async (c) => {
12509
+ app35.post("/__remote-auth/set-initial-password", async (c) => {
12538
12510
  if (isRemoteAuthConfigured()) {
12539
12511
  return c.redirect("/");
12540
12512
  }
@@ -12570,17 +12542,17 @@ app36.post("/__remote-auth/set-initial-password", async (c) => {
12570
12542
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
12571
12543
  }
12572
12544
  });
12573
- app36.get("/api/remote-auth/status", (c) => {
12545
+ app35.get("/api/remote-auth/status", (c) => {
12574
12546
  return c.json({ configured: isRemoteAuthConfigured() });
12575
12547
  });
12576
- app36.post("/api/remote-auth/set-password", async (c) => {
12548
+ app35.post("/api/remote-auth/set-password", async (c) => {
12577
12549
  let body;
12578
12550
  try {
12579
12551
  body = await c.req.json();
12580
12552
  } catch {
12581
12553
  return c.json({ error: "Invalid request" }, 400);
12582
12554
  }
12583
- if (!body.session_key || !validateSession(body.session_key, "admin")) {
12555
+ if (!body.session_key || !validateSession(body.session_key, "admin").ok) {
12584
12556
  return c.json({ error: "Unauthorized" }, 401);
12585
12557
  }
12586
12558
  if (!body.password) {
@@ -12603,9 +12575,9 @@ app36.post("/api/remote-auth/set-password", async (c) => {
12603
12575
  return c.json({ error: "Failed to save password" }, 500);
12604
12576
  }
12605
12577
  });
12606
- app36.route("/api/_client-error", client_error_default);
12578
+ app35.route("/api/_client-error", client_error_default);
12607
12579
  console.log("[client-error-route] mounted");
12608
- app36.use("*", async (c, next) => {
12580
+ app35.use("*", async (c, next) => {
12609
12581
  const host = (c.req.header("host") ?? "").split(":")[0];
12610
12582
  const path2 = c.req.path;
12611
12583
  if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
@@ -12638,15 +12610,15 @@ app36.use("*", async (c, next) => {
12638
12610
  console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
12639
12611
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
12640
12612
  });
12641
- app36.route("/api/health", health_default);
12642
- app36.route("/api/session", session_default);
12643
- app36.route("/api/chat", chat_default);
12644
- app36.route("/api/group", group_default);
12645
- app36.route("/api/access", access_default);
12646
- app36.route("/api/telegram", telegram_default);
12647
- app36.route("/api/whatsapp", whatsapp_default);
12648
- app36.route("/api/onboarding", onboarding_default);
12649
- app36.route("/api/admin", admin_default);
12613
+ app35.route("/api/health", health_default);
12614
+ app35.route("/api/session", session_default);
12615
+ app35.route("/api/chat", chat_default);
12616
+ app35.route("/api/group", group_default);
12617
+ app35.route("/api/access", access_default);
12618
+ app35.route("/api/telegram", telegram_default);
12619
+ app35.route("/api/whatsapp", whatsapp_default);
12620
+ app35.route("/api/onboarding", onboarding_default);
12621
+ app35.route("/api/admin", admin_default);
12650
12622
  var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
12651
12623
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12652
12624
  var IMAGE_MIME = {
@@ -12658,7 +12630,7 @@ var IMAGE_MIME = {
12658
12630
  ".svg": "image/svg+xml",
12659
12631
  ".ico": "image/x-icon"
12660
12632
  };
12661
- app36.get("/agent-assets/:slug/:filename", (c) => {
12633
+ app35.get("/agent-assets/:slug/:filename", (c) => {
12662
12634
  const slug = c.req.param("slug");
12663
12635
  const filename = c.req.param("filename");
12664
12636
  if (!SAFE_SLUG_RE.test(slug)) {
@@ -12693,7 +12665,7 @@ app36.get("/agent-assets/:slug/:filename", (c) => {
12693
12665
  "Cache-Control": "public, max-age=3600"
12694
12666
  });
12695
12667
  });
12696
- app36.get("/generated/:filename", (c) => {
12668
+ app35.get("/generated/:filename", (c) => {
12697
12669
  const filename = c.req.param("filename");
12698
12670
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
12699
12671
  console.error(`[generated] serve file=${filename} status=403`);
@@ -12859,7 +12831,7 @@ function brandedPublicHtml(agentSlug) {
12859
12831
  function escapeHtml(s) {
12860
12832
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
12861
12833
  }
12862
- app36.get("/", (c) => {
12834
+ app35.get("/", (c) => {
12863
12835
  const host = (c.req.header("host") ?? "").split(":")[0];
12864
12836
  if (isPublicHost(host)) {
12865
12837
  const defaultSlug = resolveDefaultSlug();
@@ -12867,12 +12839,12 @@ app36.get("/", (c) => {
12867
12839
  }
12868
12840
  return c.html(cachedHtml("index.html"));
12869
12841
  });
12870
- app36.get("/public", (c) => {
12842
+ app35.get("/public", (c) => {
12871
12843
  const host = (c.req.header("host") ?? "").split(":")[0];
12872
12844
  if (isPublicHost(host)) return c.text("Not found", 404);
12873
12845
  return c.html(cachedHtml("public.html"));
12874
12846
  });
12875
- app36.get("/chat", (c) => {
12847
+ app35.get("/chat", (c) => {
12876
12848
  const host = (c.req.header("host") ?? "").split(":")[0];
12877
12849
  if (isPublicHost(host)) return c.text("Not found", 404);
12878
12850
  return c.html(cachedHtml("public.html"));
@@ -12891,9 +12863,9 @@ async function logViewerFetch(c, next) {
12891
12863
  duration_ms: Date.now() - start
12892
12864
  });
12893
12865
  }
12894
- app36.use("/vnc-viewer.html", logViewerFetch);
12895
- app36.use("/vnc-popout.html", logViewerFetch);
12896
- app36.get("/vnc-popout.html", (c) => {
12866
+ app35.use("/vnc-viewer.html", logViewerFetch);
12867
+ app35.use("/vnc-popout.html", logViewerFetch);
12868
+ app35.get("/vnc-popout.html", (c) => {
12897
12869
  let html = htmlCache.get("vnc-popout.html");
12898
12870
  if (!html) {
12899
12871
  html = readFileSync16(resolve23(process.cwd(), "public", "vnc-popout.html"), "utf-8");
@@ -12906,7 +12878,7 @@ app36.get("/vnc-popout.html", (c) => {
12906
12878
  }
12907
12879
  return c.html(html);
12908
12880
  });
12909
- app36.post("/api/vnc/client-event", async (c) => {
12881
+ app35.post("/api/vnc/client-event", async (c) => {
12910
12882
  let body;
12911
12883
  try {
12912
12884
  body = await c.req.json();
@@ -12927,20 +12899,20 @@ app36.post("/api/vnc/client-event", async (c) => {
12927
12899
  });
12928
12900
  return c.json({ ok: true });
12929
12901
  });
12930
- app36.get("/g/:slug", (c) => {
12902
+ app35.get("/g/:slug", (c) => {
12931
12903
  return c.html(brandedPublicHtml());
12932
12904
  });
12933
- app36.get("/graph", (c) => {
12905
+ app35.get("/graph", (c) => {
12934
12906
  const host = (c.req.header("host") ?? "").split(":")[0];
12935
12907
  if (isPublicHost(host)) return c.text("Not found", 404);
12936
12908
  return c.html(cachedHtml("graph.html"));
12937
12909
  });
12938
- app36.get("/data", (c) => {
12910
+ app35.get("/data", (c) => {
12939
12911
  const host = (c.req.header("host") ?? "").split(":")[0];
12940
12912
  if (isPublicHost(host)) return c.text("Not found", 404);
12941
12913
  return c.html(cachedHtml("data.html"));
12942
12914
  });
12943
- app36.get("/:slug", async (c, next) => {
12915
+ app35.get("/:slug", async (c, next) => {
12944
12916
  const slug = c.req.param("slug");
12945
12917
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
12946
12918
  const branding = loadBrandingCache(slug);
@@ -12949,10 +12921,10 @@ app36.get("/:slug", async (c, next) => {
12949
12921
  }
12950
12922
  await next();
12951
12923
  });
12952
- app36.use("/*", serveStatic({ root: "./public" }));
12924
+ app35.use("/*", serveStatic({ root: "./public" }));
12953
12925
  var port = parseInt(process.env.MAXY_UI_INTERNAL_PORT ?? process.env.PORT ?? "19199", 10);
12954
12926
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
12955
- var httpServer = serve({ fetch: app36.fetch, port, hostname });
12927
+ var httpServer = serve({ fetch: app35.fetch, port, hostname });
12956
12928
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
12957
12929
  var SUBAPP_MANIFEST = [
12958
12930
  { prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
@@ -12972,7 +12944,7 @@ for (const m of SUBAPP_MANIFEST) {
12972
12944
  }
12973
12945
  try {
12974
12946
  const registered = [];
12975
- for (const r of app36.routes ?? []) {
12947
+ for (const r of app35.routes ?? []) {
12976
12948
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
12977
12949
  if (AGENT_SLUG_PATTERN.test(r.path)) {
12978
12950
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
@@ -12995,6 +12967,13 @@ try {
12995
12967
  console.error(`[session] backfill startup failed: ${err instanceof Error ? err.message : String(err)}`);
12996
12968
  }
12997
12969
  })();
12970
+ (async () => {
12971
+ try {
12972
+ await runBootMigrations();
12973
+ } catch (err) {
12974
+ console.error(`[migration] runBootMigrations rejected: ${err instanceof Error ? err.message : String(err)}`);
12975
+ }
12976
+ })();
12998
12977
  (async () => {
12999
12978
  try {
13000
12979
  await startReviewDetector();
@@ -1 +0,0 @@
1
- import{i as e,t}from"./jsx-runtime-DJER3a7U.js";import{t as n}from"./page-DIG7s5Jp.js";var r=e(),i=t();(0,r.createRoot)(document.getElementById(`root`)).render((0,i.jsx)(n,{}));
@@ -1 +0,0 @@
1
- import{i as e,t}from"./jsx-runtime-DJER3a7U.js";import{n}from"./page-sZb3wcOM.js";import"./Checkbox-BruL6MSR.js";var r=e(),i=t();(0,r.createRoot)(document.getElementById(`root`)).render((0,i.jsx)(n,{}));
@@ -1 +0,0 @@
1
- import{o as e}from"./chunk-DD-I1_y5.js";import{n as t,o as n,r,t as i}from"./jsx-runtime-DJER3a7U.js";import{a,i as o,n as s,o as c,r as l,s as u,t as d}from"./share-2-BndjMKeG.js";var f=r(`circle-arrow-up`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m16 12-4-4-4 4`,key:`177agl`}],[`path`,{d:`M12 16V8`,key:`1sbj14`}]]),p=r(`download`,[[`path`,{d:`M12 15V3`,key:`m9g1x1`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}],[`path`,{d:`m7 10 5 5 5-5`,key:`brsn70`}]]),m=r(`file`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}]]),h=r(`folder`,[[`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`,key:`1kt360`}]]),g=r(`upload`,[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]),_=e(n(),1),v=i();function y(){let[e,t]=(0,_.useState)(null),[n,r]=(0,_.useState)(!1);return(0,_.useEffect)(()=>{let e=!1,n=null;try{n=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!n){t(null),r(!0);return}return fetch(`/api/admin/session?session_key=${encodeURIComponent(n)}`).then(i=>{if(!e){if(i.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}window.location.href=`/`;return}t(n),r(!0)}}).catch(()=>{e||(t(n),r(!0))}),()=>{e=!0}},[]),n?e?(0,v.jsxs)(`div`,{className:`data-page`,children:[(0,v.jsxs)(`header`,{className:`data-header`,children:[(0,v.jsxs)(`h1`,{className:`data-title`,children:[(0,v.jsx)(u,{size:18}),` Data`]}),(0,v.jsx)(x,{})]}),(0,v.jsx)(b,{sessionKey:e})]}):(0,v.jsxs)(`div`,{className:`data-page`,children:[(0,v.jsx)(`header`,{className:`data-header`,children:(0,v.jsxs)(`h1`,{className:`data-title`,children:[(0,v.jsx)(u,{size:18}),` Data`]})}),(0,v.jsxs)(`div`,{className:`data-empty`,children:[(0,v.jsx)(`p`,{children:`You are not signed in.`}),(0,v.jsxs)(`p`,{children:[`Open the `,(0,v.jsx)(`a`,{href:`/`,className:`data-link`,children:`main admin page`}),` and log in, then return here.`]})]})]}):(0,v.jsx)(`div`,{className:`data-page`,children:(0,v.jsxs)(`div`,{className:`data-loading`,children:[(0,v.jsx)(a,{size:18,className:`spin`}),` Loading…`]})})}function b({sessionKey:e}){return(0,v.jsxs)(`main`,{className:`data-main`,children:[(0,v.jsx)(S,{sessionKey:e}),(0,v.jsx)(D,{sessionKey:e})]})}function x(){let[e,t]=(0,_.useState)(!1),n=(0,_.useRef)(null);(0,_.useEffect)(()=>{if(!e)return;let r=e=>{n.current&&(n.current.contains(e.target)||t(!1))},i=e=>{e.key===`Escape`&&t(!1)};return document.addEventListener(`mousedown`,r),document.addEventListener(`keydown`,i),()=>{document.removeEventListener(`mousedown`,r),document.removeEventListener(`keydown`,i)}},[e]);let r=(0,_.useCallback)(()=>{try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}window.location.href=`/`},[]);return(0,v.jsxs)(`div`,{className:`chat-burger-wrap`,ref:n,children:[(0,v.jsx)(`button`,{type:`button`,className:`chat-burger`,onClick:()=>t(e=>!e),"aria-label":`Menu`,"aria-haspopup":`true`,"aria-expanded":e,children:(0,v.jsx)(l,{size:20})}),e&&(0,v.jsxs)(`div`,{className:`chat-menu`,children:[(0,v.jsxs)(`button`,{type:`button`,className:`chat-menu-item`,onClick:()=>{t(!1),window.location.href=`/`},children:[(0,v.jsx)(c,{size:14}),` Chat`]}),(0,v.jsxs)(`button`,{type:`button`,className:`chat-menu-item`,onClick:()=>{t(!1),window.location.href=`/graph`},children:[(0,v.jsx)(d,{size:14}),` Graph`]}),(0,v.jsx)(`div`,{className:`chat-menu-divider`}),(0,v.jsxs)(`button`,{type:`button`,className:`chat-menu-item`,onClick:()=>{t(!1),r()},children:[(0,v.jsx)(o,{size:14}),` Log out`]})]})]})}function S({sessionKey:e}){let[t,n]=(0,_.useState)(``),[r,i]=(0,_.useState)(``),[o,c]=(0,_.useState)(null),[l,u]=(0,_.useState)(!1),[d,f]=(0,_.useState)(null);return(0,_.useEffect)(()=>{let e=t.trim();if(!e){i(``),c(null);return}let n=setTimeout(()=>i(e),300);return()=>clearTimeout(n)},[t]),(0,_.useEffect)(()=>{if(!r)return;let t=!1;u(!0),f(null);let n=`/api/admin/graph-search?session_key=${encodeURIComponent(e)}&q=${encodeURIComponent(r)}&limit=20`;return fetch(n).then(async e=>{let t=await e.json().catch(()=>({error:`HTTP ${e.status}`}));if(!e.ok)throw Error(t.error??`HTTP ${e.status}`);return t}).then(e=>{t||c(e.results)}).catch(e=>{t||f(e instanceof Error?e.message:String(e))}).finally(()=>{t||u(!1)}),()=>{t=!0}},[r,e]),(0,v.jsxs)(`section`,{className:`data-panel`,children:[(0,v.jsx)(`h2`,{className:`data-panel-title`,children:`Search`}),(0,v.jsx)(`p`,{className:`data-panel-subtitle`,children:`Find anything in your knowledge base by keyword.`}),(0,v.jsxs)(`div`,{className:`data-search-input`,children:[(0,v.jsx)(s,{size:14}),(0,v.jsx)(`input`,{type:`text`,placeholder:`Search your knowledge…`,value:t,onChange:e=>n(e.target.value),autoFocus:!0,autoComplete:`off`,spellCheck:!1}),l&&(0,v.jsx)(a,{size:14,className:`spin`})]}),d&&(0,v.jsxs)(`div`,{className:`data-error`,children:[`Search failed: `,d]}),o&&!l&&(0,v.jsxs)(`div`,{className:`data-results-meta`,children:[o.length,` result`,o.length===1?``:`s`]}),o&&o.length===0&&!l&&(0,v.jsx)(`div`,{className:`data-empty-results`,children:`No matches. Try a different keyword.`}),o&&o.length>0&&(0,v.jsx)(`ul`,{className:`data-results`,children:o.map(e=>(0,v.jsx)(C,{hit:e},e.nodeId))})]})}function C({hit:e}){let t=T(e.properties),n=E(e.properties),r=w(e.labels),[i,a]=(0,_.useState)(!1),o=n&&n.length>280,s=i||!o?n:n?.slice(0,280)+`…`;return(0,v.jsxs)(`li`,{className:`data-result`,children:[r&&(0,v.jsx)(`div`,{className:`data-result-header`,children:(0,v.jsx)(`span`,{className:`data-result-labels`,children:r})}),t&&(0,v.jsx)(`div`,{className:`data-result-title`,children:t}),n&&(0,v.jsx)(`pre`,{className:`data-result-body`,children:s}),o&&(0,v.jsx)(`button`,{type:`button`,className:`data-result-toggle`,onClick:()=>a(e=>!e),children:i?`Show less`:`Show more`})]})}function w(e){if(e.length===0)return null;let t=e[0].replace(/([a-z])([A-Z])/g,`$1 $2`);return t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()}function T(e){for(let t of[`title`,`name`,`summary`,`headline`]){let n=e[t];if(typeof n==`string`&&n.length>0)return n.length>140?n.slice(0,140)+`…`:n}return null}function E(e){for(let t of[`content`,`summary`,`body`,`description`,`text`]){let n=e[t];if(typeof n==`string`&&n.length>0)return n}return null}function D({sessionKey:e}){let[n,r]=(0,_.useState)(`.`),[i,o]=(0,_.useState)(null),[s,c]=(0,_.useState)([]),[l,u]=(0,_.useState)(!1),[d,y]=(0,_.useState)(null),[b,x]=(0,_.useState)(!1),[S,C]=(0,_.useState)(null),[w,T]=(0,_.useState)(null),[E,D]=(0,_.useState)(null),[A,j]=(0,_.useState)(null),M=(0,_.useRef)(null),[N,P]=(0,_.useState)(0);(0,_.useEffect)(()=>{let t=!1;u(!0),y(null);let r=`/api/admin/files?session_key=${encodeURIComponent(e)}&path=${encodeURIComponent(n===`.`?``:n)}`;return fetch(r).then(async e=>{let t=await e.json().catch(()=>({error:`HTTP ${e.status}`}));if(!e.ok)throw Error(t.error??`HTTP ${e.status}`);return t}).then(e=>{t||(o(e.entries),c(e.displayPath??[]))}).catch(e=>{t||(o([]),c([]),y(e instanceof Error?e.message:String(e)))}).finally(()=>{t||u(!1)}),()=>{t=!0}},[e,n,N]);let F=(0,_.useCallback)(e=>{r(e)},[]),I=(0,_.useCallback)(()=>{if(n===`.`||n===``)return;let e=n.split(`/`).filter(Boolean);e.pop(),r(e.length===0?`.`:e.join(`/`))},[n]),L=(0,_.useCallback)(t=>{let r=n===`.`?t.name:`${n}/${t.name}`,i=`/api/admin/files/download?session_key=${encodeURIComponent(e)}&path=${encodeURIComponent(r)}`,a=document.createElement(`a`);a.href=i,a.rel=`noopener noreferrer`,document.body.appendChild(a),a.click(),a.remove()},[n,e]),R=(0,_.useCallback)(()=>{M.current?.click()},[]),z=(0,_.useCallback)(e=>{T(null),j(e.name)},[]),B=(0,_.useCallback)(()=>{j(null)},[]),V=(0,_.useCallback)(async t=>{let r=n===`.`?t.name:`${n}/${t.name}`;T(null),j(null),D(t.name);try{let t=`/api/admin/files?session_key=${encodeURIComponent(e)}&path=${encodeURIComponent(r)}`,n=await fetch(t,{method:`DELETE`}),i=await n.json().catch(()=>({error:`HTTP ${n.status}`}));if(!n.ok)throw Error(i.error??`HTTP ${n.status}`);P(e=>e+1)}catch(e){T(e instanceof Error?e.message:String(e))}finally{D(null)}},[n,e]);(0,_.useEffect)(()=>{if(!A)return;let e=e=>{e.key===`Escape`&&j(null)};return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[A]);let H=(0,_.useCallback)(async t=>{C(null),x(!0);try{let n=new FormData;n.append(`session_key`,e),n.append(`file`,t);let i=await fetch(`/api/admin/files/upload`,{method:`POST`,body:n}),a=await i.json().catch(()=>({error:`HTTP ${i.status}`}));if(!i.ok)throw Error(a.error??`HTTP ${i.status}`);r(a.path.split(`/`).slice(0,-1).join(`/`)||`.`),P(e=>e+1)}catch(e){C(e instanceof Error?e.message:String(e))}finally{x(!1),M.current&&(M.current.value=``)}},[e]);return(0,v.jsxs)(`section`,{className:`data-panel`,children:[(0,v.jsxs)(`div`,{className:`data-panel-heading`,children:[(0,v.jsx)(`h2`,{className:`data-panel-title`,children:`Files`}),(0,v.jsxs)(`div`,{className:`data-file-actions`,children:[(0,v.jsxs)(`button`,{type:`button`,className:`data-btn`,onClick:R,disabled:b,children:[b?(0,v.jsx)(a,{size:14,className:`spin`}):(0,v.jsx)(g,{size:14}),` Upload`]}),(0,v.jsx)(`input`,{type:`file`,ref:M,hidden:!0,onChange:e=>{let t=e.target.files?.[0];t&&H(t)}})]})]}),(0,v.jsxs)(`p`,{className:`data-panel-subtitle`,children:[`Everything under your install's `,(0,v.jsx)(`code`,{children:`data/`}),` directory. Click a folder to open it, a file to download it. Uploads go to `,(0,v.jsx)(`code`,{children:`data/uploads/`}),`.`]}),(0,v.jsxs)(`div`,{className:`data-breadcrumbs`,children:[(0,v.jsx)(`button`,{type:`button`,className:`data-crumb`,onClick:()=>F(`.`),children:`data`}),s.map((e,t)=>{let n=s.slice(0,t+1).map(e=>e.name).join(`/`);return(0,v.jsxs)(`span`,{className:`data-crumb-wrap`,children:[(0,v.jsx)(`span`,{className:`data-crumb-sep`,children:`/`}),(0,v.jsx)(`button`,{type:`button`,className:`data-crumb`,onClick:()=>F(n),title:e.name,children:e.displayName??e.name})]},n)}),n!==`.`&&(0,v.jsxs)(`button`,{type:`button`,className:`data-btn data-btn-ghost data-up-btn`,onClick:I,children:[(0,v.jsx)(f,{size:14}),` Up`]})]}),S&&(0,v.jsxs)(`div`,{className:`data-error`,children:[`Upload failed: `,S]}),w&&(0,v.jsxs)(`div`,{className:`data-error`,children:[`Delete failed: `,w]}),d&&(0,v.jsx)(`div`,{className:`data-error`,children:d}),l&&(0,v.jsxs)(`div`,{className:`data-loading`,children:[(0,v.jsx)(a,{size:14,className:`spin`}),` Loading…`]}),!l&&i&&i.length===0&&!d&&(0,v.jsx)(`div`,{className:`data-empty-results`,children:`Empty directory.`}),!l&&i&&i.length>0&&(0,v.jsx)(`ul`,{className:`data-entries`,children:i.map(e=>{let r=e.displayName??e.name,i=E===e.name,o=A===e.name;return(0,v.jsx)(`li`,{className:`data-entry`,children:e.kind===`directory`?(0,v.jsxs)(`button`,{type:`button`,className:`data-entry-btn`,onClick:()=>F(n===`.`?e.name:`${n}/${e.name}`),children:[(0,v.jsx)(h,{size:14}),(0,v.jsx)(`span`,{className:`data-entry-name`,title:e.name,children:r})]}):e.kind===`file`?(0,v.jsxs)(v.Fragment,{children:[(0,v.jsxs)(`button`,{type:`button`,className:`data-entry-btn`,onClick:()=>L(e),title:`Download ${r}`,disabled:o,children:[(0,v.jsx)(m,{size:14}),(0,v.jsx)(`span`,{className:`data-entry-name`,title:e.name,children:r}),(0,v.jsxs)(`span`,{className:`data-entry-meta`,title:`Modified ${k(e.modifiedAt)}`,children:[O(e.sizeBytes),` · `,k(e.modifiedAt)]}),(0,v.jsx)(p,{size:12,className:`data-entry-download-icon`})]}),o?(0,v.jsxs)(`div`,{className:`data-entry-confirm`,role:`group`,"aria-label":`Confirm delete ${r}`,children:[(0,v.jsx)(`span`,{className:`data-entry-confirm-label`,children:`Delete?`}),(0,v.jsx)(`button`,{type:`button`,className:`data-entry-confirm-yes`,onClick:()=>V(e),autoFocus:!0,children:`Yes`}),(0,v.jsx)(`button`,{type:`button`,className:`data-entry-confirm-no`,onClick:B,children:`No`})]}):(0,v.jsx)(`button`,{type:`button`,className:`data-entry-delete`,onClick:()=>z(e),disabled:i,title:`Delete ${r}`,"aria-label":`Delete ${r}`,children:i?(0,v.jsx)(a,{size:14,className:`spin`}):(0,v.jsx)(t,{size:14})})]}):(0,v.jsxs)(`div`,{className:`data-entry-btn data-entry-disabled`,children:[(0,v.jsx)(m,{size:14}),(0,v.jsx)(`span`,{className:`data-entry-name`,children:r}),(0,v.jsx)(`span`,{className:`data-entry-meta`,children:`special`})]})},e.name)})})]})}function O(e){return e==null?``:e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:e<1024*1024*1024?`${(e/1024/1024).toFixed(1)} MB`:`${(e/1024/1024/1024).toFixed(1)} GB`}function k(e){try{let t=new Date(e);if(isNaN(t.getTime()))return`—`;let n=typeof navigator<`u`?navigator.languages&&navigator.languages.length>0?[...navigator.languages]:[navigator.language]:void 0;return t.toLocaleString(n,{dateStyle:`medium`,timeStyle:`short`})}catch{return`—`}}export{p as i,b as n,m as r,y as t};