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,367 @@
1
+ import { t as Route } from "./_id-BZ-YCWSw.js";
2
+ import { t as Button } from "./Button-Dsnw22OF.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/groups/$id/index.tsx?tsr-split=component
7
+ function GroupDetailPage() {
8
+ const { group, members, profileGroups } = Route.useLoaderData();
9
+ const router = useRouter();
10
+ const [userMd, setUserMd] = useState(group.userMd);
11
+ const [busy, setBusy] = useState(false);
12
+ const [err, setErr] = useState(null);
13
+ const [savedAt, setSavedAt] = useState(null);
14
+ async function save() {
15
+ setBusy(true);
16
+ setErr(null);
17
+ try {
18
+ const res = await fetch(`/api/groups/${encodeURIComponent(group.id)}/user-md`, {
19
+ method: "PUT",
20
+ headers: { "content-type": "application/json" },
21
+ body: JSON.stringify({ userMd })
22
+ });
23
+ if (!res.ok) {
24
+ const e = await res.json().catch(() => ({}));
25
+ throw new Error(e.error ?? `${res.status} ${res.statusText}`);
26
+ }
27
+ setSavedAt(Date.now());
28
+ await router.invalidate();
29
+ } catch (e) {
30
+ setErr(e.message);
31
+ } finally {
32
+ setBusy(false);
33
+ }
34
+ }
35
+ return /* @__PURE__ */ jsxs("main", {
36
+ className: "mx-auto max-w-3xl px-6 py-8",
37
+ children: [
38
+ /* @__PURE__ */ jsxs("h1", {
39
+ className: "font-serif text-3xl text-foreground",
40
+ children: [
41
+ group.name,
42
+ " ",
43
+ /* @__PURE__ */ jsxs("span", {
44
+ className: "text-muted-foreground text-base",
45
+ children: [
46
+ "(",
47
+ group.id,
48
+ ")"
49
+ ]
50
+ })
51
+ ]
52
+ }),
53
+ /* @__PURE__ */ jsxs("p", {
54
+ className: "text-muted-foreground text-sm mb-6 mt-1",
55
+ children: [
56
+ /* @__PURE__ */ jsx("code", {
57
+ className: "font-mono",
58
+ children: group.path
59
+ }),
60
+ " · ",
61
+ members.length,
62
+ " ",
63
+ "member",
64
+ members.length === 1 ? "" : "s",
65
+ " ·",
66
+ " ",
67
+ /* @__PURE__ */ jsx("a", {
68
+ href: `/groups/${encodeURIComponent(group.id)}/memory`,
69
+ className: "text-primary underline",
70
+ children: "shared memory →"
71
+ })
72
+ ]
73
+ }),
74
+ /* @__PURE__ */ jsxs("section", {
75
+ className: "rounded-lg border bg-card p-5 mb-6",
76
+ children: [
77
+ /* @__PURE__ */ jsx("h3", {
78
+ className: "font-serif text-xl mb-1",
79
+ children: "USER.md"
80
+ }),
81
+ /* @__PURE__ */ jsx("p", {
82
+ className: "text-muted-foreground text-sm mb-3",
83
+ children: "Read-only context about the human, injected into every member agent's system prompt. 12 KB cap. Agents cannot edit this file — only you can."
84
+ }),
85
+ /* @__PURE__ */ jsx("textarea", {
86
+ value: userMd,
87
+ onChange: (e) => setUserMd(e.target.value),
88
+ rows: 16,
89
+ className: "w-full rounded-md border bg-background px-3 py-2 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30",
90
+ placeholder: "What the agent should know about you in this group context…"
91
+ }),
92
+ /* @__PURE__ */ jsxs("div", {
93
+ className: "flex items-center gap-3 mt-3",
94
+ children: [
95
+ /* @__PURE__ */ jsx(Button, {
96
+ variant: "primary",
97
+ onClick: save,
98
+ disabled: busy || userMd === group.userMd,
99
+ children: busy ? "saving…" : "save"
100
+ }),
101
+ /* @__PURE__ */ jsxs("span", {
102
+ className: "text-xs text-muted-foreground",
103
+ children: [userMd.length, " / 12000 chars"]
104
+ }),
105
+ savedAt && /* @__PURE__ */ jsx("span", {
106
+ className: "text-xs text-emerald-700",
107
+ children: "✓ saved"
108
+ }),
109
+ err && /* @__PURE__ */ jsx("span", {
110
+ className: "text-xs text-rose-700",
111
+ children: err
112
+ })
113
+ ]
114
+ })
115
+ ]
116
+ }),
117
+ /* @__PURE__ */ jsx(TopicNameFormatCard, {
118
+ group,
119
+ sampleAgent: members[0]?.name ?? "researcher",
120
+ onSaved: () => router.invalidate()
121
+ }),
122
+ members.length === 0 && /* @__PURE__ */ jsx(SpawnFromTemplateCard, {
123
+ groupId: group.id,
124
+ profileGroups,
125
+ onSpawned: () => router.invalidate()
126
+ }),
127
+ /* @__PURE__ */ jsxs("section", {
128
+ className: "rounded-lg border bg-card p-5",
129
+ children: [/* @__PURE__ */ jsx("h3", {
130
+ className: "font-serif text-xl mb-3",
131
+ children: "members"
132
+ }), members.length === 0 ? /* @__PURE__ */ jsx("p", {
133
+ className: "text-muted-foreground text-sm",
134
+ children: "No agents in this group yet."
135
+ }) : /* @__PURE__ */ jsxs("table", {
136
+ className: "w-full text-sm",
137
+ children: [/* @__PURE__ */ jsx("thead", {
138
+ className: "text-left text-muted-foreground border-b",
139
+ children: /* @__PURE__ */ jsxs("tr", { children: [
140
+ /* @__PURE__ */ jsx("th", {
141
+ className: "py-2",
142
+ children: "name"
143
+ }),
144
+ /* @__PURE__ */ jsx("th", { children: "status" }),
145
+ /* @__PURE__ */ jsx("th", { children: "profile" }),
146
+ /* @__PURE__ */ jsx("th", {})
147
+ ] })
148
+ }), /* @__PURE__ */ jsx("tbody", { children: members.map((m) => /* @__PURE__ */ jsxs("tr", {
149
+ className: "border-b last:border-0",
150
+ children: [
151
+ /* @__PURE__ */ jsx("td", {
152
+ className: "py-2",
153
+ children: /* @__PURE__ */ jsx("a", {
154
+ href: `/agents/${m.id}`,
155
+ className: "text-primary underline",
156
+ children: m.name
157
+ })
158
+ }),
159
+ /* @__PURE__ */ jsx("td", { children: m.status }),
160
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("code", {
161
+ className: "font-mono text-xs",
162
+ children: m.profileId
163
+ }) }),
164
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("code", {
165
+ className: "font-mono text-xs text-muted-foreground",
166
+ children: [m.id.slice(0, 8), "…"]
167
+ }) })
168
+ ]
169
+ }, m.id)) })]
170
+ })]
171
+ })
172
+ ]
173
+ });
174
+ }
175
+ function TopicNameFormatCard({ group, sampleAgent, onSaved }) {
176
+ const [format, setFormat] = useState(group.telegramTopicNameFormat ?? "");
177
+ const [busy, setBusy] = useState(false);
178
+ const [err, setErr] = useState(null);
179
+ const [savedAt, setSavedAt] = useState(null);
180
+ const trimmed = format.trim();
181
+ const preview = trimmed ? trimmed.replaceAll("{agent.name}", sampleAgent).replaceAll("{group.name}", group.name).replaceAll("{group.slug}", group.id) : group.id === "default" ? sampleAgent : `${group.id} › ${sampleAgent}`;
182
+ const dirty = (group.telegramTopicNameFormat ?? "") !== format;
183
+ async function save(clear) {
184
+ setBusy(true);
185
+ setErr(null);
186
+ try {
187
+ const res = await fetch(`/api/groups/${encodeURIComponent(group.id)}/topic-format`, {
188
+ method: "PUT",
189
+ headers: { "content-type": "application/json" },
190
+ body: JSON.stringify({ format: clear ? null : format })
191
+ });
192
+ if (!res.ok) {
193
+ const e = await res.json().catch(() => ({}));
194
+ throw new Error(e.error ?? `${res.status} ${res.statusText}`);
195
+ }
196
+ if (clear) setFormat("");
197
+ setSavedAt(Date.now());
198
+ onSaved();
199
+ } catch (e) {
200
+ setErr(e.message);
201
+ } finally {
202
+ setBusy(false);
203
+ }
204
+ }
205
+ return /* @__PURE__ */ jsxs("section", {
206
+ className: "rounded-lg border bg-card p-5 mb-6",
207
+ children: [
208
+ /* @__PURE__ */ jsx("h3", {
209
+ className: "font-serif text-xl mb-1",
210
+ children: "Telegram topic names"
211
+ }),
212
+ /* @__PURE__ */ jsxs("p", {
213
+ className: "text-muted-foreground text-sm mb-3",
214
+ children: [
215
+ "Template for this group's Telegram forum-topic titles. Leave empty for built-in naming. Tokens: ",
216
+ /* @__PURE__ */ jsx("code", {
217
+ className: "font-mono",
218
+ children: "{agent.name}"
219
+ }),
220
+ " ",
221
+ /* @__PURE__ */ jsx("code", {
222
+ className: "font-mono",
223
+ children: "{group.name}"
224
+ }),
225
+ " ",
226
+ /* @__PURE__ */ jsx("code", {
227
+ className: "font-mono",
228
+ children: "{group.slug}"
229
+ }),
230
+ " — must include",
231
+ " ",
232
+ /* @__PURE__ */ jsx("code", {
233
+ className: "font-mono",
234
+ children: "{agent.name}"
235
+ }),
236
+ ". Saving renames existing topics that you haven't manually renamed in Telegram."
237
+ ]
238
+ }),
239
+ /* @__PURE__ */ jsx("input", {
240
+ value: format,
241
+ onChange: (e) => setFormat(e.target.value),
242
+ placeholder: "{group.name} / {agent.name}",
243
+ className: "w-full rounded-md border bg-background px-3 py-2 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30"
244
+ }),
245
+ /* @__PURE__ */ jsxs("p", {
246
+ className: "text-xs text-muted-foreground mt-2",
247
+ children: ["preview: ", /* @__PURE__ */ jsx("span", {
248
+ className: "font-mono text-foreground",
249
+ children: preview
250
+ })]
251
+ }),
252
+ /* @__PURE__ */ jsxs("div", {
253
+ className: "flex items-center gap-3 mt-3",
254
+ children: [
255
+ /* @__PURE__ */ jsx(Button, {
256
+ variant: "primary",
257
+ onClick: () => save(false),
258
+ disabled: busy || !dirty || trimmed.length === 0,
259
+ children: busy ? "saving…" : "save"
260
+ }),
261
+ group.telegramTopicNameFormat && /* @__PURE__ */ jsx(Button, {
262
+ variant: "ghost",
263
+ onClick: () => save(true),
264
+ disabled: busy,
265
+ children: "clear"
266
+ }),
267
+ savedAt && /* @__PURE__ */ jsx("span", {
268
+ className: "text-xs text-emerald-700",
269
+ children: "✓ saved"
270
+ }),
271
+ err && /* @__PURE__ */ jsx("span", {
272
+ className: "text-xs text-rose-700",
273
+ children: err
274
+ })
275
+ ]
276
+ })
277
+ ]
278
+ });
279
+ }
280
+ function SpawnFromTemplateCard({ groupId, profileGroups, onSpawned }) {
281
+ const eligible = profileGroups.filter((g) => g.memberCount > 0);
282
+ const [selected, setSelected] = useState(eligible[0]?.id ?? "");
283
+ const [busy, setBusy] = useState(false);
284
+ const [err, setErr] = useState(null);
285
+ async function spawn() {
286
+ if (!selected) return;
287
+ setBusy(true);
288
+ setErr(null);
289
+ try {
290
+ const res = await fetch(`/api/profile-groups/${encodeURIComponent(selected)}/spawn`, {
291
+ method: "POST",
292
+ headers: { "content-type": "application/json" },
293
+ body: JSON.stringify({ groupSlug: groupId })
294
+ });
295
+ if (!res.ok) {
296
+ const e = await res.json().catch(() => ({}));
297
+ throw new Error(e.error ?? `${res.status} ${res.statusText}`);
298
+ }
299
+ const result = await res.json();
300
+ if (result.orphanAgentIds && result.orphanAgentIds.length > 0) alert(`Spawn completed with warnings: ${result.orphanAgentIds.length} orphan agent dir(s) left on disk.`);
301
+ onSpawned();
302
+ } catch (e) {
303
+ setErr(e.message);
304
+ } finally {
305
+ setBusy(false);
306
+ }
307
+ }
308
+ return /* @__PURE__ */ jsxs("section", {
309
+ className: "rounded-lg border bg-card p-5 mb-6",
310
+ children: [
311
+ /* @__PURE__ */ jsx("h3", {
312
+ className: "font-serif text-xl mb-1",
313
+ children: "spawn a team into this group"
314
+ }),
315
+ /* @__PURE__ */ jsx("p", {
316
+ className: "text-muted-foreground text-sm mb-3",
317
+ children: "This group is empty. Pick a profile group template to spawn its entire roster into it in one transactional call."
318
+ }),
319
+ eligible.length === 0 ? /* @__PURE__ */ jsxs("p", {
320
+ className: "text-muted-foreground text-sm",
321
+ children: [
322
+ "No profile groups with members yet. Build one on",
323
+ " ",
324
+ /* @__PURE__ */ jsx("a", {
325
+ href: "/profile-groups",
326
+ className: "text-primary underline",
327
+ children: "/profile-groups"
328
+ }),
329
+ " ",
330
+ "first."
331
+ ]
332
+ }) : /* @__PURE__ */ jsxs("div", {
333
+ className: "flex items-center gap-3",
334
+ children: [
335
+ /* @__PURE__ */ jsx("select", {
336
+ value: selected,
337
+ onChange: (e) => setSelected(e.target.value),
338
+ className: "rounded-md border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-ring/30",
339
+ children: eligible.map((g) => /* @__PURE__ */ jsxs("option", {
340
+ value: g.id,
341
+ children: [
342
+ g.name,
343
+ " (",
344
+ g.memberCount,
345
+ " member",
346
+ g.memberCount === 1 ? "" : "s",
347
+ ")"
348
+ ]
349
+ }, g.id))
350
+ }),
351
+ /* @__PURE__ */ jsx(Button, {
352
+ variant: "primary",
353
+ onClick: spawn,
354
+ disabled: busy || !selected,
355
+ children: busy ? "spawning…" : "spawn team"
356
+ }),
357
+ err && /* @__PURE__ */ jsx("span", {
358
+ className: "text-xs text-rose-700",
359
+ children: err
360
+ })
361
+ ]
362
+ })
363
+ ]
364
+ });
365
+ }
366
+ //#endregion
367
+ export { GroupDetailPage as component };
@@ -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/$id.tsx
5
+ var $$splitComponentImporter = () => import("./_id-CHNm7EAd.js");
6
+ var fetchDetail = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(createSsrRpc("86dad0c33c97a6f0913d1f38e9b01ac4144f7d0970b45fdb3470e9bc9a78e0e0"));
7
+ var Route = createFileRoute("/profile-groups/$id")({
8
+ loader: ({ params }) => fetchDetail({ data: { id: params.id } }),
9
+ component: lazyRouteComponent($$splitComponentImporter, "component")
10
+ });
11
+ //#endregion
12
+ export { Route as t };
@@ -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/index.tsx?tss-serverfn-split
5
+ var fetchGroup_createServerFn_handler = createServerRpc({
6
+ id: "c64d52cbb25600424729185370431bf1182e1058dad2eacd250820ca1d62dae0",
7
+ name: "fetchGroup",
8
+ filename: "src/routes/groups/$id/index.tsx"
9
+ }, (opts) => fetchGroup.__executeServer(opts));
10
+ var fetchGroup = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(fetchGroup_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 [all, profileGroups] = await Promise.all([c.get("/api/agents?includeArchived=true"), c.get("/api/profile-groups")]);
20
+ const members = all.filter((a) => a.groupId === group.id);
21
+ return {
22
+ group,
23
+ members,
24
+ profileGroups
25
+ };
26
+ });
27
+ //#endregion
28
+ export { fetchGroup_createServerFn_handler };
@@ -0,0 +1,161 @@
1
+ import { t as Route } from "./_id-C78M9_j9.js";
2
+ import { t as Button } from "./Button-Dsnw22OF.js";
3
+ import { t as MembersEditor } from "./MembersEditor-BWQztvrX.js";
4
+ import { useState } from "react";
5
+ import { useRouter } from "@tanstack/react-router";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/routes/profile-groups/$id.tsx?tsr-split=component
8
+ function toDraft(m) {
9
+ return {
10
+ profileId: m.profileId,
11
+ agentName: m.agentName,
12
+ modelOverride: m.modelOverride,
13
+ reasoningLevel: m.reasoningLevel
14
+ };
15
+ }
16
+ function ProfileGroupDetailPage() {
17
+ const { detail, profiles, modelGroups } = Route.useLoaderData();
18
+ const router = useRouter();
19
+ const { group } = detail;
20
+ return /* @__PURE__ */ jsxs("div", { children: [
21
+ /* @__PURE__ */ jsx("h1", { children: group.name }),
22
+ /* @__PURE__ */ jsxs("p", {
23
+ className: "muted",
24
+ children: [
25
+ /* @__PURE__ */ jsx("code", { children: group.id }),
26
+ " · ",
27
+ detail.members.length,
28
+ " member",
29
+ detail.members.length === 1 ? "" : "s"
30
+ ]
31
+ }),
32
+ /* @__PURE__ */ jsx(BasicsCard, {
33
+ group,
34
+ onSaved: () => router.invalidate()
35
+ }),
36
+ /* @__PURE__ */ jsx(MembersCard, {
37
+ groupId: group.id,
38
+ initialMembers: detail.members.map(toDraft),
39
+ profiles,
40
+ modelGroups,
41
+ onSaved: () => router.invalidate()
42
+ })
43
+ ] });
44
+ }
45
+ function BasicsCard({ group, onSaved }) {
46
+ const [name, setName] = useState(group.name);
47
+ const [userMd, setUserMd] = useState(group.userMd ?? "");
48
+ const [err, setErr] = useState(null);
49
+ const [saving, setSaving] = useState(false);
50
+ async function save() {
51
+ setErr(null);
52
+ setSaving(true);
53
+ try {
54
+ const body = { name };
55
+ body.userMd = userMd === "" ? null : userMd;
56
+ const res = await fetch(`/api/profile-groups/${group.id}`, {
57
+ method: "PATCH",
58
+ headers: { "content-type": "application/json" },
59
+ body: JSON.stringify(body)
60
+ });
61
+ if (!res.ok) {
62
+ const e = await res.json().catch(() => null);
63
+ throw new Error(e?.error ?? res.statusText);
64
+ }
65
+ onSaved();
66
+ } catch (e) {
67
+ setErr(e.message);
68
+ } finally {
69
+ setSaving(false);
70
+ }
71
+ }
72
+ return /* @__PURE__ */ jsxs("div", {
73
+ className: "card",
74
+ children: [
75
+ /* @__PURE__ */ jsx("h3", { children: "basics" }),
76
+ err && /* @__PURE__ */ jsx("div", {
77
+ className: "err",
78
+ children: err
79
+ }),
80
+ /* @__PURE__ */ jsxs("label", { children: ["name", /* @__PURE__ */ jsx("input", {
81
+ value: name,
82
+ onChange: (e) => setName(e.target.value)
83
+ })] }),
84
+ /* @__PURE__ */ jsxs("label", { children: ["starter USER.md (seeded only into freshly-created target groups)", /* @__PURE__ */ jsx("textarea", {
85
+ rows: 6,
86
+ value: userMd,
87
+ onChange: (e) => setUserMd(e.target.value),
88
+ className: "font-mono text-[0.88em] leading-[1.55]"
89
+ })] }),
90
+ /* @__PURE__ */ jsx(Button, {
91
+ variant: "primary",
92
+ onClick: save,
93
+ disabled: saving,
94
+ children: saving ? "saving…" : "save basics"
95
+ })
96
+ ]
97
+ });
98
+ }
99
+ function MembersCard({ groupId, initialMembers, profiles, modelGroups, onSaved }) {
100
+ const [members, setMembers] = useState(initialMembers);
101
+ const [err, setErr] = useState(null);
102
+ const [saving, setSaving] = useState(false);
103
+ const dirty = JSON.stringify(members) !== JSON.stringify(initialMembers);
104
+ async function save() {
105
+ setErr(null);
106
+ setSaving(true);
107
+ try {
108
+ const res = await fetch(`/api/profile-groups/${groupId}/members`, {
109
+ method: "PUT",
110
+ headers: { "content-type": "application/json" },
111
+ body: JSON.stringify({ members })
112
+ });
113
+ if (!res.ok) {
114
+ const e = await res.json().catch(() => null);
115
+ throw new Error(e?.error ?? res.statusText);
116
+ }
117
+ onSaved();
118
+ } catch (e) {
119
+ setErr(e.message);
120
+ } finally {
121
+ setSaving(false);
122
+ }
123
+ }
124
+ return /* @__PURE__ */ jsxs("div", {
125
+ className: "card",
126
+ children: [
127
+ /* @__PURE__ */ jsx("h3", { children: "members" }),
128
+ err && /* @__PURE__ */ jsx("div", {
129
+ className: "err",
130
+ children: err
131
+ }),
132
+ /* @__PURE__ */ jsxs("p", {
133
+ className: "muted",
134
+ children: [
135
+ "Each member becomes one agent at spawn time. Duplicate agent-names within a template are fine — the spawn op auto-suffixes collisions with ",
136
+ /* @__PURE__ */ jsx("code", { children: "-2" }),
137
+ ", ",
138
+ /* @__PURE__ */ jsx("code", { children: "-3" }),
139
+ ", …"
140
+ ]
141
+ }),
142
+ /* @__PURE__ */ jsx(MembersEditor, {
143
+ members,
144
+ onChange: setMembers,
145
+ profiles,
146
+ modelGroups
147
+ }),
148
+ /* @__PURE__ */ jsx("div", {
149
+ className: "mt-3",
150
+ children: /* @__PURE__ */ jsx(Button, {
151
+ variant: "primary",
152
+ onClick: save,
153
+ disabled: saving || !dirty,
154
+ children: saving ? "saving…" : "save members"
155
+ })
156
+ })
157
+ ]
158
+ });
159
+ }
160
+ //#endregion
161
+ export { ProfileGroupDetailPage as component };
@@ -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/profiles/$id.tsx
5
+ var $$splitComponentImporter = () => import("./_id-pd4S7LTi.js");
6
+ var fetchProfile = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(createSsrRpc("280ae44073f538bf230afd3a1407fc41f9c78cd0cf71b6a06fb0cceff0872d1c"));
7
+ var Route = createFileRoute("/profiles/$id")({
8
+ loader: async ({ params }) => {
9
+ const data = await fetchProfile({ data: { id: params.id } });
10
+ if (!data) throw redirect({ to: "/profiles" });
11
+ return data;
12
+ },
13
+ component: lazyRouteComponent($$splitComponentImporter, "component")
14
+ });
15
+ //#endregion
16
+ export { Route as t };
@@ -0,0 +1,38 @@
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/agents/$id/index.tsx?tss-serverfn-split
5
+ var fetchAgent_createServerFn_handler = createServerRpc({
6
+ id: "846c9081aed17057351730985f133b0aab67a5dabfca9562552829a90ff30849",
7
+ name: "fetchAgent",
8
+ filename: "src/routes/agents/$id/index.tsx"
9
+ }, (opts) => fetchAgent.__executeServer(opts));
10
+ var fetchAgent = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(fetchAgent_createServerFn_handler, async ({ data }) => {
11
+ const c = daemonClient();
12
+ let resolved;
13
+ try {
14
+ resolved = await c.get(`/api/agents/${encodeURIComponent(data.id)}`);
15
+ } catch (err) {
16
+ if (err instanceof ApiClientError && err.status === 404) return null;
17
+ throw err;
18
+ }
19
+ const [msgs, head, groups, skills, models, telegramConfig] = await Promise.all([
20
+ c.get(`/api/agents/${encodeURIComponent(resolved.agent.id)}/sessions/messages`),
21
+ c.get(`/api/agents/${encodeURIComponent(resolved.agent.id)}/sessions/head`),
22
+ c.get("/api/groups"),
23
+ c.get("/api/skills"),
24
+ c.get("/api/config/available-models"),
25
+ c.get("/api/config/telegram").catch(() => ({ configured: false }))
26
+ ]);
27
+ return {
28
+ resolved,
29
+ initialMessages: msgs.messages,
30
+ sessionHead: head,
31
+ groups,
32
+ skills,
33
+ modelGroups: models.groups,
34
+ telegramConfigured: telegramConfig.configured
35
+ };
36
+ });
37
+ //#endregion
38
+ export { fetchAgent_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/agents/$id/index.tsx
5
+ var $$splitComponentImporter = () => import("./_id-GJk3EYTT.js");
6
+ var fetchAgent = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(createSsrRpc("846c9081aed17057351730985f133b0aab67a5dabfca9562552829a90ff30849"));
7
+ var Route = createFileRoute("/agents/$id/")({
8
+ loader: async ({ params }) => {
9
+ const data = await fetchAgent({ data: { id: params.id } });
10
+ if (!data) throw redirect({ to: "/agents" });
11
+ return data;
12
+ },
13
+ component: lazyRouteComponent($$splitComponentImporter, "component")
14
+ });
15
+ //#endregion
16
+ export { Route as t };
@@ -0,0 +1,27 @@
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/profiles/$id.tsx?tss-serverfn-split
5
+ var fetchProfile_createServerFn_handler = createServerRpc({
6
+ id: "280ae44073f538bf230afd3a1407fc41f9c78cd0cf71b6a06fb0cceff0872d1c",
7
+ name: "fetchProfile",
8
+ filename: "src/routes/profiles/$id.tsx"
9
+ }, (opts) => fetchProfile.__executeServer(opts));
10
+ var fetchProfile = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(fetchProfile_createServerFn_handler, async ({ data }) => {
11
+ const c = daemonClient();
12
+ let loaded;
13
+ try {
14
+ loaded = await c.get(`/api/profiles/${encodeURIComponent(data.id)}`);
15
+ } catch (err) {
16
+ if (err instanceof ApiClientError && err.status === 404) return null;
17
+ throw err;
18
+ }
19
+ const [models, skills] = await Promise.all([c.get("/api/config/available-models"), c.get("/api/skills")]);
20
+ return {
21
+ loaded,
22
+ modelGroups: models.groups,
23
+ skills
24
+ };
25
+ });
26
+ //#endregion
27
+ export { fetchProfile_createServerFn_handler };