bazilion 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +14 -9
  2. package/dist/cli.js +365 -140
  3. package/dist/cli.js.map +1 -1
  4. package/dist/daemon.js +4452 -16989
  5. package/dist/daemon.js.map +1 -1
  6. package/dist/web/client/assets/AgentAvatar-Cq7PVBE_.js +1 -0
  7. package/dist/web/client/assets/AgentTabs-M5K8emJ8.js +1 -0
  8. package/dist/web/client/assets/Button-BefUtjMZ.js +1 -0
  9. package/dist/web/client/assets/ChatPane-C8zQfpzH.js +74 -0
  10. package/dist/web/client/assets/ConfigTabs-DRqAymcN.js +1 -0
  11. package/dist/web/client/assets/FieldRow-BqWnxZiX.js +1 -0
  12. package/dist/web/client/assets/MembersEditor-B-47GLUb.js +1 -0
  13. package/dist/web/client/assets/SpawnTeamModal-DiiC7Nc0.js +1 -0
  14. package/dist/web/client/assets/TemplatesTabs-DB4KERTQ.js +1 -0
  15. package/dist/web/client/assets/_id-B7gv1aPQ.js +1 -0
  16. package/dist/web/client/assets/_id-C7d1AqS0.js +1 -0
  17. package/dist/web/client/assets/_id-DhiwjC8u.js +1 -0
  18. package/dist/web/client/assets/_id-p8lUuNFm.js +1 -0
  19. package/dist/web/client/assets/agents-v8G-wt0M.js +1 -0
  20. package/dist/web/client/assets/config-BdmYpS_y.js +3 -0
  21. package/dist/web/client/assets/groups-DiY_ExGM.js +1 -0
  22. package/dist/web/client/assets/inbox-DtfVx246.js +1 -0
  23. package/dist/web/client/assets/index-BQUL6oyH.js +12 -0
  24. package/dist/web/client/assets/login-CVS70W9g.js +1 -0
  25. package/dist/web/client/assets/mcp-BDLQq8OZ.js +1 -0
  26. package/dist/web/client/assets/memory-6GGuAXwx.js +1 -0
  27. package/dist/web/client/assets/profile-groups-BA8rwZMA.js +1 -0
  28. package/dist/web/client/assets/profiles-C0aAcPZg.js +1 -0
  29. package/dist/web/client/assets/routes-DgAhnKFw.js +1 -0
  30. package/dist/web/client/assets/services-BZ86QEah.js +1 -0
  31. package/dist/web/client/assets/skills-mv_NNNwo.js +1 -0
  32. package/dist/web/client/assets/styles-CmqUskDu.css +2 -0
  33. package/dist/web/client/assets/telegram-5f9WXs3x.js +1 -0
  34. package/dist/web/client/assets/tokens-DHiYsFUh.js +1 -0
  35. package/dist/web/client/assets/triggers-CjC8Ljrz.js +1 -0
  36. package/dist/web/client/assets/welcome-C-Cu-ziL.js +1 -0
  37. package/dist/web/client/assets/wire-constants-BkT5-597.js +1 -0
  38. package/dist/web/client/baziu.svg +8 -0
  39. package/dist/web/server/assets/AgentAvatar-8gTAy_tP.js +37 -0
  40. package/dist/web/server/assets/AgentTabs-BOjTN7QF.js +34 -0
  41. package/dist/web/server/assets/Button-Dsnw22OF.js +17 -0
  42. package/dist/web/server/assets/ChatPane-BvpswYvF.js +1084 -0
  43. package/dist/web/server/assets/ConfigTabs-CyuxzesF.js +41 -0
  44. package/dist/web/server/assets/FieldRow-DwyqycWI.js +94 -0
  45. package/dist/web/server/assets/MembersEditor-BWQztvrX.js +131 -0
  46. package/dist/web/server/assets/Sidebar-DmEiewRN.js +529 -0
  47. package/dist/web/server/assets/SpawnTeamModal-dSN421k_.js +107 -0
  48. package/dist/web/server/assets/TemplatesTabs---7h5GYa.js +30 -0
  49. package/dist/web/server/assets/_id-BZ-YCWSw.js +16 -0
  50. package/dist/web/server/assets/_id-Bm4-_AP-.js +367 -0
  51. package/dist/web/server/assets/_id-C78M9_j9.js +12 -0
  52. package/dist/web/server/assets/_id-CGZbudCl.js +28 -0
  53. package/dist/web/server/assets/_id-CHNm7EAd.js +161 -0
  54. package/dist/web/server/assets/_id-CrQbC5L8.js +16 -0
  55. package/dist/web/server/assets/_id-Crcw2HhT.js +38 -0
  56. package/dist/web/server/assets/_id-CvIGhq4U.js +16 -0
  57. package/dist/web/server/assets/_id-DF3pfi9M.js +27 -0
  58. package/dist/web/server/assets/_id-Dc8P9sy2.js +24 -0
  59. package/dist/web/server/assets/_id-GJk3EYTT.js +662 -0
  60. package/dist/web/server/assets/_id-pd4S7LTi.js +467 -0
  61. package/dist/web/server/assets/_tanstack-start-manifest_v-CPyKYMJg.js +174 -0
  62. package/dist/web/server/assets/agents-70EwQJR6.js +210 -0
  63. package/dist/web/server/assets/agents-Ds4lcREv.js +26 -0
  64. package/dist/web/server/assets/agents-K4Smhnq3.js +14 -0
  65. package/dist/web/server/assets/auth-DpAGLHpA.js +26 -0
  66. package/dist/web/server/assets/config-CMXUx_IF.js +19 -0
  67. package/dist/web/server/assets/config-DQbCsY_l.js +382 -0
  68. package/dist/web/server/assets/config-DxCGYgR9.js +12 -0
  69. package/dist/web/server/assets/createServerRpc-CBTntoKx.js +12 -0
  70. package/dist/web/server/assets/createSsrRpc-DHBVUN8O.js +16 -0
  71. package/dist/web/server/assets/daemon-client-2NRMzlTr.js +96 -0
  72. package/dist/web/server/assets/empty-plugin-adapters-Bos_V2s-.js +5 -0
  73. package/dist/web/server/assets/groups-CXVew7BP.js +150 -0
  74. package/dist/web/server/assets/groups-Cms8cvH5.js +12 -0
  75. package/dist/web/server/assets/groups-Dmcvw5ya.js +21 -0
  76. package/dist/web/server/assets/inbox-0QfwsrGo.js +27 -0
  77. package/dist/web/server/assets/inbox-8HybA2Ws.js +133 -0
  78. package/dist/web/server/assets/inbox-B7UWoICA.js +42 -0
  79. package/dist/web/server/assets/login-CNznncgA.js +58 -0
  80. package/dist/web/server/assets/login-CQybKk7Y.js +74 -0
  81. package/dist/web/server/assets/mcp-42BrkI1I.js +12 -0
  82. package/dist/web/server/assets/mcp-DIa0kIOf.js +268 -0
  83. package/dist/web/server/assets/mcp-DsTjY3uz.js +12 -0
  84. package/dist/web/server/assets/memory-BfrMp8iY.js +284 -0
  85. package/dist/web/server/assets/memory-Dr0lOM2y.js +28 -0
  86. package/dist/web/server/assets/memory-EEgLDfCj.js +16 -0
  87. package/dist/web/server/assets/profile-groups-BW5gU-fG.js +12 -0
  88. package/dist/web/server/assets/profile-groups-B_kIT6BU.js +208 -0
  89. package/dist/web/server/assets/profile-groups-C5isDI2t.js +28 -0
  90. package/dist/web/server/assets/profiles-BP1v-jna.js +453 -0
  91. package/dist/web/server/assets/profiles-BbPTpmyq.js +26 -0
  92. package/dist/web/server/assets/profiles-Cy5auEj8.js +12 -0
  93. package/dist/web/server/assets/router-CL100-Ly.js +460 -0
  94. package/dist/web/server/assets/routes-CzJLQxcS.js +14 -0
  95. package/dist/web/server/assets/routes-D2H1Hnoh.js +57 -0
  96. package/dist/web/server/assets/routes-Dzk8jvIo.js +33 -0
  97. package/dist/web/server/assets/services-Bgj6M2gC.js +12 -0
  98. package/dist/web/server/assets/services-DEgYsWJ4.js +17 -0
  99. package/dist/web/server/assets/services-DFenjiw0.js +94 -0
  100. package/dist/web/server/assets/skills-BASIP_rT.js +12 -0
  101. package/dist/web/server/assets/skills-C-JPRCHh.js +12 -0
  102. package/dist/web/server/assets/skills-DZXN680t.js +261 -0
  103. package/dist/web/server/assets/start-cOXH7eTI.js +4 -0
  104. package/dist/web/server/assets/telegram-BbvqVWxa.js +583 -0
  105. package/dist/web/server/assets/telegram-Bq49AtnP.js +12 -0
  106. package/dist/web/server/assets/telegram-sUckI94O.js +12 -0
  107. package/dist/web/server/assets/tokens-BERRE0wB.js +14 -0
  108. package/dist/web/server/assets/tokens-CImgxhDI.js +193 -0
  109. package/dist/web/server/assets/tokens-Dwn00iV7.js +12 -0
  110. package/dist/web/server/assets/triggers-DtexqbNH.js +16 -0
  111. package/dist/web/server/assets/triggers-TyIjwSYn.js +26 -0
  112. package/dist/web/server/assets/triggers-_iSeahif.js +191 -0
  113. package/dist/web/server/assets/welcome-BkQ9NC5K.js +81 -0
  114. package/dist/web/server/assets/wire-constants-Deb4NxBb.js +16 -0
  115. package/dist/web/server/server.js +5899 -0
  116. package/dist/web-server.js +42 -0
  117. package/dist/web-server.js.map +1 -0
  118. package/package.json +10 -4
@@ -0,0 +1,12 @@
1
+ import { t as createServerFn } from "../server.js";
2
+ import { t as createSsrRpc } from "./createSsrRpc-DHBVUN8O.js";
3
+ import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
4
+ //#region src/routes/config/mcp.tsx
5
+ var $$splitComponentImporter = () => import("./mcp-DIa0kIOf.js");
6
+ var fetchServers = createServerFn({ method: "GET" }).handler(createSsrRpc("278849457893891c3d22806d15e11a0a42cc3630b30e9e62b74cf2d3b982ded7"));
7
+ var Route = createFileRoute("/config/mcp")({
8
+ loader: () => fetchServers(),
9
+ component: lazyRouteComponent($$splitComponentImporter, "component")
10
+ });
11
+ //#endregion
12
+ export { Route as t };
@@ -0,0 +1,268 @@
1
+ import { t as Route } from "./mcp-42BrkI1I.js";
2
+ import { t as ConfigTabs } from "./ConfigTabs-CyuxzesF.js";
3
+ import { useState } from "react";
4
+ import { useRouter } from "@tanstack/react-router";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/routes/config/mcp.tsx?tsr-split=component
7
+ var TRANSPORTS = [
8
+ "stdio",
9
+ "http",
10
+ "sse"
11
+ ];
12
+ function McpPage() {
13
+ const { servers } = Route.useLoaderData();
14
+ const router = useRouter();
15
+ const [name, setName] = useState("");
16
+ const [transport, setTransport] = useState("stdio");
17
+ const [command, setCommand] = useState("");
18
+ const [argsStr, setArgsStr] = useState("");
19
+ const [url, setUrl] = useState("");
20
+ const [token, setToken] = useState("");
21
+ const [err, setErr] = useState(null);
22
+ const [busy, setBusy] = useState(false);
23
+ const [testResult, setTestResult] = useState({});
24
+ async function add(e) {
25
+ e.preventDefault();
26
+ setErr(null);
27
+ setBusy(true);
28
+ try {
29
+ const body = {
30
+ name,
31
+ transport,
32
+ command: transport === "stdio" ? command : null,
33
+ args: transport === "stdio" ? argsStr.split(" ").filter(Boolean) : [],
34
+ url: transport === "stdio" ? null : url,
35
+ authToken: token || void 0
36
+ };
37
+ const res = await fetch("/api/mcp-servers", {
38
+ method: "POST",
39
+ headers: { "content-type": "application/json" },
40
+ body: JSON.stringify(body)
41
+ });
42
+ if (!res.ok) {
43
+ const j = await res.json().catch(() => ({}));
44
+ throw new Error(j.error ?? `${res.status} ${res.statusText}`);
45
+ }
46
+ setName("");
47
+ setCommand("");
48
+ setArgsStr("");
49
+ setUrl("");
50
+ setToken("");
51
+ await router.invalidate();
52
+ } catch (e) {
53
+ setErr(e.message);
54
+ } finally {
55
+ setBusy(false);
56
+ }
57
+ }
58
+ async function toggle(s) {
59
+ await fetch(`/api/mcp-servers/${s.id}`, {
60
+ method: "PATCH",
61
+ headers: { "content-type": "application/json" },
62
+ body: JSON.stringify({ enabled: !s.enabled })
63
+ });
64
+ await router.invalidate();
65
+ }
66
+ async function remove(id) {
67
+ await fetch(`/api/mcp-servers/${id}`, { method: "DELETE" });
68
+ await router.invalidate();
69
+ }
70
+ async function test(id) {
71
+ setTestResult((r) => ({
72
+ ...r,
73
+ [id]: "connecting…"
74
+ }));
75
+ const j = await (await fetch(`/api/mcp-servers/${id}/test`, { method: "POST" })).json().catch(() => ({}));
76
+ setTestResult((r) => ({
77
+ ...r,
78
+ [id]: j.ok ? `✓ ${j.tools?.length ?? 0} tools: ${(j.tools ?? []).map((t) => t.name).join(", ")}` : `✗ ${j.error ?? "failed"}`
79
+ }));
80
+ }
81
+ return /* @__PURE__ */ jsxs("main", {
82
+ className: "mx-auto max-w-5xl px-6 py-8",
83
+ children: [
84
+ /* @__PURE__ */ jsx("h1", {
85
+ className: "font-serif text-3xl text-foreground mb-2",
86
+ children: "config"
87
+ }),
88
+ /* @__PURE__ */ jsx(ConfigTabs, { active: "mcp" }),
89
+ /* @__PURE__ */ jsxs("p", {
90
+ className: "text-muted-foreground text-sm mb-6",
91
+ children: [
92
+ "Model Context Protocol servers. Each enabled server's tools are exposed to every agent, namespaced ",
93
+ /* @__PURE__ */ jsx("code", {
94
+ className: "font-mono",
95
+ children: "mcp__<server>__<tool>"
96
+ }),
97
+ ". stdio servers run as local subprocesses and inherit your configured secrets; http/sse servers connect to a remote endpoint with an optional bearer token."
98
+ ]
99
+ }),
100
+ /* @__PURE__ */ jsxs("section", {
101
+ className: "rounded-lg border bg-card p-5 mb-6",
102
+ children: [/* @__PURE__ */ jsx("h3", {
103
+ className: "font-serif text-xl mb-3",
104
+ children: "Add a server"
105
+ }), /* @__PURE__ */ jsxs("form", {
106
+ onSubmit: add,
107
+ className: "space-y-3",
108
+ children: [
109
+ /* @__PURE__ */ jsxs("div", {
110
+ className: "flex gap-3 flex-wrap items-end",
111
+ children: [/* @__PURE__ */ jsxs("label", {
112
+ className: "text-sm",
113
+ children: ["Name", /* @__PURE__ */ jsx("input", {
114
+ type: "text",
115
+ value: name,
116
+ onChange: (e) => setName(e.target.value),
117
+ required: true,
118
+ placeholder: "playwright",
119
+ pattern: "[a-zA-Z0-9_]+",
120
+ className: "block mt-1 rounded-md border bg-background px-3 py-2 text-sm w-48"
121
+ })]
122
+ }), /* @__PURE__ */ jsxs("label", {
123
+ className: "text-sm",
124
+ children: ["Transport", /* @__PURE__ */ jsx("select", {
125
+ value: transport,
126
+ onChange: (e) => setTransport(e.target.value),
127
+ className: "block mt-1 rounded-md border bg-background px-3 py-2 text-sm",
128
+ children: TRANSPORTS.map((t) => /* @__PURE__ */ jsx("option", {
129
+ value: t,
130
+ children: t
131
+ }, t))
132
+ })]
133
+ })]
134
+ }),
135
+ transport === "stdio" ? /* @__PURE__ */ jsxs("div", {
136
+ className: "flex gap-3 flex-wrap items-end",
137
+ children: [/* @__PURE__ */ jsxs("label", {
138
+ className: "text-sm",
139
+ children: ["Command", /* @__PURE__ */ jsx("input", {
140
+ type: "text",
141
+ value: command,
142
+ onChange: (e) => setCommand(e.target.value),
143
+ placeholder: "npx",
144
+ className: "block mt-1 rounded-md border bg-background px-3 py-2 text-sm w-48"
145
+ })]
146
+ }), /* @__PURE__ */ jsxs("label", {
147
+ className: "text-sm flex-1",
148
+ children: ["Args (space-separated)", /* @__PURE__ */ jsx("input", {
149
+ type: "text",
150
+ value: argsStr,
151
+ onChange: (e) => setArgsStr(e.target.value),
152
+ placeholder: "-y @modelcontextprotocol/server-filesystem /tmp",
153
+ className: "block mt-1 rounded-md border bg-background px-3 py-2 text-sm w-full"
154
+ })]
155
+ })]
156
+ }) : /* @__PURE__ */ jsxs("div", {
157
+ className: "flex gap-3 flex-wrap items-end",
158
+ children: [/* @__PURE__ */ jsxs("label", {
159
+ className: "text-sm flex-1",
160
+ children: ["URL", /* @__PURE__ */ jsx("input", {
161
+ type: "url",
162
+ value: url,
163
+ onChange: (e) => setUrl(e.target.value),
164
+ placeholder: "https://mcp.example.com/sse",
165
+ className: "block mt-1 rounded-md border bg-background px-3 py-2 text-sm w-full"
166
+ })]
167
+ }), /* @__PURE__ */ jsxs("label", {
168
+ className: "text-sm",
169
+ children: ["Bearer token (optional)", /* @__PURE__ */ jsx("input", {
170
+ type: "password",
171
+ value: token,
172
+ onChange: (e) => setToken(e.target.value),
173
+ autoComplete: "off",
174
+ className: "block mt-1 rounded-md border bg-background px-3 py-2 text-sm w-56"
175
+ })]
176
+ })]
177
+ }),
178
+ /* @__PURE__ */ jsx("button", {
179
+ type: "submit",
180
+ disabled: busy,
181
+ className: "rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground disabled:opacity-50",
182
+ children: busy ? "adding…" : "add server"
183
+ }),
184
+ err && /* @__PURE__ */ jsx("p", {
185
+ className: "text-sm text-rose-700",
186
+ children: err
187
+ })
188
+ ]
189
+ })]
190
+ }),
191
+ /* @__PURE__ */ jsxs("table", {
192
+ className: "w-full text-sm",
193
+ children: [/* @__PURE__ */ jsx("thead", {
194
+ className: "text-left text-muted-foreground border-b",
195
+ children: /* @__PURE__ */ jsxs("tr", { children: [
196
+ /* @__PURE__ */ jsx("th", {
197
+ className: "py-2",
198
+ children: "name"
199
+ }),
200
+ /* @__PURE__ */ jsx("th", { children: "transport" }),
201
+ /* @__PURE__ */ jsx("th", { children: "target" }),
202
+ /* @__PURE__ */ jsx("th", { children: "state" }),
203
+ /* @__PURE__ */ jsx("th", {})
204
+ ] })
205
+ }), /* @__PURE__ */ jsxs("tbody", { children: [servers.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
206
+ colSpan: 5,
207
+ className: "py-6 text-center text-muted-foreground italic",
208
+ children: "no MCP servers yet — add one above"
209
+ }) }), servers.map((s) => /* @__PURE__ */ jsxs("tr", {
210
+ className: "border-b last:border-0 align-top",
211
+ children: [
212
+ /* @__PURE__ */ jsxs("td", {
213
+ className: "py-2",
214
+ children: [
215
+ s.name,
216
+ s.hasAuthToken && /* @__PURE__ */ jsx("span", {
217
+ className: "ml-2 text-[0.7em] uppercase tracking-wide text-muted-foreground",
218
+ children: "auth"
219
+ }),
220
+ testResult[s.id] && /* @__PURE__ */ jsx("div", {
221
+ className: "text-xs text-muted-foreground mt-1 break-all",
222
+ children: testResult[s.id]
223
+ })
224
+ ]
225
+ }),
226
+ /* @__PURE__ */ jsx("td", { children: s.transport }),
227
+ /* @__PURE__ */ jsx("td", {
228
+ className: "font-mono text-xs break-all",
229
+ children: s.transport === "stdio" ? `${s.command ?? ""} ${s.args.join(" ")}`.trim() : s.url
230
+ }),
231
+ /* @__PURE__ */ jsx("td", { children: s.enabled ? /* @__PURE__ */ jsx("span", {
232
+ className: "text-emerald-700",
233
+ children: "enabled"
234
+ }) : /* @__PURE__ */ jsx("span", {
235
+ className: "text-muted-foreground",
236
+ children: "disabled"
237
+ }) }),
238
+ /* @__PURE__ */ jsxs("td", {
239
+ className: "space-x-2 whitespace-nowrap",
240
+ children: [
241
+ /* @__PURE__ */ jsx("button", {
242
+ type: "button",
243
+ onClick: () => test(s.id),
244
+ className: "rounded-md border px-2 py-1 text-xs hover:bg-accent",
245
+ children: "test"
246
+ }),
247
+ /* @__PURE__ */ jsx("button", {
248
+ type: "button",
249
+ onClick: () => toggle(s),
250
+ className: "rounded-md border px-2 py-1 text-xs hover:bg-accent",
251
+ children: s.enabled ? "disable" : "enable"
252
+ }),
253
+ /* @__PURE__ */ jsx("button", {
254
+ type: "button",
255
+ onClick: () => remove(s.id),
256
+ className: "rounded-md border px-2 py-1 text-xs text-rose-700 hover:bg-rose-50",
257
+ children: "delete"
258
+ })
259
+ ]
260
+ })
261
+ ]
262
+ }, s.id))] })]
263
+ })
264
+ ]
265
+ });
266
+ }
267
+ //#endregion
268
+ export { McpPage as component };
@@ -0,0 +1,12 @@
1
+ import { t as createServerFn } from "../server.js";
2
+ import { t as createServerRpc } from "./createServerRpc-CBTntoKx.js";
3
+ import { n as daemonClient } from "./daemon-client-2NRMzlTr.js";
4
+ //#region src/routes/config/mcp.tsx?tss-serverfn-split
5
+ var fetchServers_createServerFn_handler = createServerRpc({
6
+ id: "278849457893891c3d22806d15e11a0a42cc3630b30e9e62b74cf2d3b982ded7",
7
+ name: "fetchServers",
8
+ filename: "src/routes/config/mcp.tsx"
9
+ }, (opts) => fetchServers.__executeServer(opts));
10
+ var fetchServers = createServerFn({ method: "GET" }).handler(fetchServers_createServerFn_handler, () => daemonClient().get("/api/mcp-servers"));
11
+ //#endregion
12
+ export { fetchServers_createServerFn_handler };
@@ -0,0 +1,284 @@
1
+ import { t as Route } from "./memory-EEgLDfCj.js";
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/routes/groups/$id/memory.tsx?tsr-split=component
5
+ function encodeKey(key) {
6
+ return key.split("/").map(encodeURIComponent).join("/");
7
+ }
8
+ function MemoryPage() {
9
+ const { group, memberCount, entries: initialEntries } = Route.useLoaderData();
10
+ const groupId = group.id;
11
+ const [rows, setRows] = useState(() => initialEntries.map((e) => ({
12
+ key: e.key,
13
+ preview: e.content.slice(0, 80)
14
+ })));
15
+ const [isSearch, setIsSearch] = useState(false);
16
+ const [query, setQuery] = useState("");
17
+ const [selectedKey, setSelectedKey] = useState(null);
18
+ const [mode, setMode] = useState("none");
19
+ const [keyInput, setKeyInput] = useState("");
20
+ const [content, setContent] = useState("");
21
+ const [status, setStatus] = useState(null);
22
+ const searchTimer = useRef(null);
23
+ async function loadList(q) {
24
+ try {
25
+ const url = q.trim().length > 0 ? `/api/groups/${encodeURIComponent(groupId)}/memory/search?q=${encodeURIComponent(q)}&limit=50` : `/api/groups/${encodeURIComponent(groupId)}/memory`;
26
+ const res = await fetch(url);
27
+ if (!res.ok) {
28
+ const body = await res.json().catch(() => null);
29
+ throw new Error(body?.error ?? res.statusText);
30
+ }
31
+ const data = await res.json();
32
+ if (q.trim().length > 0) {
33
+ setRows(data.map((h) => ({
34
+ key: h.key,
35
+ preview: h.snippet,
36
+ score: h.score
37
+ })));
38
+ setIsSearch(true);
39
+ } else {
40
+ setRows(data.map((e) => ({
41
+ key: e.key,
42
+ preview: e.content.slice(0, 80)
43
+ })));
44
+ setIsSearch(false);
45
+ }
46
+ } catch (err) {
47
+ setStatus({
48
+ msg: `error: ${err.message}`,
49
+ kind: "error"
50
+ });
51
+ }
52
+ }
53
+ useEffect(() => {
54
+ if (searchTimer.current) clearTimeout(searchTimer.current);
55
+ searchTimer.current = setTimeout(() => {
56
+ loadList(query);
57
+ }, 200);
58
+ return () => {
59
+ if (searchTimer.current) clearTimeout(searchTimer.current);
60
+ };
61
+ }, [query]);
62
+ async function openEntry(key) {
63
+ setSelectedKey(key);
64
+ setMode("edit");
65
+ setStatus({
66
+ msg: "loading…",
67
+ kind: "info"
68
+ });
69
+ try {
70
+ const res = await fetch(`/api/groups/${encodeURIComponent(groupId)}/memory/${encodeKey(key)}`);
71
+ if (!res.ok) {
72
+ const body = await res.json().catch(() => null);
73
+ throw new Error(body?.error ?? res.statusText);
74
+ }
75
+ const entry = await res.json();
76
+ setKeyInput(entry.key);
77
+ setContent(entry.content ?? "");
78
+ setStatus({
79
+ msg: `loaded ${entry.key}`,
80
+ kind: "info"
81
+ });
82
+ } catch (err) {
83
+ setStatus({
84
+ msg: `error: ${err.message}`,
85
+ kind: "error"
86
+ });
87
+ }
88
+ }
89
+ function newEntry() {
90
+ setSelectedKey(null);
91
+ setMode("new");
92
+ setKeyInput("");
93
+ setContent("");
94
+ setStatus({
95
+ msg: "new entry — type a key and content, then save",
96
+ kind: "info"
97
+ });
98
+ }
99
+ async function save() {
100
+ const key = keyInput.trim();
101
+ if (!key) {
102
+ setStatus({
103
+ msg: "key is required",
104
+ kind: "error"
105
+ });
106
+ return;
107
+ }
108
+ try {
109
+ const res = await fetch(`/api/groups/${encodeURIComponent(groupId)}/memory/${encodeKey(key)}`, {
110
+ method: "PUT",
111
+ headers: { "content-type": "application/json" },
112
+ body: JSON.stringify({ content })
113
+ });
114
+ if (!res.ok) {
115
+ const body = await res.json().catch(() => null);
116
+ throw new Error(body?.error ?? res.statusText);
117
+ }
118
+ setSelectedKey(key);
119
+ setMode("edit");
120
+ setStatus({
121
+ msg: "saved",
122
+ kind: "info"
123
+ });
124
+ await loadList(query);
125
+ } catch (err) {
126
+ setStatus({
127
+ msg: `error: ${err.message}`,
128
+ kind: "error"
129
+ });
130
+ }
131
+ }
132
+ async function del() {
133
+ if (!selectedKey) return;
134
+ if (!confirm(`delete ${selectedKey}?`)) return;
135
+ try {
136
+ const res = await fetch(`/api/groups/${encodeURIComponent(groupId)}/memory/${encodeKey(selectedKey)}`, { method: "DELETE" });
137
+ if (!res.ok && res.status !== 204) {
138
+ const body = await res.json().catch(() => null);
139
+ throw new Error(body?.error ?? res.statusText);
140
+ }
141
+ setSelectedKey(null);
142
+ setMode("none");
143
+ setKeyInput("");
144
+ setContent("");
145
+ setStatus({
146
+ msg: "deleted",
147
+ kind: "info"
148
+ });
149
+ await loadList(query);
150
+ } catch (err) {
151
+ setStatus({
152
+ msg: `error: ${err.message}`,
153
+ kind: "error"
154
+ });
155
+ }
156
+ }
157
+ const canSave = mode !== "none" && keyInput.trim().length > 0;
158
+ const canDelete = mode === "edit" && selectedKey !== null;
159
+ return /* @__PURE__ */ jsxs("main", {
160
+ className: "mx-auto max-w-5xl px-6 py-8",
161
+ children: [/* @__PURE__ */ jsxs("header", {
162
+ className: "mb-6",
163
+ children: [/* @__PURE__ */ jsxs("h1", {
164
+ className: "font-serif text-3xl text-foreground",
165
+ children: [
166
+ group.name,
167
+ " ",
168
+ /* @__PURE__ */ jsx("span", {
169
+ className: "text-muted-foreground text-base",
170
+ children: "/ shared memory"
171
+ })
172
+ ]
173
+ }), /* @__PURE__ */ jsxs("p", {
174
+ className: "text-muted-foreground text-sm mt-1",
175
+ children: [
176
+ "BM25-indexed markdown notes shared by every agent in",
177
+ " ",
178
+ /* @__PURE__ */ jsx("a", {
179
+ href: `/groups/${encodeURIComponent(group.id)}`,
180
+ className: "font-mono underline",
181
+ children: group.id
182
+ }),
183
+ " ",
184
+ "(",
185
+ memberCount,
186
+ " member",
187
+ memberCount === 1 ? "" : "s",
188
+ "). Anything written here is visible to every member; per-agent notes belong in the agent's own",
189
+ " ",
190
+ /* @__PURE__ */ jsx("code", {
191
+ className: "font-mono",
192
+ children: "IDENTITY.md"
193
+ }),
194
+ " via ",
195
+ /* @__PURE__ */ jsx("code", { children: "home_write" }),
196
+ "."
197
+ ]
198
+ })]
199
+ }), /* @__PURE__ */ jsxs("div", {
200
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-[320px_1fr]",
201
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
202
+ className: "overflow-hidden rounded-[16px] border border-frost bg-snow",
203
+ children: [/* @__PURE__ */ jsx("div", {
204
+ className: "border-b border-frost p-2",
205
+ children: /* @__PURE__ */ jsx("input", {
206
+ type: "text",
207
+ placeholder: "search (BM25)...",
208
+ autoComplete: "off",
209
+ value: query,
210
+ onChange: (e) => setQuery(e.target.value)
211
+ })
212
+ }), /* @__PURE__ */ jsx("div", {
213
+ className: "max-h-[520px] overflow-y-auto",
214
+ children: rows.length === 0 ? /* @__PURE__ */ jsx("div", {
215
+ className: "p-8 text-center text-mocha-light",
216
+ children: "no entries"
217
+ }) : rows.map((r) => {
218
+ return /* @__PURE__ */ jsxs("button", {
219
+ type: "button",
220
+ onClick: () => openEntry(r.key),
221
+ className: `unstyled block w-full cursor-pointer border-b border-frost/50 px-3.5 py-2 text-left font-mono text-[0.84em] transition-colors last:border-b-0 hover:bg-sapphire-glow ${r.key === selectedKey ? "bg-sapphire-glow font-medium text-sapphire-deep" : ""}`,
222
+ children: [
223
+ isSearch && r.score !== void 0 && /* @__PURE__ */ jsx("span", {
224
+ className: "float-right text-[0.75em] text-sapphire",
225
+ children: r.score.toFixed(2)
226
+ }),
227
+ r.key,
228
+ r.preview && /* @__PURE__ */ jsx("span", {
229
+ className: "mt-1 block text-[0.9em] font-normal text-mocha-light",
230
+ children: r.preview
231
+ })
232
+ ]
233
+ }, r.key);
234
+ })
235
+ })]
236
+ }), /* @__PURE__ */ jsx("button", {
237
+ type: "button",
238
+ className: "ghost-btn mt-3 w-full",
239
+ onClick: newEntry,
240
+ children: "+ new entry"
241
+ })] }), /* @__PURE__ */ jsxs("div", { children: [
242
+ /* @__PURE__ */ jsx("div", {
243
+ className: "mb-3 flex items-center gap-2",
244
+ children: /* @__PURE__ */ jsx("input", {
245
+ type: "text",
246
+ placeholder: "key (e.g. prefs/hiking.md)",
247
+ value: keyInput,
248
+ onChange: (e) => setKeyInput(e.target.value),
249
+ disabled: mode !== "new",
250
+ className: "flex-1 font-mono"
251
+ })
252
+ }),
253
+ /* @__PURE__ */ jsx("textarea", {
254
+ placeholder: "select an entry on the left, or create a new one.",
255
+ value: content,
256
+ onChange: (e) => setContent(e.target.value),
257
+ className: "min-h-[360px] w-full font-mono text-[0.9em] leading-[1.55]"
258
+ }),
259
+ /* @__PURE__ */ jsxs("div", {
260
+ className: "mt-3 flex gap-2",
261
+ children: [/* @__PURE__ */ jsx("button", {
262
+ type: "button",
263
+ className: "btn-primary",
264
+ onClick: save,
265
+ disabled: !canSave,
266
+ children: "save"
267
+ }), /* @__PURE__ */ jsx("button", {
268
+ type: "button",
269
+ className: "ghost-btn",
270
+ onClick: del,
271
+ disabled: !canDelete,
272
+ children: "delete"
273
+ })]
274
+ }),
275
+ status && /* @__PURE__ */ jsx("p", {
276
+ className: `mt-2 text-[0.9em] ${status.kind === "error" ? "text-[#9B3D3D]" : "text-mocha-light"}`,
277
+ children: status.msg
278
+ })
279
+ ] })]
280
+ })]
281
+ });
282
+ }
283
+ //#endregion
284
+ export { MemoryPage as component };
@@ -0,0 +1,28 @@
1
+ import { t as createServerFn } from "../server.js";
2
+ import { t as createServerRpc } from "./createServerRpc-CBTntoKx.js";
3
+ import { n as daemonClient, r as ApiClientError } from "./daemon-client-2NRMzlTr.js";
4
+ //#region src/routes/groups/$id/memory.tsx?tss-serverfn-split
5
+ var fetchMemory_createServerFn_handler = createServerRpc({
6
+ id: "457cdd4932d22a1e823c50781026fbabb2e9d4d6b5ac9a763bb74500f2b02538",
7
+ name: "fetchMemory",
8
+ filename: "src/routes/groups/$id/memory.tsx"
9
+ }, (opts) => fetchMemory.__executeServer(opts));
10
+ var fetchMemory = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(fetchMemory_createServerFn_handler, async ({ data }) => {
11
+ const c = daemonClient();
12
+ let group;
13
+ try {
14
+ group = await c.get(`/api/groups/${encodeURIComponent(data.id)}`);
15
+ } catch (err) {
16
+ if (err instanceof ApiClientError && err.status === 404) return null;
17
+ throw err;
18
+ }
19
+ const [entries, agents] = await Promise.all([c.get(`/api/groups/${encodeURIComponent(group.id)}/memory`), c.get("/api/agents?includeArchived=true")]);
20
+ const memberCount = agents.filter((a) => a.groupId === group.id).length;
21
+ return {
22
+ group,
23
+ memberCount,
24
+ entries
25
+ };
26
+ });
27
+ //#endregion
28
+ export { fetchMemory_createServerFn_handler };
@@ -0,0 +1,16 @@
1
+ import { t as createServerFn } from "../server.js";
2
+ import { t as createSsrRpc } from "./createSsrRpc-DHBVUN8O.js";
3
+ import { createFileRoute, lazyRouteComponent, redirect } from "@tanstack/react-router";
4
+ //#region src/routes/groups/$id/memory.tsx
5
+ var $$splitComponentImporter = () => import("./memory-BfrMp8iY.js");
6
+ var fetchMemory = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(createSsrRpc("457cdd4932d22a1e823c50781026fbabb2e9d4d6b5ac9a763bb74500f2b02538"));
7
+ var Route = createFileRoute("/groups/$id/memory")({
8
+ loader: async ({ params }) => {
9
+ const data = await fetchMemory({ data: { id: params.id } });
10
+ if (!data) throw redirect({ to: "/groups" });
11
+ return data;
12
+ },
13
+ component: lazyRouteComponent($$splitComponentImporter, "component")
14
+ });
15
+ //#endregion
16
+ export { Route as t };
@@ -0,0 +1,12 @@
1
+ import { t as createServerFn } from "../server.js";
2
+ import { t as createSsrRpc } from "./createSsrRpc-DHBVUN8O.js";
3
+ import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
4
+ //#region src/routes/profile-groups/index.tsx
5
+ var $$splitComponentImporter = () => import("./profile-groups-B_kIT6BU.js");
6
+ var fetchProfileGroupsData = createServerFn({ method: "GET" }).handler(createSsrRpc("be2ab9d2d20bd46baa655e08a8f6f0c2161b01657d0362564a58edeaf2195a31"));
7
+ var Route = createFileRoute("/profile-groups/")({
8
+ loader: () => fetchProfileGroupsData(),
9
+ component: lazyRouteComponent($$splitComponentImporter, "component")
10
+ });
11
+ //#endregion
12
+ export { Route as t };