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,210 @@
1
+ import { t as Route } from "./agents-K4Smhnq3.js";
2
+ import { t as AgentAvatar } from "./AgentAvatar-8gTAy_tP.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/agents/index.tsx?tsr-split=component
7
+ function AgentsPage() {
8
+ const { agents, profiles, groups, modelGroups } = Route.useLoaderData();
9
+ const { all } = Route.useSearch();
10
+ const showAll = all === "1";
11
+ const router = useRouter();
12
+ async function archive(id) {
13
+ if (!confirm("archive this agent? (reversible)")) return;
14
+ await fetch(`/api/agents/${id}/archive`, { method: "POST" });
15
+ await router.invalidate();
16
+ }
17
+ async function unarchive(id) {
18
+ await fetch(`/api/agents/${id}/unarchive`, { method: "POST" });
19
+ await router.invalidate();
20
+ }
21
+ async function del(id) {
22
+ if (!confirm("permanently delete this agent and all its data?")) return;
23
+ await fetch(`/api/agents/${id}`, { method: "DELETE" });
24
+ await router.invalidate();
25
+ }
26
+ return /* @__PURE__ */ jsxs("div", { children: [
27
+ /* @__PURE__ */ jsx("h1", { children: "agents" }),
28
+ /* @__PURE__ */ jsx(SpawnForm, {
29
+ profiles,
30
+ groups,
31
+ modelGroups,
32
+ onSpawned: router.invalidate
33
+ }),
34
+ /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("a", {
35
+ href: showAll ? "/agents" : "/agents?all=1",
36
+ children: showAll ? "hide archived" : "show archived"
37
+ }) }),
38
+ /* @__PURE__ */ jsxs("table", { children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
39
+ /* @__PURE__ */ jsx("th", { children: "id" }),
40
+ /* @__PURE__ */ jsx("th", { children: "name" }),
41
+ /* @__PURE__ */ jsx("th", { children: "profile" }),
42
+ /* @__PURE__ */ jsx("th", { children: "status" }),
43
+ /* @__PURE__ */ jsx("th", {})
44
+ ] }) }), /* @__PURE__ */ jsxs("tbody", { children: [agents.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
45
+ colSpan: 5,
46
+ className: "muted",
47
+ children: "no agents yet"
48
+ }) }), agents.map((a) => /* @__PURE__ */ jsxs("tr", { children: [
49
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("a", {
50
+ href: `/agents/${a.id}`,
51
+ title: a.id,
52
+ children: /* @__PURE__ */ jsxs("code", { children: [a.id.slice(0, 8), "…"] })
53
+ }) }),
54
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("div", {
55
+ className: "flex items-center gap-2",
56
+ children: [/* @__PURE__ */ jsx(AgentAvatar, {
57
+ identity: a.identity,
58
+ size: 26
59
+ }), /* @__PURE__ */ jsxs("div", {
60
+ className: "leading-tight",
61
+ children: [/* @__PURE__ */ jsx("div", { children: a.name }), (a.identity?.creature || a.identity?.vibe) && /* @__PURE__ */ jsx("div", {
62
+ className: "muted text-[0.8em]",
63
+ children: [a.identity?.creature, a.identity?.vibe].filter(Boolean).join(" · ")
64
+ })]
65
+ })]
66
+ }) }),
67
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("code", { children: a.profileId }) }),
68
+ /* @__PURE__ */ jsx("td", { children: a.status }),
69
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("div", {
70
+ className: "flex gap-1.5",
71
+ children: [a.status !== "archived" ? /* @__PURE__ */ jsx("button", {
72
+ type: "button",
73
+ className: "ghost-btn",
74
+ onClick: () => archive(a.id),
75
+ children: "archive"
76
+ }) : /* @__PURE__ */ jsx("button", {
77
+ type: "button",
78
+ className: "ghost-btn",
79
+ onClick: () => unarchive(a.id),
80
+ children: "unarchive"
81
+ }), /* @__PURE__ */ jsx("button", {
82
+ type: "button",
83
+ className: "ghost-btn",
84
+ style: { color: "var(--color-rose-baziu)" },
85
+ onClick: () => del(a.id),
86
+ children: "delete"
87
+ })]
88
+ }) })
89
+ ] }, a.id))] })] })
90
+ ] });
91
+ }
92
+ function SpawnForm({ profiles, groups, modelGroups, onSpawned }) {
93
+ const [profileId, setProfileId] = useState("");
94
+ const [name, setName] = useState("");
95
+ const [model, setModel] = useState("");
96
+ const [groupId, setGroupId] = useState(groups.find((g) => g.id === "default")?.id ?? "");
97
+ const [submitting, setSubmitting] = useState(false);
98
+ const [err, setErr] = useState(null);
99
+ async function submit(e) {
100
+ e.preventDefault();
101
+ if (!profileId) {
102
+ setErr("profile is required");
103
+ return;
104
+ }
105
+ setSubmitting(true);
106
+ setErr(null);
107
+ try {
108
+ const body = { profile: profileId };
109
+ if (name) body.name = name;
110
+ if (model) body.model = model;
111
+ if (groupId) body.groupId = groupId;
112
+ const res = await fetch("/api/agents", {
113
+ method: "POST",
114
+ headers: { "content-type": "application/json" },
115
+ body: JSON.stringify(body)
116
+ });
117
+ if (!res.ok) {
118
+ const b = await res.json().catch(() => null);
119
+ throw new Error(b?.error ?? res.statusText);
120
+ }
121
+ setName("");
122
+ setModel("");
123
+ onSpawned();
124
+ } catch (e2) {
125
+ setErr(e2.message);
126
+ } finally {
127
+ setSubmitting(false);
128
+ }
129
+ }
130
+ return /* @__PURE__ */ jsxs("form", {
131
+ className: "card",
132
+ onSubmit: submit,
133
+ children: [
134
+ /* @__PURE__ */ jsx("h3", { children: "spawn agent" }),
135
+ err && /* @__PURE__ */ jsx("div", {
136
+ className: "err",
137
+ children: err
138
+ }),
139
+ /* @__PURE__ */ jsx("p", {
140
+ className: "muted my-2 text-[0.85em]",
141
+ children: "Skills come from the profile's defaults at spawn time. Tweak per-agent skills after the fact from the agent detail page."
142
+ }),
143
+ /* @__PURE__ */ jsxs("div", {
144
+ className: "flex gap-4",
145
+ children: [/* @__PURE__ */ jsxs("label", {
146
+ className: "flex-1",
147
+ children: ["profile", /* @__PURE__ */ jsxs("select", {
148
+ value: profileId,
149
+ onChange: (e) => setProfileId(e.target.value),
150
+ required: true,
151
+ children: [/* @__PURE__ */ jsx("option", {
152
+ value: "",
153
+ children: "--"
154
+ }), profiles.map((p) => /* @__PURE__ */ jsx("option", {
155
+ value: p.id,
156
+ children: p.id
157
+ }, p.id))]
158
+ })]
159
+ }), /* @__PURE__ */ jsxs("label", {
160
+ className: "flex-1",
161
+ children: ["name", /* @__PURE__ */ jsx("input", {
162
+ value: name,
163
+ onChange: (e) => setName(e.target.value)
164
+ })]
165
+ })]
166
+ }),
167
+ /* @__PURE__ */ jsxs("label", { children: ["model override", modelGroups.length === 0 ? /* @__PURE__ */ jsx("input", {
168
+ value: "",
169
+ disabled: true,
170
+ placeholder: "(uses profile default — enable models on /config)"
171
+ }) : /* @__PURE__ */ jsxs("select", {
172
+ value: model,
173
+ onChange: (e) => setModel(e.target.value),
174
+ children: [/* @__PURE__ */ jsx("option", {
175
+ value: "",
176
+ children: "(uses profile default)"
177
+ }), modelGroups.map((g) => /* @__PURE__ */ jsx("optgroup", {
178
+ label: g.provider,
179
+ children: g.models.map((m) => /* @__PURE__ */ jsx("option", {
180
+ value: `${g.provider}:${m}`,
181
+ children: `${g.provider}:${m}`
182
+ }, m))
183
+ }, g.provider))]
184
+ })] }),
185
+ /* @__PURE__ */ jsxs("label", { children: ["group", groups.length === 0 ? /* @__PURE__ */ jsx("select", {
186
+ disabled: true,
187
+ children: /* @__PURE__ */ jsx("option", { children: "(no groups — register one on /groups)" })
188
+ }) : /* @__PURE__ */ jsx("select", {
189
+ value: groupId,
190
+ onChange: (e) => setGroupId(e.target.value),
191
+ children: groups.map((g) => /* @__PURE__ */ jsxs("option", {
192
+ value: g.id,
193
+ children: [
194
+ g.id,
195
+ " (",
196
+ g.name,
197
+ ")"
198
+ ]
199
+ }, g.id))
200
+ })] }),
201
+ /* @__PURE__ */ jsx("button", {
202
+ type: "submit",
203
+ disabled: submitting,
204
+ children: submitting ? "spawning…" : "spawn"
205
+ })
206
+ ]
207
+ });
208
+ }
209
+ //#endregion
210
+ export { AgentsPage as component };
@@ -0,0 +1,26 @@
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/agents/index.tsx?tss-serverfn-split
5
+ var fetchAgents_createServerFn_handler = createServerRpc({
6
+ id: "f715bab0037380aa3db7e237e7cf1e74168c363f48a960bb1ddfa5560de3a74e",
7
+ name: "fetchAgents",
8
+ filename: "src/routes/agents/index.tsx"
9
+ }, (opts) => fetchAgents.__executeServer(opts));
10
+ var fetchAgents = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(fetchAgents_createServerFn_handler, async ({ data }) => {
11
+ const c = daemonClient();
12
+ const [agents, profiles, groups, models] = await Promise.all([
13
+ c.get(`/api/agents?includeArchived=${data.all}`),
14
+ c.get("/api/profiles"),
15
+ c.get("/api/groups"),
16
+ c.get("/api/config/available-models")
17
+ ]);
18
+ return {
19
+ agents,
20
+ profiles,
21
+ groups,
22
+ modelGroups: models.groups
23
+ };
24
+ });
25
+ //#endregion
26
+ export { fetchAgents_createServerFn_handler };
@@ -0,0 +1,14 @@
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/agents/index.tsx
5
+ var $$splitComponentImporter = () => import("./agents-70EwQJR6.js");
6
+ var fetchAgents = createServerFn({ method: "POST" }).inputValidator((d) => d).handler(createSsrRpc("f715bab0037380aa3db7e237e7cf1e74168c363f48a960bb1ddfa5560de3a74e"));
7
+ var Route = createFileRoute("/agents/")({
8
+ validateSearch: (s) => ({ all: s.all === "1" ? "1" : void 0 }),
9
+ loaderDeps: ({ search }) => ({ all: search.all === "1" }),
10
+ loader: ({ deps }) => fetchAgents({ data: { all: deps.all } }),
11
+ component: lazyRouteComponent($$splitComponentImporter, "component")
12
+ });
13
+ //#endregion
14
+ export { Route as t };
@@ -0,0 +1,26 @@
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/lib/auth.ts?tss-serverfn-split
5
+ var fetchAuthState_createServerFn_handler = createServerRpc({
6
+ id: "a5d3825fc69573bb55bab6df578c750ebb0240dd394c3acee3adea02918a5dc2",
7
+ name: "fetchAuthState",
8
+ filename: "src/lib/auth.ts"
9
+ }, (opts) => fetchAuthState.__executeServer(opts));
10
+ var fetchAuthState = createServerFn({ method: "GET" }).handler(fetchAuthState_createServerFn_handler, async () => {
11
+ try {
12
+ const res = await daemonClient().get("/api/auth/me");
13
+ return {
14
+ authed: res.authed,
15
+ setupComplete: res.setupComplete
16
+ };
17
+ } catch (err) {
18
+ if (err instanceof ApiClientError && err.status === 401) return {
19
+ authed: false,
20
+ setupComplete: false
21
+ };
22
+ throw err;
23
+ }
24
+ });
25
+ //#endregion
26
+ export { fetchAuthState_createServerFn_handler };
@@ -0,0 +1,19 @@
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/index.tsx?tss-serverfn-split
5
+ var fetchProvidersData_createServerFn_handler = createServerRpc({
6
+ id: "b18a227687dba45b99ea5a2ac7a5bf8efcd9bc54387bc279cd87510fd2f83f7e",
7
+ name: "fetchProvidersData",
8
+ filename: "src/routes/config/index.tsx"
9
+ }, (opts) => fetchProvidersData.__executeServer(opts));
10
+ var fetchProvidersData = createServerFn({ method: "GET" }).handler(fetchProvidersData_createServerFn_handler, async () => {
11
+ const c = daemonClient();
12
+ const [{ providers }, openaiCodex] = await Promise.all([c.get("/api/config/providers"), c.get("/api/auth/openai")]);
13
+ return {
14
+ providers,
15
+ openaiCodex
16
+ };
17
+ });
18
+ //#endregion
19
+ export { fetchProvidersData_createServerFn_handler };
@@ -0,0 +1,382 @@
1
+ import { t as Route } from "./config-DxCGYgR9.js";
2
+ import { t as ConfigTabs } from "./ConfigTabs-CyuxzesF.js";
3
+ import { t as FieldRow } from "./FieldRow-DwyqycWI.js";
4
+ import { useState } from "react";
5
+ import { useRouter } from "@tanstack/react-router";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/routes/config/index.tsx?tsr-split=component
8
+ function ProvidersPage() {
9
+ const { providers, openaiCodex } = Route.useLoaderData();
10
+ const setupComplete = providers.some((p) => p.enabled && p.curated.length > 0);
11
+ return /* @__PURE__ */ jsxs("main", {
12
+ className: "mx-auto max-w-5xl px-6 py-8",
13
+ children: [
14
+ /* @__PURE__ */ jsx("h1", {
15
+ className: "font-serif text-3xl text-foreground mb-2",
16
+ children: "config"
17
+ }),
18
+ /* @__PURE__ */ jsx(ConfigTabs, { active: "providers" }),
19
+ !setupComplete && /* @__PURE__ */ jsx(SetupBlockerBanner, {
20
+ providers,
21
+ openaiCodex
22
+ }),
23
+ /* @__PURE__ */ jsxs("p", {
24
+ className: "text-muted-foreground text-sm mb-6",
25
+ children: [
26
+ "Each card configures one LLM provider end to end: credentials (encrypted in the",
27
+ " ",
28
+ /* @__PURE__ */ jsx("code", {
29
+ className: "font-mono",
30
+ children: "secrets"
31
+ }),
32
+ " table), URLs and IDs (plaintext in the",
33
+ " ",
34
+ /* @__PURE__ */ jsx("code", {
35
+ className: "font-mono",
36
+ children: "config"
37
+ }),
38
+ " table), and the curated model list that powers profile / agent dropdowns."
39
+ ]
40
+ }),
41
+ providers.map((p) => /* @__PURE__ */ jsx(ProviderCard, {
42
+ p,
43
+ openaiCodexStatus: p.id === "openai-codex" ? openaiCodex : void 0
44
+ }, p.id))
45
+ ]
46
+ });
47
+ }
48
+ function SetupBlockerBanner({ providers, openaiCodex }) {
49
+ const issues = [];
50
+ for (const p of providers) {
51
+ if (!p.enabled) continue;
52
+ if (p.id === "openai-codex" && !openaiCodex.connected) issues.push(`${p.id}: enabled but ChatGPT is not connected — click "Connect ChatGPT" below`);
53
+ if (p.curated.length === 0) issues.push(`${p.id}: enabled but no curated models — add at least one name in the "curated models" box below and save`);
54
+ }
55
+ const enabledCount = providers.filter((p) => p.enabled).length;
56
+ return /* @__PURE__ */ jsxs("div", {
57
+ className: "rounded-md border-2 border-amber-400 bg-amber-50 px-4 py-3 mb-4 text-sm",
58
+ children: [
59
+ /* @__PURE__ */ jsx("div", {
60
+ className: "font-semibold text-amber-900 mb-1",
61
+ children: "First-run setup is not complete"
62
+ }),
63
+ /* @__PURE__ */ jsxs("p", {
64
+ className: "text-amber-900 mb-2",
65
+ children: [
66
+ "The rest of the app stays on the Welcome screen until at least one provider is",
67
+ " ",
68
+ /* @__PURE__ */ jsx("strong", { children: "enabled" }),
69
+ " and has ",
70
+ /* @__PURE__ */ jsx("strong", { children: "at least one curated model" }),
71
+ "."
72
+ ]
73
+ }),
74
+ issues.length > 0 ? /* @__PURE__ */ jsx("ul", {
75
+ className: "list-disc pl-5 text-amber-900 space-y-0.5",
76
+ children: issues.map((i) => /* @__PURE__ */ jsx("li", { children: i }, i))
77
+ }) : enabledCount === 0 ? /* @__PURE__ */ jsx("p", {
78
+ className: "text-amber-900",
79
+ children: "No providers are enabled yet — pick one below, flip the toggle on, set credentials, and add a model name."
80
+ }) : null
81
+ ]
82
+ });
83
+ }
84
+ function ProviderCard({ p, openaiCodexStatus }) {
85
+ const router = useRouter();
86
+ const [enabled, setEnabled] = useState(p.enabled);
87
+ const [models, setModels] = useState(p.curated.join("\n"));
88
+ const [savingModels, setSavingModels] = useState(false);
89
+ const [modelStatus, setModelStatus] = useState(null);
90
+ async function toggle(next) {
91
+ setEnabled(next);
92
+ try {
93
+ await fetch(`/api/config/providers/${encodeURIComponent(p.id)}/enabled`, {
94
+ method: "PUT",
95
+ headers: { "content-type": "application/json" },
96
+ body: JSON.stringify({ enabled: next })
97
+ });
98
+ await router.invalidate();
99
+ } catch {
100
+ setEnabled(!next);
101
+ }
102
+ }
103
+ async function saveModels(e) {
104
+ e.preventDefault();
105
+ setSavingModels(true);
106
+ setModelStatus(null);
107
+ try {
108
+ const list = models.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
109
+ const res = await fetch(`/api/config/providers/${encodeURIComponent(p.id)}/models`, {
110
+ method: "PUT",
111
+ headers: { "content-type": "application/json" },
112
+ body: JSON.stringify({ models: list })
113
+ });
114
+ if (!res.ok) {
115
+ const j = await res.json().catch(() => ({}));
116
+ throw new Error(j.error ?? `${res.status} ${res.statusText}`);
117
+ }
118
+ setModelStatus("saved ✓");
119
+ await router.invalidate();
120
+ } catch (e) {
121
+ setModelStatus(`error: ${e.message}`);
122
+ } finally {
123
+ setSavingModels(false);
124
+ }
125
+ }
126
+ return /* @__PURE__ */ jsxs("section", {
127
+ className: "rounded-lg border bg-card mb-3 overflow-hidden",
128
+ children: [/* @__PURE__ */ jsxs("header", {
129
+ className: "flex items-center gap-3 px-4 py-3",
130
+ children: [
131
+ /* @__PURE__ */ jsx("span", {
132
+ className: "font-mono font-semibold",
133
+ children: p.id
134
+ }),
135
+ /* @__PURE__ */ jsxs("span", {
136
+ className: "text-muted-foreground text-sm",
137
+ children: ["· ", p.displayName]
138
+ }),
139
+ /* @__PURE__ */ jsxs("label", {
140
+ className: "flex items-center gap-1.5 text-xs uppercase tracking-wide font-semibold cursor-pointer",
141
+ children: [/* @__PURE__ */ jsx("input", {
142
+ type: "checkbox",
143
+ checked: enabled,
144
+ onChange: (e) => toggle(e.target.checked),
145
+ className: "size-4"
146
+ }), /* @__PURE__ */ jsx("span", {
147
+ className: enabled ? "text-emerald-700" : "text-muted-foreground",
148
+ children: enabled ? "enabled" : "disabled"
149
+ })]
150
+ }),
151
+ /* @__PURE__ */ jsxs("span", {
152
+ className: "ml-auto text-xs text-muted-foreground",
153
+ children: [
154
+ p.curated.length > 0 && /* @__PURE__ */ jsxs("span", { children: [p.curated.length, " curated"] }),
155
+ p.catalog.length > 0 && /* @__PURE__ */ jsxs("span", { children: [
156
+ " · ",
157
+ p.catalog.length,
158
+ " catalog"
159
+ ] }),
160
+ p.live && !p.live.error && /* @__PURE__ */ jsxs("span", { children: [
161
+ " · ",
162
+ p.live.models.length,
163
+ " live"
164
+ ] })
165
+ ]
166
+ })
167
+ ]
168
+ }), enabled && /* @__PURE__ */ jsxs("div", {
169
+ className: "border-t border-dashed px-4 py-3",
170
+ children: [
171
+ p.hint && /* @__PURE__ */ jsx("p", {
172
+ className: "text-xs text-muted-foreground mb-2",
173
+ children: p.hint
174
+ }),
175
+ p.id === "openai-codex" && openaiCodexStatus && /* @__PURE__ */ jsx(OpenAICodexCard, { status: openaiCodexStatus }),
176
+ p.fields.length === 0 && p.envHint && p.id !== "openai-codex" && /* @__PURE__ */ jsxs("p", {
177
+ className: "text-xs text-muted-foreground",
178
+ children: ["Credentials come from the process env: ", /* @__PURE__ */ jsx("code", {
179
+ className: "font-mono",
180
+ children: p.envHint
181
+ })]
182
+ }),
183
+ p.fields.map((f) => /* @__PURE__ */ jsx(FieldRow, { field: f }, f.envVar)),
184
+ /* @__PURE__ */ jsx("h4", {
185
+ className: "mt-4 mb-1 text-xs uppercase tracking-wide text-muted-foreground",
186
+ children: "curated models (one per line)"
187
+ }),
188
+ p.curated.length === 0 && /* @__PURE__ */ jsxs("p", {
189
+ className: "mb-2 text-xs font-medium text-amber-700",
190
+ children: [
191
+ "First-run setup needs at least one model name here — type one (e.g.",
192
+ " ",
193
+ /* @__PURE__ */ jsx("code", {
194
+ className: "font-mono",
195
+ children: exampleModelFor(p.id)
196
+ }),
197
+ ") and click",
198
+ " ",
199
+ /* @__PURE__ */ jsx("em", { children: "save models" }),
200
+ "."
201
+ ]
202
+ }),
203
+ /* @__PURE__ */ jsxs("form", {
204
+ onSubmit: saveModels,
205
+ children: [/* @__PURE__ */ jsx("textarea", {
206
+ value: models,
207
+ onChange: (e) => setModels(e.target.value),
208
+ rows: Math.max(3, Math.min(8, models.split("\n").length)),
209
+ className: "w-full rounded-md border bg-background px-2 py-1.5 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30",
210
+ placeholder: p.catalog.length === 0 && !p.live ? "Type model names one per line, e.g. qwen3-coder-30b" : "Click catalog chips below, or type names one per line"
211
+ }), /* @__PURE__ */ jsxs("div", {
212
+ className: "flex items-center gap-3 mt-2",
213
+ children: [/* @__PURE__ */ jsx("button", {
214
+ type: "submit",
215
+ disabled: savingModels,
216
+ className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground disabled:opacity-50",
217
+ children: "save models"
218
+ }), modelStatus && /* @__PURE__ */ jsx("span", {
219
+ className: "text-xs text-muted-foreground",
220
+ children: modelStatus
221
+ })]
222
+ })]
223
+ }),
224
+ p.catalog.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("h4", {
225
+ className: "mt-4 mb-1 text-xs uppercase tracking-wide text-muted-foreground",
226
+ children: "catalog"
227
+ }), /* @__PURE__ */ jsx(ChipList, {
228
+ items: p.catalog,
229
+ onPick: (name) => setModels((m) => m.includes(name) ? m : `${m}\n${name}`.trim())
230
+ })] }),
231
+ p.live && !p.live.error && p.live.models.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("h4", {
232
+ className: "mt-4 mb-1 text-xs uppercase tracking-wide text-muted-foreground",
233
+ children: "live"
234
+ }), /* @__PURE__ */ jsx(ChipList, {
235
+ items: p.live.models,
236
+ onPick: (name) => setModels((m) => m.includes(name) ? m : `${m}\n${name}`.trim())
237
+ })] }),
238
+ p.live?.error && /* @__PURE__ */ jsxs("p", {
239
+ className: "text-xs text-rose-700 mt-2",
240
+ children: ["could not fetch: ", p.live.error]
241
+ })
242
+ ]
243
+ })]
244
+ });
245
+ }
246
+ function exampleModelFor(providerId) {
247
+ switch (providerId) {
248
+ case "openai-codex": return "gpt-5.3-codex";
249
+ case "openai": return "gpt-5.5";
250
+ case "anthropic": return "claude-opus-4-8";
251
+ case "google": return "gemini-3-pro-preview";
252
+ case "google-vertex": return "gemini-3-pro-preview";
253
+ case "xai": return "grok-4.3";
254
+ case "groq": return "llama-3.3-70b-versatile";
255
+ case "cerebras": return "zai-glm-4.7";
256
+ case "mistral": return "mistral-large-latest";
257
+ case "zai": return "glm-5.1";
258
+ case "huggingface": return "Qwen/Qwen3.5-397B-A17B";
259
+ case "openrouter": return "anthropic/claude-opus-4.8";
260
+ case "vercel-ai-gateway": return "anthropic/claude-opus-4.8";
261
+ case "deepseek": return "deepseek-v4-pro";
262
+ case "fireworks": return "accounts/fireworks/models/deepseek-v4-pro";
263
+ case "together": return "Qwen/Qwen3.7-Max";
264
+ case "moonshotai": return "kimi-k2.6";
265
+ case "kimi-coding": return "kimi-for-coding";
266
+ case "minimax": return "MiniMax-M2.7";
267
+ case "cloudflare-workers-ai": return "@cf/moonshotai/kimi-k2.6";
268
+ case "cloudflare-ai-gateway": return "claude-opus-4-7";
269
+ case "github-copilot": return "claude-opus-4.7";
270
+ case "xiaomi": return "mimo-v2.5";
271
+ case "opencode": return "claude-opus-4-8";
272
+ case "azure-openai": return "gpt-5.5";
273
+ case "bedrock": return "anthropic.claude-opus-4-8";
274
+ case "ollama": return "llama3.3";
275
+ case "lmstudio": return "qwen3-coder-30b";
276
+ case "llamacpp": return "unsloth/Qwen3.6-35B-A3B-MTP-GGUF:MXFP4_MOE";
277
+ default: return "model-name";
278
+ }
279
+ }
280
+ function ChipList({ items, onPick }) {
281
+ return /* @__PURE__ */ jsx("div", {
282
+ className: "flex flex-wrap gap-1.5 max-h-40 overflow-y-auto rounded-md border bg-background p-1.5",
283
+ children: items.map((m) => /* @__PURE__ */ jsx("button", {
284
+ type: "button",
285
+ onClick: () => onPick(m),
286
+ className: "rounded border bg-card px-2 py-0.5 font-mono text-xs hover:border-primary hover:bg-accent",
287
+ children: m
288
+ }, m))
289
+ });
290
+ }
291
+ function OpenAICodexCard({ status }) {
292
+ const router = useRouter();
293
+ const [busy, setBusy] = useState(false);
294
+ const [err, setErr] = useState(null);
295
+ async function connect() {
296
+ setBusy(true);
297
+ setErr(null);
298
+ try {
299
+ const res = await fetch("/api/auth/openai/login", { method: "POST" });
300
+ if (!res.ok) {
301
+ const j = await res.json().catch(() => ({}));
302
+ throw new Error(j.error ?? `${res.status} ${res.statusText}`);
303
+ }
304
+ await router.invalidate();
305
+ } catch (e) {
306
+ setErr(e.message);
307
+ } finally {
308
+ setBusy(false);
309
+ }
310
+ }
311
+ async function disconnect() {
312
+ setBusy(true);
313
+ setErr(null);
314
+ try {
315
+ await fetch("/api/auth/openai", { method: "DELETE" });
316
+ await router.invalidate();
317
+ } catch (e) {
318
+ setErr(e.message);
319
+ } finally {
320
+ setBusy(false);
321
+ }
322
+ }
323
+ return /* @__PURE__ */ jsxs("div", {
324
+ className: "rounded-md border bg-muted/30 p-3 mb-3",
325
+ children: [status.connected ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
326
+ className: "flex flex-wrap gap-2 items-center mb-2",
327
+ children: [
328
+ /* @__PURE__ */ jsx("span", {
329
+ className: "rounded-full bg-emerald-100 text-emerald-800 px-2 py-0.5 text-xs font-semibold uppercase",
330
+ children: "connected"
331
+ }),
332
+ status.accountId && /* @__PURE__ */ jsxs("span", {
333
+ className: "text-xs text-muted-foreground",
334
+ children: ["account ", /* @__PURE__ */ jsx("code", {
335
+ className: "font-mono",
336
+ children: status.accountId
337
+ })]
338
+ }),
339
+ status.expiresAt && /* @__PURE__ */ jsxs("span", {
340
+ className: "text-xs text-muted-foreground",
341
+ children: [
342
+ "token expires",
343
+ " ",
344
+ new Date(status.expiresAt).toISOString().replace(/\.\d+Z$/, "Z")
345
+ ]
346
+ })
347
+ ]
348
+ }), /* @__PURE__ */ jsx("button", {
349
+ type: "button",
350
+ onClick: disconnect,
351
+ disabled: busy,
352
+ className: "rounded-md border px-3 py-1.5 text-sm text-rose-700 hover:bg-rose-50 disabled:opacity-50",
353
+ children: "disconnect"
354
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("p", {
355
+ className: "text-xs text-muted-foreground mb-2",
356
+ children: [
357
+ "Sign in with your ChatGPT account — the OAuth flow opens a new browser tab. The loopback callback at ",
358
+ /* @__PURE__ */ jsx("code", {
359
+ className: "font-mono",
360
+ children: "localhost:1455"
361
+ }),
362
+ " only works when you're using the web UI on the same machine as the daemon. For remote setups, run ",
363
+ /* @__PURE__ */ jsx("code", {
364
+ className: "font-mono",
365
+ children: "bazilion auth openai login"
366
+ }),
367
+ " on the client."
368
+ ]
369
+ }), /* @__PURE__ */ jsx("button", {
370
+ type: "button",
371
+ onClick: connect,
372
+ disabled: busy,
373
+ className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground disabled:opacity-50",
374
+ children: busy ? "opening browser…" : "Connect ChatGPT →"
375
+ })] }), err && /* @__PURE__ */ jsx("p", {
376
+ className: "text-sm text-rose-700 mt-2",
377
+ children: err
378
+ })]
379
+ });
380
+ }
381
+ //#endregion
382
+ export { ProvidersPage as component };